blob: 83c550559c0c596e0cab9c682f108cc269489284 [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{
194 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
195 xGLXGetDrawableAttributesReply reply;
196 CARD32 * data;
197 unsigned int length;
198 unsigned int i;
199 unsigned int num_attributes;
200 GLboolean use_glx_1_3 = ((priv->majorVersion > 1)
201 || (priv->minorVersion >= 3));
202
203
204 if ( (dpy == NULL) || (drawable == 0) ) {
205 return 0;
206 }
207
208
209 LockDisplay(dpy);
210
211 if ( use_glx_1_3 ) {
212 xGLXGetDrawableAttributesReq *req;
213
214 GetReqExtra( GLXGetDrawableAttributes, 4, req );
215 req->reqType = __glXSetupForCommand(dpy);
216 req->glxCode = X_GLXGetDrawableAttributes;
217 req->drawable = drawable;
218 }
219 else {
220 xGLXVendorPrivateWithReplyReq *vpreq;
221
222 GetReqExtra( GLXVendorPrivateWithReply, 4, vpreq );
223 data = (CARD32 *) (vpreq + 1);
224 data[0] = (CARD32) drawable;
225
226 vpreq->reqType = __glXSetupForCommand(dpy);
227 vpreq->glxCode = X_GLXVendorPrivateWithReply;
228 vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
229 }
230
231 _XReply(dpy, (xReply*) &reply, 0, False);
232
233 length = reply.length;
234 num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2;
235 data = (CARD32 *) Xmalloc( length * sizeof(CARD32) );
236 if ( data == NULL ) {
237 /* Throw data on the floor */
238 _XEatData(dpy, length);
239 } else {
240 _XRead(dpy, (char *)data, length * sizeof(CARD32) );
241 }
242
243 UnlockDisplay(dpy);
244 SyncHandle();
245
246
247 /* Search the set of returned attributes for the attribute requested by
248 * the caller.
249 */
250
251 for ( i = 0 ; i < num_attributes ; i++ ) {
252 if ( data[i*2] == attribute ) {
253 *value = data[ (i*2) + 1 ];
254 break;
255 }
256 }
257
258 Xfree( data );
259
260 return 0;
261}
262
263
264/**
265 * Create a non-pbuffer GLX drawable.
266 *
267 * \todo
268 * This function needs to be modified to work with direct-rendering drivers.
269 */
270static GLXDrawable
271CreateDrawable( Display *dpy, const __GLcontextModes * fbconfig,
272 Drawable drawable, const int *attrib_list,
273 CARD8 glxCode )
274{
275 xGLXCreateWindowReq * req;
276 CARD32 * data;
Ian Romanickb47731f2005-03-04 17:53:24 +0000277 unsigned int i;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000278
Ian Romanickb47731f2005-03-04 17:53:24 +0000279 i = 0;
280 if (attrib_list) {
281 while (attrib_list[i * 2] != None)
282 i++;
283 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000284
285 LockDisplay(dpy);
Ian Romanickb47731f2005-03-04 17:53:24 +0000286 GetReqExtra( GLXCreateWindow, 8 * i, req );
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000287 data = (CARD32 *) (req + 1);
288
289 req->reqType = __glXSetupForCommand(dpy);
290 req->glxCode = glxCode;
291 req->screen = (CARD32) fbconfig->screen;
292 req->fbconfig = fbconfig->fbconfigID;
293 req->window = (GLXPbuffer) drawable;
Ian Romanickb47731f2005-03-04 17:53:24 +0000294 req->glxwindow = (GLXWindow) XAllocID(dpy);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000295 req->numAttribs = (CARD32) i;
296
Ian Romanickb47731f2005-03-04 17:53:24 +0000297 memcpy( data, attrib_list, 8 * i );
298
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000299 UnlockDisplay(dpy);
300 SyncHandle();
301
Ian Romanickb47731f2005-03-04 17:53:24 +0000302 return (GLXDrawable)req->glxwindow;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000303}
304
305
306/**
307 * Destroy a non-pbuffer GLX drawable.
308 *
309 * \todo
310 * This function needs to be modified to work with direct-rendering drivers.
311 */
312static void
313DestroyDrawable( Display * dpy, GLXDrawable drawable, CARD32 glxCode )
314{
315 xGLXDestroyPbufferReq * req;
316
317 if ( (dpy == NULL) || (drawable == 0) ) {
318 return;
319 }
320
321
322 LockDisplay(dpy);
323
324 GetReqExtra( GLXDestroyPbuffer, 4, req );
325 req->reqType = __glXSetupForCommand(dpy);
326 req->glxCode = glxCode;
327 req->pbuffer = (GLXPbuffer) drawable;
328
329 UnlockDisplay(dpy);
330 SyncHandle();
331
332 return;
333}
334
335
336/**
337 * Create a pbuffer.
338 *
339 * This function is used to implement \c glXCreatePbuffer and
340 * \c glXCreateGLXPbufferSGIX.
341 *
342 * \note
343 * This function dynamically determines whether to use the SGIX_pbuffer
344 * version of the protocol or the GLX 1.3 version of the protocol.
345 *
346 * \todo
347 * This function needs to be modified to work with direct-rendering drivers.
348 */
349static GLXDrawable
350CreatePbuffer( Display *dpy, const __GLcontextModes * fbconfig,
351 unsigned int width, unsigned int height,
352 const int *attrib_list, GLboolean size_in_attribs )
353{
354 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
355 GLXDrawable id = 0;
356 CARD32 * data;
357 unsigned int i;
358
Ian Romanickb47731f2005-03-04 17:53:24 +0000359 i = 0;
360 if (attrib_list) {
361 while (attrib_list[i * 2])
362 i++;
363 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000364
365 LockDisplay(dpy);
366 id = XAllocID(dpy);
367
368 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
369 xGLXCreatePbufferReq * req;
370 unsigned int extra = (size_in_attribs) ? 0 : 2;
371
372 GetReqExtra( GLXCreatePbuffer, (8 * (i + extra)), req );
373 data = (CARD32 *) (req + 1);
374
375 req->reqType = __glXSetupForCommand(dpy);
376 req->glxCode = X_GLXCreatePbuffer;
377 req->screen = (CARD32) fbconfig->screen;
378 req->fbconfig = fbconfig->fbconfigID;
379 req->pbuffer = (GLXPbuffer) id;
380 req->numAttribs = (CARD32) (i + extra);
381
382 if ( ! size_in_attribs ) {
383 data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
384 data[(2 * i) + 1] = width;
385 data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
386 data[(2 * i) + 3] = height;
387 data += 4;
388 }
389 }
390 else {
391 xGLXVendorPrivateReq *vpreq;
392
393 GetReqExtra( GLXVendorPrivate, 20 + (8 * i), vpreq );
394 data = (CARD32 *) (vpreq + 1);
395
396 vpreq->reqType = __glXSetupForCommand(dpy);
397 vpreq->glxCode = X_GLXVendorPrivate;
398 vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
399
400 data[0] = (CARD32) fbconfig->screen;
401 data[1] = (CARD32) fbconfig->fbconfigID;
402 data[2] = (CARD32) id;
403 data[3] = (CARD32) width;
404 data[4] = (CARD32) height;
405 data += 5;
406 }
407
408 (void) memcpy( data, attrib_list, sizeof(CARD32) * 2 * i );
409
410 UnlockDisplay(dpy);
411 SyncHandle();
412
413 return id;
414}
415
416
417/**
418 * Create a new pbuffer.
419 */
Adam Jackson489ccef2004-12-15 17:18:06 +0000420PUBLIC GLXPbufferSGIX
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000421glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
422 unsigned int width, unsigned int height,
423 int *attrib_list)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000424{
425 return (GLXPbufferSGIX) CreatePbuffer( dpy, (__GLcontextModes *) config,
426 width, height,
427 attrib_list, GL_FALSE );
428}
429
430
431/**
432 * Create a new pbuffer.
433 */
Adam Jackson489ccef2004-12-15 17:18:06 +0000434PUBLIC GLXPbuffer
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000435glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attrib_list)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000436{
437 return (GLXPbuffer) CreatePbuffer( dpy, (__GLcontextModes *) config,
438 0, 0,
439 attrib_list, GL_TRUE );
440}
441
442
443/**
444 * Destroy an existing pbuffer.
445 */
Adam Jackson489ccef2004-12-15 17:18:06 +0000446PUBLIC void
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000447glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000448{
449 DestroyPbuffer( dpy, pbuf );
450}
451
452
453/**
454 * Query an attribute of a drawable.
455 */
Adam Jackson489ccef2004-12-15 17:18:06 +0000456PUBLIC void
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000457glXQueryDrawable(Display *dpy, GLXDrawable drawable,
458 int attribute, unsigned int *value)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000459{
460 GetDrawableAttribute( dpy, drawable, attribute, value );
461}
462
463
464/**
465 * Query an attribute of a pbuffer.
466 */
Adam Jackson489ccef2004-12-15 17:18:06 +0000467PUBLIC int
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000468glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX drawable,
469 int attribute, unsigned int *value)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000470{
471 return GetDrawableAttribute( dpy, drawable, attribute, value );
472}
473
474
475/**
476 * Select the event mask for a drawable.
477 */
Adam Jackson489ccef2004-12-15 17:18:06 +0000478PUBLIC void
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000479glXSelectEvent(Display *dpy, GLXDrawable drawable, unsigned long mask)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000480{
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 */
Adam Jackson489ccef2004-12-15 17:18:06 +0000493PUBLIC void
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000494glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000495{
496 unsigned int value;
497
498
499 /* The non-sense with value is required because on LP64 platforms
500 * sizeof(unsigned int) != sizeof(unsigned long). On little-endian
501 * we could just type-cast the pointer, but why?
502 */
503
504 GetDrawableAttribute( dpy, drawable, GLX_EVENT_MASK_SGIX, & value );
505 *mask = value;
506}
507
508
Adam Jackson489ccef2004-12-15 17:18:06 +0000509PUBLIC GLXPixmap
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000510glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
511 const int *attrib_list )
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000512{
513 return CreateDrawable( dpy, (__GLcontextModes *) config,
514 (Drawable) pixmap, attrib_list,
515 X_GLXCreatePixmap );
516}
517
518
Adam Jackson489ccef2004-12-15 17:18:06 +0000519PUBLIC GLXWindow
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000520glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
521 const int *attrib_list )
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000522{
523 return CreateDrawable( dpy, (__GLcontextModes *) config,
524 (Drawable) win, attrib_list,
525 X_GLXCreateWindow );
526}
527
528
Adam Jackson489ccef2004-12-15 17:18:06 +0000529PUBLIC void
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000530glXDestroyPixmap(Display *dpy, GLXPixmap pixmap)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000531{
532 DestroyDrawable( dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap );
533}
534
535
Adam Jackson489ccef2004-12-15 17:18:06 +0000536PUBLIC void
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000537glXDestroyWindow(Display *dpy, GLXWindow win)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000538{
539 DestroyDrawable( dpy, (GLXDrawable) win, X_GLXDestroyWindow );
540}
541
542
Adam Jackson489ccef2004-12-15 17:18:06 +0000543PUBLIC GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000544 (Display *dpy, GLXPbufferSGIX pbuf),
545 (dpy, pbuf),
546 glXDestroyPbuffer)
547
Adam Jackson489ccef2004-12-15 17:18:06 +0000548PUBLIC GLX_ALIAS_VOID(glXSelectEventSGIX,
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000549 (Display *dpy, GLXDrawable drawable, unsigned long mask),
550 (dpy, drawable, mask),
551 glXSelectEvent)
552
Adam Jackson489ccef2004-12-15 17:18:06 +0000553PUBLIC GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000554 (Display *dpy, GLXDrawable drawable, unsigned long *mask),
555 (dpy, drawable, mask),
556 glXGetSelectedEvent)