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...
25 static const struct cpal_format_info
{
32 { GL_PALETTE4_RGB8_OES
, GL_RGB
, GL_UNSIGNED_BYTE
, 16, 3 },
33 { GL_PALETTE4_RGBA8_OES
, GL_RGBA
, GL_UNSIGNED_BYTE
, 16, 4 },
34 { GL_PALETTE4_R5_G6_B5_OES
, GL_RGB
, GL_UNSIGNED_SHORT_5_6_5
, 16, 2 },
35 { GL_PALETTE4_RGBA4_OES
, GL_RGBA
, GL_UNSIGNED_SHORT_4_4_4_4
, 16, 2 },
36 { GL_PALETTE4_RGB5_A1_OES
, GL_RGBA
, GL_UNSIGNED_SHORT_5_5_5_1
, 16, 2 },
37 { GL_PALETTE8_RGB8_OES
, GL_RGB
, GL_UNSIGNED_BYTE
, 256, 3 },
38 { GL_PALETTE8_RGBA8_OES
, GL_RGBA
, GL_UNSIGNED_BYTE
, 256, 4 },
39 { GL_PALETTE8_R5_G6_B5_OES
, GL_RGB
, GL_UNSIGNED_SHORT_5_6_5
, 256, 2 },
40 { GL_PALETTE8_RGBA4_OES
, GL_RGBA
, GL_UNSIGNED_SHORT_4_4_4_4
, 256, 2 },
41 { GL_PALETTE8_RGB5_A1_OES
, GL_RGBA
, GL_UNSIGNED_SHORT_5_5_5_1
, 256, 2 }
46 * Get a color/entry from the palette.
49 get_palette_entry(const struct cpal_format_info
*info
, const GLubyte
*palette
,
50 GLuint index
, GLubyte
*pixel
)
52 memcpy(pixel
, palette
+ info
->size
* index
, info
->size
);
58 * Convert paletted texture to color texture.
61 paletted_to_color(const struct cpal_format_info
*info
, const GLubyte
*palette
,
62 const void *indices
, GLuint num_pixels
, GLubyte
*image
)
67 if (info
->palette_size
== 16) {
68 /* 4 bits per index */
69 const GLubyte
*ind
= (const GLubyte
*) indices
;
71 /* two pixels per iteration */
72 remain
= num_pixels
% 2;
73 for (i
= 0; i
< num_pixels
/ 2; i
++) {
74 pix
+= get_palette_entry(info
, palette
, (ind
[i
] >> 4) & 0xf, pix
);
75 pix
+= get_palette_entry(info
, palette
, ind
[i
] & 0xf, pix
);
78 get_palette_entry(info
, palette
, (ind
[i
] >> 4) & 0xf, pix
);
82 /* 8 bits per index */
83 const GLubyte
*ind
= (const GLubyte
*) indices
;
84 for (i
= 0; i
< num_pixels
; i
++)
85 pix
+= get_palette_entry(info
, palette
, ind
[i
], pix
);
90 _mesa_cpal_compressed_size(int level
, GLenum internalFormat
,
91 unsigned width
, unsigned height
)
93 const struct cpal_format_info
*info
;
94 const int num_levels
= -level
+ 1;
96 unsigned w
, h
, expect_size
;
98 if (internalFormat
< GL_PALETTE4_RGB8_OES
99 || internalFormat
> GL_PALETTE8_RGB5_A1_OES
) {
103 info
= &formats
[internalFormat
- GL_PALETTE4_RGB8_OES
];
104 ASSERT(info
->cpal_format
== internalFormat
);
106 expect_size
= info
->palette_size
* info
->size
;
107 for (lvl
= 0; lvl
< num_levels
; lvl
++) {
115 if (info
->palette_size
== 16)
116 expect_size
+= (w
* h
+ 1) / 2;
118 expect_size
+= w
* h
;
125 _mesa_cpal_compressed_format_type(GLenum internalFormat
, GLenum
*format
,
128 const struct cpal_format_info
*info
;
130 if (internalFormat
< GL_PALETTE4_RGB8_OES
131 || internalFormat
> GL_PALETTE8_RGB5_A1_OES
) {
135 info
= &formats
[internalFormat
- GL_PALETTE4_RGB8_OES
];
136 *format
= info
->format
;
141 * Convert a call to glCompressedTexImage2D() where internalFormat is a
142 * compressed palette format into a regular GLubyte/RGBA glTexImage2D() call.
145 _mesa_cpal_compressed_teximage2d(GLenum target
, GLint level
,
146 GLenum internalFormat
,
147 GLsizei width
, GLsizei height
,
148 GLsizei imageSize
, const void *palette
)
150 const struct cpal_format_info
*info
;
151 GLint lvl
, num_levels
;
152 const GLubyte
*indices
;
153 GLint saved_align
, align
;
154 GET_CURRENT_CONTEXT(ctx
);
156 /* By this point, the internalFormat should have been validated.
158 assert(internalFormat
>= GL_PALETTE4_RGB8_OES
159 && internalFormat
<= GL_PALETTE8_RGB5_A1_OES
);
161 info
= &formats
[internalFormat
- GL_PALETTE4_RGB8_OES
];
163 num_levels
= -level
+ 1;
165 /* first image follows the palette */
166 indices
= (const GLubyte
*) palette
+ info
->palette_size
* info
->size
;
168 saved_align
= ctx
->Unpack
.Alignment
;
171 for (lvl
= 0; lvl
< num_levels
; lvl
++) {
174 GLubyte
*image
= NULL
;
183 if (w
* info
->size
% align
) {
184 _mesa_PixelStorei(GL_UNPACK_ALIGNMENT
, 1);
188 /* allocate and fill dest image buffer */
190 image
= (GLubyte
*) malloc(num_texels
* info
->size
);
191 paletted_to_color(info
, palette
, indices
, num_texels
, image
);
194 _mesa_TexImage2D(target
, lvl
, info
->format
, w
, h
, 0,
195 info
->format
, info
->type
, image
);
199 /* advance index pointer to point to next src mipmap */
200 if (info
->palette_size
== 16)
201 indices
+= (num_texels
+ 1) / 2;
203 indices
+= num_texels
;
206 if (saved_align
!= align
)
207 _mesa_PixelStorei(GL_UNPACK_ALIGNMENT
, saved_align
);