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