Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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