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