merge from master
[mesa.git] / src / mesa / main / pixel.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.3
4 *
5 * Copyright (C) 1999-2007 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 #include "glheader.h"
26 #include "bufferobj.h"
27 #include "colormac.h"
28 #include "context.h"
29 #include "image.h"
30 #include "macros.h"
31 #include "pixel.h"
32 #include "mtypes.h"
33
34
35 /**********************************************************************/
36 /***** glPixelZoom *****/
37 /**********************************************************************/
38
39
40
41 void GLAPIENTRY
42 _mesa_PixelZoom( GLfloat xfactor, GLfloat yfactor )
43 {
44 GET_CURRENT_CONTEXT(ctx);
45
46 if (ctx->Pixel.ZoomX == xfactor &&
47 ctx->Pixel.ZoomY == yfactor)
48 return;
49
50 FLUSH_VERTICES(ctx, _NEW_PIXEL);
51 ctx->Pixel.ZoomX = xfactor;
52 ctx->Pixel.ZoomY = yfactor;
53 }
54
55
56
57 /**********************************************************************/
58 /***** glPixelStore *****/
59 /**********************************************************************/
60
61
62 void GLAPIENTRY
63 _mesa_PixelStorei( GLenum pname, GLint param )
64 {
65 /* NOTE: this call can't be compiled into the display list */
66 GET_CURRENT_CONTEXT(ctx);
67 ASSERT_OUTSIDE_BEGIN_END(ctx);
68
69 switch (pname) {
70 case GL_PACK_SWAP_BYTES:
71 if (param == (GLint)ctx->Pack.SwapBytes)
72 return;
73 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
74 ctx->Pack.SwapBytes = param ? GL_TRUE : GL_FALSE;
75 break;
76 case GL_PACK_LSB_FIRST:
77 if (param == (GLint)ctx->Pack.LsbFirst)
78 return;
79 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
80 ctx->Pack.LsbFirst = param ? GL_TRUE : GL_FALSE;
81 break;
82 case GL_PACK_ROW_LENGTH:
83 if (param<0) {
84 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
85 return;
86 }
87 if (ctx->Pack.RowLength == param)
88 return;
89 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
90 ctx->Pack.RowLength = param;
91 break;
92 case GL_PACK_IMAGE_HEIGHT:
93 if (param<0) {
94 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
95 return;
96 }
97 if (ctx->Pack.ImageHeight == param)
98 return;
99 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
100 ctx->Pack.ImageHeight = param;
101 break;
102 case GL_PACK_SKIP_PIXELS:
103 if (param<0) {
104 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
105 return;
106 }
107 if (ctx->Pack.SkipPixels == param)
108 return;
109 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
110 ctx->Pack.SkipPixels = param;
111 break;
112 case GL_PACK_SKIP_ROWS:
113 if (param<0) {
114 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
115 return;
116 }
117 if (ctx->Pack.SkipRows == param)
118 return;
119 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
120 ctx->Pack.SkipRows = param;
121 break;
122 case GL_PACK_SKIP_IMAGES:
123 if (param<0) {
124 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
125 return;
126 }
127 if (ctx->Pack.SkipImages == param)
128 return;
129 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
130 ctx->Pack.SkipImages = param;
131 break;
132 case GL_PACK_ALIGNMENT:
133 if (param!=1 && param!=2 && param!=4 && param!=8) {
134 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
135 return;
136 }
137 if (ctx->Pack.Alignment == param)
138 return;
139 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
140 ctx->Pack.Alignment = param;
141 break;
142 case GL_PACK_INVERT_MESA:
143 if (!ctx->Extensions.MESA_pack_invert) {
144 _mesa_error( ctx, GL_INVALID_ENUM, "glPixelstore(pname)" );
145 return;
146 }
147 if (ctx->Pack.Invert == param)
148 return;
149 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
150 ctx->Pack.Invert = param;
151 break;
152
153 case GL_UNPACK_SWAP_BYTES:
154 if (param == (GLint)ctx->Unpack.SwapBytes)
155 return;
156 if ((GLint)ctx->Unpack.SwapBytes == param)
157 return;
158 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
159 ctx->Unpack.SwapBytes = param ? GL_TRUE : GL_FALSE;
160 break;
161 case GL_UNPACK_LSB_FIRST:
162 if (param == (GLint)ctx->Unpack.LsbFirst)
163 return;
164 if ((GLint)ctx->Unpack.LsbFirst == param)
165 return;
166 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
167 ctx->Unpack.LsbFirst = param ? GL_TRUE : GL_FALSE;
168 break;
169 case GL_UNPACK_ROW_LENGTH:
170 if (param<0) {
171 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
172 return;
173 }
174 if (ctx->Unpack.RowLength == param)
175 return;
176 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
177 ctx->Unpack.RowLength = param;
178 break;
179 case GL_UNPACK_IMAGE_HEIGHT:
180 if (param<0) {
181 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
182 return;
183 }
184 if (ctx->Unpack.ImageHeight == param)
185 return;
186
187 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
188 ctx->Unpack.ImageHeight = param;
189 break;
190 case GL_UNPACK_SKIP_PIXELS:
191 if (param<0) {
192 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
193 return;
194 }
195 if (ctx->Unpack.SkipPixels == param)
196 return;
197 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
198 ctx->Unpack.SkipPixels = param;
199 break;
200 case GL_UNPACK_SKIP_ROWS:
201 if (param<0) {
202 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
203 return;
204 }
205 if (ctx->Unpack.SkipRows == param)
206 return;
207 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
208 ctx->Unpack.SkipRows = param;
209 break;
210 case GL_UNPACK_SKIP_IMAGES:
211 if (param < 0) {
212 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
213 return;
214 }
215 if (ctx->Unpack.SkipImages == param)
216 return;
217 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
218 ctx->Unpack.SkipImages = param;
219 break;
220 case GL_UNPACK_ALIGNMENT:
221 if (param!=1 && param!=2 && param!=4 && param!=8) {
222 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore" );
223 return;
224 }
225 if (ctx->Unpack.Alignment == param)
226 return;
227 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
228 ctx->Unpack.Alignment = param;
229 break;
230 case GL_UNPACK_CLIENT_STORAGE_APPLE:
231 if (param == (GLint)ctx->Unpack.ClientStorage)
232 return;
233 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
234 ctx->Unpack.ClientStorage = param ? GL_TRUE : GL_FALSE;
235 break;
236 default:
237 _mesa_error( ctx, GL_INVALID_ENUM, "glPixelStore" );
238 return;
239 }
240 }
241
242
243 void GLAPIENTRY
244 _mesa_PixelStoref( GLenum pname, GLfloat param )
245 {
246 _mesa_PixelStorei( pname, (GLint) param );
247 }
248
249
250
251 /**********************************************************************/
252 /***** glPixelMap *****/
253 /**********************************************************************/
254
255 /**
256 * Return pointer to a pixelmap by name.
257 */
258 static struct gl_pixelmap *
259 get_pixelmap(GLcontext *ctx, GLenum map)
260 {
261 switch (map) {
262 case GL_PIXEL_MAP_I_TO_I:
263 return &ctx->PixelMaps.ItoI;
264 case GL_PIXEL_MAP_S_TO_S:
265 return &ctx->PixelMaps.StoS;
266 case GL_PIXEL_MAP_I_TO_R:
267 return &ctx->PixelMaps.ItoR;
268 case GL_PIXEL_MAP_I_TO_G:
269 return &ctx->PixelMaps.ItoG;
270 case GL_PIXEL_MAP_I_TO_B:
271 return &ctx->PixelMaps.ItoB;
272 case GL_PIXEL_MAP_I_TO_A:
273 return &ctx->PixelMaps.ItoA;
274 case GL_PIXEL_MAP_R_TO_R:
275 return &ctx->PixelMaps.RtoR;
276 case GL_PIXEL_MAP_G_TO_G:
277 return &ctx->PixelMaps.GtoG;
278 case GL_PIXEL_MAP_B_TO_B:
279 return &ctx->PixelMaps.BtoB;
280 case GL_PIXEL_MAP_A_TO_A:
281 return &ctx->PixelMaps.AtoA;
282 default:
283 return NULL;
284 }
285 }
286
287
288 /**
289 * Helper routine used by the other _mesa_PixelMap() functions.
290 */
291 static void
292 store_pixelmap(GLcontext *ctx, GLenum map, GLsizei mapsize,
293 const GLfloat *values)
294 {
295 GLint i;
296 struct gl_pixelmap *pm = get_pixelmap(ctx, map);
297 if (!pm) {
298 _mesa_error(ctx, GL_INVALID_ENUM, "glPixelMap(map)");
299 return;
300 }
301
302 switch (map) {
303 case GL_PIXEL_MAP_S_TO_S:
304 /* special case */
305 ctx->PixelMaps.StoS.Size = mapsize;
306 for (i = 0; i < mapsize; i++) {
307 ctx->PixelMaps.StoS.Map[i] = IROUND(values[i]);
308 }
309 break;
310 case GL_PIXEL_MAP_I_TO_I:
311 /* special case */
312 ctx->PixelMaps.ItoI.Size = mapsize;
313 for (i = 0; i < mapsize; i++) {
314 ctx->PixelMaps.ItoI.Map[i] = values[i];
315 }
316 break;
317 default:
318 /* general case */
319 pm->Size = mapsize;
320 for (i = 0; i < mapsize; i++) {
321 GLfloat val = CLAMP(values[i], 0.0F, 1.0F);
322 pm->Map[i] = val;
323 pm->Map8[i] = (GLint) (val * 255.0F);
324 }
325 }
326 }
327
328
329 void GLAPIENTRY
330 _mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
331 {
332 GET_CURRENT_CONTEXT(ctx);
333 ASSERT_OUTSIDE_BEGIN_END(ctx);
334
335 /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
336 if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
337 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
338 return;
339 }
340
341 if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
342 /* test that mapsize is a power of two */
343 if (_mesa_bitcount((GLuint) mapsize) != 1) {
344 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
345 return;
346 }
347 }
348
349 FLUSH_VERTICES(ctx, _NEW_PIXEL);
350
351 if (ctx->Unpack.BufferObj->Name) {
352 /* unpack pixelmap from PBO */
353 GLubyte *buf;
354 /* Note, need to use DefaultPacking and Unpack's buffer object */
355 ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj;
356 if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
357 GL_INTENSITY, GL_FLOAT, values)) {
358 _mesa_error(ctx, GL_INVALID_OPERATION,
359 "glPixelMapfv(invalid PBO access)");
360 return;
361 }
362 /* restore */
363 ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
364 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
365 GL_READ_ONLY_ARB,
366 ctx->Unpack.BufferObj);
367 if (!buf) {
368 /* buffer is already mapped - that's an error */
369 _mesa_error(ctx, GL_INVALID_OPERATION,
370 "glPixelMapfv(PBO is mapped)");
371 return;
372 }
373 values = (const GLfloat *) ADD_POINTERS(buf, values);
374 }
375 else if (!values) {
376 return;
377 }
378
379 store_pixelmap(ctx, map, mapsize, values);
380
381 if (ctx->Unpack.BufferObj->Name) {
382 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
383 ctx->Unpack.BufferObj);
384 }
385 }
386
387
388 void GLAPIENTRY
389 _mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
390 {
391 GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
392 GET_CURRENT_CONTEXT(ctx);
393 ASSERT_OUTSIDE_BEGIN_END(ctx);
394
395 if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
396 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
397 return;
398 }
399
400 if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
401 /* test that mapsize is a power of two */
402 if (_mesa_bitcount((GLuint) mapsize) != 1) {
403 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
404 return;
405 }
406 }
407
408 FLUSH_VERTICES(ctx, _NEW_PIXEL);
409
410 if (ctx->Unpack.BufferObj->Name) {
411 /* unpack pixelmap from PBO */
412 GLubyte *buf;
413 /* Note, need to use DefaultPacking and Unpack's buffer object */
414 ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj;
415 if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
416 GL_INTENSITY, GL_UNSIGNED_INT, values)) {
417 _mesa_error(ctx, GL_INVALID_OPERATION,
418 "glPixelMapuiv(invalid PBO access)");
419 return;
420 }
421 /* restore */
422 ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
423 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
424 GL_READ_ONLY_ARB,
425 ctx->Unpack.BufferObj);
426 if (!buf) {
427 /* buffer is already mapped - that's an error */
428 _mesa_error(ctx, GL_INVALID_OPERATION,
429 "glPixelMapuiv(PBO is mapped)");
430 return;
431 }
432 values = (const GLuint *) ADD_POINTERS(buf, values);
433 }
434 else if (!values) {
435 return;
436 }
437
438 /* convert to floats */
439 if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
440 GLint i;
441 for (i = 0; i < mapsize; i++) {
442 fvalues[i] = (GLfloat) values[i];
443 }
444 }
445 else {
446 GLint i;
447 for (i = 0; i < mapsize; i++) {
448 fvalues[i] = UINT_TO_FLOAT( values[i] );
449 }
450 }
451
452 if (ctx->Unpack.BufferObj->Name) {
453 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
454 ctx->Unpack.BufferObj);
455 }
456
457 store_pixelmap(ctx, map, mapsize, fvalues);
458 }
459
460
461 void GLAPIENTRY
462 _mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values )
463 {
464 GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
465 GET_CURRENT_CONTEXT(ctx);
466 ASSERT_OUTSIDE_BEGIN_END(ctx);
467
468 if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
469 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapusv(mapsize)" );
470 return;
471 }
472
473 if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
474 /* test that mapsize is a power of two */
475 if (_mesa_bitcount((GLuint) mapsize) != 1) {
476 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
477 return;
478 }
479 }
480
481 FLUSH_VERTICES(ctx, _NEW_PIXEL);
482
483 if (ctx->Unpack.BufferObj->Name) {
484 /* unpack pixelmap from PBO */
485 GLubyte *buf;
486 /* Note, need to use DefaultPacking and Unpack's buffer object */
487 ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj;
488 if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
489 GL_INTENSITY, GL_UNSIGNED_SHORT,
490 values)) {
491 _mesa_error(ctx, GL_INVALID_OPERATION,
492 "glPixelMapusv(invalid PBO access)");
493 return;
494 }
495 /* restore */
496 ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
497 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
498 GL_READ_ONLY_ARB,
499 ctx->Unpack.BufferObj);
500 if (!buf) {
501 /* buffer is already mapped - that's an error */
502 _mesa_error(ctx, GL_INVALID_OPERATION,
503 "glPixelMapusv(PBO is mapped)");
504 return;
505 }
506 values = (const GLushort *) ADD_POINTERS(buf, values);
507 }
508 else if (!values) {
509 return;
510 }
511
512 /* convert to floats */
513 if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
514 GLint i;
515 for (i = 0; i < mapsize; i++) {
516 fvalues[i] = (GLfloat) values[i];
517 }
518 }
519 else {
520 GLint i;
521 for (i = 0; i < mapsize; i++) {
522 fvalues[i] = USHORT_TO_FLOAT( values[i] );
523 }
524 }
525
526 if (ctx->Unpack.BufferObj->Name) {
527 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
528 ctx->Unpack.BufferObj);
529 }
530
531 store_pixelmap(ctx, map, mapsize, fvalues);
532 }
533
534
535 void GLAPIENTRY
536 _mesa_GetPixelMapfv( GLenum map, GLfloat *values )
537 {
538 GET_CURRENT_CONTEXT(ctx);
539 GLuint mapsize, i;
540 const struct gl_pixelmap *pm;
541
542 ASSERT_OUTSIDE_BEGIN_END(ctx);
543
544 pm = get_pixelmap(ctx, map);
545 if (!pm) {
546 _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapfv(map)");
547 return;
548 }
549
550 mapsize = pm->Size;
551
552 if (ctx->Pack.BufferObj->Name) {
553 /* pack pixelmap into PBO */
554 GLubyte *buf;
555 /* Note, need to use DefaultPacking and Pack's buffer object */
556 ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj;
557 if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
558 GL_INTENSITY, GL_FLOAT, values)) {
559 _mesa_error(ctx, GL_INVALID_OPERATION,
560 "glGetPixelMapfv(invalid PBO access)");
561 return;
562 }
563 /* restore */
564 ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
565 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
566 GL_WRITE_ONLY_ARB,
567 ctx->Pack.BufferObj);
568 if (!buf) {
569 /* buffer is already mapped - that's an error */
570 _mesa_error(ctx, GL_INVALID_OPERATION,
571 "glGetPixelMapfv(PBO is mapped)");
572 return;
573 }
574 values = (GLfloat *) ADD_POINTERS(buf, values);
575 }
576 else if (!values) {
577 return;
578 }
579
580 if (map == GL_PIXEL_MAP_S_TO_S) {
581 /* special case */
582 for (i = 0; i < mapsize; i++) {
583 values[i] = (GLfloat) ctx->PixelMaps.StoS.Map[i];
584 }
585 }
586 else {
587 MEMCPY(values, pm->Map, mapsize * sizeof(GLfloat));
588 }
589
590 if (ctx->Pack.BufferObj->Name) {
591 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
592 ctx->Pack.BufferObj);
593 }
594 }
595
596
597 void GLAPIENTRY
598 _mesa_GetPixelMapuiv( GLenum map, GLuint *values )
599 {
600 GET_CURRENT_CONTEXT(ctx);
601 GLint mapsize, i;
602 const struct gl_pixelmap *pm;
603
604 ASSERT_OUTSIDE_BEGIN_END(ctx);
605
606 pm = get_pixelmap(ctx, map);
607 if (!pm) {
608 _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapuiv(map)");
609 return;
610 }
611 mapsize = pm->Size;
612
613 if (ctx->Pack.BufferObj->Name) {
614 /* pack pixelmap into PBO */
615 GLubyte *buf;
616 /* Note, need to use DefaultPacking and Pack's buffer object */
617 ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj;
618 if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
619 GL_INTENSITY, GL_UNSIGNED_INT, values)) {
620 _mesa_error(ctx, GL_INVALID_OPERATION,
621 "glGetPixelMapuiv(invalid PBO access)");
622 return;
623 }
624 /* restore */
625 ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
626 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
627 GL_WRITE_ONLY_ARB,
628 ctx->Pack.BufferObj);
629 if (!buf) {
630 /* buffer is already mapped - that's an error */
631 _mesa_error(ctx, GL_INVALID_OPERATION,
632 "glGetPixelMapuiv(PBO is mapped)");
633 return;
634 }
635 values = (GLuint *) ADD_POINTERS(buf, values);
636 }
637 else if (!values) {
638 return;
639 }
640
641 if (map == GL_PIXEL_MAP_S_TO_S) {
642 /* special case */
643 MEMCPY(values, ctx->PixelMaps.StoS.Map, mapsize * sizeof(GLint));
644 }
645 else {
646 for (i = 0; i < mapsize; i++) {
647 values[i] = FLOAT_TO_UINT( pm->Map[i] );
648 }
649 }
650
651 if (ctx->Pack.BufferObj->Name) {
652 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
653 ctx->Pack.BufferObj);
654 }
655 }
656
657
658 void GLAPIENTRY
659 _mesa_GetPixelMapusv( GLenum map, GLushort *values )
660 {
661 GET_CURRENT_CONTEXT(ctx);
662 GLint mapsize, i;
663 const struct gl_pixelmap *pm;
664
665 ASSERT_OUTSIDE_BEGIN_END(ctx);
666
667 pm = get_pixelmap(ctx, map);
668 if (!pm) {
669 _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapusv(map)");
670 return;
671 }
672 mapsize = pm ? pm->Size : 0;
673
674 if (ctx->Pack.BufferObj->Name) {
675 /* pack pixelmap into PBO */
676 GLubyte *buf;
677 /* Note, need to use DefaultPacking and Pack's buffer object */
678 ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj;
679 if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
680 GL_INTENSITY, GL_UNSIGNED_SHORT,
681 values)) {
682 _mesa_error(ctx, GL_INVALID_OPERATION,
683 "glGetPixelMapusv(invalid PBO access)");
684 return;
685 }
686 /* restore */
687 ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
688 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
689 GL_WRITE_ONLY_ARB,
690 ctx->Pack.BufferObj);
691 if (!buf) {
692 /* buffer is already mapped - that's an error */
693 _mesa_error(ctx, GL_INVALID_OPERATION,
694 "glGetPixelMapusv(PBO is mapped)");
695 return;
696 }
697 values = (GLushort *) ADD_POINTERS(buf, values);
698 }
699 else if (!values) {
700 return;
701 }
702
703 switch (map) {
704 /* special cases */
705 case GL_PIXEL_MAP_I_TO_I:
706 for (i = 0; i < mapsize; i++) {
707 values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0, 65535.);
708 }
709 break;
710 case GL_PIXEL_MAP_S_TO_S:
711 for (i = 0; i < mapsize; i++) {
712 values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0, 65535.);
713 }
714 break;
715 default:
716 for (i = 0; i < mapsize; i++) {
717 CLAMPED_FLOAT_TO_USHORT(values[i], pm->Map[i] );
718 }
719 }
720
721 if (ctx->Pack.BufferObj->Name) {
722 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
723 ctx->Pack.BufferObj);
724 }
725 }
726
727
728
729 /**********************************************************************/
730 /***** glPixelTransfer *****/
731 /**********************************************************************/
732
733
734 /*
735 * Implements glPixelTransfer[fi] whether called immediately or from a
736 * display list.
737 */
738 void GLAPIENTRY
739 _mesa_PixelTransferf( GLenum pname, GLfloat param )
740 {
741 GET_CURRENT_CONTEXT(ctx);
742 ASSERT_OUTSIDE_BEGIN_END(ctx);
743
744 switch (pname) {
745 case GL_MAP_COLOR:
746 if (ctx->Pixel.MapColorFlag == (param ? GL_TRUE : GL_FALSE))
747 return;
748 FLUSH_VERTICES(ctx, _NEW_PIXEL);
749 ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE;
750 break;
751 case GL_MAP_STENCIL:
752 if (ctx->Pixel.MapStencilFlag == (param ? GL_TRUE : GL_FALSE))
753 return;
754 FLUSH_VERTICES(ctx, _NEW_PIXEL);
755 ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE;
756 break;
757 case GL_INDEX_SHIFT:
758 if (ctx->Pixel.IndexShift == (GLint) param)
759 return;
760 FLUSH_VERTICES(ctx, _NEW_PIXEL);
761 ctx->Pixel.IndexShift = (GLint) param;
762 break;
763 case GL_INDEX_OFFSET:
764 if (ctx->Pixel.IndexOffset == (GLint) param)
765 return;
766 FLUSH_VERTICES(ctx, _NEW_PIXEL);
767 ctx->Pixel.IndexOffset = (GLint) param;
768 break;
769 case GL_RED_SCALE:
770 if (ctx->Pixel.RedScale == param)
771 return;
772 FLUSH_VERTICES(ctx, _NEW_PIXEL);
773 ctx->Pixel.RedScale = param;
774 break;
775 case GL_RED_BIAS:
776 if (ctx->Pixel.RedBias == param)
777 return;
778 FLUSH_VERTICES(ctx, _NEW_PIXEL);
779 ctx->Pixel.RedBias = param;
780 break;
781 case GL_GREEN_SCALE:
782 if (ctx->Pixel.GreenScale == param)
783 return;
784 FLUSH_VERTICES(ctx, _NEW_PIXEL);
785 ctx->Pixel.GreenScale = param;
786 break;
787 case GL_GREEN_BIAS:
788 if (ctx->Pixel.GreenBias == param)
789 return;
790 FLUSH_VERTICES(ctx, _NEW_PIXEL);
791 ctx->Pixel.GreenBias = param;
792 break;
793 case GL_BLUE_SCALE:
794 if (ctx->Pixel.BlueScale == param)
795 return;
796 FLUSH_VERTICES(ctx, _NEW_PIXEL);
797 ctx->Pixel.BlueScale = param;
798 break;
799 case GL_BLUE_BIAS:
800 if (ctx->Pixel.BlueBias == param)
801 return;
802 FLUSH_VERTICES(ctx, _NEW_PIXEL);
803 ctx->Pixel.BlueBias = param;
804 break;
805 case GL_ALPHA_SCALE:
806 if (ctx->Pixel.AlphaScale == param)
807 return;
808 FLUSH_VERTICES(ctx, _NEW_PIXEL);
809 ctx->Pixel.AlphaScale = param;
810 break;
811 case GL_ALPHA_BIAS:
812 if (ctx->Pixel.AlphaBias == param)
813 return;
814 FLUSH_VERTICES(ctx, _NEW_PIXEL);
815 ctx->Pixel.AlphaBias = param;
816 break;
817 case GL_DEPTH_SCALE:
818 if (ctx->Pixel.DepthScale == param)
819 return;
820 FLUSH_VERTICES(ctx, _NEW_PIXEL);
821 ctx->Pixel.DepthScale = param;
822 break;
823 case GL_DEPTH_BIAS:
824 if (ctx->Pixel.DepthBias == param)
825 return;
826 FLUSH_VERTICES(ctx, _NEW_PIXEL);
827 ctx->Pixel.DepthBias = param;
828 break;
829 case GL_POST_COLOR_MATRIX_RED_SCALE:
830 if (ctx->Pixel.PostColorMatrixScale[0] == param)
831 return;
832 FLUSH_VERTICES(ctx, _NEW_PIXEL);
833 ctx->Pixel.PostColorMatrixScale[0] = param;
834 break;
835 case GL_POST_COLOR_MATRIX_RED_BIAS:
836 if (ctx->Pixel.PostColorMatrixBias[0] == param)
837 return;
838 FLUSH_VERTICES(ctx, _NEW_PIXEL);
839 ctx->Pixel.PostColorMatrixBias[0] = param;
840 break;
841 case GL_POST_COLOR_MATRIX_GREEN_SCALE:
842 if (ctx->Pixel.PostColorMatrixScale[1] == param)
843 return;
844 FLUSH_VERTICES(ctx, _NEW_PIXEL);
845 ctx->Pixel.PostColorMatrixScale[1] = param;
846 break;
847 case GL_POST_COLOR_MATRIX_GREEN_BIAS:
848 if (ctx->Pixel.PostColorMatrixBias[1] == param)
849 return;
850 FLUSH_VERTICES(ctx, _NEW_PIXEL);
851 ctx->Pixel.PostColorMatrixBias[1] = param;
852 break;
853 case GL_POST_COLOR_MATRIX_BLUE_SCALE:
854 if (ctx->Pixel.PostColorMatrixScale[2] == param)
855 return;
856 FLUSH_VERTICES(ctx, _NEW_PIXEL);
857 ctx->Pixel.PostColorMatrixScale[2] = param;
858 break;
859 case GL_POST_COLOR_MATRIX_BLUE_BIAS:
860 if (ctx->Pixel.PostColorMatrixBias[2] == param)
861 return;
862 FLUSH_VERTICES(ctx, _NEW_PIXEL);
863 ctx->Pixel.PostColorMatrixBias[2] = param;
864 break;
865 case GL_POST_COLOR_MATRIX_ALPHA_SCALE:
866 if (ctx->Pixel.PostColorMatrixScale[3] == param)
867 return;
868 FLUSH_VERTICES(ctx, _NEW_PIXEL);
869 ctx->Pixel.PostColorMatrixScale[3] = param;
870 break;
871 case GL_POST_COLOR_MATRIX_ALPHA_BIAS:
872 if (ctx->Pixel.PostColorMatrixBias[3] == param)
873 return;
874 FLUSH_VERTICES(ctx, _NEW_PIXEL);
875 ctx->Pixel.PostColorMatrixBias[3] = param;
876 break;
877 case GL_POST_CONVOLUTION_RED_SCALE:
878 if (ctx->Pixel.PostConvolutionScale[0] == param)
879 return;
880 FLUSH_VERTICES(ctx, _NEW_PIXEL);
881 ctx->Pixel.PostConvolutionScale[0] = param;
882 break;
883 case GL_POST_CONVOLUTION_RED_BIAS:
884 if (ctx->Pixel.PostConvolutionBias[0] == param)
885 return;
886 FLUSH_VERTICES(ctx, _NEW_PIXEL);
887 ctx->Pixel.PostConvolutionBias[0] = param;
888 break;
889 case GL_POST_CONVOLUTION_GREEN_SCALE:
890 if (ctx->Pixel.PostConvolutionScale[1] == param)
891 return;
892 FLUSH_VERTICES(ctx, _NEW_PIXEL);
893 ctx->Pixel.PostConvolutionScale[1] = param;
894 break;
895 case GL_POST_CONVOLUTION_GREEN_BIAS:
896 if (ctx->Pixel.PostConvolutionBias[1] == param)
897 return;
898 FLUSH_VERTICES(ctx, _NEW_PIXEL);
899 ctx->Pixel.PostConvolutionBias[1] = param;
900 break;
901 case GL_POST_CONVOLUTION_BLUE_SCALE:
902 if (ctx->Pixel.PostConvolutionScale[2] == param)
903 return;
904 FLUSH_VERTICES(ctx, _NEW_PIXEL);
905 ctx->Pixel.PostConvolutionScale[2] = param;
906 break;
907 case GL_POST_CONVOLUTION_BLUE_BIAS:
908 if (ctx->Pixel.PostConvolutionBias[2] == param)
909 return;
910 FLUSH_VERTICES(ctx, _NEW_PIXEL);
911 ctx->Pixel.PostConvolutionBias[2] = param;
912 break;
913 case GL_POST_CONVOLUTION_ALPHA_SCALE:
914 if (ctx->Pixel.PostConvolutionScale[3] == param)
915 return;
916 FLUSH_VERTICES(ctx, _NEW_PIXEL);
917 ctx->Pixel.PostConvolutionScale[3] = param;
918 break;
919 case GL_POST_CONVOLUTION_ALPHA_BIAS:
920 if (ctx->Pixel.PostConvolutionBias[3] == param)
921 return;
922 FLUSH_VERTICES(ctx, _NEW_PIXEL);
923 ctx->Pixel.PostConvolutionBias[3] = param;
924 break;
925 default:
926 _mesa_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
927 return;
928 }
929 }
930
931
932 void GLAPIENTRY
933 _mesa_PixelTransferi( GLenum pname, GLint param )
934 {
935 _mesa_PixelTransferf( pname, (GLfloat) param );
936 }
937
938
939
940 /**********************************************************************/
941 /***** Pixel processing functions ******/
942 /**********************************************************************/
943
944 /*
945 * Apply scale and bias factors to an array of RGBA pixels.
946 */
947 void
948 _mesa_scale_and_bias_rgba(GLuint n, GLfloat rgba[][4],
949 GLfloat rScale, GLfloat gScale,
950 GLfloat bScale, GLfloat aScale,
951 GLfloat rBias, GLfloat gBias,
952 GLfloat bBias, GLfloat aBias)
953 {
954 if (rScale != 1.0 || rBias != 0.0) {
955 GLuint i;
956 for (i = 0; i < n; i++) {
957 rgba[i][RCOMP] = rgba[i][RCOMP] * rScale + rBias;
958 }
959 }
960 if (gScale != 1.0 || gBias != 0.0) {
961 GLuint i;
962 for (i = 0; i < n; i++) {
963 rgba[i][GCOMP] = rgba[i][GCOMP] * gScale + gBias;
964 }
965 }
966 if (bScale != 1.0 || bBias != 0.0) {
967 GLuint i;
968 for (i = 0; i < n; i++) {
969 rgba[i][BCOMP] = rgba[i][BCOMP] * bScale + bBias;
970 }
971 }
972 if (aScale != 1.0 || aBias != 0.0) {
973 GLuint i;
974 for (i = 0; i < n; i++) {
975 rgba[i][ACOMP] = rgba[i][ACOMP] * aScale + aBias;
976 }
977 }
978 }
979
980
981 /*
982 * Apply pixel mapping to an array of floating point RGBA pixels.
983 */
984 void
985 _mesa_map_rgba( const GLcontext *ctx, GLuint n, GLfloat rgba[][4] )
986 {
987 const GLfloat rscale = (GLfloat) (ctx->PixelMaps.RtoR.Size - 1);
988 const GLfloat gscale = (GLfloat) (ctx->PixelMaps.GtoG.Size - 1);
989 const GLfloat bscale = (GLfloat) (ctx->PixelMaps.BtoB.Size - 1);
990 const GLfloat ascale = (GLfloat) (ctx->PixelMaps.AtoA.Size - 1);
991 const GLfloat *rMap = ctx->PixelMaps.RtoR.Map;
992 const GLfloat *gMap = ctx->PixelMaps.GtoG.Map;
993 const GLfloat *bMap = ctx->PixelMaps.BtoB.Map;
994 const GLfloat *aMap = ctx->PixelMaps.AtoA.Map;
995 GLuint i;
996 for (i=0;i<n;i++) {
997 GLfloat r = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
998 GLfloat g = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
999 GLfloat b = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
1000 GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
1001 rgba[i][RCOMP] = rMap[IROUND(r * rscale)];
1002 rgba[i][GCOMP] = gMap[IROUND(g * gscale)];
1003 rgba[i][BCOMP] = bMap[IROUND(b * bscale)];
1004 rgba[i][ACOMP] = aMap[IROUND(a * ascale)];
1005 }
1006 }
1007
1008
1009 /*
1010 * Apply the color matrix and post color matrix scaling and biasing.
1011 */
1012 void
1013 _mesa_transform_rgba(const GLcontext *ctx, GLuint n, GLfloat rgba[][4])
1014 {
1015 const GLfloat rs = ctx->Pixel.PostColorMatrixScale[0];
1016 const GLfloat rb = ctx->Pixel.PostColorMatrixBias[0];
1017 const GLfloat gs = ctx->Pixel.PostColorMatrixScale[1];
1018 const GLfloat gb = ctx->Pixel.PostColorMatrixBias[1];
1019 const GLfloat bs = ctx->Pixel.PostColorMatrixScale[2];
1020 const GLfloat bb = ctx->Pixel.PostColorMatrixBias[2];
1021 const GLfloat as = ctx->Pixel.PostColorMatrixScale[3];
1022 const GLfloat ab = ctx->Pixel.PostColorMatrixBias[3];
1023 const GLfloat *m = ctx->ColorMatrixStack.Top->m;
1024 GLuint i;
1025 for (i = 0; i < n; i++) {
1026 const GLfloat r = rgba[i][RCOMP];
1027 const GLfloat g = rgba[i][GCOMP];
1028 const GLfloat b = rgba[i][BCOMP];
1029 const GLfloat a = rgba[i][ACOMP];
1030 rgba[i][RCOMP] = (m[0] * r + m[4] * g + m[ 8] * b + m[12] * a) * rs + rb;
1031 rgba[i][GCOMP] = (m[1] * r + m[5] * g + m[ 9] * b + m[13] * a) * gs + gb;
1032 rgba[i][BCOMP] = (m[2] * r + m[6] * g + m[10] * b + m[14] * a) * bs + bb;
1033 rgba[i][ACOMP] = (m[3] * r + m[7] * g + m[11] * b + m[15] * a) * as + ab;
1034 }
1035 }
1036
1037
1038 /**
1039 * Apply a color table lookup to an array of floating point RGBA colors.
1040 */
1041 void
1042 _mesa_lookup_rgba_float(const struct gl_color_table *table,
1043 GLuint n, GLfloat rgba[][4])
1044 {
1045 const GLint max = table->Size - 1;
1046 const GLfloat scale = (GLfloat) max;
1047 const GLfloat *lut = table->TableF;
1048 GLuint i;
1049
1050 if (!table->TableF || table->Size == 0)
1051 return;
1052
1053 switch (table->_BaseFormat) {
1054 case GL_INTENSITY:
1055 /* replace RGBA with I */
1056 for (i = 0; i < n; i++) {
1057 GLint j = IROUND(rgba[i][RCOMP] * scale);
1058 GLfloat c = lut[CLAMP(j, 0, max)];
1059 rgba[i][RCOMP] =
1060 rgba[i][GCOMP] =
1061 rgba[i][BCOMP] =
1062 rgba[i][ACOMP] = c;
1063 }
1064 break;
1065 case GL_LUMINANCE:
1066 /* replace RGB with L */
1067 for (i = 0; i < n; i++) {
1068 GLint j = IROUND(rgba[i][RCOMP] * scale);
1069 GLfloat c = lut[CLAMP(j, 0, max)];
1070 rgba[i][RCOMP] =
1071 rgba[i][GCOMP] =
1072 rgba[i][BCOMP] = c;
1073 }
1074 break;
1075 case GL_ALPHA:
1076 /* replace A with A */
1077 for (i = 0; i < n; i++) {
1078 GLint j = IROUND(rgba[i][ACOMP] * scale);
1079 rgba[i][ACOMP] = lut[CLAMP(j, 0, max)];
1080 }
1081 break;
1082 case GL_LUMINANCE_ALPHA:
1083 /* replace RGBA with LLLA */
1084 for (i = 0; i < n; i++) {
1085 GLint jL = IROUND(rgba[i][RCOMP] * scale);
1086 GLint jA = IROUND(rgba[i][ACOMP] * scale);
1087 GLfloat luminance, alpha;
1088 jL = CLAMP(jL, 0, max);
1089 jA = CLAMP(jA, 0, max);
1090 luminance = lut[jL * 2 + 0];
1091 alpha = lut[jA * 2 + 1];
1092 rgba[i][RCOMP] =
1093 rgba[i][GCOMP] =
1094 rgba[i][BCOMP] = luminance;
1095 rgba[i][ACOMP] = alpha;;
1096 }
1097 break;
1098 case GL_RGB:
1099 /* replace RGB with RGB */
1100 for (i = 0; i < n; i++) {
1101 GLint jR = IROUND(rgba[i][RCOMP] * scale);
1102 GLint jG = IROUND(rgba[i][GCOMP] * scale);
1103 GLint jB = IROUND(rgba[i][BCOMP] * scale);
1104 jR = CLAMP(jR, 0, max);
1105 jG = CLAMP(jG, 0, max);
1106 jB = CLAMP(jB, 0, max);
1107 rgba[i][RCOMP] = lut[jR * 3 + 0];
1108 rgba[i][GCOMP] = lut[jG * 3 + 1];
1109 rgba[i][BCOMP] = lut[jB * 3 + 2];
1110 }
1111 break;
1112 case GL_RGBA:
1113 /* replace RGBA with RGBA */
1114 for (i = 0; i < n; i++) {
1115 GLint jR = IROUND(rgba[i][RCOMP] * scale);
1116 GLint jG = IROUND(rgba[i][GCOMP] * scale);
1117 GLint jB = IROUND(rgba[i][BCOMP] * scale);
1118 GLint jA = IROUND(rgba[i][ACOMP] * scale);
1119 jR = CLAMP(jR, 0, max);
1120 jG = CLAMP(jG, 0, max);
1121 jB = CLAMP(jB, 0, max);
1122 jA = CLAMP(jA, 0, max);
1123 rgba[i][RCOMP] = lut[jR * 4 + 0];
1124 rgba[i][GCOMP] = lut[jG * 4 + 1];
1125 rgba[i][BCOMP] = lut[jB * 4 + 2];
1126 rgba[i][ACOMP] = lut[jA * 4 + 3];
1127 }
1128 break;
1129 default:
1130 _mesa_problem(NULL, "Bad format in _mesa_lookup_rgba_float");
1131 return;
1132 }
1133 }
1134
1135
1136
1137 /**
1138 * Apply a color table lookup to an array of ubyte/RGBA colors.
1139 */
1140 void
1141 _mesa_lookup_rgba_ubyte(const struct gl_color_table *table,
1142 GLuint n, GLubyte rgba[][4])
1143 {
1144 const GLubyte *lut = table->TableUB;
1145 const GLfloat scale = (GLfloat) (table->Size - 1) / 255.0;
1146 GLuint i;
1147
1148 if (!table->TableUB || table->Size == 0)
1149 return;
1150
1151 switch (table->_BaseFormat) {
1152 case GL_INTENSITY:
1153 /* replace RGBA with I */
1154 if (table->Size == 256) {
1155 for (i = 0; i < n; i++) {
1156 const GLubyte c = lut[rgba[i][RCOMP]];
1157 rgba[i][RCOMP] =
1158 rgba[i][GCOMP] =
1159 rgba[i][BCOMP] =
1160 rgba[i][ACOMP] = c;
1161 }
1162 }
1163 else {
1164 for (i = 0; i < n; i++) {
1165 GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale);
1166 rgba[i][RCOMP] =
1167 rgba[i][GCOMP] =
1168 rgba[i][BCOMP] =
1169 rgba[i][ACOMP] = lut[j];
1170 }
1171 }
1172 break;
1173 case GL_LUMINANCE:
1174 /* replace RGB with L */
1175 if (table->Size == 256) {
1176 for (i = 0; i < n; i++) {
1177 const GLubyte c = lut[rgba[i][RCOMP]];
1178 rgba[i][RCOMP] =
1179 rgba[i][GCOMP] =
1180 rgba[i][BCOMP] = c;
1181 }
1182 }
1183 else {
1184 for (i = 0; i < n; i++) {
1185 GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale);
1186 rgba[i][RCOMP] =
1187 rgba[i][GCOMP] =
1188 rgba[i][BCOMP] = lut[j];
1189 }
1190 }
1191 break;
1192 case GL_ALPHA:
1193 /* replace A with A */
1194 if (table->Size == 256) {
1195 for (i = 0; i < n; i++) {
1196 rgba[i][ACOMP] = lut[rgba[i][ACOMP]];
1197 }
1198 }
1199 else {
1200 for (i = 0; i < n; i++) {
1201 GLint j = IROUND((GLfloat) rgba[i][ACOMP] * scale);
1202 rgba[i][ACOMP] = lut[j];
1203 }
1204 }
1205 break;
1206 case GL_LUMINANCE_ALPHA:
1207 /* replace RGBA with LLLA */
1208 if (table->Size == 256) {
1209 for (i = 0; i < n; i++) {
1210 GLubyte l = lut[rgba[i][RCOMP] * 2 + 0];
1211 GLubyte a = lut[rgba[i][ACOMP] * 2 + 1];;
1212 rgba[i][RCOMP] =
1213 rgba[i][GCOMP] =
1214 rgba[i][BCOMP] = l;
1215 rgba[i][ACOMP] = a;
1216 }
1217 }
1218 else {
1219 for (i = 0; i < n; i++) {
1220 GLint jL = IROUND((GLfloat) rgba[i][RCOMP] * scale);
1221 GLint jA = IROUND((GLfloat) rgba[i][ACOMP] * scale);
1222 GLubyte luminance = lut[jL * 2 + 0];
1223 GLubyte alpha = lut[jA * 2 + 1];
1224 rgba[i][RCOMP] =
1225 rgba[i][GCOMP] =
1226 rgba[i][BCOMP] = luminance;
1227 rgba[i][ACOMP] = alpha;
1228 }
1229 }
1230 break;
1231 case GL_RGB:
1232 if (table->Size == 256) {
1233 for (i = 0; i < n; i++) {
1234 rgba[i][RCOMP] = lut[rgba[i][RCOMP] * 3 + 0];
1235 rgba[i][GCOMP] = lut[rgba[i][GCOMP] * 3 + 1];
1236 rgba[i][BCOMP] = lut[rgba[i][BCOMP] * 3 + 2];
1237 }
1238 }
1239 else {
1240 for (i = 0; i < n; i++) {
1241 GLint jR = IROUND((GLfloat) rgba[i][RCOMP] * scale);
1242 GLint jG = IROUND((GLfloat) rgba[i][GCOMP] * scale);
1243 GLint jB = IROUND((GLfloat) rgba[i][BCOMP] * scale);
1244 rgba[i][RCOMP] = lut[jR * 3 + 0];
1245 rgba[i][GCOMP] = lut[jG * 3 + 1];
1246 rgba[i][BCOMP] = lut[jB * 3 + 2];
1247 }
1248 }
1249 break;
1250 case GL_RGBA:
1251 if (table->Size == 256) {
1252 for (i = 0; i < n; i++) {
1253 rgba[i][RCOMP] = lut[rgba[i][RCOMP] * 4 + 0];
1254 rgba[i][GCOMP] = lut[rgba[i][GCOMP] * 4 + 1];
1255 rgba[i][BCOMP] = lut[rgba[i][BCOMP] * 4 + 2];
1256 rgba[i][ACOMP] = lut[rgba[i][ACOMP] * 4 + 3];
1257 }
1258 }
1259 else {
1260 for (i = 0; i < n; i++) {
1261 GLint jR = IROUND((GLfloat) rgba[i][RCOMP] * scale);
1262 GLint jG = IROUND((GLfloat) rgba[i][GCOMP] * scale);
1263 GLint jB = IROUND((GLfloat) rgba[i][BCOMP] * scale);
1264 GLint jA = IROUND((GLfloat) rgba[i][ACOMP] * scale);
1265 CLAMPED_FLOAT_TO_CHAN(rgba[i][RCOMP], lut[jR * 4 + 0]);
1266 CLAMPED_FLOAT_TO_CHAN(rgba[i][GCOMP], lut[jG * 4 + 1]);
1267 CLAMPED_FLOAT_TO_CHAN(rgba[i][BCOMP], lut[jB * 4 + 2]);
1268 CLAMPED_FLOAT_TO_CHAN(rgba[i][ACOMP], lut[jA * 4 + 3]);
1269 }
1270 }
1271 break;
1272 default:
1273 _mesa_problem(NULL, "Bad format in _mesa_lookup_rgba_chan");
1274 return;
1275 }
1276 }
1277
1278
1279
1280 /*
1281 * Map color indexes to float rgba values.
1282 */
1283 void
1284 _mesa_map_ci_to_rgba( const GLcontext *ctx, GLuint n,
1285 const GLuint index[], GLfloat rgba[][4] )
1286 {
1287 GLuint rmask = ctx->PixelMaps.ItoR.Size - 1;
1288 GLuint gmask = ctx->PixelMaps.ItoG.Size - 1;
1289 GLuint bmask = ctx->PixelMaps.ItoB.Size - 1;
1290 GLuint amask = ctx->PixelMaps.ItoA.Size - 1;
1291 const GLfloat *rMap = ctx->PixelMaps.ItoR.Map;
1292 const GLfloat *gMap = ctx->PixelMaps.ItoG.Map;
1293 const GLfloat *bMap = ctx->PixelMaps.ItoB.Map;
1294 const GLfloat *aMap = ctx->PixelMaps.ItoA.Map;
1295 GLuint i;
1296 for (i=0;i<n;i++) {
1297 rgba[i][RCOMP] = rMap[index[i] & rmask];
1298 rgba[i][GCOMP] = gMap[index[i] & gmask];
1299 rgba[i][BCOMP] = bMap[index[i] & bmask];
1300 rgba[i][ACOMP] = aMap[index[i] & amask];
1301 }
1302 }
1303
1304
1305 /**
1306 * Map ubyte color indexes to ubyte/RGBA values.
1307 */
1308 void
1309 _mesa_map_ci8_to_rgba8(const GLcontext *ctx, GLuint n, const GLubyte index[],
1310 GLubyte rgba[][4])
1311 {
1312 GLuint rmask = ctx->PixelMaps.ItoR.Size - 1;
1313 GLuint gmask = ctx->PixelMaps.ItoG.Size - 1;
1314 GLuint bmask = ctx->PixelMaps.ItoB.Size - 1;
1315 GLuint amask = ctx->PixelMaps.ItoA.Size - 1;
1316 const GLubyte *rMap = ctx->PixelMaps.ItoR.Map8;
1317 const GLubyte *gMap = ctx->PixelMaps.ItoG.Map8;
1318 const GLubyte *bMap = ctx->PixelMaps.ItoB.Map8;
1319 const GLubyte *aMap = ctx->PixelMaps.ItoA.Map8;
1320 GLuint i;
1321 for (i=0;i<n;i++) {
1322 rgba[i][RCOMP] = rMap[index[i] & rmask];
1323 rgba[i][GCOMP] = gMap[index[i] & gmask];
1324 rgba[i][BCOMP] = bMap[index[i] & bmask];
1325 rgba[i][ACOMP] = aMap[index[i] & amask];
1326 }
1327 }
1328
1329
1330 void
1331 _mesa_scale_and_bias_depth(const GLcontext *ctx, GLuint n,
1332 GLfloat depthValues[])
1333 {
1334 const GLfloat scale = ctx->Pixel.DepthScale;
1335 const GLfloat bias = ctx->Pixel.DepthBias;
1336 GLuint i;
1337 for (i = 0; i < n; i++) {
1338 GLfloat d = depthValues[i] * scale + bias;
1339 depthValues[i] = CLAMP(d, 0.0F, 1.0F);
1340 }
1341 }
1342
1343
1344
1345 /**********************************************************************/
1346 /***** State Management *****/
1347 /**********************************************************************/
1348
1349 /*
1350 * Return a bitmask of IMAGE_*_BIT flags which to indicate which
1351 * pixel transfer operations are enabled.
1352 */
1353 static void
1354 update_image_transfer_state(GLcontext *ctx)
1355 {
1356 GLuint mask = 0;
1357
1358 if (ctx->Pixel.RedScale != 1.0F || ctx->Pixel.RedBias != 0.0F ||
1359 ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F ||
1360 ctx->Pixel.BlueScale != 1.0F || ctx->Pixel.BlueBias != 0.0F ||
1361 ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F)
1362 mask |= IMAGE_SCALE_BIAS_BIT;
1363
1364 if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset)
1365 mask |= IMAGE_SHIFT_OFFSET_BIT;
1366
1367 if (ctx->Pixel.MapColorFlag)
1368 mask |= IMAGE_MAP_COLOR_BIT;
1369
1370 if (ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION])
1371 mask |= IMAGE_COLOR_TABLE_BIT;
1372
1373 if (ctx->Pixel.Convolution1DEnabled ||
1374 ctx->Pixel.Convolution2DEnabled ||
1375 ctx->Pixel.Separable2DEnabled) {
1376 mask |= IMAGE_CONVOLUTION_BIT;
1377 if (ctx->Pixel.PostConvolutionScale[0] != 1.0F ||
1378 ctx->Pixel.PostConvolutionScale[1] != 1.0F ||
1379 ctx->Pixel.PostConvolutionScale[2] != 1.0F ||
1380 ctx->Pixel.PostConvolutionScale[3] != 1.0F ||
1381 ctx->Pixel.PostConvolutionBias[0] != 0.0F ||
1382 ctx->Pixel.PostConvolutionBias[1] != 0.0F ||
1383 ctx->Pixel.PostConvolutionBias[2] != 0.0F ||
1384 ctx->Pixel.PostConvolutionBias[3] != 0.0F) {
1385 mask |= IMAGE_POST_CONVOLUTION_SCALE_BIAS;
1386 }
1387 }
1388
1389 if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION])
1390 mask |= IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT;
1391
1392 if (ctx->ColorMatrixStack.Top->type != MATRIX_IDENTITY ||
1393 ctx->Pixel.PostColorMatrixScale[0] != 1.0F ||
1394 ctx->Pixel.PostColorMatrixBias[0] != 0.0F ||
1395 ctx->Pixel.PostColorMatrixScale[1] != 1.0F ||
1396 ctx->Pixel.PostColorMatrixBias[1] != 0.0F ||
1397 ctx->Pixel.PostColorMatrixScale[2] != 1.0F ||
1398 ctx->Pixel.PostColorMatrixBias[2] != 0.0F ||
1399 ctx->Pixel.PostColorMatrixScale[3] != 1.0F ||
1400 ctx->Pixel.PostColorMatrixBias[3] != 0.0F)
1401 mask |= IMAGE_COLOR_MATRIX_BIT;
1402
1403 if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX])
1404 mask |= IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT;
1405
1406 if (ctx->Pixel.HistogramEnabled)
1407 mask |= IMAGE_HISTOGRAM_BIT;
1408
1409 if (ctx->Pixel.MinMaxEnabled)
1410 mask |= IMAGE_MIN_MAX_BIT;
1411
1412 ctx->_ImageTransferState = mask;
1413 }
1414
1415
1416 void _mesa_update_pixel( GLcontext *ctx, GLuint new_state )
1417 {
1418 if (new_state & _NEW_COLOR_MATRIX)
1419 _math_matrix_analyse( ctx->ColorMatrixStack.Top );
1420
1421 /* References ColorMatrix.type (derived above).
1422 */
1423 if (new_state & _IMAGE_NEW_TRANSFER_STATE)
1424 update_image_transfer_state(ctx);
1425 }
1426
1427
1428 /**********************************************************************/
1429 /***** Initialization *****/
1430 /**********************************************************************/
1431
1432 static void
1433 init_pixelmap(struct gl_pixelmap *map)
1434 {
1435 map->Size = 1;
1436 map->Map[0] = 0.0;
1437 map->Map8[0] = 0;
1438 }
1439
1440
1441 /**
1442 * Initialize the context's PIXEL attribute group.
1443 */
1444 void
1445 _mesa_init_pixel( GLcontext *ctx )
1446 {
1447 int i;
1448
1449 /* Pixel group */
1450 ctx->Pixel.RedBias = 0.0;
1451 ctx->Pixel.RedScale = 1.0;
1452 ctx->Pixel.GreenBias = 0.0;
1453 ctx->Pixel.GreenScale = 1.0;
1454 ctx->Pixel.BlueBias = 0.0;
1455 ctx->Pixel.BlueScale = 1.0;
1456 ctx->Pixel.AlphaBias = 0.0;
1457 ctx->Pixel.AlphaScale = 1.0;
1458 ctx->Pixel.DepthBias = 0.0;
1459 ctx->Pixel.DepthScale = 1.0;
1460 ctx->Pixel.IndexOffset = 0;
1461 ctx->Pixel.IndexShift = 0;
1462 ctx->Pixel.ZoomX = 1.0;
1463 ctx->Pixel.ZoomY = 1.0;
1464 ctx->Pixel.MapColorFlag = GL_FALSE;
1465 ctx->Pixel.MapStencilFlag = GL_FALSE;
1466 init_pixelmap(&ctx->PixelMaps.StoS);
1467 init_pixelmap(&ctx->PixelMaps.ItoI);
1468 init_pixelmap(&ctx->PixelMaps.ItoR);
1469 init_pixelmap(&ctx->PixelMaps.ItoG);
1470 init_pixelmap(&ctx->PixelMaps.ItoB);
1471 init_pixelmap(&ctx->PixelMaps.ItoA);
1472 init_pixelmap(&ctx->PixelMaps.RtoR);
1473 init_pixelmap(&ctx->PixelMaps.GtoG);
1474 init_pixelmap(&ctx->PixelMaps.BtoB);
1475 init_pixelmap(&ctx->PixelMaps.AtoA);
1476 ctx->Pixel.HistogramEnabled = GL_FALSE;
1477 ctx->Pixel.MinMaxEnabled = GL_FALSE;
1478 ASSIGN_4V(ctx->Pixel.PostColorMatrixScale, 1.0, 1.0, 1.0, 1.0);
1479 ASSIGN_4V(ctx->Pixel.PostColorMatrixBias, 0.0, 0.0, 0.0, 0.0);
1480 for (i = 0; i < COLORTABLE_MAX; i++) {
1481 ASSIGN_4V(ctx->Pixel.ColorTableScale[i], 1.0, 1.0, 1.0, 1.0);
1482 ASSIGN_4V(ctx->Pixel.ColorTableBias[i], 0.0, 0.0, 0.0, 0.0);
1483 ctx->Pixel.ColorTableEnabled[i] = GL_FALSE;
1484 }
1485 ctx->Pixel.Convolution1DEnabled = GL_FALSE;
1486 ctx->Pixel.Convolution2DEnabled = GL_FALSE;
1487 ctx->Pixel.Separable2DEnabled = GL_FALSE;
1488 for (i = 0; i < 3; i++) {
1489 ASSIGN_4V(ctx->Pixel.ConvolutionBorderColor[i], 0.0, 0.0, 0.0, 0.0);
1490 ctx->Pixel.ConvolutionBorderMode[i] = GL_REDUCE;
1491 ASSIGN_4V(ctx->Pixel.ConvolutionFilterScale[i], 1.0, 1.0, 1.0, 1.0);
1492 ASSIGN_4V(ctx->Pixel.ConvolutionFilterBias[i], 0.0, 0.0, 0.0, 0.0);
1493 }
1494 for (i = 0; i < MAX_CONVOLUTION_WIDTH * MAX_CONVOLUTION_WIDTH * 4; i++) {
1495 ctx->Convolution1D.Filter[i] = 0.0;
1496 ctx->Convolution2D.Filter[i] = 0.0;
1497 ctx->Separable2D.Filter[i] = 0.0;
1498 }
1499 ASSIGN_4V(ctx->Pixel.PostConvolutionScale, 1.0, 1.0, 1.0, 1.0);
1500 ASSIGN_4V(ctx->Pixel.PostConvolutionBias, 0.0, 0.0, 0.0, 0.0);
1501 /* GL_SGI_texture_color_table */
1502 ASSIGN_4V(ctx->Pixel.TextureColorTableScale, 1.0, 1.0, 1.0, 1.0);
1503 ASSIGN_4V(ctx->Pixel.TextureColorTableBias, 0.0, 0.0, 0.0, 0.0);
1504
1505 /* Pixel transfer */
1506 ctx->Pack.Alignment = 4;
1507 ctx->Pack.RowLength = 0;
1508 ctx->Pack.ImageHeight = 0;
1509 ctx->Pack.SkipPixels = 0;
1510 ctx->Pack.SkipRows = 0;
1511 ctx->Pack.SkipImages = 0;
1512 ctx->Pack.SwapBytes = GL_FALSE;
1513 ctx->Pack.LsbFirst = GL_FALSE;
1514 ctx->Pack.ClientStorage = GL_FALSE;
1515 ctx->Pack.Invert = GL_FALSE;
1516 #if FEATURE_EXT_pixel_buffer_object
1517 ctx->Pack.BufferObj = ctx->Array.NullBufferObj;
1518 #endif
1519 ctx->Unpack.Alignment = 4;
1520 ctx->Unpack.RowLength = 0;
1521 ctx->Unpack.ImageHeight = 0;
1522 ctx->Unpack.SkipPixels = 0;
1523 ctx->Unpack.SkipRows = 0;
1524 ctx->Unpack.SkipImages = 0;
1525 ctx->Unpack.SwapBytes = GL_FALSE;
1526 ctx->Unpack.LsbFirst = GL_FALSE;
1527 ctx->Unpack.ClientStorage = GL_FALSE;
1528 ctx->Unpack.Invert = GL_FALSE;
1529 #if FEATURE_EXT_pixel_buffer_object
1530 ctx->Unpack.BufferObj = ctx->Array.NullBufferObj;
1531 #endif
1532
1533 /*
1534 * _mesa_unpack_image() returns image data in this format. When we
1535 * execute image commands (glDrawPixels(), glTexImage(), etc) from
1536 * within display lists we have to be sure to set the current
1537 * unpacking parameters to these values!
1538 */
1539 ctx->DefaultPacking.Alignment = 1;
1540 ctx->DefaultPacking.RowLength = 0;
1541 ctx->DefaultPacking.SkipPixels = 0;
1542 ctx->DefaultPacking.SkipRows = 0;
1543 ctx->DefaultPacking.ImageHeight = 0;
1544 ctx->DefaultPacking.SkipImages = 0;
1545 ctx->DefaultPacking.SwapBytes = GL_FALSE;
1546 ctx->DefaultPacking.LsbFirst = GL_FALSE;
1547 ctx->DefaultPacking.ClientStorage = GL_FALSE;
1548 ctx->DefaultPacking.Invert = GL_FALSE;
1549 #if FEATURE_EXT_pixel_buffer_object
1550 ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
1551 #endif
1552
1553 if (ctx->Visual.doubleBufferMode) {
1554 ctx->Pixel.ReadBuffer = GL_BACK;
1555 }
1556 else {
1557 ctx->Pixel.ReadBuffer = GL_FRONT;
1558 }
1559
1560 /* Miscellaneous */
1561 ctx->_ImageTransferState = 0;
1562 }