Hard-code the client-side maximum GL version. It turns out that there are
[mesa.git] / src / glx / x11 / glx_pbuffer.c
1 /*
2 * (C) Copyright IBM Corporation 2004
3 * 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 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file glx_pbuffer.c
27 * Implementation of pbuffer related functions.
28 *
29 * \author Ian Romanick <idr@us.ibm.com>
30 */
31
32 #include <inttypes.h>
33 #include "glxclient.h"
34 #include <extutil.h>
35 #include <Xext.h>
36 #include <assert.h>
37 #include <string.h>
38 #include "glapi.h"
39 #include "glxextensions.h"
40 #include "glcontextmodes.h"
41 #include "glheader.h"
42
43 #ifdef IN_DOXYGEN
44 #define GLX_PREFIX(x) x
45 #endif /* IN_DOXYGEN */
46
47 static void ChangeDrawableAttribute( Display * dpy, GLXDrawable drawable,
48 const CARD32 * attribs, size_t num_attribs );
49
50 static void DestroyPbuffer( Display * dpy, GLXDrawable drawable );
51
52 static GLXDrawable CreatePbuffer( Display *dpy,
53 const __GLcontextModes * fbconfig, unsigned int width, unsigned int height,
54 const int *attrib_list, GLboolean size_in_attribs );
55
56 static int GetDrawableAttribute( Display *dpy, GLXDrawable drawable,
57 int attribute, unsigned int *value );
58
59
60 /**
61 * Change a drawable's attribute.
62 *
63 * This function is used to implement \c glXSelectEvent and
64 * \c glXSelectEventSGIX.
65 *
66 * \note
67 * This function dynamically determines whether to use the SGIX_pbuffer
68 * version of the protocol or the GLX 1.3 version of the protocol.
69 *
70 * \todo
71 * This function needs to be modified to work with direct-rendering drivers.
72 */
73 static void
74 ChangeDrawableAttribute( Display * dpy, GLXDrawable drawable,
75 const CARD32 * attribs, size_t num_attribs )
76 {
77 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
78 CARD32 * output;
79
80
81 if ( (dpy == NULL) || (drawable == 0) ) {
82 return;
83 }
84
85
86 LockDisplay(dpy);
87
88 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
89 xGLXChangeDrawableAttributesReq *req;
90
91 GetReqExtra( GLXChangeDrawableAttributes, 8 + (8 * num_attribs), req );
92 output = (CARD32 *) (req + 1);
93
94 req->reqType = __glXSetupForCommand(dpy);
95 req->glxCode = X_GLXChangeDrawableAttributes;
96 req->drawable = drawable;
97 req->numAttribs = (CARD32) num_attribs;
98 }
99 else {
100 xGLXVendorPrivateWithReplyReq *vpreq;
101
102 GetReqExtra( GLXVendorPrivateWithReply, 4 + (8 * num_attribs), vpreq );
103 output = (CARD32 *) (vpreq + 1);
104
105 vpreq->reqType = __glXSetupForCommand(dpy);
106 vpreq->glxCode = X_GLXVendorPrivateWithReply;
107 vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX;
108
109 output[0] = (CARD32) drawable;
110 output++;
111 }
112
113 (void) memcpy( output, attribs, sizeof( CARD32 ) * 2 * num_attribs );
114
115 UnlockDisplay(dpy);
116 SyncHandle();
117
118 return;
119 }
120
121
122 /**
123 * Destroy a pbuffer.
124 *
125 * This function is used to implement \c glXDestroyPbuffer and
126 * \c glXDestroyGLXPbufferSGIX.
127 *
128 * \note
129 * This function dynamically determines whether to use the SGIX_pbuffer
130 * version of the protocol or the GLX 1.3 version of the protocol.
131 *
132 * \todo
133 * This function needs to be modified to work with direct-rendering drivers.
134 */
135 static void
136 DestroyPbuffer( Display * dpy, GLXDrawable drawable )
137 {
138 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
139
140 if ( (dpy == NULL) || (drawable == 0) ) {
141 return;
142 }
143
144
145 LockDisplay(dpy);
146
147 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
148 xGLXDestroyPbufferReq * req;
149
150 GetReqExtra( GLXDestroyPbuffer, 4, req );
151 req->reqType = __glXSetupForCommand(dpy);
152 req->glxCode = X_GLXDestroyPbuffer;
153 req->pbuffer = (GLXPbuffer) drawable;
154 }
155 else {
156 xGLXVendorPrivateWithReplyReq *vpreq;
157 CARD32 * data;
158
159 GetReqExtra( GLXVendorPrivateWithReply, 4, vpreq );
160 data = (CARD32 *) (vpreq + 1);
161
162 data[0] = (CARD32) drawable;
163
164 vpreq->reqType = __glXSetupForCommand(dpy);
165 vpreq->glxCode = X_GLXVendorPrivateWithReply;
166 vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX;
167 }
168
169 UnlockDisplay(dpy);
170 SyncHandle();
171
172 return;
173 }
174
175
176 /**
177 * Get a drawable's attribute.
178 *
179 * This function is used to implement \c glXGetSelectedEvent and
180 * \c glXGetSelectedEventSGIX.
181 *
182 * \note
183 * This function dynamically determines whether to use the SGIX_pbuffer
184 * version of the protocol or the GLX 1.3 version of the protocol.
185 *
186 * \todo
187 * The number of attributes returned is likely to be small, probably less than
188 * 10. Given that, this routine should try to use an array on the stack to
189 * capture the reply rather than always calling Xmalloc.
190 *
191 * \todo
192 * This function needs to be modified to work with direct-rendering drivers.
193 */
194 static int
195 GetDrawableAttribute( Display *dpy, GLXDrawable drawable,
196 int attribute, unsigned int *value )
197 {
198 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
199 xGLXGetDrawableAttributesReply reply;
200 CARD32 * data;
201 unsigned int length;
202 unsigned int i;
203 unsigned int num_attributes;
204 GLboolean use_glx_1_3 = ((priv->majorVersion > 1)
205 || (priv->minorVersion >= 3));
206
207
208 if ( (dpy == NULL) || (drawable == 0) ) {
209 return 0;
210 }
211
212
213 LockDisplay(dpy);
214
215 if ( use_glx_1_3 ) {
216 xGLXGetDrawableAttributesReq *req;
217
218 GetReqExtra( GLXGetDrawableAttributes, 4, req );
219 req->reqType = __glXSetupForCommand(dpy);
220 req->glxCode = X_GLXGetDrawableAttributes;
221 req->drawable = drawable;
222 }
223 else {
224 xGLXVendorPrivateWithReplyReq *vpreq;
225
226 GetReqExtra( GLXVendorPrivateWithReply, 4, vpreq );
227 data = (CARD32 *) (vpreq + 1);
228 data[0] = (CARD32) drawable;
229
230 vpreq->reqType = __glXSetupForCommand(dpy);
231 vpreq->glxCode = X_GLXVendorPrivateWithReply;
232 vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
233 }
234
235 _XReply(dpy, (xReply*) &reply, 0, False);
236
237 length = reply.length;
238 num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2;
239 data = (CARD32 *) Xmalloc( length * sizeof(CARD32) );
240 if ( data == NULL ) {
241 /* Throw data on the floor */
242 _XEatData(dpy, length);
243 } else {
244 _XRead(dpy, (char *)data, length * sizeof(CARD32) );
245 }
246
247 UnlockDisplay(dpy);
248 SyncHandle();
249
250
251 /* Search the set of returned attributes for the attribute requested by
252 * the caller.
253 */
254
255 for ( i = 0 ; i < num_attributes ; i++ ) {
256 if ( data[i*2] == attribute ) {
257 *value = data[ (i*2) + 1 ];
258 break;
259 }
260 }
261
262 Xfree( data );
263
264 return 0;
265 }
266
267
268 /**
269 * Create a non-pbuffer GLX drawable.
270 *
271 * \todo
272 * This function needs to be modified to work with direct-rendering drivers.
273 */
274 static GLXDrawable
275 CreateDrawable( Display *dpy, const __GLcontextModes * fbconfig,
276 Drawable drawable, const int *attrib_list,
277 CARD8 glxCode )
278 {
279 xGLXCreateWindowReq * req;
280 CARD32 * data;
281 unsigned int i;
282
283 i = 0;
284 if (attrib_list) {
285 while (attrib_list[i * 2] != None)
286 i++;
287 }
288
289 LockDisplay(dpy);
290 GetReqExtra( GLXCreateWindow, 8 * i, req );
291 data = (CARD32 *) (req + 1);
292
293 req->reqType = __glXSetupForCommand(dpy);
294 req->glxCode = glxCode;
295 req->screen = (CARD32) fbconfig->screen;
296 req->fbconfig = fbconfig->fbconfigID;
297 req->window = (GLXPbuffer) drawable;
298 req->glxwindow = (GLXWindow) XAllocID(dpy);
299 req->numAttribs = (CARD32) i;
300
301 memcpy( data, attrib_list, 8 * i );
302
303 UnlockDisplay(dpy);
304 SyncHandle();
305
306 return (GLXDrawable)req->glxwindow;
307 }
308
309
310 /**
311 * Destroy a non-pbuffer GLX drawable.
312 *
313 * \todo
314 * This function needs to be modified to work with direct-rendering drivers.
315 */
316 static void
317 DestroyDrawable( Display * dpy, GLXDrawable drawable, CARD32 glxCode )
318 {
319 xGLXDestroyPbufferReq * req;
320
321 if ( (dpy == NULL) || (drawable == 0) ) {
322 return;
323 }
324
325
326 LockDisplay(dpy);
327
328 GetReqExtra( GLXDestroyPbuffer, 4, req );
329 req->reqType = __glXSetupForCommand(dpy);
330 req->glxCode = glxCode;
331 req->pbuffer = (GLXPbuffer) drawable;
332
333 UnlockDisplay(dpy);
334 SyncHandle();
335
336 return;
337 }
338
339
340 /**
341 * Create a pbuffer.
342 *
343 * This function is used to implement \c glXCreatePbuffer and
344 * \c glXCreateGLXPbufferSGIX.
345 *
346 * \note
347 * This function dynamically determines whether to use the SGIX_pbuffer
348 * version of the protocol or the GLX 1.3 version of the protocol.
349 *
350 * \todo
351 * This function needs to be modified to work with direct-rendering drivers.
352 */
353 static GLXDrawable
354 CreatePbuffer( Display *dpy, const __GLcontextModes * fbconfig,
355 unsigned int width, unsigned int height,
356 const int *attrib_list, GLboolean size_in_attribs )
357 {
358 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
359 GLXDrawable id = 0;
360 CARD32 * data;
361 unsigned int i;
362
363 i = 0;
364 if (attrib_list) {
365 while (attrib_list[i * 2])
366 i++;
367 }
368
369 LockDisplay(dpy);
370 id = XAllocID(dpy);
371
372 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
373 xGLXCreatePbufferReq * req;
374 unsigned int extra = (size_in_attribs) ? 0 : 2;
375
376 GetReqExtra( GLXCreatePbuffer, (8 * (i + extra)), req );
377 data = (CARD32 *) (req + 1);
378
379 req->reqType = __glXSetupForCommand(dpy);
380 req->glxCode = X_GLXCreatePbuffer;
381 req->screen = (CARD32) fbconfig->screen;
382 req->fbconfig = fbconfig->fbconfigID;
383 req->pbuffer = (GLXPbuffer) id;
384 req->numAttribs = (CARD32) (i + extra);
385
386 if ( ! size_in_attribs ) {
387 data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
388 data[(2 * i) + 1] = width;
389 data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
390 data[(2 * i) + 3] = height;
391 data += 4;
392 }
393 }
394 else {
395 xGLXVendorPrivateReq *vpreq;
396
397 GetReqExtra( GLXVendorPrivate, 20 + (8 * i), vpreq );
398 data = (CARD32 *) (vpreq + 1);
399
400 vpreq->reqType = __glXSetupForCommand(dpy);
401 vpreq->glxCode = X_GLXVendorPrivate;
402 vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
403
404 data[0] = (CARD32) fbconfig->screen;
405 data[1] = (CARD32) fbconfig->fbconfigID;
406 data[2] = (CARD32) id;
407 data[3] = (CARD32) width;
408 data[4] = (CARD32) height;
409 data += 5;
410 }
411
412 (void) memcpy( data, attrib_list, sizeof(CARD32) * 2 * i );
413
414 UnlockDisplay(dpy);
415 SyncHandle();
416
417 return id;
418 }
419
420
421 /**
422 * Create a new pbuffer.
423 */
424 PUBLIC GLXPbufferSGIX
425 GLX_PREFIX(glXCreateGLXPbufferSGIX)(Display *dpy, GLXFBConfigSGIX config,
426 unsigned int width, unsigned int height,
427 int *attrib_list)
428 {
429 return (GLXPbufferSGIX) CreatePbuffer( dpy, (__GLcontextModes *) config,
430 width, height,
431 attrib_list, GL_FALSE );
432 }
433
434
435 /**
436 * Create a new pbuffer.
437 */
438 PUBLIC GLXPbuffer
439 GLX_PREFIX(glXCreatePbuffer)(Display *dpy, GLXFBConfig config,
440 const int *attrib_list)
441 {
442 return (GLXPbuffer) CreatePbuffer( dpy, (__GLcontextModes *) config,
443 0, 0,
444 attrib_list, GL_TRUE );
445 }
446
447
448 /**
449 * Destroy an existing pbuffer.
450 */
451 PUBLIC void
452 GLX_PREFIX(glXDestroyPbuffer)(Display *dpy, GLXPbuffer pbuf)
453 {
454 DestroyPbuffer( dpy, pbuf );
455 }
456
457
458 /**
459 * Query an attribute of a drawable.
460 */
461 PUBLIC void
462 GLX_PREFIX(glXQueryDrawable)(Display *dpy, GLXDrawable drawable,
463 int attribute, unsigned int *value)
464 {
465 GetDrawableAttribute( dpy, drawable, attribute, value );
466 }
467
468
469 /**
470 * Query an attribute of a pbuffer.
471 */
472 PUBLIC int
473 GLX_PREFIX(glXQueryGLXPbufferSGIX)(Display *dpy, GLXPbufferSGIX drawable,
474 int attribute, unsigned int *value)
475 {
476 return GetDrawableAttribute( dpy, drawable, attribute, value );
477 }
478
479
480 /**
481 * Select the event mask for a drawable.
482 */
483 PUBLIC void
484 GLX_PREFIX(glXSelectEvent)(Display *dpy, GLXDrawable drawable,
485 unsigned long mask)
486 {
487 CARD32 attribs[2];
488
489 attribs[0] = (CARD32) GLX_EVENT_MASK;
490 attribs[1] = (CARD32) mask;
491
492 ChangeDrawableAttribute( dpy, drawable, attribs, 1 );
493 }
494
495
496 /**
497 * Get the selected event mask for a drawable.
498 */
499 PUBLIC void
500 GLX_PREFIX(glXGetSelectedEvent)(Display *dpy, GLXDrawable drawable,
501 unsigned long *mask)
502 {
503 unsigned int value;
504
505
506 /* The non-sense with value is required because on LP64 platforms
507 * sizeof(unsigned int) != sizeof(unsigned long). On little-endian
508 * we could just type-cast the pointer, but why?
509 */
510
511 GetDrawableAttribute( dpy, drawable, GLX_EVENT_MASK_SGIX, & value );
512 *mask = value;
513 }
514
515
516 PUBLIC GLXPixmap
517 GLX_PREFIX(glXCreatePixmap)( Display *dpy, GLXFBConfig config, Pixmap pixmap,
518 const int *attrib_list )
519 {
520 return CreateDrawable( dpy, (__GLcontextModes *) config,
521 (Drawable) pixmap, attrib_list,
522 X_GLXCreatePixmap );
523 }
524
525
526 PUBLIC GLXWindow
527 GLX_PREFIX(glXCreateWindow)( Display *dpy, GLXFBConfig config, Window win,
528 const int *attrib_list )
529 {
530 return CreateDrawable( dpy, (__GLcontextModes *) config,
531 (Drawable) win, attrib_list,
532 X_GLXCreateWindow );
533 }
534
535
536 PUBLIC void
537 GLX_PREFIX(glXDestroyPixmap)(Display *dpy, GLXPixmap pixmap)
538 {
539 DestroyDrawable( dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap );
540 }
541
542
543 PUBLIC void
544 GLX_PREFIX(glXDestroyWindow)(Display *dpy, GLXWindow win)
545 {
546 DestroyDrawable( dpy, (GLXDrawable) win, X_GLXDestroyWindow );
547 }
548
549
550 PUBLIC GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
551 (Display *dpy, GLXPbufferSGIX pbuf),
552 (dpy, pbuf),
553 glXDestroyPbuffer)
554
555 PUBLIC GLX_ALIAS_VOID(glXSelectEventSGIX,
556 (Display *dpy, GLXDrawable drawable, unsigned long mask),
557 (dpy, drawable, mask),
558 glXSelectEvent)
559
560 PUBLIC GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
561 (Display *dpy, GLXDrawable drawable, unsigned long *mask),
562 (dpy, drawable, mask),
563 glXGetSelectedEvent)