/*1* Copyright © 2011 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER20* DEALINGS IN THE SOFTWARE.21*/2223#include <limits.h>24#include "glxclient.h"25#include "glx_error.h"26#include <xcb/glx.h>27#include <X11/Xlib-xcb.h>2829#include <assert.h>3031#if INT_MAX != 214748364732#error This code requires sizeof(uint32_t) == sizeof(int).33#endif3435/* An "Atrribs/Attribs" typo was fixed in glxproto.h in Nov 2014.36* This is in case we don't have the updated header.37*/38#if !defined(X_GLXCreateContextAttribsARB) && \39defined(X_GLXCreateContextAtrribsARB)40#define X_GLXCreateContextAttribsARB X_GLXCreateContextAtrribsARB41#endif4243_X_HIDDEN GLXContext44glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config,45GLXContext share_context, Bool direct,46const int *attrib_list)47{48xcb_connection_t *const c = XGetXCBConnection(dpy);49struct glx_config *const cfg = (struct glx_config *) config;50struct glx_context *const share = (struct glx_context *) share_context;51struct glx_context *gc = NULL;52unsigned num_attribs = 0;53struct glx_screen *psc;54xcb_generic_error_t *err;55xcb_void_cookie_t cookie;56unsigned dummy_err = 0;57uint32_t xid, share_xid;58int screen = -1;5960if (dpy == NULL)61return NULL;6263/* Count the number of attributes specified by the application. All64* attributes appear in pairs, except the terminating None.65*/66if (attrib_list != NULL) {67for (/* empty */; attrib_list[num_attribs * 2] != 0; num_attribs++)68/* empty */ ;69}7071if (cfg) {72screen = cfg->screen;73} else {74for (unsigned int i = 0; i < num_attribs; i++) {75if (attrib_list[i * 2] == GLX_SCREEN)76screen = attrib_list[i * 2 + 1];77}78if (screen == -1) {79__glXSendError(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True);80return NULL;81}82}8384/* This means that either the caller passed the wrong display pointer or85* one of the internal GLX data structures (probably the fbconfig) has an86* error. There is nothing sensible to do, so return an error.87*/88psc = GetGLXScreenConfigs(dpy, screen);89if (psc == NULL)90return NULL;9192assert(screen == psc->scr);9394if (direct && psc->vtable->create_context_attribs) {95/* GLX drops the error returned by the driver. The expectation is that96* an error will also be returned by the server. The server's error97* will be delivered to the application.98*/99gc = psc->vtable->create_context_attribs(psc, cfg, share, num_attribs,100(const uint32_t *) attrib_list,101&dummy_err);102}103104if (gc == NULL) {105#ifdef GLX_USE_APPLEGL106gc = applegl_create_context(psc, cfg, share, 0);107#else108gc = indirect_create_context_attribs(psc, cfg, share, num_attribs,109(const uint32_t *) attrib_list,110&dummy_err);111#endif112}113114xid = xcb_generate_id(c);115share_xid = (share != NULL) ? share->xid : 0;116117/* The manual pages for glXCreateContext and glXCreateNewContext say:118*119* "NULL is returned if execution fails on the client side."120*121* If the server generates an error, the application is supposed to catch122* the protocol error and handle it. Part of handling the error is freeing123* the possibly non-NULL value returned by this function.124*/125cookie =126xcb_glx_create_context_attribs_arb_checked(c,127xid,128cfg ? cfg->fbconfigID : 0,129screen,130share_xid,131gc ? gc->isDirect : direct,132num_attribs,133(const uint32_t *)134attrib_list);135err = xcb_request_check(c, cookie);136if (err != NULL) {137if (gc)138gc->vtable->destroy(gc);139gc = NULL;140141__glXSendErrorForXcb(dpy, err);142free(err);143} else if (!gc) {144/* the server thought the context description was okay, but we failed145* somehow on the client side. clean up the server resource and panic.146*/147xcb_glx_destroy_context(c, xid);148/* increment dpy->request in order to give a unique serial number to the149* error */150XNoOp(dpy);151__glXSendError(dpy, GLXBadFBConfig, xid, 0, False);152} else {153gc->xid = xid;154gc->share_xid = share_xid;155}156157return (GLXContext) gc;158}159160161