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