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