/* * Copyright © 2011 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include "glxclient.h" #include "glx_error.h" #include #include #include #if INT_MAX != 2147483647 #error This code requires sizeof(uint32_t) == sizeof(int). #endif /* An "Atrribs/Attribs" typo was fixed in glxproto.h in Nov 2014. * This is in case we don't have the updated header. */ #if !defined(X_GLXCreateContextAttribsARB) && \ defined(X_GLXCreateContextAtrribsARB) #define X_GLXCreateContextAttribsARB X_GLXCreateContextAtrribsARB #endif _X_HIDDEN GLXContext glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list) { xcb_connection_t *const c = XGetXCBConnection(dpy); struct glx_config *const cfg = (struct glx_config *) config; struct glx_context *const share = (struct glx_context *) share_context; struct glx_context *gc = NULL; unsigned num_attribs = 0; struct glx_screen *psc; xcb_generic_error_t *err; xcb_void_cookie_t cookie; unsigned dummy_err = 0; uint32_t xid, share_xid; int screen = -1; if (dpy == NULL) return NULL; /* Count the number of attributes specified by the application. All * attributes appear in pairs, except the terminating None. */ if (attrib_list != NULL) { for (/* empty */; attrib_list[num_attribs * 2] != 0; num_attribs++) /* empty */ ; } if (cfg) { screen = cfg->screen; } else { for (unsigned int i = 0; i < num_attribs; i++) { if (attrib_list[i * 2] == GLX_SCREEN) screen = attrib_list[i * 2 + 1]; } if (screen == -1) { __glXSendError(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True); return NULL; } } /* This means that either the caller passed the wrong display pointer or * one of the internal GLX data structures (probably the fbconfig) has an * error. There is nothing sensible to do, so return an error. */ psc = GetGLXScreenConfigs(dpy, screen); if (psc == NULL) return NULL; assert(screen == psc->scr); /* Some application may request an indirect context but we may want to force a direct * one because Xorg only allows indirect contexts if they were enabled. */ if (!direct && psc->force_direct_context) { direct = true; } if (direct && psc->vtable->create_context_attribs) { /* GLX drops the error returned by the driver. The expectation is that * an error will also be returned by the server. The server's error * will be delivered to the application. */ gc = psc->vtable->create_context_attribs(psc, cfg, share, num_attribs, (const uint32_t *) attrib_list, &dummy_err); } if (gc == NULL) { #ifdef GLX_USE_APPLEGL gc = applegl_create_context(psc, cfg, share, 0); #else gc = indirect_create_context_attribs(psc, cfg, share, num_attribs, (const uint32_t *) attrib_list, &dummy_err); #endif } xid = xcb_generate_id(c); share_xid = (share != NULL) ? share->xid : 0; /* The manual pages for glXCreateContext and glXCreateNewContext say: * * "NULL is returned if execution fails on the client side." * * If the server generates an error, the application is supposed to catch * the protocol error and handle it. Part of handling the error is freeing * the possibly non-NULL value returned by this function. */ cookie = xcb_glx_create_context_attribs_arb_checked(c, xid, cfg ? cfg->fbconfigID : 0, screen, share_xid, gc ? gc->isDirect : direct, num_attribs, (const uint32_t *) attrib_list); err = xcb_request_check(c, cookie); if (err != NULL) { if (gc) gc->vtable->destroy(gc); gc = NULL; __glXSendErrorForXcb(dpy, err); free(err); } else if (!gc) { /* the server thought the context description was okay, but we failed * somehow on the client side. clean up the server resource and panic. */ xcb_glx_destroy_context(c, xid); /* increment dpy->request in order to give a unique serial number to the * error */ XNoOp(dpy); __glXSendError(dpy, GLXBadFBConfig, xid, 0, False); } else { gc->xid = xid; gc->share_xid = share_xid; } return (GLXContext) gc; }