1 /* -*- mode: c; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3; coding: utf-8-unix -*- */
3 * (C) Copyright IBM Corporation 2004
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * on the rights to use, copy, modify, merge, publish, distribute, sub
10 * license, and/or sell copies of the Software, and to permit persons to whom
11 * the Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
28 * Implementation of pbuffer related functions.
30 * \author Ian Romanick <idr@us.ibm.com>
34 #include "glxclient.h"
35 #include <X11/extensions/extutil.h>
36 #include <X11/extensions/Xext.h>
40 #include "glxextensions.h"
41 #include "glcontextmodes.h"
45 * Change a drawable's attribute.
47 * This function is used to implement \c glXSelectEvent and
48 * \c glXSelectEventSGIX.
51 * This function dynamically determines whether to use the SGIX_pbuffer
52 * version of the protocol or the GLX 1.3 version of the protocol.
55 * This function needs to be modified to work with direct-rendering drivers.
58 ChangeDrawableAttribute(Display
* dpy
, GLXDrawable drawable
,
59 const CARD32
* attribs
, size_t num_attribs
)
61 __GLXdisplayPrivate
*priv
= __glXInitialize(dpy
);
65 if ((dpy
== NULL
) || (drawable
== 0)) {
69 opcode
= __glXSetupForCommand(dpy
);
75 if ((priv
->majorVersion
> 1) || (priv
->minorVersion
>= 3)) {
76 xGLXChangeDrawableAttributesReq
*req
;
78 GetReqExtra(GLXChangeDrawableAttributes
, 8 + (8 * num_attribs
), req
);
79 output
= (CARD32
*) (req
+ 1);
81 req
->reqType
= opcode
;
82 req
->glxCode
= X_GLXChangeDrawableAttributes
;
83 req
->drawable
= drawable
;
84 req
->numAttribs
= (CARD32
) num_attribs
;
87 xGLXVendorPrivateWithReplyReq
*vpreq
;
89 GetReqExtra(GLXVendorPrivateWithReply
, 4 + (8 * num_attribs
), vpreq
);
90 output
= (CARD32
*) (vpreq
+ 1);
92 vpreq
->reqType
= opcode
;
93 vpreq
->glxCode
= X_GLXVendorPrivateWithReply
;
94 vpreq
->vendorCode
= X_GLXvop_ChangeDrawableAttributesSGIX
;
96 output
[0] = (CARD32
) drawable
;
100 (void) memcpy(output
, attribs
, sizeof(CARD32
) * 2 * num_attribs
);
112 * This function is used to implement \c glXDestroyPbuffer and
113 * \c glXDestroyGLXPbufferSGIX.
116 * This function dynamically determines whether to use the SGIX_pbuffer
117 * version of the protocol or the GLX 1.3 version of the protocol.
120 * This function needs to be modified to work with direct-rendering drivers.
123 DestroyPbuffer(Display
* dpy
, GLXDrawable drawable
)
125 __GLXdisplayPrivate
*priv
= __glXInitialize(dpy
);
128 if ((dpy
== NULL
) || (drawable
== 0)) {
132 opcode
= __glXSetupForCommand(dpy
);
138 if ((priv
->majorVersion
> 1) || (priv
->minorVersion
>= 3)) {
139 xGLXDestroyPbufferReq
*req
;
141 GetReq(GLXDestroyPbuffer
, req
);
142 req
->reqType
= opcode
;
143 req
->glxCode
= X_GLXDestroyPbuffer
;
144 req
->pbuffer
= (GLXPbuffer
) drawable
;
147 xGLXVendorPrivateWithReplyReq
*vpreq
;
150 GetReqExtra(GLXVendorPrivateWithReply
, 4, vpreq
);
151 data
= (CARD32
*) (vpreq
+ 1);
153 data
[0] = (CARD32
) drawable
;
155 vpreq
->reqType
= opcode
;
156 vpreq
->glxCode
= X_GLXVendorPrivateWithReply
;
157 vpreq
->vendorCode
= X_GLXvop_DestroyGLXPbufferSGIX
;
167 #ifdef GLX_DIRECT_RENDERING
168 extern __GLXDRIdrawable
*GetGLXDRIDrawable(Display
* dpy
,
169 GLXDrawable drawable
,
170 int *const scrn_num
);
173 determineTextureTarget(const int *attribs
, int numAttribs
)
178 for (i
= 0; i
< numAttribs
; i
++) {
179 if (attribs
[2 * i
] == GLX_TEXTURE_TARGET_EXT
) {
180 switch (attribs
[2 * i
+ 1]) {
181 case GLX_TEXTURE_2D_EXT
:
182 target
= GL_TEXTURE_2D
;
184 case GLX_TEXTURE_RECTANGLE_EXT
:
185 target
= GL_TEXTURE_RECTANGLE_ARB
;
196 * Get a drawable's attribute.
198 * This function is used to implement \c glXGetSelectedEvent and
199 * \c glXGetSelectedEventSGIX.
202 * This function dynamically determines whether to use the SGIX_pbuffer
203 * version of the protocol or the GLX 1.3 version of the protocol.
206 * The number of attributes returned is likely to be small, probably less than
207 * 10. Given that, this routine should try to use an array on the stack to
208 * capture the reply rather than always calling Xmalloc.
211 * This function needs to be modified to work with direct-rendering drivers.
214 GetDrawableAttribute(Display
* dpy
, GLXDrawable drawable
,
215 int attribute
, unsigned int *value
)
217 __GLXdisplayPrivate
*priv
;
218 xGLXGetDrawableAttributesReply reply
;
223 unsigned int num_attributes
;
225 if ((dpy
== NULL
) || (drawable
== 0)) {
229 priv
= __glXInitialize(dpy
);
230 GLboolean use_glx_1_3
= ((priv
->majorVersion
> 1)
231 || (priv
->minorVersion
>= 3));
236 opcode
= __glXSetupForCommand(dpy
);
243 xGLXGetDrawableAttributesReq
*req
;
245 GetReqExtra(GLXGetDrawableAttributes
, 4, req
);
246 req
->reqType
= opcode
;
247 req
->glxCode
= X_GLXGetDrawableAttributes
;
248 req
->drawable
= drawable
;
251 xGLXVendorPrivateWithReplyReq
*vpreq
;
253 GetReqExtra(GLXVendorPrivateWithReply
, 4, vpreq
);
254 data
= (CARD32
*) (vpreq
+ 1);
255 data
[0] = (CARD32
) drawable
;
257 vpreq
->reqType
= opcode
;
258 vpreq
->glxCode
= X_GLXVendorPrivateWithReply
;
259 vpreq
->vendorCode
= X_GLXvop_GetDrawableAttributesSGIX
;
262 _XReply(dpy
, (xReply
*) & reply
, 0, False
);
264 if (reply
.type
== X_Error
) {
270 length
= reply
.length
;
272 num_attributes
= (use_glx_1_3
) ? reply
.numAttribs
: length
/ 2;
273 data
= (CARD32
*) Xmalloc(length
* sizeof(CARD32
));
275 /* Throw data on the floor */
276 _XEatData(dpy
, length
);
279 _XRead(dpy
, (char *) data
, length
* sizeof(CARD32
));
281 /* Search the set of returned attributes for the attribute requested by
284 for (i
= 0; i
< num_attributes
; i
++) {
285 if (data
[i
* 2] == attribute
) {
286 *value
= data
[(i
* 2) + 1];
291 #ifdef GLX_DIRECT_RENDERING
293 __GLXDRIdrawable
*pdraw
= GetGLXDRIDrawable(dpy
, drawable
, NULL
);
295 if (pdraw
!= NULL
&& !pdraw
->textureTarget
)
296 pdraw
->textureTarget
=
297 determineTextureTarget((const int *) data
, num_attributes
);
312 * Create a non-pbuffer GLX drawable.
315 * This function needs to be modified to work with direct-rendering drivers.
318 CreateDrawable(Display
* dpy
, const __GLcontextModes
* fbconfig
,
319 Drawable drawable
, const int *attrib_list
, CARD8 glxCode
)
321 xGLXCreateWindowReq
*req
;
328 while (attrib_list
[i
* 2] != None
)
332 opcode
= __glXSetupForCommand(dpy
);
337 GetReqExtra(GLXCreateWindow
, 8 * i
, req
);
338 data
= (CARD32
*) (req
+ 1);
340 req
->reqType
= opcode
;
341 req
->glxCode
= glxCode
;
342 req
->screen
= (CARD32
) fbconfig
->screen
;
343 req
->fbconfig
= fbconfig
->fbconfigID
;
344 req
->window
= (CARD32
) drawable
;
345 req
->glxwindow
= (GLXWindow
) XAllocID(dpy
);
346 req
->numAttribs
= (CARD32
) i
;
348 memcpy(data
, attrib_list
, 8 * i
);
353 #ifdef GLX_DIRECT_RENDERING
355 /* FIXME: Maybe delay __DRIdrawable creation until the drawable
356 * is actually bound to a context... */
358 __GLXdisplayPrivate
*const priv
= __glXInitialize(dpy
);
359 __GLXDRIdrawable
*pdraw
;
360 __GLXscreenConfigs
*psc
;
362 psc
= &priv
->screenConfigs
[fbconfig
->screen
];
363 if (psc
->driScreen
== NULL
)
365 pdraw
= psc
->driScreen
->createDrawable(psc
, drawable
,
366 req
->glxwindow
, fbconfig
);
368 fprintf(stderr
, "failed to create drawable\n");
372 if (__glxHashInsert(psc
->drawHash
, req
->glxwindow
, pdraw
)) {
373 (*pdraw
->destroyDrawable
) (pdraw
);
374 return None
; /* FIXME: Check what we're supposed to do here... */
377 pdraw
->textureTarget
= determineTextureTarget(attrib_list
, i
);
381 return (GLXDrawable
) req
->glxwindow
;
386 * Destroy a non-pbuffer GLX drawable.
389 * This function needs to be modified to work with direct-rendering drivers.
392 DestroyDrawable(Display
* dpy
, GLXDrawable drawable
, CARD32 glxCode
)
394 xGLXDestroyPbufferReq
*req
;
397 if ((dpy
== NULL
) || (drawable
== 0)) {
402 opcode
= __glXSetupForCommand(dpy
);
408 GetReqExtra(GLXDestroyPbuffer
, 4, req
);
409 req
->reqType
= opcode
;
410 req
->glxCode
= glxCode
;
411 req
->pbuffer
= (GLXPbuffer
) drawable
;
416 #ifdef GLX_DIRECT_RENDERING
419 __GLXdisplayPrivate
*const priv
= __glXInitialize(dpy
);
420 __GLXDRIdrawable
*pdraw
= GetGLXDRIDrawable(dpy
, drawable
, &screen
);
421 __GLXscreenConfigs
*psc
= &priv
->screenConfigs
[screen
];
424 (*pdraw
->destroyDrawable
) (pdraw
);
425 __glxHashDelete(psc
->drawHash
, drawable
);
437 * This function is used to implement \c glXCreatePbuffer and
438 * \c glXCreateGLXPbufferSGIX.
441 * This function dynamically determines whether to use the SGIX_pbuffer
442 * version of the protocol or the GLX 1.3 version of the protocol.
445 * This function needs to be modified to work with direct-rendering drivers.
448 CreatePbuffer(Display
* dpy
, const __GLcontextModes
* fbconfig
,
449 unsigned int width
, unsigned int height
,
450 const int *attrib_list
, GLboolean size_in_attribs
)
452 __GLXdisplayPrivate
*priv
= __glXInitialize(dpy
);
460 while (attrib_list
[i
* 2])
464 opcode
= __glXSetupForCommand(dpy
);
471 if ((priv
->majorVersion
> 1) || (priv
->minorVersion
>= 3)) {
472 xGLXCreatePbufferReq
*req
;
473 unsigned int extra
= (size_in_attribs
) ? 0 : 2;
475 GetReqExtra(GLXCreatePbuffer
, (8 * (i
+ extra
)), req
);
476 data
= (CARD32
*) (req
+ 1);
478 req
->reqType
= opcode
;
479 req
->glxCode
= X_GLXCreatePbuffer
;
480 req
->screen
= (CARD32
) fbconfig
->screen
;
481 req
->fbconfig
= fbconfig
->fbconfigID
;
482 req
->pbuffer
= (GLXPbuffer
) id
;
483 req
->numAttribs
= (CARD32
) (i
+ extra
);
485 if (!size_in_attribs
) {
486 data
[(2 * i
) + 0] = GLX_PBUFFER_WIDTH
;
487 data
[(2 * i
) + 1] = width
;
488 data
[(2 * i
) + 2] = GLX_PBUFFER_HEIGHT
;
489 data
[(2 * i
) + 3] = height
;
494 xGLXVendorPrivateReq
*vpreq
;
496 GetReqExtra(GLXVendorPrivate
, 20 + (8 * i
), vpreq
);
497 data
= (CARD32
*) (vpreq
+ 1);
499 vpreq
->reqType
= opcode
;
500 vpreq
->glxCode
= X_GLXVendorPrivate
;
501 vpreq
->vendorCode
= X_GLXvop_CreateGLXPbufferSGIX
;
503 data
[0] = (CARD32
) fbconfig
->screen
;
504 data
[1] = (CARD32
) fbconfig
->fbconfigID
;
505 data
[2] = (CARD32
) id
;
506 data
[3] = (CARD32
) width
;
507 data
[4] = (CARD32
) height
;
511 (void) memcpy(data
, attrib_list
, sizeof(CARD32
) * 2 * i
);
521 * Create a new pbuffer.
523 PUBLIC GLXPbufferSGIX
524 glXCreateGLXPbufferSGIX(Display
* dpy
, GLXFBConfigSGIX config
,
525 unsigned int width
, unsigned int height
,
528 return (GLXPbufferSGIX
) CreatePbuffer(dpy
, (__GLcontextModes
*) config
,
530 attrib_list
, GL_FALSE
);
535 * Create a new pbuffer.
538 glXCreatePbuffer(Display
* dpy
, GLXFBConfig config
, const int *attrib_list
)
540 int i
, width
, height
;
545 for (i
= 0; attrib_list
[i
* 2]; i
++) {
546 switch (attrib_list
[i
* 2]) {
547 case GLX_PBUFFER_WIDTH
:
548 width
= attrib_list
[i
* 2 + 1];
550 case GLX_PBUFFER_HEIGHT
:
551 height
= attrib_list
[i
* 2 + 1];
556 return (GLXPbuffer
) CreatePbuffer(dpy
, (__GLcontextModes
*) config
,
557 width
, height
, attrib_list
, GL_TRUE
);
562 * Destroy an existing pbuffer.
565 glXDestroyPbuffer(Display
* dpy
, GLXPbuffer pbuf
)
567 DestroyPbuffer(dpy
, pbuf
);
572 * Query an attribute of a drawable.
575 glXQueryDrawable(Display
* dpy
, GLXDrawable drawable
,
576 int attribute
, unsigned int *value
)
578 GetDrawableAttribute(dpy
, drawable
, attribute
, value
);
583 * Query an attribute of a pbuffer.
586 glXQueryGLXPbufferSGIX(Display
* dpy
, GLXPbufferSGIX drawable
,
587 int attribute
, unsigned int *value
)
589 return GetDrawableAttribute(dpy
, drawable
, attribute
, value
);
594 * Select the event mask for a drawable.
597 glXSelectEvent(Display
* dpy
, GLXDrawable drawable
, unsigned long mask
)
601 attribs
[0] = (CARD32
) GLX_EVENT_MASK
;
602 attribs
[1] = (CARD32
) mask
;
604 ChangeDrawableAttribute(dpy
, drawable
, attribs
, 1);
609 * Get the selected event mask for a drawable.
612 glXGetSelectedEvent(Display
* dpy
, GLXDrawable drawable
, unsigned long *mask
)
617 /* The non-sense with value is required because on LP64 platforms
618 * sizeof(unsigned int) != sizeof(unsigned long). On little-endian
619 * we could just type-cast the pointer, but why?
622 GetDrawableAttribute(dpy
, drawable
, GLX_EVENT_MASK_SGIX
, &value
);
628 glXCreatePixmap(Display
* dpy
, GLXFBConfig config
, Pixmap pixmap
,
629 const int *attrib_list
)
631 return CreateDrawable(dpy
, (__GLcontextModes
*) config
,
632 (Drawable
) pixmap
, attrib_list
, X_GLXCreatePixmap
);
637 glXCreateWindow(Display
* dpy
, GLXFBConfig config
, Window win
,
638 const int *attrib_list
)
640 return CreateDrawable(dpy
, (__GLcontextModes
*) config
,
641 (Drawable
) win
, attrib_list
, X_GLXCreateWindow
);
646 glXDestroyPixmap(Display
* dpy
, GLXPixmap pixmap
)
648 DestroyDrawable(dpy
, (GLXDrawable
) pixmap
, X_GLXDestroyPixmap
);
653 glXDestroyWindow(Display
* dpy
, GLXWindow win
)
655 DestroyDrawable(dpy
, (GLXDrawable
) win
, X_GLXDestroyWindow
);
660 GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX
,
661 (Display
* dpy
, GLXPbufferSGIX pbuf
),
662 (dpy
, pbuf
), glXDestroyPbuffer
)
665 GLX_ALIAS_VOID(glXSelectEventSGIX
,
666 (Display
* dpy
, GLXDrawable drawable
,
667 unsigned long mask
), (dpy
, drawable
, mask
),
671 GLX_ALIAS_VOID(glXGetSelectedEventSGIX
,
672 (Display
* dpy
, GLXDrawable drawable
,
673 unsigned long *mask
), (dpy
, drawable
, mask
),