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