summaryrefslogtreecommitdiff
path: root/src/mesa/es/main/es_cpaltex.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/es/main/es_cpaltex.c')
-rw-r--r--src/mesa/es/main/es_cpaltex.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/src/mesa/es/main/es_cpaltex.c b/src/mesa/es/main/es_cpaltex.c
new file mode 100644
index 0000000000..0d6f7410c3
--- /dev/null
+++ b/src/mesa/es/main/es_cpaltex.c
@@ -0,0 +1,240 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+
+/**
+ * Code to convert compressed/paletted texture images to ordinary 4-byte RGBA.
+ * See the GL_OES_compressed_paletted_texture spec at
+ * http://khronos.org/registry/gles/extensions/OES/OES_compressed_paletted_texture.txt
+ */
+
+
+#include <stdlib.h>
+#include <assert.h>
+#include "GLES/gl.h"
+#include "GLES/glext.h"
+
+
+void GL_APIENTRY _es_CompressedTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+
+void GL_APIENTRY _mesa_TexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+void GL_APIENTRY _mesa_CompressedTexImage2DARB(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+
+
+static const struct {
+ GLenum format;
+ GLuint palette_size;
+ GLuint size;
+} formats[] = {
+ { GL_PALETTE4_RGB8_OES, 16, 3 },
+ { GL_PALETTE4_RGBA8_OES, 16, 4 },
+ { GL_PALETTE4_R5_G6_B5_OES, 16, 2 },
+ { GL_PALETTE4_RGBA4_OES, 16, 2 },
+ { GL_PALETTE4_RGB5_A1_OES, 16, 2 },
+ { GL_PALETTE8_RGB8_OES, 256, 3 },
+ { GL_PALETTE8_RGBA8_OES, 256, 4 },
+ { GL_PALETTE8_R5_G6_B5_OES, 256, 2 },
+ { GL_PALETTE8_RGBA4_OES, 256, 2 },
+ { GL_PALETTE8_RGB5_A1_OES, 256, 2 }
+};
+
+
+/**
+ * Get a color/entry from the palette. Convert to GLubyte/RGBA format.
+ */
+static void
+get_palette_entry(GLenum format, const void *palette, GLuint index,
+ GLubyte rgba[4])
+{
+ switch (format) {
+ case GL_PALETTE4_RGB8_OES:
+ case GL_PALETTE8_RGB8_OES:
+ {
+ const GLubyte *pal = (const GLubyte *) palette;
+ rgba[0] = pal[index * 3 + 0];
+ rgba[1] = pal[index * 3 + 1];
+ rgba[2] = pal[index * 3 + 2];
+ rgba[3] = 255;
+ }
+ break;
+ case GL_PALETTE4_RGBA8_OES:
+ case GL_PALETTE8_RGBA8_OES:
+ {
+ const GLubyte *pal = (const GLubyte *) palette;
+ rgba[0] = pal[index * 4 + 0];
+ rgba[1] = pal[index * 4 + 1];
+ rgba[2] = pal[index * 4 + 2];
+ rgba[3] = pal[index * 4 + 3];
+ }
+ break;
+ case GL_PALETTE4_R5_G6_B5_OES:
+ case GL_PALETTE8_R5_G6_B5_OES:
+ {
+ const GLushort *pal = (const GLushort *) palette;
+ const GLushort color = pal[index];
+ rgba[0] = ((color >> 8) & 0xf8) | ((color >> 11) & 0x3);
+ rgba[1] = ((color >> 3) & 0xfc) | ((color >> 1 ) & 0x3);
+ rgba[2] = ((color << 3) & 0xf8) | ((color ) & 0x7);
+ rgba[3] = 255;
+ }
+ break;
+ case GL_PALETTE4_RGBA4_OES:
+ case GL_PALETTE8_RGBA4_OES:
+ {
+ const GLushort *pal = (const GLushort *) palette;
+ const GLushort color = pal[index];
+ rgba[0] = ((color & 0xf000) >> 8) | ((color & 0xf000) >> 12);
+ rgba[1] = ((color & 0x0f00) >> 4) | ((color & 0x0f00) >> 8);
+ rgba[2] = ((color & 0x00f0) ) | ((color & 0x00f0) >> 4);
+ rgba[3] = ((color & 0x000f) << 4) | ((color & 0x000f) );
+ }
+ break;
+ case GL_PALETTE4_RGB5_A1_OES:
+ case GL_PALETTE8_RGB5_A1_OES:
+ {
+ const GLushort *pal = (const GLushort *) palette;
+ const GLushort color = pal[index];
+ rgba[0] = ((color >> 8) & 0xf8) | ((color >> 11) & 0x7);
+ rgba[1] = ((color >> 3) & 0xf8) | ((color >> 6) & 0x7);
+ rgba[2] = ((color << 2) & 0xf8) | ((color >> 1) & 0x7);
+ rgba[3] = (color & 0x1) * 255;
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * Convert paletted texture to simple GLubyte/RGBA format.
+ */
+static void
+paletted_to_rgba(GLenum src_format,
+ const void *palette,
+ const void *indexes,
+ GLsizei width, GLsizei height,
+ GLubyte *rgba)
+{
+ GLuint pal_ents, i;
+
+ assert(src_format >= GL_PALETTE4_RGB8_OES);
+ assert(src_format <= GL_PALETTE8_RGB5_A1_OES);
+ assert(formats[src_format - GL_PALETTE4_RGB8_OES].format == src_format);
+
+ pal_ents = formats[src_format - GL_PALETTE4_RGB8_OES].palette_size;
+
+ if (pal_ents == 16) {
+ /* 4 bits per index */
+ const GLubyte *ind = (const GLubyte *) indexes;
+
+ if (width * height == 1) {
+ /* special case the only odd-sized image */
+ GLuint index0 = ind[0] >> 4;
+ get_palette_entry(src_format, palette, index0, rgba);
+ return;
+ }
+ /* two pixels per iteration */
+ for (i = 0; i < width * height / 2; i++) {
+ GLuint index0 = ind[i] >> 4;
+ GLuint index1 = ind[i] & 0xf;
+ get_palette_entry(src_format, palette, index0, rgba + i * 8);
+ get_palette_entry(src_format, palette, index1, rgba + i * 8 + 4);
+ }
+ }
+ else {
+ /* 8 bits per index */
+ const GLubyte *ind = (const GLubyte *) indexes;
+ for (i = 0; i < width * height; i++) {
+ GLuint index = ind[i];
+ get_palette_entry(src_format, palette, index, rgba + i * 4);
+ }
+ }
+}
+
+
+/**
+ * Convert a call to glCompressedTexImage2D() where internalFormat is a
+ * compressed palette format into a regular GLubyte/RGBA glTexImage2D() call.
+ */
+static void
+cpal_compressed_teximage2d(GLenum target, GLint level,
+ GLenum internalFormat,
+ GLsizei width, GLsizei height,
+ const void *pixels)
+{
+ GLuint pal_ents, pal_ent_size, pal_bytes;
+ const GLint num_levels = level + 1;
+ GLint lvl;
+ const GLubyte *indexes;
+
+ assert(internalFormat >= GL_PALETTE4_RGB8_OES);
+ assert(internalFormat <= GL_PALETTE8_RGB5_A1_OES);
+ assert(formats[internalFormat - GL_PALETTE4_RGB8_OES].format == internalFormat);
+
+ pal_ents = formats[internalFormat - GL_PALETTE4_RGB8_OES].palette_size;
+ pal_ent_size = formats[internalFormat - GL_PALETTE4_RGB8_OES].size;
+ pal_bytes = pal_ents * pal_ent_size;
+
+ /* first image follows the palette */
+ indexes = (const GLubyte *) pixels + pal_bytes;
+
+ /* No worries about glPixelStore state since the only supported parameter is
+ * GL_UNPACK_ALIGNMENT and it doesn't matter when unpacking GLubyte/RGBA.
+ */
+
+ for (lvl = 0; lvl < num_levels; lvl++) {
+ /* Allocate GLubyte/RGBA dest image buffer */
+ GLubyte *rgba = (GLubyte *) malloc(width * height * 4);
+
+ if (pixels)
+ paletted_to_rgba(internalFormat, pixels, indexes, width, height, rgba);
+
+ _mesa_TexImage2D(target, lvl, GL_RGBA, width, height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, rgba);
+
+ free(rgba);
+
+ /* advance index pointer to point to next src mipmap */
+ if (pal_ents == 4)
+ indexes += width * height / 2;
+ else
+ indexes += width * height;
+
+ /* next mipmap level size */
+ if (width > 1)
+ width /= 2;
+ if (height > 1)
+ height /= 2;
+ }
+}
+
+
+void GL_APIENTRY
+_es_CompressedTexImage2D(GLenum target, GLint level, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLint border,
+ GLsizei imageSize, const GLvoid *data)
+{
+ switch (internalFormat) {
+ case GL_PALETTE4_RGB8_OES:
+ case GL_PALETTE4_RGBA8_OES:
+ case GL_PALETTE4_R5_G6_B5_OES:
+ case GL_PALETTE4_RGBA4_OES:
+ case GL_PALETTE4_RGB5_A1_OES:
+ case GL_PALETTE8_RGB8_OES:
+ case GL_PALETTE8_RGBA8_OES:
+ case GL_PALETTE8_R5_G6_B5_OES:
+ case GL_PALETTE8_RGBA4_OES:
+ case GL_PALETTE8_RGB5_A1_OES:
+ cpal_compressed_teximage2d(target, level, internalFormat,
+ width, height, data);
+ break;
+ default:
+ _mesa_CompressedTexImage2DARB(target, level, internalFormat,
+ width, height, border, imageSize, data);
+ }
+}