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