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