1c1f859d4Smrg/* 2c1f859d4Smrg * Mesa 3-D graphics library 3c1f859d4Smrg * 4c1f859d4Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5c1f859d4Smrg * 6c1f859d4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7c1f859d4Smrg * copy of this software and associated documentation files (the "Software"), 8c1f859d4Smrg * to deal in the Software without restriction, including without limitation 9c1f859d4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10c1f859d4Smrg * and/or sell copies of the Software, and to permit persons to whom the 11c1f859d4Smrg * Software is furnished to do so, subject to the following conditions: 12c1f859d4Smrg * 13c1f859d4Smrg * The above copyright notice and this permission notice shall be included 14c1f859d4Smrg * in all copies or substantial portions of the Software. 15c1f859d4Smrg * 16c1f859d4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17c1f859d4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18c1f859d4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 23c1f859d4Smrg */ 24c1f859d4Smrg 25c1f859d4Smrg/** 26c1f859d4Smrg * \file pixelstore.c 27c1f859d4Smrg * glPixelStore functions. 28c1f859d4Smrg */ 29c1f859d4Smrg 30c1f859d4Smrg 31c1f859d4Smrg#include "glheader.h" 32c1f859d4Smrg#include "bufferobj.h" 33c1f859d4Smrg#include "context.h" 34c1f859d4Smrg#include "pixelstore.h" 35c1f859d4Smrg#include "mtypes.h" 367ec681f3Smrg#include "util/rounding.h" 37c1f859d4Smrg 38c1f859d4Smrg 3901e04c3fSmrgstatic ALWAYS_INLINE void 4001e04c3fSmrgpixel_storei(GLenum pname, GLint param, bool no_error) 41c1f859d4Smrg{ 42c1f859d4Smrg /* NOTE: this call can't be compiled into the display list */ 43c1f859d4Smrg GET_CURRENT_CONTEXT(ctx); 44c1f859d4Smrg 45c1f859d4Smrg switch (pname) { 46c1f859d4Smrg case GL_PACK_SWAP_BYTES: 4701e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 48af69d88dSmrg goto invalid_enum_error; 49c1f859d4Smrg ctx->Pack.SwapBytes = param ? GL_TRUE : GL_FALSE; 50af69d88dSmrg break; 51c1f859d4Smrg case GL_PACK_LSB_FIRST: 5201e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 53af69d88dSmrg goto invalid_enum_error; 54c1f859d4Smrg ctx->Pack.LsbFirst = param ? GL_TRUE : GL_FALSE; 55af69d88dSmrg break; 56c1f859d4Smrg case GL_PACK_ROW_LENGTH: 5701e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 58af69d88dSmrg goto invalid_enum_error; 5901e04c3fSmrg if (!no_error && param<0) 60af69d88dSmrg goto invalid_value_error; 61af69d88dSmrg ctx->Pack.RowLength = param; 62af69d88dSmrg break; 63c1f859d4Smrg case GL_PACK_IMAGE_HEIGHT: 6401e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 65af69d88dSmrg goto invalid_enum_error; 6601e04c3fSmrg if (!no_error && param<0) 67af69d88dSmrg goto invalid_value_error; 68af69d88dSmrg ctx->Pack.ImageHeight = param; 69c1f859d4Smrg break; 70c1f859d4Smrg case GL_PACK_SKIP_PIXELS: 7101e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 72af69d88dSmrg goto invalid_enum_error; 7301e04c3fSmrg if (!no_error && param<0) 74af69d88dSmrg goto invalid_value_error; 75af69d88dSmrg ctx->Pack.SkipPixels = param; 76af69d88dSmrg break; 77c1f859d4Smrg case GL_PACK_SKIP_ROWS: 7801e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 79af69d88dSmrg goto invalid_enum_error; 8001e04c3fSmrg if (!no_error && param<0) 81af69d88dSmrg goto invalid_value_error; 82af69d88dSmrg ctx->Pack.SkipRows = param; 83af69d88dSmrg break; 84c1f859d4Smrg case GL_PACK_SKIP_IMAGES: 8501e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 86af69d88dSmrg goto invalid_enum_error; 8701e04c3fSmrg if (!no_error && param<0) 88af69d88dSmrg goto invalid_value_error; 89af69d88dSmrg ctx->Pack.SkipImages = param; 90af69d88dSmrg break; 91c1f859d4Smrg case GL_PACK_ALIGNMENT: 9201e04c3fSmrg if (!no_error && param!=1 && param!=2 && param!=4 && param!=8) 93af69d88dSmrg goto invalid_value_error; 94af69d88dSmrg ctx->Pack.Alignment = param; 95af69d88dSmrg break; 96c1f859d4Smrg case GL_PACK_INVERT_MESA: 977ec681f3Smrg if (!no_error && !_mesa_has_MESA_pack_invert(ctx)) 987ec681f3Smrg goto invalid_enum_error; 997ec681f3Smrg ctx->Pack.Invert = param; 1007ec681f3Smrg break; 1017ec681f3Smrg case GL_PACK_REVERSE_ROW_ORDER_ANGLE: 1027ec681f3Smrg if (!no_error && !_mesa_has_ANGLE_pack_reverse_row_order(ctx)) 103af69d88dSmrg goto invalid_enum_error; 104c1f859d4Smrg ctx->Pack.Invert = param; 105c1f859d4Smrg break; 106af69d88dSmrg case GL_PACK_COMPRESSED_BLOCK_WIDTH: 10701e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 108af69d88dSmrg goto invalid_enum_error; 10901e04c3fSmrg if (!no_error && param<0) 110af69d88dSmrg goto invalid_value_error; 111af69d88dSmrg ctx->Pack.CompressedBlockWidth = param; 112af69d88dSmrg break; 113af69d88dSmrg case GL_PACK_COMPRESSED_BLOCK_HEIGHT: 11401e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 115af69d88dSmrg goto invalid_enum_error; 11601e04c3fSmrg if (!no_error && param<0) 117af69d88dSmrg goto invalid_value_error; 118af69d88dSmrg ctx->Pack.CompressedBlockHeight = param; 119af69d88dSmrg break; 120af69d88dSmrg case GL_PACK_COMPRESSED_BLOCK_DEPTH: 12101e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 122af69d88dSmrg goto invalid_enum_error; 12301e04c3fSmrg if (!no_error && param<0) 124af69d88dSmrg goto invalid_value_error; 125af69d88dSmrg ctx->Pack.CompressedBlockDepth = param; 126af69d88dSmrg break; 127af69d88dSmrg case GL_PACK_COMPRESSED_BLOCK_SIZE: 12801e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 129af69d88dSmrg goto invalid_enum_error; 13001e04c3fSmrg if (!no_error && param<0) 131af69d88dSmrg goto invalid_value_error; 132af69d88dSmrg ctx->Pack.CompressedBlockSize = param; 133af69d88dSmrg break; 134c1f859d4Smrg 135c1f859d4Smrg case GL_UNPACK_SWAP_BYTES: 13601e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 137af69d88dSmrg goto invalid_enum_error; 138af69d88dSmrg ctx->Unpack.SwapBytes = param ? GL_TRUE : GL_FALSE; 139c1f859d4Smrg break; 140c1f859d4Smrg case GL_UNPACK_LSB_FIRST: 14101e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 142af69d88dSmrg goto invalid_enum_error; 143af69d88dSmrg ctx->Unpack.LsbFirst = param ? GL_TRUE : GL_FALSE; 144af69d88dSmrg break; 145c1f859d4Smrg case GL_UNPACK_ROW_LENGTH: 14601e04c3fSmrg if (!no_error && ctx->API == API_OPENGLES) 147af69d88dSmrg goto invalid_enum_error; 14801e04c3fSmrg if (!no_error && param<0) 149af69d88dSmrg goto invalid_value_error; 150af69d88dSmrg ctx->Unpack.RowLength = param; 151af69d88dSmrg break; 152c1f859d4Smrg case GL_UNPACK_IMAGE_HEIGHT: 15301e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 154af69d88dSmrg goto invalid_enum_error; 15501e04c3fSmrg if (!no_error && param<0) 156af69d88dSmrg goto invalid_value_error; 157af69d88dSmrg ctx->Unpack.ImageHeight = param; 158c1f859d4Smrg break; 159c1f859d4Smrg case GL_UNPACK_SKIP_PIXELS: 16001e04c3fSmrg if (!no_error && ctx->API == API_OPENGLES) 161af69d88dSmrg goto invalid_enum_error; 16201e04c3fSmrg if (!no_error && param<0) 163af69d88dSmrg goto invalid_value_error; 164af69d88dSmrg ctx->Unpack.SkipPixels = param; 165af69d88dSmrg break; 166c1f859d4Smrg case GL_UNPACK_SKIP_ROWS: 16701e04c3fSmrg if (!no_error && ctx->API == API_OPENGLES) 168af69d88dSmrg goto invalid_enum_error; 16901e04c3fSmrg if (!no_error && param<0) 170af69d88dSmrg goto invalid_value_error; 171af69d88dSmrg ctx->Unpack.SkipRows = param; 172af69d88dSmrg break; 173c1f859d4Smrg case GL_UNPACK_SKIP_IMAGES: 17401e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 175af69d88dSmrg goto invalid_enum_error; 17601e04c3fSmrg if (!no_error && param < 0) 177af69d88dSmrg goto invalid_value_error; 178af69d88dSmrg ctx->Unpack.SkipImages = param; 179af69d88dSmrg break; 180c1f859d4Smrg case GL_UNPACK_ALIGNMENT: 18101e04c3fSmrg if (!no_error && param!=1 && param!=2 && param!=4 && param!=8) 182af69d88dSmrg goto invalid_value_error; 183af69d88dSmrg ctx->Unpack.Alignment = param; 184af69d88dSmrg break; 185af69d88dSmrg case GL_UNPACK_COMPRESSED_BLOCK_WIDTH: 18601e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 187af69d88dSmrg goto invalid_enum_error; 18801e04c3fSmrg if (!no_error && param<0) 189af69d88dSmrg goto invalid_value_error; 190af69d88dSmrg ctx->Unpack.CompressedBlockWidth = param; 191af69d88dSmrg break; 192af69d88dSmrg case GL_UNPACK_COMPRESSED_BLOCK_HEIGHT: 19301e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 194af69d88dSmrg goto invalid_enum_error; 19501e04c3fSmrg if (!no_error && param<0) 196af69d88dSmrg goto invalid_value_error; 197af69d88dSmrg ctx->Unpack.CompressedBlockHeight = param; 198af69d88dSmrg break; 199af69d88dSmrg case GL_UNPACK_COMPRESSED_BLOCK_DEPTH: 20001e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 201af69d88dSmrg goto invalid_enum_error; 20201e04c3fSmrg if (!no_error && param<0) 203af69d88dSmrg goto invalid_value_error; 204af69d88dSmrg ctx->Unpack.CompressedBlockDepth = param; 205af69d88dSmrg break; 206af69d88dSmrg case GL_UNPACK_COMPRESSED_BLOCK_SIZE: 20701e04c3fSmrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 208af69d88dSmrg goto invalid_enum_error; 20901e04c3fSmrg if (!no_error && param<0) 210af69d88dSmrg goto invalid_value_error; 211af69d88dSmrg ctx->Unpack.CompressedBlockSize = param; 212c1f859d4Smrg break; 213c1f859d4Smrg default: 21401e04c3fSmrg if (!no_error) 21501e04c3fSmrg goto invalid_enum_error; 21601e04c3fSmrg else 21701e04c3fSmrg unreachable("invalid pixel store enum"); 218c1f859d4Smrg } 219af69d88dSmrg 220af69d88dSmrg return; 221af69d88dSmrg 222af69d88dSmrginvalid_enum_error: 22301e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glPixelStore"); 224af69d88dSmrg return; 225af69d88dSmrg 226af69d88dSmrginvalid_value_error: 22701e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glPixelStore(param)"); 228af69d88dSmrg return; 229c1f859d4Smrg} 230c1f859d4Smrg 231c1f859d4Smrg 232c1f859d4Smrgvoid GLAPIENTRY 23301e04c3fSmrg_mesa_PixelStorei(GLenum pname, GLint param) 23401e04c3fSmrg{ 23501e04c3fSmrg pixel_storei(pname, param, false); 23601e04c3fSmrg} 23701e04c3fSmrg 23801e04c3fSmrg 23901e04c3fSmrgvoid GLAPIENTRY 24001e04c3fSmrg_mesa_PixelStoref(GLenum pname, GLfloat param) 24101e04c3fSmrg{ 2427ec681f3Smrg _mesa_PixelStorei(pname, lroundf(param)); 24301e04c3fSmrg} 24401e04c3fSmrg 24501e04c3fSmrg 24601e04c3fSmrgvoid GLAPIENTRY 24701e04c3fSmrg_mesa_PixelStorei_no_error(GLenum pname, GLint param) 248c1f859d4Smrg{ 24901e04c3fSmrg pixel_storei(pname, param, true); 250c1f859d4Smrg} 251c1f859d4Smrg 252c1f859d4Smrg 25301e04c3fSmrgvoid GLAPIENTRY 25401e04c3fSmrg_mesa_PixelStoref_no_error(GLenum pname, GLfloat param) 25501e04c3fSmrg{ 2567ec681f3Smrg _mesa_PixelStorei_no_error(pname, lroundf(param)); 25701e04c3fSmrg} 25801e04c3fSmrg 259c1f859d4Smrg 260c1f859d4Smrg/** 261c1f859d4Smrg * Initialize the context's pixel store state. 262c1f859d4Smrg */ 263c1f859d4Smrgvoid 26401e04c3fSmrg_mesa_init_pixelstore(struct gl_context *ctx) 265c1f859d4Smrg{ 266c1f859d4Smrg /* Pixel transfer */ 267c1f859d4Smrg ctx->Pack.Alignment = 4; 268c1f859d4Smrg ctx->Pack.RowLength = 0; 269c1f859d4Smrg ctx->Pack.ImageHeight = 0; 270c1f859d4Smrg ctx->Pack.SkipPixels = 0; 271c1f859d4Smrg ctx->Pack.SkipRows = 0; 272c1f859d4Smrg ctx->Pack.SkipImages = 0; 273c1f859d4Smrg ctx->Pack.SwapBytes = GL_FALSE; 274c1f859d4Smrg ctx->Pack.LsbFirst = GL_FALSE; 275c1f859d4Smrg ctx->Pack.Invert = GL_FALSE; 276af69d88dSmrg ctx->Pack.CompressedBlockWidth = 0; 277af69d88dSmrg ctx->Pack.CompressedBlockHeight = 0; 278af69d88dSmrg ctx->Pack.CompressedBlockDepth = 0; 279af69d88dSmrg ctx->Pack.CompressedBlockSize = 0; 2807ec681f3Smrg _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL); 281c1f859d4Smrg ctx->Unpack.Alignment = 4; 282c1f859d4Smrg ctx->Unpack.RowLength = 0; 283c1f859d4Smrg ctx->Unpack.ImageHeight = 0; 284c1f859d4Smrg ctx->Unpack.SkipPixels = 0; 285c1f859d4Smrg ctx->Unpack.SkipRows = 0; 286c1f859d4Smrg ctx->Unpack.SkipImages = 0; 287c1f859d4Smrg ctx->Unpack.SwapBytes = GL_FALSE; 288c1f859d4Smrg ctx->Unpack.LsbFirst = GL_FALSE; 289c1f859d4Smrg ctx->Unpack.Invert = GL_FALSE; 290af69d88dSmrg ctx->Unpack.CompressedBlockWidth = 0; 291af69d88dSmrg ctx->Unpack.CompressedBlockHeight = 0; 292af69d88dSmrg ctx->Unpack.CompressedBlockDepth = 0; 293af69d88dSmrg ctx->Unpack.CompressedBlockSize = 0; 2947ec681f3Smrg _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL); 295c1f859d4Smrg 296c1f859d4Smrg /* 297c1f859d4Smrg * _mesa_unpack_image() returns image data in this format. When we 298c1f859d4Smrg * execute image commands (glDrawPixels(), glTexImage(), etc) from 299c1f859d4Smrg * within display lists we have to be sure to set the current 300c1f859d4Smrg * unpacking parameters to these values! 301c1f859d4Smrg */ 302c1f859d4Smrg ctx->DefaultPacking.Alignment = 1; 303c1f859d4Smrg ctx->DefaultPacking.RowLength = 0; 304c1f859d4Smrg ctx->DefaultPacking.SkipPixels = 0; 305c1f859d4Smrg ctx->DefaultPacking.SkipRows = 0; 306c1f859d4Smrg ctx->DefaultPacking.ImageHeight = 0; 307c1f859d4Smrg ctx->DefaultPacking.SkipImages = 0; 308c1f859d4Smrg ctx->DefaultPacking.SwapBytes = GL_FALSE; 309c1f859d4Smrg ctx->DefaultPacking.LsbFirst = GL_FALSE; 310c1f859d4Smrg ctx->DefaultPacking.Invert = GL_FALSE; 3117ec681f3Smrg _mesa_reference_buffer_object(ctx, &ctx->DefaultPacking.BufferObj, NULL); 312af69d88dSmrg} 313af69d88dSmrg 314af69d88dSmrg 315af69d88dSmrg/** 316af69d88dSmrg * Check if the given compressed pixel storage parameters are legal. 317af69d88dSmrg * Record a GL error if illegal. 318af69d88dSmrg * \return true if legal, false if illegal 319af69d88dSmrg */ 320af69d88dSmrgbool 321af69d88dSmrg_mesa_compressed_pixel_storage_error_check( 322af69d88dSmrg struct gl_context *ctx, 323af69d88dSmrg GLint dimensions, 324af69d88dSmrg const struct gl_pixelstore_attrib *packing, 325af69d88dSmrg const char *caller) 326af69d88dSmrg{ 327af69d88dSmrg if (!_mesa_is_desktop_gl(ctx) || !packing->CompressedBlockSize) 328af69d88dSmrg return true; 329af69d88dSmrg 330af69d88dSmrg if (packing->CompressedBlockWidth && 331af69d88dSmrg packing->SkipPixels % packing->CompressedBlockWidth) { 332af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 333af69d88dSmrg "%s(skip-pixels %% block-width)", caller); 334af69d88dSmrg return false; 335af69d88dSmrg } 336af69d88dSmrg 337af69d88dSmrg if (dimensions > 1 && 338af69d88dSmrg packing->CompressedBlockHeight && 339af69d88dSmrg packing->SkipRows % packing->CompressedBlockHeight) { 340af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 341af69d88dSmrg "%s(skip-rows %% block-height)", caller); 342af69d88dSmrg return false; 343af69d88dSmrg } 344af69d88dSmrg 345af69d88dSmrg if (dimensions > 2 && 346af69d88dSmrg packing->CompressedBlockDepth && 347af69d88dSmrg packing->SkipImages % packing->CompressedBlockDepth) { 348af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 349af69d88dSmrg "%s(skip-images %% block-depth)", caller); 350af69d88dSmrg return false; 351af69d88dSmrg } 352af69d88dSmrg 353af69d88dSmrg return true; 354c1f859d4Smrg} 355