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 */
23 #include "pixelstore.h"
30 static const struct cpal_format_info
{
37 { GL_PALETTE4_RGB8_OES
, GL_RGB
, GL_UNSIGNED_BYTE
, 16, 3 },
38 { GL_PALETTE4_RGBA8_OES
, GL_RGBA
, GL_UNSIGNED_BYTE
, 16, 4 },
39 { GL_PALETTE4_R5_G6_B5_OES
, GL_RGB
, GL_UNSIGNED_SHORT_5_6_5
, 16, 2 },
40 { GL_PALETTE4_RGBA4_OES
, GL_RGBA
, GL_UNSIGNED_SHORT_4_4_4_4
, 16, 2 },
41 { GL_PALETTE4_RGB5_A1_OES
, GL_RGBA
, GL_UNSIGNED_SHORT_5_5_5_1
, 16, 2 },
42 { GL_PALETTE8_RGB8_OES
, GL_RGB
, GL_UNSIGNED_BYTE
, 256, 3 },
43 { GL_PALETTE8_RGBA8_OES
, GL_RGBA
, GL_UNSIGNED_BYTE
, 256, 4 },
44 { GL_PALETTE8_R5_G6_B5_OES
, GL_RGB
, GL_UNSIGNED_SHORT_5_6_5
, 256, 2 },
45 { GL_PALETTE8_RGBA4_OES
, GL_RGBA
, GL_UNSIGNED_SHORT_4_4_4_4
, 256, 2 },
46 { GL_PALETTE8_RGB5_A1_OES
, GL_RGBA
, GL_UNSIGNED_SHORT_5_5_5_1
, 256, 2 }
51 * Get a color/entry from the palette.
54 get_palette_entry(const struct cpal_format_info
*info
, const GLubyte
*palette
,
55 GLuint index
, GLubyte
*pixel
)
57 memcpy(pixel
, palette
+ info
->size
* index
, info
->size
);
63 * Convert paletted texture to color texture.
66 paletted_to_color(const struct cpal_format_info
*info
, const GLubyte
*palette
,
67 const void *indices
, GLuint num_pixels
, GLubyte
*image
)
72 if (info
->palette_size
== 16) {
73 /* 4 bits per index */
74 const GLubyte
*ind
= (const GLubyte
*) indices
;
76 /* two pixels per iteration */
77 remain
= num_pixels
% 2;
78 for (i
= 0; i
< num_pixels
/ 2; i
++) {
79 pix
+= get_palette_entry(info
, palette
, (ind
[i
] >> 4) & 0xf, pix
);
80 pix
+= get_palette_entry(info
, palette
, ind
[i
] & 0xf, pix
);
83 get_palette_entry(info
, palette
, (ind
[i
] >> 4) & 0xf, pix
);
87 /* 8 bits per index */
88 const GLubyte
*ind
= (const GLubyte
*) indices
;
89 for (i
= 0; i
< num_pixels
; i
++)
90 pix
+= get_palette_entry(info
, palette
, ind
[i
], pix
);
95 static const struct cpal_format_info
*
96 cpal_get_info(GLint level
, GLenum internalFormat
,
97 GLsizei width
, GLsizei height
, GLsizei imageSize
)
99 const struct cpal_format_info
*info
;
100 GLint lvl
, num_levels
;
101 GLsizei w
, h
, expect_size
;
103 info
= &formats
[internalFormat
- GL_PALETTE4_RGB8_OES
];
104 ASSERT(info
->cpal_format
== internalFormat
);
107 _mesa_error(_mesa_get_current_context(), GL_INVALID_VALUE
,
108 "glCompressedTexImage2D(level=%d)", level
);
112 num_levels
= -level
+ 1;
113 expect_size
= info
->palette_size
* info
->size
;
114 for (lvl
= 0; lvl
< num_levels
; lvl
++) {
122 if (info
->palette_size
== 16)
123 expect_size
+= (w
* h
+ 1) / 2;
125 expect_size
+= w
* h
;
127 if (expect_size
> imageSize
) {
128 _mesa_error(_mesa_get_current_context(), GL_INVALID_VALUE
,
129 "glCompressedTexImage2D(imageSize=%d)", imageSize
);
136 * Convert a call to glCompressedTexImage2D() where internalFormat is a
137 * compressed palette format into a regular GLubyte/RGBA glTexImage2D() call.
140 _mesa_cpal_compressed_teximage2d(GLenum target
, GLint level
,
141 GLenum internalFormat
,
142 GLsizei width
, GLsizei height
,
143 GLsizei imageSize
, const void *palette
)
145 const struct cpal_format_info
*info
;
146 GLint lvl
, num_levels
;
147 const GLubyte
*indices
;
148 GLint saved_align
, align
;
149 GET_CURRENT_CONTEXT(ctx
);
151 info
= cpal_get_info(level
, internalFormat
, width
, height
, imageSize
);
155 info
= &formats
[internalFormat
- GL_PALETTE4_RGB8_OES
];
156 ASSERT(info
->cpal_format
== internalFormat
);
157 num_levels
= -level
+ 1;
159 /* first image follows the palette */
160 indices
= (const GLubyte
*) palette
+ info
->palette_size
* info
->size
;
162 saved_align
= ctx
->Unpack
.Alignment
;
165 for (lvl
= 0; lvl
< num_levels
; lvl
++) {
168 GLubyte
*image
= NULL
;
177 if (w
* info
->size
% align
) {
178 _mesa_PixelStorei(GL_UNPACK_ALIGNMENT
, 1);
182 /* allocate and fill dest image buffer */
184 image
= (GLubyte
*) malloc(num_texels
* info
->size
);
185 paletted_to_color(info
, palette
, indices
, num_texels
, image
);
188 _mesa_TexImage2D(target
, lvl
, info
->format
, w
, h
, 0,
189 info
->format
, info
->type
, image
);
193 /* advance index pointer to point to next src mipmap */
194 if (info
->palette_size
== 16)
195 indices
+= (num_texels
+ 1) / 2;
197 indices
+= num_texels
;
200 if (saved_align
!= align
)
201 _mesa_PixelStorei(GL_UNPACK_ALIGNMENT
, saved_align
);