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>
39 #include "glxextensions.h"
40 #include "glcontextmodes.h"
44 * Change a drawable's attribute.
46 * This function is used to implement \c glXSelectEvent and
47 * \c glXSelectEventSGIX.
50 * This function dynamically determines whether to use the SGIX_pbuffer
51 * version of the protocol or the GLX 1.3 version of the protocol.
54 * This function needs to be modified to work with direct-rendering drivers.
57 ChangeDrawableAttribute(Display
* dpy
, GLXDrawable drawable
,
58 const CARD32
* attribs
, size_t num_attribs
)
60 __GLXdisplayPrivate
*priv
= __glXInitialize(dpy
);
64 if ((dpy
== NULL
) || (drawable
== 0)) {
68 opcode
= __glXSetupForCommand(dpy
);
74 if ((priv
->majorVersion
> 1) || (priv
->minorVersion
>= 3)) {
75 xGLXChangeDrawableAttributesReq
*req
;
77 GetReqExtra(GLXChangeDrawableAttributes
, 8 + (8 * num_attribs
), req
);
78 output
= (CARD32
*) (req
+ 1);
80 req
->reqType
= opcode
;
81 req
->glxCode
= X_GLXChangeDrawableAttributes
;
82 req
->drawable
= drawable
;
83 req
->numAttribs
= (CARD32
) num_attribs
;
86 xGLXVendorPrivateWithReplyReq
*vpreq
;
88 GetReqExtra(GLXVendorPrivateWithReply
, 4 + (8 * num_attribs
), vpreq
);
89 output
= (CARD32
*) (vpreq
+ 1);
91 vpreq
->reqType
= opcode
;
92 vpreq
->glxCode
= X_GLXVendorPrivateWithReply
;
93 vpreq
->vendorCode
= X_GLXvop_ChangeDrawableAttributesSGIX
;
95 output
[0] = (CARD32
) drawable
;
99 (void) memcpy(output
, attribs
, sizeof(CARD32
) * 2 * num_attribs
);
111 * This function is used to implement \c glXDestroyPbuffer and
112 * \c glXDestroyGLXPbufferSGIX.
115 * This function dynamically determines whether to use the SGIX_pbuffer
116 * version of the protocol or the GLX 1.3 version of the protocol.
119 * This function needs to be modified to work with direct-rendering drivers.
122 DestroyPbuffer(Display
* dpy
, GLXDrawable drawable
)
124 __GLXdisplayPrivate
*priv
= __glXInitialize(dpy
);
127 if ((dpy
== NULL
) || (drawable
== 0)) {
131 opcode
= __glXSetupForCommand(dpy
);
137 if ((priv
->majorVersion
> 1) || (priv
->minorVersion
>= 3)) {
138 xGLXDestroyPbufferReq
*req
;
140 GetReq(GLXDestroyPbuffer
, req
);
141 req
->reqType
= opcode
;
142 req
->glxCode
= X_GLXDestroyPbuffer
;
143 req
->pbuffer
= (GLXPbuffer
) drawable
;
146 xGLXVendorPrivateWithReplyReq
*vpreq
;
149 GetReqExtra(GLXVendorPrivateWithReply
, 4, vpreq
);
150 data
= (CARD32
*) (vpreq
+ 1);
152 data
[0] = (CARD32
) drawable
;
154 vpreq
->reqType
= opcode
;
155 vpreq
->glxCode
= X_GLXVendorPrivateWithReply
;
156 vpreq
->vendorCode
= X_GLXvop_DestroyGLXPbufferSGIX
;
166 #ifdef GLX_DIRECT_RENDERING
167 extern __GLXDRIdrawable
*GetGLXDRIDrawable(Display
* dpy
,
168 GLXDrawable drawable
,
169 int *const scrn_num
);
172 determineTextureTarget(const int *attribs
, int numAttribs
)
177 for (i
= 0; i
< numAttribs
; i
++) {
178 if (attribs
[2 * i
] == GLX_TEXTURE_TARGET_EXT
) {
179 switch (attribs
[2 * i
+ 1]) {
180 case GLX_TEXTURE_2D_EXT
:
181 target
= GL_TEXTURE_2D
;
183 case GLX_TEXTURE_RECTANGLE_EXT
:
184 target
= GL_TEXTURE_RECTANGLE_ARB
;
195 determineTextureFormat(const int *attribs
, int numAttribs
)
199 for (i
= 0; i
< numAttribs
; i
++) {
200 if (attribs
[2 * i
] == GLX_TEXTURE_FORMAT_EXT
)
201 return attribs
[2 * i
+ 1];
209 * Get a drawable's attribute.
211 * This function is used to implement \c glXGetSelectedEvent and
212 * \c glXGetSelectedEventSGIX.
215 * This function dynamically determines whether to use the SGIX_pbuffer
216 * version of the protocol or the GLX 1.3 version of the protocol.
219 * The number of attributes returned is likely to be small, probably less than
220 * 10. Given that, this routine should try to use an array on the stack to
221 * capture the reply rather than always calling Xmalloc.
224 * This function needs to be modified to work with direct-rendering drivers.
227 GetDrawableAttribute(Display
* dpy
, GLXDrawable drawable
,
228 int attribute
, unsigned int *value
)
230 __GLXdisplayPrivate
*priv
;
231 xGLXGetDrawableAttributesReply reply
;
236 unsigned int num_attributes
;
237 GLboolean use_glx_1_3
;
239 if ((dpy
== NULL
) || (drawable
== 0)) {
243 priv
= __glXInitialize(dpy
);
244 use_glx_1_3
= ((priv
->majorVersion
> 1) || (priv
->minorVersion
>= 3));
249 opcode
= __glXSetupForCommand(dpy
);
256 xGLXGetDrawableAttributesReq
*req
;
258 GetReqExtra(GLXGetDrawableAttributes
, 4, req
);
259 req
->reqType
= opcode
;
260 req
->glxCode
= X_GLXGetDrawableAttributes
;
261 req
->drawable
= drawable
;
264 xGLXVendorPrivateWithReplyReq
*vpreq
;
266 GetReqExtra(GLXVendorPrivateWithReply
, 4, vpreq
);
267 data
= (CARD32
*) (vpreq
+ 1);
268 data
[0] = (CARD32
) drawable
;
270 vpreq
->reqType
= opcode
;
271 vpreq
->glxCode
= X_GLXVendorPrivateWithReply
;
272 vpreq
->vendorCode
= X_GLXvop_GetDrawableAttributesSGIX
;
275 _XReply(dpy
, (xReply
*) & reply
, 0, False
);
277 if (reply
.type
== X_Error
) {
283 length
= reply
.length
;
285 num_attributes
= (use_glx_1_3
) ? reply
.numAttribs
: length
/ 2;
286 data
= (CARD32
*) Xmalloc(length
* sizeof(CARD32
));
288 /* Throw data on the floor */
289 _XEatData(dpy
, length
);
292 _XRead(dpy
, (char *) data
, length
* sizeof(CARD32
));
294 /* Search the set of returned attributes for the attribute requested by
297 for (i
= 0; i
< num_attributes
; i
++) {
298 if (data
[i
* 2] == attribute
) {
299 *value
= data
[(i
* 2) + 1];
304 #ifdef GLX_DIRECT_RENDERING
306 __GLXDRIdrawable
*pdraw
= GetGLXDRIDrawable(dpy
, drawable
, NULL
);
308 if (pdraw
!= NULL
&& !pdraw
->textureTarget
)
309 pdraw
->textureTarget
=
310 determineTextureTarget((const int *) data
, num_attributes
);
311 if (pdraw
!= NULL
&& !pdraw
->textureFormat
)
312 pdraw
->textureFormat
=
313 determineTextureFormat((const int *) data
, num_attributes
);
328 * Create a non-pbuffer GLX drawable.
331 * This function needs to be modified to work with direct-rendering drivers.
334 CreateDrawable(Display
* dpy
, const __GLcontextModes
* fbconfig
,
335 Drawable drawable
, const int *attrib_list
, CARD8 glxCode
)
337 xGLXCreateWindowReq
*req
;
344 while (attrib_list
[i
* 2] != None
)
348 opcode
= __glXSetupForCommand(dpy
);
353 GetReqExtra(GLXCreateWindow
, 8 * i
, req
);
354 data
= (CARD32
*) (req
+ 1);
356 req
->reqType
= opcode
;
357 req
->glxCode
= glxCode
;
358 req
->screen
= (CARD32
) fbconfig
->screen
;
359 req
->fbconfig
= fbconfig
->fbconfigID
;
360 req
->window
= (CARD32
) drawable
;
361 req
->glxwindow
= (GLXWindow
) XAllocID(dpy
);
362 req
->numAttribs
= (CARD32
) i
;
364 memcpy(data
, attrib_list
, 8 * i
);
369 #ifdef GLX_DIRECT_RENDERING
371 /* FIXME: Maybe delay __DRIdrawable creation until the drawable
372 * is actually bound to a context... */
374 __GLXdisplayPrivate
*const priv
= __glXInitialize(dpy
);
375 __GLXDRIdrawable
*pdraw
;
376 __GLXscreenConfigs
*psc
;
378 psc
= &priv
->screenConfigs
[fbconfig
->screen
];
379 if (psc
->driScreen
== NULL
)
381 pdraw
= psc
->driScreen
->createDrawable(psc
, drawable
,
382 req
->glxwindow
, fbconfig
);
384 fprintf(stderr
, "failed to create drawable\n");
388 if (__glxHashInsert(psc
->drawHash
, req
->glxwindow
, pdraw
)) {
389 (*pdraw
->destroyDrawable
) (pdraw
);
390 return None
; /* FIXME: Check what we're supposed to do here... */
393 pdraw
->textureTarget
= determineTextureTarget(attrib_list
, i
);
394 pdraw
->textureFormat
= determineTextureFormat(attrib_list
, i
);
398 return (GLXDrawable
) req
->glxwindow
;
403 * Destroy a non-pbuffer GLX drawable.
406 * This function needs to be modified to work with direct-rendering drivers.
409 DestroyDrawable(Display
* dpy
, GLXDrawable drawable
, CARD32 glxCode
)
411 xGLXDestroyPbufferReq
*req
;
414 if ((dpy
== NULL
) || (drawable
== 0)) {
419 opcode
= __glXSetupForCommand(dpy
);
425 GetReqExtra(GLXDestroyPbuffer
, 4, req
);
426 req
->reqType
= opcode
;
427 req
->glxCode
= glxCode
;
428 req
->pbuffer
= (GLXPbuffer
) drawable
;
433 #ifdef GLX_DIRECT_RENDERING
436 __GLXdisplayPrivate
*const priv
= __glXInitialize(dpy
);
437 __GLXDRIdrawable
*pdraw
= GetGLXDRIDrawable(dpy
, drawable
, &screen
);
438 __GLXscreenConfigs
*psc
= &priv
->screenConfigs
[screen
];
441 (*pdraw
->destroyDrawable
) (pdraw
);
442 __glxHashDelete(psc
->drawHash
, drawable
);
454 * This function is used to implement \c glXCreatePbuffer and
455 * \c glXCreateGLXPbufferSGIX.
458 * This function dynamically determines whether to use the SGIX_pbuffer
459 * version of the protocol or the GLX 1.3 version of the protocol.
462 * This function needs to be modified to work with direct-rendering drivers.
465 CreatePbuffer(Display
* dpy
, const __GLcontextModes
* fbconfig
,
466 unsigned int width
, unsigned int height
,
467 const int *attrib_list
, GLboolean size_in_attribs
)
469 __GLXdisplayPrivate
*priv
= __glXInitialize(dpy
);
477 while (attrib_list
[i
* 2])
481 opcode
= __glXSetupForCommand(dpy
);
488 if ((priv
->majorVersion
> 1) || (priv
->minorVersion
>= 3)) {
489 xGLXCreatePbufferReq
*req
;
490 unsigned int extra
= (size_in_attribs
) ? 0 : 2;
492 GetReqExtra(GLXCreatePbuffer
, (8 * (i
+ extra
)), req
);
493 data
= (CARD32
*) (req
+ 1);
495 req
->reqType
= opcode
;
496 req
->glxCode
= X_GLXCreatePbuffer
;
497 req
->screen
= (CARD32
) fbconfig
->screen
;
498 req
->fbconfig
= fbconfig
->fbconfigID
;
499 req
->pbuffer
= (GLXPbuffer
) id
;
500 req
->numAttribs
= (CARD32
) (i
+ extra
);
502 if (!size_in_attribs
) {
503 data
[(2 * i
) + 0] = GLX_PBUFFER_WIDTH
;
504 data
[(2 * i
) + 1] = width
;
505 data
[(2 * i
) + 2] = GLX_PBUFFER_HEIGHT
;
506 data
[(2 * i
) + 3] = height
;
511 xGLXVendorPrivateReq
*vpreq
;
513 GetReqExtra(GLXVendorPrivate
, 20 + (8 * i
), vpreq
);
514 data
= (CARD32
*) (vpreq
+ 1);
516 vpreq
->reqType
= opcode
;
517 vpreq
->glxCode
= X_GLXVendorPrivate
;
518 vpreq
->vendorCode
= X_GLXvop_CreateGLXPbufferSGIX
;
520 data
[0] = (CARD32
) fbconfig
->screen
;
521 data
[1] = (CARD32
) fbconfig
->fbconfigID
;
522 data
[2] = (CARD32
) id
;
523 data
[3] = (CARD32
) width
;
524 data
[4] = (CARD32
) height
;
528 (void) memcpy(data
, attrib_list
, sizeof(CARD32
) * 2 * i
);
538 * Create a new pbuffer.
540 PUBLIC GLXPbufferSGIX
541 glXCreateGLXPbufferSGIX(Display
* dpy
, GLXFBConfigSGIX config
,
542 unsigned int width
, unsigned int height
,
545 return (GLXPbufferSGIX
) CreatePbuffer(dpy
, (__GLcontextModes
*) config
,
547 attrib_list
, GL_FALSE
);
552 * Create a new pbuffer.
555 glXCreatePbuffer(Display
* dpy
, GLXFBConfig config
, const int *attrib_list
)
557 int i
, width
, height
;
562 for (i
= 0; attrib_list
[i
* 2]; i
++) {
563 switch (attrib_list
[i
* 2]) {
564 case GLX_PBUFFER_WIDTH
:
565 width
= attrib_list
[i
* 2 + 1];
567 case GLX_PBUFFER_HEIGHT
:
568 height
= attrib_list
[i
* 2 + 1];
573 return (GLXPbuffer
) CreatePbuffer(dpy
, (__GLcontextModes
*) config
,
574 width
, height
, attrib_list
, GL_TRUE
);
579 * Destroy an existing pbuffer.
582 glXDestroyPbuffer(Display
* dpy
, GLXPbuffer pbuf
)
584 DestroyPbuffer(dpy
, pbuf
);
589 * Query an attribute of a drawable.
592 glXQueryDrawable(Display
* dpy
, GLXDrawable drawable
,
593 int attribute
, unsigned int *value
)
595 GetDrawableAttribute(dpy
, drawable
, attribute
, value
);
600 * Query an attribute of a pbuffer.
603 glXQueryGLXPbufferSGIX(Display
* dpy
, GLXPbufferSGIX drawable
,
604 int attribute
, unsigned int *value
)
606 return GetDrawableAttribute(dpy
, drawable
, attribute
, value
);
611 * Select the event mask for a drawable.
614 glXSelectEvent(Display
* dpy
, GLXDrawable drawable
, unsigned long mask
)
618 attribs
[0] = (CARD32
) GLX_EVENT_MASK
;
619 attribs
[1] = (CARD32
) mask
;
621 ChangeDrawableAttribute(dpy
, drawable
, attribs
, 1);
626 * Get the selected event mask for a drawable.
629 glXGetSelectedEvent(Display
* dpy
, GLXDrawable drawable
, unsigned long *mask
)
634 /* The non-sense with value is required because on LP64 platforms
635 * sizeof(unsigned int) != sizeof(unsigned long). On little-endian
636 * we could just type-cast the pointer, but why?
639 GetDrawableAttribute(dpy
, drawable
, GLX_EVENT_MASK_SGIX
, &value
);
645 glXCreatePixmap(Display
* dpy
, GLXFBConfig config
, Pixmap pixmap
,
646 const int *attrib_list
)
648 return CreateDrawable(dpy
, (__GLcontextModes
*) config
,
649 (Drawable
) pixmap
, attrib_list
, X_GLXCreatePixmap
);
654 glXCreateWindow(Display
* dpy
, GLXFBConfig config
, Window win
,
655 const int *attrib_list
)
657 return CreateDrawable(dpy
, (__GLcontextModes
*) config
,
658 (Drawable
) win
, attrib_list
, X_GLXCreateWindow
);
663 glXDestroyPixmap(Display
* dpy
, GLXPixmap pixmap
)
665 DestroyDrawable(dpy
, (GLXDrawable
) pixmap
, X_GLXDestroyPixmap
);
670 glXDestroyWindow(Display
* dpy
, GLXWindow win
)
672 DestroyDrawable(dpy
, (GLXDrawable
) win
, X_GLXDestroyWindow
);
677 GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX
,
678 (Display
* dpy
, GLXPbufferSGIX pbuf
),
679 (dpy
, pbuf
), glXDestroyPbuffer
)
682 GLX_ALIAS_VOID(glXSelectEventSGIX
,
683 (Display
* dpy
, GLXDrawable drawable
,
684 unsigned long mask
), (dpy
, drawable
, mask
),
688 GLX_ALIAS_VOID(glXGetSelectedEventSGIX
,
689 (Display
* dpy
, GLXDrawable drawable
,
690 unsigned long *mask
), (dpy
, drawable
, mask
),