1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6 **************************************************************************/
10 * Code to convert compressed/paletted texture images to ordinary images.
11 * See the GL_OES_compressed_paletted_texture spec at
12 * http://khronos.org/registry/gles/extensions/OES/OES_compressed_paletted_texture.txt
14 * XXX this makes it impossible to add hardware support...
19 #include "compiler.h" /* for ASSERT */
21 #include "mfeatures.h"
24 #include "pixelstore.h"
31 static const struct cpal_format_info {
38 { GL_PALETTE4_RGB8_OES, GL_RGB, GL_UNSIGNED_BYTE, 16, 3 },
39 { GL_PALETTE4_RGBA8_OES, GL_RGBA, GL_UNSIGNED_BYTE, 16, 4 },
40 { GL_PALETTE4_R5_G6_B5_OES, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 16, 2 },
41 { GL_PALETTE4_RGBA4_OES, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 16, 2 },
42 { GL_PALETTE4_RGB5_A1_OES, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 16, 2 },
43 { GL_PALETTE8_RGB8_OES, GL_RGB, GL_UNSIGNED_BYTE, 256, 3 },
44 { GL_PALETTE8_RGBA8_OES, GL_RGBA, GL_UNSIGNED_BYTE, 256, 4 },
45 { GL_PALETTE8_R5_G6_B5_OES, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 256, 2 },
46 { GL_PALETTE8_RGBA4_OES, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 256, 2 },
47 { GL_PALETTE8_RGB5_A1_OES, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 256, 2 }
52 * Get a color/entry from the palette.
55 get_palette_entry(const struct cpal_format_info *info, const GLubyte *palette,
56 GLuint index, GLubyte *pixel)
58 memcpy(pixel, palette + info->size * index, info->size);
64 * Convert paletted texture to color texture.
67 paletted_to_color(const struct cpal_format_info *info, const GLubyte *palette,
68 const void *indices, GLuint num_pixels, GLubyte *image)
73 if (info->palette_size == 16) {
74 /* 4 bits per index */
75 const GLubyte *ind = (const GLubyte *) indices;
77 /* two pixels per iteration */
78 remain = num_pixels % 2;
79 for (i = 0; i < num_pixels / 2; i++) {
80 pix += get_palette_entry(info, palette, (ind[i] >> 4) & 0xf, pix);
81 pix += get_palette_entry(info, palette, ind[i] & 0xf, pix);
84 get_palette_entry(info, palette, (ind[i] >> 4) & 0xf, pix);
88 /* 8 bits per index */
89 const GLubyte *ind = (const GLubyte *) indices;
90 for (i = 0; i < num_pixels; i++)
91 pix += get_palette_entry(info, palette, ind[i], pix);
96 _mesa_cpal_compressed_size(int level, GLenum internalFormat,
97 unsigned width, unsigned height)
99 const struct cpal_format_info *info;
100 const int num_levels = -level + 1;
102 unsigned w, h, expect_size;
104 if (internalFormat < GL_PALETTE4_RGB8_OES
105 || internalFormat > GL_PALETTE8_RGB5_A1_OES) {
109 info = &formats[internalFormat - GL_PALETTE4_RGB8_OES];
110 ASSERT(info->cpal_format == internalFormat);
112 expect_size = info->palette_size * info->size;
113 for (lvl = 0; lvl < num_levels; lvl++) {
121 if (info->palette_size == 16)
122 expect_size += (w * h + 1) / 2;
124 expect_size += w * h;
131 _mesa_cpal_compressed_format_type(GLenum internalFormat, GLenum *format,
134 const struct cpal_format_info *info;
136 if (internalFormat < GL_PALETTE4_RGB8_OES
137 || internalFormat > GL_PALETTE8_RGB5_A1_OES) {
141 info = &formats[internalFormat - GL_PALETTE4_RGB8_OES];
142 *format = info->format;
147 * Convert a call to glCompressedTexImage2D() where internalFormat is a
148 * compressed palette format into a regular GLubyte/RGBA glTexImage2D() call.
151 _mesa_cpal_compressed_teximage2d(GLenum target, GLint level,
152 GLenum internalFormat,
153 GLsizei width, GLsizei height,
154 GLsizei imageSize, const void *palette)
156 const struct cpal_format_info *info;
157 GLint lvl, num_levels;
158 const GLubyte *indices;
159 GLint saved_align, align;
160 GET_CURRENT_CONTEXT(ctx);
162 /* By this point, the internalFormat should have been validated.
164 assert(internalFormat >= GL_PALETTE4_RGB8_OES
165 && internalFormat <= GL_PALETTE8_RGB5_A1_OES);
167 info = &formats[internalFormat - GL_PALETTE4_RGB8_OES];
169 num_levels = -level + 1;
171 /* first image follows the palette */
172 indices = (const GLubyte *) palette + info->palette_size * info->size;
174 saved_align = ctx->Unpack.Alignment;
177 for (lvl = 0; lvl < num_levels; lvl++) {
180 GLubyte *image = NULL;
189 if (w * info->size % align) {
190 _mesa_PixelStorei(GL_UNPACK_ALIGNMENT, 1);
194 /* allocate and fill dest image buffer */
196 image = (GLubyte *) malloc(num_texels * info->size);
197 paletted_to_color(info, palette, indices, num_texels, image);
200 _mesa_TexImage2D(target, lvl, info->format, w, h, 0,
201 info->format, info->type, image);
205 /* advance index pointer to point to next src mipmap */
206 if (info->palette_size == 16)
207 indices += (num_texels + 1) / 2;
209 indices += num_texels;
212 if (saved_align != align)
213 _mesa_PixelStorei(GL_UNPACK_ALIGNMENT, saved_align);