1/* 2 * Copyright (C) 2014 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24/** 25 * \file texcompress_bptc.c 26 * GL_ARB_texture_compression_bptc support. 27 */ 28 29#include <stdbool.h> 30#include "texcompress.h" 31#include "texcompress_bptc.h" 32#include "texcompress_bptc_tmp.h" 33#include "texstore.h" 34#include "image.h" 35#include "mtypes.h" 36 37static void 38fetch_bptc_rgb_float(const GLubyte *map, 39 GLint rowStride, GLint i, GLint j, 40 GLfloat *texel, 41 bool is_signed) 42{ 43 const GLubyte *block; 44 45 block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; 46 47 fetch_rgb_float_from_block(block, texel, (i % 4) + (j % 4) * 4, is_signed); 48} 49 50static void 51fetch_bptc_rgb_signed_float(const GLubyte *map, 52 GLint rowStride, GLint i, GLint j, 53 GLfloat *texel) 54{ 55 fetch_bptc_rgb_float(map, rowStride, i, j, texel, true); 56} 57 58static void 59fetch_bptc_rgb_unsigned_float(const GLubyte *map, 60 GLint rowStride, GLint i, GLint j, 61 GLfloat *texel) 62{ 63 fetch_bptc_rgb_float(map, rowStride, i, j, texel, false); 64} 65 66static void 67fetch_bptc_rgba_unorm_bytes(const GLubyte *map, 68 GLint rowStride, GLint i, GLint j, 69 GLubyte *texel) 70{ 71 const GLubyte *block; 72 73 block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; 74 75 fetch_rgba_unorm_from_block(block, texel, (i % 4) + (j % 4) * 4); 76} 77 78static void 79fetch_bptc_rgba_unorm(const GLubyte *map, 80 GLint rowStride, GLint i, GLint j, 81 GLfloat *texel) 82{ 83 GLubyte texel_bytes[4]; 84 85 fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes); 86 87 texel[RCOMP] = UBYTE_TO_FLOAT(texel_bytes[0]); 88 texel[GCOMP] = UBYTE_TO_FLOAT(texel_bytes[1]); 89 texel[BCOMP] = UBYTE_TO_FLOAT(texel_bytes[2]); 90 texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]); 91} 92 93static void 94fetch_bptc_srgb_alpha_unorm(const GLubyte *map, 95 GLint rowStride, GLint i, GLint j, 96 GLfloat *texel) 97{ 98 GLubyte texel_bytes[4]; 99 100 fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes); 101 102 texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[0]); 103 texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[1]); 104 texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[2]); 105 texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]); 106} 107 108compressed_fetch_func 109_mesa_get_bptc_fetch_func(mesa_format format) 110{ 111 switch (format) { 112 case MESA_FORMAT_BPTC_RGBA_UNORM: 113 return fetch_bptc_rgba_unorm; 114 case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM: 115 return fetch_bptc_srgb_alpha_unorm; 116 case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT: 117 return fetch_bptc_rgb_signed_float; 118 case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT: 119 return fetch_bptc_rgb_unsigned_float; 120 default: 121 return NULL; 122 } 123} 124 125GLboolean 126_mesa_texstore_bptc_rgba_unorm(TEXSTORE_PARAMS) 127{ 128 const GLubyte *pixels; 129 const GLubyte *tempImage = NULL; 130 int rowstride; 131 132 if (srcFormat != GL_RGBA || 133 srcType != GL_UNSIGNED_BYTE || 134 ctx->_ImageTransferState || 135 srcPacking->SwapBytes) { 136 /* convert image to RGBA/ubyte */ 137 GLubyte *tempImageSlices[1]; 138 int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte); 139 tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte)); 140 if (!tempImage) 141 return GL_FALSE; /* out of memory */ 142 tempImageSlices[0] = (GLubyte *) tempImage; 143 _mesa_texstore(ctx, dims, 144 baseInternalFormat, 145 _mesa_little_endian() ? MESA_FORMAT_R8G8B8A8_UNORM 146 : MESA_FORMAT_A8B8G8R8_UNORM, 147 rgbaRowStride, tempImageSlices, 148 srcWidth, srcHeight, srcDepth, 149 srcFormat, srcType, srcAddr, 150 srcPacking); 151 152 pixels = tempImage; 153 rowstride = srcWidth * 4; 154 } else { 155 pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight, 156 srcFormat, srcType, 0, 0); 157 rowstride = _mesa_image_row_stride(srcPacking, srcWidth, 158 srcFormat, srcType); 159 } 160 161 compress_rgba_unorm(srcWidth, srcHeight, 162 pixels, rowstride, 163 dstSlices[0], dstRowStride); 164 165 free((void *) tempImage); 166 167 return GL_TRUE; 168} 169 170static GLboolean 171texstore_bptc_rgb_float(TEXSTORE_PARAMS, 172 bool is_signed) 173{ 174 const float *pixels; 175 const float *tempImage = NULL; 176 int rowstride; 177 178 if (srcFormat != GL_RGB || 179 srcType != GL_FLOAT || 180 ctx->_ImageTransferState || 181 srcPacking->SwapBytes) { 182 /* convert image to RGB/float */ 183 GLfloat *tempImageSlices[1]; 184 int rgbRowStride = 3 * srcWidth * sizeof(GLfloat); 185 tempImage = malloc(srcWidth * srcHeight * 3 * sizeof(GLfloat)); 186 if (!tempImage) 187 return GL_FALSE; /* out of memory */ 188 tempImageSlices[0] = (GLfloat *) tempImage; 189 _mesa_texstore(ctx, dims, 190 baseInternalFormat, 191 MESA_FORMAT_RGB_FLOAT32, 192 rgbRowStride, (GLubyte **)tempImageSlices, 193 srcWidth, srcHeight, srcDepth, 194 srcFormat, srcType, srcAddr, 195 srcPacking); 196 197 pixels = tempImage; 198 rowstride = srcWidth * sizeof(float) * 3; 199 } else { 200 pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight, 201 srcFormat, srcType, 0, 0); 202 rowstride = _mesa_image_row_stride(srcPacking, srcWidth, 203 srcFormat, srcType); 204 } 205 206 compress_rgb_float(srcWidth, srcHeight, 207 pixels, rowstride, 208 dstSlices[0], dstRowStride, 209 is_signed); 210 211 free((void *) tempImage); 212 213 return GL_TRUE; 214} 215 216GLboolean 217_mesa_texstore_bptc_rgb_signed_float(TEXSTORE_PARAMS) 218{ 219 assert(dstFormat == MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT); 220 221 return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat, 222 dstFormat, dstRowStride, dstSlices, 223 srcWidth, srcHeight, srcDepth, 224 srcFormat, srcType, 225 srcAddr, srcPacking, 226 true /* signed */); 227} 228 229GLboolean 230_mesa_texstore_bptc_rgb_unsigned_float(TEXSTORE_PARAMS) 231{ 232 assert(dstFormat == MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT); 233 234 return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat, 235 dstFormat, dstRowStride, dstSlices, 236 srcWidth, srcHeight, srcDepth, 237 srcFormat, srcType, 238 srcAddr, srcPacking, 239 false /* unsigned */); 240} 241