Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/glx/glx_pbuffer.c
4558 views
1
/*
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 <[email protected]>
30
*/
31
32
#include <inttypes.h>
33
#include "glxclient.h"
34
#include <X11/extensions/extutil.h>
35
#include <X11/extensions/Xext.h>
36
#include <assert.h>
37
#include <string.h>
38
#include <limits.h>
39
#include "glxextensions.h"
40
41
#ifdef GLX_USE_APPLEGL
42
#include <pthread.h>
43
#include "apple/apple_glx_drawable.h"
44
#endif
45
46
#include "glx_error.h"
47
48
#ifndef GLX_USE_APPLEGL
49
/**
50
* Change a drawable's attribute.
51
*
52
* This function is used to implement \c glXSelectEvent and
53
* \c glXSelectEventSGIX.
54
*
55
* \note
56
* This function dynamically determines whether to use the SGIX_pbuffer
57
* version of the protocol or the GLX 1.3 version of the protocol.
58
*/
59
static void
60
ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable,
61
const CARD32 * attribs, size_t num_attribs)
62
{
63
struct glx_display *priv = __glXInitialize(dpy);
64
#ifdef GLX_DIRECT_RENDERING
65
__GLXDRIdrawable *pdraw;
66
int i;
67
#endif
68
CARD32 *output;
69
CARD8 opcode;
70
71
if ((priv == NULL) || (dpy == NULL) || (drawable == 0)) {
72
return;
73
}
74
75
opcode = __glXSetupForCommand(dpy);
76
if (!opcode)
77
return;
78
79
LockDisplay(dpy);
80
81
if (priv->minorVersion >= 3) {
82
xGLXChangeDrawableAttributesReq *req;
83
84
GetReqExtra(GLXChangeDrawableAttributes, 8 * num_attribs, req);
85
output = (CARD32 *) (req + 1);
86
87
req->reqType = opcode;
88
req->glxCode = X_GLXChangeDrawableAttributes;
89
req->drawable = drawable;
90
req->numAttribs = (CARD32) num_attribs;
91
}
92
else {
93
xGLXVendorPrivateWithReplyReq *vpreq;
94
95
GetReqExtra(GLXVendorPrivateWithReply, 8 + (8 * num_attribs), vpreq);
96
output = (CARD32 *) (vpreq + 1);
97
98
vpreq->reqType = opcode;
99
vpreq->glxCode = X_GLXVendorPrivateWithReply;
100
vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX;
101
102
output[0] = (CARD32) drawable;
103
output[1] = num_attribs;
104
output += 2;
105
}
106
107
(void) memcpy(output, attribs, sizeof(CARD32) * 2 * num_attribs);
108
109
UnlockDisplay(dpy);
110
SyncHandle();
111
112
#ifdef GLX_DIRECT_RENDERING
113
pdraw = GetGLXDRIDrawable(dpy, drawable);
114
115
if (!pdraw)
116
return;
117
118
for (i = 0; i < num_attribs; i++) {
119
switch(attribs[i * 2]) {
120
case GLX_EVENT_MASK:
121
/* Keep a local copy for masking out DRI2 proto events as needed */
122
pdraw->eventMask = attribs[i * 2 + 1];
123
break;
124
}
125
}
126
#endif
127
128
return;
129
}
130
131
132
#ifdef GLX_DIRECT_RENDERING
133
static GLenum
134
determineTextureTarget(const int *attribs, int numAttribs)
135
{
136
GLenum target = 0;
137
int i;
138
139
for (i = 0; i < numAttribs; i++) {
140
if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) {
141
switch (attribs[2 * i + 1]) {
142
case GLX_TEXTURE_2D_EXT:
143
target = GL_TEXTURE_2D;
144
break;
145
case GLX_TEXTURE_RECTANGLE_EXT:
146
target = GL_TEXTURE_RECTANGLE_ARB;
147
break;
148
}
149
}
150
}
151
152
return target;
153
}
154
155
static GLenum
156
determineTextureFormat(const int *attribs, int numAttribs)
157
{
158
int i;
159
160
for (i = 0; i < numAttribs; i++) {
161
if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT)
162
return attribs[2 * i + 1];
163
}
164
165
return 0;
166
}
167
#endif
168
169
static GLboolean
170
CreateDRIDrawable(Display *dpy, struct glx_config *config,
171
XID drawable, XID glxdrawable,
172
const int *attrib_list, size_t num_attribs)
173
{
174
#ifdef GLX_DIRECT_RENDERING
175
struct glx_display *const priv = __glXInitialize(dpy);
176
__GLXDRIdrawable *pdraw;
177
struct glx_screen *psc;
178
179
if (priv == NULL) {
180
fprintf(stderr, "failed to create drawable\n");
181
return GL_FALSE;
182
}
183
184
psc = priv->screens[config->screen];
185
if (psc->driScreen == NULL)
186
return GL_TRUE;
187
188
pdraw = psc->driScreen->createDrawable(psc, drawable,
189
glxdrawable, config);
190
if (pdraw == NULL) {
191
fprintf(stderr, "failed to create drawable\n");
192
return GL_FALSE;
193
}
194
195
if (__glxHashInsert(priv->drawHash, glxdrawable, pdraw)) {
196
(*pdraw->destroyDrawable) (pdraw);
197
return GL_FALSE;
198
}
199
200
pdraw->textureTarget = determineTextureTarget(attrib_list, num_attribs);
201
pdraw->textureFormat = determineTextureFormat(attrib_list, num_attribs);
202
#endif
203
204
return GL_TRUE;
205
}
206
207
static void
208
DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable)
209
{
210
#ifdef GLX_DIRECT_RENDERING
211
struct glx_display *const priv = __glXInitialize(dpy);
212
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
213
XID xid;
214
215
if (priv != NULL && pdraw != NULL) {
216
xid = pdraw->xDrawable;
217
(*pdraw->destroyDrawable) (pdraw);
218
__glxHashDelete(priv->drawHash, drawable);
219
if (destroy_xdrawable)
220
XFreePixmap(priv->dpy, xid);
221
}
222
#endif
223
}
224
225
/**
226
* Get a drawable's attribute.
227
*
228
* This function is used to implement \c glXGetSelectedEvent and
229
* \c glXGetSelectedEventSGIX.
230
*
231
* \note
232
* This function dynamically determines whether to use the SGIX_pbuffer
233
* version of the protocol or the GLX 1.3 version of the protocol.
234
*
235
* \todo
236
* The number of attributes returned is likely to be small, probably less than
237
* 10. Given that, this routine should try to use an array on the stack to
238
* capture the reply rather than always calling Xmalloc.
239
*/
240
int
241
__glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable,
242
int attribute, unsigned int *value)
243
{
244
struct glx_display *priv;
245
xGLXGetDrawableAttributesReply reply;
246
CARD32 *data;
247
CARD8 opcode;
248
unsigned int length;
249
unsigned int i;
250
unsigned int num_attributes;
251
int found = 0;
252
253
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
254
__GLXDRIdrawable *pdraw;
255
#endif
256
257
if (dpy == NULL)
258
return 0;
259
260
/* Page 38 (page 52 of the PDF) of glxencode1.3.pdf says:
261
*
262
* "If drawable is not a valid GLX drawable, a GLXBadDrawable error is
263
* generated."
264
*/
265
if (drawable == 0) {
266
__glXSendError(dpy, GLXBadDrawable, 0, X_GLXGetDrawableAttributes, false);
267
return 0;
268
}
269
270
priv = __glXInitialize(dpy);
271
if (priv == NULL)
272
return 0;
273
274
*value = 0;
275
276
opcode = __glXSetupForCommand(dpy);
277
if (!opcode)
278
return 0;
279
280
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
281
pdraw = GetGLXDRIDrawable(dpy, drawable);
282
283
if (attribute == GLX_BACK_BUFFER_AGE_EXT) {
284
struct glx_context *gc = __glXGetCurrentContext();
285
struct glx_screen *psc;
286
287
/* The GLX_EXT_buffer_age spec says:
288
*
289
* "If querying GLX_BACK_BUFFER_AGE_EXT and <draw> is not bound to
290
* the calling thread's current context a GLXBadDrawable error is
291
* generated."
292
*/
293
if (pdraw == NULL || gc == &dummyContext || gc->currentDpy != dpy ||
294
(gc->currentDrawable != drawable &&
295
gc->currentReadable != drawable)) {
296
__glXSendError(dpy, GLXBadDrawable, drawable,
297
X_GLXGetDrawableAttributes, false);
298
return 0;
299
}
300
301
psc = pdraw->psc;
302
303
if (psc->driScreen->getBufferAge != NULL)
304
*value = psc->driScreen->getBufferAge(pdraw);
305
306
return 0;
307
}
308
309
if (pdraw) {
310
if (attribute == GLX_SWAP_INTERVAL_EXT) {
311
*value = pdraw->psc->driScreen->getSwapInterval(pdraw);
312
return 0;
313
} else if (attribute == GLX_MAX_SWAP_INTERVAL_EXT) {
314
*value = INT_MAX;
315
return 0;
316
} else if (attribute == GLX_LATE_SWAPS_TEAR_EXT) {
317
*value = __glXExtensionBitIsEnabled(pdraw->psc,
318
EXT_swap_control_tear_bit);
319
return 0;
320
}
321
}
322
#endif
323
324
LockDisplay(dpy);
325
326
if (priv->minorVersion >= 3) {
327
xGLXGetDrawableAttributesReq *req;
328
329
GetReq(GLXGetDrawableAttributes, req);
330
req->reqType = opcode;
331
req->glxCode = X_GLXGetDrawableAttributes;
332
req->drawable = drawable;
333
}
334
else {
335
xGLXVendorPrivateWithReplyReq *vpreq;
336
337
GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
338
data = (CARD32 *) (vpreq + 1);
339
data[0] = (CARD32) drawable;
340
341
vpreq->reqType = opcode;
342
vpreq->glxCode = X_GLXVendorPrivateWithReply;
343
vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
344
}
345
346
_XReply(dpy, (xReply *) & reply, 0, False);
347
348
if (reply.type == X_Error) {
349
UnlockDisplay(dpy);
350
SyncHandle();
351
return 0;
352
}
353
354
length = reply.length;
355
if (length) {
356
num_attributes = (priv->minorVersion > 2) ? reply.numAttribs : length / 2;
357
data = malloc(length * sizeof(CARD32));
358
if (data == NULL) {
359
/* Throw data on the floor */
360
_XEatData(dpy, length);
361
}
362
else {
363
_XRead(dpy, (char *) data, length * sizeof(CARD32));
364
365
/* Search the set of returned attributes for the attribute requested by
366
* the caller.
367
*/
368
for (i = 0; i < num_attributes; i++) {
369
if (data[i * 2] == attribute) {
370
found = 1;
371
*value = data[(i * 2) + 1];
372
break;
373
}
374
}
375
376
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
377
if (pdraw != NULL) {
378
if (!pdraw->textureTarget)
379
pdraw->textureTarget =
380
determineTextureTarget((const int *) data, num_attributes);
381
if (!pdraw->textureFormat)
382
pdraw->textureFormat =
383
determineTextureFormat((const int *) data, num_attributes);
384
}
385
#endif
386
387
free(data);
388
}
389
}
390
391
UnlockDisplay(dpy);
392
SyncHandle();
393
394
return found;
395
}
396
397
static void
398
protocolDestroyDrawable(Display *dpy, GLXDrawable drawable, CARD32 glxCode)
399
{
400
xGLXDestroyPbufferReq *req;
401
CARD8 opcode;
402
403
opcode = __glXSetupForCommand(dpy);
404
if (!opcode)
405
return;
406
407
LockDisplay(dpy);
408
409
GetReq(GLXDestroyPbuffer, req);
410
req->reqType = opcode;
411
req->glxCode = glxCode;
412
req->pbuffer = (GLXPbuffer) drawable;
413
414
UnlockDisplay(dpy);
415
SyncHandle();
416
}
417
418
/**
419
* Create a non-pbuffer GLX drawable.
420
*/
421
static GLXDrawable
422
CreateDrawable(Display *dpy, struct glx_config *config,
423
Drawable drawable, const int *attrib_list, CARD8 glxCode)
424
{
425
xGLXCreateWindowReq *req;
426
struct glx_drawable *glxDraw;
427
CARD32 *data;
428
unsigned int i;
429
CARD8 opcode;
430
GLXDrawable xid;
431
432
if (!config)
433
return None;
434
435
i = 0;
436
if (attrib_list) {
437
while (attrib_list[i * 2] != None)
438
i++;
439
}
440
441
opcode = __glXSetupForCommand(dpy);
442
if (!opcode)
443
return None;
444
445
glxDraw = malloc(sizeof(*glxDraw));
446
if (!glxDraw)
447
return None;
448
449
LockDisplay(dpy);
450
GetReqExtra(GLXCreateWindow, 8 * i, req);
451
data = (CARD32 *) (req + 1);
452
453
req->reqType = opcode;
454
req->glxCode = glxCode;
455
req->screen = config->screen;
456
req->fbconfig = config->fbconfigID;
457
req->window = drawable;
458
req->glxwindow = xid = XAllocID(dpy);
459
req->numAttribs = i;
460
461
if (attrib_list)
462
memcpy(data, attrib_list, 8 * i);
463
464
UnlockDisplay(dpy);
465
SyncHandle();
466
467
if (InitGLXDrawable(dpy, glxDraw, drawable, xid)) {
468
free(glxDraw);
469
return None;
470
}
471
472
if (!CreateDRIDrawable(dpy, config, drawable, xid, attrib_list, i)) {
473
if (glxCode == X_GLXCreatePixmap)
474
glxCode = X_GLXDestroyPixmap;
475
else
476
glxCode = X_GLXDestroyWindow;
477
protocolDestroyDrawable(dpy, xid, glxCode);
478
xid = None;
479
}
480
481
return xid;
482
}
483
484
485
/**
486
* Destroy a non-pbuffer GLX drawable.
487
*/
488
static void
489
DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode)
490
{
491
if ((dpy == NULL) || (drawable == 0)) {
492
return;
493
}
494
495
protocolDestroyDrawable(dpy, drawable, glxCode);
496
497
DestroyGLXDrawable(dpy, drawable);
498
DestroyDRIDrawable(dpy, drawable, GL_FALSE);
499
500
return;
501
}
502
503
504
/**
505
* Create a pbuffer.
506
*
507
* This function is used to implement \c glXCreatePbuffer and
508
* \c glXCreateGLXPbufferSGIX.
509
*
510
* \note
511
* This function dynamically determines whether to use the SGIX_pbuffer
512
* version of the protocol or the GLX 1.3 version of the protocol.
513
*/
514
static GLXDrawable
515
CreatePbuffer(Display * dpy, struct glx_config *config,
516
unsigned int width, unsigned int height,
517
const int *attrib_list, GLboolean size_in_attribs)
518
{
519
struct glx_display *priv = __glXInitialize(dpy);
520
GLXDrawable id = 0;
521
CARD32 *data;
522
CARD8 opcode;
523
unsigned int i;
524
Pixmap pixmap;
525
GLboolean glx_1_3 = GL_FALSE;
526
int depth = config->rgbBits;
527
528
if (priv == NULL)
529
return None;
530
531
i = 0;
532
if (attrib_list) {
533
while (attrib_list[i * 2])
534
i++;
535
}
536
537
opcode = __glXSetupForCommand(dpy);
538
if (!opcode)
539
return None;
540
541
LockDisplay(dpy);
542
id = XAllocID(dpy);
543
544
if (priv->minorVersion >= 3) {
545
xGLXCreatePbufferReq *req;
546
unsigned int extra = (size_in_attribs) ? 0 : 2;
547
548
glx_1_3 = GL_TRUE;
549
550
GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req);
551
data = (CARD32 *) (req + 1);
552
553
req->reqType = opcode;
554
req->glxCode = X_GLXCreatePbuffer;
555
req->screen = config->screen;
556
req->fbconfig = config->fbconfigID;
557
req->pbuffer = id;
558
req->numAttribs = i + extra;
559
560
if (!size_in_attribs) {
561
data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
562
data[(2 * i) + 1] = width;
563
data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
564
data[(2 * i) + 3] = height;
565
data += 4;
566
}
567
}
568
else {
569
xGLXVendorPrivateReq *vpreq;
570
571
GetReqExtra(GLXVendorPrivate, 20 + (8 * i), vpreq);
572
data = (CARD32 *) (vpreq + 1);
573
574
vpreq->reqType = opcode;
575
vpreq->glxCode = X_GLXVendorPrivate;
576
vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
577
578
data[0] = config->screen;
579
data[1] = config->fbconfigID;
580
data[2] = id;
581
data[3] = width;
582
data[4] = height;
583
data += 5;
584
}
585
586
(void) memcpy(data, attrib_list, sizeof(CARD32) * 2 * i);
587
588
UnlockDisplay(dpy);
589
SyncHandle();
590
591
if (depth == 30)
592
depth = 32;
593
594
pixmap = XCreatePixmap(dpy, RootWindow(dpy, config->screen),
595
width, height, depth);
596
597
if (!CreateDRIDrawable(dpy, config, pixmap, id, attrib_list, i)) {
598
CARD32 o = glx_1_3 ? X_GLXDestroyPbuffer : X_GLXvop_DestroyGLXPbufferSGIX;
599
XFreePixmap(dpy, pixmap);
600
protocolDestroyDrawable(dpy, id, o);
601
id = None;
602
}
603
604
return id;
605
}
606
607
/**
608
* Destroy a pbuffer.
609
*
610
* This function is used to implement \c glXDestroyPbuffer and
611
* \c glXDestroyGLXPbufferSGIX.
612
*
613
* \note
614
* This function dynamically determines whether to use the SGIX_pbuffer
615
* version of the protocol or the GLX 1.3 version of the protocol.
616
*/
617
static void
618
DestroyPbuffer(Display * dpy, GLXDrawable drawable)
619
{
620
struct glx_display *priv = __glXInitialize(dpy);
621
CARD8 opcode;
622
623
if ((priv == NULL) || (dpy == NULL) || (drawable == 0)) {
624
return;
625
}
626
627
opcode = __glXSetupForCommand(dpy);
628
if (!opcode)
629
return;
630
631
LockDisplay(dpy);
632
633
if (priv->minorVersion >= 3) {
634
xGLXDestroyPbufferReq *req;
635
636
GetReq(GLXDestroyPbuffer, req);
637
req->reqType = opcode;
638
req->glxCode = X_GLXDestroyPbuffer;
639
req->pbuffer = (GLXPbuffer) drawable;
640
}
641
else {
642
xGLXVendorPrivateWithReplyReq *vpreq;
643
CARD32 *data;
644
645
GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
646
data = (CARD32 *) (vpreq + 1);
647
648
data[0] = (CARD32) drawable;
649
650
vpreq->reqType = opcode;
651
vpreq->glxCode = X_GLXVendorPrivateWithReply;
652
vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX;
653
}
654
655
UnlockDisplay(dpy);
656
SyncHandle();
657
658
DestroyDRIDrawable(dpy, drawable, GL_TRUE);
659
660
return;
661
}
662
663
/**
664
* Create a new pbuffer.
665
*/
666
_GLX_PUBLIC GLXPbufferSGIX
667
glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config,
668
unsigned int width, unsigned int height,
669
int *attrib_list)
670
{
671
return (GLXPbufferSGIX) CreatePbuffer(dpy, (struct glx_config *) config,
672
width, height,
673
attrib_list, GL_FALSE);
674
}
675
676
#endif /* GLX_USE_APPLEGL */
677
678
/**
679
* Create a new pbuffer.
680
*/
681
_GLX_PUBLIC GLXPbuffer
682
glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list)
683
{
684
int i, width, height;
685
#ifdef GLX_USE_APPLEGL
686
GLXPbuffer result;
687
int errorcode;
688
#endif
689
690
width = 0;
691
height = 0;
692
693
#ifdef GLX_USE_APPLEGL
694
for (i = 0; attrib_list[i]; ++i) {
695
switch (attrib_list[i]) {
696
case GLX_PBUFFER_WIDTH:
697
width = attrib_list[i + 1];
698
++i;
699
break;
700
701
case GLX_PBUFFER_HEIGHT:
702
height = attrib_list[i + 1];
703
++i;
704
break;
705
706
case GLX_LARGEST_PBUFFER:
707
/* This is a hint we should probably handle, but how? */
708
++i;
709
break;
710
711
case GLX_PRESERVED_CONTENTS:
712
/* The contents are always preserved with AppleSGLX with CGL. */
713
++i;
714
break;
715
716
default:
717
return None;
718
}
719
}
720
721
if (apple_glx_pbuffer_create(dpy, config, width, height, &errorcode,
722
&result)) {
723
/*
724
* apple_glx_pbuffer_create only sets the errorcode to core X11
725
* errors.
726
*/
727
__glXSendError(dpy, errorcode, 0, X_GLXCreatePbuffer, true);
728
729
return None;
730
}
731
732
return result;
733
#else
734
for (i = 0; attrib_list[i * 2]; i++) {
735
switch (attrib_list[i * 2]) {
736
case GLX_PBUFFER_WIDTH:
737
width = attrib_list[i * 2 + 1];
738
break;
739
case GLX_PBUFFER_HEIGHT:
740
height = attrib_list[i * 2 + 1];
741
break;
742
}
743
}
744
745
return (GLXPbuffer) CreatePbuffer(dpy, (struct glx_config *) config,
746
width, height, attrib_list, GL_TRUE);
747
#endif
748
}
749
750
751
/**
752
* Destroy an existing pbuffer.
753
*/
754
_GLX_PUBLIC void
755
glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf)
756
{
757
#ifdef GLX_USE_APPLEGL
758
if (apple_glx_pbuffer_destroy(dpy, pbuf)) {
759
__glXSendError(dpy, GLXBadPbuffer, pbuf, X_GLXDestroyPbuffer, false);
760
}
761
#else
762
DestroyPbuffer(dpy, pbuf);
763
#endif
764
}
765
766
767
/**
768
* Query an attribute of a drawable.
769
*/
770
_GLX_PUBLIC void
771
glXQueryDrawable(Display * dpy, GLXDrawable drawable,
772
int attribute, unsigned int *value)
773
{
774
#ifdef GLX_USE_APPLEGL
775
Window root;
776
int x, y;
777
unsigned int width, height, bd, depth;
778
779
if (apple_glx_pixmap_query(drawable, attribute, value))
780
return; /*done */
781
782
if (apple_glx_pbuffer_query(drawable, attribute, value))
783
return; /*done */
784
785
/*
786
* The OpenGL spec states that we should report GLXBadDrawable if
787
* the drawable is invalid, however doing so would require that we
788
* use XSetErrorHandler(), which is known to not be thread safe.
789
* If we use a round-trip call to validate the drawable, there could
790
* be a race, so instead we just opt in favor of letting the
791
* XGetGeometry request fail with a GetGeometry request X error
792
* rather than GLXBadDrawable, in what is hoped to be a rare
793
* case of an invalid drawable. In practice most and possibly all
794
* X11 apps using GLX shouldn't notice a difference.
795
*/
796
if (XGetGeometry
797
(dpy, drawable, &root, &x, &y, &width, &height, &bd, &depth)) {
798
switch (attribute) {
799
case GLX_WIDTH:
800
*value = width;
801
break;
802
803
case GLX_HEIGHT:
804
*value = height;
805
break;
806
}
807
}
808
#else
809
__glXGetDrawableAttribute(dpy, drawable, attribute, value);
810
#endif
811
}
812
813
814
#ifndef GLX_USE_APPLEGL
815
/**
816
* Query an attribute of a pbuffer.
817
*/
818
_GLX_PUBLIC void
819
glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX drawable,
820
int attribute, unsigned int *value)
821
{
822
__glXGetDrawableAttribute(dpy, drawable, attribute, value);
823
}
824
#endif
825
826
/**
827
* Select the event mask for a drawable.
828
*/
829
_GLX_PUBLIC void
830
glXSelectEvent(Display * dpy, GLXDrawable drawable, unsigned long mask)
831
{
832
#ifdef GLX_USE_APPLEGL
833
XWindowAttributes xwattr;
834
835
if (apple_glx_pbuffer_set_event_mask(drawable, mask))
836
return; /*done */
837
838
/*
839
* The spec allows a window, but currently there are no valid
840
* events for a window, so do nothing.
841
*/
842
if (XGetWindowAttributes(dpy, drawable, &xwattr))
843
return; /*done */
844
/* The drawable seems to be invalid. Report an error. */
845
846
__glXSendError(dpy, GLXBadDrawable, drawable,
847
X_GLXChangeDrawableAttributes, false);
848
#else
849
CARD32 attribs[2];
850
851
attribs[0] = (CARD32) GLX_EVENT_MASK;
852
attribs[1] = (CARD32) mask;
853
854
ChangeDrawableAttribute(dpy, drawable, attribs, 1);
855
#endif
856
}
857
858
859
/**
860
* Get the selected event mask for a drawable.
861
*/
862
_GLX_PUBLIC void
863
glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask)
864
{
865
#ifdef GLX_USE_APPLEGL
866
XWindowAttributes xwattr;
867
868
if (apple_glx_pbuffer_get_event_mask(drawable, mask))
869
return; /*done */
870
871
/*
872
* The spec allows a window, but currently there are no valid
873
* events for a window, so do nothing, but set the mask to 0.
874
*/
875
if (XGetWindowAttributes(dpy, drawable, &xwattr)) {
876
/* The window is valid, so set the mask to 0. */
877
*mask = 0;
878
return; /*done */
879
}
880
/* The drawable seems to be invalid. Report an error. */
881
882
__glXSendError(dpy, GLXBadDrawable, drawable, X_GLXGetDrawableAttributes,
883
true);
884
#else
885
unsigned int value = 0;
886
887
888
/* The non-sense with value is required because on LP64 platforms
889
* sizeof(unsigned int) != sizeof(unsigned long). On little-endian
890
* we could just type-cast the pointer, but why?
891
*/
892
893
__glXGetDrawableAttribute(dpy, drawable, GLX_EVENT_MASK_SGIX, &value);
894
*mask = value;
895
#endif
896
}
897
898
899
_GLX_PUBLIC GLXPixmap
900
glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap,
901
const int *attrib_list)
902
{
903
#ifdef GLX_USE_APPLEGL
904
const struct glx_config *modes = (const struct glx_config *) config;
905
906
if (apple_glx_pixmap_create(dpy, modes->screen, pixmap, modes))
907
return None;
908
909
return pixmap;
910
#else
911
return CreateDrawable(dpy, (struct glx_config *) config,
912
(Drawable) pixmap, attrib_list, X_GLXCreatePixmap);
913
#endif
914
}
915
916
917
_GLX_PUBLIC GLXWindow
918
glXCreateWindow(Display * dpy, GLXFBConfig config, Window win,
919
const int *attrib_list)
920
{
921
#ifdef GLX_USE_APPLEGL
922
XWindowAttributes xwattr;
923
XVisualInfo *visinfo;
924
925
(void) attrib_list; /*unused according to GLX 1.4 */
926
927
XGetWindowAttributes(dpy, win, &xwattr);
928
929
visinfo = glXGetVisualFromFBConfig(dpy, config);
930
931
if (NULL == visinfo) {
932
__glXSendError(dpy, GLXBadFBConfig, 0, X_GLXCreateWindow, false);
933
return None;
934
}
935
936
if (visinfo->visualid != XVisualIDFromVisual(xwattr.visual)) {
937
__glXSendError(dpy, BadMatch, 0, X_GLXCreateWindow, true);
938
return None;
939
}
940
941
free(visinfo);
942
943
return win;
944
#else
945
return CreateDrawable(dpy, (struct glx_config *) config,
946
(Drawable) win, attrib_list, X_GLXCreateWindow);
947
#endif
948
}
949
950
951
_GLX_PUBLIC void
952
glXDestroyPixmap(Display * dpy, GLXPixmap pixmap)
953
{
954
#ifdef GLX_USE_APPLEGL
955
if (apple_glx_pixmap_destroy(dpy, pixmap))
956
__glXSendError(dpy, GLXBadPixmap, pixmap, X_GLXDestroyPixmap, false);
957
#else
958
DestroyDrawable(dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap);
959
#endif
960
}
961
962
963
_GLX_PUBLIC void
964
glXDestroyWindow(Display * dpy, GLXWindow win)
965
{
966
#ifndef GLX_USE_APPLEGL
967
DestroyDrawable(dpy, (GLXDrawable) win, X_GLXDestroyWindow);
968
#endif
969
}
970
971
_GLX_PUBLIC
972
GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
973
(Display * dpy, GLXPbufferSGIX pbuf),
974
(dpy, pbuf), glXDestroyPbuffer)
975
976
_GLX_PUBLIC
977
GLX_ALIAS_VOID(glXSelectEventSGIX,
978
(Display * dpy, GLXDrawable drawable,
979
unsigned long mask), (dpy, drawable, mask), glXSelectEvent)
980
981
_GLX_PUBLIC
982
GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
983
(Display * dpy, GLXDrawable drawable,
984
unsigned long *mask), (dpy, drawable, mask),
985
glXGetSelectedEvent)
986
987