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