pixel.c revision af69d88d
1/*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26/**
27 * \file pixel.c
28 * Pixel transfer functions (glPixelZoom, glPixelMap, glPixelTransfer)
29 */
30
31#include "glheader.h"
32#include "bufferobj.h"
33#include "colormac.h"
34#include "context.h"
35#include "macros.h"
36#include "pixel.h"
37#include "pbo.h"
38#include "mtypes.h"
39#include "main/dispatch.h"
40
41
42/**********************************************************************/
43/*****                    glPixelZoom                             *****/
44/**********************************************************************/
45
46void GLAPIENTRY
47_mesa_PixelZoom( GLfloat xfactor, GLfloat yfactor )
48{
49   GET_CURRENT_CONTEXT(ctx);
50
51   if (ctx->Pixel.ZoomX == xfactor &&
52       ctx->Pixel.ZoomY == yfactor)
53      return;
54
55   FLUSH_VERTICES(ctx, _NEW_PIXEL);
56   ctx->Pixel.ZoomX = xfactor;
57   ctx->Pixel.ZoomY = yfactor;
58}
59
60
61
62/**********************************************************************/
63/*****                         glPixelMap                         *****/
64/**********************************************************************/
65
66/**
67 * Return pointer to a pixelmap by name.
68 */
69static struct gl_pixelmap *
70get_pixelmap(struct gl_context *ctx, GLenum map)
71{
72   switch (map) {
73   case GL_PIXEL_MAP_I_TO_I:
74      return &ctx->PixelMaps.ItoI;
75   case GL_PIXEL_MAP_S_TO_S:
76      return &ctx->PixelMaps.StoS;
77   case GL_PIXEL_MAP_I_TO_R:
78      return &ctx->PixelMaps.ItoR;
79   case GL_PIXEL_MAP_I_TO_G:
80      return &ctx->PixelMaps.ItoG;
81   case GL_PIXEL_MAP_I_TO_B:
82      return &ctx->PixelMaps.ItoB;
83   case GL_PIXEL_MAP_I_TO_A:
84      return &ctx->PixelMaps.ItoA;
85   case GL_PIXEL_MAP_R_TO_R:
86      return &ctx->PixelMaps.RtoR;
87   case GL_PIXEL_MAP_G_TO_G:
88      return &ctx->PixelMaps.GtoG;
89   case GL_PIXEL_MAP_B_TO_B:
90      return &ctx->PixelMaps.BtoB;
91   case GL_PIXEL_MAP_A_TO_A:
92      return &ctx->PixelMaps.AtoA;
93   default:
94      return NULL;
95   }
96}
97
98
99/**
100 * Helper routine used by the other _mesa_PixelMap() functions.
101 */
102static void
103store_pixelmap(struct gl_context *ctx, GLenum map, GLsizei mapsize,
104               const GLfloat *values)
105{
106   GLint i;
107   struct gl_pixelmap *pm = get_pixelmap(ctx, map);
108   if (!pm) {
109      _mesa_error(ctx, GL_INVALID_ENUM, "glPixelMap(map)");
110      return;
111   }
112
113   switch (map) {
114   case GL_PIXEL_MAP_S_TO_S:
115      /* special case */
116      ctx->PixelMaps.StoS.Size = mapsize;
117      for (i = 0; i < mapsize; i++) {
118         ctx->PixelMaps.StoS.Map[i] = (GLfloat)IROUND(values[i]);
119      }
120      break;
121   case GL_PIXEL_MAP_I_TO_I:
122      /* special case */
123      ctx->PixelMaps.ItoI.Size = mapsize;
124      for (i = 0; i < mapsize; i++) {
125         ctx->PixelMaps.ItoI.Map[i] = values[i];
126      }
127      break;
128   default:
129      /* general case */
130      pm->Size = mapsize;
131      for (i = 0; i < mapsize; i++) {
132         GLfloat val = CLAMP(values[i], 0.0F, 1.0F);
133         pm->Map[i] = val;
134      }
135   }
136}
137
138
139/**
140 * Convenience wrapper for _mesa_validate_pbo_access() for gl[Get]PixelMap().
141 */
142static GLboolean
143validate_pbo_access(struct gl_context *ctx,
144                    struct gl_pixelstore_attrib *pack, GLsizei mapsize,
145                    GLenum format, GLenum type, GLsizei clientMemSize,
146                    const GLvoid *ptr)
147{
148   GLboolean ok;
149
150   /* Note, need to use DefaultPacking and Unpack's buffer object */
151   _mesa_reference_buffer_object(ctx,
152                                 &ctx->DefaultPacking.BufferObj,
153                                 pack->BufferObj);
154
155   ok = _mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
156                                  format, type, clientMemSize, ptr);
157
158   /* restore */
159   _mesa_reference_buffer_object(ctx,
160                                 &ctx->DefaultPacking.BufferObj,
161                                 ctx->Shared->NullBufferObj);
162
163   if (!ok) {
164      if (_mesa_is_bufferobj(pack->BufferObj)) {
165         _mesa_error(ctx, GL_INVALID_OPERATION,
166                     "gl[Get]PixelMap*v(out of bounds PBO access)");
167      } else {
168         _mesa_error(ctx, GL_INVALID_OPERATION,
169                     "glGetnPixelMap*vARB(out of bounds access:"
170                     " bufSize (%d) is too small)", clientMemSize);
171      }
172   }
173   return ok;
174}
175
176
177void GLAPIENTRY
178_mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
179{
180   GET_CURRENT_CONTEXT(ctx);
181
182   /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
183   if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
184      _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
185      return;
186   }
187
188   if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
189      /* test that mapsize is a power of two */
190      if (!_mesa_is_pow_two(mapsize)) {
191	 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
192         return;
193      }
194   }
195
196   FLUSH_VERTICES(ctx, _NEW_PIXEL);
197
198   if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize, GL_INTENSITY,
199                            GL_FLOAT, INT_MAX, values)) {
200      return;
201   }
202
203   values = (const GLfloat *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
204   if (!values) {
205      if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
206         _mesa_error(ctx, GL_INVALID_OPERATION,
207                     "glPixelMapfv(PBO is mapped)");
208      }
209      return;
210   }
211
212   store_pixelmap(ctx, map, mapsize, values);
213
214   _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
215}
216
217
218void GLAPIENTRY
219_mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
220{
221   GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
222   GET_CURRENT_CONTEXT(ctx);
223
224   if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
225      _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
226      return;
227   }
228
229   if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
230      /* test that mapsize is a power of two */
231      if (!_mesa_is_pow_two(mapsize)) {
232	 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
233         return;
234      }
235   }
236
237   FLUSH_VERTICES(ctx, _NEW_PIXEL);
238
239   if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize, GL_INTENSITY,
240                            GL_UNSIGNED_INT, INT_MAX, values)) {
241      return;
242   }
243
244   values = (const GLuint *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
245   if (!values) {
246      if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
247         _mesa_error(ctx, GL_INVALID_OPERATION,
248                     "glPixelMapuiv(PBO is mapped)");
249      }
250      return;
251   }
252
253   /* convert to floats */
254   if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
255      GLint i;
256      for (i = 0; i < mapsize; i++) {
257         fvalues[i] = (GLfloat) values[i];
258      }
259   }
260   else {
261      GLint i;
262      for (i = 0; i < mapsize; i++) {
263         fvalues[i] = UINT_TO_FLOAT( values[i] );
264      }
265   }
266
267   _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
268
269   store_pixelmap(ctx, map, mapsize, fvalues);
270}
271
272
273void GLAPIENTRY
274_mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values )
275{
276   GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
277   GET_CURRENT_CONTEXT(ctx);
278
279   if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
280      _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapusv(mapsize)" );
281      return;
282   }
283
284   if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
285      /* test that mapsize is a power of two */
286      if (!_mesa_is_pow_two(mapsize)) {
287	 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
288         return;
289      }
290   }
291
292   FLUSH_VERTICES(ctx, _NEW_PIXEL);
293
294   if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize, GL_INTENSITY,
295                            GL_UNSIGNED_SHORT, INT_MAX, values)) {
296      return;
297   }
298
299   values = (const GLushort *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
300   if (!values) {
301      if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
302         _mesa_error(ctx, GL_INVALID_OPERATION,
303                     "glPixelMapusv(PBO is mapped)");
304      }
305      return;
306   }
307
308   /* convert to floats */
309   if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
310      GLint i;
311      for (i = 0; i < mapsize; i++) {
312         fvalues[i] = (GLfloat) values[i];
313      }
314   }
315   else {
316      GLint i;
317      for (i = 0; i < mapsize; i++) {
318         fvalues[i] = USHORT_TO_FLOAT( values[i] );
319      }
320   }
321
322   _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
323
324   store_pixelmap(ctx, map, mapsize, fvalues);
325}
326
327
328void GLAPIENTRY
329_mesa_GetnPixelMapfvARB( GLenum map, GLsizei bufSize, GLfloat *values )
330{
331   GET_CURRENT_CONTEXT(ctx);
332   GLint mapsize, i;
333   const struct gl_pixelmap *pm;
334
335   pm = get_pixelmap(ctx, map);
336   if (!pm) {
337      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapfv(map)");
338      return;
339   }
340
341   mapsize = pm->Size;
342
343   if (!validate_pbo_access(ctx, &ctx->Pack, mapsize, GL_INTENSITY,
344                            GL_FLOAT, bufSize, values)) {
345      return;
346   }
347
348   values = (GLfloat *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
349   if (!values) {
350      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
351         _mesa_error(ctx, GL_INVALID_OPERATION,
352                     "glGetPixelMapfv(PBO is mapped)");
353      }
354      return;
355   }
356
357   if (map == GL_PIXEL_MAP_S_TO_S) {
358      /* special case */
359      for (i = 0; i < mapsize; i++) {
360         values[i] = (GLfloat) ctx->PixelMaps.StoS.Map[i];
361      }
362   }
363   else {
364      memcpy(values, pm->Map, mapsize * sizeof(GLfloat));
365   }
366
367   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
368}
369
370
371void GLAPIENTRY
372_mesa_GetPixelMapfv( GLenum map, GLfloat *values )
373{
374   _mesa_GetnPixelMapfvARB(map, INT_MAX, values);
375}
376
377void GLAPIENTRY
378_mesa_GetnPixelMapuivARB( GLenum map, GLsizei bufSize, GLuint *values )
379{
380   GET_CURRENT_CONTEXT(ctx);
381   GLint mapsize, i;
382   const struct gl_pixelmap *pm;
383
384   pm = get_pixelmap(ctx, map);
385   if (!pm) {
386      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapuiv(map)");
387      return;
388   }
389
390   mapsize = pm->Size;
391
392   if (!validate_pbo_access(ctx, &ctx->Pack, mapsize, GL_INTENSITY,
393                            GL_UNSIGNED_INT, bufSize, values)) {
394      return;
395   }
396
397   values = (GLuint *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
398   if (!values) {
399      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
400         _mesa_error(ctx, GL_INVALID_OPERATION,
401                     "glGetPixelMapuiv(PBO is mapped)");
402      }
403      return;
404   }
405
406   if (map == GL_PIXEL_MAP_S_TO_S) {
407      /* special case */
408      memcpy(values, ctx->PixelMaps.StoS.Map, mapsize * sizeof(GLint));
409   }
410   else {
411      for (i = 0; i < mapsize; i++) {
412         values[i] = FLOAT_TO_UINT( pm->Map[i] );
413      }
414   }
415
416   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
417}
418
419
420void GLAPIENTRY
421_mesa_GetPixelMapuiv( GLenum map, GLuint *values )
422{
423   _mesa_GetnPixelMapuivARB(map, INT_MAX, values);
424}
425
426void GLAPIENTRY
427_mesa_GetnPixelMapusvARB( GLenum map, GLsizei bufSize, GLushort *values )
428{
429   GET_CURRENT_CONTEXT(ctx);
430   GLint mapsize, i;
431   const struct gl_pixelmap *pm;
432
433   pm = get_pixelmap(ctx, map);
434   if (!pm) {
435      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapusv(map)");
436      return;
437   }
438
439   mapsize = pm->Size;
440
441   if (!validate_pbo_access(ctx, &ctx->Pack, mapsize, GL_INTENSITY,
442                            GL_UNSIGNED_SHORT, bufSize, values)) {
443      return;
444   }
445
446   values = (GLushort *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
447   if (!values) {
448      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
449         _mesa_error(ctx, GL_INVALID_OPERATION,
450                     "glGetPixelMapusv(PBO is mapped)");
451      }
452      return;
453   }
454
455   switch (map) {
456   /* special cases */
457   case GL_PIXEL_MAP_I_TO_I:
458      for (i = 0; i < mapsize; i++) {
459         values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0, 65535.);
460      }
461      break;
462   case GL_PIXEL_MAP_S_TO_S:
463      for (i = 0; i < mapsize; i++) {
464         values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0, 65535.);
465      }
466      break;
467   default:
468      for (i = 0; i < mapsize; i++) {
469         CLAMPED_FLOAT_TO_USHORT(values[i], pm->Map[i] );
470      }
471   }
472
473   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
474}
475
476
477void GLAPIENTRY
478_mesa_GetPixelMapusv( GLenum map, GLushort *values )
479{
480   _mesa_GetnPixelMapusvARB(map, INT_MAX, values);
481}
482
483
484/**********************************************************************/
485/*****                       glPixelTransfer                      *****/
486/**********************************************************************/
487
488
489/*
490 * Implements glPixelTransfer[fi] whether called immediately or from a
491 * display list.
492 */
493void GLAPIENTRY
494_mesa_PixelTransferf( GLenum pname, GLfloat param )
495{
496   GET_CURRENT_CONTEXT(ctx);
497
498   switch (pname) {
499      case GL_MAP_COLOR:
500         if (ctx->Pixel.MapColorFlag == (param ? GL_TRUE : GL_FALSE))
501	    return;
502	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
503         ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE;
504	 break;
505      case GL_MAP_STENCIL:
506         if (ctx->Pixel.MapStencilFlag == (param ? GL_TRUE : GL_FALSE))
507	    return;
508	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
509         ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE;
510	 break;
511      case GL_INDEX_SHIFT:
512         if (ctx->Pixel.IndexShift == (GLint) param)
513	    return;
514	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
515         ctx->Pixel.IndexShift = (GLint) param;
516	 break;
517      case GL_INDEX_OFFSET:
518         if (ctx->Pixel.IndexOffset == (GLint) param)
519	    return;
520	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
521         ctx->Pixel.IndexOffset = (GLint) param;
522	 break;
523      case GL_RED_SCALE:
524         if (ctx->Pixel.RedScale == param)
525	    return;
526	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
527         ctx->Pixel.RedScale = param;
528	 break;
529      case GL_RED_BIAS:
530         if (ctx->Pixel.RedBias == param)
531	    return;
532	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
533         ctx->Pixel.RedBias = param;
534	 break;
535      case GL_GREEN_SCALE:
536         if (ctx->Pixel.GreenScale == param)
537	    return;
538	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
539         ctx->Pixel.GreenScale = param;
540	 break;
541      case GL_GREEN_BIAS:
542         if (ctx->Pixel.GreenBias == param)
543	    return;
544	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
545         ctx->Pixel.GreenBias = param;
546	 break;
547      case GL_BLUE_SCALE:
548         if (ctx->Pixel.BlueScale == param)
549	    return;
550	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
551         ctx->Pixel.BlueScale = param;
552	 break;
553      case GL_BLUE_BIAS:
554         if (ctx->Pixel.BlueBias == param)
555	    return;
556	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
557         ctx->Pixel.BlueBias = param;
558	 break;
559      case GL_ALPHA_SCALE:
560         if (ctx->Pixel.AlphaScale == param)
561	    return;
562	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
563         ctx->Pixel.AlphaScale = param;
564	 break;
565      case GL_ALPHA_BIAS:
566         if (ctx->Pixel.AlphaBias == param)
567	    return;
568	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
569         ctx->Pixel.AlphaBias = param;
570	 break;
571      case GL_DEPTH_SCALE:
572         if (ctx->Pixel.DepthScale == param)
573	    return;
574	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
575         ctx->Pixel.DepthScale = param;
576	 break;
577      case GL_DEPTH_BIAS:
578         if (ctx->Pixel.DepthBias == param)
579	    return;
580	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
581         ctx->Pixel.DepthBias = param;
582	 break;
583      default:
584         _mesa_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
585         return;
586   }
587}
588
589
590void GLAPIENTRY
591_mesa_PixelTransferi( GLenum pname, GLint param )
592{
593   _mesa_PixelTransferf( pname, (GLfloat) param );
594}
595
596
597
598/**********************************************************************/
599/*****                    State Management                        *****/
600/**********************************************************************/
601
602/*
603 * Return a bitmask of IMAGE_*_BIT flags which to indicate which
604 * pixel transfer operations are enabled.
605 */
606static void
607update_image_transfer_state(struct gl_context *ctx)
608{
609   GLuint mask = 0;
610
611   if (ctx->Pixel.RedScale   != 1.0F || ctx->Pixel.RedBias   != 0.0F ||
612       ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F ||
613       ctx->Pixel.BlueScale  != 1.0F || ctx->Pixel.BlueBias  != 0.0F ||
614       ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F)
615      mask |= IMAGE_SCALE_BIAS_BIT;
616
617   if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset)
618      mask |= IMAGE_SHIFT_OFFSET_BIT;
619
620   if (ctx->Pixel.MapColorFlag)
621      mask |= IMAGE_MAP_COLOR_BIT;
622
623   ctx->_ImageTransferState = mask;
624}
625
626
627/**
628 * Update mesa pixel transfer derived state.
629 */
630void _mesa_update_pixel( struct gl_context *ctx, GLuint new_state )
631{
632   if (new_state & _NEW_PIXEL)
633      update_image_transfer_state(ctx);
634}
635
636
637/**********************************************************************/
638/*****                      Initialization                        *****/
639/**********************************************************************/
640
641static void
642init_pixelmap(struct gl_pixelmap *map)
643{
644   map->Size = 1;
645   map->Map[0] = 0.0;
646}
647
648
649/**
650 * Initialize the context's PIXEL attribute group.
651 */
652void
653_mesa_init_pixel( struct gl_context *ctx )
654{
655   /* Pixel group */
656   ctx->Pixel.RedBias = 0.0;
657   ctx->Pixel.RedScale = 1.0;
658   ctx->Pixel.GreenBias = 0.0;
659   ctx->Pixel.GreenScale = 1.0;
660   ctx->Pixel.BlueBias = 0.0;
661   ctx->Pixel.BlueScale = 1.0;
662   ctx->Pixel.AlphaBias = 0.0;
663   ctx->Pixel.AlphaScale = 1.0;
664   ctx->Pixel.DepthBias = 0.0;
665   ctx->Pixel.DepthScale = 1.0;
666   ctx->Pixel.IndexOffset = 0;
667   ctx->Pixel.IndexShift = 0;
668   ctx->Pixel.ZoomX = 1.0;
669   ctx->Pixel.ZoomY = 1.0;
670   ctx->Pixel.MapColorFlag = GL_FALSE;
671   ctx->Pixel.MapStencilFlag = GL_FALSE;
672   init_pixelmap(&ctx->PixelMaps.StoS);
673   init_pixelmap(&ctx->PixelMaps.ItoI);
674   init_pixelmap(&ctx->PixelMaps.ItoR);
675   init_pixelmap(&ctx->PixelMaps.ItoG);
676   init_pixelmap(&ctx->PixelMaps.ItoB);
677   init_pixelmap(&ctx->PixelMaps.ItoA);
678   init_pixelmap(&ctx->PixelMaps.RtoR);
679   init_pixelmap(&ctx->PixelMaps.GtoG);
680   init_pixelmap(&ctx->PixelMaps.BtoB);
681   init_pixelmap(&ctx->PixelMaps.AtoA);
682
683   if (ctx->Visual.doubleBufferMode) {
684      ctx->Pixel.ReadBuffer = GL_BACK;
685   }
686   else {
687      ctx->Pixel.ReadBuffer = GL_FRONT;
688   }
689
690   /* Miscellaneous */
691   ctx->_ImageTransferState = 0;
692}
693