Merge commit 'origin/master' into gallium-0.2
[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 void GLAPIENTRY
140 _mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
141 {
142 GET_CURRENT_CONTEXT(ctx);
143 ASSERT_OUTSIDE_BEGIN_END(ctx);
144
145 /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
146 if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
147 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
148 return;
149 }
150
151 if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
152 /* test that mapsize is a power of two */
153 if (_mesa_bitcount((GLuint) mapsize) != 1) {
154 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
155 return;
156 }
157 }
158
159 FLUSH_VERTICES(ctx, _NEW_PIXEL);
160
161 if (ctx->Unpack.BufferObj->Name) {
162 /* unpack pixelmap from PBO */
163 GLubyte *buf;
164 /* Note, need to use DefaultPacking and Unpack's buffer object */
165 ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj;
166 if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
167 GL_INTENSITY, GL_FLOAT, values)) {
168 _mesa_error(ctx, GL_INVALID_OPERATION,
169 "glPixelMapfv(invalid PBO access)");
170 return;
171 }
172 /* restore */
173 ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
174 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
175 GL_READ_ONLY_ARB,
176 ctx->Unpack.BufferObj);
177 if (!buf) {
178 /* buffer is already mapped - that's an error */
179 _mesa_error(ctx, GL_INVALID_OPERATION,
180 "glPixelMapfv(PBO is mapped)");
181 return;
182 }
183 values = (const GLfloat *) ADD_POINTERS(buf, values);
184 }
185 else if (!values) {
186 return;
187 }
188
189 store_pixelmap(ctx, map, mapsize, values);
190
191 if (ctx->Unpack.BufferObj->Name) {
192 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
193 ctx->Unpack.BufferObj);
194 }
195 }
196
197
198 void GLAPIENTRY
199 _mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
200 {
201 GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
202 GET_CURRENT_CONTEXT(ctx);
203 ASSERT_OUTSIDE_BEGIN_END(ctx);
204
205 if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
206 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
207 return;
208 }
209
210 if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
211 /* test that mapsize is a power of two */
212 if (_mesa_bitcount((GLuint) mapsize) != 1) {
213 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
214 return;
215 }
216 }
217
218 FLUSH_VERTICES(ctx, _NEW_PIXEL);
219
220 if (ctx->Unpack.BufferObj->Name) {
221 /* unpack pixelmap from PBO */
222 GLubyte *buf;
223 /* Note, need to use DefaultPacking and Unpack's buffer object */
224 ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj;
225 if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
226 GL_INTENSITY, GL_UNSIGNED_INT, values)) {
227 _mesa_error(ctx, GL_INVALID_OPERATION,
228 "glPixelMapuiv(invalid PBO access)");
229 return;
230 }
231 /* restore */
232 ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
233 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
234 GL_READ_ONLY_ARB,
235 ctx->Unpack.BufferObj);
236 if (!buf) {
237 /* buffer is already mapped - that's an error */
238 _mesa_error(ctx, GL_INVALID_OPERATION,
239 "glPixelMapuiv(PBO is mapped)");
240 return;
241 }
242 values = (const GLuint *) ADD_POINTERS(buf, values);
243 }
244 else if (!values) {
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 if (ctx->Unpack.BufferObj->Name) {
263 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
264 ctx->Unpack.BufferObj);
265 }
266
267 store_pixelmap(ctx, map, mapsize, fvalues);
268 }
269
270
271 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_bitcount((GLuint) mapsize) != 1) {
286 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
287 return;
288 }
289 }
290
291 FLUSH_VERTICES(ctx, _NEW_PIXEL);
292
293 if (ctx->Unpack.BufferObj->Name) {
294 /* unpack pixelmap from PBO */
295 GLubyte *buf;
296 /* Note, need to use DefaultPacking and Unpack's buffer object */
297 ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj;
298 if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
299 GL_INTENSITY, GL_UNSIGNED_SHORT,
300 values)) {
301 _mesa_error(ctx, GL_INVALID_OPERATION,
302 "glPixelMapusv(invalid PBO access)");
303 return;
304 }
305 /* restore */
306 ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
307 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
308 GL_READ_ONLY_ARB,
309 ctx->Unpack.BufferObj);
310 if (!buf) {
311 /* buffer is already mapped - that's an error */
312 _mesa_error(ctx, GL_INVALID_OPERATION,
313 "glPixelMapusv(PBO is mapped)");
314 return;
315 }
316 values = (const GLushort *) ADD_POINTERS(buf, values);
317 }
318 else if (!values) {
319 return;
320 }
321
322 /* convert to floats */
323 if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
324 GLint i;
325 for (i = 0; i < mapsize; i++) {
326 fvalues[i] = (GLfloat) values[i];
327 }
328 }
329 else {
330 GLint i;
331 for (i = 0; i < mapsize; i++) {
332 fvalues[i] = USHORT_TO_FLOAT( values[i] );
333 }
334 }
335
336 if (ctx->Unpack.BufferObj->Name) {
337 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
338 ctx->Unpack.BufferObj);
339 }
340
341 store_pixelmap(ctx, map, mapsize, fvalues);
342 }
343
344
345 void GLAPIENTRY
346 _mesa_GetPixelMapfv( GLenum map, GLfloat *values )
347 {
348 GET_CURRENT_CONTEXT(ctx);
349 GLuint mapsize, i;
350 const struct gl_pixelmap *pm;
351
352 ASSERT_OUTSIDE_BEGIN_END(ctx);
353
354 pm = get_pixelmap(ctx, map);
355 if (!pm) {
356 _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapfv(map)");
357 return;
358 }
359
360 mapsize = pm->Size;
361
362 if (ctx->Pack.BufferObj->Name) {
363 /* pack pixelmap into PBO */
364 GLubyte *buf;
365 /* Note, need to use DefaultPacking and Pack's buffer object */
366 ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj;
367 if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
368 GL_INTENSITY, GL_FLOAT, values)) {
369 _mesa_error(ctx, GL_INVALID_OPERATION,
370 "glGetPixelMapfv(invalid PBO access)");
371 return;
372 }
373 /* restore */
374 ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
375 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
376 GL_WRITE_ONLY_ARB,
377 ctx->Pack.BufferObj);
378 if (!buf) {
379 /* buffer is already mapped - that's an error */
380 _mesa_error(ctx, GL_INVALID_OPERATION,
381 "glGetPixelMapfv(PBO is mapped)");
382 return;
383 }
384 values = (GLfloat *) ADD_POINTERS(buf, values);
385 }
386 else if (!values) {
387 return;
388 }
389
390 if (map == GL_PIXEL_MAP_S_TO_S) {
391 /* special case */
392 for (i = 0; i < mapsize; i++) {
393 values[i] = (GLfloat) ctx->PixelMaps.StoS.Map[i];
394 }
395 }
396 else {
397 MEMCPY(values, pm->Map, mapsize * sizeof(GLfloat));
398 }
399
400 if (ctx->Pack.BufferObj->Name) {
401 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
402 ctx->Pack.BufferObj);
403 }
404 }
405
406
407 void GLAPIENTRY
408 _mesa_GetPixelMapuiv( GLenum map, GLuint *values )
409 {
410 GET_CURRENT_CONTEXT(ctx);
411 GLint mapsize, i;
412 const struct gl_pixelmap *pm;
413
414 ASSERT_OUTSIDE_BEGIN_END(ctx);
415
416 pm = get_pixelmap(ctx, map);
417 if (!pm) {
418 _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapuiv(map)");
419 return;
420 }
421 mapsize = pm->Size;
422
423 if (ctx->Pack.BufferObj->Name) {
424 /* pack pixelmap into PBO */
425 GLubyte *buf;
426 /* Note, need to use DefaultPacking and Pack's buffer object */
427 ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj;
428 if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
429 GL_INTENSITY, GL_UNSIGNED_INT, values)) {
430 _mesa_error(ctx, GL_INVALID_OPERATION,
431 "glGetPixelMapuiv(invalid PBO access)");
432 return;
433 }
434 /* restore */
435 ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
436 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
437 GL_WRITE_ONLY_ARB,
438 ctx->Pack.BufferObj);
439 if (!buf) {
440 /* buffer is already mapped - that's an error */
441 _mesa_error(ctx, GL_INVALID_OPERATION,
442 "glGetPixelMapuiv(PBO is mapped)");
443 return;
444 }
445 values = (GLuint *) ADD_POINTERS(buf, values);
446 }
447 else if (!values) {
448 return;
449 }
450
451 if (map == GL_PIXEL_MAP_S_TO_S) {
452 /* special case */
453 MEMCPY(values, ctx->PixelMaps.StoS.Map, mapsize * sizeof(GLint));
454 }
455 else {
456 for (i = 0; i < mapsize; i++) {
457 values[i] = FLOAT_TO_UINT( pm->Map[i] );
458 }
459 }
460
461 if (ctx->Pack.BufferObj->Name) {
462 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
463 ctx->Pack.BufferObj);
464 }
465 }
466
467
468 void GLAPIENTRY
469 _mesa_GetPixelMapusv( GLenum map, GLushort *values )
470 {
471 GET_CURRENT_CONTEXT(ctx);
472 GLint mapsize, i;
473 const struct gl_pixelmap *pm;
474
475 ASSERT_OUTSIDE_BEGIN_END(ctx);
476
477 pm = get_pixelmap(ctx, map);
478 if (!pm) {
479 _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapusv(map)");
480 return;
481 }
482 mapsize = pm ? pm->Size : 0;
483
484 if (ctx->Pack.BufferObj->Name) {
485 /* pack pixelmap into PBO */
486 GLubyte *buf;
487 /* Note, need to use DefaultPacking and Pack's buffer object */
488 ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj;
489 if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
490 GL_INTENSITY, GL_UNSIGNED_SHORT,
491 values)) {
492 _mesa_error(ctx, GL_INVALID_OPERATION,
493 "glGetPixelMapusv(invalid PBO access)");
494 return;
495 }
496 /* restore */
497 ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
498 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
499 GL_WRITE_ONLY_ARB,
500 ctx->Pack.BufferObj);
501 if (!buf) {
502 /* buffer is already mapped - that's an error */
503 _mesa_error(ctx, GL_INVALID_OPERATION,
504 "glGetPixelMapusv(PBO is mapped)");
505 return;
506 }
507 values = (GLushort *) ADD_POINTERS(buf, values);
508 }
509 else if (!values) {
510 return;
511 }
512
513 switch (map) {
514 /* special cases */
515 case GL_PIXEL_MAP_I_TO_I:
516 for (i = 0; i < mapsize; i++) {
517 values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0, 65535.);
518 }
519 break;
520 case GL_PIXEL_MAP_S_TO_S:
521 for (i = 0; i < mapsize; i++) {
522 values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0, 65535.);
523 }
524 break;
525 default:
526 for (i = 0; i < mapsize; i++) {
527 CLAMPED_FLOAT_TO_USHORT(values[i], pm->Map[i] );
528 }
529 }
530
531 if (ctx->Pack.BufferObj->Name) {
532 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
533 ctx->Pack.BufferObj);
534 }
535 }
536
537
538
539 /**********************************************************************/
540 /***** glPixelTransfer *****/
541 /**********************************************************************/
542
543
544 /*
545 * Implements glPixelTransfer[fi] whether called immediately or from a
546 * display list.
547 */
548 void GLAPIENTRY
549 _mesa_PixelTransferf( GLenum pname, GLfloat param )
550 {
551 GET_CURRENT_CONTEXT(ctx);
552 ASSERT_OUTSIDE_BEGIN_END(ctx);
553
554 switch (pname) {
555 case GL_MAP_COLOR:
556 if (ctx->Pixel.MapColorFlag == (param ? GL_TRUE : GL_FALSE))
557 return;
558 FLUSH_VERTICES(ctx, _NEW_PIXEL);
559 ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE;
560 break;
561 case GL_MAP_STENCIL:
562 if (ctx->Pixel.MapStencilFlag == (param ? GL_TRUE : GL_FALSE))
563 return;
564 FLUSH_VERTICES(ctx, _NEW_PIXEL);
565 ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE;
566 break;
567 case GL_INDEX_SHIFT:
568 if (ctx->Pixel.IndexShift == (GLint) param)
569 return;
570 FLUSH_VERTICES(ctx, _NEW_PIXEL);
571 ctx->Pixel.IndexShift = (GLint) param;
572 break;
573 case GL_INDEX_OFFSET:
574 if (ctx->Pixel.IndexOffset == (GLint) param)
575 return;
576 FLUSH_VERTICES(ctx, _NEW_PIXEL);
577 ctx->Pixel.IndexOffset = (GLint) param;
578 break;
579 case GL_RED_SCALE:
580 if (ctx->Pixel.RedScale == param)
581 return;
582 FLUSH_VERTICES(ctx, _NEW_PIXEL);
583 ctx->Pixel.RedScale = param;
584 break;
585 case GL_RED_BIAS:
586 if (ctx->Pixel.RedBias == param)
587 return;
588 FLUSH_VERTICES(ctx, _NEW_PIXEL);
589 ctx->Pixel.RedBias = param;
590 break;
591 case GL_GREEN_SCALE:
592 if (ctx->Pixel.GreenScale == param)
593 return;
594 FLUSH_VERTICES(ctx, _NEW_PIXEL);
595 ctx->Pixel.GreenScale = param;
596 break;
597 case GL_GREEN_BIAS:
598 if (ctx->Pixel.GreenBias == param)
599 return;
600 FLUSH_VERTICES(ctx, _NEW_PIXEL);
601 ctx->Pixel.GreenBias = param;
602 break;
603 case GL_BLUE_SCALE:
604 if (ctx->Pixel.BlueScale == param)
605 return;
606 FLUSH_VERTICES(ctx, _NEW_PIXEL);
607 ctx->Pixel.BlueScale = param;
608 break;
609 case GL_BLUE_BIAS:
610 if (ctx->Pixel.BlueBias == param)
611 return;
612 FLUSH_VERTICES(ctx, _NEW_PIXEL);
613 ctx->Pixel.BlueBias = param;
614 break;
615 case GL_ALPHA_SCALE:
616 if (ctx->Pixel.AlphaScale == param)
617 return;
618 FLUSH_VERTICES(ctx, _NEW_PIXEL);
619 ctx->Pixel.AlphaScale = param;
620 break;
621 case GL_ALPHA_BIAS:
622 if (ctx->Pixel.AlphaBias == param)
623 return;
624 FLUSH_VERTICES(ctx, _NEW_PIXEL);
625 ctx->Pixel.AlphaBias = param;
626 break;
627 case GL_DEPTH_SCALE:
628 if (ctx->Pixel.DepthScale == param)
629 return;
630 FLUSH_VERTICES(ctx, _NEW_PIXEL);
631 ctx->Pixel.DepthScale = param;
632 break;
633 case GL_DEPTH_BIAS:
634 if (ctx->Pixel.DepthBias == param)
635 return;
636 FLUSH_VERTICES(ctx, _NEW_PIXEL);
637 ctx->Pixel.DepthBias = param;
638 break;
639 case GL_POST_COLOR_MATRIX_RED_SCALE:
640 if (ctx->Pixel.PostColorMatrixScale[0] == param)
641 return;
642 FLUSH_VERTICES(ctx, _NEW_PIXEL);
643 ctx->Pixel.PostColorMatrixScale[0] = param;
644 break;
645 case GL_POST_COLOR_MATRIX_RED_BIAS:
646 if (ctx->Pixel.PostColorMatrixBias[0] == param)
647 return;
648 FLUSH_VERTICES(ctx, _NEW_PIXEL);
649 ctx->Pixel.PostColorMatrixBias[0] = param;
650 break;
651 case GL_POST_COLOR_MATRIX_GREEN_SCALE:
652 if (ctx->Pixel.PostColorMatrixScale[1] == param)
653 return;
654 FLUSH_VERTICES(ctx, _NEW_PIXEL);
655 ctx->Pixel.PostColorMatrixScale[1] = param;
656 break;
657 case GL_POST_COLOR_MATRIX_GREEN_BIAS:
658 if (ctx->Pixel.PostColorMatrixBias[1] == param)
659 return;
660 FLUSH_VERTICES(ctx, _NEW_PIXEL);
661 ctx->Pixel.PostColorMatrixBias[1] = param;
662 break;
663 case GL_POST_COLOR_MATRIX_BLUE_SCALE:
664 if (ctx->Pixel.PostColorMatrixScale[2] == param)
665 return;
666 FLUSH_VERTICES(ctx, _NEW_PIXEL);
667 ctx->Pixel.PostColorMatrixScale[2] = param;
668 break;
669 case GL_POST_COLOR_MATRIX_BLUE_BIAS:
670 if (ctx->Pixel.PostColorMatrixBias[2] == param)
671 return;
672 FLUSH_VERTICES(ctx, _NEW_PIXEL);
673 ctx->Pixel.PostColorMatrixBias[2] = param;
674 break;
675 case GL_POST_COLOR_MATRIX_ALPHA_SCALE:
676 if (ctx->Pixel.PostColorMatrixScale[3] == param)
677 return;
678 FLUSH_VERTICES(ctx, _NEW_PIXEL);
679 ctx->Pixel.PostColorMatrixScale[3] = param;
680 break;
681 case GL_POST_COLOR_MATRIX_ALPHA_BIAS:
682 if (ctx->Pixel.PostColorMatrixBias[3] == param)
683 return;
684 FLUSH_VERTICES(ctx, _NEW_PIXEL);
685 ctx->Pixel.PostColorMatrixBias[3] = param;
686 break;
687 case GL_POST_CONVOLUTION_RED_SCALE:
688 if (ctx->Pixel.PostConvolutionScale[0] == param)
689 return;
690 FLUSH_VERTICES(ctx, _NEW_PIXEL);
691 ctx->Pixel.PostConvolutionScale[0] = param;
692 break;
693 case GL_POST_CONVOLUTION_RED_BIAS:
694 if (ctx->Pixel.PostConvolutionBias[0] == param)
695 return;
696 FLUSH_VERTICES(ctx, _NEW_PIXEL);
697 ctx->Pixel.PostConvolutionBias[0] = param;
698 break;
699 case GL_POST_CONVOLUTION_GREEN_SCALE:
700 if (ctx->Pixel.PostConvolutionScale[1] == param)
701 return;
702 FLUSH_VERTICES(ctx, _NEW_PIXEL);
703 ctx->Pixel.PostConvolutionScale[1] = param;
704 break;
705 case GL_POST_CONVOLUTION_GREEN_BIAS:
706 if (ctx->Pixel.PostConvolutionBias[1] == param)
707 return;
708 FLUSH_VERTICES(ctx, _NEW_PIXEL);
709 ctx->Pixel.PostConvolutionBias[1] = param;
710 break;
711 case GL_POST_CONVOLUTION_BLUE_SCALE:
712 if (ctx->Pixel.PostConvolutionScale[2] == param)
713 return;
714 FLUSH_VERTICES(ctx, _NEW_PIXEL);
715 ctx->Pixel.PostConvolutionScale[2] = param;
716 break;
717 case GL_POST_CONVOLUTION_BLUE_BIAS:
718 if (ctx->Pixel.PostConvolutionBias[2] == param)
719 return;
720 FLUSH_VERTICES(ctx, _NEW_PIXEL);
721 ctx->Pixel.PostConvolutionBias[2] = param;
722 break;
723 case GL_POST_CONVOLUTION_ALPHA_SCALE:
724 if (ctx->Pixel.PostConvolutionScale[3] == param)
725 return;
726 FLUSH_VERTICES(ctx, _NEW_PIXEL);
727 ctx->Pixel.PostConvolutionScale[3] = param;
728 break;
729 case GL_POST_CONVOLUTION_ALPHA_BIAS:
730 if (ctx->Pixel.PostConvolutionBias[3] == param)
731 return;
732 FLUSH_VERTICES(ctx, _NEW_PIXEL);
733 ctx->Pixel.PostConvolutionBias[3] = param;
734 break;
735 default:
736 _mesa_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
737 return;
738 }
739 }
740
741
742 void GLAPIENTRY
743 _mesa_PixelTransferi( GLenum pname, GLint param )
744 {
745 _mesa_PixelTransferf( pname, (GLfloat) param );
746 }
747
748
749
750 /**********************************************************************/
751 /***** State Management *****/
752 /**********************************************************************/
753
754 /*
755 * Return a bitmask of IMAGE_*_BIT flags which to indicate which
756 * pixel transfer operations are enabled.
757 */
758 static void
759 update_image_transfer_state(GLcontext *ctx)
760 {
761 GLuint mask = 0;
762
763 if (ctx->Pixel.RedScale != 1.0F || ctx->Pixel.RedBias != 0.0F ||
764 ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F ||
765 ctx->Pixel.BlueScale != 1.0F || ctx->Pixel.BlueBias != 0.0F ||
766 ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F)
767 mask |= IMAGE_SCALE_BIAS_BIT;
768
769 if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset)
770 mask |= IMAGE_SHIFT_OFFSET_BIT;
771
772 if (ctx->Pixel.MapColorFlag)
773 mask |= IMAGE_MAP_COLOR_BIT;
774
775 if (ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION])
776 mask |= IMAGE_COLOR_TABLE_BIT;
777
778 if (ctx->Pixel.Convolution1DEnabled ||
779 ctx->Pixel.Convolution2DEnabled ||
780 ctx->Pixel.Separable2DEnabled) {
781 mask |= IMAGE_CONVOLUTION_BIT;
782 if (ctx->Pixel.PostConvolutionScale[0] != 1.0F ||
783 ctx->Pixel.PostConvolutionScale[1] != 1.0F ||
784 ctx->Pixel.PostConvolutionScale[2] != 1.0F ||
785 ctx->Pixel.PostConvolutionScale[3] != 1.0F ||
786 ctx->Pixel.PostConvolutionBias[0] != 0.0F ||
787 ctx->Pixel.PostConvolutionBias[1] != 0.0F ||
788 ctx->Pixel.PostConvolutionBias[2] != 0.0F ||
789 ctx->Pixel.PostConvolutionBias[3] != 0.0F) {
790 mask |= IMAGE_POST_CONVOLUTION_SCALE_BIAS;
791 }
792 }
793
794 if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION])
795 mask |= IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT;
796
797 if (ctx->ColorMatrixStack.Top->type != MATRIX_IDENTITY ||
798 ctx->Pixel.PostColorMatrixScale[0] != 1.0F ||
799 ctx->Pixel.PostColorMatrixBias[0] != 0.0F ||
800 ctx->Pixel.PostColorMatrixScale[1] != 1.0F ||
801 ctx->Pixel.PostColorMatrixBias[1] != 0.0F ||
802 ctx->Pixel.PostColorMatrixScale[2] != 1.0F ||
803 ctx->Pixel.PostColorMatrixBias[2] != 0.0F ||
804 ctx->Pixel.PostColorMatrixScale[3] != 1.0F ||
805 ctx->Pixel.PostColorMatrixBias[3] != 0.0F)
806 mask |= IMAGE_COLOR_MATRIX_BIT;
807
808 if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX])
809 mask |= IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT;
810
811 if (ctx->Pixel.HistogramEnabled)
812 mask |= IMAGE_HISTOGRAM_BIT;
813
814 if (ctx->Pixel.MinMaxEnabled)
815 mask |= IMAGE_MIN_MAX_BIT;
816
817 ctx->_ImageTransferState = mask;
818 }
819
820
821 /**
822 * Update meas pixel transfer derived state.
823 */
824 void _mesa_update_pixel( GLcontext *ctx, GLuint new_state )
825 {
826 if (new_state & _NEW_COLOR_MATRIX)
827 _math_matrix_analyse( ctx->ColorMatrixStack.Top );
828
829 /* References ColorMatrix.type (derived above).
830 */
831 if (new_state & _IMAGE_NEW_TRANSFER_STATE)
832 update_image_transfer_state(ctx);
833 }
834
835
836 /**********************************************************************/
837 /***** Initialization *****/
838 /**********************************************************************/
839
840 static void
841 init_pixelmap(struct gl_pixelmap *map)
842 {
843 map->Size = 1;
844 map->Map[0] = 0.0;
845 map->Map8[0] = 0;
846 }
847
848
849 /**
850 * Initialize the context's PIXEL attribute group.
851 */
852 void
853 _mesa_init_pixel( GLcontext *ctx )
854 {
855 int i;
856
857 /* Pixel group */
858 ctx->Pixel.RedBias = 0.0;
859 ctx->Pixel.RedScale = 1.0;
860 ctx->Pixel.GreenBias = 0.0;
861 ctx->Pixel.GreenScale = 1.0;
862 ctx->Pixel.BlueBias = 0.0;
863 ctx->Pixel.BlueScale = 1.0;
864 ctx->Pixel.AlphaBias = 0.0;
865 ctx->Pixel.AlphaScale = 1.0;
866 ctx->Pixel.DepthBias = 0.0;
867 ctx->Pixel.DepthScale = 1.0;
868 ctx->Pixel.IndexOffset = 0;
869 ctx->Pixel.IndexShift = 0;
870 ctx->Pixel.ZoomX = 1.0;
871 ctx->Pixel.ZoomY = 1.0;
872 ctx->Pixel.MapColorFlag = GL_FALSE;
873 ctx->Pixel.MapStencilFlag = GL_FALSE;
874 init_pixelmap(&ctx->PixelMaps.StoS);
875 init_pixelmap(&ctx->PixelMaps.ItoI);
876 init_pixelmap(&ctx->PixelMaps.ItoR);
877 init_pixelmap(&ctx->PixelMaps.ItoG);
878 init_pixelmap(&ctx->PixelMaps.ItoB);
879 init_pixelmap(&ctx->PixelMaps.ItoA);
880 init_pixelmap(&ctx->PixelMaps.RtoR);
881 init_pixelmap(&ctx->PixelMaps.GtoG);
882 init_pixelmap(&ctx->PixelMaps.BtoB);
883 init_pixelmap(&ctx->PixelMaps.AtoA);
884 ctx->Pixel.HistogramEnabled = GL_FALSE;
885 ctx->Pixel.MinMaxEnabled = GL_FALSE;
886 ASSIGN_4V(ctx->Pixel.PostColorMatrixScale, 1.0, 1.0, 1.0, 1.0);
887 ASSIGN_4V(ctx->Pixel.PostColorMatrixBias, 0.0, 0.0, 0.0, 0.0);
888 for (i = 0; i < COLORTABLE_MAX; i++) {
889 ASSIGN_4V(ctx->Pixel.ColorTableScale[i], 1.0, 1.0, 1.0, 1.0);
890 ASSIGN_4V(ctx->Pixel.ColorTableBias[i], 0.0, 0.0, 0.0, 0.0);
891 ctx->Pixel.ColorTableEnabled[i] = GL_FALSE;
892 }
893 ctx->Pixel.Convolution1DEnabled = GL_FALSE;
894 ctx->Pixel.Convolution2DEnabled = GL_FALSE;
895 ctx->Pixel.Separable2DEnabled = GL_FALSE;
896 for (i = 0; i < 3; i++) {
897 ASSIGN_4V(ctx->Pixel.ConvolutionBorderColor[i], 0.0, 0.0, 0.0, 0.0);
898 ctx->Pixel.ConvolutionBorderMode[i] = GL_REDUCE;
899 ASSIGN_4V(ctx->Pixel.ConvolutionFilterScale[i], 1.0, 1.0, 1.0, 1.0);
900 ASSIGN_4V(ctx->Pixel.ConvolutionFilterBias[i], 0.0, 0.0, 0.0, 0.0);
901 }
902 for (i = 0; i < MAX_CONVOLUTION_WIDTH * MAX_CONVOLUTION_WIDTH * 4; i++) {
903 ctx->Convolution1D.Filter[i] = 0.0;
904 ctx->Convolution2D.Filter[i] = 0.0;
905 ctx->Separable2D.Filter[i] = 0.0;
906 }
907 ASSIGN_4V(ctx->Pixel.PostConvolutionScale, 1.0, 1.0, 1.0, 1.0);
908 ASSIGN_4V(ctx->Pixel.PostConvolutionBias, 0.0, 0.0, 0.0, 0.0);
909 /* GL_SGI_texture_color_table */
910 ASSIGN_4V(ctx->Pixel.TextureColorTableScale, 1.0, 1.0, 1.0, 1.0);
911 ASSIGN_4V(ctx->Pixel.TextureColorTableBias, 0.0, 0.0, 0.0, 0.0);
912
913 if (ctx->Visual.doubleBufferMode) {
914 ctx->Pixel.ReadBuffer = GL_BACK;
915 }
916 else {
917 ctx->Pixel.ReadBuffer = GL_FRONT;
918 }
919
920 /* Miscellaneous */
921 ctx->_ImageTransferState = 0;
922 }