1848b8605Smrg/* 2848b8605Smrg * Copyright (C) 2014 Intel Corporation 3848b8605Smrg * 4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5848b8605Smrg * copy of this software and associated documentation files (the "Software"), 6848b8605Smrg * to deal in the Software without restriction, including without limitation 7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 9848b8605Smrg * Software is furnished to do so, subject to the following conditions: 10848b8605Smrg * 11848b8605Smrg * The above copyright notice and this permission notice (including the next 12848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the 13848b8605Smrg * Software. 14848b8605Smrg * 15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21848b8605Smrg * DEALINGS IN THE SOFTWARE. 22848b8605Smrg */ 23848b8605Smrg 24848b8605Smrg/** 25848b8605Smrg * \file texcompress_bptc.c 26848b8605Smrg * GL_ARB_texture_compression_bptc support. 27848b8605Smrg */ 28848b8605Smrg 29848b8605Smrg#include <stdbool.h> 30848b8605Smrg#include "texcompress.h" 31848b8605Smrg#include "texcompress_bptc.h" 32b8e80941Smrg#include "texcompress_bptc_tmp.h" 33848b8605Smrg#include "texstore.h" 34848b8605Smrg#include "image.h" 35b8e80941Smrg#include "mtypes.h" 36848b8605Smrg 37b8e80941Smrgstatic void 38b8e80941Smrgfetch_bptc_rgb_float(const GLubyte *map, 39b8e80941Smrg GLint rowStride, GLint i, GLint j, 40b8e80941Smrg GLfloat *texel, 41b8e80941Smrg bool is_signed) 42848b8605Smrg{ 43b8e80941Smrg const GLubyte *block; 44848b8605Smrg 45b8e80941Smrg block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; 46848b8605Smrg 47b8e80941Smrg fetch_rgb_float_from_block(block, texel, (i % 4) + (j % 4) * 4, is_signed); 48848b8605Smrg} 49848b8605Smrg 50848b8605Smrgstatic void 51b8e80941Smrgfetch_bptc_rgb_signed_float(const GLubyte *map, 52b8e80941Smrg GLint rowStride, GLint i, GLint j, 53b8e80941Smrg GLfloat *texel) 54848b8605Smrg{ 55b8e80941Smrg fetch_bptc_rgb_float(map, rowStride, i, j, texel, true); 56848b8605Smrg} 57848b8605Smrg 58848b8605Smrgstatic void 59b8e80941Smrgfetch_bptc_rgb_unsigned_float(const GLubyte *map, 60b8e80941Smrg GLint rowStride, GLint i, GLint j, 61b8e80941Smrg GLfloat *texel) 62848b8605Smrg{ 63b8e80941Smrg fetch_bptc_rgb_float(map, rowStride, i, j, texel, false); 64848b8605Smrg} 65848b8605Smrg 66848b8605Smrgstatic void 67848b8605Smrgfetch_bptc_rgba_unorm_bytes(const GLubyte *map, 68848b8605Smrg GLint rowStride, GLint i, GLint j, 69848b8605Smrg GLubyte *texel) 70848b8605Smrg{ 71848b8605Smrg const GLubyte *block; 72848b8605Smrg 73848b8605Smrg block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; 74848b8605Smrg 75848b8605Smrg fetch_rgba_unorm_from_block(block, texel, (i % 4) + (j % 4) * 4); 76848b8605Smrg} 77848b8605Smrg 78848b8605Smrgstatic void 79848b8605Smrgfetch_bptc_rgba_unorm(const GLubyte *map, 80848b8605Smrg GLint rowStride, GLint i, GLint j, 81848b8605Smrg GLfloat *texel) 82848b8605Smrg{ 83848b8605Smrg GLubyte texel_bytes[4]; 84848b8605Smrg 85848b8605Smrg fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes); 86848b8605Smrg 87848b8605Smrg texel[RCOMP] = UBYTE_TO_FLOAT(texel_bytes[0]); 88848b8605Smrg texel[GCOMP] = UBYTE_TO_FLOAT(texel_bytes[1]); 89848b8605Smrg texel[BCOMP] = UBYTE_TO_FLOAT(texel_bytes[2]); 90848b8605Smrg texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]); 91848b8605Smrg} 92848b8605Smrg 93848b8605Smrgstatic void 94848b8605Smrgfetch_bptc_srgb_alpha_unorm(const GLubyte *map, 95848b8605Smrg GLint rowStride, GLint i, GLint j, 96848b8605Smrg GLfloat *texel) 97848b8605Smrg{ 98848b8605Smrg GLubyte texel_bytes[4]; 99848b8605Smrg 100848b8605Smrg fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes); 101848b8605Smrg 102848b8605Smrg texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[0]); 103848b8605Smrg texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[1]); 104848b8605Smrg texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[2]); 105848b8605Smrg texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]); 106848b8605Smrg} 107848b8605Smrg 108848b8605Smrgcompressed_fetch_func 109848b8605Smrg_mesa_get_bptc_fetch_func(mesa_format format) 110848b8605Smrg{ 111848b8605Smrg switch (format) { 112848b8605Smrg case MESA_FORMAT_BPTC_RGBA_UNORM: 113848b8605Smrg return fetch_bptc_rgba_unorm; 114848b8605Smrg case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM: 115848b8605Smrg return fetch_bptc_srgb_alpha_unorm; 116848b8605Smrg case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT: 117848b8605Smrg return fetch_bptc_rgb_signed_float; 118848b8605Smrg case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT: 119848b8605Smrg return fetch_bptc_rgb_unsigned_float; 120848b8605Smrg default: 121848b8605Smrg return NULL; 122848b8605Smrg } 123848b8605Smrg} 124848b8605Smrg 125848b8605SmrgGLboolean 126848b8605Smrg_mesa_texstore_bptc_rgba_unorm(TEXSTORE_PARAMS) 127848b8605Smrg{ 128848b8605Smrg const GLubyte *pixels; 129848b8605Smrg const GLubyte *tempImage = NULL; 130848b8605Smrg int rowstride; 131848b8605Smrg 132848b8605Smrg if (srcFormat != GL_RGBA || 133848b8605Smrg srcType != GL_UNSIGNED_BYTE || 134848b8605Smrg ctx->_ImageTransferState || 135848b8605Smrg srcPacking->SwapBytes) { 136848b8605Smrg /* convert image to RGBA/ubyte */ 137b8e80941Smrg GLubyte *tempImageSlices[1]; 138b8e80941Smrg int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte); 139b8e80941Smrg tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte)); 140848b8605Smrg if (!tempImage) 141848b8605Smrg return GL_FALSE; /* out of memory */ 142b8e80941Smrg tempImageSlices[0] = (GLubyte *) tempImage; 143b8e80941Smrg _mesa_texstore(ctx, dims, 144b8e80941Smrg baseInternalFormat, 145b8e80941Smrg _mesa_little_endian() ? MESA_FORMAT_R8G8B8A8_UNORM 146b8e80941Smrg : MESA_FORMAT_A8B8G8R8_UNORM, 147b8e80941Smrg rgbaRowStride, tempImageSlices, 148b8e80941Smrg srcWidth, srcHeight, srcDepth, 149b8e80941Smrg srcFormat, srcType, srcAddr, 150b8e80941Smrg srcPacking); 151848b8605Smrg 152848b8605Smrg pixels = tempImage; 153848b8605Smrg rowstride = srcWidth * 4; 154848b8605Smrg } else { 155848b8605Smrg pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight, 156848b8605Smrg srcFormat, srcType, 0, 0); 157848b8605Smrg rowstride = _mesa_image_row_stride(srcPacking, srcWidth, 158848b8605Smrg srcFormat, srcType); 159848b8605Smrg } 160848b8605Smrg 161848b8605Smrg compress_rgba_unorm(srcWidth, srcHeight, 162848b8605Smrg pixels, rowstride, 163848b8605Smrg dstSlices[0], dstRowStride); 164848b8605Smrg 165848b8605Smrg free((void *) tempImage); 166848b8605Smrg 167848b8605Smrg return GL_TRUE; 168848b8605Smrg} 169848b8605Smrg 170848b8605Smrgstatic GLboolean 171848b8605Smrgtexstore_bptc_rgb_float(TEXSTORE_PARAMS, 172848b8605Smrg bool is_signed) 173848b8605Smrg{ 174848b8605Smrg const float *pixels; 175848b8605Smrg const float *tempImage = NULL; 176848b8605Smrg int rowstride; 177848b8605Smrg 178848b8605Smrg if (srcFormat != GL_RGB || 179848b8605Smrg srcType != GL_FLOAT || 180848b8605Smrg ctx->_ImageTransferState || 181848b8605Smrg srcPacking->SwapBytes) { 182848b8605Smrg /* convert image to RGB/float */ 183b8e80941Smrg GLfloat *tempImageSlices[1]; 184b8e80941Smrg int rgbRowStride = 3 * srcWidth * sizeof(GLfloat); 185b8e80941Smrg tempImage = malloc(srcWidth * srcHeight * 3 * sizeof(GLfloat)); 186848b8605Smrg if (!tempImage) 187848b8605Smrg return GL_FALSE; /* out of memory */ 188b8e80941Smrg tempImageSlices[0] = (GLfloat *) tempImage; 189b8e80941Smrg _mesa_texstore(ctx, dims, 190b8e80941Smrg baseInternalFormat, 191b8e80941Smrg MESA_FORMAT_RGB_FLOAT32, 192b8e80941Smrg rgbRowStride, (GLubyte **)tempImageSlices, 193b8e80941Smrg srcWidth, srcHeight, srcDepth, 194b8e80941Smrg srcFormat, srcType, srcAddr, 195b8e80941Smrg srcPacking); 196848b8605Smrg 197848b8605Smrg pixels = tempImage; 198848b8605Smrg rowstride = srcWidth * sizeof(float) * 3; 199848b8605Smrg } else { 200848b8605Smrg pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight, 201848b8605Smrg srcFormat, srcType, 0, 0); 202848b8605Smrg rowstride = _mesa_image_row_stride(srcPacking, srcWidth, 203848b8605Smrg srcFormat, srcType); 204848b8605Smrg } 205848b8605Smrg 206848b8605Smrg compress_rgb_float(srcWidth, srcHeight, 207848b8605Smrg pixels, rowstride, 208848b8605Smrg dstSlices[0], dstRowStride, 209848b8605Smrg is_signed); 210848b8605Smrg 211848b8605Smrg free((void *) tempImage); 212848b8605Smrg 213848b8605Smrg return GL_TRUE; 214848b8605Smrg} 215848b8605Smrg 216848b8605SmrgGLboolean 217848b8605Smrg_mesa_texstore_bptc_rgb_signed_float(TEXSTORE_PARAMS) 218848b8605Smrg{ 219b8e80941Smrg assert(dstFormat == MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT); 220848b8605Smrg 221848b8605Smrg return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat, 222848b8605Smrg dstFormat, dstRowStride, dstSlices, 223848b8605Smrg srcWidth, srcHeight, srcDepth, 224848b8605Smrg srcFormat, srcType, 225848b8605Smrg srcAddr, srcPacking, 226848b8605Smrg true /* signed */); 227848b8605Smrg} 228848b8605Smrg 229848b8605SmrgGLboolean 230848b8605Smrg_mesa_texstore_bptc_rgb_unsigned_float(TEXSTORE_PARAMS) 231848b8605Smrg{ 232b8e80941Smrg assert(dstFormat == MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT); 233848b8605Smrg 234848b8605Smrg return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat, 235848b8605Smrg dstFormat, dstRowStride, dstSlices, 236848b8605Smrg srcWidth, srcHeight, srcDepth, 237848b8605Smrg srcFormat, srcType, 238848b8605Smrg srcAddr, srcPacking, 239848b8605Smrg false /* unsigned */); 240848b8605Smrg} 241