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
);