Home | History | Annotate | Download | only in main
      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
     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 *
     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
    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
    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
    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
    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
    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
    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
    383 _mesa_GetPixelMapfv( GLenum map, GLfloat *values )
    384 {
    385    _mesa_GetnPixelMapfvARB(map, INT_MAX, values);
    386 }
    387 
    388 static void GLAPIENTRY
    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
    434 _mesa_GetPixelMapuiv( GLenum map, GLuint *values )
    435 {
    436    _mesa_GetnPixelMapuivARB(map, INT_MAX, values);
    437 }
    438 
    439 static void GLAPIENTRY
    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
    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
    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
    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
    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  */
    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
    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
    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
    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