Make glXChooseFBConfig handle unspecified sRGB correctly
[mesa.git] / src / glx / pixelstore.c
1 /*
2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice including the dates of first publication and
13 * either this permission notice or a reference to
14 * http://oss.sgi.com/projects/FreeB/
15 * shall be included 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 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Except as contained in this notice, the name of Silicon Graphics, Inc.
26 * shall not be used in advertising or otherwise to promote the sale, use or
27 * other dealings in this Software without prior written authorization from
28 * Silicon Graphics, Inc.
29 */
30
31 #include "glxclient.h"
32 #include "indirect.h"
33 #include "util/rounding.h"
34
35 #if !defined(__GNUC__)
36 # define __builtin_expect(x, y) x
37 #endif
38
39 /**
40 * Send glPixelStore command to the server
41 *
42 * \param gc Current GLX context
43 * \param sop Either \c X_GLsop_PixelStoref or \c X_GLsop_PixelStorei
44 * \param pname Selector of which pixel parameter is to be set.
45 * \param param Value that \c pname is set to.
46 *
47 * \sa __indirect_glPixelStorei, __indirect_glPixelStoref
48 */
49 static void
50 send_PixelStore(struct glx_context * gc, unsigned sop, GLenum pname,
51 const void *param)
52 {
53 Display *const dpy = gc->currentDpy;
54 const GLuint cmdlen = 8;
55 if (__builtin_expect(dpy != NULL, 1)) {
56 GLubyte const *pc = __glXSetupSingleRequest(gc, sop, cmdlen);
57 (void) memcpy((void *) (pc + 0), (void *) (&pname), 4);
58 (void) memcpy((void *) (pc + 4), param, 4);
59 UnlockDisplay(dpy);
60 SyncHandle();
61 }
62 return;
63 }
64
65 /*
66 ** Specify parameters that control the storage format of pixel arrays.
67 */
68 void
69 __indirect_glPixelStoref(GLenum pname, GLfloat param)
70 {
71 struct glx_context *gc = __glXGetCurrentContext();
72 __GLXattribute *state = gc->client_state_private;
73 Display *dpy = gc->currentDpy;
74 GLuint a;
75
76 if (!dpy)
77 return;
78
79 switch (pname) {
80 case GL_PACK_ROW_LENGTH:
81 a = _mesa_lroundevenf(param);
82 if (((GLint) a) < 0) {
83 __glXSetError(gc, GL_INVALID_VALUE);
84 return;
85 }
86 state->storePack.rowLength = a;
87 break;
88 case GL_PACK_IMAGE_HEIGHT:
89 a = _mesa_lroundevenf(param);
90 if (((GLint) a) < 0) {
91 __glXSetError(gc, GL_INVALID_VALUE);
92 return;
93 }
94 state->storePack.imageHeight = a;
95 break;
96 case GL_PACK_SKIP_ROWS:
97 a = _mesa_lroundevenf(param);
98 if (((GLint) a) < 0) {
99 __glXSetError(gc, GL_INVALID_VALUE);
100 return;
101 }
102 state->storePack.skipRows = a;
103 break;
104 case GL_PACK_SKIP_PIXELS:
105 a = _mesa_lroundevenf(param);
106 if (((GLint) a) < 0) {
107 __glXSetError(gc, GL_INVALID_VALUE);
108 return;
109 }
110 state->storePack.skipPixels = a;
111 break;
112 case GL_PACK_SKIP_IMAGES:
113 a = _mesa_lroundevenf(param);
114 if (((GLint) a) < 0) {
115 __glXSetError(gc, GL_INVALID_VALUE);
116 return;
117 }
118 state->storePack.skipImages = a;
119 break;
120 case GL_PACK_ALIGNMENT:
121 a = _mesa_lroundevenf(param);
122 switch (a) {
123 case 1:
124 case 2:
125 case 4:
126 case 8:
127 state->storePack.alignment = a;
128 break;
129 default:
130 __glXSetError(gc, GL_INVALID_VALUE);
131 return;
132 }
133 break;
134 case GL_PACK_SWAP_BYTES:
135 state->storePack.swapEndian = (param != 0);
136 break;
137 case GL_PACK_LSB_FIRST:
138 state->storePack.lsbFirst = (param != 0);
139 break;
140
141 case GL_UNPACK_ROW_LENGTH:
142 a = _mesa_lroundevenf(param);
143 if (((GLint) a) < 0) {
144 __glXSetError(gc, GL_INVALID_VALUE);
145 return;
146 }
147 state->storeUnpack.rowLength = a;
148 break;
149 case GL_UNPACK_IMAGE_HEIGHT:
150 a = _mesa_lroundevenf(param);
151 if (((GLint) a) < 0) {
152 __glXSetError(gc, GL_INVALID_VALUE);
153 return;
154 }
155 state->storeUnpack.imageHeight = a;
156 break;
157 case GL_UNPACK_SKIP_ROWS:
158 a = _mesa_lroundevenf(param);
159 if (((GLint) a) < 0) {
160 __glXSetError(gc, GL_INVALID_VALUE);
161 return;
162 }
163 state->storeUnpack.skipRows = a;
164 break;
165 case GL_UNPACK_SKIP_PIXELS:
166 a = _mesa_lroundevenf(param);
167 if (((GLint) a) < 0) {
168 __glXSetError(gc, GL_INVALID_VALUE);
169 return;
170 }
171 state->storeUnpack.skipPixels = a;
172 break;
173 case GL_UNPACK_SKIP_IMAGES:
174 a = _mesa_lroundevenf(param);
175 if (((GLint) a) < 0) {
176 __glXSetError(gc, GL_INVALID_VALUE);
177 return;
178 }
179 state->storeUnpack.skipImages = a;
180 break;
181 case GL_UNPACK_ALIGNMENT:
182 a = _mesa_lroundevenf(param);
183 switch (a) {
184 case 1:
185 case 2:
186 case 4:
187 case 8:
188 state->storeUnpack.alignment = a;
189 break;
190 default:
191 __glXSetError(gc, GL_INVALID_VALUE);
192 return;
193 }
194 break;
195 case GL_UNPACK_SWAP_BYTES:
196 state->storeUnpack.swapEndian = (param != 0);
197 break;
198 case GL_UNPACK_LSB_FIRST:
199 state->storeUnpack.lsbFirst = (param != 0);
200 break;
201
202 /* Group all of the pixel store modes that need to be sent to the
203 * server here. Care must be used to only send modes to the server that
204 * won't affect the size of the data sent to or received from the
205 * server. GL_PACK_INVERT_MESA is safe in this respect, but other,
206 * future modes may not be.
207 */
208 case GL_PACK_INVERT_MESA:
209 send_PixelStore(gc, X_GLsop_PixelStoref, pname, &param);
210 break;
211
212 default:
213 __glXSetError(gc, GL_INVALID_ENUM);
214 break;
215 }
216 }
217
218 void
219 __indirect_glPixelStorei(GLenum pname, GLint param)
220 {
221 struct glx_context *gc = __glXGetCurrentContext();
222 __GLXattribute *state = gc->client_state_private;
223 Display *dpy = gc->currentDpy;
224
225 if (!dpy)
226 return;
227
228 switch (pname) {
229 case GL_PACK_ROW_LENGTH:
230 if (param < 0) {
231 __glXSetError(gc, GL_INVALID_VALUE);
232 return;
233 }
234 state->storePack.rowLength = param;
235 break;
236 case GL_PACK_IMAGE_HEIGHT:
237 if (param < 0) {
238 __glXSetError(gc, GL_INVALID_VALUE);
239 return;
240 }
241 state->storePack.imageHeight = param;
242 break;
243 case GL_PACK_SKIP_ROWS:
244 if (param < 0) {
245 __glXSetError(gc, GL_INVALID_VALUE);
246 return;
247 }
248 state->storePack.skipRows = param;
249 break;
250 case GL_PACK_SKIP_PIXELS:
251 if (param < 0) {
252 __glXSetError(gc, GL_INVALID_VALUE);
253 return;
254 }
255 state->storePack.skipPixels = param;
256 break;
257 case GL_PACK_SKIP_IMAGES:
258 if (param < 0) {
259 __glXSetError(gc, GL_INVALID_VALUE);
260 return;
261 }
262 state->storePack.skipImages = param;
263 break;
264 case GL_PACK_ALIGNMENT:
265 switch (param) {
266 case 1:
267 case 2:
268 case 4:
269 case 8:
270 state->storePack.alignment = param;
271 break;
272 default:
273 __glXSetError(gc, GL_INVALID_VALUE);
274 return;
275 }
276 break;
277 case GL_PACK_SWAP_BYTES:
278 state->storePack.swapEndian = (param != 0);
279 break;
280 case GL_PACK_LSB_FIRST:
281 state->storePack.lsbFirst = (param != 0);
282 break;
283
284 case GL_UNPACK_ROW_LENGTH:
285 if (param < 0) {
286 __glXSetError(gc, GL_INVALID_VALUE);
287 return;
288 }
289 state->storeUnpack.rowLength = param;
290 break;
291 case GL_UNPACK_IMAGE_HEIGHT:
292 if (param < 0) {
293 __glXSetError(gc, GL_INVALID_VALUE);
294 return;
295 }
296 state->storeUnpack.imageHeight = param;
297 break;
298 case GL_UNPACK_SKIP_ROWS:
299 if (param < 0) {
300 __glXSetError(gc, GL_INVALID_VALUE);
301 return;
302 }
303 state->storeUnpack.skipRows = param;
304 break;
305 case GL_UNPACK_SKIP_PIXELS:
306 if (param < 0) {
307 __glXSetError(gc, GL_INVALID_VALUE);
308 return;
309 }
310 state->storeUnpack.skipPixels = param;
311 break;
312 case GL_UNPACK_SKIP_IMAGES:
313 if (param < 0) {
314 __glXSetError(gc, GL_INVALID_VALUE);
315 return;
316 }
317 state->storeUnpack.skipImages = param;
318 break;
319 case GL_UNPACK_ALIGNMENT:
320 switch (param) {
321 case 1:
322 case 2:
323 case 4:
324 case 8:
325 state->storeUnpack.alignment = param;
326 break;
327 default:
328 __glXSetError(gc, GL_INVALID_VALUE);
329 return;
330 }
331 break;
332 case GL_UNPACK_SWAP_BYTES:
333 state->storeUnpack.swapEndian = (param != 0);
334 break;
335 case GL_UNPACK_LSB_FIRST:
336 state->storeUnpack.lsbFirst = (param != 0);
337 break;
338
339 /* Group all of the pixel store modes that need to be sent to the
340 * server here. Care must be used to only send modes to the server that
341 * won't affect the size of the data sent to or received from the
342 * server. GL_PACK_INVERT_MESA is safe in this respect, but other,
343 * future modes may not be.
344 */
345 case GL_PACK_INVERT_MESA:
346 send_PixelStore(gc, X_GLsop_PixelStorei, pname, &param);
347 break;
348
349 default:
350 __glXSetError(gc, GL_INVALID_ENUM);
351 break;
352 }
353 }