1 /* $Id: pixel.c,v 1.8 1997/07/24 01:23:44 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 2.4
6 * Copyright (C) 1995-1997 Brian Paul
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23
24 /*
25 * $Log: pixel.c,v $
26 * Revision 1.8 1997/07/24 01:23:44 brianp
27 * changed precompiled header symbol from PCH to PC_HEADER
28 *
29 * Revision 1.7 1997/05/28 03:26:02 brianp
30 * added precompiled header (PCH) support
31 *
32 * Revision 1.6 1997/02/09 20:05:03 brianp
33 * new arguments for gl_pixel_addr_in_image()
34 *
35 * Revision 1.5 1997/02/09 18:52:37 brianp
36 * added GL_EXT_texture3D support
37 *
38 * Revision 1.4 1996/11/06 04:09:37 brianp
39 * added a missing return after a gl_error() call
40 *
41 * Revision 1.3 1996/09/26 22:35:10 brianp
42 * fixed a few compiler warnings from IRIX 6 -n32 and -64 compiler
43 *
44 * Revision 1.2 1996/09/15 14:18:55 brianp
45 * now use GLframebuffer and GLvisual
46 *
47 * Revision 1.1 1996/09/13 01:38:16 brianp
48 * Initial revision
49 *
50 */
51
52
53 /*
54 * glPixelStore, glPixelTransfer, glPixelMap, glPixelZoom, etc.
55 */
56
57
58 #ifdef PC_HEADER
59 #include "all.h"
60 #else
61 #include <assert.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include "context.h"
66 #include "dlist.h"
67 #include "macros.h"
68 #include "pixel.h"
69 #include "image.h"
70 #include "span.h"
71 #include "stencil.h"
72 #include "types.h"
73 #endif
74
75
76
77 /*
78 * Determine if we can use the optimized glDrawPixels function.
79 */
update_drawpixels_state(GLcontext * ctx)80 static void update_drawpixels_state( GLcontext *ctx )
81 {
82 if (ctx->Visual->RGBAflag==GL_TRUE &&
83 ctx->Visual->EightBitColor &&
84 ctx->Pixel.RedBias==0.0 && ctx->Pixel.RedScale==1.0 &&
85 ctx->Pixel.GreenBias==0.0 && ctx->Pixel.GreenScale==1.0 &&
86 ctx->Pixel.BlueBias==0.0 && ctx->Pixel.BlueScale==1.0 &&
87 ctx->Pixel.AlphaBias==0.0 && ctx->Pixel.AlphaScale==1.0 &&
88 ctx->Pixel.MapColorFlag==GL_FALSE &&
89 ctx->Pixel.ZoomX==1.0 && ctx->Pixel.ZoomY==1.0 &&
90 /* ctx->Unpack.Alignment==4 &&*/
91 ctx->Unpack.RowLength==0 &&
92 ctx->Unpack.SkipPixels==0 &&
93 ctx->Unpack.SkipRows==0 &&
94 ctx->Unpack.SwapBytes==0 &&
95 ctx->Unpack.LsbFirst==0) {
96 ctx->FastDrawPixels = GL_TRUE;
97 }
98 else {
99 ctx->FastDrawPixels = GL_FALSE;
100 }
101 }
102
103
104
105
106 /**********************************************************************/
107 /***** glPixelZoom *****/
108 /**********************************************************************/
109
110
111
gl_PixelZoom(GLcontext * ctx,GLfloat xfactor,GLfloat yfactor)112 void gl_PixelZoom( GLcontext *ctx, GLfloat xfactor, GLfloat yfactor )
113 {
114 if (INSIDE_BEGIN_END(ctx)) {
115 gl_error( ctx, GL_INVALID_OPERATION, "glPixelZoom" );
116 return;
117 }
118 ctx->Pixel.ZoomX = xfactor;
119 ctx->Pixel.ZoomY = yfactor;
120 update_drawpixels_state( ctx );
121 }
122
123
124
125
126 /*
127 * Write a span of pixels to the frame buffer while applying a pixel zoom.
128 * This is only used by glDrawPixels and glCopyPixels.
129 * Input: n - number of pixels in input row
130 * x, y - destination of the span
131 * z - depth values for the span
132 * red, green, blue, alpha - array of colors
133 * y0 - location of first row in the image we're drawing.
134 */
135 void
gl_write_zoomed_color_span(GLcontext * ctx,GLuint n,GLint x,GLint y,const GLdepth z[],const GLubyte red[],const GLubyte green[],const GLubyte blue[],const GLubyte alpha[],GLint y0)136 gl_write_zoomed_color_span( GLcontext *ctx,
137 GLuint n, GLint x, GLint y, const GLdepth z[],
138 const GLubyte red[], const GLubyte green[],
139 const GLubyte blue[], const GLubyte alpha[],
140 GLint y0 )
141 {
142 GLint m;
143 GLint r0, r1, row, r;
144 GLint i, j, skipcol;
145 GLubyte zred[MAX_WIDTH], zgreen[MAX_WIDTH]; /* zoomed pixel colors */
146 GLubyte zblue[MAX_WIDTH], zalpha[MAX_WIDTH];
147 GLdepth zdepth[MAX_WIDTH]; /* zoomed depth values */
148 GLint maxwidth = MIN2( ctx->Buffer->Width, MAX_WIDTH );
149
150 /* compute width of output row */
151 m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
152 if (m==0) {
153 return;
154 }
155 if (ctx->Pixel.ZoomX<0.0) {
156 /* adjust x coordinate for left/right mirroring */
157 x = x - m;
158 }
159
160 /* compute which rows to draw */
161 row = y-y0;
162 r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
163 r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
164 if (r0==r1) {
165 return;
166 }
167 else if (r1<r0) {
168 GLint rtmp = r1;
169 r1 = r0;
170 r0 = rtmp;
171 }
172
173 /* return early if r0...r1 is above or below window */
174 if (r0<0 && r1<0) {
175 /* below window */
176 return;
177 }
178 if (r0>=ctx->Buffer->Height && r1>=ctx->Buffer->Height) {
179 /* above window */
180 return;
181 }
182
183 /* check if left edge is outside window */
184 skipcol = 0;
185 if (x<0) {
186 skipcol = -x;
187 m += x;
188 }
189 /* make sure span isn't too long or short */
190 if (m>maxwidth) {
191 m = maxwidth;
192 }
193 else if (m<=0) {
194 return;
195 }
196
197 assert( m <= MAX_WIDTH );
198
199 /* zoom the span horizontally */
200 if (ctx->Pixel.ZoomX==-1.0F) {
201 /* n==m */
202 for (j=0;j<m;j++) {
203 i = n - (j+skipcol) - 1;
204 zred[j] = red[i];
205 zgreen[j] = green[i];
206 zblue[j] = blue[i];
207 zalpha[j] = alpha[i];
208 zdepth[j] = z[i];
209 }
210 }
211 else {
212 GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
213 for (j=0;j<m;j++) {
214 i = (j+skipcol) * xscale;
215 if (i<0) i = n + i - 1;
216 zred[j] = red[i];
217 zgreen[j] = green[i];
218 zblue[j] = blue[i];
219 zalpha[j] = alpha[i];
220 zdepth[j] = z[i];
221 }
222 }
223
224 /* write the span */
225 for (r=r0; r<r1; r++) {
226 gl_write_color_span( ctx, m, x+skipcol, r, zdepth,
227 zred, zgreen, zblue, zalpha, GL_BITMAP );
228 }
229 }
230
231
232
233 /*
234 * As above, but write CI pixels.
235 */
236 void
gl_write_zoomed_index_span(GLcontext * ctx,GLuint n,GLint x,GLint y,const GLdepth z[],const GLuint indexes[],GLint y0)237 gl_write_zoomed_index_span( GLcontext *ctx,
238 GLuint n, GLint x, GLint y, const GLdepth z[],
239 const GLuint indexes[], GLint y0 )
240 {
241 GLint m;
242 GLint r0, r1, row, r;
243 GLint i, j, skipcol;
244 GLuint zindexes[MAX_WIDTH]; /* zoomed color indexes */
245 GLdepth zdepth[MAX_WIDTH]; /* zoomed depth values */
246 GLint maxwidth = MIN2( ctx->Buffer->Width, MAX_WIDTH );
247
248 /* compute width of output row */
249 m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
250 if (m==0) {
251 return;
252 }
253 if (ctx->Pixel.ZoomX<0.0) {
254 /* adjust x coordinate for left/right mirroring */
255 x = x - m;
256 }
257
258 /* compute which rows to draw */
259 row = y-y0;
260 r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
261 r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
262 if (r0==r1) {
263 return;
264 }
265 else if (r1<r0) {
266 GLint rtmp = r1;
267 r1 = r0;
268 r0 = rtmp;
269 }
270
271 /* return early if r0...r1 is above or below window */
272 if (r0<0 && r1<0) {
273 /* below window */
274 return;
275 }
276 if (r0>=ctx->Buffer->Height && r1>=ctx->Buffer->Height) {
277 /* above window */
278 return;
279 }
280
281 /* check if left edge is outside window */
282 skipcol = 0;
283 if (x<0) {
284 skipcol = -x;
285 m += x;
286 }
287 /* make sure span isn't too long or short */
288 if (m>maxwidth) {
289 m = maxwidth;
290 }
291 else if (m<=0) {
292 return;
293 }
294
295 assert( m <= MAX_WIDTH );
296
297 /* zoom the span horizontally */
298 if (ctx->Pixel.ZoomX==-1.0F) {
299 /* n==m */
300 for (j=0;j<m;j++) {
301 i = n - (j+skipcol) - 1;
302 zindexes[j] = indexes[i];
303 zdepth[j] = z[i];
304 }
305 }
306 else {
307 GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
308 for (j=0;j<m;j++) {
309 i = (j+skipcol) * xscale;
310 if (i<0) i = n + i - 1;
311 zindexes[j] = indexes[i];
312 zdepth[j] = z[i];
313 }
314 }
315
316 /* write the span */
317 for (r=r0; r<r1; r++) {
318 gl_write_index_span( ctx, m, x+skipcol, r, zdepth, zindexes, GL_BITMAP );
319 }
320 }
321
322
323
324 /*
325 * As above, but write stencil values.
326 */
327 void
gl_write_zoomed_stencil_span(GLcontext * ctx,GLuint n,GLint x,GLint y,const GLubyte stencil[],GLint y0)328 gl_write_zoomed_stencil_span( GLcontext *ctx,
329 GLuint n, GLint x, GLint y,
330 const GLubyte stencil[], GLint y0 )
331 {
332 GLint m;
333 GLint r0, r1, row, r;
334 GLint i, j, skipcol;
335 GLubyte zstencil[MAX_WIDTH]; /* zoomed stencil values */
336 GLint maxwidth = MIN2( ctx->Buffer->Width, MAX_WIDTH );
337
338 /* compute width of output row */
339 m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
340 if (m==0) {
341 return;
342 }
343 if (ctx->Pixel.ZoomX<0.0) {
344 /* adjust x coordinate for left/right mirroring */
345 x = x - m;
346 }
347
348 /* compute which rows to draw */
349 row = y-y0;
350 r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
351 r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
352 if (r0==r1) {
353 return;
354 }
355 else if (r1<r0) {
356 GLint rtmp = r1;
357 r1 = r0;
358 r0 = rtmp;
359 }
360
361 /* return early if r0...r1 is above or below window */
362 if (r0<0 && r1<0) {
363 /* below window */
364 return;
365 }
366 if (r0>=ctx->Buffer->Height && r1>=ctx->Buffer->Height) {
367 /* above window */
368 return;
369 }
370
371 /* check if left edge is outside window */
372 skipcol = 0;
373 if (x<0) {
374 skipcol = -x;
375 m += x;
376 }
377 /* make sure span isn't too long or short */
378 if (m>maxwidth) {
379 m = maxwidth;
380 }
381 else if (m<=0) {
382 return;
383 }
384
385 assert( m <= MAX_WIDTH );
386
387 /* zoom the span horizontally */
388 if (ctx->Pixel.ZoomX==-1.0F) {
389 /* n==m */
390 for (j=0;j<m;j++) {
391 i = n - (j+skipcol) - 1;
392 zstencil[j] = stencil[i];
393 }
394 }
395 else {
396 GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
397 for (j=0;j<m;j++) {
398 i = (j+skipcol) * xscale;
399 if (i<0) i = n + i - 1;
400 zstencil[j] = stencil[i];
401 }
402 }
403
404 /* write the span */
405 for (r=r0; r<r1; r++) {
406 gl_write_stencil_span( ctx, m, x+skipcol, r, zstencil );
407 }
408 }
409
410
411
412
413 /**********************************************************************/
414 /***** glPixelStore *****/
415 /**********************************************************************/
416
417
gl_PixelStorei(GLcontext * ctx,GLenum pname,GLint param)418 void gl_PixelStorei( GLcontext *ctx, GLenum pname, GLint param )
419 {
420 /* NOTE: this call can't be compiled into the display list */
421
422 if (INSIDE_BEGIN_END(ctx)) {
423 gl_error( ctx, GL_INVALID_OPERATION, "glPixelStore" );
424 return;
425 }
426
427 switch (pname) {
428 case GL_PACK_SWAP_BYTES:
429 ctx->Pack.SwapBytes = param ? GL_TRUE : GL_FALSE;
430 break;
431 case GL_PACK_LSB_FIRST:
432 ctx->Pack.LsbFirst = param ? GL_TRUE : GL_FALSE;
433 break;
434 case GL_PACK_ROW_LENGTH:
435 if (param<0) {
436 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
437 }
438 else {
439 ctx->Pack.RowLength = param;
440 }
441 break;
442 case GL_PACK_SKIP_PIXELS:
443 if (param<0) {
444 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
445 }
446 else {
447 ctx->Pack.SkipPixels = param;
448 }
449 break;
450 case GL_PACK_SKIP_ROWS:
451 if (param<0) {
452 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
453 }
454 else {
455 ctx->Pack.SkipRows = param;
456 }
457 break;
458 case GL_PACK_ALIGNMENT:
459 if (param==1 || param==2 || param==4 || param==8) {
460 ctx->Pack.Alignment = param;
461 }
462 else {
463 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
464 }
465 break;
466 case GL_UNPACK_SWAP_BYTES:
467 ctx->Unpack.SwapBytes = param ? GL_TRUE : GL_FALSE;
468 break;
469 case GL_UNPACK_LSB_FIRST:
470 ctx->Unpack.LsbFirst = param ? GL_TRUE : GL_FALSE;
471 break;
472 case GL_UNPACK_ROW_LENGTH:
473 if (param<0) {
474 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
475 }
476 else {
477 ctx->Unpack.RowLength = param;
478 }
479 break;
480 case GL_UNPACK_SKIP_PIXELS:
481 if (param<0) {
482 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
483 }
484 else {
485 ctx->Unpack.SkipPixels = param;
486 }
487 break;
488 case GL_UNPACK_SKIP_ROWS:
489 if (param<0) {
490 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
491 }
492 else {
493 ctx->Unpack.SkipRows = param;
494 }
495 break;
496 case GL_UNPACK_ALIGNMENT:
497 if (param==1 || param==2 || param==4 || param==8) {
498 ctx->Unpack.Alignment = param;
499 }
500 else {
501 gl_error( ctx, GL_INVALID_VALUE, "glPixelStore" );
502 }
503 break;
504 default:
505 gl_error( ctx, GL_INVALID_ENUM, "glPixelStore" );
506 }
507 update_drawpixels_state( ctx );
508 }
509
510
511
512
513
514 /**********************************************************************/
515 /***** glPixelMap *****/
516 /**********************************************************************/
517
518
519
gl_PixelMapfv(GLcontext * ctx,GLenum map,GLint mapsize,const GLfloat * values)520 void gl_PixelMapfv( GLcontext *ctx,
521 GLenum map, GLint mapsize, const GLfloat *values )
522 {
523 GLuint i;
524
525 if (INSIDE_BEGIN_END(ctx)) {
526 gl_error( ctx, GL_INVALID_OPERATION, "glPixelMapfv" );
527 return;
528 }
529
530 if (mapsize<0 || mapsize>MAX_PIXEL_MAP_TABLE) {
531 gl_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
532 return;
533 }
534
535 if (map>=GL_PIXEL_MAP_S_TO_S && map<=GL_PIXEL_MAP_I_TO_A) {
536 /* test that mapsize is a power of two */
537 GLuint p;
538 GLboolean ok = GL_FALSE;
539 for (p=1; p<=MAX_PIXEL_MAP_TABLE; p=p<<1) {
540 if ( (p&mapsize) == p ) {
541 ok = GL_TRUE;
542 break;
543 }
544 }
545 if (!ok) {
546 gl_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
547 return;
548 }
549 }
550
551 switch (map) {
552 case GL_PIXEL_MAP_S_TO_S:
553 ctx->Pixel.MapStoSsize = mapsize;
554 for (i=0;i<mapsize;i++) {
555 ctx->Pixel.MapStoS[i] = (GLint) values[i];
556 }
557 break;
558 case GL_PIXEL_MAP_I_TO_I:
559 ctx->Pixel.MapItoIsize = mapsize;
560 for (i=0;i<mapsize;i++) {
561 ctx->Pixel.MapItoI[i] = (GLint) values[i];
562 }
563 break;
564 case GL_PIXEL_MAP_I_TO_R:
565 ctx->Pixel.MapItoRsize = mapsize;
566 for (i=0;i<mapsize;i++) {
567 ctx->Pixel.MapItoR[i] = CLAMP( values[i], 0.0, 1.0 );
568 }
569 break;
570 case GL_PIXEL_MAP_I_TO_G:
571 ctx->Pixel.MapItoGsize = mapsize;
572 for (i=0;i<mapsize;i++) {
573 ctx->Pixel.MapItoG[i] = CLAMP( values[i], 0.0, 1.0 );
574 }
575 break;
576 case GL_PIXEL_MAP_I_TO_B:
577 ctx->Pixel.MapItoBsize = mapsize;
578 for (i=0;i<mapsize;i++) {
579 ctx->Pixel.MapItoB[i] = CLAMP( values[i], 0.0, 1.0 );
580 }
581 break;
582 case GL_PIXEL_MAP_I_TO_A:
583 ctx->Pixel.MapItoAsize = mapsize;
584 for (i=0;i<mapsize;i++) {
585 ctx->Pixel.MapItoA[i] = CLAMP( values[i], 0.0, 1.0 );
586 }
587 break;
588 case GL_PIXEL_MAP_R_TO_R:
589 ctx->Pixel.MapRtoRsize = mapsize;
590 for (i=0;i<mapsize;i++) {
591 ctx->Pixel.MapRtoR[i] = CLAMP( values[i], 0.0, 1.0 );
592 }
593 break;
594 case GL_PIXEL_MAP_G_TO_G:
595 ctx->Pixel.MapGtoGsize = mapsize;
596 for (i=0;i<mapsize;i++) {
597 ctx->Pixel.MapGtoG[i] = CLAMP( values[i], 0.0, 1.0 );
598 }
599 break;
600 case GL_PIXEL_MAP_B_TO_B:
601 ctx->Pixel.MapBtoBsize = mapsize;
602 for (i=0;i<mapsize;i++) {
603 ctx->Pixel.MapBtoB[i] = CLAMP( values[i], 0.0, 1.0 );
604 }
605 break;
606 case GL_PIXEL_MAP_A_TO_A:
607 ctx->Pixel.MapAtoAsize = mapsize;
608 for (i=0;i<mapsize;i++) {
609 ctx->Pixel.MapAtoA[i] = CLAMP( values[i], 0.0, 1.0 );
610 }
611 break;
612 default:
613 gl_error( ctx, GL_INVALID_ENUM, "glPixelMapfv(map)" );
614 }
615 }
616
617
618
619
620
gl_GetPixelMapfv(GLcontext * ctx,GLenum map,GLfloat * values)621 void gl_GetPixelMapfv( GLcontext *ctx, GLenum map, GLfloat *values )
622 {
623 GLuint i;
624
625 if (INSIDE_BEGIN_END(ctx)) {
626 gl_error( ctx, GL_INVALID_OPERATION, "glGetPixelMapfv" );
627 return;
628 }
629 switch (map) {
630 case GL_PIXEL_MAP_I_TO_I:
631 for (i=0;i<ctx->Pixel.MapItoIsize;i++) {
632 values[i] = (GLfloat) ctx->Pixel.MapItoI[i];
633 }
634 break;
635 case GL_PIXEL_MAP_S_TO_S:
636 for (i=0;i<ctx->Pixel.MapStoSsize;i++) {
637 values[i] = (GLfloat) ctx->Pixel.MapStoS[i];
638 }
639 break;
640 case GL_PIXEL_MAP_I_TO_R:
641 MEMCPY(values,ctx->Pixel.MapItoR,ctx->Pixel.MapItoRsize*sizeof(GLfloat));
642 break;
643 case GL_PIXEL_MAP_I_TO_G:
644 MEMCPY(values,ctx->Pixel.MapItoG,ctx->Pixel.MapItoGsize*sizeof(GLfloat));
645 break;
646 case GL_PIXEL_MAP_I_TO_B:
647 MEMCPY(values,ctx->Pixel.MapItoB,ctx->Pixel.MapItoBsize*sizeof(GLfloat));
648 break;
649 case GL_PIXEL_MAP_I_TO_A:
650 MEMCPY(values,ctx->Pixel.MapItoA,ctx->Pixel.MapItoAsize*sizeof(GLfloat));
651 break;
652 case GL_PIXEL_MAP_R_TO_R:
653 MEMCPY(values,ctx->Pixel.MapRtoR,ctx->Pixel.MapRtoRsize*sizeof(GLfloat));
654 break;
655 case GL_PIXEL_MAP_G_TO_G:
656 MEMCPY(values,ctx->Pixel.MapGtoG,ctx->Pixel.MapGtoGsize*sizeof(GLfloat));
657 break;
658 case GL_PIXEL_MAP_B_TO_B:
659 MEMCPY(values,ctx->Pixel.MapBtoB,ctx->Pixel.MapBtoBsize*sizeof(GLfloat));
660 break;
661 case GL_PIXEL_MAP_A_TO_A:
662 MEMCPY(values,ctx->Pixel.MapAtoA,ctx->Pixel.MapAtoAsize*sizeof(GLfloat));
663 break;
664 default:
665 gl_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" );
666 }
667 }
668
669
gl_GetPixelMapuiv(GLcontext * ctx,GLenum map,GLuint * values)670 void gl_GetPixelMapuiv( GLcontext *ctx, GLenum map, GLuint *values )
671 {
672 GLuint i;
673
674 if (INSIDE_BEGIN_END(ctx)) {
675 gl_error( ctx, GL_INVALID_OPERATION, "glGetPixelMapfv" );
676 return;
677 }
678 switch (map) {
679 case GL_PIXEL_MAP_I_TO_I:
680 MEMCPY(values, ctx->Pixel.MapItoI, ctx->Pixel.MapItoIsize*sizeof(GLint));
681 break;
682 case GL_PIXEL_MAP_S_TO_S:
683 MEMCPY(values, ctx->Pixel.MapStoS, ctx->Pixel.MapStoSsize*sizeof(GLint));
684 break;
685 case GL_PIXEL_MAP_I_TO_R:
686 for (i=0;i<ctx->Pixel.MapItoRsize;i++) {
687 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoR[i] );
688 }
689 break;
690 case GL_PIXEL_MAP_I_TO_G:
691 for (i=0;i<ctx->Pixel.MapItoGsize;i++) {
692 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoG[i] );
693 }
694 break;
695 case GL_PIXEL_MAP_I_TO_B:
696 for (i=0;i<ctx->Pixel.MapItoBsize;i++) {
697 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoB[i] );
698 }
699 break;
700 case GL_PIXEL_MAP_I_TO_A:
701 for (i=0;i<ctx->Pixel.MapItoAsize;i++) {
702 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoA[i] );
703 }
704 break;
705 case GL_PIXEL_MAP_R_TO_R:
706 for (i=0;i<ctx->Pixel.MapRtoRsize;i++) {
707 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapRtoR[i] );
708 }
709 break;
710 case GL_PIXEL_MAP_G_TO_G:
711 for (i=0;i<ctx->Pixel.MapGtoGsize;i++) {
712 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapGtoG[i] );
713 }
714 break;
715 case GL_PIXEL_MAP_B_TO_B:
716 for (i=0;i<ctx->Pixel.MapBtoBsize;i++) {
717 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapBtoB[i] );
718 }
719 break;
720 case GL_PIXEL_MAP_A_TO_A:
721 for (i=0;i<ctx->Pixel.MapAtoAsize;i++) {
722 values[i] = FLOAT_TO_UINT( ctx->Pixel.MapAtoA[i] );
723 }
724 break;
725 default:
726 gl_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" );
727 }
728 }
729
730
gl_GetPixelMapusv(GLcontext * ctx,GLenum map,GLushort * values)731 void gl_GetPixelMapusv( GLcontext *ctx, GLenum map, GLushort *values )
732 {
733 GLuint i;
734
735 if (INSIDE_BEGIN_END(ctx)) {
736 gl_error( ctx, GL_INVALID_OPERATION, "glGetPixelMapfv" );
737 return;
738 }
739 switch (map) {
740 case GL_PIXEL_MAP_I_TO_I:
741 for (i=0;i<ctx->Pixel.MapItoIsize;i++) {
742 values[i] = (GLushort) ctx->Pixel.MapItoI[i];
743 }
744 break;
745 case GL_PIXEL_MAP_S_TO_S:
746 for (i=0;i<ctx->Pixel.MapStoSsize;i++) {
747 values[i] = (GLushort) ctx->Pixel.MapStoS[i];
748 }
749 break;
750 case GL_PIXEL_MAP_I_TO_R:
751 for (i=0;i<ctx->Pixel.MapItoRsize;i++) {
752 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoR[i] );
753 }
754 break;
755 case GL_PIXEL_MAP_I_TO_G:
756 for (i=0;i<ctx->Pixel.MapItoGsize;i++) {
757 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoG[i] );
758 }
759 break;
760 case GL_PIXEL_MAP_I_TO_B:
761 for (i=0;i<ctx->Pixel.MapItoBsize;i++) {
762 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoB[i] );
763 }
764 break;
765 case GL_PIXEL_MAP_I_TO_A:
766 for (i=0;i<ctx->Pixel.MapItoAsize;i++) {
767 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoA[i] );
768 }
769 break;
770 case GL_PIXEL_MAP_R_TO_R:
771 for (i=0;i<ctx->Pixel.MapRtoRsize;i++) {
772 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapRtoR[i] );
773 }
774 break;
775 case GL_PIXEL_MAP_G_TO_G:
776 for (i=0;i<ctx->Pixel.MapGtoGsize;i++) {
777 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapGtoG[i] );
778 }
779 break;
780 case GL_PIXEL_MAP_B_TO_B:
781 for (i=0;i<ctx->Pixel.MapBtoBsize;i++) {
782 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapBtoB[i] );
783 }
784 break;
785 case GL_PIXEL_MAP_A_TO_A:
786 for (i=0;i<ctx->Pixel.MapAtoAsize;i++) {
787 values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapAtoA[i] );
788 }
789 break;
790 default:
791 gl_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" );
792 }
793 }
794
795
796
797 /**********************************************************************/
798 /***** glPixelTransfer *****/
799 /**********************************************************************/
800
801
802 /*
803 * Implements glPixelTransfer[fi] whether called immediately or from a
804 * display list.
805 */
gl_PixelTransferf(GLcontext * ctx,GLenum pname,GLfloat param)806 void gl_PixelTransferf( GLcontext *ctx, GLenum pname, GLfloat param )
807 {
808 if (INSIDE_BEGIN_END(ctx)) {
809 gl_error( ctx, GL_INVALID_OPERATION, "glPixelTransfer" );
810 return;
811 }
812
813 switch (pname) {
814 case GL_MAP_COLOR:
815 ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE;
816 break;
817 case GL_MAP_STENCIL:
818 ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE;
819 break;
820 case GL_INDEX_SHIFT:
821 ctx->Pixel.IndexShift = (GLint) param;
822 break;
823 case GL_INDEX_OFFSET:
824 ctx->Pixel.IndexOffset = (GLint) param;
825 break;
826 case GL_RED_SCALE:
827 ctx->Pixel.RedScale = param;
828 break;
829 case GL_RED_BIAS:
830 ctx->Pixel.RedBias = param;
831 break;
832 case GL_GREEN_SCALE:
833 ctx->Pixel.GreenScale = param;
834 break;
835 case GL_GREEN_BIAS:
836 ctx->Pixel.GreenBias = param;
837 break;
838 case GL_BLUE_SCALE:
839 ctx->Pixel.BlueScale = param;
840 break;
841 case GL_BLUE_BIAS:
842 ctx->Pixel.BlueBias = param;
843 break;
844 case GL_ALPHA_SCALE:
845 ctx->Pixel.AlphaScale = param;
846 break;
847 case GL_ALPHA_BIAS:
848 ctx->Pixel.AlphaBias = param;
849 break;
850 case GL_DEPTH_SCALE:
851 ctx->Pixel.DepthScale = param;
852 break;
853 case GL_DEPTH_BIAS:
854 ctx->Pixel.DepthBias = param;
855 break;
856 default:
857 gl_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
858 return;
859 }
860 update_drawpixels_state( ctx );
861 }
862
863
864
865
866
867 /**********************************************************************/
868 /***** Pixel packing/unpacking *****/
869 /**********************************************************************/
870
871
872
873 /*
874 * Unpack a 2-D pixel array/image. The unpacked format will be con-
875 * tiguous (no "empty" bytes) with byte/bit swapping applied as needed.
876 * Input: same as glDrawPixels
877 * Output: pointer to block of pixel data in same format and type as input
878 * or NULL if error.
879 */
gl_unpack_pixels(GLcontext * ctx,GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid * pixels)880 GLvoid *gl_unpack_pixels( GLcontext *ctx,
881 GLsizei width, GLsizei height,
882 GLenum format, GLenum type,
883 const GLvoid *pixels )
884 {
885 GLint s, n;
886
887 s = gl_sizeof_type( type );
888 if (s<0) {
889 gl_error( ctx, GL_INVALID_ENUM, "internal error in gl_unpack(type)" );
890 return NULL;
891 }
892
893 n = gl_components_in_format( format );
894 if (n<0) {
895 gl_error( ctx, GL_INVALID_ENUM, "gl_unpack_pixels(format)" );
896 return NULL;
897 }
898
899 if (type==GL_BITMAP) {
900 /* BITMAP data */
901 GLint bytes, i, width_in_bytes;
902 GLubyte *buffer, *dst;
903 GLvoid *src;
904
905 /* Alloc dest storage */
906 bytes = CEILING( width * height , 8 );
907 buffer = (GLubyte *) malloc( bytes );
908 if (!buffer) {
909 return NULL;
910 }
911
912 /* Copy/unpack pixel data to buffer */
913 width_in_bytes = CEILING( width, 8 );
914 dst = buffer;
915 for (i=0;i<height;i++) {
916 src = gl_pixel_addr_in_image( &ctx->Unpack, pixels, width, height,
917 format, type, i);
918 if (!src) {
919 free(buffer);
920 return NULL;
921 }
922 MEMCPY( dst, src, width_in_bytes );
923 dst += width_in_bytes;
924 }
925
926 /* Bit flipping */
927 if (ctx->Unpack.LsbFirst) {
928 gl_flip_bytes( buffer, bytes );
929 }
930 return (GLvoid *) buffer;
931 }
932 else {
933 /* Non-BITMAP data */
934 GLint width_in_bytes, bytes, i;
935 GLubyte *buffer, *dst;
936 GLvoid *src;
937
938 width_in_bytes = width * n * s;
939
940 /* Alloc dest storage */
941 bytes = height * width_in_bytes;
942 buffer = (GLubyte *) malloc( bytes );
943 if (!buffer) {
944 return NULL;
945 }
946
947 /* Copy/unpack pixel data to buffer */
948 dst = buffer;
949 for (i=0;i<height;i++) {
950 src = gl_pixel_addr_in_image( &ctx->Unpack, pixels, width, height,
951 format, type, i);
952 if (!src) {
953 free(buffer);
954 return NULL;
955 }
956 MEMCPY( dst, src, width_in_bytes );
957 dst += width_in_bytes;
958 }
959
960 /* Byte swapping */
961 if (ctx->Unpack.SwapBytes && s>1) {
962 if (s==2) {
963 gl_swap2( (GLushort *) buffer, bytes/2 );
964 }
965 else if (s==4) {
966 gl_swap4( (GLuint *) buffer, bytes/4 );
967 }
968 }
969 return (GLvoid *) buffer;
970 }
971 }
972
973
974
975
976 /*
977 if (s>=a) {
978 k = n * l;
979 }
980 else { *s<a*
981 k = (a/s) * ceil( s*n*l / a );
982 }
983
984 s = size in bytes of a single component
985 a = alignment
986 n = number of components in a pixel
987 l = number of pixels in a row
988
989 k = number of components or indices between first pixel in each row in mem.
990 */
991
992