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