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