1 /*
2  * Mesa 3-D graphics library
3  * Version:  7.1
4  *
5  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR 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 "mfeatures.h"
36 #include "mtypes.h"
37 
38 
39 void GLAPIENTRY
_mesa_PixelStorei(GLenum pname,GLint param)40 _mesa_PixelStorei( GLenum pname, GLint param )
41 {
42    /* NOTE: this call can't be compiled into the display list */
43    GET_CURRENT_CONTEXT(ctx);
44    ASSERT_OUTSIDE_BEGIN_END(ctx);
45 
46    switch (pname) {
47       case GL_PACK_SWAP_BYTES:
48          if (!_mesa_is_desktop_gl(ctx))
49             goto invalid_enum_error;
50 	 if (param == (GLint)ctx->Pack.SwapBytes)
51 	    return;
52 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
53          ctx->Pack.SwapBytes = param ? GL_TRUE : GL_FALSE;
54 	 break;
55       case GL_PACK_LSB_FIRST:
56          if (!_mesa_is_desktop_gl(ctx))
57             goto invalid_enum_error;
58 	 if (param == (GLint)ctx->Pack.LsbFirst)
59 	    return;
60 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
61          ctx->Pack.LsbFirst = param ? GL_TRUE : GL_FALSE;
62 	 break;
63       case GL_PACK_ROW_LENGTH:
64          if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
65             goto invalid_enum_error;
66 	 if (param<0) {
67 	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
68 	    return;
69 	 }
70 	 if (ctx->Pack.RowLength == param)
71 	    return;
72 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
73 	 ctx->Pack.RowLength = param;
74 	 break;
75       case GL_PACK_IMAGE_HEIGHT:
76          if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
77             goto invalid_enum_error;
78          if (param<0) {
79             _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
80 	    return;
81 	 }
82 	 if (ctx->Pack.ImageHeight == param)
83 	    return;
84 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
85 	 ctx->Pack.ImageHeight = param;
86          break;
87       case GL_PACK_SKIP_PIXELS:
88          if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
89             goto invalid_enum_error;
90 	 if (param<0) {
91 	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
92 	    return;
93 	 }
94 	 if (ctx->Pack.SkipPixels == param)
95 	    return;
96 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
97 	 ctx->Pack.SkipPixels = param;
98 	 break;
99       case GL_PACK_SKIP_ROWS:
100          if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
101             goto invalid_enum_error;
102 	 if (param<0) {
103 	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
104 	    return;
105 	 }
106 	 if (ctx->Pack.SkipRows == param)
107 	    return;
108 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
109 	 ctx->Pack.SkipRows = param;
110 	 break;
111       case GL_PACK_SKIP_IMAGES:
112          if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
113             goto invalid_enum_error;
114 	 if (param<0) {
115 	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
116 	    return;
117 	 }
118 	 if (ctx->Pack.SkipImages == param)
119 	    return;
120 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
121 	 ctx->Pack.SkipImages = param;
122 	 break;
123       case GL_PACK_ALIGNMENT:
124          if (param!=1 && param!=2 && param!=4 && param!=8) {
125 	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
126 	    return;
127 	 }
128 	 if (ctx->Pack.Alignment == param)
129 	    return;
130 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
131 	 ctx->Pack.Alignment = param;
132 	 break;
133       case GL_PACK_INVERT_MESA:
134          if (!_mesa_is_desktop_gl(ctx))
135             goto invalid_enum_error;
136          if (!ctx->Extensions.MESA_pack_invert) {
137             _mesa_error( ctx, GL_INVALID_ENUM, "glPixelstore(pname)" );
138             return;
139          }
140          if (ctx->Pack.Invert == param)
141             return;
142          FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
143          ctx->Pack.Invert = param;
144          break;
145 
146       case GL_UNPACK_SWAP_BYTES:
147          if (!_mesa_is_desktop_gl(ctx))
148             goto invalid_enum_error;
149 	 if (param == (GLint)ctx->Unpack.SwapBytes)
150 	    return;
151 	 if ((GLint)ctx->Unpack.SwapBytes == param)
152 	    return;
153 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
154 	 ctx->Unpack.SwapBytes = param ? GL_TRUE : GL_FALSE;
155          break;
156       case GL_UNPACK_LSB_FIRST:
157          if (!_mesa_is_desktop_gl(ctx))
158             goto invalid_enum_error;
159 	 if (param == (GLint)ctx->Unpack.LsbFirst)
160 	    return;
161 	 if ((GLint)ctx->Unpack.LsbFirst == param)
162 	    return;
163 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
164 	 ctx->Unpack.LsbFirst = param ? GL_TRUE : GL_FALSE;
165 	 break;
166       case GL_UNPACK_ROW_LENGTH:
167          if (ctx->API == API_OPENGLES)
168             goto invalid_enum_error;
169 	 if (param<0) {
170 	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
171 	    return;
172 	 }
173 	 if (ctx->Unpack.RowLength == param)
174 	    return;
175 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
176 	 ctx->Unpack.RowLength = param;
177 	 break;
178       case GL_UNPACK_IMAGE_HEIGHT:
179          if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
180             goto invalid_enum_error;
181          if (param<0) {
182             _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
183 	    return;
184 	 }
185 	 if (ctx->Unpack.ImageHeight == param)
186 	    return;
187 
188 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
189 	 ctx->Unpack.ImageHeight = param;
190          break;
191       case GL_UNPACK_SKIP_PIXELS:
192          if (ctx->API == API_OPENGLES)
193             goto invalid_enum_error;
194 	 if (param<0) {
195 	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
196 	    return;
197 	 }
198 	 if (ctx->Unpack.SkipPixels == param)
199 	    return;
200 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
201 	 ctx->Unpack.SkipPixels = param;
202 	 break;
203       case GL_UNPACK_SKIP_ROWS:
204          if (ctx->API == API_OPENGLES)
205             goto invalid_enum_error;
206 	 if (param<0) {
207 	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
208 	    return;
209 	 }
210 	 if (ctx->Unpack.SkipRows == param)
211 	    return;
212 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
213 	 ctx->Unpack.SkipRows = param;
214 	 break;
215       case GL_UNPACK_SKIP_IMAGES:
216          if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
217             goto invalid_enum_error;
218 	 if (param < 0) {
219 	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
220 	    return;
221 	 }
222 	 if (ctx->Unpack.SkipImages == param)
223 	    return;
224 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
225 	 ctx->Unpack.SkipImages = param;
226 	 break;
227       case GL_UNPACK_ALIGNMENT:
228          if (param!=1 && param!=2 && param!=4 && param!=8) {
229 	    _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore" );
230 	    return;
231 	 }
232 	 if (ctx->Unpack.Alignment == param)
233 	    return;
234 	 FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
235 	 ctx->Unpack.Alignment = param;
236 	 break;
237       default:
238          goto invalid_enum_error;
239    }
240 
241    return;
242 
243 invalid_enum_error:
244    _mesa_error( ctx, GL_INVALID_ENUM, "glPixelStore" );
245    return;
246 }
247 
248 
249 void GLAPIENTRY
_mesa_PixelStoref(GLenum pname,GLfloat param)250 _mesa_PixelStoref( GLenum pname, GLfloat param )
251 {
252    _mesa_PixelStorei( pname, IROUND(param) );
253 }
254 
255 
256 
257 /**
258  * Initialize the context's pixel store state.
259  */
260 void
_mesa_init_pixelstore(struct gl_context * ctx)261 _mesa_init_pixelstore( struct gl_context *ctx )
262 {
263    /* Pixel transfer */
264    ctx->Pack.Alignment = 4;
265    ctx->Pack.RowLength = 0;
266    ctx->Pack.ImageHeight = 0;
267    ctx->Pack.SkipPixels = 0;
268    ctx->Pack.SkipRows = 0;
269    ctx->Pack.SkipImages = 0;
270    ctx->Pack.SwapBytes = GL_FALSE;
271    ctx->Pack.LsbFirst = GL_FALSE;
272    ctx->Pack.Invert = GL_FALSE;
273 #if FEATURE_EXT_pixel_buffer_object
274    _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj,
275                                  ctx->Shared->NullBufferObj);
276 #endif
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 #if FEATURE_EXT_pixel_buffer_object
287    _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj,
288                                  ctx->Shared->NullBufferObj);
289 #endif
290 
291    /*
292     * _mesa_unpack_image() returns image data in this format.  When we
293     * execute image commands (glDrawPixels(), glTexImage(), etc) from
294     * within display lists we have to be sure to set the current
295     * unpacking parameters to these values!
296     */
297    ctx->DefaultPacking.Alignment = 1;
298    ctx->DefaultPacking.RowLength = 0;
299    ctx->DefaultPacking.SkipPixels = 0;
300    ctx->DefaultPacking.SkipRows = 0;
301    ctx->DefaultPacking.ImageHeight = 0;
302    ctx->DefaultPacking.SkipImages = 0;
303    ctx->DefaultPacking.SwapBytes = GL_FALSE;
304    ctx->DefaultPacking.LsbFirst = GL_FALSE;
305    ctx->DefaultPacking.Invert = GL_FALSE;
306 #if FEATURE_EXT_pixel_buffer_object
307    _mesa_reference_buffer_object(ctx, &ctx->DefaultPacking.BufferObj,
308                                  ctx->Shared->NullBufferObj);
309 #endif
310 }
311