xref: /reactos/dll/opengl/mesa/pixel.c (revision 5f2bebf7)
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