2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
27 #include "bufferobj.h"
32 #include "mfeatures.h"
39 #include "main/dispatch.h"
42 #if FEATURE_colortable
46 * Given an internalFormat token passed to glColorTable,
47 * return the corresponding base format.
48 * Return -1 if invalid token.
51 base_colortab_format( GLenum format
)
66 case GL_LUMINANCE_ALPHA
:
67 case GL_LUMINANCE4_ALPHA4
:
68 case GL_LUMINANCE6_ALPHA2
:
69 case GL_LUMINANCE8_ALPHA8
:
70 case GL_LUMINANCE12_ALPHA4
:
71 case GL_LUMINANCE12_ALPHA12
:
72 case GL_LUMINANCE16_ALPHA16
:
73 return GL_LUMINANCE_ALPHA
;
99 return -1; /* error */
106 * Examine table's format and set the component sizes accordingly.
109 set_component_sizes( struct gl_color_table
*table
)
111 /* assuming the ubyte table */
112 const GLubyte sz
= 8;
114 switch (table
->_BaseFormat
) {
117 table
->GreenSize
= 0;
119 table
->AlphaSize
= sz
;
120 table
->IntensitySize
= 0;
121 table
->LuminanceSize
= 0;
125 table
->GreenSize
= 0;
127 table
->AlphaSize
= 0;
128 table
->IntensitySize
= 0;
129 table
->LuminanceSize
= sz
;
131 case GL_LUMINANCE_ALPHA
:
133 table
->GreenSize
= 0;
135 table
->AlphaSize
= sz
;
136 table
->IntensitySize
= 0;
137 table
->LuminanceSize
= sz
;
141 table
->GreenSize
= 0;
143 table
->AlphaSize
= 0;
144 table
->IntensitySize
= sz
;
145 table
->LuminanceSize
= 0;
149 table
->GreenSize
= sz
;
150 table
->BlueSize
= sz
;
151 table
->AlphaSize
= 0;
152 table
->IntensitySize
= 0;
153 table
->LuminanceSize
= 0;
157 table
->GreenSize
= sz
;
158 table
->BlueSize
= sz
;
159 table
->AlphaSize
= sz
;
160 table
->IntensitySize
= 0;
161 table
->LuminanceSize
= 0;
164 _mesa_problem(NULL
, "unexpected format in set_component_sizes");
171 * Update/replace all or part of a color table. Helper function
172 * used by _mesa_ColorTable() and _mesa_ColorSubTable().
173 * The table->Table buffer should already be allocated.
174 * \param start first entry to update
175 * \param count number of entries to update
176 * \param format format of user-provided table data
177 * \param type datatype of user-provided table data
178 * \param data user-provided table data
179 * \param [rgba]Scale - RGBA scale factors
180 * \param [rgba]Bias - RGBA bias factors
183 store_colortable_entries(struct gl_context
*ctx
, struct gl_color_table
*table
,
184 GLsizei start
, GLsizei count
,
185 GLenum format
, GLenum type
, const GLvoid
*data
,
186 GLfloat rScale
, GLfloat rBias
,
187 GLfloat gScale
, GLfloat gBias
,
188 GLfloat bScale
, GLfloat bBias
,
189 GLfloat aScale
, GLfloat aBias
)
191 data
= _mesa_map_validate_pbo_source(ctx
,
192 1, &ctx
->Unpack
, count
, 1, 1,
193 format
, type
, INT_MAX
, data
,
194 "glColor[Sub]Table");
199 /* convert user-provided data to GLfloat values */
200 GLfloat tempTab
[MAX_COLOR_TABLE_SIZE
* 4];
204 _mesa_unpack_color_span_float(ctx
,
205 count
, /* number of pixels */
206 table
->_BaseFormat
, /* dest format */
207 tempTab
, /* dest address */
208 format
, type
, /* src format/type */
211 IMAGE_CLAMP_BIT
); /* transfer ops */
213 /* the destination */
214 tableF
= table
->TableF
;
216 /* Apply scale & bias & clamp now */
217 switch (table
->_BaseFormat
) {
219 for (i
= 0; i
< count
; i
++) {
220 GLuint j
= start
+ i
;
221 tableF
[j
] = CLAMP(tempTab
[i
] * rScale
+ rBias
, 0.0F
, 1.0F
);
225 for (i
= 0; i
< count
; i
++) {
226 GLuint j
= start
+ i
;
227 tableF
[j
] = CLAMP(tempTab
[i
] * rScale
+ rBias
, 0.0F
, 1.0F
);
231 for (i
= 0; i
< count
; i
++) {
232 GLuint j
= start
+ i
;
233 tableF
[j
] = CLAMP(tempTab
[i
] * aScale
+ aBias
, 0.0F
, 1.0F
);
236 case GL_LUMINANCE_ALPHA
:
237 for (i
= 0; i
< count
; i
++) {
238 GLuint j
= start
+ i
;
239 tableF
[j
*2+0] = CLAMP(tempTab
[i
*2+0] * rScale
+ rBias
, 0.0F
, 1.0F
);
240 tableF
[j
*2+1] = CLAMP(tempTab
[i
*2+1] * aScale
+ aBias
, 0.0F
, 1.0F
);
244 for (i
= 0; i
< count
; i
++) {
245 GLuint j
= start
+ i
;
246 tableF
[j
*3+0] = CLAMP(tempTab
[i
*3+0] * rScale
+ rBias
, 0.0F
, 1.0F
);
247 tableF
[j
*3+1] = CLAMP(tempTab
[i
*3+1] * gScale
+ gBias
, 0.0F
, 1.0F
);
248 tableF
[j
*3+2] = CLAMP(tempTab
[i
*3+2] * bScale
+ bBias
, 0.0F
, 1.0F
);
252 for (i
= 0; i
< count
; i
++) {
253 GLuint j
= start
+ i
;
254 tableF
[j
*4+0] = CLAMP(tempTab
[i
*4+0] * rScale
+ rBias
, 0.0F
, 1.0F
);
255 tableF
[j
*4+1] = CLAMP(tempTab
[i
*4+1] * gScale
+ gBias
, 0.0F
, 1.0F
);
256 tableF
[j
*4+2] = CLAMP(tempTab
[i
*4+2] * bScale
+ bBias
, 0.0F
, 1.0F
);
257 tableF
[j
*4+3] = CLAMP(tempTab
[i
*4+3] * aScale
+ aBias
, 0.0F
, 1.0F
);
261 _mesa_problem(ctx
, "Bad format in store_colortable_entries");
266 /* update the ubyte table */
268 const GLint comps
= _mesa_components_in_format(table
->_BaseFormat
);
269 const GLfloat
*tableF
= table
->TableF
+ start
* comps
;
270 GLubyte
*tableUB
= table
->TableUB
+ start
* comps
;
272 for (i
= 0; i
< count
* comps
; i
++) {
273 CLAMPED_FLOAT_TO_UBYTE(tableUB
[i
], tableF
[i
]);
277 _mesa_unmap_pbo_source(ctx
, &ctx
->Unpack
);
283 _mesa_ColorTable( GLenum target
, GLenum internalFormat
,
284 GLsizei width
, GLenum format
, GLenum type
,
287 static const GLfloat one
[4] = { 1.0, 1.0, 1.0, 1.0 };
288 static const GLfloat zero
[4] = { 0.0, 0.0, 0.0, 0.0 };
289 GET_CURRENT_CONTEXT(ctx
);
290 struct gl_texture_unit
*texUnit
= _mesa_get_current_tex_unit(ctx
);
291 struct gl_texture_object
*texObj
= NULL
;
292 struct gl_color_table
*table
= NULL
;
293 GLboolean proxy
= GL_FALSE
;
295 const GLfloat
*scale
= one
, *bias
= zero
;
298 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
); /* too complex */
301 case GL_SHARED_TEXTURE_PALETTE_EXT
:
302 table
= &ctx
->Texture
.Palette
;
305 /* try texture targets */
307 struct gl_texture_object
*texobj
308 = _mesa_select_tex_object(ctx
, texUnit
, target
);
310 table
= &texobj
->Palette
;
311 proxy
= _mesa_is_proxy_texture(target
);
314 _mesa_error(ctx
, GL_INVALID_ENUM
, "glColorTable(target)");
322 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
) ||
323 format
== GL_INTENSITY
) {
324 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glColorTable(format or type)");
328 baseFormat
= base_colortab_format(internalFormat
);
329 if (baseFormat
< 0) {
330 _mesa_error(ctx
, GL_INVALID_ENUM
, "glColorTable(internalFormat)");
334 if (width
< 0 || (width
!= 0 && !_mesa_is_pow_two(width
))) {
338 table
->InternalFormat
= (GLenum
) 0;
339 table
->_BaseFormat
= (GLenum
) 0;
342 _mesa_error(ctx
, GL_INVALID_VALUE
, "glColorTable(width=%d)", width
);
347 if (width
> (GLsizei
) ctx
->Const
.MaxColorTableSize
) {
350 table
->InternalFormat
= (GLenum
) 0;
351 table
->_BaseFormat
= (GLenum
) 0;
354 _mesa_error(ctx
, GL_TABLE_TOO_LARGE
, "glColorTable(width)");
360 table
->InternalFormat
= internalFormat
;
361 table
->_BaseFormat
= (GLenum
) baseFormat
;
363 comps
= _mesa_components_in_format(table
->_BaseFormat
);
364 assert(comps
> 0); /* error should have been caught sooner */
367 _mesa_free_colortable_data(table
);
370 table
->TableF
= (GLfloat
*) malloc(comps
* width
* sizeof(GLfloat
));
371 table
->TableUB
= (GLubyte
*) malloc(comps
* width
* sizeof(GLubyte
));
373 if (!table
->TableF
|| !table
->TableUB
) {
374 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glColorTable");
378 store_colortable_entries(ctx
, table
,
379 0, width
, /* start, count */
388 /* do this after the table's Type and Format are set */
389 set_component_sizes(table
);
391 if (texObj
|| target
== GL_SHARED_TEXTURE_PALETTE_EXT
) {
392 /* texture object palette, texObj==NULL means the shared palette */
393 if (ctx
->Driver
.UpdateTexturePalette
) {
394 (*ctx
->Driver
.UpdateTexturePalette
)( ctx
, texObj
);
398 ctx
->NewState
|= _NEW_PIXEL
;
404 _mesa_ColorSubTable( GLenum target
, GLsizei start
,
405 GLsizei count
, GLenum format
, GLenum type
,
408 static const GLfloat one
[4] = { 1.0, 1.0, 1.0, 1.0 };
409 static const GLfloat zero
[4] = { 0.0, 0.0, 0.0, 0.0 };
410 GET_CURRENT_CONTEXT(ctx
);
411 struct gl_texture_unit
*texUnit
= _mesa_get_current_tex_unit(ctx
);
412 struct gl_texture_object
*texObj
= NULL
;
413 struct gl_color_table
*table
= NULL
;
414 const GLfloat
*scale
= one
, *bias
= zero
;
416 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
419 case GL_SHARED_TEXTURE_PALETTE_EXT
:
420 table
= &ctx
->Texture
.Palette
;
423 /* try texture targets */
424 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
425 if (texObj
&& !_mesa_is_proxy_texture(target
)) {
426 table
= &texObj
->Palette
;
429 _mesa_error(ctx
, GL_INVALID_ENUM
, "glColorSubTable(target)");
436 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
) ||
437 format
== GL_INTENSITY
) {
438 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glColorSubTable(format or type)");
443 _mesa_error(ctx
, GL_INVALID_VALUE
, "glColorSubTable(count)");
447 /* error should have been caught sooner */
448 assert(_mesa_components_in_format(table
->_BaseFormat
) > 0);
450 if (start
+ count
> (GLint
) table
->Size
) {
451 _mesa_error(ctx
, GL_INVALID_VALUE
, "glColorSubTable(count)");
455 if (!table
->TableF
|| !table
->TableUB
) {
456 /* a GL_OUT_OF_MEMORY error would have been recorded previously */
460 store_colortable_entries(ctx
, table
, start
, count
,
467 if (texObj
|| target
== GL_SHARED_TEXTURE_PALETTE_EXT
) {
468 /* per-texture object palette */
469 if (ctx
->Driver
.UpdateTexturePalette
) {
470 (*ctx
->Driver
.UpdateTexturePalette
)( ctx
, texObj
);
474 ctx
->NewState
|= _NEW_PIXEL
;
479 static void GLAPIENTRY
480 _mesa_CopyColorTable(GLenum target
, GLenum internalformat
,
481 GLint x
, GLint y
, GLsizei width
)
483 GET_CURRENT_CONTEXT(ctx
);
484 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
486 if (!ctx
->ReadBuffer
->_ColorReadBuffer
) {
487 return; /* no readbuffer - OK */
490 ctx
->Driver
.CopyColorTable( ctx
, target
, internalformat
, x
, y
, width
);
495 static void GLAPIENTRY
496 _mesa_CopyColorSubTable(GLenum target
, GLsizei start
,
497 GLint x
, GLint y
, GLsizei width
)
499 GET_CURRENT_CONTEXT(ctx
);
500 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
502 if (!ctx
->ReadBuffer
->_ColorReadBuffer
) {
503 return; /* no readbuffer - OK */
506 ctx
->Driver
.CopyColorSubTable( ctx
, target
, start
, x
, y
, width
);
511 static void GLAPIENTRY
512 _mesa_GetnColorTableARB( GLenum target
, GLenum format
, GLenum type
,
513 GLsizei bufSize
, GLvoid
*data
)
515 GET_CURRENT_CONTEXT(ctx
);
516 struct gl_texture_unit
*texUnit
= _mesa_get_current_tex_unit(ctx
);
517 struct gl_color_table
*table
= NULL
;
518 GLfloat rgba
[MAX_COLOR_TABLE_SIZE
][4];
519 GLbitfield transferOps
= 0;
520 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
523 _mesa_update_state(ctx
);
527 case GL_SHARED_TEXTURE_PALETTE_EXT
:
528 table
= &ctx
->Texture
.Palette
;
531 /* try texture targets */
533 struct gl_texture_object
*texobj
534 = _mesa_select_tex_object(ctx
, texUnit
, target
);
535 if (texobj
&& !_mesa_is_proxy_texture(target
)) {
536 table
= &texobj
->Palette
;
539 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetColorTable(target)");
547 if (table
->Size
<= 0) {
551 switch (table
->_BaseFormat
) {
555 for (i
= 0; i
< table
->Size
; i
++) {
559 rgba
[i
][ACOMP
] = table
->TableF
[i
];
566 for (i
= 0; i
< table
->Size
; i
++) {
569 rgba
[i
][BCOMP
] = table
->TableF
[i
];
570 rgba
[i
][ACOMP
] = 1.0F
;
574 case GL_LUMINANCE_ALPHA
:
577 for (i
= 0; i
< table
->Size
; i
++) {
580 rgba
[i
][BCOMP
] = table
->TableF
[i
*2+0];
581 rgba
[i
][ACOMP
] = table
->TableF
[i
*2+1];
588 for (i
= 0; i
< table
->Size
; i
++) {
592 rgba
[i
][ACOMP
] = table
->TableF
[i
];
599 for (i
= 0; i
< table
->Size
; i
++) {
600 rgba
[i
][RCOMP
] = table
->TableF
[i
*3+0];
601 rgba
[i
][GCOMP
] = table
->TableF
[i
*3+1];
602 rgba
[i
][BCOMP
] = table
->TableF
[i
*3+2];
603 rgba
[i
][ACOMP
] = 1.0F
;
608 memcpy(rgba
, table
->TableF
, 4 * table
->Size
* sizeof(GLfloat
));
611 _mesa_problem(ctx
, "bad table format in glGetColorTable");
615 data
= _mesa_map_validate_pbo_dest(ctx
,
616 1, &ctx
->Pack
, table
->Size
, 1, 1,
617 format
, type
, bufSize
, data
,
622 /* TODO: is this correct? */
623 if(ctx
->Color
._ClampReadColor
)
624 transferOps
|= IMAGE_CLAMP_BIT
;
626 _mesa_pack_rgba_span_float(ctx
, table
->Size
, rgba
,
627 format
, type
, data
, &ctx
->Pack
, transferOps
);
629 _mesa_unmap_pbo_dest(ctx
, &ctx
->Pack
);
633 static void GLAPIENTRY
634 _mesa_GetColorTable( GLenum target
, GLenum format
,
635 GLenum type
, GLvoid
*data
)
637 _mesa_GetnColorTableARB(target
, format
, type
, INT_MAX
, data
);
641 static void GLAPIENTRY
642 _mesa_ColorTableParameterfv(GLenum target
, GLenum pname
, const GLfloat
*params
)
644 /* no extensions use this function */
645 GET_CURRENT_CONTEXT(ctx
);
646 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
647 _mesa_error(ctx
, GL_INVALID_ENUM
, "glColorTableParameterfv(target)");
652 static void GLAPIENTRY
653 _mesa_ColorTableParameteriv(GLenum target
, GLenum pname
, const GLint
*params
)
655 /* no extensions use this function */
656 GET_CURRENT_CONTEXT(ctx
);
657 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
658 _mesa_error(ctx
, GL_INVALID_ENUM
, "glColorTableParameteriv(target)");
663 static void GLAPIENTRY
664 _mesa_GetColorTableParameterfv( GLenum target
, GLenum pname
, GLfloat
*params
)
666 GET_CURRENT_CONTEXT(ctx
);
667 struct gl_texture_unit
*texUnit
= _mesa_get_current_tex_unit(ctx
);
668 struct gl_color_table
*table
= NULL
;
669 ASSERT_OUTSIDE_BEGIN_END(ctx
);
672 case GL_SHARED_TEXTURE_PALETTE_EXT
:
673 table
= &ctx
->Texture
.Palette
;
676 /* try texture targets */
678 struct gl_texture_object
*texobj
679 = _mesa_select_tex_object(ctx
, texUnit
, target
);
681 table
= &texobj
->Palette
;
684 _mesa_error(ctx
, GL_INVALID_ENUM
,
685 "glGetColorTableParameterfv(target)");
694 case GL_COLOR_TABLE_FORMAT
:
695 *params
= (GLfloat
) table
->InternalFormat
;
697 case GL_COLOR_TABLE_WIDTH
:
698 *params
= (GLfloat
) table
->Size
;
700 case GL_COLOR_TABLE_RED_SIZE
:
701 *params
= (GLfloat
) table
->RedSize
;
703 case GL_COLOR_TABLE_GREEN_SIZE
:
704 *params
= (GLfloat
) table
->GreenSize
;
706 case GL_COLOR_TABLE_BLUE_SIZE
:
707 *params
= (GLfloat
) table
->BlueSize
;
709 case GL_COLOR_TABLE_ALPHA_SIZE
:
710 *params
= (GLfloat
) table
->AlphaSize
;
712 case GL_COLOR_TABLE_LUMINANCE_SIZE
:
713 *params
= (GLfloat
) table
->LuminanceSize
;
715 case GL_COLOR_TABLE_INTENSITY_SIZE
:
716 *params
= (GLfloat
) table
->IntensitySize
;
719 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetColorTableParameterfv(pname)" );
726 static void GLAPIENTRY
727 _mesa_GetColorTableParameteriv( GLenum target
, GLenum pname
, GLint
*params
)
729 GET_CURRENT_CONTEXT(ctx
);
730 struct gl_texture_unit
*texUnit
= _mesa_get_current_tex_unit(ctx
);
731 struct gl_color_table
*table
= NULL
;
732 ASSERT_OUTSIDE_BEGIN_END(ctx
);
735 case GL_SHARED_TEXTURE_PALETTE_EXT
:
736 table
= &ctx
->Texture
.Palette
;
739 /* Try texture targets */
741 struct gl_texture_object
*texobj
742 = _mesa_select_tex_object(ctx
, texUnit
, target
);
744 table
= &texobj
->Palette
;
747 _mesa_error(ctx
, GL_INVALID_ENUM
,
748 "glGetColorTableParameteriv(target)");
757 case GL_COLOR_TABLE_FORMAT
:
758 *params
= table
->InternalFormat
;
760 case GL_COLOR_TABLE_WIDTH
:
761 *params
= table
->Size
;
763 case GL_COLOR_TABLE_RED_SIZE
:
764 *params
= table
->RedSize
;
766 case GL_COLOR_TABLE_GREEN_SIZE
:
767 *params
= table
->GreenSize
;
769 case GL_COLOR_TABLE_BLUE_SIZE
:
770 *params
= table
->BlueSize
;
772 case GL_COLOR_TABLE_ALPHA_SIZE
:
773 *params
= table
->AlphaSize
;
775 case GL_COLOR_TABLE_LUMINANCE_SIZE
:
776 *params
= table
->LuminanceSize
;
778 case GL_COLOR_TABLE_INTENSITY_SIZE
:
779 *params
= table
->IntensitySize
;
782 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetColorTableParameteriv(pname)" );
789 _mesa_init_colortable_dispatch(struct _glapi_table
*disp
)
791 SET_ColorSubTable(disp
, _mesa_ColorSubTable
);
792 SET_ColorTable(disp
, _mesa_ColorTable
);
793 SET_ColorTableParameterfv(disp
, _mesa_ColorTableParameterfv
);
794 SET_ColorTableParameteriv(disp
, _mesa_ColorTableParameteriv
);
795 SET_CopyColorSubTable(disp
, _mesa_CopyColorSubTable
);
796 SET_CopyColorTable(disp
, _mesa_CopyColorTable
);
797 SET_GetColorTable(disp
, _mesa_GetColorTable
);
798 SET_GetColorTableParameterfv(disp
, _mesa_GetColorTableParameterfv
);
799 SET_GetColorTableParameteriv(disp
, _mesa_GetColorTableParameteriv
);
801 /* GL_ARB_robustness */
802 SET_GetnColorTableARB(disp
, _mesa_GetnColorTableARB
);
806 #endif /* FEATURE_colortable */
809 /**********************************************************************/
810 /***** Initialization *****/
811 /**********************************************************************/
815 _mesa_init_colortable( struct gl_color_table
*p
)
820 p
->InternalFormat
= GL_RGBA
;
826 _mesa_free_colortable_data( struct gl_color_table
*p
)