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 #ifdef HAVE_DIX_CONFIG_H
32 #include <dix-config.h>
33 #endif
34 
35 #include "glxserver.h"
36 #include "glxext.h"
37 #include "singlesize.h"
38 #include "unpack.h"
39 #include "indirect_size_get.h"
40 #include "indirect_dispatch.h"
41 
42 int
__glXDisp_ReadPixels(__GLXclientState * cl,GLbyte * pc)43 __glXDisp_ReadPixels(__GLXclientState * cl, GLbyte * pc)
44 {
45     GLsizei width, height;
46     GLenum format, type;
47     GLboolean swapBytes, lsbFirst;
48     GLint compsize;
49     __GLXcontext *cx;
50     ClientPtr client = cl->client;
51     int error;
52     char *answer, answerBuffer[200];
53     xGLXSingleReply reply = { 0, };
54 
55     REQUEST_FIXED_SIZE(xGLXSingleReq, 28);
56 
57     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
58     if (!cx) {
59         return error;
60     }
61 
62     pc += __GLX_SINGLE_HDR_SIZE;
63     width = *(GLsizei *) (pc + 8);
64     height = *(GLsizei *) (pc + 12);
65     format = *(GLenum *) (pc + 16);
66     type = *(GLenum *) (pc + 20);
67     swapBytes = *(GLboolean *) (pc + 24);
68     lsbFirst = *(GLboolean *) (pc + 25);
69     compsize = __glReadPixels_size(format, type, width, height);
70     if (compsize < 0)
71         return BadLength;
72 
73     glPixelStorei(GL_PACK_SWAP_BYTES, swapBytes);
74     glPixelStorei(GL_PACK_LSB_FIRST, lsbFirst);
75     __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1);
76     __glXClearErrorOccured();
77     glReadPixels(*(GLint *) (pc + 0), *(GLint *) (pc + 4),
78                  *(GLsizei *) (pc + 8), *(GLsizei *) (pc + 12),
79                  *(GLenum *) (pc + 16), *(GLenum *) (pc + 20), answer);
80 
81     if (__glXErrorOccured()) {
82         __GLX_BEGIN_REPLY(0);
83         __GLX_SEND_HEADER();
84     }
85     else {
86         __GLX_BEGIN_REPLY(compsize);
87         __GLX_SEND_HEADER();
88         __GLX_SEND_VOID_ARRAY(compsize);
89     }
90     return Success;
91 }
92 
93 int
__glXDisp_GetTexImage(__GLXclientState * cl,GLbyte * pc)94 __glXDisp_GetTexImage(__GLXclientState * cl, GLbyte * pc)
95 {
96     GLint level, compsize;
97     GLenum format, type, target;
98     GLboolean swapBytes;
99     __GLXcontext *cx;
100     ClientPtr client = cl->client;
101     int error;
102     char *answer, answerBuffer[200];
103     GLint width = 0, height = 0, depth = 1;
104     xGLXSingleReply reply = { 0, };
105 
106     REQUEST_FIXED_SIZE(xGLXSingleReq, 20);
107 
108     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
109     if (!cx) {
110         return error;
111     }
112 
113     pc += __GLX_SINGLE_HDR_SIZE;
114     level = *(GLint *) (pc + 4);
115     format = *(GLenum *) (pc + 8);
116     type = *(GLenum *) (pc + 12);
117     target = *(GLenum *) (pc + 0);
118     swapBytes = *(GLboolean *) (pc + 16);
119 
120     glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
121     glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
122     if (target == GL_TEXTURE_3D) {
123         glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth);
124     }
125     /*
126      * The three queries above might fail if we're in a state where queries
127      * are illegal, but then width, height, and depth would still be zero anyway.
128      */
129     compsize =
130         __glGetTexImage_size(target, level, format, type, width, height, depth);
131     if (compsize < 0)
132         return BadLength;
133 
134     glPixelStorei(GL_PACK_SWAP_BYTES, swapBytes);
135     __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1);
136     __glXClearErrorOccured();
137     glGetTexImage(*(GLenum *) (pc + 0), *(GLint *) (pc + 4),
138                   *(GLenum *) (pc + 8), *(GLenum *) (pc + 12), answer);
139 
140     if (__glXErrorOccured()) {
141         __GLX_BEGIN_REPLY(0);
142         __GLX_SEND_HEADER();
143     }
144     else {
145         __GLX_BEGIN_REPLY(compsize);
146         ((xGLXGetTexImageReply *) &reply)->width = width;
147         ((xGLXGetTexImageReply *) &reply)->height = height;
148         ((xGLXGetTexImageReply *) &reply)->depth = depth;
149         __GLX_SEND_HEADER();
150         __GLX_SEND_VOID_ARRAY(compsize);
151     }
152     return Success;
153 }
154 
155 int
__glXDisp_GetPolygonStipple(__GLXclientState * cl,GLbyte * pc)156 __glXDisp_GetPolygonStipple(__GLXclientState * cl, GLbyte * pc)
157 {
158     GLboolean lsbFirst;
159     __GLXcontext *cx;
160     ClientPtr client = cl->client;
161     int error;
162     GLubyte answerBuffer[200];
163     char *answer;
164     xGLXSingleReply reply = { 0, };
165 
166     REQUEST_FIXED_SIZE(xGLXSingleReq, 4);
167 
168     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
169     if (!cx) {
170         return error;
171     }
172 
173     pc += __GLX_SINGLE_HDR_SIZE;
174     lsbFirst = *(GLboolean *) (pc + 0);
175 
176     glPixelStorei(GL_PACK_LSB_FIRST, lsbFirst);
177     __GLX_GET_ANSWER_BUFFER(answer, cl, 128, 1);
178 
179     __glXClearErrorOccured();
180     glGetPolygonStipple((GLubyte *) answer);
181 
182     if (__glXErrorOccured()) {
183         __GLX_BEGIN_REPLY(0);
184         __GLX_SEND_HEADER();
185     }
186     else {
187         __GLX_BEGIN_REPLY(128);
188         __GLX_SEND_HEADER();
189         __GLX_SEND_BYTE_ARRAY(128);
190     }
191     return Success;
192 }
193 
194 static int
GetSeparableFilter(__GLXclientState * cl,GLbyte * pc,GLXContextTag tag)195 GetSeparableFilter(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag)
196 {
197     GLint compsize, compsize2;
198     GLenum format, type, target;
199     GLboolean swapBytes;
200     __GLXcontext *cx;
201     ClientPtr client = cl->client;
202     int error;
203     char *answer, answerBuffer[200];
204     GLint width = 0, height = 0;
205     xGLXSingleReply reply = { 0, };
206 
207     cx = __glXForceCurrent(cl, tag, &error);
208     if (!cx) {
209         return error;
210     }
211 
212     format = *(GLenum *) (pc + 4);
213     type = *(GLenum *) (pc + 8);
214     target = *(GLenum *) (pc + 0);
215     swapBytes = *(GLboolean *) (pc + 12);
216 
217     /* target must be SEPARABLE_2D, however I guess we can let the GL
218        barf on this one.... */
219 
220     glGetConvolutionParameteriv(target, GL_CONVOLUTION_WIDTH, &width);
221     glGetConvolutionParameteriv(target, GL_CONVOLUTION_HEIGHT, &height);
222     /*
223      * The two queries above might fail if we're in a state where queries
224      * are illegal, but then width and height would still be zero anyway.
225      */
226     compsize = __glGetTexImage_size(target, 1, format, type, width, 1, 1);
227     compsize2 = __glGetTexImage_size(target, 1, format, type, height, 1, 1);
228 
229     if ((compsize = safe_pad(compsize)) < 0)
230         return BadLength;
231     if ((compsize2 = safe_pad(compsize2)) < 0)
232         return BadLength;
233 
234     glPixelStorei(GL_PACK_SWAP_BYTES, swapBytes);
235     __GLX_GET_ANSWER_BUFFER(answer, cl, safe_add(compsize, compsize2), 1);
236     __glXClearErrorOccured();
237     glGetSeparableFilter(*(GLenum *) (pc + 0), *(GLenum *) (pc + 4),
238                          *(GLenum *) (pc + 8), answer, answer + compsize, NULL);
239 
240     if (__glXErrorOccured()) {
241         __GLX_BEGIN_REPLY(0);
242         __GLX_SEND_HEADER();
243     }
244     else {
245         __GLX_BEGIN_REPLY(compsize + compsize2);
246         ((xGLXGetSeparableFilterReply *) &reply)->width = width;
247         ((xGLXGetSeparableFilterReply *) &reply)->height = height;
248         __GLX_SEND_HEADER();
249         __GLX_SEND_VOID_ARRAY(compsize + compsize2);
250     }
251 
252     return Success;
253 }
254 
255 int
__glXDisp_GetSeparableFilter(__GLXclientState * cl,GLbyte * pc)256 __glXDisp_GetSeparableFilter(__GLXclientState * cl, GLbyte * pc)
257 {
258     const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc);
259     ClientPtr client = cl->client;
260     REQUEST_FIXED_SIZE(xGLXSingleReq, 16);
261     return GetSeparableFilter(cl, pc + __GLX_SINGLE_HDR_SIZE, tag);
262 }
263 
264 int
__glXDisp_GetSeparableFilterEXT(__GLXclientState * cl,GLbyte * pc)265 __glXDisp_GetSeparableFilterEXT(__GLXclientState * cl, GLbyte * pc)
266 {
267     const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc);
268     ClientPtr client = cl->client;
269     REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16);
270     return GetSeparableFilter(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag);
271 }
272 
273 static int
GetConvolutionFilter(__GLXclientState * cl,GLbyte * pc,GLXContextTag tag)274 GetConvolutionFilter(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag)
275 {
276     GLint compsize;
277     GLenum format, type, target;
278     GLboolean swapBytes;
279     __GLXcontext *cx;
280     ClientPtr client = cl->client;
281     int error;
282     char *answer, answerBuffer[200];
283     GLint width = 0, height = 0;
284     xGLXSingleReply reply = { 0, };
285 
286     cx = __glXForceCurrent(cl, tag, &error);
287     if (!cx) {
288         return error;
289     }
290 
291     format = *(GLenum *) (pc + 4);
292     type = *(GLenum *) (pc + 8);
293     target = *(GLenum *) (pc + 0);
294     swapBytes = *(GLboolean *) (pc + 12);
295 
296     glGetConvolutionParameteriv(target, GL_CONVOLUTION_WIDTH, &width);
297     if (target == GL_CONVOLUTION_1D) {
298         height = 1;
299     }
300     else {
301         glGetConvolutionParameteriv(target, GL_CONVOLUTION_HEIGHT, &height);
302     }
303     /*
304      * The two queries above might fail if we're in a state where queries
305      * are illegal, but then width and height would still be zero anyway.
306      */
307     compsize = __glGetTexImage_size(target, 1, format, type, width, height, 1);
308     if (compsize < 0)
309         return BadLength;
310 
311     glPixelStorei(GL_PACK_SWAP_BYTES, swapBytes);
312     __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1);
313     __glXClearErrorOccured();
314     glGetConvolutionFilter(*(GLenum *) (pc + 0), *(GLenum *) (pc + 4),
315                            *(GLenum *) (pc + 8), answer);
316 
317     if (__glXErrorOccured()) {
318         __GLX_BEGIN_REPLY(0);
319         __GLX_SEND_HEADER();
320     }
321     else {
322         __GLX_BEGIN_REPLY(compsize);
323         ((xGLXGetConvolutionFilterReply *) &reply)->width = width;
324         ((xGLXGetConvolutionFilterReply *) &reply)->height = height;
325         __GLX_SEND_HEADER();
326         __GLX_SEND_VOID_ARRAY(compsize);
327     }
328 
329     return Success;
330 }
331 
332 int
__glXDisp_GetConvolutionFilter(__GLXclientState * cl,GLbyte * pc)333 __glXDisp_GetConvolutionFilter(__GLXclientState * cl, GLbyte * pc)
334 {
335     const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc);
336     ClientPtr client = cl->client;
337     REQUEST_FIXED_SIZE(xGLXSingleReq, 16);
338     return GetConvolutionFilter(cl, pc + __GLX_SINGLE_HDR_SIZE, tag);
339 }
340 
341 int
__glXDisp_GetConvolutionFilterEXT(__GLXclientState * cl,GLbyte * pc)342 __glXDisp_GetConvolutionFilterEXT(__GLXclientState * cl, GLbyte * pc)
343 {
344     const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc);
345     ClientPtr client = cl->client;
346     REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16);
347     return GetConvolutionFilter(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag);
348 }
349 
350 static int
GetHistogram(__GLXclientState * cl,GLbyte * pc,GLXContextTag tag)351 GetHistogram(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag)
352 {
353     GLint compsize;
354     GLenum format, type, target;
355     GLboolean swapBytes, reset;
356     __GLXcontext *cx;
357     ClientPtr client = cl->client;
358     int error;
359     char *answer, answerBuffer[200];
360     GLint width = 0;
361     xGLXSingleReply reply = { 0, };
362 
363     cx = __glXForceCurrent(cl, tag, &error);
364     if (!cx) {
365         return error;
366     }
367 
368     format = *(GLenum *) (pc + 4);
369     type = *(GLenum *) (pc + 8);
370     target = *(GLenum *) (pc + 0);
371     swapBytes = *(GLboolean *) (pc + 12);
372     reset = *(GLboolean *) (pc + 13);
373 
374     glGetHistogramParameteriv(target, GL_HISTOGRAM_WIDTH, &width);
375     /*
376      * The one query above might fail if we're in a state where queries
377      * are illegal, but then width would still be zero anyway.
378      */
379     compsize = __glGetTexImage_size(target, 1, format, type, width, 1, 1);
380     if (compsize < 0)
381         return BadLength;
382 
383     glPixelStorei(GL_PACK_SWAP_BYTES, swapBytes);
384     __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1);
385     __glXClearErrorOccured();
386     glGetHistogram(target, reset, format, type, answer);
387 
388     if (__glXErrorOccured()) {
389         __GLX_BEGIN_REPLY(0);
390         __GLX_SEND_HEADER();
391     }
392     else {
393         __GLX_BEGIN_REPLY(compsize);
394         ((xGLXGetHistogramReply *) &reply)->width = width;
395         __GLX_SEND_HEADER();
396         __GLX_SEND_VOID_ARRAY(compsize);
397     }
398 
399     return Success;
400 }
401 
402 int
__glXDisp_GetHistogram(__GLXclientState * cl,GLbyte * pc)403 __glXDisp_GetHistogram(__GLXclientState * cl, GLbyte * pc)
404 {
405     const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc);
406     ClientPtr client = cl->client;
407     REQUEST_FIXED_SIZE(xGLXSingleReq, 16);
408     return GetHistogram(cl, pc + __GLX_SINGLE_HDR_SIZE, tag);
409 }
410 
411 int
__glXDisp_GetHistogramEXT(__GLXclientState * cl,GLbyte * pc)412 __glXDisp_GetHistogramEXT(__GLXclientState * cl, GLbyte * pc)
413 {
414     const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc);
415     ClientPtr client = cl->client;
416     REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16);
417     return GetHistogram(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag);
418 }
419 
420 static int
GetMinmax(__GLXclientState * cl,GLbyte * pc,GLXContextTag tag)421 GetMinmax(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag)
422 {
423     GLint compsize;
424     GLenum format, type, target;
425     GLboolean swapBytes, reset;
426     __GLXcontext *cx;
427     ClientPtr client = cl->client;
428     int error;
429     char *answer, answerBuffer[200];
430     xGLXSingleReply reply = { 0, };
431 
432     cx = __glXForceCurrent(cl, tag, &error);
433     if (!cx) {
434         return error;
435     }
436 
437     format = *(GLenum *) (pc + 4);
438     type = *(GLenum *) (pc + 8);
439     target = *(GLenum *) (pc + 0);
440     swapBytes = *(GLboolean *) (pc + 12);
441     reset = *(GLboolean *) (pc + 13);
442 
443     compsize = __glGetTexImage_size(target, 1, format, type, 2, 1, 1);
444     if (compsize < 0)
445         return BadLength;
446 
447     glPixelStorei(GL_PACK_SWAP_BYTES, swapBytes);
448     __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1);
449     __glXClearErrorOccured();
450     glGetMinmax(target, reset, format, type, answer);
451 
452     if (__glXErrorOccured()) {
453         __GLX_BEGIN_REPLY(0);
454         __GLX_SEND_HEADER();
455     }
456     else {
457         __GLX_BEGIN_REPLY(compsize);
458         __GLX_SEND_HEADER();
459         __GLX_SEND_VOID_ARRAY(compsize);
460     }
461 
462     return Success;
463 }
464 
465 int
__glXDisp_GetMinmax(__GLXclientState * cl,GLbyte * pc)466 __glXDisp_GetMinmax(__GLXclientState * cl, GLbyte * pc)
467 {
468     const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc);
469     ClientPtr client = cl->client;
470     REQUEST_FIXED_SIZE(xGLXSingleReq, 16);
471     return GetMinmax(cl, pc + __GLX_SINGLE_HDR_SIZE, tag);
472 }
473 
474 int
__glXDisp_GetMinmaxEXT(__GLXclientState * cl,GLbyte * pc)475 __glXDisp_GetMinmaxEXT(__GLXclientState * cl, GLbyte * pc)
476 {
477     const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc);
478     ClientPtr client = cl->client;
479     REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16);
480     return GetMinmax(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag);
481 }
482 
483 static int
GetColorTable(__GLXclientState * cl,GLbyte * pc,GLXContextTag tag)484 GetColorTable(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag)
485 {
486     GLint compsize;
487     GLenum format, type, target;
488     GLboolean swapBytes;
489     __GLXcontext *cx;
490     ClientPtr client = cl->client;
491     int error;
492     char *answer, answerBuffer[200];
493     GLint width = 0;
494     xGLXSingleReply reply = { 0, };
495 
496     cx = __glXForceCurrent(cl, tag, &error);
497     if (!cx) {
498         return error;
499     }
500 
501     target = *(GLenum *) (pc + 0);
502     format = *(GLenum *) (pc + 4);
503     type = *(GLenum *) (pc + 8);
504     swapBytes = *(GLboolean *) (pc + 12);
505 
506     glGetColorTableParameteriv(target, GL_COLOR_TABLE_WIDTH, &width);
507     /*
508      * The one query above might fail if we're in a state where queries
509      * are illegal, but then width would still be zero anyway.
510      */
511     compsize = __glGetTexImage_size(target, 1, format, type, width, 1, 1);
512     if (compsize < 0)
513         return BadLength;
514 
515     glPixelStorei(GL_PACK_SWAP_BYTES, swapBytes);
516     __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1);
517     __glXClearErrorOccured();
518     glGetColorTable(*(GLenum *) (pc + 0), *(GLenum *) (pc + 4),
519                     *(GLenum *) (pc + 8), answer);
520 
521     if (__glXErrorOccured()) {
522         __GLX_BEGIN_REPLY(0);
523         __GLX_SEND_HEADER();
524     }
525     else {
526         __GLX_BEGIN_REPLY(compsize);
527         ((xGLXGetColorTableReply *) &reply)->width = width;
528         __GLX_SEND_HEADER();
529         __GLX_SEND_VOID_ARRAY(compsize);
530     }
531 
532     return Success;
533 }
534 
535 int
__glXDisp_GetColorTable(__GLXclientState * cl,GLbyte * pc)536 __glXDisp_GetColorTable(__GLXclientState * cl, GLbyte * pc)
537 {
538     const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc);
539     ClientPtr client = cl->client;
540     REQUEST_FIXED_SIZE(xGLXSingleReq, 16);
541     return GetColorTable(cl, pc + __GLX_SINGLE_HDR_SIZE, tag);
542 }
543 
544 int
__glXDisp_GetColorTableSGI(__GLXclientState * cl,GLbyte * pc)545 __glXDisp_GetColorTableSGI(__GLXclientState * cl, GLbyte * pc)
546 {
547     const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc);
548     ClientPtr client = cl->client;
549     REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16);
550     return GetColorTable(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag);
551 }
552