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