1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg/** 26848b8605Smrg * \file pixelstore.c 27848b8605Smrg * glPixelStore functions. 28848b8605Smrg */ 29848b8605Smrg 30848b8605Smrg 31848b8605Smrg#include "glheader.h" 32848b8605Smrg#include "bufferobj.h" 33848b8605Smrg#include "context.h" 34848b8605Smrg#include "pixelstore.h" 35848b8605Smrg#include "mtypes.h" 36848b8605Smrg 37848b8605Smrg 38b8e80941Smrgstatic ALWAYS_INLINE void 39b8e80941Smrgpixel_storei(GLenum pname, GLint param, bool no_error) 40848b8605Smrg{ 41848b8605Smrg /* NOTE: this call can't be compiled into the display list */ 42848b8605Smrg GET_CURRENT_CONTEXT(ctx); 43848b8605Smrg 44848b8605Smrg switch (pname) { 45848b8605Smrg case GL_PACK_SWAP_BYTES: 46b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 47848b8605Smrg goto invalid_enum_error; 48848b8605Smrg ctx->Pack.SwapBytes = param ? GL_TRUE : GL_FALSE; 49848b8605Smrg break; 50848b8605Smrg case GL_PACK_LSB_FIRST: 51b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 52848b8605Smrg goto invalid_enum_error; 53848b8605Smrg ctx->Pack.LsbFirst = param ? GL_TRUE : GL_FALSE; 54848b8605Smrg break; 55848b8605Smrg case GL_PACK_ROW_LENGTH: 56b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 57848b8605Smrg goto invalid_enum_error; 58b8e80941Smrg if (!no_error && param<0) 59848b8605Smrg goto invalid_value_error; 60848b8605Smrg ctx->Pack.RowLength = param; 61848b8605Smrg break; 62848b8605Smrg case GL_PACK_IMAGE_HEIGHT: 63b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 64848b8605Smrg goto invalid_enum_error; 65b8e80941Smrg if (!no_error && param<0) 66848b8605Smrg goto invalid_value_error; 67848b8605Smrg ctx->Pack.ImageHeight = param; 68848b8605Smrg break; 69848b8605Smrg case GL_PACK_SKIP_PIXELS: 70b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 71848b8605Smrg goto invalid_enum_error; 72b8e80941Smrg if (!no_error && param<0) 73848b8605Smrg goto invalid_value_error; 74848b8605Smrg ctx->Pack.SkipPixels = param; 75848b8605Smrg break; 76848b8605Smrg case GL_PACK_SKIP_ROWS: 77b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 78848b8605Smrg goto invalid_enum_error; 79b8e80941Smrg if (!no_error && param<0) 80848b8605Smrg goto invalid_value_error; 81848b8605Smrg ctx->Pack.SkipRows = param; 82848b8605Smrg break; 83848b8605Smrg case GL_PACK_SKIP_IMAGES: 84b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 85848b8605Smrg goto invalid_enum_error; 86b8e80941Smrg if (!no_error && param<0) 87848b8605Smrg goto invalid_value_error; 88848b8605Smrg ctx->Pack.SkipImages = param; 89848b8605Smrg break; 90848b8605Smrg case GL_PACK_ALIGNMENT: 91b8e80941Smrg if (!no_error && param!=1 && param!=2 && param!=4 && param!=8) 92848b8605Smrg goto invalid_value_error; 93848b8605Smrg ctx->Pack.Alignment = param; 94848b8605Smrg break; 95848b8605Smrg case GL_PACK_INVERT_MESA: 96b8e80941Smrg if (!no_error && 97b8e80941Smrg (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.MESA_pack_invert)) 98848b8605Smrg goto invalid_enum_error; 99848b8605Smrg ctx->Pack.Invert = param; 100848b8605Smrg break; 101848b8605Smrg case GL_PACK_COMPRESSED_BLOCK_WIDTH: 102b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 103848b8605Smrg goto invalid_enum_error; 104b8e80941Smrg if (!no_error && param<0) 105848b8605Smrg goto invalid_value_error; 106848b8605Smrg ctx->Pack.CompressedBlockWidth = param; 107848b8605Smrg break; 108848b8605Smrg case GL_PACK_COMPRESSED_BLOCK_HEIGHT: 109b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 110848b8605Smrg goto invalid_enum_error; 111b8e80941Smrg if (!no_error && param<0) 112848b8605Smrg goto invalid_value_error; 113848b8605Smrg ctx->Pack.CompressedBlockHeight = param; 114848b8605Smrg break; 115848b8605Smrg case GL_PACK_COMPRESSED_BLOCK_DEPTH: 116b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 117848b8605Smrg goto invalid_enum_error; 118b8e80941Smrg if (!no_error && param<0) 119848b8605Smrg goto invalid_value_error; 120848b8605Smrg ctx->Pack.CompressedBlockDepth = param; 121848b8605Smrg break; 122848b8605Smrg case GL_PACK_COMPRESSED_BLOCK_SIZE: 123b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 124848b8605Smrg goto invalid_enum_error; 125b8e80941Smrg if (!no_error && param<0) 126848b8605Smrg goto invalid_value_error; 127848b8605Smrg ctx->Pack.CompressedBlockSize = param; 128848b8605Smrg break; 129848b8605Smrg 130848b8605Smrg case GL_UNPACK_SWAP_BYTES: 131b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 132848b8605Smrg goto invalid_enum_error; 133848b8605Smrg ctx->Unpack.SwapBytes = param ? GL_TRUE : GL_FALSE; 134848b8605Smrg break; 135848b8605Smrg case GL_UNPACK_LSB_FIRST: 136b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 137848b8605Smrg goto invalid_enum_error; 138848b8605Smrg ctx->Unpack.LsbFirst = param ? GL_TRUE : GL_FALSE; 139848b8605Smrg break; 140848b8605Smrg case GL_UNPACK_ROW_LENGTH: 141b8e80941Smrg if (!no_error && ctx->API == API_OPENGLES) 142848b8605Smrg goto invalid_enum_error; 143b8e80941Smrg if (!no_error && param<0) 144848b8605Smrg goto invalid_value_error; 145848b8605Smrg ctx->Unpack.RowLength = param; 146848b8605Smrg break; 147848b8605Smrg case GL_UNPACK_IMAGE_HEIGHT: 148b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 149848b8605Smrg goto invalid_enum_error; 150b8e80941Smrg if (!no_error && param<0) 151848b8605Smrg goto invalid_value_error; 152848b8605Smrg ctx->Unpack.ImageHeight = param; 153848b8605Smrg break; 154848b8605Smrg case GL_UNPACK_SKIP_PIXELS: 155b8e80941Smrg if (!no_error && ctx->API == API_OPENGLES) 156848b8605Smrg goto invalid_enum_error; 157b8e80941Smrg if (!no_error && param<0) 158848b8605Smrg goto invalid_value_error; 159848b8605Smrg ctx->Unpack.SkipPixels = param; 160848b8605Smrg break; 161848b8605Smrg case GL_UNPACK_SKIP_ROWS: 162b8e80941Smrg if (!no_error && ctx->API == API_OPENGLES) 163848b8605Smrg goto invalid_enum_error; 164b8e80941Smrg if (!no_error && param<0) 165848b8605Smrg goto invalid_value_error; 166848b8605Smrg ctx->Unpack.SkipRows = param; 167848b8605Smrg break; 168848b8605Smrg case GL_UNPACK_SKIP_IMAGES: 169b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) 170848b8605Smrg goto invalid_enum_error; 171b8e80941Smrg if (!no_error && param < 0) 172848b8605Smrg goto invalid_value_error; 173848b8605Smrg ctx->Unpack.SkipImages = param; 174848b8605Smrg break; 175848b8605Smrg case GL_UNPACK_ALIGNMENT: 176b8e80941Smrg if (!no_error && param!=1 && param!=2 && param!=4 && param!=8) 177848b8605Smrg goto invalid_value_error; 178848b8605Smrg ctx->Unpack.Alignment = param; 179848b8605Smrg break; 180848b8605Smrg case GL_UNPACK_COMPRESSED_BLOCK_WIDTH: 181b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 182848b8605Smrg goto invalid_enum_error; 183b8e80941Smrg if (!no_error && param<0) 184848b8605Smrg goto invalid_value_error; 185848b8605Smrg ctx->Unpack.CompressedBlockWidth = param; 186848b8605Smrg break; 187848b8605Smrg case GL_UNPACK_COMPRESSED_BLOCK_HEIGHT: 188b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 189848b8605Smrg goto invalid_enum_error; 190b8e80941Smrg if (!no_error && param<0) 191848b8605Smrg goto invalid_value_error; 192848b8605Smrg ctx->Unpack.CompressedBlockHeight = param; 193848b8605Smrg break; 194848b8605Smrg case GL_UNPACK_COMPRESSED_BLOCK_DEPTH: 195b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 196848b8605Smrg goto invalid_enum_error; 197b8e80941Smrg if (!no_error && param<0) 198848b8605Smrg goto invalid_value_error; 199848b8605Smrg ctx->Unpack.CompressedBlockDepth = param; 200848b8605Smrg break; 201848b8605Smrg case GL_UNPACK_COMPRESSED_BLOCK_SIZE: 202b8e80941Smrg if (!no_error && !_mesa_is_desktop_gl(ctx)) 203848b8605Smrg goto invalid_enum_error; 204b8e80941Smrg if (!no_error && param<0) 205848b8605Smrg goto invalid_value_error; 206848b8605Smrg ctx->Unpack.CompressedBlockSize = param; 207848b8605Smrg break; 208848b8605Smrg default: 209b8e80941Smrg if (!no_error) 210b8e80941Smrg goto invalid_enum_error; 211b8e80941Smrg else 212b8e80941Smrg unreachable("invalid pixel store enum"); 213848b8605Smrg } 214848b8605Smrg 215848b8605Smrg return; 216848b8605Smrg 217848b8605Smrginvalid_enum_error: 218b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glPixelStore"); 219848b8605Smrg return; 220848b8605Smrg 221848b8605Smrginvalid_value_error: 222b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glPixelStore(param)"); 223848b8605Smrg return; 224848b8605Smrg} 225848b8605Smrg 226848b8605Smrg 227848b8605Smrgvoid GLAPIENTRY 228b8e80941Smrg_mesa_PixelStorei(GLenum pname, GLint param) 229b8e80941Smrg{ 230b8e80941Smrg pixel_storei(pname, param, false); 231b8e80941Smrg} 232b8e80941Smrg 233b8e80941Smrg 234b8e80941Smrgvoid GLAPIENTRY 235b8e80941Smrg_mesa_PixelStoref(GLenum pname, GLfloat param) 236b8e80941Smrg{ 237b8e80941Smrg _mesa_PixelStorei(pname, IROUND(param)); 238b8e80941Smrg} 239b8e80941Smrg 240b8e80941Smrg 241b8e80941Smrgvoid GLAPIENTRY 242b8e80941Smrg_mesa_PixelStorei_no_error(GLenum pname, GLint param) 243848b8605Smrg{ 244b8e80941Smrg pixel_storei(pname, param, true); 245848b8605Smrg} 246848b8605Smrg 247848b8605Smrg 248b8e80941Smrgvoid GLAPIENTRY 249b8e80941Smrg_mesa_PixelStoref_no_error(GLenum pname, GLfloat param) 250b8e80941Smrg{ 251b8e80941Smrg _mesa_PixelStorei_no_error(pname, IROUND(param)); 252b8e80941Smrg} 253b8e80941Smrg 254848b8605Smrg 255848b8605Smrg/** 256848b8605Smrg * Initialize the context's pixel store state. 257848b8605Smrg */ 258848b8605Smrgvoid 259b8e80941Smrg_mesa_init_pixelstore(struct gl_context *ctx) 260848b8605Smrg{ 261848b8605Smrg /* Pixel transfer */ 262848b8605Smrg ctx->Pack.Alignment = 4; 263848b8605Smrg ctx->Pack.RowLength = 0; 264848b8605Smrg ctx->Pack.ImageHeight = 0; 265848b8605Smrg ctx->Pack.SkipPixels = 0; 266848b8605Smrg ctx->Pack.SkipRows = 0; 267848b8605Smrg ctx->Pack.SkipImages = 0; 268848b8605Smrg ctx->Pack.SwapBytes = GL_FALSE; 269848b8605Smrg ctx->Pack.LsbFirst = GL_FALSE; 270848b8605Smrg ctx->Pack.Invert = GL_FALSE; 271848b8605Smrg ctx->Pack.CompressedBlockWidth = 0; 272848b8605Smrg ctx->Pack.CompressedBlockHeight = 0; 273848b8605Smrg ctx->Pack.CompressedBlockDepth = 0; 274848b8605Smrg ctx->Pack.CompressedBlockSize = 0; 275848b8605Smrg _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, 276848b8605Smrg ctx->Shared->NullBufferObj); 277848b8605Smrg ctx->Unpack.Alignment = 4; 278848b8605Smrg ctx->Unpack.RowLength = 0; 279848b8605Smrg ctx->Unpack.ImageHeight = 0; 280848b8605Smrg ctx->Unpack.SkipPixels = 0; 281848b8605Smrg ctx->Unpack.SkipRows = 0; 282848b8605Smrg ctx->Unpack.SkipImages = 0; 283848b8605Smrg ctx->Unpack.SwapBytes = GL_FALSE; 284848b8605Smrg ctx->Unpack.LsbFirst = GL_FALSE; 285848b8605Smrg ctx->Unpack.Invert = GL_FALSE; 286848b8605Smrg ctx->Unpack.CompressedBlockWidth = 0; 287848b8605Smrg ctx->Unpack.CompressedBlockHeight = 0; 288848b8605Smrg ctx->Unpack.CompressedBlockDepth = 0; 289848b8605Smrg ctx->Unpack.CompressedBlockSize = 0; 290848b8605Smrg _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, 291848b8605Smrg ctx->Shared->NullBufferObj); 292848b8605Smrg 293848b8605Smrg /* 294848b8605Smrg * _mesa_unpack_image() returns image data in this format. When we 295848b8605Smrg * execute image commands (glDrawPixels(), glTexImage(), etc) from 296848b8605Smrg * within display lists we have to be sure to set the current 297848b8605Smrg * unpacking parameters to these values! 298848b8605Smrg */ 299848b8605Smrg ctx->DefaultPacking.Alignment = 1; 300848b8605Smrg ctx->DefaultPacking.RowLength = 0; 301848b8605Smrg ctx->DefaultPacking.SkipPixels = 0; 302848b8605Smrg ctx->DefaultPacking.SkipRows = 0; 303848b8605Smrg ctx->DefaultPacking.ImageHeight = 0; 304848b8605Smrg ctx->DefaultPacking.SkipImages = 0; 305848b8605Smrg ctx->DefaultPacking.SwapBytes = GL_FALSE; 306848b8605Smrg ctx->DefaultPacking.LsbFirst = GL_FALSE; 307848b8605Smrg ctx->DefaultPacking.Invert = GL_FALSE; 308848b8605Smrg _mesa_reference_buffer_object(ctx, &ctx->DefaultPacking.BufferObj, 309848b8605Smrg ctx->Shared->NullBufferObj); 310848b8605Smrg} 311848b8605Smrg 312848b8605Smrg 313848b8605Smrg/** 314848b8605Smrg * Check if the given compressed pixel storage parameters are legal. 315848b8605Smrg * Record a GL error if illegal. 316848b8605Smrg * \return true if legal, false if illegal 317848b8605Smrg */ 318848b8605Smrgbool 319848b8605Smrg_mesa_compressed_pixel_storage_error_check( 320848b8605Smrg struct gl_context *ctx, 321848b8605Smrg GLint dimensions, 322848b8605Smrg const struct gl_pixelstore_attrib *packing, 323848b8605Smrg const char *caller) 324848b8605Smrg{ 325848b8605Smrg if (!_mesa_is_desktop_gl(ctx) || !packing->CompressedBlockSize) 326848b8605Smrg return true; 327848b8605Smrg 328848b8605Smrg if (packing->CompressedBlockWidth && 329848b8605Smrg packing->SkipPixels % packing->CompressedBlockWidth) { 330848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 331848b8605Smrg "%s(skip-pixels %% block-width)", caller); 332848b8605Smrg return false; 333848b8605Smrg } 334848b8605Smrg 335848b8605Smrg if (dimensions > 1 && 336848b8605Smrg packing->CompressedBlockHeight && 337848b8605Smrg packing->SkipRows % packing->CompressedBlockHeight) { 338848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 339848b8605Smrg "%s(skip-rows %% block-height)", caller); 340848b8605Smrg return false; 341848b8605Smrg } 342848b8605Smrg 343848b8605Smrg if (dimensions > 2 && 344848b8605Smrg packing->CompressedBlockDepth && 345848b8605Smrg packing->SkipImages % packing->CompressedBlockDepth) { 346848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 347848b8605Smrg "%s(skip-images %% block-depth)", caller); 348848b8605Smrg return false; 349848b8605Smrg } 350848b8605Smrg 351848b8605Smrg return true; 352848b8605Smrg} 353