Fixed typo
[reactos.git] / dll / opengl / mesa / main / texpal.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 **************************************************************************/
7
8
9 /**
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
13 *
14 * XXX this makes it impossible to add hardware support...
15 */
16
17
18 #include <precomp.h>
19
20 #include "texpal.h"
21
22 #if FEATURE_ES
23
24
25 static const struct cpal_format_info {
26 GLenum cpal_format;
27 GLenum format;
28 GLenum type;
29 GLuint palette_size;
30 GLuint size;
31 } formats[] = {
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 }
42 };
43
44
45 /**
46 * Get a color/entry from the palette.
47 */
48 static GLuint
49 get_palette_entry(const struct cpal_format_info *info, const GLubyte *palette,
50 GLuint index, GLubyte *pixel)
51 {
52 memcpy(pixel, palette + info->size * index, info->size);
53 return info->size;
54 }
55
56
57 /**
58 * Convert paletted texture to color texture.
59 */
60 static void
61 paletted_to_color(const struct cpal_format_info *info, const GLubyte *palette,
62 const void *indices, GLuint num_pixels, GLubyte *image)
63 {
64 GLubyte *pix = image;
65 GLuint remain, i;
66
67 if (info->palette_size == 16) {
68 /* 4 bits per index */
69 const GLubyte *ind = (const GLubyte *) indices;
70
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);
76 }
77 if (remain) {
78 get_palette_entry(info, palette, (ind[i] >> 4) & 0xf, pix);
79 }
80 }
81 else {
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);
86 }
87 }
88
89 unsigned
90 _mesa_cpal_compressed_size(int level, GLenum internalFormat,
91 unsigned width, unsigned height)
92 {
93 const struct cpal_format_info *info;
94 const int num_levels = -level + 1;
95 int lvl;
96 unsigned w, h, expect_size;
97
98 if (internalFormat < GL_PALETTE4_RGB8_OES
99 || internalFormat > GL_PALETTE8_RGB5_A1_OES) {
100 return 0;
101 }
102
103 info = &formats[internalFormat - GL_PALETTE4_RGB8_OES];
104 ASSERT(info->cpal_format == internalFormat);
105
106 expect_size = info->palette_size * info->size;
107 for (lvl = 0; lvl < num_levels; lvl++) {
108 w = width >> lvl;
109 if (!w)
110 w = 1;
111 h = height >> lvl;
112 if (!h)
113 h = 1;
114
115 if (info->palette_size == 16)
116 expect_size += (w * h + 1) / 2;
117 else
118 expect_size += w * h;
119 }
120
121 return expect_size;
122 }
123
124 void
125 _mesa_cpal_compressed_format_type(GLenum internalFormat, GLenum *format,
126 GLenum *type)
127 {
128 const struct cpal_format_info *info;
129
130 if (internalFormat < GL_PALETTE4_RGB8_OES
131 || internalFormat > GL_PALETTE8_RGB5_A1_OES) {
132 return;
133 }
134
135 info = &formats[internalFormat - GL_PALETTE4_RGB8_OES];
136 *format = info->format;
137 *type = info->type;
138 }
139
140 /**
141 * Convert a call to glCompressedTexImage2D() where internalFormat is a
142 * compressed palette format into a regular GLubyte/RGBA glTexImage2D() call.
143 */
144 void
145 _mesa_cpal_compressed_teximage2d(GLenum target, GLint level,
146 GLenum internalFormat,
147 GLsizei width, GLsizei height,
148 GLsizei imageSize, const void *palette)
149 {
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);
155
156 /* By this point, the internalFormat should have been validated.
157 */
158 assert(internalFormat >= GL_PALETTE4_RGB8_OES
159 && internalFormat <= GL_PALETTE8_RGB5_A1_OES);
160
161 info = &formats[internalFormat - GL_PALETTE4_RGB8_OES];
162
163 num_levels = -level + 1;
164
165 /* first image follows the palette */
166 indices = (const GLubyte *) palette + info->palette_size * info->size;
167
168 saved_align = ctx->Unpack.Alignment;
169 align = saved_align;
170
171 for (lvl = 0; lvl < num_levels; lvl++) {
172 GLsizei w, h;
173 GLuint num_texels;
174 GLubyte *image = NULL;
175
176 w = width >> lvl;
177 if (!w)
178 w = 1;
179 h = height >> lvl;
180 if (!h)
181 h = 1;
182 num_texels = w * h;
183 if (w * info->size % align) {
184 _mesa_PixelStorei(GL_UNPACK_ALIGNMENT, 1);
185 align = 1;
186 }
187
188 /* allocate and fill dest image buffer */
189 if (palette) {
190 image = (GLubyte *) malloc(num_texels * info->size);
191 paletted_to_color(info, palette, indices, num_texels, image);
192 }
193
194 _mesa_TexImage2D(target, lvl, info->format, w, h, 0,
195 info->format, info->type, image);
196 if (image)
197 free(image);
198
199 /* advance index pointer to point to next src mipmap */
200 if (info->palette_size == 16)
201 indices += (num_texels + 1) / 2;
202 else
203 indices += num_texels;
204 }
205
206 if (saved_align != align)
207 _mesa_PixelStorei(GL_UNPACK_ALIGNMENT, saved_align);
208 }
209
210 #endif