Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 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 "glheader.h" |
||
19 | #include "compiler.h" /* for ASSERT */ |
||
20 | #include "context.h" |
||
21 | #include "mtypes.h" |
||
22 | #include "imports.h" |
||
23 | #include "pixelstore.h" |
||
24 | #include "teximage.h" |
||
25 | #include "texpal.h" |
||
26 | |||
27 | #if FEATURE_ES |
||
28 | |||
29 | |||
30 | static const struct cpal_format_info { |
||
31 | GLenum cpal_format; |
||
32 | GLenum format; |
||
33 | GLenum type; |
||
34 | GLuint palette_size; |
||
35 | GLuint size; |
||
36 | } formats[] = { |
||
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 } |
||
47 | }; |
||
48 | |||
49 | |||
50 | /** |
||
51 | * Get a color/entry from the palette. |
||
52 | */ |
||
53 | static GLuint |
||
54 | get_palette_entry(const struct cpal_format_info *info, const GLubyte *palette, |
||
55 | GLuint index, GLubyte *pixel) |
||
56 | { |
||
57 | memcpy(pixel, palette + info->size * index, info->size); |
||
58 | return info->size; |
||
59 | } |
||
60 | |||
61 | |||
62 | /** |
||
63 | * Convert paletted texture to color texture. |
||
64 | */ |
||
65 | static void |
||
66 | paletted_to_color(const struct cpal_format_info *info, const GLubyte *palette, |
||
67 | const void *indices, GLuint num_pixels, GLubyte *image) |
||
68 | { |
||
69 | GLubyte *pix = image; |
||
70 | GLuint remain, i; |
||
71 | |||
72 | if (info->palette_size == 16) { |
||
73 | /* 4 bits per index */ |
||
74 | const GLubyte *ind = (const GLubyte *) indices; |
||
75 | |||
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); |
||
81 | } |
||
82 | if (remain) { |
||
83 | get_palette_entry(info, palette, (ind[i] >> 4) & 0xf, pix); |
||
84 | } |
||
85 | } |
||
86 | else { |
||
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); |
||
91 | } |
||
92 | } |
||
93 | |||
94 | |||
95 | static const struct cpal_format_info * |
||
96 | cpal_get_info(GLint level, GLenum internalFormat, |
||
97 | GLsizei width, GLsizei height, GLsizei imageSize) |
||
98 | { |
||
99 | const struct cpal_format_info *info; |
||
100 | GLint lvl, num_levels; |
||
101 | GLsizei w, h, expect_size; |
||
102 | |||
103 | info = &formats[internalFormat - GL_PALETTE4_RGB8_OES]; |
||
104 | ASSERT(info->cpal_format == internalFormat); |
||
105 | |||
106 | if (level > 0) { |
||
107 | _mesa_error(_mesa_get_current_context(), GL_INVALID_VALUE, |
||
108 | "glCompressedTexImage2D(level=%d)", level); |
||
109 | return NULL; |
||
110 | } |
||
111 | |||
112 | num_levels = -level + 1; |
||
113 | expect_size = info->palette_size * info->size; |
||
114 | for (lvl = 0; lvl < num_levels; lvl++) { |
||
115 | w = width >> lvl; |
||
116 | if (!w) |
||
117 | w = 1; |
||
118 | h = height >> lvl; |
||
119 | if (!h) |
||
120 | h = 1; |
||
121 | |||
122 | if (info->palette_size == 16) |
||
123 | expect_size += (w * h + 1) / 2; |
||
124 | else |
||
125 | expect_size += w * h; |
||
126 | } |
||
127 | if (expect_size > imageSize) { |
||
128 | _mesa_error(_mesa_get_current_context(), GL_INVALID_VALUE, |
||
129 | "glCompressedTexImage2D(imageSize=%d)", imageSize); |
||
130 | return NULL; |
||
131 | } |
||
132 | return info; |
||
133 | } |
||
134 | |||
135 | /** |
||
136 | * Convert a call to glCompressedTexImage2D() where internalFormat is a |
||
137 | * compressed palette format into a regular GLubyte/RGBA glTexImage2D() call. |
||
138 | */ |
||
139 | void |
||
140 | _mesa_cpal_compressed_teximage2d(GLenum target, GLint level, |
||
141 | GLenum internalFormat, |
||
142 | GLsizei width, GLsizei height, |
||
143 | GLsizei imageSize, const void *palette) |
||
144 | { |
||
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); |
||
150 | |||
151 | info = cpal_get_info(level, internalFormat, width, height, imageSize); |
||
152 | if (!info) |
||
153 | return; |
||
154 | |||
155 | info = &formats[internalFormat - GL_PALETTE4_RGB8_OES]; |
||
156 | ASSERT(info->cpal_format == internalFormat); |
||
157 | num_levels = -level + 1; |
||
158 | |||
159 | /* first image follows the palette */ |
||
160 | indices = (const GLubyte *) palette + info->palette_size * info->size; |
||
161 | |||
162 | saved_align = ctx->Unpack.Alignment; |
||
163 | align = saved_align; |
||
164 | |||
165 | for (lvl = 0; lvl < num_levels; lvl++) { |
||
166 | GLsizei w, h; |
||
167 | GLuint num_texels; |
||
168 | GLubyte *image = NULL; |
||
169 | |||
170 | w = width >> lvl; |
||
171 | if (!w) |
||
172 | w = 1; |
||
173 | h = height >> lvl; |
||
174 | if (!h) |
||
175 | h = 1; |
||
176 | num_texels = w * h; |
||
177 | if (w * info->size % align) { |
||
178 | _mesa_PixelStorei(GL_UNPACK_ALIGNMENT, 1); |
||
179 | align = 1; |
||
180 | } |
||
181 | |||
182 | /* allocate and fill dest image buffer */ |
||
183 | if (palette) { |
||
184 | image = (GLubyte *) malloc(num_texels * info->size); |
||
185 | paletted_to_color(info, palette, indices, num_texels, image); |
||
186 | } |
||
187 | |||
188 | _mesa_TexImage2D(target, lvl, info->format, w, h, 0, |
||
189 | info->format, info->type, image); |
||
190 | if (image) |
||
191 | free(image); |
||
192 | |||
193 | /* advance index pointer to point to next src mipmap */ |
||
194 | if (info->palette_size == 16) |
||
195 | indices += (num_texels + 1) / 2; |
||
196 | else |
||
197 | indices += num_texels; |
||
198 | } |
||
199 | |||
200 | if (saved_align != align) |
||
201 | _mesa_PixelStorei(GL_UNPACK_ALIGNMENT, saved_align); |
||
202 | } |
||
203 | |||
204 | #endif>>>> |