2 * (C) Copyright IBM Corporation 2004
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:
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
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.
27 * Implementation of pbuffer related functions.
29 * \author Ian Romanick <idr@us.ibm.com>
33 #include "glxclient.h"
34 #include <X11/extensions/extutil.h>
35 #include <X11/extensions/Xext.h>
38 #include "glxextensions.h"
40 #define WARN_ONCE_GLX_1_3(a, b) { \
41 static int warned=1; \
43 warn_GLX_1_3((a), b ); \
49 * Emit a warning when clients use GLX 1.3 functions on pre-1.3 systems.
52 warn_GLX_1_3(Display
*dpy
, const char *function_name
)
54 __GLXdisplayPrivate
*priv
= __glXInitialize(dpy
);
56 if (priv
->minorVersion
< 3) {
58 "WARNING: Application calling GLX 1.3 function \"%s\" "
59 "when GLX 1.3 is not supported! This is an application bug!\n",
66 * Change a drawable's attribute.
68 * This function is used to implement \c glXSelectEvent and
69 * \c glXSelectEventSGIX.
72 * This function dynamically determines whether to use the SGIX_pbuffer
73 * version of the protocol or the GLX 1.3 version of the protocol.
76 * This function needs to be modified to work with direct-rendering drivers.
79 ChangeDrawableAttribute(Display
* dpy
, GLXDrawable drawable
,
80 const CARD32
* attribs
, size_t num_attribs
)
82 __GLXdisplayPrivate
*priv
= __glXInitialize(dpy
);
86 if ((dpy
== NULL
) || (drawable
== 0)) {
90 opcode
= __glXSetupForCommand(dpy
);
96 if ((priv
->majorVersion
> 1) || (priv
->minorVersion
>= 3)) {
97 xGLXChangeDrawableAttributesReq
*req
;
99 GetReqExtra(GLXChangeDrawableAttributes
, 8 + (8 * num_attribs
), req
);
100 output
= (CARD32
*) (req
+ 1);
102 req
->reqType
= opcode
;
103 req
->glxCode
= X_GLXChangeDrawableAttributes
;
104 req
->drawable
= drawable
;
105 req
->numAttribs
= (CARD32
) num_attribs
;
108 xGLXVendorPrivateWithReplyReq
*vpreq
;
110 GetReqExtra(GLXVendorPrivateWithReply
, 4 + (8 * num_attribs
), vpreq
);
111 output
= (CARD32
*) (vpreq
+ 1);
113 vpreq
->reqType
= opcode
;
114 vpreq
->glxCode
= X_GLXVendorPrivateWithReply
;
115 vpreq
->vendorCode
= X_GLXvop_ChangeDrawableAttributesSGIX
;
117 output
[0] = (CARD32
) drawable
;
121 (void) memcpy(output
, attribs
, sizeof(CARD32
) * 2 * num_attribs
);
130 #ifdef GLX_DIRECT_RENDERING
132 determineTextureTarget(const int *attribs
, int numAttribs
)
137 for (i
= 0; i
< numAttribs
; i
++) {
138 if (attribs
[2 * i
] == GLX_TEXTURE_TARGET_EXT
) {
139 switch (attribs
[2 * i
+ 1]) {
140 case GLX_TEXTURE_2D_EXT
:
141 target
= GL_TEXTURE_2D
;
143 case GLX_TEXTURE_RECTANGLE_EXT
:
144 target
= GL_TEXTURE_RECTANGLE_ARB
;
154 determineTextureFormat(const int *attribs
, int numAttribs
)
158 for (i
= 0; i
< numAttribs
; i
++) {
159 if (attribs
[2 * i
] == GLX_TEXTURE_FORMAT_EXT
)
160 return attribs
[2 * i
+ 1];
167 CreateDRIDrawable(Display
*dpy
, const __GLcontextModes
*fbconfig
,
168 XID drawable
, XID glxdrawable
,
169 const int *attrib_list
, size_t num_attribs
)
171 __GLXdisplayPrivate
*const priv
= __glXInitialize(dpy
);
172 __GLXDRIdrawable
*pdraw
;
173 __GLXscreenConfigs
*psc
;
175 psc
= &priv
->screenConfigs
[fbconfig
->screen
];
176 if (psc
->driScreen
== NULL
)
179 pdraw
= psc
->driScreen
->createDrawable(psc
, drawable
,
180 glxdrawable
, fbconfig
);
182 fprintf(stderr
, "failed to create drawable\n");
186 if (__glxHashInsert(psc
->drawHash
, glxdrawable
, pdraw
)) {
187 (*pdraw
->destroyDrawable
) (pdraw
);
188 return; /* FIXME: Check what we're supposed to do here... */
191 pdraw
->textureTarget
= determineTextureTarget(attrib_list
, num_attribs
);
192 pdraw
->textureFormat
= determineTextureFormat(attrib_list
, num_attribs
);
196 DestroyDRIDrawable(Display
*dpy
, GLXDrawable drawable
, int destroy_xdrawable
)
199 __GLXdisplayPrivate
*const priv
= __glXInitialize(dpy
);
200 __GLXDRIdrawable
*pdraw
= GetGLXDRIDrawable(dpy
, drawable
, &screen
);
201 __GLXscreenConfigs
*psc
= &priv
->screenConfigs
[screen
];
204 if (destroy_xdrawable
)
205 XFreePixmap(psc
->dpy
, pdraw
->xDrawable
);
206 (*pdraw
->destroyDrawable
) (pdraw
);
207 __glxHashDelete(psc
->drawHash
, drawable
);
214 CreateDRIDrawable(Display
*dpy
, const __GLcontextModes
* fbconfig
,
215 XID drawable
, XID glxdrawable
,
216 const int *attrib_list
, size_t num_attribs
)
221 DestroyDRIDrawable(Display
*dpy
, GLXDrawable drawable
, int destroy_xdrawable
)
228 * Get a drawable's attribute.
230 * This function is used to implement \c glXGetSelectedEvent and
231 * \c glXGetSelectedEventSGIX.
234 * This function dynamically determines whether to use the SGIX_pbuffer
235 * version of the protocol or the GLX 1.3 version of the protocol.
238 * The number of attributes returned is likely to be small, probably less than
239 * 10. Given that, this routine should try to use an array on the stack to
240 * capture the reply rather than always calling Xmalloc.
243 * This function needs to be modified to work with direct-rendering drivers.
246 GetDrawableAttribute(Display
* dpy
, GLXDrawable drawable
,
247 int attribute
, unsigned int *value
)
249 __GLXdisplayPrivate
*priv
;
250 xGLXGetDrawableAttributesReply reply
;
255 unsigned int num_attributes
;
256 GLboolean use_glx_1_3
;
258 if ((dpy
== NULL
) || (drawable
== 0)) {
262 priv
= __glXInitialize(dpy
);
263 use_glx_1_3
= ((priv
->majorVersion
> 1) || (priv
->minorVersion
>= 3));
268 opcode
= __glXSetupForCommand(dpy
);
275 xGLXGetDrawableAttributesReq
*req
;
277 GetReqExtra(GLXGetDrawableAttributes
, 4, req
);
278 req
->reqType
= opcode
;
279 req
->glxCode
= X_GLXGetDrawableAttributes
;
280 req
->drawable
= drawable
;
283 xGLXVendorPrivateWithReplyReq
*vpreq
;
285 GetReqExtra(GLXVendorPrivateWithReply
, 4, vpreq
);
286 data
= (CARD32
*) (vpreq
+ 1);
287 data
[0] = (CARD32
) drawable
;
289 vpreq
->reqType
= opcode
;
290 vpreq
->glxCode
= X_GLXVendorPrivateWithReply
;
291 vpreq
->vendorCode
= X_GLXvop_GetDrawableAttributesSGIX
;
294 _XReply(dpy
, (xReply
*) & reply
, 0, False
);
296 if (reply
.type
== X_Error
) {
302 length
= reply
.length
;
304 num_attributes
= (use_glx_1_3
) ? reply
.numAttribs
: length
/ 2;
305 data
= (CARD32
*) Xmalloc(length
* sizeof(CARD32
));
307 /* Throw data on the floor */
308 _XEatData(dpy
, length
);
311 _XRead(dpy
, (char *) data
, length
* sizeof(CARD32
));
313 /* Search the set of returned attributes for the attribute requested by
316 for (i
= 0; i
< num_attributes
; i
++) {
317 if (data
[i
* 2] == attribute
) {
318 *value
= data
[(i
* 2) + 1];
323 #ifdef GLX_DIRECT_RENDERING
325 __GLXDRIdrawable
*pdraw
= GetGLXDRIDrawable(dpy
, drawable
, NULL
);
327 if (pdraw
!= NULL
&& !pdraw
->textureTarget
)
328 pdraw
->textureTarget
=
329 determineTextureTarget((const int *) data
, num_attributes
);
330 if (pdraw
!= NULL
&& !pdraw
->textureFormat
)
331 pdraw
->textureFormat
=
332 determineTextureFormat((const int *) data
, num_attributes
);
347 * Create a non-pbuffer GLX drawable.
350 * This function needs to be modified to work with direct-rendering drivers.
353 CreateDrawable(Display
* dpy
, const __GLcontextModes
* fbconfig
,
354 Drawable drawable
, const int *attrib_list
, CARD8 glxCode
)
356 xGLXCreateWindowReq
*req
;
363 while (attrib_list
[i
* 2] != None
)
367 opcode
= __glXSetupForCommand(dpy
);
372 GetReqExtra(GLXCreateWindow
, 8 * i
, req
);
373 data
= (CARD32
*) (req
+ 1);
375 req
->reqType
= opcode
;
376 req
->glxCode
= glxCode
;
377 req
->screen
= (CARD32
) fbconfig
->screen
;
378 req
->fbconfig
= fbconfig
->fbconfigID
;
379 req
->window
= (CARD32
) drawable
;
380 req
->glxwindow
= (GLXWindow
) XAllocID(dpy
);
381 req
->numAttribs
= (CARD32
) i
;
384 memcpy(data
, attrib_list
, 8 * i
);
389 CreateDRIDrawable(dpy
, fbconfig
, drawable
, req
->glxwindow
, attrib_list
, i
);
391 return (GLXDrawable
) req
->glxwindow
;
396 * Destroy a non-pbuffer GLX drawable.
399 DestroyDrawable(Display
* dpy
, GLXDrawable drawable
, CARD32 glxCode
)
401 xGLXDestroyPbufferReq
*req
;
404 if ((dpy
== NULL
) || (drawable
== 0)) {
409 opcode
= __glXSetupForCommand(dpy
);
415 GetReqExtra(GLXDestroyPbuffer
, 4, req
);
416 req
->reqType
= opcode
;
417 req
->glxCode
= glxCode
;
418 req
->pbuffer
= (GLXPbuffer
) drawable
;
423 DestroyDRIDrawable(dpy
, drawable
, GL_FALSE
);
432 * This function is used to implement \c glXCreatePbuffer and
433 * \c glXCreateGLXPbufferSGIX.
436 * This function dynamically determines whether to use the SGIX_pbuffer
437 * version of the protocol or the GLX 1.3 version of the protocol.
440 * This function needs to be modified to work with direct-rendering drivers.
443 CreatePbuffer(Display
* dpy
, const __GLcontextModes
* fbconfig
,
444 unsigned int width
, unsigned int height
,
445 const int *attrib_list
, GLboolean size_in_attribs
)
447 __GLXdisplayPrivate
*priv
= __glXInitialize(dpy
);
456 while (attrib_list
[i
* 2])
460 opcode
= __glXSetupForCommand(dpy
);
467 if ((priv
->majorVersion
> 1) || (priv
->minorVersion
>= 3)) {
468 xGLXCreatePbufferReq
*req
;
469 unsigned int extra
= (size_in_attribs
) ? 0 : 2;
471 GetReqExtra(GLXCreatePbuffer
, (8 * (i
+ extra
)), req
);
472 data
= (CARD32
*) (req
+ 1);
474 req
->reqType
= opcode
;
475 req
->glxCode
= X_GLXCreatePbuffer
;
476 req
->screen
= (CARD32
) fbconfig
->screen
;
477 req
->fbconfig
= fbconfig
->fbconfigID
;
478 req
->pbuffer
= (GLXPbuffer
) id
;
479 req
->numAttribs
= (CARD32
) (i
+ extra
);
481 if (!size_in_attribs
) {
482 data
[(2 * i
) + 0] = GLX_PBUFFER_WIDTH
;
483 data
[(2 * i
) + 1] = width
;
484 data
[(2 * i
) + 2] = GLX_PBUFFER_HEIGHT
;
485 data
[(2 * i
) + 3] = height
;
490 xGLXVendorPrivateReq
*vpreq
;
492 GetReqExtra(GLXVendorPrivate
, 20 + (8 * i
), vpreq
);
493 data
= (CARD32
*) (vpreq
+ 1);
495 vpreq
->reqType
= opcode
;
496 vpreq
->glxCode
= X_GLXVendorPrivate
;
497 vpreq
->vendorCode
= X_GLXvop_CreateGLXPbufferSGIX
;
499 data
[0] = (CARD32
) fbconfig
->screen
;
500 data
[1] = (CARD32
) fbconfig
->fbconfigID
;
501 data
[2] = (CARD32
) id
;
502 data
[3] = (CARD32
) width
;
503 data
[4] = (CARD32
) height
;
507 (void) memcpy(data
, attrib_list
, sizeof(CARD32
) * 2 * i
);
512 pixmap
= XCreatePixmap(dpy
, RootWindow(dpy
, fbconfig
->screen
),
513 width
, height
, fbconfig
->rgbBits
);
515 CreateDRIDrawable(dpy
, fbconfig
, pixmap
, id
, attrib_list
, i
);
523 * This function is used to implement \c glXDestroyPbuffer and
524 * \c glXDestroyGLXPbufferSGIX.
527 * This function dynamically determines whether to use the SGIX_pbuffer
528 * version of the protocol or the GLX 1.3 version of the protocol.
531 DestroyPbuffer(Display
* dpy
, GLXDrawable drawable
)
533 __GLXdisplayPrivate
*priv
= __glXInitialize(dpy
);
536 if ((dpy
== NULL
) || (drawable
== 0)) {
540 opcode
= __glXSetupForCommand(dpy
);
546 if ((priv
->majorVersion
> 1) || (priv
->minorVersion
>= 3)) {
547 xGLXDestroyPbufferReq
*req
;
549 GetReq(GLXDestroyPbuffer
, req
);
550 req
->reqType
= opcode
;
551 req
->glxCode
= X_GLXDestroyPbuffer
;
552 req
->pbuffer
= (GLXPbuffer
) drawable
;
555 xGLXVendorPrivateWithReplyReq
*vpreq
;
558 GetReqExtra(GLXVendorPrivateWithReply
, 4, vpreq
);
559 data
= (CARD32
*) (vpreq
+ 1);
561 data
[0] = (CARD32
) drawable
;
563 vpreq
->reqType
= opcode
;
564 vpreq
->glxCode
= X_GLXVendorPrivateWithReply
;
565 vpreq
->vendorCode
= X_GLXvop_DestroyGLXPbufferSGIX
;
571 DestroyDRIDrawable(dpy
, drawable
, GL_TRUE
);
577 * Create a new pbuffer.
579 PUBLIC GLXPbufferSGIX
580 glXCreateGLXPbufferSGIX(Display
* dpy
, GLXFBConfigSGIX config
,
581 unsigned int width
, unsigned int height
,
584 return (GLXPbufferSGIX
) CreatePbuffer(dpy
, (__GLcontextModes
*) config
,
586 attrib_list
, GL_FALSE
);
591 * Create a new pbuffer.
594 glXCreatePbuffer(Display
* dpy
, GLXFBConfig config
, const int *attrib_list
)
596 int i
, width
, height
;
601 WARN_ONCE_GLX_1_3(dpy
, __func__
);
603 for (i
= 0; attrib_list
[i
* 2]; i
++) {
604 switch (attrib_list
[i
* 2]) {
605 case GLX_PBUFFER_WIDTH
:
606 width
= attrib_list
[i
* 2 + 1];
608 case GLX_PBUFFER_HEIGHT
:
609 height
= attrib_list
[i
* 2 + 1];
614 return (GLXPbuffer
) CreatePbuffer(dpy
, (__GLcontextModes
*) config
,
615 width
, height
, attrib_list
, GL_TRUE
);
620 * Destroy an existing pbuffer.
623 glXDestroyPbuffer(Display
* dpy
, GLXPbuffer pbuf
)
625 DestroyPbuffer(dpy
, pbuf
);
630 * Query an attribute of a drawable.
633 glXQueryDrawable(Display
* dpy
, GLXDrawable drawable
,
634 int attribute
, unsigned int *value
)
636 WARN_ONCE_GLX_1_3(dpy
, __func__
);
637 GetDrawableAttribute(dpy
, drawable
, attribute
, value
);
642 * Query an attribute of a pbuffer.
645 glXQueryGLXPbufferSGIX(Display
* dpy
, GLXPbufferSGIX drawable
,
646 int attribute
, unsigned int *value
)
648 return GetDrawableAttribute(dpy
, drawable
, attribute
, value
);
653 * Select the event mask for a drawable.
656 glXSelectEvent(Display
* dpy
, GLXDrawable drawable
, unsigned long mask
)
660 attribs
[0] = (CARD32
) GLX_EVENT_MASK
;
661 attribs
[1] = (CARD32
) mask
;
663 ChangeDrawableAttribute(dpy
, drawable
, attribs
, 1);
668 * Get the selected event mask for a drawable.
671 glXGetSelectedEvent(Display
* dpy
, GLXDrawable drawable
, unsigned long *mask
)
676 /* The non-sense with value is required because on LP64 platforms
677 * sizeof(unsigned int) != sizeof(unsigned long). On little-endian
678 * we could just type-cast the pointer, but why?
681 GetDrawableAttribute(dpy
, drawable
, GLX_EVENT_MASK_SGIX
, &value
);
687 glXCreatePixmap(Display
* dpy
, GLXFBConfig config
, Pixmap pixmap
,
688 const int *attrib_list
)
690 WARN_ONCE_GLX_1_3(dpy
, __func__
);
692 return CreateDrawable(dpy
, (__GLcontextModes
*) config
,
693 (Drawable
) pixmap
, attrib_list
, X_GLXCreatePixmap
);
698 glXCreateWindow(Display
* dpy
, GLXFBConfig config
, Window win
,
699 const int *attrib_list
)
701 WARN_ONCE_GLX_1_3(dpy
, __func__
);
703 return CreateDrawable(dpy
, (__GLcontextModes
*) config
,
704 (Drawable
) win
, attrib_list
, X_GLXCreateWindow
);
709 glXDestroyPixmap(Display
* dpy
, GLXPixmap pixmap
)
711 WARN_ONCE_GLX_1_3(dpy
, __func__
);
713 DestroyDrawable(dpy
, (GLXDrawable
) pixmap
, X_GLXDestroyPixmap
);
718 glXDestroyWindow(Display
* dpy
, GLXWindow win
)
720 WARN_ONCE_GLX_1_3(dpy
, __func__
);
722 DestroyDrawable(dpy
, (GLXDrawable
) win
, X_GLXDestroyWindow
);
727 GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX
,
728 (Display
* dpy
, GLXPbufferSGIX pbuf
),
729 (dpy
, pbuf
), glXDestroyPbuffer
)
732 GLX_ALIAS_VOID(glXSelectEventSGIX
,
733 (Display
* dpy
, GLXDrawable drawable
,
734 unsigned long mask
), (dpy
, drawable
, mask
), glXSelectEvent
)
737 GLX_ALIAS_VOID(glXGetSelectedEventSGIX
,
738 (Display
* dpy
, GLXDrawable drawable
,
739 unsigned long *mask
), (dpy
, drawable
, mask
),