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