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
39void GLAPIENTRY
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
243invalid_enum_error:
244   _mesa_error( ctx, GL_INVALID_ENUM, "glPixelStore" );
245   return;
246}
247
248
249void GLAPIENTRY
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 */
260void
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