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