mesa: Move src/mesa/glapi/dispatch.h to 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 "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_COLOR_MATRIX_RED_SCALE:
570 if (ctx->Pixel.PostColorMatrixScale[0] == param)
571 return;
572 FLUSH_VERTICES(ctx, _NEW_PIXEL);
573 ctx->Pixel.PostColorMatrixScale[0] = param;
574 break;
575 case GL_POST_COLOR_MATRIX_RED_BIAS:
576 if (ctx->Pixel.PostColorMatrixBias[0] == param)
577 return;
578 FLUSH_VERTICES(ctx, _NEW_PIXEL);
579 ctx->Pixel.PostColorMatrixBias[0] = param;
580 break;
581 case GL_POST_COLOR_MATRIX_GREEN_SCALE:
582 if (ctx->Pixel.PostColorMatrixScale[1] == param)
583 return;
584 FLUSH_VERTICES(ctx, _NEW_PIXEL);
585 ctx->Pixel.PostColorMatrixScale[1] = param;
586 break;
587 case GL_POST_COLOR_MATRIX_GREEN_BIAS:
588 if (ctx->Pixel.PostColorMatrixBias[1] == param)
589 return;
590 FLUSH_VERTICES(ctx, _NEW_PIXEL);
591 ctx->Pixel.PostColorMatrixBias[1] = param;
592 break;
593 case GL_POST_COLOR_MATRIX_BLUE_SCALE:
594 if (ctx->Pixel.PostColorMatrixScale[2] == param)
595 return;
596 FLUSH_VERTICES(ctx, _NEW_PIXEL);
597 ctx->Pixel.PostColorMatrixScale[2] = param;
598 break;
599 case GL_POST_COLOR_MATRIX_BLUE_BIAS:
600 if (ctx->Pixel.PostColorMatrixBias[2] == param)
601 return;
602 FLUSH_VERTICES(ctx, _NEW_PIXEL);
603 ctx->Pixel.PostColorMatrixBias[2] = param;
604 break;
605 case GL_POST_COLOR_MATRIX_ALPHA_SCALE:
606 if (ctx->Pixel.PostColorMatrixScale[3] == param)
607 return;
608 FLUSH_VERTICES(ctx, _NEW_PIXEL);
609 ctx->Pixel.PostColorMatrixScale[3] = param;
610 break;
611 case GL_POST_COLOR_MATRIX_ALPHA_BIAS:
612 if (ctx->Pixel.PostColorMatrixBias[3] == param)
613 return;
614 FLUSH_VERTICES(ctx, _NEW_PIXEL);
615 ctx->Pixel.PostColorMatrixBias[3] = param;
616 break;
617 case GL_POST_CONVOLUTION_RED_SCALE:
618 if (ctx->Pixel.PostConvolutionScale[0] == param)
619 return;
620 FLUSH_VERTICES(ctx, _NEW_PIXEL);
621 ctx->Pixel.PostConvolutionScale[0] = param;
622 break;
623 case GL_POST_CONVOLUTION_RED_BIAS:
624 if (ctx->Pixel.PostConvolutionBias[0] == param)
625 return;
626 FLUSH_VERTICES(ctx, _NEW_PIXEL);
627 ctx->Pixel.PostConvolutionBias[0] = param;
628 break;
629 case GL_POST_CONVOLUTION_GREEN_SCALE:
630 if (ctx->Pixel.PostConvolutionScale[1] == param)
631 return;
632 FLUSH_VERTICES(ctx, _NEW_PIXEL);
633 ctx->Pixel.PostConvolutionScale[1] = param;
634 break;
635 case GL_POST_CONVOLUTION_GREEN_BIAS:
636 if (ctx->Pixel.PostConvolutionBias[1] == param)
637 return;
638 FLUSH_VERTICES(ctx, _NEW_PIXEL);
639 ctx->Pixel.PostConvolutionBias[1] = param;
640 break;
641 case GL_POST_CONVOLUTION_BLUE_SCALE:
642 if (ctx->Pixel.PostConvolutionScale[2] == param)
643 return;
644 FLUSH_VERTICES(ctx, _NEW_PIXEL);
645 ctx->Pixel.PostConvolutionScale[2] = param;
646 break;
647 case GL_POST_CONVOLUTION_BLUE_BIAS:
648 if (ctx->Pixel.PostConvolutionBias[2] == param)
649 return;
650 FLUSH_VERTICES(ctx, _NEW_PIXEL);
651 ctx->Pixel.PostConvolutionBias[2] = param;
652 break;
653 case GL_POST_CONVOLUTION_ALPHA_SCALE:
654 if (ctx->Pixel.PostConvolutionScale[3] == param)
655 return;
656 FLUSH_VERTICES(ctx, _NEW_PIXEL);
657 ctx->Pixel.PostConvolutionScale[3] = param;
658 break;
659 case GL_POST_CONVOLUTION_ALPHA_BIAS:
660 if (ctx->Pixel.PostConvolutionBias[3] == param)
661 return;
662 FLUSH_VERTICES(ctx, _NEW_PIXEL);
663 ctx->Pixel.PostConvolutionBias[3] = param;
664 break;
665 default:
666 _mesa_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
667 return;
668 }
669 }
670
671
672 static void GLAPIENTRY
673 _mesa_PixelTransferi( GLenum pname, GLint param )
674 {
675 _mesa_PixelTransferf( pname, (GLfloat) param );
676 }
677
678
679
680 /**********************************************************************/
681 /***** State Management *****/
682 /**********************************************************************/
683
684 /*
685 * Return a bitmask of IMAGE_*_BIT flags which to indicate which
686 * pixel transfer operations are enabled.
687 */
688 static void
689 update_image_transfer_state(GLcontext *ctx)
690 {
691 GLuint mask = 0;
692
693 if (ctx->Pixel.RedScale != 1.0F || ctx->Pixel.RedBias != 0.0F ||
694 ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F ||
695 ctx->Pixel.BlueScale != 1.0F || ctx->Pixel.BlueBias != 0.0F ||
696 ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F)
697 mask |= IMAGE_SCALE_BIAS_BIT;
698
699 if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset)
700 mask |= IMAGE_SHIFT_OFFSET_BIT;
701
702 if (ctx->Pixel.MapColorFlag)
703 mask |= IMAGE_MAP_COLOR_BIT;
704
705 if (ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION])
706 mask |= IMAGE_COLOR_TABLE_BIT;
707
708 if (ctx->Pixel.Convolution1DEnabled ||
709 ctx->Pixel.Convolution2DEnabled ||
710 ctx->Pixel.Separable2DEnabled) {
711 mask |= IMAGE_CONVOLUTION_BIT;
712 if (ctx->Pixel.PostConvolutionScale[0] != 1.0F ||
713 ctx->Pixel.PostConvolutionScale[1] != 1.0F ||
714 ctx->Pixel.PostConvolutionScale[2] != 1.0F ||
715 ctx->Pixel.PostConvolutionScale[3] != 1.0F ||
716 ctx->Pixel.PostConvolutionBias[0] != 0.0F ||
717 ctx->Pixel.PostConvolutionBias[1] != 0.0F ||
718 ctx->Pixel.PostConvolutionBias[2] != 0.0F ||
719 ctx->Pixel.PostConvolutionBias[3] != 0.0F) {
720 mask |= IMAGE_POST_CONVOLUTION_SCALE_BIAS;
721 }
722 }
723
724 if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION])
725 mask |= IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT;
726
727 if (ctx->ColorMatrixStack.Top->type != MATRIX_IDENTITY ||
728 ctx->Pixel.PostColorMatrixScale[0] != 1.0F ||
729 ctx->Pixel.PostColorMatrixBias[0] != 0.0F ||
730 ctx->Pixel.PostColorMatrixScale[1] != 1.0F ||
731 ctx->Pixel.PostColorMatrixBias[1] != 0.0F ||
732 ctx->Pixel.PostColorMatrixScale[2] != 1.0F ||
733 ctx->Pixel.PostColorMatrixBias[2] != 0.0F ||
734 ctx->Pixel.PostColorMatrixScale[3] != 1.0F ||
735 ctx->Pixel.PostColorMatrixBias[3] != 0.0F)
736 mask |= IMAGE_COLOR_MATRIX_BIT;
737
738 if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX])
739 mask |= IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT;
740
741 if (ctx->Pixel.HistogramEnabled)
742 mask |= IMAGE_HISTOGRAM_BIT;
743
744 if (ctx->Pixel.MinMaxEnabled)
745 mask |= IMAGE_MIN_MAX_BIT;
746
747 ctx->_ImageTransferState = mask;
748 }
749
750
751 /**
752 * Update mesa pixel transfer derived state.
753 */
754 void _mesa_update_pixel( GLcontext *ctx, GLuint new_state )
755 {
756 if (new_state & _NEW_COLOR_MATRIX)
757 _math_matrix_analyse( ctx->ColorMatrixStack.Top );
758
759 /* References ColorMatrix.type (derived above).
760 */
761 if (new_state & _MESA_NEW_TRANSFER_STATE)
762 update_image_transfer_state(ctx);
763 }
764
765
766 void
767 _mesa_init_pixel_dispatch(struct _glapi_table *disp)
768 {
769 SET_GetPixelMapfv(disp, _mesa_GetPixelMapfv);
770 SET_GetPixelMapuiv(disp, _mesa_GetPixelMapuiv);
771 SET_GetPixelMapusv(disp, _mesa_GetPixelMapusv);
772 SET_PixelMapfv(disp, _mesa_PixelMapfv);
773 SET_PixelMapuiv(disp, _mesa_PixelMapuiv);
774 SET_PixelMapusv(disp, _mesa_PixelMapusv);
775 SET_PixelTransferf(disp, _mesa_PixelTransferf);
776 SET_PixelTransferi(disp, _mesa_PixelTransferi);
777 SET_PixelZoom(disp, _mesa_PixelZoom);
778 }
779
780
781 #endif /* FEATURE_pixel_transfer */
782
783
784 /**********************************************************************/
785 /***** Initialization *****/
786 /**********************************************************************/
787
788 static void
789 init_pixelmap(struct gl_pixelmap *map)
790 {
791 map->Size = 1;
792 map->Map[0] = 0.0;
793 map->Map8[0] = 0;
794 }
795
796
797 /**
798 * Initialize the context's PIXEL attribute group.
799 */
800 void
801 _mesa_init_pixel( GLcontext *ctx )
802 {
803 int i;
804
805 /* Pixel group */
806 ctx->Pixel.RedBias = 0.0;
807 ctx->Pixel.RedScale = 1.0;
808 ctx->Pixel.GreenBias = 0.0;
809 ctx->Pixel.GreenScale = 1.0;
810 ctx->Pixel.BlueBias = 0.0;
811 ctx->Pixel.BlueScale = 1.0;
812 ctx->Pixel.AlphaBias = 0.0;
813 ctx->Pixel.AlphaScale = 1.0;
814 ctx->Pixel.DepthBias = 0.0;
815 ctx->Pixel.DepthScale = 1.0;
816 ctx->Pixel.IndexOffset = 0;
817 ctx->Pixel.IndexShift = 0;
818 ctx->Pixel.ZoomX = 1.0;
819 ctx->Pixel.ZoomY = 1.0;
820 ctx->Pixel.MapColorFlag = GL_FALSE;
821 ctx->Pixel.MapStencilFlag = GL_FALSE;
822 init_pixelmap(&ctx->PixelMaps.StoS);
823 init_pixelmap(&ctx->PixelMaps.ItoI);
824 init_pixelmap(&ctx->PixelMaps.ItoR);
825 init_pixelmap(&ctx->PixelMaps.ItoG);
826 init_pixelmap(&ctx->PixelMaps.ItoB);
827 init_pixelmap(&ctx->PixelMaps.ItoA);
828 init_pixelmap(&ctx->PixelMaps.RtoR);
829 init_pixelmap(&ctx->PixelMaps.GtoG);
830 init_pixelmap(&ctx->PixelMaps.BtoB);
831 init_pixelmap(&ctx->PixelMaps.AtoA);
832 ctx->Pixel.HistogramEnabled = GL_FALSE;
833 ctx->Pixel.MinMaxEnabled = GL_FALSE;
834 ASSIGN_4V(ctx->Pixel.PostColorMatrixScale, 1.0, 1.0, 1.0, 1.0);
835 ASSIGN_4V(ctx->Pixel.PostColorMatrixBias, 0.0, 0.0, 0.0, 0.0);
836 for (i = 0; i < COLORTABLE_MAX; i++) {
837 ASSIGN_4V(ctx->Pixel.ColorTableScale[i], 1.0, 1.0, 1.0, 1.0);
838 ASSIGN_4V(ctx->Pixel.ColorTableBias[i], 0.0, 0.0, 0.0, 0.0);
839 ctx->Pixel.ColorTableEnabled[i] = GL_FALSE;
840 }
841 ctx->Pixel.Convolution1DEnabled = GL_FALSE;
842 ctx->Pixel.Convolution2DEnabled = GL_FALSE;
843 ctx->Pixel.Separable2DEnabled = GL_FALSE;
844 for (i = 0; i < 3; i++) {
845 ASSIGN_4V(ctx->Pixel.ConvolutionBorderColor[i], 0.0, 0.0, 0.0, 0.0);
846 ctx->Pixel.ConvolutionBorderMode[i] = GL_REDUCE;
847 ASSIGN_4V(ctx->Pixel.ConvolutionFilterScale[i], 1.0, 1.0, 1.0, 1.0);
848 ASSIGN_4V(ctx->Pixel.ConvolutionFilterBias[i], 0.0, 0.0, 0.0, 0.0);
849 }
850 for (i = 0; i < MAX_CONVOLUTION_WIDTH * MAX_CONVOLUTION_WIDTH * 4; i++) {
851 ctx->Convolution1D.Filter[i] = 0.0;
852 ctx->Convolution2D.Filter[i] = 0.0;
853 ctx->Separable2D.Filter[i] = 0.0;
854 }
855 ASSIGN_4V(ctx->Pixel.PostConvolutionScale, 1.0, 1.0, 1.0, 1.0);
856 ASSIGN_4V(ctx->Pixel.PostConvolutionBias, 0.0, 0.0, 0.0, 0.0);
857 /* GL_SGI_texture_color_table */
858 ASSIGN_4V(ctx->Pixel.TextureColorTableScale, 1.0, 1.0, 1.0, 1.0);
859 ASSIGN_4V(ctx->Pixel.TextureColorTableBias, 0.0, 0.0, 0.0, 0.0);
860
861 if (ctx->Visual.doubleBufferMode) {
862 ctx->Pixel.ReadBuffer = GL_BACK;
863 }
864 else {
865 ctx->Pixel.ReadBuffer = GL_FRONT;
866 }
867
868 /* Miscellaneous */
869 ctx->_ImageTransferState = 0;
870 }