pixel.c revision 7126e38d9037da66fd531c4cb02b3843b68b84ff
1/*
2 * Mesa 3-D graphics library
3 * Version:  7.1
4 *
5 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR 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 "mtypes.h"
38#include "main/dispatch.h"
39
40
41#if FEATURE_pixel_transfer
42
43
44/**********************************************************************/
45/*****                    glPixelZoom                             *****/
46/**********************************************************************/
47
48static void GLAPIENTRY
49_mesa_PixelZoom( GLfloat xfactor, GLfloat yfactor )
50{
51   GET_CURRENT_CONTEXT(ctx);
52
53   if (ctx->Pixel.ZoomX == xfactor &&
54       ctx->Pixel.ZoomY == yfactor)
55      return;
56
57   FLUSH_VERTICES(ctx, _NEW_PIXEL);
58   ctx->Pixel.ZoomX = xfactor;
59   ctx->Pixel.ZoomY = yfactor;
60}
61
62
63
64/**********************************************************************/
65/*****                         glPixelMap                         *****/
66/**********************************************************************/
67
68/**
69 * Return pointer to a pixelmap by name.
70 */
71static struct gl_pixelmap *
72get_pixelmap(GLcontext *ctx, GLenum map)
73{
74   switch (map) {
75   case GL_PIXEL_MAP_I_TO_I:
76      return &ctx->PixelMaps.ItoI;
77   case GL_PIXEL_MAP_S_TO_S:
78      return &ctx->PixelMaps.StoS;
79   case GL_PIXEL_MAP_I_TO_R:
80      return &ctx->PixelMaps.ItoR;
81   case GL_PIXEL_MAP_I_TO_G:
82      return &ctx->PixelMaps.ItoG;
83   case GL_PIXEL_MAP_I_TO_B:
84      return &ctx->PixelMaps.ItoB;
85   case GL_PIXEL_MAP_I_TO_A:
86      return &ctx->PixelMaps.ItoA;
87   case GL_PIXEL_MAP_R_TO_R:
88      return &ctx->PixelMaps.RtoR;
89   case GL_PIXEL_MAP_G_TO_G:
90      return &ctx->PixelMaps.GtoG;
91   case GL_PIXEL_MAP_B_TO_B:
92      return &ctx->PixelMaps.BtoB;
93   case GL_PIXEL_MAP_A_TO_A:
94      return &ctx->PixelMaps.AtoA;
95   default:
96      return NULL;
97   }
98}
99
100
101/**
102 * Helper routine used by the other _mesa_PixelMap() functions.
103 */
104static void
105store_pixelmap(GLcontext *ctx, GLenum map, GLsizei mapsize,
106               const GLfloat *values)
107{
108   GLint i;
109   struct gl_pixelmap *pm = get_pixelmap(ctx, map);
110   if (!pm) {
111      _mesa_error(ctx, GL_INVALID_ENUM, "glPixelMap(map)");
112      return;
113   }
114
115   switch (map) {
116   case GL_PIXEL_MAP_S_TO_S:
117      /* special case */
118      ctx->PixelMaps.StoS.Size = mapsize;
119      for (i = 0; i < mapsize; i++) {
120         ctx->PixelMaps.StoS.Map[i] = (GLfloat)IROUND(values[i]);
121      }
122      break;
123   case GL_PIXEL_MAP_I_TO_I:
124      /* special case */
125      ctx->PixelMaps.ItoI.Size = mapsize;
126      for (i = 0; i < mapsize; i++) {
127         ctx->PixelMaps.ItoI.Map[i] = values[i];
128      }
129      break;
130   default:
131      /* general case */
132      pm->Size = mapsize;
133      for (i = 0; i < mapsize; i++) {
134         GLfloat val = CLAMP(values[i], 0.0F, 1.0F);
135         pm->Map[i] = val;
136         pm->Map8[i] = (GLint) (val * 255.0F);
137      }
138   }
139}
140
141
142/**
143 * Convenience wrapper for _mesa_validate_pbo_access() for gl[Get]PixelMap().
144 */
145static GLboolean
146validate_pbo_access(GLcontext *ctx, struct gl_pixelstore_attrib *pack,
147                    GLsizei mapsize, GLenum format, GLenum type,
148                    const GLvoid *ptr)
149{
150   GLboolean ok;
151
152   /* Note, need to use DefaultPacking and Unpack's buffer object */
153   _mesa_reference_buffer_object(ctx,
154                                 &ctx->DefaultPacking.BufferObj,
155                                 pack->BufferObj);
156
157   ok = _mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
158                                  format, type, ptr);
159
160   /* restore */
161   _mesa_reference_buffer_object(ctx,
162                                 &ctx->DefaultPacking.BufferObj,
163                                 ctx->Shared->NullBufferObj);
164
165   if (!ok) {
166      _mesa_error(ctx, GL_INVALID_OPERATION,
167                  "glPixelMap(invalid PBO access)");
168   }
169   return ok;
170}
171
172
173static void GLAPIENTRY
174_mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
175{
176   GET_CURRENT_CONTEXT(ctx);
177   ASSERT_OUTSIDE_BEGIN_END(ctx);
178
179   /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
180   if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
181      _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
182      return;
183   }
184
185   if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
186      /* test that mapsize is a power of two */
187      if (!_mesa_is_pow_two(mapsize)) {
188	 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
189         return;
190      }
191   }
192
193   FLUSH_VERTICES(ctx, _NEW_PIXEL);
194
195   if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
196                            GL_INTENSITY, GL_FLOAT, values)) {
197      return;
198   }
199
200   values = (const GLfloat *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
201   if (!values) {
202      if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
203         _mesa_error(ctx, GL_INVALID_OPERATION,
204                     "glPixelMapfv(PBO is mapped)");
205      }
206      return;
207   }
208
209   store_pixelmap(ctx, map, mapsize, values);
210
211   _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
212}
213
214
215static void GLAPIENTRY
216_mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
217{
218   GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
219   GET_CURRENT_CONTEXT(ctx);
220   ASSERT_OUTSIDE_BEGIN_END(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,
238                            GL_INTENSITY, GL_UNSIGNED_INT, 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
271static void 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   ASSERT_OUTSIDE_BEGIN_END(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,
294                            GL_INTENSITY, GL_UNSIGNED_SHORT, 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
327static void GLAPIENTRY
328_mesa_GetPixelMapfv( GLenum map, GLfloat *values )
329{
330   GET_CURRENT_CONTEXT(ctx);
331   GLuint mapsize, i;
332   const struct gl_pixelmap *pm;
333
334   ASSERT_OUTSIDE_BEGIN_END(ctx);
335
336   pm = get_pixelmap(ctx, map);
337   if (!pm) {
338      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapfv(map)");
339      return;
340   }
341
342   mapsize = pm->Size;
343
344   if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
345                            GL_INTENSITY, GL_FLOAT, values)) {
346      return;
347   }
348
349   values = (GLfloat *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
350   if (!values) {
351      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
352         _mesa_error(ctx, GL_INVALID_OPERATION,
353                     "glGetPixelMapfv(PBO is mapped)");
354      }
355      return;
356   }
357
358   if (map == GL_PIXEL_MAP_S_TO_S) {
359      /* special case */
360      for (i = 0; i < mapsize; i++) {
361         values[i] = (GLfloat) ctx->PixelMaps.StoS.Map[i];
362      }
363   }
364   else {
365      memcpy(values, pm->Map, mapsize * sizeof(GLfloat));
366   }
367
368   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
369}
370
371
372static void GLAPIENTRY
373_mesa_GetPixelMapuiv( GLenum map, GLuint *values )
374{
375   GET_CURRENT_CONTEXT(ctx);
376   GLint mapsize, i;
377   const struct gl_pixelmap *pm;
378
379   ASSERT_OUTSIDE_BEGIN_END(ctx);
380
381   pm = get_pixelmap(ctx, map);
382   if (!pm) {
383      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapuiv(map)");
384      return;
385   }
386   mapsize = pm->Size;
387
388   if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
389                            GL_INTENSITY, GL_UNSIGNED_INT, values)) {
390      return;
391   }
392
393   values = (GLuint *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
394   if (!values) {
395      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
396         _mesa_error(ctx, GL_INVALID_OPERATION,
397                     "glGetPixelMapuiv(PBO is mapped)");
398      }
399      return;
400   }
401
402   if (map == GL_PIXEL_MAP_S_TO_S) {
403      /* special case */
404      memcpy(values, ctx->PixelMaps.StoS.Map, mapsize * sizeof(GLint));
405   }
406   else {
407      for (i = 0; i < mapsize; i++) {
408         values[i] = FLOAT_TO_UINT( pm->Map[i] );
409      }
410   }
411
412   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
413}
414
415
416static void GLAPIENTRY
417_mesa_GetPixelMapusv( GLenum map, GLushort *values )
418{
419   GET_CURRENT_CONTEXT(ctx);
420   GLint mapsize, i;
421   const struct gl_pixelmap *pm;
422
423   ASSERT_OUTSIDE_BEGIN_END(ctx);
424
425   pm = get_pixelmap(ctx, map);
426   if (!pm) {
427      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapusv(map)");
428      return;
429   }
430   mapsize = pm->Size;
431
432   if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
433                            GL_INTENSITY, GL_UNSIGNED_SHORT, values)) {
434      return;
435   }
436
437   values = (GLushort *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
438   if (!values) {
439      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
440         _mesa_error(ctx, GL_INVALID_OPERATION,
441                     "glGetPixelMapusv(PBO is mapped)");
442      }
443      return;
444   }
445
446   switch (map) {
447   /* special cases */
448   case GL_PIXEL_MAP_I_TO_I:
449      for (i = 0; i < mapsize; i++) {
450         values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0, 65535.);
451      }
452      break;
453   case GL_PIXEL_MAP_S_TO_S:
454      for (i = 0; i < mapsize; i++) {
455         values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0, 65535.);
456      }
457      break;
458   default:
459      for (i = 0; i < mapsize; i++) {
460         CLAMPED_FLOAT_TO_USHORT(values[i], pm->Map[i] );
461      }
462   }
463
464   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
465}
466
467
468
469/**********************************************************************/
470/*****                       glPixelTransfer                      *****/
471/**********************************************************************/
472
473
474/*
475 * Implements glPixelTransfer[fi] whether called immediately or from a
476 * display list.
477 */
478static void GLAPIENTRY
479_mesa_PixelTransferf( GLenum pname, GLfloat param )
480{
481   GET_CURRENT_CONTEXT(ctx);
482   ASSERT_OUTSIDE_BEGIN_END(ctx);
483
484   switch (pname) {
485      case GL_MAP_COLOR:
486         if (ctx->Pixel.MapColorFlag == (param ? GL_TRUE : GL_FALSE))
487	    return;
488	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
489         ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE;
490	 break;
491      case GL_MAP_STENCIL:
492         if (ctx->Pixel.MapStencilFlag == (param ? GL_TRUE : GL_FALSE))
493	    return;
494	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
495         ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE;
496	 break;
497      case GL_INDEX_SHIFT:
498         if (ctx->Pixel.IndexShift == (GLint) param)
499	    return;
500	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
501         ctx->Pixel.IndexShift = (GLint) param;
502	 break;
503      case GL_INDEX_OFFSET:
504         if (ctx->Pixel.IndexOffset == (GLint) param)
505	    return;
506	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
507         ctx->Pixel.IndexOffset = (GLint) param;
508	 break;
509      case GL_RED_SCALE:
510         if (ctx->Pixel.RedScale == param)
511	    return;
512	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
513         ctx->Pixel.RedScale = param;
514	 break;
515      case GL_RED_BIAS:
516         if (ctx->Pixel.RedBias == param)
517	    return;
518	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
519         ctx->Pixel.RedBias = param;
520	 break;
521      case GL_GREEN_SCALE:
522         if (ctx->Pixel.GreenScale == param)
523	    return;
524	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
525         ctx->Pixel.GreenScale = param;
526	 break;
527      case GL_GREEN_BIAS:
528         if (ctx->Pixel.GreenBias == param)
529	    return;
530	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
531         ctx->Pixel.GreenBias = param;
532	 break;
533      case GL_BLUE_SCALE:
534         if (ctx->Pixel.BlueScale == param)
535	    return;
536	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
537         ctx->Pixel.BlueScale = param;
538	 break;
539      case GL_BLUE_BIAS:
540         if (ctx->Pixel.BlueBias == param)
541	    return;
542	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
543         ctx->Pixel.BlueBias = param;
544	 break;
545      case GL_ALPHA_SCALE:
546         if (ctx->Pixel.AlphaScale == param)
547	    return;
548	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
549         ctx->Pixel.AlphaScale = param;
550	 break;
551      case GL_ALPHA_BIAS:
552         if (ctx->Pixel.AlphaBias == param)
553	    return;
554	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
555         ctx->Pixel.AlphaBias = param;
556	 break;
557      case GL_DEPTH_SCALE:
558         if (ctx->Pixel.DepthScale == param)
559	    return;
560	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
561         ctx->Pixel.DepthScale = param;
562	 break;
563      case GL_DEPTH_BIAS:
564         if (ctx->Pixel.DepthBias == param)
565	    return;
566	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
567         ctx->Pixel.DepthBias = param;
568	 break;
569      case GL_POST_COLOR_MATRIX_RED_SCALE:
570         if (ctx->Pixel.PostColorMatrixScale[0] == param)
571	    return;
572	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
573         ctx->Pixel.PostColorMatrixScale[0] = param;
574	 break;
575      case GL_POST_COLOR_MATRIX_RED_BIAS:
576         if (ctx->Pixel.PostColorMatrixBias[0] == param)
577	    return;
578	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
579         ctx->Pixel.PostColorMatrixBias[0] = param;
580	 break;
581      case GL_POST_COLOR_MATRIX_GREEN_SCALE:
582         if (ctx->Pixel.PostColorMatrixScale[1] == param)
583	    return;
584	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
585         ctx->Pixel.PostColorMatrixScale[1] = param;
586	 break;
587      case GL_POST_COLOR_MATRIX_GREEN_BIAS:
588         if (ctx->Pixel.PostColorMatrixBias[1] == param)
589	    return;
590	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
591         ctx->Pixel.PostColorMatrixBias[1] = param;
592	 break;
593      case GL_POST_COLOR_MATRIX_BLUE_SCALE:
594         if (ctx->Pixel.PostColorMatrixScale[2] == param)
595	    return;
596	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
597         ctx->Pixel.PostColorMatrixScale[2] = param;
598	 break;
599      case GL_POST_COLOR_MATRIX_BLUE_BIAS:
600         if (ctx->Pixel.PostColorMatrixBias[2] == param)
601	    return;
602	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
603         ctx->Pixel.PostColorMatrixBias[2] = param;
604	 break;
605      case GL_POST_COLOR_MATRIX_ALPHA_SCALE:
606         if (ctx->Pixel.PostColorMatrixScale[3] == param)
607	    return;
608	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
609         ctx->Pixel.PostColorMatrixScale[3] = param;
610	 break;
611      case GL_POST_COLOR_MATRIX_ALPHA_BIAS:
612         if (ctx->Pixel.PostColorMatrixBias[3] == param)
613	    return;
614	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
615         ctx->Pixel.PostColorMatrixBias[3] = param;
616	 break;
617      case GL_POST_CONVOLUTION_RED_SCALE:
618         if (ctx->Pixel.PostConvolutionScale[0] == param)
619	    return;
620	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
621         ctx->Pixel.PostConvolutionScale[0] = param;
622	 break;
623      case GL_POST_CONVOLUTION_RED_BIAS:
624         if (ctx->Pixel.PostConvolutionBias[0] == param)
625	    return;
626	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
627         ctx->Pixel.PostConvolutionBias[0] = param;
628	 break;
629      case GL_POST_CONVOLUTION_GREEN_SCALE:
630         if (ctx->Pixel.PostConvolutionScale[1] == param)
631	    return;
632	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
633         ctx->Pixel.PostConvolutionScale[1] = param;
634	 break;
635      case GL_POST_CONVOLUTION_GREEN_BIAS:
636         if (ctx->Pixel.PostConvolutionBias[1] == param)
637	    return;
638	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
639         ctx->Pixel.PostConvolutionBias[1] = param;
640	 break;
641      case GL_POST_CONVOLUTION_BLUE_SCALE:
642         if (ctx->Pixel.PostConvolutionScale[2] == param)
643	    return;
644	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
645         ctx->Pixel.PostConvolutionScale[2] = param;
646	 break;
647      case GL_POST_CONVOLUTION_BLUE_BIAS:
648         if (ctx->Pixel.PostConvolutionBias[2] == param)
649	    return;
650	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
651         ctx->Pixel.PostConvolutionBias[2] = param;
652	 break;
653      case GL_POST_CONVOLUTION_ALPHA_SCALE:
654         if (ctx->Pixel.PostConvolutionScale[3] == param)
655	    return;
656	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
657         ctx->Pixel.PostConvolutionScale[3] = param;
658	 break;
659      case GL_POST_CONVOLUTION_ALPHA_BIAS:
660         if (ctx->Pixel.PostConvolutionBias[3] == param)
661	    return;
662	 FLUSH_VERTICES(ctx, _NEW_PIXEL);
663         ctx->Pixel.PostConvolutionBias[3] = param;
664	 break;
665      default:
666         _mesa_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
667         return;
668   }
669}
670
671
672static void GLAPIENTRY
673_mesa_PixelTransferi( GLenum pname, GLint param )
674{
675   _mesa_PixelTransferf( pname, (GLfloat) param );
676}
677
678
679
680/**********************************************************************/
681/*****                    State Management                        *****/
682/**********************************************************************/
683
684/*
685 * Return a bitmask of IMAGE_*_BIT flags which to indicate which
686 * pixel transfer operations are enabled.
687 */
688static void
689update_image_transfer_state(GLcontext *ctx)
690{
691   GLuint mask = 0;
692
693   if (ctx->Pixel.RedScale   != 1.0F || ctx->Pixel.RedBias   != 0.0F ||
694       ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F ||
695       ctx->Pixel.BlueScale  != 1.0F || ctx->Pixel.BlueBias  != 0.0F ||
696       ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F)
697      mask |= IMAGE_SCALE_BIAS_BIT;
698
699   if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset)
700      mask |= IMAGE_SHIFT_OFFSET_BIT;
701
702   if (ctx->Pixel.MapColorFlag)
703      mask |= IMAGE_MAP_COLOR_BIT;
704
705   if (ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION])
706      mask |= IMAGE_COLOR_TABLE_BIT;
707
708   if (ctx->Pixel.Convolution1DEnabled ||
709       ctx->Pixel.Convolution2DEnabled ||
710       ctx->Pixel.Separable2DEnabled) {
711      mask |= IMAGE_CONVOLUTION_BIT;
712      if (ctx->Pixel.PostConvolutionScale[0] != 1.0F ||
713          ctx->Pixel.PostConvolutionScale[1] != 1.0F ||
714          ctx->Pixel.PostConvolutionScale[2] != 1.0F ||
715          ctx->Pixel.PostConvolutionScale[3] != 1.0F ||
716          ctx->Pixel.PostConvolutionBias[0] != 0.0F ||
717          ctx->Pixel.PostConvolutionBias[1] != 0.0F ||
718          ctx->Pixel.PostConvolutionBias[2] != 0.0F ||
719          ctx->Pixel.PostConvolutionBias[3] != 0.0F) {
720         mask |= IMAGE_POST_CONVOLUTION_SCALE_BIAS;
721      }
722   }
723
724   if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION])
725      mask |= IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT;
726
727   if (ctx->ColorMatrixStack.Top->type != MATRIX_IDENTITY ||
728       ctx->Pixel.PostColorMatrixScale[0] != 1.0F ||
729       ctx->Pixel.PostColorMatrixBias[0]  != 0.0F ||
730       ctx->Pixel.PostColorMatrixScale[1] != 1.0F ||
731       ctx->Pixel.PostColorMatrixBias[1]  != 0.0F ||
732       ctx->Pixel.PostColorMatrixScale[2] != 1.0F ||
733       ctx->Pixel.PostColorMatrixBias[2]  != 0.0F ||
734       ctx->Pixel.PostColorMatrixScale[3] != 1.0F ||
735       ctx->Pixel.PostColorMatrixBias[3]  != 0.0F)
736      mask |= IMAGE_COLOR_MATRIX_BIT;
737
738   if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX])
739      mask |= IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT;
740
741   ctx->_ImageTransferState = mask;
742}
743
744
745/**
746 * Update mesa pixel transfer derived state.
747 */
748void _mesa_update_pixel( GLcontext *ctx, GLuint new_state )
749{
750   if (new_state & _NEW_COLOR_MATRIX)
751      _math_matrix_analyse( ctx->ColorMatrixStack.Top );
752
753   /* References ColorMatrix.type (derived above).
754    */
755   if (new_state & _MESA_NEW_TRANSFER_STATE)
756      update_image_transfer_state(ctx);
757}
758
759
760void
761_mesa_init_pixel_dispatch(struct _glapi_table *disp)
762{
763   SET_GetPixelMapfv(disp, _mesa_GetPixelMapfv);
764   SET_GetPixelMapuiv(disp, _mesa_GetPixelMapuiv);
765   SET_GetPixelMapusv(disp, _mesa_GetPixelMapusv);
766   SET_PixelMapfv(disp, _mesa_PixelMapfv);
767   SET_PixelMapuiv(disp, _mesa_PixelMapuiv);
768   SET_PixelMapusv(disp, _mesa_PixelMapusv);
769   SET_PixelTransferf(disp, _mesa_PixelTransferf);
770   SET_PixelTransferi(disp, _mesa_PixelTransferi);
771   SET_PixelZoom(disp, _mesa_PixelZoom);
772}
773
774
775#endif /* FEATURE_pixel_transfer */
776
777
778/**********************************************************************/
779/*****                      Initialization                        *****/
780/**********************************************************************/
781
782static void
783init_pixelmap(struct gl_pixelmap *map)
784{
785   map->Size = 1;
786   map->Map[0] = 0.0;
787   map->Map8[0] = 0;
788}
789
790
791/**
792 * Initialize the context's PIXEL attribute group.
793 */
794void
795_mesa_init_pixel( GLcontext *ctx )
796{
797   int i;
798
799   /* Pixel group */
800   ctx->Pixel.RedBias = 0.0;
801   ctx->Pixel.RedScale = 1.0;
802   ctx->Pixel.GreenBias = 0.0;
803   ctx->Pixel.GreenScale = 1.0;
804   ctx->Pixel.BlueBias = 0.0;
805   ctx->Pixel.BlueScale = 1.0;
806   ctx->Pixel.AlphaBias = 0.0;
807   ctx->Pixel.AlphaScale = 1.0;
808   ctx->Pixel.DepthBias = 0.0;
809   ctx->Pixel.DepthScale = 1.0;
810   ctx->Pixel.IndexOffset = 0;
811   ctx->Pixel.IndexShift = 0;
812   ctx->Pixel.ZoomX = 1.0;
813   ctx->Pixel.ZoomY = 1.0;
814   ctx->Pixel.MapColorFlag = GL_FALSE;
815   ctx->Pixel.MapStencilFlag = GL_FALSE;
816   init_pixelmap(&ctx->PixelMaps.StoS);
817   init_pixelmap(&ctx->PixelMaps.ItoI);
818   init_pixelmap(&ctx->PixelMaps.ItoR);
819   init_pixelmap(&ctx->PixelMaps.ItoG);
820   init_pixelmap(&ctx->PixelMaps.ItoB);
821   init_pixelmap(&ctx->PixelMaps.ItoA);
822   init_pixelmap(&ctx->PixelMaps.RtoR);
823   init_pixelmap(&ctx->PixelMaps.GtoG);
824   init_pixelmap(&ctx->PixelMaps.BtoB);
825   init_pixelmap(&ctx->PixelMaps.AtoA);
826   ASSIGN_4V(ctx->Pixel.PostColorMatrixScale, 1.0, 1.0, 1.0, 1.0);
827   ASSIGN_4V(ctx->Pixel.PostColorMatrixBias, 0.0, 0.0, 0.0, 0.0);
828   for (i = 0; i < COLORTABLE_MAX; i++) {
829      ASSIGN_4V(ctx->Pixel.ColorTableScale[i], 1.0, 1.0, 1.0, 1.0);
830      ASSIGN_4V(ctx->Pixel.ColorTableBias[i], 0.0, 0.0, 0.0, 0.0);
831      ctx->Pixel.ColorTableEnabled[i] = GL_FALSE;
832   }
833   ctx->Pixel.Convolution1DEnabled = GL_FALSE;
834   ctx->Pixel.Convolution2DEnabled = GL_FALSE;
835   ctx->Pixel.Separable2DEnabled = GL_FALSE;
836   for (i = 0; i < 3; i++) {
837      ASSIGN_4V(ctx->Pixel.ConvolutionBorderColor[i], 0.0, 0.0, 0.0, 0.0);
838      ctx->Pixel.ConvolutionBorderMode[i] = GL_REDUCE;
839      ASSIGN_4V(ctx->Pixel.ConvolutionFilterScale[i], 1.0, 1.0, 1.0, 1.0);
840      ASSIGN_4V(ctx->Pixel.ConvolutionFilterBias[i], 0.0, 0.0, 0.0, 0.0);
841   }
842   for (i = 0; i < MAX_CONVOLUTION_WIDTH * MAX_CONVOLUTION_WIDTH * 4; i++) {
843      ctx->Convolution1D.Filter[i] = 0.0;
844      ctx->Convolution2D.Filter[i] = 0.0;
845      ctx->Separable2D.Filter[i] = 0.0;
846   }
847   ASSIGN_4V(ctx->Pixel.PostConvolutionScale, 1.0, 1.0, 1.0, 1.0);
848   ASSIGN_4V(ctx->Pixel.PostConvolutionBias, 0.0, 0.0, 0.0, 0.0);
849   /* GL_SGI_texture_color_table */
850   ASSIGN_4V(ctx->Pixel.TextureColorTableScale, 1.0, 1.0, 1.0, 1.0);
851   ASSIGN_4V(ctx->Pixel.TextureColorTableBias, 0.0, 0.0, 0.0, 0.0);
852
853   if (ctx->Visual.doubleBufferMode) {
854      ctx->Pixel.ReadBuffer = GL_BACK;
855   }
856   else {
857      ctx->Pixel.ReadBuffer = GL_FRONT;
858   }
859
860   /* Miscellaneous */
861   ctx->_ImageTransferState = 0;
862}
863