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