colortab.c revision 845117bd054862baae29c4df61d5b4a61dd97f62
1/* $Id: colortab.c,v 1.5 1999/11/11 17:50:04 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.3
6 *
7 * Copyright (C) 1999  Brian Paul   All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28#ifdef PC_HEADER
29#include "all.h"
30#else
31#include "glheader.h"
32#include "colortab.h"
33#include "context.h"
34#include "image.h"
35#include "macros.h"
36#endif
37
38
39
40/*
41 * Return GL_TRUE if k is a power of two, else return GL_FALSE.
42 */
43static GLboolean
44power_of_two( GLint k )
45{
46   GLint i, m = 1;
47   for (i=0; i<32; i++) {
48      if (k == m)
49         return GL_TRUE;
50      m = m << 1;
51   }
52   return GL_FALSE;
53}
54
55
56static GLint
57decode_internal_format( GLint format )
58{
59   switch (format) {
60      case GL_ALPHA:
61      case GL_ALPHA4:
62      case GL_ALPHA8:
63      case GL_ALPHA12:
64      case GL_ALPHA16:
65         return GL_ALPHA;
66      case 1:
67      case GL_LUMINANCE:
68      case GL_LUMINANCE4:
69      case GL_LUMINANCE8:
70      case GL_LUMINANCE12:
71      case GL_LUMINANCE16:
72         return GL_LUMINANCE;
73      case 2:
74      case GL_LUMINANCE_ALPHA:
75      case GL_LUMINANCE4_ALPHA4:
76      case GL_LUMINANCE6_ALPHA2:
77      case GL_LUMINANCE8_ALPHA8:
78      case GL_LUMINANCE12_ALPHA4:
79      case GL_LUMINANCE12_ALPHA12:
80      case GL_LUMINANCE16_ALPHA16:
81         return GL_LUMINANCE_ALPHA;
82      case GL_INTENSITY:
83      case GL_INTENSITY4:
84      case GL_INTENSITY8:
85      case GL_INTENSITY12:
86      case GL_INTENSITY16:
87         return GL_INTENSITY;
88      case 3:
89      case GL_RGB:
90      case GL_R3_G3_B2:
91      case GL_RGB4:
92      case GL_RGB5:
93      case GL_RGB8:
94      case GL_RGB10:
95      case GL_RGB12:
96      case GL_RGB16:
97         return GL_RGB;
98      case 4:
99      case GL_RGBA:
100      case GL_RGBA2:
101      case GL_RGBA4:
102      case GL_RGB5_A1:
103      case GL_RGBA8:
104      case GL_RGB10_A2:
105      case GL_RGBA12:
106      case GL_RGBA16:
107         return GL_RGBA;
108      default:
109         return -1;  /* error */
110   }
111}
112
113
114void
115_mesa_ColorTableEXT( GLenum target, GLenum internalFormat,
116                     GLsizei width, GLenum format, GLenum type,
117                     const GLvoid *table )
118{
119   GET_CURRENT_CONTEXT(ctx);
120   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
121   struct gl_texture_object *texObj;
122   struct gl_palette *palette;
123   GLboolean proxy = GL_FALSE;
124
125   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glColorTableEXT");
126
127   switch (target) {
128      case GL_TEXTURE_1D:
129         texObj = texUnit->CurrentD[1];
130         palette = &texObj->Palette;
131         break;
132      case GL_TEXTURE_2D:
133         texObj = texUnit->CurrentD[2];
134         palette = &texObj->Palette;
135         break;
136      case GL_TEXTURE_3D:
137         texObj = texUnit->CurrentD[3];
138         palette = &texObj->Palette;
139         break;
140      case GL_PROXY_TEXTURE_1D:
141         texObj = ctx->Texture.Proxy1D;
142         palette = &texObj->Palette;
143         proxy = GL_TRUE;
144         break;
145      case GL_PROXY_TEXTURE_2D:
146         texObj = ctx->Texture.Proxy2D;
147         palette = &texObj->Palette;
148         proxy = GL_TRUE;
149         break;
150      case GL_PROXY_TEXTURE_3D:
151         texObj = ctx->Texture.Proxy3D;
152         palette = &texObj->Palette;
153         proxy = GL_TRUE;
154         break;
155      case GL_SHARED_TEXTURE_PALETTE_EXT:
156         texObj = NULL;
157         palette = &ctx->Texture.Palette;
158         break;
159      default:
160         gl_error(ctx, GL_INVALID_ENUM, "glColorTableEXT(target)");
161         return;
162   }
163
164   assert(palette);
165
166   if (!gl_is_legal_format_and_type(format, type)) {
167      gl_error(ctx, GL_INVALID_ENUM, "glColorTableEXT(format or type)");
168      return;
169   }
170
171   if (decode_internal_format(internalFormat) < 0) {
172      gl_error( ctx, GL_INVALID_ENUM, "glColorTableEXT(internalFormat)" );
173      return;
174   }
175
176   if (width < 1 || width > MAX_TEXTURE_PALETTE_SIZE || !power_of_two(width)) {
177      gl_error(ctx, GL_INVALID_VALUE, "glColorTableEXT(width)");
178      if (proxy) {
179         palette->Size = 0;
180         palette->IntFormat = (GLenum) 0;
181         palette->Format = (GLenum) 0;
182      }
183      return;
184   }
185
186   palette->Size = width;
187   palette->IntFormat = internalFormat;
188   palette->Format = (GLenum) decode_internal_format(internalFormat);
189   if (!proxy) {
190      _mesa_unpack_ubyte_color_span(ctx, width, palette->Format,
191                                    palette->Table,  /* dest */
192                                    format, type, table,
193                                    &ctx->Unpack, GL_FALSE);
194   }
195   if (texObj) {
196      /* per-texture object palette */
197      if (ctx->Driver.UpdateTexturePalette) {
198         (*ctx->Driver.UpdateTexturePalette)( ctx, texObj );
199      }
200   }
201   else {
202      /* shared texture palette */
203      if (ctx->Driver.UpdateTexturePalette) {
204         (*ctx->Driver.UpdateTexturePalette)( ctx, NULL );
205      }
206   }
207}
208
209
210
211void
212_mesa_ColorSubTableEXT( GLenum target, GLsizei start,
213                        GLsizei count, GLenum format, GLenum type,
214                        const GLvoid *table )
215{
216   GET_CURRENT_CONTEXT(ctx);
217   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
218   struct gl_texture_object *texObj;
219   struct gl_palette *palette;
220   GLint comps;
221   GLubyte *dest;
222
223   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glColorSubTable");
224
225   switch (target) {
226      case GL_TEXTURE_1D:
227         texObj = texUnit->CurrentD[1];
228         palette = &texObj->Palette;
229         break;
230      case GL_TEXTURE_2D:
231         texObj = texUnit->CurrentD[2];
232         palette = &texObj->Palette;
233         break;
234      case GL_TEXTURE_3D:
235         texObj = texUnit->CurrentD[3];
236         palette = &texObj->Palette;
237         break;
238      case GL_SHARED_TEXTURE_PALETTE_EXT:
239         texObj = NULL;
240         palette = &ctx->Texture.Palette;
241         break;
242      default:
243         gl_error(ctx, GL_INVALID_ENUM, "glColorSubTableEXT(target)");
244         return;
245   }
246
247   assert(palette);
248
249   if (!gl_is_legal_format_and_type(format, type)) {
250      gl_error(ctx, GL_INVALID_ENUM, "glColorSubTableEXT(format or type)");
251      return;
252   }
253
254   if (count < 1) {
255      gl_error(ctx, GL_INVALID_VALUE, "glColorSubTableEXT(count)");
256      return;
257   }
258
259   comps = gl_components_in_format(format);
260   assert(comps > 0);  /* error should be caught sooner */
261
262   if (start + count > palette->Size) {
263      gl_error(ctx, GL_INVALID_VALUE, "glColorSubTableEXT(count)");
264      return;
265   }
266   dest = palette->Table + start * comps * sizeof(GLubyte);
267   _mesa_unpack_ubyte_color_span(ctx, count, palette->Format, dest,
268                                 format, type, table,
269                                 &ctx->Unpack, GL_FALSE);
270
271   if (texObj) {
272      /* per-texture object palette */
273      if (ctx->Driver.UpdateTexturePalette) {
274         (*ctx->Driver.UpdateTexturePalette)( ctx, texObj );
275      }
276   }
277   else {
278      /* shared texture palette */
279      if (ctx->Driver.UpdateTexturePalette) {
280         (*ctx->Driver.UpdateTexturePalette)( ctx, NULL );
281      }
282   }
283}
284
285
286
287void
288_mesa_GetColorTableEXT( GLenum target, GLenum format,
289                        GLenum type, GLvoid *table )
290{
291   GET_CURRENT_CONTEXT(ctx);
292   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
293   struct gl_palette *palette;
294   GLubyte rgba[MAX_TEXTURE_PALETTE_SIZE][4];
295   GLint i;
296
297   ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetColorTableEXT");
298
299   switch (target) {
300      case GL_TEXTURE_1D:
301         palette = &texUnit->CurrentD[1]->Palette;
302         break;
303      case GL_TEXTURE_2D:
304         palette = &texUnit->CurrentD[2]->Palette;
305         break;
306      case GL_TEXTURE_3D:
307         palette = &texUnit->CurrentD[3]->Palette;
308         break;
309      case GL_SHARED_TEXTURE_PALETTE_EXT:
310         palette = &ctx->Texture.Palette;
311         break;
312      default:
313         gl_error(ctx, GL_INVALID_ENUM, "glGetColorTableEXT(target)");
314         return;
315   }
316
317   assert(palette);
318
319   switch (palette->Format) {
320      case GL_ALPHA:
321         for (i = 0; i < palette->Size; i++) {
322            rgba[i][RCOMP] = 0;
323            rgba[i][GCOMP] = 0;
324            rgba[i][BCOMP] = 0;
325            rgba[i][ACOMP] = palette->Table[i];
326         }
327         break;
328      case GL_LUMINANCE:
329         for (i = 0; i < palette->Size; i++) {
330            rgba[i][RCOMP] = palette->Table[i];
331            rgba[i][GCOMP] = palette->Table[i];
332            rgba[i][BCOMP] = palette->Table[i];
333            rgba[i][ACOMP] = 255;
334         }
335         break;
336      case GL_LUMINANCE_ALPHA:
337         for (i = 0; i < palette->Size; i++) {
338            rgba[i][RCOMP] = palette->Table[i*2+0];
339            rgba[i][GCOMP] = palette->Table[i*2+0];
340            rgba[i][BCOMP] = palette->Table[i*2+0];
341            rgba[i][ACOMP] = palette->Table[i*2+1];
342         }
343         break;
344      case GL_INTENSITY:
345         for (i = 0; i < palette->Size; i++) {
346            rgba[i][RCOMP] = palette->Table[i];
347            rgba[i][GCOMP] = palette->Table[i];
348            rgba[i][BCOMP] = palette->Table[i];
349            rgba[i][ACOMP] = 255;
350         }
351         break;
352      case GL_RGB:
353         for (i = 0; i < palette->Size; i++) {
354            rgba[i][RCOMP] = palette->Table[i*3+0];
355            rgba[i][GCOMP] = palette->Table[i*3+1];
356            rgba[i][BCOMP] = palette->Table[i*3+2];
357            rgba[i][ACOMP] = 255;
358         }
359         break;
360      case GL_RGBA:
361         for (i = 0; i < palette->Size; i++) {
362            rgba[i][RCOMP] = palette->Table[i*4+0];
363            rgba[i][GCOMP] = palette->Table[i*4+1];
364            rgba[i][BCOMP] = palette->Table[i*4+2];
365            rgba[i][ACOMP] = palette->Table[i*4+3];
366         }
367         break;
368      default:
369         gl_problem(ctx, "bad palette format in glGetColorTableEXT");
370         return;
371   }
372
373   gl_pack_rgba_span(ctx, palette->Size, (const GLubyte (*)[]) rgba,
374                     format, type, table, &ctx->Pack, GL_FALSE);
375
376   (void) format;
377   (void) type;
378   (void) table;
379}
380
381
382
383void
384_mesa_GetColorTableParameterfvEXT( GLenum target, GLenum pname, GLfloat *params )
385{
386   GLint iparams[10];
387   _mesa_GetColorTableParameterivEXT( target, pname, iparams );
388   *params = (GLfloat) iparams[0];
389}
390
391
392
393void
394_mesa_GetColorTableParameterivEXT( GLenum target, GLenum pname, GLint *params )
395{
396   GET_CURRENT_CONTEXT(ctx);
397   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
398   struct gl_palette *palette;
399
400   ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetColorTableParameterEXT");
401
402   switch (target) {
403      case GL_TEXTURE_1D:
404         palette = &texUnit->CurrentD[1]->Palette;
405         break;
406      case GL_TEXTURE_2D:
407         palette = &texUnit->CurrentD[2]->Palette;
408         break;
409      case GL_TEXTURE_3D:
410         palette = &texUnit->CurrentD[3]->Palette;
411         break;
412      case GL_SHARED_TEXTURE_PALETTE_EXT:
413         palette = &ctx->Texture.Palette;
414         break;
415      default:
416         gl_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameterEXT(target)");
417         return;
418   }
419
420   switch (pname) {
421      case GL_COLOR_TABLE_FORMAT:
422         *params = palette->IntFormat;
423         break;
424      case GL_COLOR_TABLE_WIDTH:
425         *params = palette->Size;
426         break;
427      case GL_COLOR_TABLE_RED_SIZE:
428         *params = 8;
429         break;
430      case GL_COLOR_TABLE_GREEN_SIZE:
431         *params = 8;
432         break;
433      case GL_COLOR_TABLE_BLUE_SIZE:
434         *params = 8;
435         break;
436      case GL_COLOR_TABLE_ALPHA_SIZE:
437         *params = 8;
438         break;
439      case GL_COLOR_TABLE_LUMINANCE_SIZE:
440         *params = 8;
441         break;
442      case GL_COLOR_TABLE_INTENSITY_SIZE:
443         *params = 8;
444         break;
445      default:
446         gl_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameterEXT" );
447         return;
448   }
449}
450
451
452