Fix up glx/x11 to work when built with -fvisibility=hidden.
[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
284 for ( i = 0 ; attrib_list[i * 2] != None ; i++ )
285 /* empty */ ;
286
287 LockDisplay(dpy);
288 GetReqExtra( GLXCreateWindow, 20 + (8 * i), req );
289 data = (CARD32 *) (req + 1);
290
291 req->reqType = __glXSetupForCommand(dpy);
292 req->glxCode = glxCode;
293 req->screen = (CARD32) fbconfig->screen;
294 req->fbconfig = fbconfig->fbconfigID;
295 req->window = (GLXPbuffer) drawable;
296 req->numAttribs = (CARD32) i;
297
298 UnlockDisplay(dpy);
299 SyncHandle();
300
301 return drawable;
302 }
303
304
305 /**
306 * Destroy a non-pbuffer GLX drawable.
307 *
308 * \todo
309 * This function needs to be modified to work with direct-rendering drivers.
310 */
311 static void
312 DestroyDrawable( Display * dpy, GLXDrawable drawable, CARD32 glxCode )
313 {
314 xGLXDestroyPbufferReq * req;
315
316 if ( (dpy == NULL) || (drawable == 0) ) {
317 return;
318 }
319
320
321 LockDisplay(dpy);
322
323 GetReqExtra( GLXDestroyPbuffer, 4, req );
324 req->reqType = __glXSetupForCommand(dpy);
325 req->glxCode = glxCode;
326 req->pbuffer = (GLXPbuffer) drawable;
327
328 UnlockDisplay(dpy);
329 SyncHandle();
330
331 return;
332 }
333
334
335 /**
336 * Create a pbuffer.
337 *
338 * This function is used to implement \c glXCreatePbuffer and
339 * \c glXCreateGLXPbufferSGIX.
340 *
341 * \note
342 * This function dynamically determines whether to use the SGIX_pbuffer
343 * version of the protocol or the GLX 1.3 version of the protocol.
344 *
345 * \todo
346 * This function needs to be modified to work with direct-rendering drivers.
347 */
348 static GLXDrawable
349 CreatePbuffer( Display *dpy, const __GLcontextModes * fbconfig,
350 unsigned int width, unsigned int height,
351 const int *attrib_list, GLboolean size_in_attribs )
352 {
353 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
354 GLXDrawable id = 0;
355 CARD32 * data;
356 unsigned int i;
357
358
359 for ( i = 0 ; attrib_list[i * 2] != None ; i++ )
360 /* empty */ ;
361
362
363 LockDisplay(dpy);
364 id = XAllocID(dpy);
365
366 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
367 xGLXCreatePbufferReq * req;
368 unsigned int extra = (size_in_attribs) ? 0 : 2;
369
370 GetReqExtra( GLXCreatePbuffer, (8 * (i + extra)), req );
371 data = (CARD32 *) (req + 1);
372
373 req->reqType = __glXSetupForCommand(dpy);
374 req->glxCode = X_GLXCreatePbuffer;
375 req->screen = (CARD32) fbconfig->screen;
376 req->fbconfig = fbconfig->fbconfigID;
377 req->pbuffer = (GLXPbuffer) id;
378 req->numAttribs = (CARD32) (i + extra);
379
380 if ( ! size_in_attribs ) {
381 data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
382 data[(2 * i) + 1] = width;
383 data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
384 data[(2 * i) + 3] = height;
385 data += 4;
386 }
387 }
388 else {
389 xGLXVendorPrivateReq *vpreq;
390
391 GetReqExtra( GLXVendorPrivate, 20 + (8 * i), vpreq );
392 data = (CARD32 *) (vpreq + 1);
393
394 vpreq->reqType = __glXSetupForCommand(dpy);
395 vpreq->glxCode = X_GLXVendorPrivate;
396 vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
397
398 data[0] = (CARD32) fbconfig->screen;
399 data[1] = (CARD32) fbconfig->fbconfigID;
400 data[2] = (CARD32) id;
401 data[3] = (CARD32) width;
402 data[4] = (CARD32) height;
403 data += 5;
404 }
405
406 (void) memcpy( data, attrib_list, sizeof(CARD32) * 2 * i );
407
408 UnlockDisplay(dpy);
409 SyncHandle();
410
411 return id;
412 }
413
414
415 /**
416 * Create a new pbuffer.
417 */
418 PUBLIC GLXPbufferSGIX
419 GLX_PREFIX(glXCreateGLXPbufferSGIX)(Display *dpy, GLXFBConfigSGIX config,
420 unsigned int width, unsigned int height,
421 int *attrib_list)
422 {
423 return (GLXPbufferSGIX) CreatePbuffer( dpy, (__GLcontextModes *) config,
424 width, height,
425 attrib_list, GL_FALSE );
426 }
427
428
429 /**
430 * Create a new pbuffer.
431 */
432 PUBLIC GLXPbuffer
433 GLX_PREFIX(glXCreatePbuffer)(Display *dpy, GLXFBConfig config,
434 const int *attrib_list)
435 {
436 return (GLXPbuffer) CreatePbuffer( dpy, (__GLcontextModes *) config,
437 0, 0,
438 attrib_list, GL_TRUE );
439 }
440
441
442 /**
443 * Destroy an existing pbuffer.
444 */
445 PUBLIC void
446 GLX_PREFIX(glXDestroyPbuffer)(Display *dpy, GLXPbuffer pbuf)
447 {
448 DestroyPbuffer( dpy, pbuf );
449 }
450
451
452 /**
453 * Query an attribute of a drawable.
454 */
455 PUBLIC void
456 GLX_PREFIX(glXQueryDrawable)(Display *dpy, GLXDrawable drawable,
457 int attribute, unsigned int *value)
458 {
459 GetDrawableAttribute( dpy, drawable, attribute, value );
460 }
461
462
463 /**
464 * Query an attribute of a pbuffer.
465 */
466 PUBLIC int
467 GLX_PREFIX(glXQueryGLXPbufferSGIX)(Display *dpy, GLXPbufferSGIX drawable,
468 int attribute, unsigned int *value)
469 {
470 return GetDrawableAttribute( dpy, drawable, attribute, value );
471 }
472
473
474 /**
475 * Select the event mask for a drawable.
476 */
477 PUBLIC void
478 GLX_PREFIX(glXSelectEvent)(Display *dpy, GLXDrawable drawable,
479 unsigned long mask)
480 {
481 CARD32 attribs[2];
482
483 attribs[0] = (CARD32) GLX_EVENT_MASK;
484 attribs[1] = (CARD32) mask;
485
486 ChangeDrawableAttribute( dpy, drawable, attribs, 1 );
487 }
488
489
490 /**
491 * Get the selected event mask for a drawable.
492 */
493 PUBLIC void
494 GLX_PREFIX(glXGetSelectedEvent)(Display *dpy, GLXDrawable drawable,
495 unsigned long *mask)
496 {
497 unsigned int value;
498
499
500 /* The non-sense with value is required because on LP64 platforms
501 * sizeof(unsigned int) != sizeof(unsigned long). On little-endian
502 * we could just type-cast the pointer, but why?
503 */
504
505 GetDrawableAttribute( dpy, drawable, GLX_EVENT_MASK_SGIX, & value );
506 *mask = value;
507 }
508
509
510 PUBLIC GLXPixmap
511 GLX_PREFIX(glXCreatePixmap)( Display *dpy, GLXFBConfig config, Pixmap pixmap,
512 const int *attrib_list )
513 {
514 return CreateDrawable( dpy, (__GLcontextModes *) config,
515 (Drawable) pixmap, attrib_list,
516 X_GLXCreatePixmap );
517 }
518
519
520 PUBLIC GLXWindow
521 GLX_PREFIX(glXCreateWindow)( Display *dpy, GLXFBConfig config, Window win,
522 const int *attrib_list )
523 {
524 return CreateDrawable( dpy, (__GLcontextModes *) config,
525 (Drawable) win, attrib_list,
526 X_GLXCreateWindow );
527 }
528
529
530 PUBLIC void
531 GLX_PREFIX(glXDestroyPixmap)(Display *dpy, GLXPixmap pixmap)
532 {
533 DestroyDrawable( dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap );
534 }
535
536
537 PUBLIC void
538 GLX_PREFIX(glXDestroyWindow)(Display *dpy, GLXWindow win)
539 {
540 DestroyDrawable( dpy, (GLXDrawable) win, X_GLXDestroyWindow );
541 }
542
543
544 PUBLIC GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
545 (Display *dpy, GLXPbufferSGIX pbuf),
546 (dpy, pbuf),
547 glXDestroyPbuffer)
548
549 PUBLIC GLX_ALIAS_VOID(glXSelectEventSGIX,
550 (Display *dpy, GLXDrawable drawable, unsigned long mask),
551 (dpy, drawable, mask),
552 glXSelectEvent)
553
554 PUBLIC GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
555 (Display *dpy, GLXDrawable drawable, unsigned long *mask),
556 (dpy, drawable, mask),
557 glXGetSelectedEvent)