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