Home | History | Annotate | Download | only in main
      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  * \file pixelstore.c
     27  * glPixelStore functions.
     28  */
     29 
     30 
     31 #include "glheader.h"
     32 #include "bufferobj.h"
     33 #include "context.h"
     34 #include "pixelstore.h"
     35 #include "mtypes.h"
     36 
     37 
     38 void GLAPIENTRY
     39 _mesa_PixelStorei( GLenum pname, GLint param )
     40 {
     41    /* NOTE: this call can't be compiled into the display list */
     42    GET_CURRENT_CONTEXT(ctx);
     43 
     44    switch (pname) {
     45       case GL_PACK_SWAP_BYTES:
     46          if (!_mesa_is_desktop_gl(ctx))
     47             goto invalid_enum_error;
     48          ctx->Pack.SwapBytes = param ? GL_TRUE : GL_FALSE;
     49          break;
     50       case GL_PACK_LSB_FIRST:
     51          if (!_mesa_is_desktop_gl(ctx))
     52             goto invalid_enum_error;
     53          ctx->Pack.LsbFirst = param ? GL_TRUE : GL_FALSE;
     54          break;
     55       case GL_PACK_ROW_LENGTH:
     56          if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
     57             goto invalid_enum_error;
     58          if (param<0)
     59             goto invalid_value_error;
     60          ctx->Pack.RowLength = param;
     61          break;
     62       case GL_PACK_IMAGE_HEIGHT:
     63          if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
     64             goto invalid_enum_error;
     65          if (param<0)
     66             goto invalid_value_error;
     67          ctx->Pack.ImageHeight = param;
     68          break;
     69       case GL_PACK_SKIP_PIXELS:
     70          if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
     71             goto invalid_enum_error;
     72          if (param<0)
     73             goto invalid_value_error;
     74          ctx->Pack.SkipPixels = param;
     75          break;
     76       case GL_PACK_SKIP_ROWS:
     77          if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
     78             goto invalid_enum_error;
     79          if (param<0)
     80             goto invalid_value_error;
     81          ctx->Pack.SkipRows = param;
     82          break;
     83       case GL_PACK_SKIP_IMAGES:
     84          if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
     85             goto invalid_enum_error;
     86          if (param<0)
     87             goto invalid_value_error;
     88          ctx->Pack.SkipImages = param;
     89          break;
     90       case GL_PACK_ALIGNMENT:
     91          if (param!=1 && param!=2 && param!=4 && param!=8)
     92             goto invalid_value_error;
     93          ctx->Pack.Alignment = param;
     94          break;
     95       case GL_PACK_INVERT_MESA:
     96          if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.MESA_pack_invert)
     97             goto invalid_enum_error;
     98          ctx->Pack.Invert = param;
     99          break;
    100       case GL_PACK_COMPRESSED_BLOCK_WIDTH:
    101          if (!_mesa_is_desktop_gl(ctx))
    102             goto invalid_enum_error;
    103          if (param<0)
    104             goto invalid_value_error;
    105          ctx->Pack.CompressedBlockWidth = param;
    106          break;
    107       case GL_PACK_COMPRESSED_BLOCK_HEIGHT:
    108          if (!_mesa_is_desktop_gl(ctx))
    109             goto invalid_enum_error;
    110          if (param<0)
    111             goto invalid_value_error;
    112          ctx->Pack.CompressedBlockHeight = param;
    113          break;
    114       case GL_PACK_COMPRESSED_BLOCK_DEPTH:
    115          if (!_mesa_is_desktop_gl(ctx))
    116             goto invalid_enum_error;
    117          if (param<0)
    118             goto invalid_value_error;
    119          ctx->Pack.CompressedBlockDepth = param;
    120          break;
    121       case GL_PACK_COMPRESSED_BLOCK_SIZE:
    122          if (!_mesa_is_desktop_gl(ctx))
    123             goto invalid_enum_error;
    124          if (param<0)
    125             goto invalid_value_error;
    126          ctx->Pack.CompressedBlockSize = param;
    127          break;
    128 
    129       case GL_UNPACK_SWAP_BYTES:
    130          if (!_mesa_is_desktop_gl(ctx))
    131             goto invalid_enum_error;
    132          ctx->Unpack.SwapBytes = param ? GL_TRUE : GL_FALSE;
    133          break;
    134       case GL_UNPACK_LSB_FIRST:
    135          if (!_mesa_is_desktop_gl(ctx))
    136             goto invalid_enum_error;
    137          ctx->Unpack.LsbFirst = param ? GL_TRUE : GL_FALSE;
    138          break;
    139       case GL_UNPACK_ROW_LENGTH:
    140          if (ctx->API == API_OPENGLES)
    141             goto invalid_enum_error;
    142          if (param<0)
    143             goto invalid_value_error;
    144          ctx->Unpack.RowLength = param;
    145          break;
    146       case GL_UNPACK_IMAGE_HEIGHT:
    147          if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
    148             goto invalid_enum_error;
    149          if (param<0)
    150             goto invalid_value_error;
    151          ctx->Unpack.ImageHeight = param;
    152          break;
    153       case GL_UNPACK_SKIP_PIXELS:
    154          if (ctx->API == API_OPENGLES)
    155             goto invalid_enum_error;
    156          if (param<0)
    157             goto invalid_value_error;
    158          ctx->Unpack.SkipPixels = param;
    159          break;
    160       case GL_UNPACK_SKIP_ROWS:
    161          if (ctx->API == API_OPENGLES)
    162             goto invalid_enum_error;
    163          if (param<0)
    164             goto invalid_value_error;
    165          ctx->Unpack.SkipRows = param;
    166          break;
    167       case GL_UNPACK_SKIP_IMAGES:
    168          if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
    169             goto invalid_enum_error;
    170          if (param < 0)
    171             goto invalid_value_error;
    172          ctx->Unpack.SkipImages = param;
    173          break;
    174       case GL_UNPACK_ALIGNMENT:
    175          if (param!=1 && param!=2 && param!=4 && param!=8)
    176             goto invalid_value_error;
    177          ctx->Unpack.Alignment = param;
    178          break;
    179       case GL_UNPACK_COMPRESSED_BLOCK_WIDTH:
    180          if (!_mesa_is_desktop_gl(ctx))
    181             goto invalid_enum_error;
    182          if (param<0)
    183             goto invalid_value_error;
    184          ctx->Unpack.CompressedBlockWidth = param;
    185          break;
    186       case GL_UNPACK_COMPRESSED_BLOCK_HEIGHT:
    187          if (!_mesa_is_desktop_gl(ctx))
    188             goto invalid_enum_error;
    189          if (param<0)
    190             goto invalid_value_error;
    191          ctx->Unpack.CompressedBlockHeight = param;
    192          break;
    193       case GL_UNPACK_COMPRESSED_BLOCK_DEPTH:
    194          if (!_mesa_is_desktop_gl(ctx))
    195             goto invalid_enum_error;
    196          if (param<0)
    197             goto invalid_value_error;
    198          ctx->Unpack.CompressedBlockDepth = param;
    199          break;
    200       case GL_UNPACK_COMPRESSED_BLOCK_SIZE:
    201          if (!_mesa_is_desktop_gl(ctx))
    202             goto invalid_enum_error;
    203          if (param<0)
    204             goto invalid_value_error;
    205          ctx->Unpack.CompressedBlockSize = param;
    206          break;
    207       default:
    208          goto invalid_enum_error;
    209    }
    210 
    211    return;
    212 
    213 invalid_enum_error:
    214    _mesa_error( ctx, GL_INVALID_ENUM, "glPixelStore" );
    215    return;
    216 
    217 invalid_value_error:
    218    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
    219    return;
    220 }
    221 
    222 
    223 void GLAPIENTRY
    224 _mesa_PixelStoref( GLenum pname, GLfloat param )
    225 {
    226    _mesa_PixelStorei( pname, IROUND(param) );
    227 }
    228 
    229 
    230 
    231 /**
    232  * Initialize the context's pixel store state.
    233  */
    234 void
    235 _mesa_init_pixelstore( struct gl_context *ctx )
    236 {
    237    /* Pixel transfer */
    238    ctx->Pack.Alignment = 4;
    239    ctx->Pack.RowLength = 0;
    240    ctx->Pack.ImageHeight = 0;
    241    ctx->Pack.SkipPixels = 0;
    242    ctx->Pack.SkipRows = 0;
    243    ctx->Pack.SkipImages = 0;
    244    ctx->Pack.SwapBytes = GL_FALSE;
    245    ctx->Pack.LsbFirst = GL_FALSE;
    246    ctx->Pack.Invert = GL_FALSE;
    247    ctx->Pack.CompressedBlockWidth = 0;
    248    ctx->Pack.CompressedBlockHeight = 0;
    249    ctx->Pack.CompressedBlockDepth = 0;
    250    ctx->Pack.CompressedBlockSize = 0;
    251    _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj,
    252                                  ctx->Shared->NullBufferObj);
    253    ctx->Unpack.Alignment = 4;
    254    ctx->Unpack.RowLength = 0;
    255    ctx->Unpack.ImageHeight = 0;
    256    ctx->Unpack.SkipPixels = 0;
    257    ctx->Unpack.SkipRows = 0;
    258    ctx->Unpack.SkipImages = 0;
    259    ctx->Unpack.SwapBytes = GL_FALSE;
    260    ctx->Unpack.LsbFirst = GL_FALSE;
    261    ctx->Unpack.Invert = GL_FALSE;
    262    ctx->Unpack.CompressedBlockWidth = 0;
    263    ctx->Unpack.CompressedBlockHeight = 0;
    264    ctx->Unpack.CompressedBlockDepth = 0;
    265    ctx->Unpack.CompressedBlockSize = 0;
    266    _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj,
    267                                  ctx->Shared->NullBufferObj);
    268 
    269    /*
    270     * _mesa_unpack_image() returns image data in this format.  When we
    271     * execute image commands (glDrawPixels(), glTexImage(), etc) from
    272     * within display lists we have to be sure to set the current
    273     * unpacking parameters to these values!
    274     */
    275    ctx->DefaultPacking.Alignment = 1;
    276    ctx->DefaultPacking.RowLength = 0;
    277    ctx->DefaultPacking.SkipPixels = 0;
    278    ctx->DefaultPacking.SkipRows = 0;
    279    ctx->DefaultPacking.ImageHeight = 0;
    280    ctx->DefaultPacking.SkipImages = 0;
    281    ctx->DefaultPacking.SwapBytes = GL_FALSE;
    282    ctx->DefaultPacking.LsbFirst = GL_FALSE;
    283    ctx->DefaultPacking.Invert = GL_FALSE;
    284    _mesa_reference_buffer_object(ctx, &ctx->DefaultPacking.BufferObj,
    285                                  ctx->Shared->NullBufferObj);
    286 }
    287 
    288 
    289 /**
    290  * Check if the given compressed pixel storage parameters are legal.
    291  * Record a GL error if illegal.
    292  * \return  true if legal, false if illegal
    293  */
    294 bool
    295 _mesa_compressed_pixel_storage_error_check(
    296    struct gl_context *ctx,
    297    GLint dimensions,
    298    const struct gl_pixelstore_attrib *packing,
    299    const char *caller)
    300 {
    301    if (!_mesa_is_desktop_gl(ctx) || !packing->CompressedBlockSize)
    302       return true;
    303 
    304    if (packing->CompressedBlockWidth &&
    305        packing->SkipPixels % packing->CompressedBlockWidth) {
    306       _mesa_error(ctx, GL_INVALID_OPERATION,
    307                   "%s(skip-pixels %% block-width)", caller);
    308       return false;
    309    }
    310 
    311    if (dimensions > 1 &&
    312        packing->CompressedBlockHeight &&
    313        packing->SkipRows % packing->CompressedBlockHeight) {
    314       _mesa_error(ctx, GL_INVALID_OPERATION,
    315                   "%s(skip-rows %% block-height)", caller);
    316       return false;
    317    }
    318 
    319    if (dimensions > 2 &&
    320        packing->CompressedBlockDepth &&
    321        packing->SkipImages % packing->CompressedBlockDepth) {
    322       _mesa_error(ctx, GL_INVALID_OPERATION,
    323                   "%s(skip-images %% block-depth)", caller);
    324       return false;
    325    }
    326 
    327    return true;
    328 }
    329