#include "texcompress.h"
#include "texcompress_etc.h"
#include "texstore.h"
+#include "config.h"
#include "macros.h"
#include "format_unpack.h"
+#include "util/format_srgb.h"
struct etc2_block {
#undef UINT8_TYPE
GLboolean
-_mesa_texstore_etc1_rgb8(TEXSTORE_PARAMS)
+_mesa_texstore_etc1_rgb8(UNUSED_TEXSTORE_PARAMS)
{
/* GL_ETC1_RGB8_OES is only valid in glCompressedTexImage2D */
- ASSERT(0);
+ assert(0);
return GL_FALSE;
}
block->is_planar_mode = true;
/* opaque bit must be set in planar mode */
- if (!block->opaque)
- block->opaque = true;
+ block->opaque = true;
for (i = 0; i < 3; i++) {
block->base_colors[0][i] = etc2_base_color_o_planar(src, i);
/* Use same modifier tables as for etc1 textures if opaque bit is set
* or if non punchthrough texture format
*/
- block->modifier_tables[0] = (block->opaque || !punchthrough_alpha) ?
+ block->modifier_tables[0] = (!punchthrough_alpha || block->opaque) ?
etc1_modifier_tables[table1_idx] :
etc2_modifier_tables_non_opaque[table1_idx];
- block->modifier_tables[1] = (block->opaque || !punchthrough_alpha) ?
+ block->modifier_tables[1] = (!punchthrough_alpha || block->opaque) ?
etc1_modifier_tables[table2_idx] :
etc2_modifier_tables_non_opaque[table2_idx];
if (punchthrough_alpha)
dst[3] = 255;
}
+ else
+ unreachable("unhandled block mode");
}
static void
for (y = 0; y < height; y += bh) {
const uint8_t *src = src_row;
+ /*
+ * Destination texture may not be a multiple of four texels in
+ * height. Compute a safe height to avoid writing outside the texture.
+ */
+ const unsigned h = MIN2(bh, height - y);
for (x = 0; x < width; x+= bw) {
+ /*
+ * Destination texture may not be a multiple of four texels in
+ * width. Compute a safe width to avoid writing outside the texture.
+ */
+ const unsigned w = MIN2(bw, width - x);
+
etc2_rgb8_parse_block(&block, src,
false /* punchthrough_alpha */);
- for (j = 0; j < bh; j++) {
+ for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
- for (i = 0; i < bw; i++) {
+ for (i = 0; i < w; i++) {
etc2_rgb8_fetch_texel(&block, i, j, dst,
false /* punchthrough_alpha */);
dst[3] = 255;
const uint8_t *src_row,
unsigned src_stride,
unsigned width,
- unsigned height)
+ unsigned height,
+ bool bgra)
{
const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
struct etc2_block block;
for (y = 0; y < height; y += bh) {
const uint8_t *src = src_row;
+ const unsigned h = MIN2(bh, height - y);
for (x = 0; x < width; x+= bw) {
+ const unsigned w = MIN2(bw, width - x);
etc2_rgb8_parse_block(&block, src,
false /* punchthrough_alpha */);
- for (j = 0; j < bh; j++) {
+
+ for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
- for (i = 0; i < bw; i++) {
+ for (i = 0; i < w; i++) {
etc2_rgb8_fetch_texel(&block, i, j, dst,
false /* punchthrough_alpha */);
- /* Convert to MESA_FORMAT_SARGB8 */
- tmp = dst[0];
- dst[0] = dst[2];
- dst[2] = tmp;
- dst[3] = 255;
+
+ if (bgra) {
+ /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */
+ tmp = dst[0];
+ dst[0] = dst[2];
+ dst[2] = tmp;
+ dst[3] = 255;
+ }
dst += comps;
}
for (y = 0; y < height; y += bh) {
const uint8_t *src = src_row;
+ const unsigned h = MIN2(bh, height - y);
for (x = 0; x < width; x+= bw) {
+ const unsigned w = MIN2(bw, width - x);
etc2_rgba8_parse_block(&block, src);
- for (j = 0; j < bh; j++) {
+ for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
- for (i = 0; i < bw; i++) {
+ for (i = 0; i < w; i++) {
etc2_rgba8_fetch_texel(&block, i, j, dst);
dst += comps;
}
const uint8_t *src_row,
unsigned src_stride,
unsigned width,
- unsigned height)
+ unsigned height,
+ bool bgra)
{
/* If internalformat is COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, each 4 × 4 block
* of RGBA8888 information is compressed to 128 bits. To decode a block, the
uint8_t tmp;
for (y = 0; y < height; y += bh) {
+ const unsigned h = MIN2(bh, height - y);
const uint8_t *src = src_row;
for (x = 0; x < width; x+= bw) {
+ const unsigned w = MIN2(bw, width - x);
etc2_rgba8_parse_block(&block, src);
- for (j = 0; j < bh; j++) {
+ for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
- for (i = 0; i < bw; i++) {
+ for (i = 0; i < w; i++) {
etc2_rgba8_fetch_texel(&block, i, j, dst);
- /* Convert to MESA_FORMAT_SARGB8 */
- tmp = dst[0];
- dst[0] = dst[2];
- dst[2] = tmp;
- dst[3] = dst[3];
+ if (bgra) {
+ /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */
+ tmp = dst[0];
+ dst[0] = dst[2];
+ dst[2] = tmp;
+ dst[3] = dst[3];
+ }
dst += comps;
}
unsigned x, y, i, j;
for (y = 0; y < height; y += bh) {
+ const unsigned h = MIN2(bh, height - y);
const uint8_t *src = src_row;
for (x = 0; x < width; x+= bw) {
+ const unsigned w = MIN2(bw, width - x);
etc2_r11_parse_block(&block, src);
- for (j = 0; j < bh; j++) {
+ for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps * comp_size;
- for (i = 0; i < bw; i++) {
+ for (i = 0; i < w; i++) {
etc2_r11_fetch_texel(&block, i, j, dst);
dst += comps * comp_size;
}
unsigned x, y, i, j;
for (y = 0; y < height; y += bh) {
+ const unsigned h = MIN2(bh, height - y);
const uint8_t *src = src_row;
for (x = 0; x < width; x+= bw) {
+ const unsigned w = MIN2(bw, width - x);
/* red component */
etc2_r11_parse_block(&block, src);
- for (j = 0; j < bh; j++) {
+ for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride +
x * comps * comp_size;
- for (i = 0; i < bw; i++) {
+ for (i = 0; i < w; i++) {
etc2_r11_fetch_texel(&block, i, j, dst);
dst += comps * comp_size;
}
/* green component */
etc2_r11_parse_block(&block, src + 8);
- for (j = 0; j < bh; j++) {
+ for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride +
x * comps * comp_size;
- for (i = 0; i < bw; i++) {
+ for (i = 0; i < w; i++) {
etc2_r11_fetch_texel(&block, i, j, dst + comp_size);
dst += comps * comp_size;
}
unsigned x, y, i, j;
for (y = 0; y < height; y += bh) {
+ const unsigned h = MIN2(bh, height - y);
const uint8_t *src = src_row;
for (x = 0; x < width; x+= bw) {
+ const unsigned w = MIN2(bw, width - x);
etc2_r11_parse_block(&block, src);
- for (j = 0; j < bh; j++) {
+ for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride +
x * comps * comp_size;
- for (i = 0; i < bw; i++) {
+ for (i = 0; i < w; i++) {
etc2_signed_r11_fetch_texel(&block, i, j, dst);
dst += comps * comp_size;
}
unsigned x, y, i, j;
for (y = 0; y < height; y += bh) {
+ const unsigned h = MIN2(bh, height - y);
const uint8_t *src = src_row;
for (x = 0; x < width; x+= bw) {
+ const unsigned w = MIN2(bw, width - x);
/* red component */
etc2_r11_parse_block(&block, src);
- for (j = 0; j < bh; j++) {
+ for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride +
x * comps * comp_size;
- for (i = 0; i < bw; i++) {
+ for (i = 0; i < w; i++) {
etc2_signed_r11_fetch_texel(&block, i, j, dst);
dst += comps * comp_size;
}
/* green component */
etc2_r11_parse_block(&block, src + 8);
- for (j = 0; j < bh; j++) {
+ for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride +
x * comps * comp_size;
- for (i = 0; i < bw; i++) {
+ for (i = 0; i < w; i++) {
etc2_signed_r11_fetch_texel(&block, i, j, dst + comp_size);
dst += comps * comp_size;
}
unsigned x, y, i, j;
for (y = 0; y < height; y += bh) {
+ const unsigned h = MIN2(bh, height - y);
const uint8_t *src = src_row;
for (x = 0; x < width; x+= bw) {
+ const unsigned w = MIN2(bw, width - x);
etc2_rgb8_parse_block(&block, src,
true /* punchthrough_alpha */);
- for (j = 0; j < bh; j++) {
+ for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
- for (i = 0; i < bw; i++) {
+ for (i = 0; i < w; i++) {
etc2_rgb8_fetch_texel(&block, i, j, dst,
true /* punchthrough_alpha */);
dst += comps;
const uint8_t *src_row,
unsigned src_stride,
unsigned width,
- unsigned height)
+ unsigned height,
+ bool bgra)
{
const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
struct etc2_block block;
uint8_t tmp;
for (y = 0; y < height; y += bh) {
+ const unsigned h = MIN2(bh, height - y);
const uint8_t *src = src_row;
for (x = 0; x < width; x+= bw) {
+ const unsigned w = MIN2(bw, width - x);
etc2_rgb8_parse_block(&block, src,
true /* punchthrough_alpha */);
- for (j = 0; j < bh; j++) {
+ for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
- for (i = 0; i < bw; i++) {
+ for (i = 0; i < w; i++) {
etc2_rgb8_fetch_texel(&block, i, j, dst,
true /* punchthrough_alpha */);
- /* Convert to MESA_FORMAT_SARGB8 */
- tmp = dst[0];
- dst[0] = dst[2];
- dst[2] = tmp;
- dst[3] = dst[3];
+
+ if (bgra) {
+ /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */
+ tmp = dst[0];
+ dst[0] = dst[2];
+ dst[2] = tmp;
+ dst[3] = dst[3];
+ }
dst += comps;
}
/* ETC2 texture formats are valid in glCompressedTexImage2D and
* glCompressedTexSubImage2D functions */
GLboolean
-_mesa_texstore_etc2_rgb8(TEXSTORE_PARAMS)
+_mesa_texstore_etc2_rgb8(UNUSED_TEXSTORE_PARAMS)
{
- ASSERT(0);
+ assert(0);
return GL_FALSE;
}
GLboolean
-_mesa_texstore_etc2_srgb8(TEXSTORE_PARAMS)
+_mesa_texstore_etc2_srgb8(UNUSED_TEXSTORE_PARAMS)
{
- ASSERT(0);
+ assert(0);
return GL_FALSE;
}
GLboolean
-_mesa_texstore_etc2_rgba8_eac(TEXSTORE_PARAMS)
+_mesa_texstore_etc2_rgba8_eac(UNUSED_TEXSTORE_PARAMS)
{
- ASSERT(0);
+ assert(0);
return GL_FALSE;
}
GLboolean
-_mesa_texstore_etc2_srgb8_alpha8_eac(TEXSTORE_PARAMS)
+_mesa_texstore_etc2_srgb8_alpha8_eac(UNUSED_TEXSTORE_PARAMS)
{
- ASSERT(0);
+ assert(0);
return GL_FALSE;
}
GLboolean
-_mesa_texstore_etc2_r11_eac(TEXSTORE_PARAMS)
+_mesa_texstore_etc2_r11_eac(UNUSED_TEXSTORE_PARAMS)
{
- ASSERT(0);
+ assert(0);
return GL_FALSE;
}
GLboolean
-_mesa_texstore_etc2_signed_r11_eac(TEXSTORE_PARAMS)
+_mesa_texstore_etc2_signed_r11_eac(UNUSED_TEXSTORE_PARAMS)
{
- ASSERT(0);
+ assert(0);
return GL_FALSE;
}
GLboolean
-_mesa_texstore_etc2_rg11_eac(TEXSTORE_PARAMS)
+_mesa_texstore_etc2_rg11_eac(UNUSED_TEXSTORE_PARAMS)
{
- ASSERT(0);
+ assert(0);
return GL_FALSE;
}
GLboolean
-_mesa_texstore_etc2_signed_rg11_eac(TEXSTORE_PARAMS)
+_mesa_texstore_etc2_signed_rg11_eac(UNUSED_TEXSTORE_PARAMS)
{
- ASSERT(0);
+ assert(0);
return GL_FALSE;
}
GLboolean
-_mesa_texstore_etc2_rgb8_punchthrough_alpha1(TEXSTORE_PARAMS)
+_mesa_texstore_etc2_rgb8_punchthrough_alpha1(UNUSED_TEXSTORE_PARAMS)
{
- ASSERT(0);
+ assert(0);
return GL_FALSE;
}
GLboolean
-_mesa_texstore_etc2_srgb8_punchthrough_alpha1(TEXSTORE_PARAMS)
+_mesa_texstore_etc2_srgb8_punchthrough_alpha1(UNUSED_TEXSTORE_PARAMS)
{
- ASSERT(0);
+ assert(0);
return GL_FALSE;
}
unsigned src_stride,
unsigned src_width,
unsigned src_height,
- gl_format format)
+ mesa_format format,
+ bool bgra)
{
if (format == MESA_FORMAT_ETC2_RGB8)
etc2_unpack_rgb8(dst_row, dst_stride,
else if (format == MESA_FORMAT_ETC2_SRGB8)
etc2_unpack_srgb8(dst_row, dst_stride,
src_row, src_stride,
- src_width, src_height);
+ src_width, src_height, bgra);
else if (format == MESA_FORMAT_ETC2_RGBA8_EAC)
etc2_unpack_rgba8(dst_row, dst_stride,
src_row, src_stride,
else if (format == MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC)
etc2_unpack_srgb8_alpha8(dst_row, dst_stride,
src_row, src_stride,
- src_width, src_height);
+ src_width, src_height, bgra);
else if (format == MESA_FORMAT_ETC2_R11_EAC)
etc2_unpack_r11(dst_row, dst_stride,
src_row, src_stride,
else if (format == MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1)
etc2_unpack_srgb8_punchthrough_alpha1(dst_row, dst_stride,
src_row, src_stride,
- src_width, src_height);
+ src_width, src_height, bgra);
}
static void
-fetch_etc1_rgb8(const GLubyte *map, const GLuint imageOffsets[],
- GLint rowStride, GLint i, GLint j, GLint k,
+fetch_etc1_rgb8(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j,
GLfloat *texel)
{
struct etc1_block block;
static void
-fetch_etc2_rgb8(const GLubyte *map, const GLuint imageOffsets[],
- GLint rowStride, GLint i, GLint j, GLint k,
- GLfloat *texel)
+fetch_etc2_rgb8(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j, GLfloat *texel)
{
struct etc2_block block;
uint8_t dst[3];
}
static void
-fetch_etc2_srgb8(const GLubyte *map, const GLuint imageOffsets[],
- GLint rowStride, GLint i, GLint j, GLint k,
- GLfloat *texel)
+fetch_etc2_srgb8(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j, GLfloat *texel)
{
struct etc2_block block;
uint8_t dst[3];
etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst,
false /* punchthrough_alpha */);
- texel[RCOMP] = _mesa_nonlinear_to_linear(dst[0]);
- texel[GCOMP] = _mesa_nonlinear_to_linear(dst[1]);
- texel[BCOMP] = _mesa_nonlinear_to_linear(dst[2]);
+ texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]);
+ texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]);
+ texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]);
texel[ACOMP] = 1.0f;
}
static void
-fetch_etc2_rgba8_eac(const GLubyte *map, const GLuint imageOffsets[],
- GLint rowStride, GLint i, GLint j, GLint k,
- GLfloat *texel)
+fetch_etc2_rgba8_eac(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j, GLfloat *texel)
{
struct etc2_block block;
uint8_t dst[4];
}
static void
-fetch_etc2_srgb8_alpha8_eac(const GLubyte *map, const GLuint imageOffsets[],
- GLint rowStride, GLint i, GLint j, GLint k,
- GLfloat *texel)
+fetch_etc2_srgb8_alpha8_eac(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j, GLfloat *texel)
{
struct etc2_block block;
uint8_t dst[4];
etc2_rgba8_parse_block(&block, src);
etc2_rgba8_fetch_texel(&block, i % 4, j % 4, dst);
- texel[RCOMP] = _mesa_nonlinear_to_linear(dst[0]);
- texel[GCOMP] = _mesa_nonlinear_to_linear(dst[1]);
- texel[BCOMP] = _mesa_nonlinear_to_linear(dst[2]);
+ texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]);
+ texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]);
+ texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]);
texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]);
}
static void
-fetch_etc2_r11_eac(const GLubyte *map, const GLuint imageOffsets[],
- GLint rowStride, GLint i, GLint j, GLint k,
- GLfloat *texel)
+fetch_etc2_r11_eac(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j, GLfloat *texel)
{
struct etc2_block block;
GLushort dst;
}
static void
-fetch_etc2_rg11_eac(const GLubyte *map, const GLuint imageOffsets[],
- GLint rowStride, GLint i, GLint j, GLint k,
- GLfloat *texel)
+fetch_etc2_rg11_eac(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j, GLfloat *texel)
{
struct etc2_block block;
GLushort dst[2];
}
static void
-fetch_etc2_signed_r11_eac(const GLubyte *map, const GLuint imageOffsets[],
- GLint rowStride, GLint i, GLint j, GLint k,
- GLfloat *texel)
+fetch_etc2_signed_r11_eac(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j, GLfloat *texel)
{
struct etc2_block block;
GLushort dst;
}
static void
-fetch_etc2_signed_rg11_eac(const GLubyte *map, const GLuint imageOffsets[],
- GLint rowStride, GLint i, GLint j, GLint k,
- GLfloat *texel)
+fetch_etc2_signed_rg11_eac(const GLubyte *map,
+ GLint rowStride, GLint i, GLint j, GLfloat *texel)
{
struct etc2_block block;
GLushort dst[2];
static void
fetch_etc2_rgb8_punchthrough_alpha1(const GLubyte *map,
- const GLuint imageOffsets[],
- GLint rowStride, GLint i, GLint j, GLint k,
+ GLint rowStride, GLint i, GLint j,
GLfloat *texel)
{
struct etc2_block block;
static void
fetch_etc2_srgb8_punchthrough_alpha1(const GLubyte *map,
- const GLuint imageOffsets[],
GLint rowStride,
- GLint i, GLint j, GLint k,
- GLfloat *texel)
+ GLint i, GLint j, GLfloat *texel)
{
struct etc2_block block;
uint8_t dst[4];
true /* punchthrough alpha */);
etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst,
true /* punchthrough alpha */);
- texel[RCOMP] = _mesa_nonlinear_to_linear(dst[0]);
- texel[GCOMP] = _mesa_nonlinear_to_linear(dst[1]);
- texel[BCOMP] = _mesa_nonlinear_to_linear(dst[2]);
+ texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]);
+ texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]);
+ texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]);
texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]);
}
compressed_fetch_func
-_mesa_get_etc_fetch_func(gl_format format)
+_mesa_get_etc_fetch_func(mesa_format format)
{
switch (format) {
case MESA_FORMAT_ETC1_RGB8: