1af69d88dSmrg/* 2af69d88dSmrg * Copyright (C) 2014 Intel Corporation 3af69d88dSmrg * 4af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5af69d88dSmrg * copy of this software and associated documentation files (the "Software"), 6af69d88dSmrg * to deal in the Software without restriction, including without limitation 7af69d88dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8af69d88dSmrg * and/or sell copies of the Software, and to permit persons to whom the 9af69d88dSmrg * Software is furnished to do so, subject to the following conditions: 10af69d88dSmrg * 11af69d88dSmrg * The above copyright notice and this permission notice (including the next 12af69d88dSmrg * paragraph) shall be included in all copies or substantial portions of the 13af69d88dSmrg * Software. 14af69d88dSmrg * 15af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16af69d88dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19af69d88dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20af69d88dSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21af69d88dSmrg * DEALINGS IN THE SOFTWARE. 22af69d88dSmrg */ 23af69d88dSmrg 24af69d88dSmrg/** 25af69d88dSmrg * \file texcompress_bptc.c 26af69d88dSmrg * GL_ARB_texture_compression_bptc support. 27af69d88dSmrg */ 28af69d88dSmrg 29af69d88dSmrg#include <stdbool.h> 30af69d88dSmrg#include "texcompress.h" 31af69d88dSmrg#include "texcompress_bptc.h" 3201e04c3fSmrg#include "texcompress_bptc_tmp.h" 33af69d88dSmrg#include "texstore.h" 34af69d88dSmrg#include "image.h" 3501e04c3fSmrg#include "mtypes.h" 36af69d88dSmrg 3701e04c3fSmrgstatic void 3801e04c3fSmrgfetch_bptc_rgb_float(const GLubyte *map, 3901e04c3fSmrg GLint rowStride, GLint i, GLint j, 4001e04c3fSmrg GLfloat *texel, 4101e04c3fSmrg bool is_signed) 42af69d88dSmrg{ 4301e04c3fSmrg const GLubyte *block; 44af69d88dSmrg 4501e04c3fSmrg block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; 46af69d88dSmrg 4701e04c3fSmrg fetch_rgb_float_from_block(block, texel, (i % 4) + (j % 4) * 4, is_signed); 48af69d88dSmrg} 49af69d88dSmrg 50af69d88dSmrgstatic void 5101e04c3fSmrgfetch_bptc_rgb_signed_float(const GLubyte *map, 5201e04c3fSmrg GLint rowStride, GLint i, GLint j, 5301e04c3fSmrg GLfloat *texel) 54af69d88dSmrg{ 5501e04c3fSmrg fetch_bptc_rgb_float(map, rowStride, i, j, texel, true); 56af69d88dSmrg} 57af69d88dSmrg 58af69d88dSmrgstatic void 5901e04c3fSmrgfetch_bptc_rgb_unsigned_float(const GLubyte *map, 6001e04c3fSmrg GLint rowStride, GLint i, GLint j, 6101e04c3fSmrg GLfloat *texel) 62af69d88dSmrg{ 6301e04c3fSmrg fetch_bptc_rgb_float(map, rowStride, i, j, texel, false); 64af69d88dSmrg} 65af69d88dSmrg 66af69d88dSmrgstatic void 67af69d88dSmrgfetch_bptc_rgba_unorm_bytes(const GLubyte *map, 68af69d88dSmrg GLint rowStride, GLint i, GLint j, 69af69d88dSmrg GLubyte *texel) 70af69d88dSmrg{ 71af69d88dSmrg const GLubyte *block; 72af69d88dSmrg 73af69d88dSmrg block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; 74af69d88dSmrg 75af69d88dSmrg fetch_rgba_unorm_from_block(block, texel, (i % 4) + (j % 4) * 4); 76af69d88dSmrg} 77af69d88dSmrg 78af69d88dSmrgstatic void 79af69d88dSmrgfetch_bptc_rgba_unorm(const GLubyte *map, 80af69d88dSmrg GLint rowStride, GLint i, GLint j, 81af69d88dSmrg GLfloat *texel) 82af69d88dSmrg{ 83af69d88dSmrg GLubyte texel_bytes[4]; 84af69d88dSmrg 85af69d88dSmrg fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes); 86af69d88dSmrg 87af69d88dSmrg texel[RCOMP] = UBYTE_TO_FLOAT(texel_bytes[0]); 88af69d88dSmrg texel[GCOMP] = UBYTE_TO_FLOAT(texel_bytes[1]); 89af69d88dSmrg texel[BCOMP] = UBYTE_TO_FLOAT(texel_bytes[2]); 90af69d88dSmrg texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]); 91af69d88dSmrg} 92af69d88dSmrg 93af69d88dSmrgstatic void 94af69d88dSmrgfetch_bptc_srgb_alpha_unorm(const GLubyte *map, 95af69d88dSmrg GLint rowStride, GLint i, GLint j, 96af69d88dSmrg GLfloat *texel) 97af69d88dSmrg{ 98af69d88dSmrg GLubyte texel_bytes[4]; 99af69d88dSmrg 100af69d88dSmrg fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes); 101af69d88dSmrg 102af69d88dSmrg texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[0]); 103af69d88dSmrg texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[1]); 104af69d88dSmrg texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[2]); 105af69d88dSmrg texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]); 106af69d88dSmrg} 107af69d88dSmrg 108af69d88dSmrgcompressed_fetch_func 109af69d88dSmrg_mesa_get_bptc_fetch_func(mesa_format format) 110af69d88dSmrg{ 111af69d88dSmrg switch (format) { 112af69d88dSmrg case MESA_FORMAT_BPTC_RGBA_UNORM: 113af69d88dSmrg return fetch_bptc_rgba_unorm; 114af69d88dSmrg case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM: 115af69d88dSmrg return fetch_bptc_srgb_alpha_unorm; 116af69d88dSmrg case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT: 117af69d88dSmrg return fetch_bptc_rgb_signed_float; 118af69d88dSmrg case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT: 119af69d88dSmrg return fetch_bptc_rgb_unsigned_float; 120af69d88dSmrg default: 121af69d88dSmrg return NULL; 122af69d88dSmrg } 123af69d88dSmrg} 124af69d88dSmrg 125af69d88dSmrgGLboolean 126af69d88dSmrg_mesa_texstore_bptc_rgba_unorm(TEXSTORE_PARAMS) 127af69d88dSmrg{ 128af69d88dSmrg const GLubyte *pixels; 129af69d88dSmrg const GLubyte *tempImage = NULL; 130af69d88dSmrg int rowstride; 131af69d88dSmrg 132af69d88dSmrg if (srcFormat != GL_RGBA || 133af69d88dSmrg srcType != GL_UNSIGNED_BYTE || 134af69d88dSmrg ctx->_ImageTransferState || 135af69d88dSmrg srcPacking->SwapBytes) { 136af69d88dSmrg /* convert image to RGBA/ubyte */ 13701e04c3fSmrg GLubyte *tempImageSlices[1]; 13801e04c3fSmrg int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte); 13901e04c3fSmrg tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte)); 140af69d88dSmrg if (!tempImage) 141af69d88dSmrg return GL_FALSE; /* out of memory */ 14201e04c3fSmrg tempImageSlices[0] = (GLubyte *) tempImage; 14301e04c3fSmrg _mesa_texstore(ctx, dims, 14401e04c3fSmrg baseInternalFormat, 1457ec681f3Smrg#if UTIL_ARCH_LITTLE_ENDIAN 1467ec681f3Smrg MESA_FORMAT_R8G8B8A8_UNORM, 1477ec681f3Smrg#else 1487ec681f3Smrg MESA_FORMAT_A8B8G8R8_UNORM, 1497ec681f3Smrg#endif 15001e04c3fSmrg rgbaRowStride, tempImageSlices, 15101e04c3fSmrg srcWidth, srcHeight, srcDepth, 15201e04c3fSmrg srcFormat, srcType, srcAddr, 15301e04c3fSmrg srcPacking); 154af69d88dSmrg 155af69d88dSmrg pixels = tempImage; 156af69d88dSmrg rowstride = srcWidth * 4; 157af69d88dSmrg } else { 158af69d88dSmrg pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight, 159af69d88dSmrg srcFormat, srcType, 0, 0); 160af69d88dSmrg rowstride = _mesa_image_row_stride(srcPacking, srcWidth, 161af69d88dSmrg srcFormat, srcType); 162af69d88dSmrg } 163af69d88dSmrg 164af69d88dSmrg compress_rgba_unorm(srcWidth, srcHeight, 165af69d88dSmrg pixels, rowstride, 166af69d88dSmrg dstSlices[0], dstRowStride); 167af69d88dSmrg 168af69d88dSmrg free((void *) tempImage); 169af69d88dSmrg 170af69d88dSmrg return GL_TRUE; 171af69d88dSmrg} 172af69d88dSmrg 173af69d88dSmrgstatic GLboolean 174af69d88dSmrgtexstore_bptc_rgb_float(TEXSTORE_PARAMS, 175af69d88dSmrg bool is_signed) 176af69d88dSmrg{ 177af69d88dSmrg const float *pixels; 178af69d88dSmrg const float *tempImage = NULL; 179af69d88dSmrg int rowstride; 180af69d88dSmrg 181af69d88dSmrg if (srcFormat != GL_RGB || 182af69d88dSmrg srcType != GL_FLOAT || 183af69d88dSmrg ctx->_ImageTransferState || 184af69d88dSmrg srcPacking->SwapBytes) { 185af69d88dSmrg /* convert image to RGB/float */ 18601e04c3fSmrg GLfloat *tempImageSlices[1]; 18701e04c3fSmrg int rgbRowStride = 3 * srcWidth * sizeof(GLfloat); 18801e04c3fSmrg tempImage = malloc(srcWidth * srcHeight * 3 * sizeof(GLfloat)); 189af69d88dSmrg if (!tempImage) 190af69d88dSmrg return GL_FALSE; /* out of memory */ 19101e04c3fSmrg tempImageSlices[0] = (GLfloat *) tempImage; 19201e04c3fSmrg _mesa_texstore(ctx, dims, 19301e04c3fSmrg baseInternalFormat, 19401e04c3fSmrg MESA_FORMAT_RGB_FLOAT32, 19501e04c3fSmrg rgbRowStride, (GLubyte **)tempImageSlices, 19601e04c3fSmrg srcWidth, srcHeight, srcDepth, 19701e04c3fSmrg srcFormat, srcType, srcAddr, 19801e04c3fSmrg srcPacking); 199af69d88dSmrg 200af69d88dSmrg pixels = tempImage; 201af69d88dSmrg rowstride = srcWidth * sizeof(float) * 3; 202af69d88dSmrg } else { 203af69d88dSmrg pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight, 204af69d88dSmrg srcFormat, srcType, 0, 0); 205af69d88dSmrg rowstride = _mesa_image_row_stride(srcPacking, srcWidth, 206af69d88dSmrg srcFormat, srcType); 207af69d88dSmrg } 208af69d88dSmrg 209af69d88dSmrg compress_rgb_float(srcWidth, srcHeight, 210af69d88dSmrg pixels, rowstride, 211af69d88dSmrg dstSlices[0], dstRowStride, 212af69d88dSmrg is_signed); 213af69d88dSmrg 214af69d88dSmrg free((void *) tempImage); 215af69d88dSmrg 216af69d88dSmrg return GL_TRUE; 217af69d88dSmrg} 218af69d88dSmrg 219af69d88dSmrgGLboolean 220af69d88dSmrg_mesa_texstore_bptc_rgb_signed_float(TEXSTORE_PARAMS) 221af69d88dSmrg{ 22201e04c3fSmrg assert(dstFormat == MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT); 223af69d88dSmrg 224af69d88dSmrg return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat, 225af69d88dSmrg dstFormat, dstRowStride, dstSlices, 226af69d88dSmrg srcWidth, srcHeight, srcDepth, 227af69d88dSmrg srcFormat, srcType, 228af69d88dSmrg srcAddr, srcPacking, 229af69d88dSmrg true /* signed */); 230af69d88dSmrg} 231af69d88dSmrg 232af69d88dSmrgGLboolean 233af69d88dSmrg_mesa_texstore_bptc_rgb_unsigned_float(TEXSTORE_PARAMS) 234af69d88dSmrg{ 23501e04c3fSmrg assert(dstFormat == MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT); 236af69d88dSmrg 237af69d88dSmrg return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat, 238af69d88dSmrg dstFormat, dstRowStride, dstSlices, 239af69d88dSmrg srcWidth, srcHeight, srcDepth, 240af69d88dSmrg srcFormat, srcType, 241af69d88dSmrg srcAddr, srcPacking, 242af69d88dSmrg false /* unsigned */); 243af69d88dSmrg} 244