mesa: Remove SGI_color_matrix.
[mesa.git] / src / mesa / main / pixel.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.1
4 *
5 * Copyright (C) 1999-2008 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 /**
27 * \file pixel.c
28 * Pixel transfer functions (glPixelZoom, glPixelMap, glPixelTransfer)
29 */
30
31 #include "glheader.h"
32 #include "bufferobj.h"
33 #include "colormac.h"
34 #include "context.h"
35 #include "macros.h"
36 #include "pixel.h"
37 #include "mtypes.h"
38 #include "main/dispatch.h"
39
40
41 #if FEATURE_pixel_transfer
42
43
44 /**********************************************************************/
45 /***** glPixelZoom *****/
46 /**********************************************************************/
47
48 static void GLAPIENTRY
49 _mesa_PixelZoom( GLfloat xfactor, GLfloat yfactor )
50 {
51 GET_CURRENT_CONTEXT(ctx);
52
53 if (ctx->Pixel.ZoomX == xfactor &&
54 ctx->Pixel.ZoomY == yfactor)
55 return;
56
57 FLUSH_VERTICES(ctx, _NEW_PIXEL);
58 ctx->Pixel.ZoomX = xfactor;
59 ctx->Pixel.ZoomY = yfactor;
60 }
61
62
63
64 /**********************************************************************/
65 /***** glPixelMap *****/
66 /**********************************************************************/
67
68 /**
69 * Return pointer to a pixelmap by name.
70 */
71 static struct gl_pixelmap *
72 get_pixelmap(GLcontext *ctx, GLenum map)
73 {
74 switch (map) {
75 case GL_PIXEL_MAP_I_TO_I:
76 return &ctx->PixelMaps.ItoI;
77 case GL_PIXEL_MAP_S_TO_S:
78 return &ctx->PixelMaps.StoS;
79 case GL_PIXEL_MAP_I_TO_R:
80 return &ctx->PixelMaps.ItoR;
81 case GL_PIXEL_MAP_I_TO_G:
82 return &ctx->PixelMaps.ItoG;
83 case GL_PIXEL_MAP_I_TO_B:
84 return &ctx->PixelMaps.ItoB;
85 case GL_PIXEL_MAP_I_TO_A:
86 return &ctx->PixelMaps.ItoA;
87 case GL_PIXEL_MAP_R_TO_R:
88 return &ctx->PixelMaps.RtoR;
89 case GL_PIXEL_MAP_G_TO_G:
90 return &ctx->PixelMaps.GtoG;
91 case GL_PIXEL_MAP_B_TO_B:
92 return &ctx->PixelMaps.BtoB;
93 case GL_PIXEL_MAP_A_TO_A:
94 return &ctx->PixelMaps.AtoA;
95 default:
96 return NULL;
97 }
98 }
99
100
101 /**
102 * Helper routine used by the other _mesa_PixelMap() functions.
103 */
104 static void
105 store_pixelmap(GLcontext *ctx, GLenum map, GLsizei mapsize,
106 const GLfloat *values)
107 {
108 GLint i;
109 struct gl_pixelmap *pm = get_pixelmap(ctx, map);
110 if (!pm) {
111 _mesa_error(ctx, GL_INVALID_ENUM, "glPixelMap(map)");
112 return;
113 }
114
115 switch (map) {
116 case GL_PIXEL_MAP_S_TO_S:
117 /* special case */
118 ctx->PixelMaps.StoS.Size = mapsize;
119 for (i = 0; i < mapsize; i++) {
120 ctx->PixelMaps.StoS.Map[i] = (GLfloat)IROUND(values[i]);
121 }
122 break;
123 case GL_PIXEL_MAP_I_TO_I:
124 /* special case */
125 ctx->PixelMaps.ItoI.Size = mapsize;
126 for (i = 0; i < mapsize; i++) {
127 ctx->PixelMaps.ItoI.Map[i] = values[i];
128 }
129 break;
130 default:
131 /* general case */
132 pm->Size = mapsize;
133 for (i = 0; i < mapsize; i++) {
134 GLfloat val = CLAMP(values[i], 0.0F, 1.0F);
135 pm->Map[i] = val;
136 pm->Map8[i] = (GLint) (val * 255.0F);
137 }
138 }
139 }
140
141
142 /**
143 * Convenience wrapper for _mesa_validate_pbo_access() for gl[Get]PixelMap().
144 */
145 static GLboolean
146 validate_pbo_access(GLcontext *ctx, struct gl_pixelstore_attrib *pack,
147 GLsizei mapsize, GLenum format, GLenum type,
148 const GLvoid *ptr)
149 {
150 GLboolean ok;
151
152 /* Note, need to use DefaultPacking and Unpack's buffer object */
153 _mesa_reference_buffer_object(ctx,
154 &ctx->DefaultPacking.BufferObj,
155 pack->BufferObj);
156
157 ok = _mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
158 format, type, ptr);
159
160 /* restore */
161 _mesa_reference_buffer_object(ctx,
162 &ctx->DefaultPacking.BufferObj,
163 ctx->Shared->NullBufferObj);
164
165 if (!ok) {
166 _mesa_error(ctx, GL_INVALID_OPERATION,
167 "glPixelMap(invalid PBO access)");
168 }
169 return ok;
170 }
171
172
173 static void GLAPIENTRY
174 _mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
175 {
176 GET_CURRENT_CONTEXT(ctx);
177 ASSERT_OUTSIDE_BEGIN_END(ctx);
178
179 /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
180 if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
181 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
182 return;
183 }
184
185 if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
186 /* test that mapsize is a power of two */
187 if (!_mesa_is_pow_two(mapsize)) {
188 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
189 return;
190 }
191 }
192
193 FLUSH_VERTICES(ctx, _NEW_PIXEL);
194
195 if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
196 GL_INTENSITY, GL_FLOAT, values)) {
197 return;
198 }
199
200 values = (const GLfloat *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
201 if (!values) {
202 if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
203 _mesa_error(ctx, GL_INVALID_OPERATION,
204 "glPixelMapfv(PBO is mapped)");
205 }
206 return;
207 }
208
209 store_pixelmap(ctx, map, mapsize, values);
210
211 _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
212 }
213
214
215 static void GLAPIENTRY
216 _mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
217 {
218 GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
219 GET_CURRENT_CONTEXT(ctx);
220 ASSERT_OUTSIDE_BEGIN_END(ctx);
221
222 if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
223 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
224 return;
225 }
226
227 if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
228 /* test that mapsize is a power of two */
229 if (!_mesa_is_pow_two(mapsize)) {
230 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
231 return;
232 }
233 }
234
235 FLUSH_VERTICES(ctx, _NEW_PIXEL);
236
237 if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
238 GL_INTENSITY, GL_UNSIGNED_INT, values)) {
239 return;
240 }
241
242 values = (const GLuint *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
243 if (!values) {
244 if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
245 _mesa_error(ctx, GL_INVALID_OPERATION,
246 "glPixelMapuiv(PBO is mapped)");
247 }
248 return;
249 }
250
251 /* convert to floats */
252 if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
253 GLint i;
254 for (i = 0; i < mapsize; i++) {
255 fvalues[i] = (GLfloat) values[i];
256 }
257 }
258 else {
259 GLint i;
260 for (i = 0; i < mapsize; i++) {
261 fvalues[i] = UINT_TO_FLOAT( values[i] );
262 }
263 }
264
265 _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
266
267 store_pixelmap(ctx, map, mapsize, fvalues);
268 }
269
270
271 static void GLAPIENTRY
272 _mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values )
273 {
274 GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
275 GET_CURRENT_CONTEXT(ctx);
276 ASSERT_OUTSIDE_BEGIN_END(ctx);
277
278 if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
279 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapusv(mapsize)" );
280 return;
281 }
282
283 if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
284 /* test that mapsize is a power of two */
285 if (!_mesa_is_pow_two(mapsize)) {
286 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
287 return;
288 }
289 }
290
291 FLUSH_VERTICES(ctx, _NEW_PIXEL);
292
293 if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
294 GL_INTENSITY, GL_UNSIGNED_SHORT, values)) {
295 return;
296 }
297
298 values = (const GLushort *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
299 if (!values) {
300 if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
301 _mesa_error(ctx, GL_INVALID_OPERATION,
302 "glPixelMapusv(PBO is mapped)");
303 }
304 return;
305 }
306
307 /* convert to floats */
308 if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
309 GLint i;
310 for (i = 0; i < mapsize; i++) {
311 fvalues[i] = (GLfloat) values[i];
312 }
313 }
314 else {
315 GLint i;
316 for (i = 0; i < mapsize; i++) {
317 fvalues[i] = USHORT_TO_FLOAT( values[i] );
318 }
319 }
320
321 _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
322
323 store_pixelmap(ctx, map, mapsize, fvalues);
324 }
325
326
327 static void GLAPIENTRY
328 _mesa_GetPixelMapfv( GLenum map, GLfloat *values )
329 {
330 GET_CURRENT_CONTEXT(ctx);
331 GLuint mapsize, i;
332 const struct gl_pixelmap *pm;
333
334 ASSERT_OUTSIDE_BEGIN_END(ctx);
335
336 pm = get_pixelmap(ctx, map);
337 if (!pm) {
338 _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapfv(map)");
339 return;
340 }
341
342 mapsize = pm->Size;
343
344 if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
345 GL_INTENSITY, GL_FLOAT, values)) {
346 return;
347 }
348
349 values = (GLfloat *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
350 if (!values) {
351 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
352 _mesa_error(ctx, GL_INVALID_OPERATION,
353 "glGetPixelMapfv(PBO is mapped)");
354 }
355 return;
356 }
357
358 if (map == GL_PIXEL_MAP_S_TO_S) {
359 /* special case */
360 for (i = 0; i < mapsize; i++) {
361 values[i] = (GLfloat) ctx->PixelMaps.StoS.Map[i];
362 }
363 }
364 else {
365 memcpy(values, pm->Map, mapsize * sizeof(GLfloat));
366 }
367
368 _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
369 }
370
371
372 static void GLAPIENTRY
373 _mesa_GetPixelMapuiv( GLenum map, GLuint *values )
374 {
375 GET_CURRENT_CONTEXT(ctx);
376 GLint mapsize, i;
377 const struct gl_pixelmap *pm;
378
379 ASSERT_OUTSIDE_BEGIN_END(ctx);
380
381 pm = get_pixelmap(ctx, map);
382 if (!pm) {
383 _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapuiv(map)");
384 return;
385 }
386 mapsize = pm->Size;
387
388 if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
389 GL_INTENSITY, GL_UNSIGNED_INT, values)) {
390 return;
391 }
392
393 values = (GLuint *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
394 if (!values) {
395 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
396 _mesa_error(ctx, GL_INVALID_OPERATION,
397 "glGetPixelMapuiv(PBO is mapped)");
398 }
399 return;
400 }
401
402 if (map == GL_PIXEL_MAP_S_TO_S) {
403 /* special case */
404 memcpy(values, ctx->PixelMaps.StoS.Map, mapsize * sizeof(GLint));
405 }
406 else {
407 for (i = 0; i < mapsize; i++) {
408 values[i] = FLOAT_TO_UINT( pm->Map[i] );
409 }
410 }
411
412 _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
413 }
414
415
416 static void GLAPIENTRY
417 _mesa_GetPixelMapusv( GLenum map, GLushort *values )
418 {
419 GET_CURRENT_CONTEXT(ctx);
420 GLint mapsize, i;
421 const struct gl_pixelmap *pm;
422
423 ASSERT_OUTSIDE_BEGIN_END(ctx);
424
425 pm = get_pixelmap(ctx, map);
426 if (!pm) {
427 _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapusv(map)");
428 return;
429 }
430 mapsize = pm->Size;
431
432 if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
433 GL_INTENSITY, GL_UNSIGNED_SHORT, values)) {
434 return;
435 }
436
437 values = (GLushort *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
438 if (!values) {
439 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
440 _mesa_error(ctx, GL_INVALID_OPERATION,
441 "glGetPixelMapusv(PBO is mapped)");
442 }
443 return;
444 }
445
446 switch (map) {
447 /* special cases */
448 case GL_PIXEL_MAP_I_TO_I:
449 for (i = 0; i < mapsize; i++) {
450 values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0, 65535.);
451 }
452 break;
453 case GL_PIXEL_MAP_S_TO_S:
454 for (i = 0; i < mapsize; i++) {
455 values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0, 65535.);
456 }
457 break;
458 default:
459 for (i = 0; i < mapsize; i++) {
460 CLAMPED_FLOAT_TO_USHORT(values[i], pm->Map[i] );
461 }
462 }
463
464 _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
465 }
466
467
468
469 /**********************************************************************/
470 /***** glPixelTransfer *****/
471 /**********************************************************************/
472
473
474 /*
475 * Implements glPixelTransfer[fi] whether called immediately or from a
476 * display list.
477 */
478 static void GLAPIENTRY
479 _mesa_PixelTransferf( GLenum pname, GLfloat param )
480 {
481 GET_CURRENT_CONTEXT(ctx);
482 ASSERT_OUTSIDE_BEGIN_END(ctx);
483
484 switch (pname) {
485 case GL_MAP_COLOR:
486 if (ctx->Pixel.MapColorFlag == (param ? GL_TRUE : GL_FALSE))
487 return;
488 FLUSH_VERTICES(ctx, _NEW_PIXEL);
489 ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE;
490 break;
491 case GL_MAP_STENCIL:
492 if (ctx->Pixel.MapStencilFlag == (param ? GL_TRUE : GL_FALSE))
493 return;
494 FLUSH_VERTICES(ctx, _NEW_PIXEL);
495 ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE;
496 break;
497 case GL_INDEX_SHIFT:
498 if (ctx->Pixel.IndexShift == (GLint) param)
499 return;
500 FLUSH_VERTICES(ctx, _NEW_PIXEL);
501 ctx->Pixel.IndexShift = (GLint) param;
502 break;
503 case GL_INDEX_OFFSET:
504 if (ctx->Pixel.IndexOffset == (GLint) param)
505 return;
506 FLUSH_VERTICES(ctx, _NEW_PIXEL);
507 ctx->Pixel.IndexOffset = (GLint) param;
508 break;
509 case GL_RED_SCALE:
510 if (ctx->Pixel.RedScale == param)
511 return;
512 FLUSH_VERTICES(ctx, _NEW_PIXEL);
513 ctx->Pixel.RedScale = param;
514 break;
515 case GL_RED_BIAS:
516 if (ctx->Pixel.RedBias == param)
517 return;
518 FLUSH_VERTICES(ctx, _NEW_PIXEL);
519 ctx->Pixel.RedBias = param;
520 break;
521 case GL_GREEN_SCALE:
522 if (ctx->Pixel.GreenScale == param)
523 return;
524 FLUSH_VERTICES(ctx, _NEW_PIXEL);
525 ctx->Pixel.GreenScale = param;
526 break;
527 case GL_GREEN_BIAS:
528 if (ctx->Pixel.GreenBias == param)
529 return;
530 FLUSH_VERTICES(ctx, _NEW_PIXEL);
531 ctx->Pixel.GreenBias = param;
532 break;
533 case GL_BLUE_SCALE:
534 if (ctx->Pixel.BlueScale == param)
535 return;
536 FLUSH_VERTICES(ctx, _NEW_PIXEL);
537 ctx->Pixel.BlueScale = param;
538 break;
539 case GL_BLUE_BIAS:
540 if (ctx->Pixel.BlueBias == param)
541 return;
542 FLUSH_VERTICES(ctx, _NEW_PIXEL);
543 ctx->Pixel.BlueBias = param;
544 break;
545 case GL_ALPHA_SCALE:
546 if (ctx->Pixel.AlphaScale == param)
547 return;
548 FLUSH_VERTICES(ctx, _NEW_PIXEL);
549 ctx->Pixel.AlphaScale = param;
550 break;
551 case GL_ALPHA_BIAS:
552 if (ctx->Pixel.AlphaBias == param)
553 return;
554 FLUSH_VERTICES(ctx, _NEW_PIXEL);
555 ctx->Pixel.AlphaBias = param;
556 break;
557 case GL_DEPTH_SCALE:
558 if (ctx->Pixel.DepthScale == param)
559 return;
560 FLUSH_VERTICES(ctx, _NEW_PIXEL);
561 ctx->Pixel.DepthScale = param;
562 break;
563 case GL_DEPTH_BIAS:
564 if (ctx->Pixel.DepthBias == param)
565 return;
566 FLUSH_VERTICES(ctx, _NEW_PIXEL);
567 ctx->Pixel.DepthBias = param;
568 break;
569 case GL_POST_CONVOLUTION_RED_SCALE:
570 if (ctx->Pixel.PostConvolutionScale[0] == param)
571 return;
572 FLUSH_VERTICES(ctx, _NEW_PIXEL);
573 ctx->Pixel.PostConvolutionScale[0] = param;
574 break;
575 case GL_POST_CONVOLUTION_RED_BIAS:
576 if (ctx->Pixel.PostConvolutionBias[0] == param)
577 return;
578 FLUSH_VERTICES(ctx, _NEW_PIXEL);
579 ctx->Pixel.PostConvolutionBias[0] = param;
580 break;
581 case GL_POST_CONVOLUTION_GREEN_SCALE:
582 if (ctx->Pixel.PostConvolutionScale[1] == param)
583 return;
584 FLUSH_VERTICES(ctx, _NEW_PIXEL);
585 ctx->Pixel.PostConvolutionScale[1] = param;
586 break;
587 case GL_POST_CONVOLUTION_GREEN_BIAS:
588 if (ctx->Pixel.PostConvolutionBias[1] == param)
589 return;
590 FLUSH_VERTICES(ctx, _NEW_PIXEL);
591 ctx->Pixel.PostConvolutionBias[1] = param;
592 break;
593 case GL_POST_CONVOLUTION_BLUE_SCALE:
594 if (ctx->Pixel.PostConvolutionScale[2] == param)
595 return;
596 FLUSH_VERTICES(ctx, _NEW_PIXEL);
597 ctx->Pixel.PostConvolutionScale[2] = param;
598 break;
599 case GL_POST_CONVOLUTION_BLUE_BIAS:
600 if (ctx->Pixel.PostConvolutionBias[2] == param)
601 return;
602 FLUSH_VERTICES(ctx, _NEW_PIXEL);
603 ctx->Pixel.PostConvolutionBias[2] = param;
604 break;
605 case GL_POST_CONVOLUTION_ALPHA_SCALE:
606 if (ctx->Pixel.PostConvolutionScale[3] == param)
607 return;
608 FLUSH_VERTICES(ctx, _NEW_PIXEL);
609 ctx->Pixel.PostConvolutionScale[3] = param;
610 break;
611 case GL_POST_CONVOLUTION_ALPHA_BIAS:
612 if (ctx->Pixel.PostConvolutionBias[3] == param)
613 return;
614 FLUSH_VERTICES(ctx, _NEW_PIXEL);
615 ctx->Pixel.PostConvolutionBias[3] = param;
616 break;
617 default:
618 _mesa_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
619 return;
620 }
621 }
622
623
624 static void GLAPIENTRY
625 _mesa_PixelTransferi( GLenum pname, GLint param )
626 {
627 _mesa_PixelTransferf( pname, (GLfloat) param );
628 }
629
630
631
632 /**********************************************************************/
633 /***** State Management *****/
634 /**********************************************************************/
635
636 /*
637 * Return a bitmask of IMAGE_*_BIT flags which to indicate which
638 * pixel transfer operations are enabled.
639 */
640 static void
641 update_image_transfer_state(GLcontext *ctx)
642 {
643 GLuint mask = 0;
644
645 if (ctx->Pixel.RedScale != 1.0F || ctx->Pixel.RedBias != 0.0F ||
646 ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F ||
647 ctx->Pixel.BlueScale != 1.0F || ctx->Pixel.BlueBias != 0.0F ||
648 ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F)
649 mask |= IMAGE_SCALE_BIAS_BIT;
650
651 if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset)
652 mask |= IMAGE_SHIFT_OFFSET_BIT;
653
654 if (ctx->Pixel.MapColorFlag)
655 mask |= IMAGE_MAP_COLOR_BIT;
656
657 if (ctx->Pixel.Convolution1DEnabled ||
658 ctx->Pixel.Convolution2DEnabled ||
659 ctx->Pixel.Separable2DEnabled) {
660 mask |= IMAGE_CONVOLUTION_BIT;
661 if (ctx->Pixel.PostConvolutionScale[0] != 1.0F ||
662 ctx->Pixel.PostConvolutionScale[1] != 1.0F ||
663 ctx->Pixel.PostConvolutionScale[2] != 1.0F ||
664 ctx->Pixel.PostConvolutionScale[3] != 1.0F ||
665 ctx->Pixel.PostConvolutionBias[0] != 0.0F ||
666 ctx->Pixel.PostConvolutionBias[1] != 0.0F ||
667 ctx->Pixel.PostConvolutionBias[2] != 0.0F ||
668 ctx->Pixel.PostConvolutionBias[3] != 0.0F) {
669 mask |= IMAGE_POST_CONVOLUTION_SCALE_BIAS;
670 }
671 }
672
673 ctx->_ImageTransferState = mask;
674 }
675
676
677 /**
678 * Update mesa pixel transfer derived state.
679 */
680 void _mesa_update_pixel( GLcontext *ctx, GLuint new_state )
681 {
682 if (new_state & _MESA_NEW_TRANSFER_STATE)
683 update_image_transfer_state(ctx);
684 }
685
686
687 void
688 _mesa_init_pixel_dispatch(struct _glapi_table *disp)
689 {
690 SET_GetPixelMapfv(disp, _mesa_GetPixelMapfv);
691 SET_GetPixelMapuiv(disp, _mesa_GetPixelMapuiv);
692 SET_GetPixelMapusv(disp, _mesa_GetPixelMapusv);
693 SET_PixelMapfv(disp, _mesa_PixelMapfv);
694 SET_PixelMapuiv(disp, _mesa_PixelMapuiv);
695 SET_PixelMapusv(disp, _mesa_PixelMapusv);
696 SET_PixelTransferf(disp, _mesa_PixelTransferf);
697 SET_PixelTransferi(disp, _mesa_PixelTransferi);
698 SET_PixelZoom(disp, _mesa_PixelZoom);
699 }
700
701
702 #endif /* FEATURE_pixel_transfer */
703
704
705 /**********************************************************************/
706 /***** Initialization *****/
707 /**********************************************************************/
708
709 static void
710 init_pixelmap(struct gl_pixelmap *map)
711 {
712 map->Size = 1;
713 map->Map[0] = 0.0;
714 map->Map8[0] = 0;
715 }
716
717
718 /**
719 * Initialize the context's PIXEL attribute group.
720 */
721 void
722 _mesa_init_pixel( GLcontext *ctx )
723 {
724 int i;
725
726 /* Pixel group */
727 ctx->Pixel.RedBias = 0.0;
728 ctx->Pixel.RedScale = 1.0;
729 ctx->Pixel.GreenBias = 0.0;
730 ctx->Pixel.GreenScale = 1.0;
731 ctx->Pixel.BlueBias = 0.0;
732 ctx->Pixel.BlueScale = 1.0;
733 ctx->Pixel.AlphaBias = 0.0;
734 ctx->Pixel.AlphaScale = 1.0;
735 ctx->Pixel.DepthBias = 0.0;
736 ctx->Pixel.DepthScale = 1.0;
737 ctx->Pixel.IndexOffset = 0;
738 ctx->Pixel.IndexShift = 0;
739 ctx->Pixel.ZoomX = 1.0;
740 ctx->Pixel.ZoomY = 1.0;
741 ctx->Pixel.MapColorFlag = GL_FALSE;
742 ctx->Pixel.MapStencilFlag = GL_FALSE;
743 init_pixelmap(&ctx->PixelMaps.StoS);
744 init_pixelmap(&ctx->PixelMaps.ItoI);
745 init_pixelmap(&ctx->PixelMaps.ItoR);
746 init_pixelmap(&ctx->PixelMaps.ItoG);
747 init_pixelmap(&ctx->PixelMaps.ItoB);
748 init_pixelmap(&ctx->PixelMaps.ItoA);
749 init_pixelmap(&ctx->PixelMaps.RtoR);
750 init_pixelmap(&ctx->PixelMaps.GtoG);
751 init_pixelmap(&ctx->PixelMaps.BtoB);
752 init_pixelmap(&ctx->PixelMaps.AtoA);
753 ctx->Pixel.Convolution1DEnabled = GL_FALSE;
754 ctx->Pixel.Convolution2DEnabled = GL_FALSE;
755 ctx->Pixel.Separable2DEnabled = GL_FALSE;
756 for (i = 0; i < 3; i++) {
757 ASSIGN_4V(ctx->Pixel.ConvolutionBorderColor[i], 0.0, 0.0, 0.0, 0.0);
758 ctx->Pixel.ConvolutionBorderMode[i] = GL_REDUCE;
759 ASSIGN_4V(ctx->Pixel.ConvolutionFilterScale[i], 1.0, 1.0, 1.0, 1.0);
760 ASSIGN_4V(ctx->Pixel.ConvolutionFilterBias[i], 0.0, 0.0, 0.0, 0.0);
761 }
762 for (i = 0; i < MAX_CONVOLUTION_WIDTH * MAX_CONVOLUTION_WIDTH * 4; i++) {
763 ctx->Convolution1D.Filter[i] = 0.0;
764 ctx->Convolution2D.Filter[i] = 0.0;
765 ctx->Separable2D.Filter[i] = 0.0;
766 }
767 ASSIGN_4V(ctx->Pixel.PostConvolutionScale, 1.0, 1.0, 1.0, 1.0);
768 ASSIGN_4V(ctx->Pixel.PostConvolutionBias, 0.0, 0.0, 0.0, 0.0);
769 /* GL_SGI_texture_color_table */
770 ASSIGN_4V(ctx->Pixel.TextureColorTableScale, 1.0, 1.0, 1.0, 1.0);
771 ASSIGN_4V(ctx->Pixel.TextureColorTableBias, 0.0, 0.0, 0.0, 0.0);
772
773 if (ctx->Visual.doubleBufferMode) {
774 ctx->Pixel.ReadBuffer = GL_BACK;
775 }
776 else {
777 ctx->Pixel.ReadBuffer = GL_FRONT;
778 }
779
780 /* Miscellaneous */
781 ctx->_ImageTransferState = 0;
782 }