/*
|
* Copyright (C) 2011 Red Hat Inc.
|
*
|
* block compression parts are:
|
* Copyright (C) 2004 Roland Scheidegger All Rights Reserved.
|
*
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
* copy of this software and associated documentation files (the "Software"),
|
* to deal in the Software without restriction, including without limitation
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* and/or sell copies of the Software, and to permit persons to whom the
|
* Software is furnished to do so, subject to the following conditions:
|
*
|
* The above copyright notice and this permission notice (including the next
|
* paragraph) shall be included in all copies or substantial portions of the
|
* Software.
|
*
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
* DEALINGS IN THE SOFTWARE.
|
*
|
* Author:
|
* Dave Airlie
|
*/
|
|
/**
|
* \file texcompress_rgtc.c
|
* GL_EXT_texture_compression_rgtc support.
|
*/
|
|
|
#include "glheader.h"
|
#include "imports.h"
|
#include "image.h"
|
#include "macros.h"
|
#include "mipmap.h"
|
#include "texcompress.h"
|
#include "util/rgtc.h"
|
#include "texcompress_rgtc.h"
|
#include "texstore.h"
|
|
static void extractsrc_u( GLubyte srcpixels[4][4], const GLubyte *srcaddr,
|
GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
|
{
|
GLubyte i, j;
|
const GLubyte *curaddr;
|
for (j = 0; j < numypixels; j++) {
|
curaddr = srcaddr + j * srcRowStride * comps;
|
for (i = 0; i < numxpixels; i++) {
|
srcpixels[j][i] = *curaddr;
|
curaddr += comps;
|
}
|
}
|
}
|
|
static void extractsrc_s( GLbyte srcpixels[4][4], const GLfloat *srcaddr,
|
GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
|
{
|
GLubyte i, j;
|
const GLfloat *curaddr;
|
for (j = 0; j < numypixels; j++) {
|
curaddr = srcaddr + j * srcRowStride * comps;
|
for (i = 0; i < numxpixels; i++) {
|
srcpixels[j][i] = FLOAT_TO_BYTE_TEX(*curaddr);
|
curaddr += comps;
|
}
|
}
|
}
|
|
|
GLboolean
|
_mesa_texstore_red_rgtc1(TEXSTORE_PARAMS)
|
{
|
GLubyte *dst;
|
const GLubyte *tempImage = NULL;
|
int i, j;
|
int numxpixels, numypixels;
|
const GLubyte *srcaddr;
|
GLubyte srcpixels[4][4];
|
GLubyte *blkaddr;
|
GLint dstRowDiff, redRowStride;
|
GLubyte *tempImageSlices[1];
|
|
assert(dstFormat == MESA_FORMAT_R_RGTC1_UNORM ||
|
dstFormat == MESA_FORMAT_L_LATC1_UNORM);
|
|
tempImage = malloc(srcWidth * srcHeight * 1 * sizeof(GLubyte));
|
if (!tempImage)
|
return GL_FALSE; /* out of memory */
|
redRowStride = 1 * srcWidth * sizeof(GLubyte);
|
tempImageSlices[0] = (GLubyte *) tempImage;
|
_mesa_texstore(ctx, dims,
|
baseInternalFormat,
|
MESA_FORMAT_R_UNORM8,
|
redRowStride, tempImageSlices,
|
srcWidth, srcHeight, srcDepth,
|
srcFormat, srcType, srcAddr,
|
srcPacking);
|
|
dst = dstSlices[0];
|
|
blkaddr = dst;
|
dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
|
for (j = 0; j < srcHeight; j+=4) {
|
if (srcHeight > j + 3) numypixels = 4;
|
else numypixels = srcHeight - j;
|
srcaddr = tempImage + j * srcWidth;
|
for (i = 0; i < srcWidth; i += 4) {
|
if (srcWidth > i + 3) numxpixels = 4;
|
else numxpixels = srcWidth - i;
|
extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
|
util_format_unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
|
srcaddr += numxpixels;
|
blkaddr += 8;
|
}
|
blkaddr += dstRowDiff;
|
}
|
|
free((void *) tempImage);
|
|
return GL_TRUE;
|
}
|
|
GLboolean
|
_mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS)
|
{
|
GLbyte *dst;
|
const GLfloat *tempImage = NULL;
|
int i, j;
|
int numxpixels, numypixels;
|
const GLfloat *srcaddr;
|
GLbyte srcpixels[4][4];
|
GLbyte *blkaddr;
|
GLint dstRowDiff, redRowStride;
|
GLfloat *tempImageSlices[1];
|
|
assert(dstFormat == MESA_FORMAT_R_RGTC1_SNORM ||
|
dstFormat == MESA_FORMAT_L_LATC1_SNORM);
|
|
redRowStride = 1 * srcWidth * sizeof(GLfloat);
|
tempImage = malloc(srcWidth * srcHeight * 1 * sizeof(GLfloat));
|
if (!tempImage)
|
return GL_FALSE; /* out of memory */
|
tempImageSlices[0] = (GLfloat *) tempImage;
|
_mesa_texstore(ctx, dims,
|
baseInternalFormat,
|
MESA_FORMAT_R_FLOAT32,
|
redRowStride, (GLubyte **)tempImageSlices,
|
srcWidth, srcHeight, srcDepth,
|
srcFormat, srcType, srcAddr,
|
srcPacking);
|
|
dst = (GLbyte *) dstSlices[0];
|
|
blkaddr = dst;
|
dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
|
for (j = 0; j < srcHeight; j+=4) {
|
if (srcHeight > j + 3) numypixels = 4;
|
else numypixels = srcHeight - j;
|
srcaddr = tempImage + j * srcWidth;
|
for (i = 0; i < srcWidth; i += 4) {
|
if (srcWidth > i + 3) numxpixels = 4;
|
else numxpixels = srcWidth - i;
|
extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
|
util_format_signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
|
srcaddr += numxpixels;
|
blkaddr += 8;
|
}
|
blkaddr += dstRowDiff;
|
}
|
|
free((void *) tempImage);
|
|
return GL_TRUE;
|
}
|
|
GLboolean
|
_mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)
|
{
|
GLubyte *dst;
|
const GLubyte *tempImage = NULL;
|
int i, j;
|
int numxpixels, numypixels;
|
const GLubyte *srcaddr;
|
GLubyte srcpixels[4][4];
|
GLubyte *blkaddr;
|
GLint dstRowDiff, rgRowStride;
|
mesa_format tempFormat;
|
GLubyte *tempImageSlices[1];
|
|
assert(dstFormat == MESA_FORMAT_RG_RGTC2_UNORM ||
|
dstFormat == MESA_FORMAT_LA_LATC2_UNORM);
|
|
if (baseInternalFormat == GL_RG)
|
tempFormat = _mesa_little_endian() ? MESA_FORMAT_R8G8_UNORM
|
: MESA_FORMAT_G8R8_UNORM;
|
else
|
tempFormat = _mesa_little_endian() ? MESA_FORMAT_L8A8_UNORM
|
: MESA_FORMAT_A8L8_UNORM;
|
|
rgRowStride = 2 * srcWidth * sizeof(GLubyte);
|
tempImage = malloc(srcWidth * srcHeight * 2 * sizeof(GLubyte));
|
if (!tempImage)
|
return GL_FALSE; /* out of memory */
|
tempImageSlices[0] = (GLubyte *) tempImage;
|
_mesa_texstore(ctx, dims,
|
baseInternalFormat,
|
tempFormat,
|
rgRowStride, tempImageSlices,
|
srcWidth, srcHeight, srcDepth,
|
srcFormat, srcType, srcAddr,
|
srcPacking);
|
|
dst = dstSlices[0];
|
|
blkaddr = dst;
|
dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
|
for (j = 0; j < srcHeight; j+=4) {
|
if (srcHeight > j + 3) numypixels = 4;
|
else numypixels = srcHeight - j;
|
srcaddr = tempImage + j * srcWidth * 2;
|
for (i = 0; i < srcWidth; i += 4) {
|
if (srcWidth > i + 3) numxpixels = 4;
|
else numxpixels = srcWidth - i;
|
extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
|
util_format_unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
|
|
blkaddr += 8;
|
extractsrc_u(srcpixels, (GLubyte *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
|
util_format_unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
|
|
blkaddr += 8;
|
|
srcaddr += numxpixels * 2;
|
}
|
blkaddr += dstRowDiff;
|
}
|
|
free((void *) tempImage);
|
|
return GL_TRUE;
|
}
|
|
GLboolean
|
_mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS)
|
{
|
GLbyte *dst;
|
const GLfloat *tempImage = NULL;
|
int i, j;
|
int numxpixels, numypixels;
|
const GLfloat *srcaddr;
|
GLbyte srcpixels[4][4];
|
GLbyte *blkaddr;
|
GLint dstRowDiff, rgRowStride;
|
mesa_format tempFormat;
|
GLfloat *tempImageSlices[1];
|
|
assert(dstFormat == MESA_FORMAT_RG_RGTC2_SNORM ||
|
dstFormat == MESA_FORMAT_LA_LATC2_SNORM);
|
|
if (baseInternalFormat == GL_RG)
|
tempFormat = MESA_FORMAT_RG_FLOAT32;
|
else
|
tempFormat = MESA_FORMAT_LA_FLOAT32;
|
|
rgRowStride = 2 * srcWidth * sizeof(GLfloat);
|
tempImage = malloc(srcWidth * srcHeight * 2 * sizeof(GLfloat));
|
if (!tempImage)
|
return GL_FALSE; /* out of memory */
|
tempImageSlices[0] = (GLfloat *) tempImage;
|
_mesa_texstore(ctx, dims,
|
baseInternalFormat,
|
tempFormat,
|
rgRowStride, (GLubyte **)tempImageSlices,
|
srcWidth, srcHeight, srcDepth,
|
srcFormat, srcType, srcAddr,
|
srcPacking);
|
|
dst = (GLbyte *) dstSlices[0];
|
|
blkaddr = dst;
|
dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
|
for (j = 0; j < srcHeight; j += 4) {
|
if (srcHeight > j + 3) numypixels = 4;
|
else numypixels = srcHeight - j;
|
srcaddr = tempImage + j * srcWidth * 2;
|
for (i = 0; i < srcWidth; i += 4) {
|
if (srcWidth > i + 3) numxpixels = 4;
|
else numxpixels = srcWidth - i;
|
|
extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
|
util_format_signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
|
blkaddr += 8;
|
|
extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
|
util_format_signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
|
blkaddr += 8;
|
|
srcaddr += numxpixels * 2;
|
|
}
|
blkaddr += dstRowDiff;
|
}
|
|
free((void *) tempImage);
|
|
return GL_TRUE;
|
}
|
|
static void
|
fetch_red_rgtc1(const GLubyte *map,
|
GLint rowStride, GLint i, GLint j, GLfloat *texel)
|
{
|
GLubyte red;
|
util_format_unsigned_fetch_texel_rgtc(rowStride, map, i, j, &red, 1);
|
texel[RCOMP] = UBYTE_TO_FLOAT(red);
|
texel[GCOMP] = 0.0;
|
texel[BCOMP] = 0.0;
|
texel[ACOMP] = 1.0;
|
}
|
|
static void
|
fetch_l_latc1(const GLubyte *map,
|
GLint rowStride, GLint i, GLint j, GLfloat *texel)
|
{
|
GLubyte red;
|
util_format_unsigned_fetch_texel_rgtc(rowStride, map, i, j, &red, 1);
|
texel[RCOMP] =
|
texel[GCOMP] =
|
texel[BCOMP] = UBYTE_TO_FLOAT(red);
|
texel[ACOMP] = 1.0;
|
}
|
|
static void
|
fetch_signed_red_rgtc1(const GLubyte *map,
|
GLint rowStride, GLint i, GLint j, GLfloat *texel)
|
{
|
GLbyte red;
|
util_format_signed_fetch_texel_rgtc(rowStride, (const GLbyte *) map,
|
i, j, &red, 1);
|
texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
|
texel[GCOMP] = 0.0;
|
texel[BCOMP] = 0.0;
|
texel[ACOMP] = 1.0;
|
}
|
|
static void
|
fetch_signed_l_latc1(const GLubyte *map,
|
GLint rowStride, GLint i, GLint j, GLfloat *texel)
|
{
|
GLbyte red;
|
util_format_signed_fetch_texel_rgtc(rowStride, (GLbyte *) map,
|
i, j, &red, 1);
|
texel[RCOMP] =
|
texel[GCOMP] =
|
texel[BCOMP] = BYTE_TO_FLOAT(red);
|
texel[ACOMP] = 1.0;
|
}
|
|
static void
|
fetch_rg_rgtc2(const GLubyte *map,
|
GLint rowStride, GLint i, GLint j, GLfloat *texel)
|
{
|
GLubyte red, green;
|
util_format_unsigned_fetch_texel_rgtc(rowStride,
|
map,
|
i, j, &red, 2);
|
util_format_unsigned_fetch_texel_rgtc(rowStride,
|
map + 8,
|
i, j, &green, 2);
|
texel[RCOMP] = UBYTE_TO_FLOAT(red);
|
texel[GCOMP] = UBYTE_TO_FLOAT(green);
|
texel[BCOMP] = 0.0;
|
texel[ACOMP] = 1.0;
|
}
|
|
static void
|
fetch_la_latc2(const GLubyte *map,
|
GLint rowStride, GLint i, GLint j, GLfloat *texel)
|
{
|
GLubyte red, green;
|
util_format_unsigned_fetch_texel_rgtc(rowStride,
|
map,
|
i, j, &red, 2);
|
util_format_unsigned_fetch_texel_rgtc(rowStride,
|
map + 8,
|
i, j, &green, 2);
|
texel[RCOMP] =
|
texel[GCOMP] =
|
texel[BCOMP] = UBYTE_TO_FLOAT(red);
|
texel[ACOMP] = UBYTE_TO_FLOAT(green);
|
}
|
|
|
static void
|
fetch_signed_rg_rgtc2(const GLubyte *map,
|
GLint rowStride, GLint i, GLint j, GLfloat *texel)
|
{
|
GLbyte red, green;
|
util_format_signed_fetch_texel_rgtc(rowStride,
|
(GLbyte *) map,
|
i, j, &red, 2);
|
util_format_signed_fetch_texel_rgtc(rowStride,
|
(GLbyte *) map + 8,
|
i, j, &green, 2);
|
texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
|
texel[GCOMP] = BYTE_TO_FLOAT_TEX(green);
|
texel[BCOMP] = 0.0;
|
texel[ACOMP] = 1.0;
|
}
|
|
|
static void
|
fetch_signed_la_latc2(const GLubyte *map,
|
GLint rowStride, GLint i, GLint j, GLfloat *texel)
|
{
|
GLbyte red, green;
|
util_format_signed_fetch_texel_rgtc(rowStride,
|
(GLbyte *) map,
|
i, j, &red, 2);
|
util_format_signed_fetch_texel_rgtc(rowStride,
|
(GLbyte *) map + 8,
|
i, j, &green, 2);
|
texel[RCOMP] =
|
texel[GCOMP] =
|
texel[BCOMP] = BYTE_TO_FLOAT_TEX(red);
|
texel[ACOMP] = BYTE_TO_FLOAT_TEX(green);
|
}
|
|
|
compressed_fetch_func
|
_mesa_get_compressed_rgtc_func(mesa_format format)
|
{
|
switch (format) {
|
case MESA_FORMAT_R_RGTC1_UNORM:
|
return fetch_red_rgtc1;
|
case MESA_FORMAT_L_LATC1_UNORM:
|
return fetch_l_latc1;
|
case MESA_FORMAT_R_RGTC1_SNORM:
|
return fetch_signed_red_rgtc1;
|
case MESA_FORMAT_L_LATC1_SNORM:
|
return fetch_signed_l_latc1;
|
case MESA_FORMAT_RG_RGTC2_UNORM:
|
return fetch_rg_rgtc2;
|
case MESA_FORMAT_LA_LATC2_UNORM:
|
return fetch_la_latc2;
|
case MESA_FORMAT_RG_RGTC2_SNORM:
|
return fetch_signed_rg_rgtc2;
|
case MESA_FORMAT_LA_LATC2_SNORM:
|
return fetch_signed_la_latc2;
|
default:
|
return NULL;
|
}
|
}
|