Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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