blob: 59971585d1221a091a0544afa9935cb728101fe0 [file] [log] [blame]
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001/*
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"
Brian Paul82dfd4b2005-08-11 14:18:53 +000034#include <X11/extensions/extutil.h>
35#include <X11/extensions/Xext.h>
Adam Jacksoncb3610e2004-10-25 21:09:16 +000036#include <assert.h>
37#include <string.h>
38#include "glapi.h"
39#include "glxextensions.h"
40#include "glcontextmodes.h"
Adam Jackson489ccef2004-12-15 17:18:06 +000041#include "glheader.h"
Adam Jacksoncb3610e2004-10-25 21:09:16 +000042
Adam Jacksoncb3610e2004-10-25 21:09:16 +000043static void ChangeDrawableAttribute( Display * dpy, GLXDrawable drawable,
44 const CARD32 * attribs, size_t num_attribs );
45
46static void DestroyPbuffer( Display * dpy, GLXDrawable drawable );
47
48static GLXDrawable CreatePbuffer( Display *dpy,
49 const __GLcontextModes * fbconfig, unsigned int width, unsigned int height,
50 const int *attrib_list, GLboolean size_in_attribs );
51
52static int GetDrawableAttribute( Display *dpy, GLXDrawable drawable,
53 int attribute, unsigned int *value );
54
55
56/**
57 * Change a drawable's attribute.
58 *
59 * This function is used to implement \c glXSelectEvent and
60 * \c glXSelectEventSGIX.
61 *
62 * \note
63 * This function dynamically determines whether to use the SGIX_pbuffer
64 * version of the protocol or the GLX 1.3 version of the protocol.
65 *
66 * \todo
67 * This function needs to be modified to work with direct-rendering drivers.
68 */
69static void
70ChangeDrawableAttribute( Display * dpy, GLXDrawable drawable,
71 const CARD32 * attribs, size_t num_attribs )
72{
73 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
74 CARD32 * output;
75
76
77 if ( (dpy == NULL) || (drawable == 0) ) {
78 return;
79 }
80
81
82 LockDisplay(dpy);
83
84 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
85 xGLXChangeDrawableAttributesReq *req;
86
87 GetReqExtra( GLXChangeDrawableAttributes, 8 + (8 * num_attribs), req );
88 output = (CARD32 *) (req + 1);
89
90 req->reqType = __glXSetupForCommand(dpy);
91 req->glxCode = X_GLXChangeDrawableAttributes;
92 req->drawable = drawable;
93 req->numAttribs = (CARD32) num_attribs;
94 }
95 else {
96 xGLXVendorPrivateWithReplyReq *vpreq;
97
98 GetReqExtra( GLXVendorPrivateWithReply, 4 + (8 * num_attribs), vpreq );
99 output = (CARD32 *) (vpreq + 1);
100
101 vpreq->reqType = __glXSetupForCommand(dpy);
102 vpreq->glxCode = X_GLXVendorPrivateWithReply;
103 vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX;
104
105 output[0] = (CARD32) drawable;
106 output++;
107 }
108
109 (void) memcpy( output, attribs, sizeof( CARD32 ) * 2 * num_attribs );
110
111 UnlockDisplay(dpy);
112 SyncHandle();
113
114 return;
115}
116
117
118/**
119 * Destroy a pbuffer.
120 *
121 * This function is used to implement \c glXDestroyPbuffer and
122 * \c glXDestroyGLXPbufferSGIX.
123 *
124 * \note
125 * This function dynamically determines whether to use the SGIX_pbuffer
126 * version of the protocol or the GLX 1.3 version of the protocol.
127 *
128 * \todo
129 * This function needs to be modified to work with direct-rendering drivers.
130 */
131static void
132DestroyPbuffer( Display * dpy, GLXDrawable drawable )
133{
134 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
135
136 if ( (dpy == NULL) || (drawable == 0) ) {
137 return;
138 }
139
140
141 LockDisplay(dpy);
142
143 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
144 xGLXDestroyPbufferReq * req;
145
146 GetReqExtra( GLXDestroyPbuffer, 4, req );
147 req->reqType = __glXSetupForCommand(dpy);
148 req->glxCode = X_GLXDestroyPbuffer;
149 req->pbuffer = (GLXPbuffer) drawable;
150 }
151 else {
152 xGLXVendorPrivateWithReplyReq *vpreq;
153 CARD32 * data;
154
155 GetReqExtra( GLXVendorPrivateWithReply, 4, vpreq );
156 data = (CARD32 *) (vpreq + 1);
157
158 data[0] = (CARD32) drawable;
159
160 vpreq->reqType = __glXSetupForCommand(dpy);
161 vpreq->glxCode = X_GLXVendorPrivateWithReply;
162 vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX;
163 }
164
165 UnlockDisplay(dpy);
166 SyncHandle();
167
168 return;
169}
170
171
172/**
173 * Get a drawable's attribute.
174 *
175 * This function is used to implement \c glXGetSelectedEvent and
176 * \c glXGetSelectedEventSGIX.
177 *
178 * \note
179 * This function dynamically determines whether to use the SGIX_pbuffer
180 * version of the protocol or the GLX 1.3 version of the protocol.
181 *
182 * \todo
183 * The number of attributes returned is likely to be small, probably less than
184 * 10. Given that, this routine should try to use an array on the stack to
185 * capture the reply rather than always calling Xmalloc.
186 *
187 * \todo
188 * This function needs to be modified to work with direct-rendering drivers.
189 */
190static int
191GetDrawableAttribute( Display *dpy, GLXDrawable drawable,
192 int attribute, unsigned int *value )
193{
Adam Jacksond25ad502006-04-07 00:05:50 +0000194 __GLXdisplayPrivate *priv;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000195 xGLXGetDrawableAttributesReply reply;
196 CARD32 * data;
197 unsigned int length;
198 unsigned int i;
199 unsigned int num_attributes;
Adam Jacksond25ad502006-04-07 00:05:50 +0000200
201 if ( (dpy == NULL) || (drawable == 0) ) {
202 return 0;
203 }
204
205 priv = __glXInitialize(dpy);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000206 GLboolean use_glx_1_3 = ((priv->majorVersion > 1)
207 || (priv->minorVersion >= 3));
208
Brian Paul42725d62006-02-07 00:39:56 +0000209 *value = 0;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000210
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000211
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
Brian Paul42725d62006-02-07 00:39:56 +0000237 if (reply.type == X_Error)
238 {
239 UnlockDisplay(dpy);
240 SyncHandle();
241 return 0;
242 }
243
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000244 length = reply.length;
Brian Paul42725d62006-02-07 00:39:56 +0000245 if (length)
246 {
247 num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2;
248 data = (CARD32 *) Xmalloc( length * sizeof(CARD32) );
249 if ( data == NULL ) {
250 /* Throw data on the floor */
251 _XEatData(dpy, length);
252 } else {
253 _XRead(dpy, (char *)data, length * sizeof(CARD32) );
254
255 /* Search the set of returned attributes for the attribute requested by
256 * the caller.
257 */
258 for ( i = 0 ; i < num_attributes ; i++ ) {
259 if ( data[i*2] == attribute ) {
260 *value = data[ (i*2) + 1 ];
261 break;
262 }
263 }
264
265 Xfree( data );
266 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000267 }
268
269 UnlockDisplay(dpy);
270 SyncHandle();
271
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000272 return 0;
273}
274
275
276/**
277 * Create a non-pbuffer GLX drawable.
278 *
279 * \todo
280 * This function needs to be modified to work with direct-rendering drivers.
281 */
282static GLXDrawable
283CreateDrawable( Display *dpy, const __GLcontextModes * fbconfig,
284 Drawable drawable, const int *attrib_list,
285 CARD8 glxCode )
286{
287 xGLXCreateWindowReq * req;
288 CARD32 * data;
Ian Romanickb47731f2005-03-04 17:53:24 +0000289 unsigned int i;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000290
Ian Romanickb47731f2005-03-04 17:53:24 +0000291 i = 0;
292 if (attrib_list) {
293 while (attrib_list[i * 2] != None)
294 i++;
295 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000296
297 LockDisplay(dpy);
Ian Romanickb47731f2005-03-04 17:53:24 +0000298 GetReqExtra( GLXCreateWindow, 8 * i, req );
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000299 data = (CARD32 *) (req + 1);
300
301 req->reqType = __glXSetupForCommand(dpy);
302 req->glxCode = glxCode;
303 req->screen = (CARD32) fbconfig->screen;
304 req->fbconfig = fbconfig->fbconfigID;
305 req->window = (GLXPbuffer) drawable;
Ian Romanickb47731f2005-03-04 17:53:24 +0000306 req->glxwindow = (GLXWindow) XAllocID(dpy);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000307 req->numAttribs = (CARD32) i;
308
Ian Romanickb47731f2005-03-04 17:53:24 +0000309 memcpy( data, attrib_list, 8 * i );
310
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000311 UnlockDisplay(dpy);
312 SyncHandle();
313
Ian Romanickb47731f2005-03-04 17:53:24 +0000314 return (GLXDrawable)req->glxwindow;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000315}
316
317
318/**
319 * Destroy a non-pbuffer GLX drawable.
320 *
321 * \todo
322 * This function needs to be modified to work with direct-rendering drivers.
323 */
324static void
325DestroyDrawable( Display * dpy, GLXDrawable drawable, CARD32 glxCode )
326{
327 xGLXDestroyPbufferReq * req;
328
329 if ( (dpy == NULL) || (drawable == 0) ) {
330 return;
331 }
332
333
334 LockDisplay(dpy);
335
336 GetReqExtra( GLXDestroyPbuffer, 4, req );
337 req->reqType = __glXSetupForCommand(dpy);
338 req->glxCode = glxCode;
339 req->pbuffer = (GLXPbuffer) drawable;
340
341 UnlockDisplay(dpy);
342 SyncHandle();
343
344 return;
345}
346
347
348/**
349 * Create a pbuffer.
350 *
351 * This function is used to implement \c glXCreatePbuffer and
352 * \c glXCreateGLXPbufferSGIX.
353 *
354 * \note
355 * This function dynamically determines whether to use the SGIX_pbuffer
356 * version of the protocol or the GLX 1.3 version of the protocol.
357 *
358 * \todo
359 * This function needs to be modified to work with direct-rendering drivers.
360 */
361static GLXDrawable
362CreatePbuffer( Display *dpy, const __GLcontextModes * fbconfig,
363 unsigned int width, unsigned int height,
364 const int *attrib_list, GLboolean size_in_attribs )
365{
366 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
367 GLXDrawable id = 0;
368 CARD32 * data;
369 unsigned int i;
370
Ian Romanickb47731f2005-03-04 17:53:24 +0000371 i = 0;
372 if (attrib_list) {
373 while (attrib_list[i * 2])
374 i++;
375 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000376
377 LockDisplay(dpy);
378 id = XAllocID(dpy);
379
380 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
381 xGLXCreatePbufferReq * req;
382 unsigned int extra = (size_in_attribs) ? 0 : 2;
383
384 GetReqExtra( GLXCreatePbuffer, (8 * (i + extra)), req );
385 data = (CARD32 *) (req + 1);
386
387 req->reqType = __glXSetupForCommand(dpy);
388 req->glxCode = X_GLXCreatePbuffer;
389 req->screen = (CARD32) fbconfig->screen;
390 req->fbconfig = fbconfig->fbconfigID;
391 req->pbuffer = (GLXPbuffer) id;
392 req->numAttribs = (CARD32) (i + extra);
393
394 if ( ! size_in_attribs ) {
395 data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
396 data[(2 * i) + 1] = width;
397 data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
398 data[(2 * i) + 3] = height;
399 data += 4;
400 }
401 }
402 else {
403 xGLXVendorPrivateReq *vpreq;
404
405 GetReqExtra( GLXVendorPrivate, 20 + (8 * i), vpreq );
406 data = (CARD32 *) (vpreq + 1);
407
408 vpreq->reqType = __glXSetupForCommand(dpy);
409 vpreq->glxCode = X_GLXVendorPrivate;
410 vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
411
412 data[0] = (CARD32) fbconfig->screen;
413 data[1] = (CARD32) fbconfig->fbconfigID;
414 data[2] = (CARD32) id;
415 data[3] = (CARD32) width;
416 data[4] = (CARD32) height;
417 data += 5;
418 }
419
420 (void) memcpy( data, attrib_list, sizeof(CARD32) * 2 * i );
421
422 UnlockDisplay(dpy);
423 SyncHandle();
424
425 return id;
426}
427
428
429/**
430 * Create a new pbuffer.
431 */
Adam Jackson489ccef2004-12-15 17:18:06 +0000432PUBLIC GLXPbufferSGIX
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000433glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
434 unsigned int width, unsigned int height,
435 int *attrib_list)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000436{
437 return (GLXPbufferSGIX) CreatePbuffer( dpy, (__GLcontextModes *) config,
438 width, height,
439 attrib_list, GL_FALSE );
440}
441
442
443/**
444 * Create a new pbuffer.
445 */
Adam Jackson489ccef2004-12-15 17:18:06 +0000446PUBLIC GLXPbuffer
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000447glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attrib_list)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000448{
449 return (GLXPbuffer) CreatePbuffer( dpy, (__GLcontextModes *) config,
450 0, 0,
451 attrib_list, GL_TRUE );
452}
453
454
455/**
456 * Destroy an existing pbuffer.
457 */
Adam Jackson489ccef2004-12-15 17:18:06 +0000458PUBLIC void
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000459glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000460{
461 DestroyPbuffer( dpy, pbuf );
462}
463
464
465/**
466 * Query an attribute of a drawable.
467 */
Adam Jackson489ccef2004-12-15 17:18:06 +0000468PUBLIC void
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000469glXQueryDrawable(Display *dpy, GLXDrawable drawable,
470 int attribute, unsigned int *value)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000471{
472 GetDrawableAttribute( dpy, drawable, attribute, value );
473}
474
475
476/**
477 * Query an attribute of a pbuffer.
478 */
Adam Jackson489ccef2004-12-15 17:18:06 +0000479PUBLIC int
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000480glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX drawable,
481 int attribute, unsigned int *value)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000482{
483 return GetDrawableAttribute( dpy, drawable, attribute, value );
484}
485
486
487/**
488 * Select the event mask for a drawable.
489 */
Adam Jackson489ccef2004-12-15 17:18:06 +0000490PUBLIC void
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000491glXSelectEvent(Display *dpy, GLXDrawable drawable, unsigned long mask)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000492{
493 CARD32 attribs[2];
494
495 attribs[0] = (CARD32) GLX_EVENT_MASK;
496 attribs[1] = (CARD32) mask;
497
498 ChangeDrawableAttribute( dpy, drawable, attribs, 1 );
499}
500
501
502/**
503 * Get the selected event mask for a drawable.
504 */
Adam Jackson489ccef2004-12-15 17:18:06 +0000505PUBLIC void
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000506glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000507{
508 unsigned int value;
509
510
511 /* The non-sense with value is required because on LP64 platforms
512 * sizeof(unsigned int) != sizeof(unsigned long). On little-endian
513 * we could just type-cast the pointer, but why?
514 */
515
516 GetDrawableAttribute( dpy, drawable, GLX_EVENT_MASK_SGIX, & value );
517 *mask = value;
518}
519
520
Adam Jackson489ccef2004-12-15 17:18:06 +0000521PUBLIC GLXPixmap
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000522glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
523 const int *attrib_list )
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000524{
525 return CreateDrawable( dpy, (__GLcontextModes *) config,
526 (Drawable) pixmap, attrib_list,
527 X_GLXCreatePixmap );
528}
529
530
Adam Jackson489ccef2004-12-15 17:18:06 +0000531PUBLIC GLXWindow
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000532glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
533 const int *attrib_list )
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000534{
535 return CreateDrawable( dpy, (__GLcontextModes *) config,
536 (Drawable) win, attrib_list,
537 X_GLXCreateWindow );
538}
539
540
Adam Jackson489ccef2004-12-15 17:18:06 +0000541PUBLIC void
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000542glXDestroyPixmap(Display *dpy, GLXPixmap pixmap)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000543{
544 DestroyDrawable( dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap );
545}
546
547
Adam Jackson489ccef2004-12-15 17:18:06 +0000548PUBLIC void
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000549glXDestroyWindow(Display *dpy, GLXWindow win)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000550{
551 DestroyDrawable( dpy, (GLXDrawable) win, X_GLXDestroyWindow );
552}
553
554
Adam Jackson489ccef2004-12-15 17:18:06 +0000555PUBLIC GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000556 (Display *dpy, GLXPbufferSGIX pbuf),
557 (dpy, pbuf),
558 glXDestroyPbuffer)
559
Adam Jackson489ccef2004-12-15 17:18:06 +0000560PUBLIC GLX_ALIAS_VOID(glXSelectEventSGIX,
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000561 (Display *dpy, GLXDrawable drawable, unsigned long mask),
562 (dpy, drawable, mask),
563 glXSelectEvent)
564
Adam Jackson489ccef2004-12-15 17:18:06 +0000565PUBLIC GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000566 (Display *dpy, GLXDrawable drawable, unsigned long *mask),
567 (dpy, drawable, mask),
568 glXGetSelectedEvent)