colortab.c revision c7ac486261ad30ef654f6d0b1608da4e8483cd40
1/*
2 * Mesa 3-D graphics library
3 * Version:  7.1
4 *
5 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26#include "glheader.h"
27#include "bufferobj.h"
28#include "colortab.h"
29#include "context.h"
30#include "image.h"
31#include "macros.h"
32#include "state.h"
33#include "teximage.h"
34#include "texstate.h"
35#include "glapi/dispatch.h"
36
37
38#if FEATURE_colortable
39
40
41/**
42 * Given an internalFormat token passed to glColorTable,
43 * return the corresponding base format.
44 * Return -1 if invalid token.
45 */
46static GLint
47base_colortab_format( GLenum format )
48{
49   switch (format) {
50      case GL_ALPHA:
51      case GL_ALPHA4:
52      case GL_ALPHA8:
53      case GL_ALPHA12:
54      case GL_ALPHA16:
55         return GL_ALPHA;
56      case GL_LUMINANCE:
57      case GL_LUMINANCE4:
58      case GL_LUMINANCE8:
59      case GL_LUMINANCE12:
60      case GL_LUMINANCE16:
61         return GL_LUMINANCE;
62      case GL_LUMINANCE_ALPHA:
63      case GL_LUMINANCE4_ALPHA4:
64      case GL_LUMINANCE6_ALPHA2:
65      case GL_LUMINANCE8_ALPHA8:
66      case GL_LUMINANCE12_ALPHA4:
67      case GL_LUMINANCE12_ALPHA12:
68      case GL_LUMINANCE16_ALPHA16:
69         return GL_LUMINANCE_ALPHA;
70      case GL_INTENSITY:
71      case GL_INTENSITY4:
72      case GL_INTENSITY8:
73      case GL_INTENSITY12:
74      case GL_INTENSITY16:
75         return GL_INTENSITY;
76      case GL_RGB:
77      case GL_R3_G3_B2:
78      case GL_RGB4:
79      case GL_RGB5:
80      case GL_RGB8:
81      case GL_RGB10:
82      case GL_RGB12:
83      case GL_RGB16:
84         return GL_RGB;
85      case GL_RGBA:
86      case GL_RGBA2:
87      case GL_RGBA4:
88      case GL_RGB5_A1:
89      case GL_RGBA8:
90      case GL_RGB10_A2:
91      case GL_RGBA12:
92      case GL_RGBA16:
93         return GL_RGBA;
94      default:
95         return -1;  /* error */
96   }
97}
98
99
100
101/**
102 * Examine table's format and set the component sizes accordingly.
103 */
104static void
105set_component_sizes( struct gl_color_table *table )
106{
107   /* assuming the ubyte table */
108   const GLubyte sz = 8;
109
110   switch (table->_BaseFormat) {
111      case GL_ALPHA:
112         table->RedSize = 0;
113         table->GreenSize = 0;
114         table->BlueSize = 0;
115         table->AlphaSize = sz;
116         table->IntensitySize = 0;
117         table->LuminanceSize = 0;
118         break;
119      case GL_LUMINANCE:
120         table->RedSize = 0;
121         table->GreenSize = 0;
122         table->BlueSize = 0;
123         table->AlphaSize = 0;
124         table->IntensitySize = 0;
125         table->LuminanceSize = sz;
126         break;
127      case GL_LUMINANCE_ALPHA:
128         table->RedSize = 0;
129         table->GreenSize = 0;
130         table->BlueSize = 0;
131         table->AlphaSize = sz;
132         table->IntensitySize = 0;
133         table->LuminanceSize = sz;
134         break;
135      case GL_INTENSITY:
136         table->RedSize = 0;
137         table->GreenSize = 0;
138         table->BlueSize = 0;
139         table->AlphaSize = 0;
140         table->IntensitySize = sz;
141         table->LuminanceSize = 0;
142         break;
143      case GL_RGB:
144         table->RedSize = sz;
145         table->GreenSize = sz;
146         table->BlueSize = sz;
147         table->AlphaSize = 0;
148         table->IntensitySize = 0;
149         table->LuminanceSize = 0;
150         break;
151      case GL_RGBA:
152         table->RedSize = sz;
153         table->GreenSize = sz;
154         table->BlueSize = sz;
155         table->AlphaSize = sz;
156         table->IntensitySize = 0;
157         table->LuminanceSize = 0;
158         break;
159      default:
160         _mesa_problem(NULL, "unexpected format in set_component_sizes");
161   }
162}
163
164
165
166/**
167 * Update/replace all or part of a color table.  Helper function
168 * used by _mesa_ColorTable() and _mesa_ColorSubTable().
169 * The table->Table buffer should already be allocated.
170 * \param start first entry to update
171 * \param count number of entries to update
172 * \param format format of user-provided table data
173 * \param type datatype of user-provided table data
174 * \param data user-provided table data
175 * \param [rgba]Scale - RGBA scale factors
176 * \param [rgba]Bias - RGBA bias factors
177 */
178static void
179store_colortable_entries(GLcontext *ctx, struct gl_color_table *table,
180			 GLsizei start, GLsizei count,
181			 GLenum format, GLenum type, const GLvoid *data,
182			 GLfloat rScale, GLfloat rBias,
183			 GLfloat gScale, GLfloat gBias,
184			 GLfloat bScale, GLfloat bBias,
185			 GLfloat aScale, GLfloat aBias)
186{
187   data = _mesa_map_validate_pbo_source(ctx,
188                                        1, &ctx->Unpack, count, 1, 1,
189                                        format, type, data,
190                                        "glColor[Sub]Table");
191   if (!data)
192      return;
193
194   {
195      /* convert user-provided data to GLfloat values */
196      GLfloat tempTab[MAX_COLOR_TABLE_SIZE * 4];
197      GLfloat *tableF;
198      GLint i;
199
200      _mesa_unpack_color_span_float(ctx,
201                                    count,         /* number of pixels */
202                                    table->_BaseFormat, /* dest format */
203                                    tempTab,       /* dest address */
204                                    format, type,  /* src format/type */
205                                    data,          /* src data */
206                                    &ctx->Unpack,
207                                    IMAGE_CLAMP_BIT); /* transfer ops */
208
209      /* the destination */
210      tableF = table->TableF;
211
212      /* Apply scale & bias & clamp now */
213      switch (table->_BaseFormat) {
214         case GL_INTENSITY:
215            for (i = 0; i < count; i++) {
216               GLuint j = start + i;
217               tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F);
218            }
219            break;
220         case GL_LUMINANCE:
221            for (i = 0; i < count; i++) {
222               GLuint j = start + i;
223               tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F);
224            }
225            break;
226         case GL_ALPHA:
227            for (i = 0; i < count; i++) {
228               GLuint j = start + i;
229               tableF[j] = CLAMP(tempTab[i] * aScale + aBias, 0.0F, 1.0F);
230            }
231            break;
232         case GL_LUMINANCE_ALPHA:
233            for (i = 0; i < count; i++) {
234               GLuint j = start + i;
235               tableF[j*2+0] = CLAMP(tempTab[i*2+0] * rScale + rBias, 0.0F, 1.0F);
236               tableF[j*2+1] = CLAMP(tempTab[i*2+1] * aScale + aBias, 0.0F, 1.0F);
237            }
238            break;
239         case GL_RGB:
240            for (i = 0; i < count; i++) {
241               GLuint j = start + i;
242               tableF[j*3+0] = CLAMP(tempTab[i*3+0] * rScale + rBias, 0.0F, 1.0F);
243               tableF[j*3+1] = CLAMP(tempTab[i*3+1] * gScale + gBias, 0.0F, 1.0F);
244               tableF[j*3+2] = CLAMP(tempTab[i*3+2] * bScale + bBias, 0.0F, 1.0F);
245            }
246            break;
247         case GL_RGBA:
248            for (i = 0; i < count; i++) {
249               GLuint j = start + i;
250               tableF[j*4+0] = CLAMP(tempTab[i*4+0] * rScale + rBias, 0.0F, 1.0F);
251               tableF[j*4+1] = CLAMP(tempTab[i*4+1] * gScale + gBias, 0.0F, 1.0F);
252               tableF[j*4+2] = CLAMP(tempTab[i*4+2] * bScale + bBias, 0.0F, 1.0F);
253               tableF[j*4+3] = CLAMP(tempTab[i*4+3] * aScale + aBias, 0.0F, 1.0F);
254            }
255            break;
256         default:
257            _mesa_problem(ctx, "Bad format in store_colortable_entries");
258            return;
259         }
260   }
261
262   /* update the ubyte table */
263   {
264      const GLint comps = _mesa_components_in_format(table->_BaseFormat);
265      const GLfloat *tableF = table->TableF + start * comps;
266      GLubyte *tableUB = table->TableUB + start * comps;
267      GLint i;
268      for (i = 0; i < count * comps; i++) {
269         CLAMPED_FLOAT_TO_UBYTE(tableUB[i], tableF[i]);
270      }
271   }
272
273   _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
274}
275
276
277
278void GLAPIENTRY
279_mesa_ColorTable( GLenum target, GLenum internalFormat,
280                  GLsizei width, GLenum format, GLenum type,
281                  const GLvoid *data )
282{
283   static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 };
284   static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 };
285   GET_CURRENT_CONTEXT(ctx);
286   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
287   struct gl_texture_object *texObj = NULL;
288   struct gl_color_table *table = NULL;
289   GLboolean proxy = GL_FALSE;
290   GLint baseFormat;
291   const GLfloat *scale = one, *bias = zero;
292   GLint comps;
293
294   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */
295
296   switch (target) {
297      case GL_SHARED_TEXTURE_PALETTE_EXT:
298         table = &ctx->Texture.Palette;
299         break;
300      case GL_COLOR_TABLE:
301         table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
302         scale = ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION];
303         bias = ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION];
304         break;
305      case GL_PROXY_COLOR_TABLE:
306         table = &ctx->ProxyColorTable[COLORTABLE_PRECONVOLUTION];
307         proxy = GL_TRUE;
308         break;
309      case GL_TEXTURE_COLOR_TABLE_SGI:
310         if (!ctx->Extensions.SGI_texture_color_table) {
311            _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)");
312            return;
313         }
314         table = &(texUnit->ColorTable);
315         scale = ctx->Pixel.TextureColorTableScale;
316         bias = ctx->Pixel.TextureColorTableBias;
317         break;
318      case GL_PROXY_TEXTURE_COLOR_TABLE_SGI:
319         if (!ctx->Extensions.SGI_texture_color_table) {
320            _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)");
321            return;
322         }
323         table = &(texUnit->ProxyColorTable);
324         proxy = GL_TRUE;
325         break;
326      case GL_POST_CONVOLUTION_COLOR_TABLE:
327         table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
328         scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION];
329         bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION];
330         break;
331      case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE:
332         table = &ctx->ProxyColorTable[COLORTABLE_POSTCONVOLUTION];
333         proxy = GL_TRUE;
334         break;
335      case GL_POST_COLOR_MATRIX_COLOR_TABLE:
336         table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
337         scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX];
338         bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX];
339         break;
340      case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE:
341         table = &ctx->ProxyColorTable[COLORTABLE_POSTCOLORMATRIX];
342         proxy = GL_TRUE;
343         break;
344      default:
345         /* try texture targets */
346         {
347            struct gl_texture_object *texobj
348               = _mesa_select_tex_object(ctx, texUnit, target);
349            if (texobj) {
350               table = &texobj->Palette;
351               proxy = _mesa_is_proxy_texture(target);
352            }
353            else {
354               _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)");
355               return;
356            }
357         }
358   }
359
360   assert(table);
361
362   if (!_mesa_is_legal_format_and_type(ctx, format, type) ||
363       format == GL_INTENSITY) {
364      _mesa_error(ctx, GL_INVALID_OPERATION, "glColorTable(format or type)");
365      return;
366   }
367
368   baseFormat = base_colortab_format(internalFormat);
369   if (baseFormat < 0) {
370      _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(internalFormat)");
371      return;
372   }
373
374   if (width < 0 || (width != 0 && !_mesa_is_pow_two(width))) {
375      /* error */
376      if (proxy) {
377         table->Size = 0;
378         table->InternalFormat = (GLenum) 0;
379         table->_BaseFormat = (GLenum) 0;
380      }
381      else {
382         _mesa_error(ctx, GL_INVALID_VALUE, "glColorTable(width=%d)", width);
383      }
384      return;
385   }
386
387   if (width > (GLsizei) ctx->Const.MaxColorTableSize) {
388      if (proxy) {
389         table->Size = 0;
390         table->InternalFormat = (GLenum) 0;
391         table->_BaseFormat = (GLenum) 0;
392      }
393      else {
394         _mesa_error(ctx, GL_TABLE_TOO_LARGE, "glColorTable(width)");
395      }
396      return;
397   }
398
399   table->Size = width;
400   table->InternalFormat = internalFormat;
401   table->_BaseFormat = (GLenum) baseFormat;
402
403   comps = _mesa_components_in_format(table->_BaseFormat);
404   assert(comps > 0);  /* error should have been caught sooner */
405
406   if (!proxy) {
407      _mesa_free_colortable_data(table);
408
409      if (width > 0) {
410         table->TableF = (GLfloat *) _mesa_malloc(comps * width * sizeof(GLfloat));
411         table->TableUB = (GLubyte *) _mesa_malloc(comps * width * sizeof(GLubyte));
412
413	 if (!table->TableF || !table->TableUB) {
414	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glColorTable");
415	    return;
416	 }
417
418	 store_colortable_entries(ctx, table,
419				  0, width,  /* start, count */
420				  format, type, data,
421				  scale[0], bias[0],
422				  scale[1], bias[1],
423				  scale[2], bias[2],
424				  scale[3], bias[3]);
425      }
426   } /* proxy */
427
428   /* do this after the table's Type and Format are set */
429   set_component_sizes(table);
430
431   if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) {
432      /* texture object palette, texObj==NULL means the shared palette */
433      if (ctx->Driver.UpdateTexturePalette) {
434         (*ctx->Driver.UpdateTexturePalette)( ctx, texObj );
435      }
436   }
437
438   ctx->NewState |= _NEW_PIXEL;
439}
440
441
442
443void GLAPIENTRY
444_mesa_ColorSubTable( GLenum target, GLsizei start,
445                     GLsizei count, GLenum format, GLenum type,
446                     const GLvoid *data )
447{
448   static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 };
449   static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 };
450   GET_CURRENT_CONTEXT(ctx);
451   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
452   struct gl_texture_object *texObj = NULL;
453   struct gl_color_table *table = NULL;
454   const GLfloat *scale = one, *bias = zero;
455
456   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
457
458   switch (target) {
459      case GL_SHARED_TEXTURE_PALETTE_EXT:
460         table = &ctx->Texture.Palette;
461         break;
462      case GL_COLOR_TABLE:
463         table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
464         scale = ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION];
465         bias = ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION];
466         break;
467      case GL_TEXTURE_COLOR_TABLE_SGI:
468         if (!ctx->Extensions.SGI_texture_color_table) {
469            _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)");
470            return;
471         }
472         table = &(texUnit->ColorTable);
473         scale = ctx->Pixel.TextureColorTableScale;
474         bias = ctx->Pixel.TextureColorTableBias;
475         break;
476      case GL_POST_CONVOLUTION_COLOR_TABLE:
477         table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
478         scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION];
479         bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION];
480         break;
481      case GL_POST_COLOR_MATRIX_COLOR_TABLE:
482         table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
483         scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX];
484         bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX];
485         break;
486      default:
487         /* try texture targets */
488         texObj = _mesa_select_tex_object(ctx, texUnit, target);
489         if (texObj && !_mesa_is_proxy_texture(target)) {
490            table = &texObj->Palette;
491         }
492         else {
493            _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)");
494            return;
495         }
496   }
497
498   assert(table);
499
500   if (!_mesa_is_legal_format_and_type(ctx, format, type) ||
501       format == GL_INTENSITY) {
502      _mesa_error(ctx, GL_INVALID_OPERATION, "glColorSubTable(format or type)");
503      return;
504   }
505
506   if (count < 1) {
507      _mesa_error(ctx, GL_INVALID_VALUE, "glColorSubTable(count)");
508      return;
509   }
510
511   /* error should have been caught sooner */
512   assert(_mesa_components_in_format(table->_BaseFormat) > 0);
513
514   if (start + count > (GLint) table->Size) {
515      _mesa_error(ctx, GL_INVALID_VALUE, "glColorSubTable(count)");
516      return;
517   }
518
519   if (!table->TableF || !table->TableUB) {
520      /* a GL_OUT_OF_MEMORY error would have been recorded previously */
521      return;
522   }
523
524   store_colortable_entries(ctx, table, start, count,
525			    format, type, data,
526                            scale[0], bias[0],
527                            scale[1], bias[1],
528                            scale[2], bias[2],
529                            scale[3], bias[3]);
530
531   if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) {
532      /* per-texture object palette */
533      if (ctx->Driver.UpdateTexturePalette) {
534         (*ctx->Driver.UpdateTexturePalette)( ctx, texObj );
535      }
536   }
537
538   ctx->NewState |= _NEW_PIXEL;
539}
540
541
542
543static void GLAPIENTRY
544_mesa_CopyColorTable(GLenum target, GLenum internalformat,
545                     GLint x, GLint y, GLsizei width)
546{
547   GET_CURRENT_CONTEXT(ctx);
548   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
549
550   if (!ctx->ReadBuffer->_ColorReadBuffer) {
551      return;      /* no readbuffer - OK */
552   }
553
554   ctx->Driver.CopyColorTable( ctx, target, internalformat, x, y, width );
555}
556
557
558
559static void GLAPIENTRY
560_mesa_CopyColorSubTable(GLenum target, GLsizei start,
561                        GLint x, GLint y, GLsizei width)
562{
563   GET_CURRENT_CONTEXT(ctx);
564   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
565
566   if (!ctx->ReadBuffer->_ColorReadBuffer) {
567      return;      /* no readbuffer - OK */
568   }
569
570   ctx->Driver.CopyColorSubTable( ctx, target, start, x, y, width );
571}
572
573
574
575static void GLAPIENTRY
576_mesa_GetColorTable( GLenum target, GLenum format,
577                     GLenum type, GLvoid *data )
578{
579   GET_CURRENT_CONTEXT(ctx);
580   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
581   struct gl_color_table *table = NULL;
582   GLfloat rgba[MAX_COLOR_TABLE_SIZE][4];
583   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
584
585   if (ctx->NewState) {
586      _mesa_update_state(ctx);
587   }
588
589   switch (target) {
590      case GL_SHARED_TEXTURE_PALETTE_EXT:
591         table = &ctx->Texture.Palette;
592         break;
593      case GL_COLOR_TABLE:
594         table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
595         break;
596      case GL_TEXTURE_COLOR_TABLE_SGI:
597         if (!ctx->Extensions.SGI_texture_color_table) {
598            _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)");
599            return;
600         }
601         table = &(texUnit->ColorTable);
602         break;
603      case GL_POST_CONVOLUTION_COLOR_TABLE:
604         table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
605         break;
606      case GL_POST_COLOR_MATRIX_COLOR_TABLE:
607         table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
608         break;
609      default:
610         /* try texture targets */
611         {
612            struct gl_texture_object *texobj
613               = _mesa_select_tex_object(ctx, texUnit, target);
614            if (texobj && !_mesa_is_proxy_texture(target)) {
615               table = &texobj->Palette;
616            }
617            else {
618               _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)");
619               return;
620            }
621         }
622   }
623
624   ASSERT(table);
625
626   if (table->Size <= 0) {
627      return;
628   }
629
630   switch (table->_BaseFormat) {
631   case GL_ALPHA:
632      {
633         GLuint i;
634         for (i = 0; i < table->Size; i++) {
635            rgba[i][RCOMP] = 0;
636            rgba[i][GCOMP] = 0;
637            rgba[i][BCOMP] = 0;
638            rgba[i][ACOMP] = table->TableF[i];
639         }
640      }
641      break;
642   case GL_LUMINANCE:
643      {
644         GLuint i;
645         for (i = 0; i < table->Size; i++) {
646            rgba[i][RCOMP] =
647            rgba[i][GCOMP] =
648            rgba[i][BCOMP] = table->TableF[i];
649            rgba[i][ACOMP] = 1.0F;
650         }
651      }
652      break;
653   case GL_LUMINANCE_ALPHA:
654      {
655         GLuint i;
656         for (i = 0; i < table->Size; i++) {
657            rgba[i][RCOMP] =
658            rgba[i][GCOMP] =
659            rgba[i][BCOMP] = table->TableF[i*2+0];
660            rgba[i][ACOMP] = table->TableF[i*2+1];
661         }
662      }
663      break;
664   case GL_INTENSITY:
665      {
666         GLuint i;
667         for (i = 0; i < table->Size; i++) {
668            rgba[i][RCOMP] =
669            rgba[i][GCOMP] =
670            rgba[i][BCOMP] =
671            rgba[i][ACOMP] = table->TableF[i];
672         }
673      }
674      break;
675   case GL_RGB:
676      {
677         GLuint i;
678         for (i = 0; i < table->Size; i++) {
679            rgba[i][RCOMP] = table->TableF[i*3+0];
680            rgba[i][GCOMP] = table->TableF[i*3+1];
681            rgba[i][BCOMP] = table->TableF[i*3+2];
682            rgba[i][ACOMP] = 1.0F;
683         }
684      }
685      break;
686   case GL_RGBA:
687      memcpy(rgba, table->TableF, 4 * table->Size * sizeof(GLfloat));
688      break;
689   default:
690      _mesa_problem(ctx, "bad table format in glGetColorTable");
691      return;
692   }
693
694   data = _mesa_map_validate_pbo_dest(ctx,
695                                      1, &ctx->Pack, table->Size, 1, 1,
696                                      format, type, data,
697                                      "glGetColorTable");
698   if (!data)
699      return;
700
701   _mesa_pack_rgba_span_float(ctx, table->Size, rgba,
702                              format, type, data, &ctx->Pack, 0x0);
703
704   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
705}
706
707
708
709static void GLAPIENTRY
710_mesa_ColorTableParameterfv(GLenum target, GLenum pname, const GLfloat *params)
711{
712   GLfloat *scale, *bias;
713   GET_CURRENT_CONTEXT(ctx);
714   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
715
716   switch (target) {
717   case GL_COLOR_TABLE_SGI:
718      scale = ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION];
719      bias  = ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION];
720      break;
721   case GL_TEXTURE_COLOR_TABLE_SGI:
722      scale = ctx->Pixel.TextureColorTableScale;
723      bias  = ctx->Pixel.TextureColorTableBias;
724      break;
725   case GL_POST_CONVOLUTION_COLOR_TABLE_SGI:
726      scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION];
727      bias  = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION];
728      break;
729   case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI:
730      scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX];
731      bias  = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX];
732      break;
733   default:
734      _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameter(target)");
735      return;
736   }
737
738   if (pname == GL_COLOR_TABLE_SCALE_SGI) {
739      COPY_4V(scale, params);
740   }
741   else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
742      COPY_4V(bias, params);
743   }
744   else {
745      _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameterfv(pname)");
746      return;
747   }
748
749   ctx->NewState |= _NEW_PIXEL;
750}
751
752
753
754static void GLAPIENTRY
755_mesa_ColorTableParameteriv(GLenum target, GLenum pname, const GLint *params)
756{
757   GLfloat fparams[4];
758   if (pname == GL_COLOR_TABLE_SGI ||
759       pname == GL_TEXTURE_COLOR_TABLE_SGI ||
760       pname == GL_POST_CONVOLUTION_COLOR_TABLE_SGI ||
761       pname == GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI) {
762      /* four values */
763      fparams[0] = (GLfloat) params[0];
764      fparams[1] = (GLfloat) params[1];
765      fparams[2] = (GLfloat) params[2];
766      fparams[3] = (GLfloat) params[3];
767   }
768   else {
769      /* one values */
770      fparams[0] = (GLfloat) params[0];
771   }
772   _mesa_ColorTableParameterfv(target, pname, fparams);
773}
774
775
776
777static void GLAPIENTRY
778_mesa_GetColorTableParameterfv( GLenum target, GLenum pname, GLfloat *params )
779{
780   GET_CURRENT_CONTEXT(ctx);
781   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
782   struct gl_color_table *table = NULL;
783   ASSERT_OUTSIDE_BEGIN_END(ctx);
784
785   switch (target) {
786      case GL_SHARED_TEXTURE_PALETTE_EXT:
787         table = &ctx->Texture.Palette;
788         break;
789      case GL_COLOR_TABLE:
790         table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
791         if (pname == GL_COLOR_TABLE_SCALE_SGI) {
792            COPY_4V(params, ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION]);
793            return;
794         }
795         else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
796            COPY_4V(params, ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION]);
797            return;
798         }
799         break;
800      case GL_PROXY_COLOR_TABLE:
801         table = &ctx->ProxyColorTable[COLORTABLE_PRECONVOLUTION];
802         break;
803      case GL_TEXTURE_COLOR_TABLE_SGI:
804         if (!ctx->Extensions.SGI_texture_color_table) {
805            _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)");
806            return;
807         }
808         table = &(texUnit->ColorTable);
809         if (pname == GL_COLOR_TABLE_SCALE_SGI) {
810            COPY_4V(params, ctx->Pixel.TextureColorTableScale);
811            return;
812         }
813         else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
814            COPY_4V(params, ctx->Pixel.TextureColorTableBias);
815            return;
816         }
817         break;
818      case GL_PROXY_TEXTURE_COLOR_TABLE_SGI:
819         if (!ctx->Extensions.SGI_texture_color_table) {
820            _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)");
821            return;
822         }
823         table = &(texUnit->ProxyColorTable);
824         break;
825      case GL_POST_CONVOLUTION_COLOR_TABLE:
826         table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
827         if (pname == GL_COLOR_TABLE_SCALE_SGI) {
828            COPY_4V(params, ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION]);
829            return;
830         }
831         else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
832            COPY_4V(params, ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION]);
833            return;
834         }
835         break;
836      case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE:
837         table = &ctx->ProxyColorTable[COLORTABLE_POSTCONVOLUTION];
838         break;
839      case GL_POST_COLOR_MATRIX_COLOR_TABLE:
840         table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
841         if (pname == GL_COLOR_TABLE_SCALE_SGI) {
842            COPY_4V(params, ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX]);
843            return;
844         }
845         else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
846            COPY_4V(params, ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX]);
847            return;
848         }
849         break;
850      case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE:
851         table = &ctx->ProxyColorTable[COLORTABLE_POSTCOLORMATRIX];
852         break;
853      default:
854         /* try texture targets */
855         {
856            struct gl_texture_object *texobj
857               = _mesa_select_tex_object(ctx, texUnit, target);
858            if (texobj) {
859               table = &texobj->Palette;
860            }
861            else {
862               _mesa_error(ctx, GL_INVALID_ENUM,
863                           "glGetColorTableParameterfv(target)");
864               return;
865            }
866         }
867   }
868
869   assert(table);
870
871   switch (pname) {
872      case GL_COLOR_TABLE_FORMAT:
873         *params = (GLfloat) table->InternalFormat;
874         break;
875      case GL_COLOR_TABLE_WIDTH:
876         *params = (GLfloat) table->Size;
877         break;
878      case GL_COLOR_TABLE_RED_SIZE:
879         *params = (GLfloat) table->RedSize;
880         break;
881      case GL_COLOR_TABLE_GREEN_SIZE:
882         *params = (GLfloat) table->GreenSize;
883         break;
884      case GL_COLOR_TABLE_BLUE_SIZE:
885         *params = (GLfloat) table->BlueSize;
886         break;
887      case GL_COLOR_TABLE_ALPHA_SIZE:
888         *params = (GLfloat) table->AlphaSize;
889         break;
890      case GL_COLOR_TABLE_LUMINANCE_SIZE:
891         *params = (GLfloat) table->LuminanceSize;
892         break;
893      case GL_COLOR_TABLE_INTENSITY_SIZE:
894         *params = (GLfloat) table->IntensitySize;
895         break;
896      default:
897         _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameterfv(pname)" );
898         return;
899   }
900}
901
902
903
904static void GLAPIENTRY
905_mesa_GetColorTableParameteriv( GLenum target, GLenum pname, GLint *params )
906{
907   GET_CURRENT_CONTEXT(ctx);
908   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
909   struct gl_color_table *table = NULL;
910   ASSERT_OUTSIDE_BEGIN_END(ctx);
911
912   switch (target) {
913      case GL_SHARED_TEXTURE_PALETTE_EXT:
914         table = &ctx->Texture.Palette;
915         break;
916      case GL_COLOR_TABLE:
917         table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
918         if (pname == GL_COLOR_TABLE_SCALE_SGI) {
919            GLfloat *scale = ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION];
920            params[0] = (GLint) scale[0];
921            params[1] = (GLint) scale[1];
922            params[2] = (GLint) scale[2];
923            params[3] = (GLint) scale[3];
924            return;
925         }
926         else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
927            GLfloat *bias = ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION];
928            params[0] = (GLint) bias[0];
929            params[1] = (GLint) bias[1];
930            params[2] = (GLint) bias[2];
931            params[3] = (GLint) bias[3];
932            return;
933         }
934         break;
935      case GL_PROXY_COLOR_TABLE:
936         table = &ctx->ProxyColorTable[COLORTABLE_PRECONVOLUTION];
937         break;
938      case GL_TEXTURE_COLOR_TABLE_SGI:
939         if (!ctx->Extensions.SGI_texture_color_table) {
940            _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)");
941            return;
942         }
943         table = &(texUnit->ColorTable);
944         if (pname == GL_COLOR_TABLE_SCALE_SGI) {
945            params[0] = (GLint) ctx->Pixel.TextureColorTableScale[0];
946            params[1] = (GLint) ctx->Pixel.TextureColorTableScale[1];
947            params[2] = (GLint) ctx->Pixel.TextureColorTableScale[2];
948            params[3] = (GLint) ctx->Pixel.TextureColorTableScale[3];
949            return;
950         }
951         else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
952            params[0] = (GLint) ctx->Pixel.TextureColorTableBias[0];
953            params[1] = (GLint) ctx->Pixel.TextureColorTableBias[1];
954            params[2] = (GLint) ctx->Pixel.TextureColorTableBias[2];
955            params[3] = (GLint) ctx->Pixel.TextureColorTableBias[3];
956            return;
957         }
958         break;
959      case GL_PROXY_TEXTURE_COLOR_TABLE_SGI:
960         if (!ctx->Extensions.SGI_texture_color_table) {
961            _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)");
962            return;
963         }
964         table = &(texUnit->ProxyColorTable);
965         break;
966      case GL_POST_CONVOLUTION_COLOR_TABLE:
967         table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
968         if (pname == GL_COLOR_TABLE_SCALE_SGI) {
969            GLfloat *scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION];
970            params[0] = (GLint) scale[0];
971            params[1] = (GLint) scale[1];
972            params[2] = (GLint) scale[2];
973            params[3] = (GLint) scale[3];
974            return;
975         }
976         else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
977            GLfloat *bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION];
978            params[0] = (GLint) bias[0];
979            params[1] = (GLint) bias[1];
980            params[2] = (GLint) bias[2];
981            params[3] = (GLint) bias[3];
982            return;
983         }
984         break;
985      case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE:
986         table = &ctx->ProxyColorTable[COLORTABLE_POSTCONVOLUTION];
987         break;
988      case GL_POST_COLOR_MATRIX_COLOR_TABLE:
989         table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
990         if (pname == GL_COLOR_TABLE_SCALE_SGI) {
991            GLfloat *scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX];
992            params[0] = (GLint) scale[0];
993            params[0] = (GLint) scale[1];
994            params[0] = (GLint) scale[2];
995            params[0] = (GLint) scale[3];
996            return;
997         }
998         else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
999            GLfloat *bias = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX];
1000            params[0] = (GLint) bias[0];
1001            params[1] = (GLint) bias[1];
1002            params[2] = (GLint) bias[2];
1003            params[3] = (GLint) bias[3];
1004            return;
1005         }
1006         break;
1007      case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE:
1008         table = &ctx->ProxyColorTable[COLORTABLE_POSTCOLORMATRIX];
1009         break;
1010      default:
1011         /* Try texture targets */
1012         {
1013            struct gl_texture_object *texobj
1014               = _mesa_select_tex_object(ctx, texUnit, target);
1015            if (texobj) {
1016               table = &texobj->Palette;
1017            }
1018            else {
1019               _mesa_error(ctx, GL_INVALID_ENUM,
1020                           "glGetColorTableParameteriv(target)");
1021               return;
1022            }
1023         }
1024   }
1025
1026   assert(table);
1027
1028   switch (pname) {
1029      case GL_COLOR_TABLE_FORMAT:
1030         *params = table->InternalFormat;
1031         break;
1032      case GL_COLOR_TABLE_WIDTH:
1033         *params = table->Size;
1034         break;
1035      case GL_COLOR_TABLE_RED_SIZE:
1036         *params = table->RedSize;
1037         break;
1038      case GL_COLOR_TABLE_GREEN_SIZE:
1039         *params = table->GreenSize;
1040         break;
1041      case GL_COLOR_TABLE_BLUE_SIZE:
1042         *params = table->BlueSize;
1043         break;
1044      case GL_COLOR_TABLE_ALPHA_SIZE:
1045         *params = table->AlphaSize;
1046         break;
1047      case GL_COLOR_TABLE_LUMINANCE_SIZE:
1048         *params = table->LuminanceSize;
1049         break;
1050      case GL_COLOR_TABLE_INTENSITY_SIZE:
1051         *params = table->IntensitySize;
1052         break;
1053      default:
1054         _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameteriv(pname)" );
1055         return;
1056   }
1057}
1058
1059
1060void
1061_mesa_init_colortable_dispatch(struct _glapi_table *disp)
1062{
1063   SET_ColorSubTable(disp, _mesa_ColorSubTable);
1064   SET_ColorTable(disp, _mesa_ColorTable);
1065   SET_ColorTableParameterfv(disp, _mesa_ColorTableParameterfv);
1066   SET_ColorTableParameteriv(disp, _mesa_ColorTableParameteriv);
1067   SET_CopyColorSubTable(disp, _mesa_CopyColorSubTable);
1068   SET_CopyColorTable(disp, _mesa_CopyColorTable);
1069   SET_GetColorTable(disp, _mesa_GetColorTable);
1070   SET_GetColorTableParameterfv(disp, _mesa_GetColorTableParameterfv);
1071   SET_GetColorTableParameteriv(disp, _mesa_GetColorTableParameteriv);
1072}
1073
1074
1075#endif /* FEATURE_colortable */
1076
1077
1078/**********************************************************************/
1079/*****                      Initialization                        *****/
1080/**********************************************************************/
1081
1082
1083void
1084_mesa_init_colortable( struct gl_color_table *p )
1085{
1086   p->TableF = NULL;
1087   p->TableUB = NULL;
1088   p->Size = 0;
1089   p->InternalFormat = GL_RGBA;
1090}
1091
1092
1093
1094void
1095_mesa_free_colortable_data( struct gl_color_table *p )
1096{
1097   if (p->TableF) {
1098      _mesa_free(p->TableF);
1099      p->TableF = NULL;
1100   }
1101   if (p->TableUB) {
1102      _mesa_free(p->TableUB);
1103      p->TableUB = NULL;
1104   }
1105}
1106
1107
1108/*
1109 * Initialize all colortables for a context.
1110 */
1111void
1112_mesa_init_colortables( GLcontext * ctx )
1113{
1114   GLuint i;
1115   for (i = 0; i < COLORTABLE_MAX; i++) {
1116      _mesa_init_colortable(&ctx->ColorTable[i]);
1117      _mesa_init_colortable(&ctx->ProxyColorTable[i]);
1118   }
1119}
1120
1121
1122/*
1123 * Free all colortable data for a context
1124 */
1125void
1126_mesa_free_colortables_data( GLcontext *ctx )
1127{
1128   GLuint i;
1129   for (i = 0; i < COLORTABLE_MAX; i++) {
1130      _mesa_free_colortable_data(&ctx->ColorTable[i]);
1131      _mesa_free_colortable_data(&ctx->ProxyColorTable[i]);
1132   }
1133}
1134