xref: /aosp_15_r20/external/mesa3d/src/glx/dri_common.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
3*61046927SAndroid Build Coastguard Worker  * Copyright © 2008 Red Hat, Inc.
4*61046927SAndroid Build Coastguard Worker  *
5*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
6*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Soft-
7*61046927SAndroid Build Coastguard Worker  * ware"), to deal in the Software without restriction, including without
8*61046927SAndroid Build Coastguard Worker  * limitation the rights to use, copy, modify, merge, publish, distribute,
9*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
10*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, provided that the above copyright
11*61046927SAndroid Build Coastguard Worker  * notice(s) and this permission notice appear in all copies of the Soft-
12*61046927SAndroid Build Coastguard Worker  * ware and that both the above copyright notice(s) and this permission
13*61046927SAndroid Build Coastguard Worker  * notice appear in supporting documentation.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16*61046927SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
17*61046927SAndroid Build Coastguard Worker  * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
18*61046927SAndroid Build Coastguard Worker  * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
19*61046927SAndroid Build Coastguard Worker  * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
20*61046927SAndroid Build Coastguard Worker  * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21*61046927SAndroid Build Coastguard Worker  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22*61046927SAndroid Build Coastguard Worker  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
23*61046927SAndroid Build Coastguard Worker  * MANCE OF THIS SOFTWARE.
24*61046927SAndroid Build Coastguard Worker  *
25*61046927SAndroid Build Coastguard Worker  * Except as contained in this notice, the name of a copyright holder shall
26*61046927SAndroid Build Coastguard Worker  * not be used in advertising or otherwise to promote the sale, use or
27*61046927SAndroid Build Coastguard Worker  * other dealings in this Software without prior written authorization of
28*61046927SAndroid Build Coastguard Worker  * the copyright holder.
29*61046927SAndroid Build Coastguard Worker  *
30*61046927SAndroid Build Coastguard Worker  * Authors:
31*61046927SAndroid Build Coastguard Worker  *   Kevin E. Martin <[email protected]>
32*61046927SAndroid Build Coastguard Worker  *   Brian Paul <[email protected]>
33*61046927SAndroid Build Coastguard Worker  *   Kristian Høgsberg ([email protected])
34*61046927SAndroid Build Coastguard Worker  */
35*61046927SAndroid Build Coastguard Worker 
36*61046927SAndroid Build Coastguard Worker #if defined(GLX_DIRECT_RENDERING) && (!defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE))
37*61046927SAndroid Build Coastguard Worker 
38*61046927SAndroid Build Coastguard Worker #include <unistd.h>
39*61046927SAndroid Build Coastguard Worker #include <dlfcn.h>
40*61046927SAndroid Build Coastguard Worker #include <stdarg.h>
41*61046927SAndroid Build Coastguard Worker #include "glxclient.h"
42*61046927SAndroid Build Coastguard Worker #include "dri_common.h"
43*61046927SAndroid Build Coastguard Worker #include "loader.h"
44*61046927SAndroid Build Coastguard Worker #include <X11/Xlib-xcb.h>
45*61046927SAndroid Build Coastguard Worker #include <xcb/xproto.h>
46*61046927SAndroid Build Coastguard Worker #include "dri_util.h"
47*61046927SAndroid Build Coastguard Worker #include "pipe-loader/pipe_loader.h"
48*61046927SAndroid Build Coastguard Worker 
49*61046927SAndroid Build Coastguard Worker #define __ATTRIB(attrib, field) \
50*61046927SAndroid Build Coastguard Worker     { attrib, offsetof(struct glx_config, field) }
51*61046927SAndroid Build Coastguard Worker 
52*61046927SAndroid Build Coastguard Worker static const struct
53*61046927SAndroid Build Coastguard Worker {
54*61046927SAndroid Build Coastguard Worker    unsigned int attrib, offset;
55*61046927SAndroid Build Coastguard Worker } attribMap[] = {
56*61046927SAndroid Build Coastguard Worker    __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits),
57*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_LEVEL, level),
58*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits),
59*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits),
60*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits),
61*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits),
62*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits),
63*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits),
64*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits),
65*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits),
66*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits),
67*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits),
68*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers),
69*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_SAMPLES, samples),
70*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode),
71*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode),
72*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers),
73*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb),
74*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba),
75*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture),
76*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),
77*61046927SAndroid Build Coastguard Worker       __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable)
78*61046927SAndroid Build Coastguard Worker };
79*61046927SAndroid Build Coastguard Worker 
80*61046927SAndroid Build Coastguard Worker static int
scalarEqual(struct glx_config * mode,unsigned int attrib,unsigned int value)81*61046927SAndroid Build Coastguard Worker scalarEqual(struct glx_config *mode, unsigned int attrib, unsigned int value)
82*61046927SAndroid Build Coastguard Worker {
83*61046927SAndroid Build Coastguard Worker    unsigned glxValue, i;
84*61046927SAndroid Build Coastguard Worker 
85*61046927SAndroid Build Coastguard Worker    for (i = 0; i < ARRAY_SIZE(attribMap); i++)
86*61046927SAndroid Build Coastguard Worker       if (attribMap[i].attrib == attrib) {
87*61046927SAndroid Build Coastguard Worker          glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset);
88*61046927SAndroid Build Coastguard Worker          return glxValue == GLX_DONT_CARE || glxValue == value;
89*61046927SAndroid Build Coastguard Worker       }
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker    return GL_TRUE;              /* Is a non-existing attribute equal to value? */
92*61046927SAndroid Build Coastguard Worker }
93*61046927SAndroid Build Coastguard Worker 
94*61046927SAndroid Build Coastguard Worker static int
driConfigEqual(struct glx_config * config,const __DRIconfig * driConfig)95*61046927SAndroid Build Coastguard Worker driConfigEqual(struct glx_config *config, const __DRIconfig *driConfig)
96*61046927SAndroid Build Coastguard Worker {
97*61046927SAndroid Build Coastguard Worker    unsigned int attrib, value, glxValue;
98*61046927SAndroid Build Coastguard Worker    int i;
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker    i = 0;
101*61046927SAndroid Build Coastguard Worker    while (driIndexConfigAttrib(driConfig, i++, &attrib, &value)) {
102*61046927SAndroid Build Coastguard Worker       switch (attrib) {
103*61046927SAndroid Build Coastguard Worker       case __DRI_ATTRIB_RENDER_TYPE:
104*61046927SAndroid Build Coastguard Worker          glxValue = 0;
105*61046927SAndroid Build Coastguard Worker          if (value & __DRI_ATTRIB_RGBA_BIT) {
106*61046927SAndroid Build Coastguard Worker             glxValue |= GLX_RGBA_BIT;
107*61046927SAndroid Build Coastguard Worker          }
108*61046927SAndroid Build Coastguard Worker          if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) {
109*61046927SAndroid Build Coastguard Worker             glxValue |= GLX_COLOR_INDEX_BIT;
110*61046927SAndroid Build Coastguard Worker          }
111*61046927SAndroid Build Coastguard Worker          if (value & __DRI_ATTRIB_FLOAT_BIT) {
112*61046927SAndroid Build Coastguard Worker             glxValue |= GLX_RGBA_FLOAT_BIT_ARB;
113*61046927SAndroid Build Coastguard Worker          }
114*61046927SAndroid Build Coastguard Worker          if (value & __DRI_ATTRIB_UNSIGNED_FLOAT_BIT) {
115*61046927SAndroid Build Coastguard Worker             glxValue |= GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT;
116*61046927SAndroid Build Coastguard Worker          }
117*61046927SAndroid Build Coastguard Worker          if (glxValue != config->renderType)
118*61046927SAndroid Build Coastguard Worker             return GL_FALSE;
119*61046927SAndroid Build Coastguard Worker          break;
120*61046927SAndroid Build Coastguard Worker 
121*61046927SAndroid Build Coastguard Worker       case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS:
122*61046927SAndroid Build Coastguard Worker          glxValue = 0;
123*61046927SAndroid Build Coastguard Worker          if (value & __DRI_ATTRIB_TEXTURE_1D_BIT)
124*61046927SAndroid Build Coastguard Worker             glxValue |= GLX_TEXTURE_1D_BIT_EXT;
125*61046927SAndroid Build Coastguard Worker          if (value & __DRI_ATTRIB_TEXTURE_2D_BIT)
126*61046927SAndroid Build Coastguard Worker             glxValue |= GLX_TEXTURE_2D_BIT_EXT;
127*61046927SAndroid Build Coastguard Worker          if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT)
128*61046927SAndroid Build Coastguard Worker             glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT;
129*61046927SAndroid Build Coastguard Worker          if (config->bindToTextureTargets != GLX_DONT_CARE &&
130*61046927SAndroid Build Coastguard Worker              glxValue != config->bindToTextureTargets)
131*61046927SAndroid Build Coastguard Worker             return GL_FALSE;
132*61046927SAndroid Build Coastguard Worker          break;
133*61046927SAndroid Build Coastguard Worker 
134*61046927SAndroid Build Coastguard Worker       /* Nerf some attributes we can safely ignore if the server claims to
135*61046927SAndroid Build Coastguard Worker        * support them but the driver does not.
136*61046927SAndroid Build Coastguard Worker        */
137*61046927SAndroid Build Coastguard Worker       case __DRI_ATTRIB_CONFIG_CAVEAT:
138*61046927SAndroid Build Coastguard Worker          if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
139*61046927SAndroid Build Coastguard Worker             glxValue = GLX_NON_CONFORMANT_CONFIG;
140*61046927SAndroid Build Coastguard Worker          else if (value & __DRI_ATTRIB_SLOW_BIT)
141*61046927SAndroid Build Coastguard Worker             glxValue = GLX_SLOW_CONFIG;
142*61046927SAndroid Build Coastguard Worker          else
143*61046927SAndroid Build Coastguard Worker             glxValue = GLX_NONE;
144*61046927SAndroid Build Coastguard Worker          if (glxValue != config->visualRating) {
145*61046927SAndroid Build Coastguard Worker             if (config->visualRating == GLX_NONE) {
146*61046927SAndroid Build Coastguard Worker                static int warned;
147*61046927SAndroid Build Coastguard Worker                if (!warned) {
148*61046927SAndroid Build Coastguard Worker                   DebugMessageF("Not downgrading visual rating\n");
149*61046927SAndroid Build Coastguard Worker                   warned = 1;
150*61046927SAndroid Build Coastguard Worker                }
151*61046927SAndroid Build Coastguard Worker             } else {
152*61046927SAndroid Build Coastguard Worker                return GL_FALSE;
153*61046927SAndroid Build Coastguard Worker             }
154*61046927SAndroid Build Coastguard Worker          }
155*61046927SAndroid Build Coastguard Worker          break;
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker       case __DRI_ATTRIB_AUX_BUFFERS:
158*61046927SAndroid Build Coastguard Worker          if (!scalarEqual(config, attrib, value)) {
159*61046927SAndroid Build Coastguard Worker             static int warned;
160*61046927SAndroid Build Coastguard Worker             if (!warned) {
161*61046927SAndroid Build Coastguard Worker                DebugMessageF("Disabling server's aux buffer support\n");
162*61046927SAndroid Build Coastguard Worker                warned = 1;
163*61046927SAndroid Build Coastguard Worker             }
164*61046927SAndroid Build Coastguard Worker             config->numAuxBuffers = 0;
165*61046927SAndroid Build Coastguard Worker          }
166*61046927SAndroid Build Coastguard Worker          break;
167*61046927SAndroid Build Coastguard Worker 
168*61046927SAndroid Build Coastguard Worker       case __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE:
169*61046927SAndroid Build Coastguard Worker          if (!scalarEqual(config, attrib, value)) {
170*61046927SAndroid Build Coastguard Worker             static int warned;
171*61046927SAndroid Build Coastguard Worker             if (!warned) {
172*61046927SAndroid Build Coastguard Worker                DebugMessageF("Disabling server's tfp mipmap support\n");
173*61046927SAndroid Build Coastguard Worker                warned = 1;
174*61046927SAndroid Build Coastguard Worker             }
175*61046927SAndroid Build Coastguard Worker             config->bindToMipmapTexture = 0;
176*61046927SAndroid Build Coastguard Worker          }
177*61046927SAndroid Build Coastguard Worker          break;
178*61046927SAndroid Build Coastguard Worker 
179*61046927SAndroid Build Coastguard Worker       default:
180*61046927SAndroid Build Coastguard Worker          if (!scalarEqual(config, attrib, value))
181*61046927SAndroid Build Coastguard Worker             return GL_FALSE;
182*61046927SAndroid Build Coastguard Worker       }
183*61046927SAndroid Build Coastguard Worker    }
184*61046927SAndroid Build Coastguard Worker 
185*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
186*61046927SAndroid Build Coastguard Worker }
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker static struct glx_config *
createDriMode(struct glx_config * config,const __DRIconfig ** driConfigs)189*61046927SAndroid Build Coastguard Worker createDriMode(struct glx_config *config, const __DRIconfig **driConfigs)
190*61046927SAndroid Build Coastguard Worker {
191*61046927SAndroid Build Coastguard Worker    __GLXDRIconfigPrivate *driConfig;
192*61046927SAndroid Build Coastguard Worker    int i;
193*61046927SAndroid Build Coastguard Worker 
194*61046927SAndroid Build Coastguard Worker    for (i = 0; driConfigs[i]; i++) {
195*61046927SAndroid Build Coastguard Worker       if (driConfigEqual(config, driConfigs[i]))
196*61046927SAndroid Build Coastguard Worker          break;
197*61046927SAndroid Build Coastguard Worker    }
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker    if (driConfigs[i] == NULL)
200*61046927SAndroid Build Coastguard Worker       return NULL;
201*61046927SAndroid Build Coastguard Worker 
202*61046927SAndroid Build Coastguard Worker    driConfig = malloc(sizeof *driConfig);
203*61046927SAndroid Build Coastguard Worker    if (driConfig == NULL)
204*61046927SAndroid Build Coastguard Worker       return NULL;
205*61046927SAndroid Build Coastguard Worker 
206*61046927SAndroid Build Coastguard Worker    driConfig->base = *config;
207*61046927SAndroid Build Coastguard Worker    driConfig->driConfig = driConfigs[i];
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker    return &driConfig->base;
210*61046927SAndroid Build Coastguard Worker }
211*61046927SAndroid Build Coastguard Worker 
212*61046927SAndroid Build Coastguard Worker _X_HIDDEN struct glx_config *
driConvertConfigs(struct glx_config * configs,const __DRIconfig ** driConfigs)213*61046927SAndroid Build Coastguard Worker driConvertConfigs(struct glx_config *configs, const __DRIconfig **driConfigs)
214*61046927SAndroid Build Coastguard Worker {
215*61046927SAndroid Build Coastguard Worker    struct glx_config head, *tail, *m;
216*61046927SAndroid Build Coastguard Worker 
217*61046927SAndroid Build Coastguard Worker    tail = &head;
218*61046927SAndroid Build Coastguard Worker    head.next = NULL;
219*61046927SAndroid Build Coastguard Worker    for (m = configs; m; m = m->next) {
220*61046927SAndroid Build Coastguard Worker       tail->next = createDriMode(m, driConfigs);
221*61046927SAndroid Build Coastguard Worker       if (tail->next == NULL) {
222*61046927SAndroid Build Coastguard Worker          /* no matching dri config for m */
223*61046927SAndroid Build Coastguard Worker          continue;
224*61046927SAndroid Build Coastguard Worker       }
225*61046927SAndroid Build Coastguard Worker 
226*61046927SAndroid Build Coastguard Worker 
227*61046927SAndroid Build Coastguard Worker       tail = tail->next;
228*61046927SAndroid Build Coastguard Worker    }
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker    return head.next;
231*61046927SAndroid Build Coastguard Worker }
232*61046927SAndroid Build Coastguard Worker 
233*61046927SAndroid Build Coastguard Worker _X_HIDDEN void
driDestroyConfigs(const __DRIconfig ** configs)234*61046927SAndroid Build Coastguard Worker driDestroyConfigs(const __DRIconfig **configs)
235*61046927SAndroid Build Coastguard Worker {
236*61046927SAndroid Build Coastguard Worker    int i;
237*61046927SAndroid Build Coastguard Worker 
238*61046927SAndroid Build Coastguard Worker    for (i = 0; configs[i]; i++)
239*61046927SAndroid Build Coastguard Worker       free((__DRIconfig *) configs[i]);
240*61046927SAndroid Build Coastguard Worker    free(configs);
241*61046927SAndroid Build Coastguard Worker }
242*61046927SAndroid Build Coastguard Worker 
243*61046927SAndroid Build Coastguard Worker static struct glx_config *
driInferDrawableConfig(struct glx_screen * psc,GLXDrawable draw)244*61046927SAndroid Build Coastguard Worker driInferDrawableConfig(struct glx_screen *psc, GLXDrawable draw)
245*61046927SAndroid Build Coastguard Worker {
246*61046927SAndroid Build Coastguard Worker    unsigned int fbconfig = 0;
247*61046927SAndroid Build Coastguard Worker    xcb_get_window_attributes_cookie_t cookie = { 0 };
248*61046927SAndroid Build Coastguard Worker    xcb_get_window_attributes_reply_t *attr = NULL;
249*61046927SAndroid Build Coastguard Worker    xcb_connection_t *conn = XGetXCBConnection(psc->dpy);
250*61046927SAndroid Build Coastguard Worker 
251*61046927SAndroid Build Coastguard Worker    /* In practice here, either the XID is a bare Window or it was created
252*61046927SAndroid Build Coastguard Worker     * by some other client. First let's see if the X server can tell us
253*61046927SAndroid Build Coastguard Worker     * the answer. Xorg first added GLX_EXT_no_config_context in 1.20, where
254*61046927SAndroid Build Coastguard Worker     * this usually works except for bare Windows that haven't been made
255*61046927SAndroid Build Coastguard Worker     * current yet.
256*61046927SAndroid Build Coastguard Worker     */
257*61046927SAndroid Build Coastguard Worker    if (__glXGetDrawableAttribute(psc->dpy, draw, GLX_FBCONFIG_ID, &fbconfig)) {
258*61046927SAndroid Build Coastguard Worker       return glx_config_find_fbconfig(psc->configs, fbconfig);
259*61046927SAndroid Build Coastguard Worker    }
260*61046927SAndroid Build Coastguard Worker 
261*61046927SAndroid Build Coastguard Worker    /* Well this had better be a Window then. Figure out its visual and
262*61046927SAndroid Build Coastguard Worker     * then find the corresponding GLX visual.
263*61046927SAndroid Build Coastguard Worker     */
264*61046927SAndroid Build Coastguard Worker    cookie = xcb_get_window_attributes(conn, draw);
265*61046927SAndroid Build Coastguard Worker    attr = xcb_get_window_attributes_reply(conn, cookie, NULL);
266*61046927SAndroid Build Coastguard Worker 
267*61046927SAndroid Build Coastguard Worker    if (attr) {
268*61046927SAndroid Build Coastguard Worker       uint32_t vid = attr->visual;
269*61046927SAndroid Build Coastguard Worker       free(attr);
270*61046927SAndroid Build Coastguard Worker       return glx_config_find_visual(psc->visuals, vid);
271*61046927SAndroid Build Coastguard Worker    }
272*61046927SAndroid Build Coastguard Worker 
273*61046927SAndroid Build Coastguard Worker    return NULL;
274*61046927SAndroid Build Coastguard Worker }
275*61046927SAndroid Build Coastguard Worker 
276*61046927SAndroid Build Coastguard Worker _X_HIDDEN __GLXDRIdrawable *
driFetchDrawable(struct glx_context * gc,GLXDrawable glxDrawable)277*61046927SAndroid Build Coastguard Worker driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable)
278*61046927SAndroid Build Coastguard Worker {
279*61046927SAndroid Build Coastguard Worker    Display *dpy = gc->psc->dpy;
280*61046927SAndroid Build Coastguard Worker    struct glx_display *const priv = __glXInitialize(dpy);
281*61046927SAndroid Build Coastguard Worker    __GLXDRIdrawable *pdraw;
282*61046927SAndroid Build Coastguard Worker    struct glx_screen *psc = gc->psc;
283*61046927SAndroid Build Coastguard Worker    struct glx_config *config = gc->config;
284*61046927SAndroid Build Coastguard Worker    unsigned int type;
285*61046927SAndroid Build Coastguard Worker 
286*61046927SAndroid Build Coastguard Worker    if (priv == NULL)
287*61046927SAndroid Build Coastguard Worker       return NULL;
288*61046927SAndroid Build Coastguard Worker 
289*61046927SAndroid Build Coastguard Worker    if (glxDrawable == None)
290*61046927SAndroid Build Coastguard Worker       return NULL;
291*61046927SAndroid Build Coastguard Worker 
292*61046927SAndroid Build Coastguard Worker    if (priv->drawHash == NULL)
293*61046927SAndroid Build Coastguard Worker       return NULL;
294*61046927SAndroid Build Coastguard Worker 
295*61046927SAndroid Build Coastguard Worker    if (__glxHashLookup(priv->drawHash, glxDrawable, (void *) &pdraw) == 0) {
296*61046927SAndroid Build Coastguard Worker       /* Resurrected, so remove from the alive-query-set if exist. */
297*61046927SAndroid Build Coastguard Worker       _mesa_set_remove_key(priv->zombieGLXDrawable, pdraw);
298*61046927SAndroid Build Coastguard Worker 
299*61046927SAndroid Build Coastguard Worker       pdraw->refcount ++;
300*61046927SAndroid Build Coastguard Worker       return pdraw;
301*61046927SAndroid Build Coastguard Worker    }
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker    /* if this is a no-config context, infer the fbconfig from the drawable */
304*61046927SAndroid Build Coastguard Worker    if (config == NULL)
305*61046927SAndroid Build Coastguard Worker       config = driInferDrawableConfig(psc, glxDrawable);
306*61046927SAndroid Build Coastguard Worker    if (config == NULL)
307*61046927SAndroid Build Coastguard Worker       return NULL;
308*61046927SAndroid Build Coastguard Worker 
309*61046927SAndroid Build Coastguard Worker    /* We can't find this GLX drawable above because it's either:
310*61046927SAndroid Build Coastguard Worker     *
311*61046927SAndroid Build Coastguard Worker     * 1. An X window ID instead of a GLX window ID. This could happend when
312*61046927SAndroid Build Coastguard Worker     *    glXMakeCurrent() is passed an X window directly instead of creating
313*61046927SAndroid Build Coastguard Worker     *    GLXWindow with glXCreateWindow() first.
314*61046927SAndroid Build Coastguard Worker     *
315*61046927SAndroid Build Coastguard Worker     * 2. A GLXPbuffer created on other display:
316*61046927SAndroid Build Coastguard Worker     *
317*61046927SAndroid Build Coastguard Worker     *    From the GLX spec:
318*61046927SAndroid Build Coastguard Worker     *
319*61046927SAndroid Build Coastguard Worker     *      Like other drawable types, GLXPbuffers are shared; any client which
320*61046927SAndroid Build Coastguard Worker     *      knows the associated XID can use a GLXPbuffer.
321*61046927SAndroid Build Coastguard Worker     *
322*61046927SAndroid Build Coastguard Worker     *    So client other than the creator of this GLXPbuffer could use its
323*61046927SAndroid Build Coastguard Worker     *    XID to do something like glXMakeCurrent(). I can't find explicite
324*61046927SAndroid Build Coastguard Worker     *    statement in GLX spec that also allow GLXWindow and GLXPixmap.
325*61046927SAndroid Build Coastguard Worker     *
326*61046927SAndroid Build Coastguard Worker     *    But even GLXWindow and GLXPixmap is allowed, currently client other
327*61046927SAndroid Build Coastguard Worker     *    than the GLX drawable creator has no way to find which X drawable
328*61046927SAndroid Build Coastguard Worker     *    (window or pixmap) this GLX drawable uses, except the GLXPbuffer
329*61046927SAndroid Build Coastguard Worker     *    case which use the same XID for both X pixmap and GLX drawable.
330*61046927SAndroid Build Coastguard Worker     */
331*61046927SAndroid Build Coastguard Worker 
332*61046927SAndroid Build Coastguard Worker    /* Infer the GLX drawable type. */
333*61046927SAndroid Build Coastguard Worker    if (__glXGetDrawableAttribute(dpy, glxDrawable, GLX_DRAWABLE_TYPE, &type)) {
334*61046927SAndroid Build Coastguard Worker       /* Xserver may support query with raw X11 window. */
335*61046927SAndroid Build Coastguard Worker       if (type == GLX_PIXMAP_BIT) {
336*61046927SAndroid Build Coastguard Worker          ErrorMessageF("GLXPixmap drawable type is not supported\n");
337*61046927SAndroid Build Coastguard Worker          return NULL;
338*61046927SAndroid Build Coastguard Worker       }
339*61046927SAndroid Build Coastguard Worker    } else {
340*61046927SAndroid Build Coastguard Worker       /* Xserver may not implement GLX_DRAWABLE_TYPE query yet. */
341*61046927SAndroid Build Coastguard Worker       type = GLX_PBUFFER_BIT | GLX_WINDOW_BIT;
342*61046927SAndroid Build Coastguard Worker    }
343*61046927SAndroid Build Coastguard Worker 
344*61046927SAndroid Build Coastguard Worker    pdraw = psc->driScreen.createDrawable(psc, glxDrawable, glxDrawable,
345*61046927SAndroid Build Coastguard Worker                                           type, config);
346*61046927SAndroid Build Coastguard Worker 
347*61046927SAndroid Build Coastguard Worker    if (pdraw == NULL) {
348*61046927SAndroid Build Coastguard Worker       ErrorMessageF("failed to create drawable\n");
349*61046927SAndroid Build Coastguard Worker       return NULL;
350*61046927SAndroid Build Coastguard Worker    }
351*61046927SAndroid Build Coastguard Worker 
352*61046927SAndroid Build Coastguard Worker    if (__glxHashInsert(priv->drawHash, glxDrawable, pdraw)) {
353*61046927SAndroid Build Coastguard Worker       pdraw->destroyDrawable(pdraw);
354*61046927SAndroid Build Coastguard Worker       return NULL;
355*61046927SAndroid Build Coastguard Worker    }
356*61046927SAndroid Build Coastguard Worker    pdraw->refcount = 1;
357*61046927SAndroid Build Coastguard Worker 
358*61046927SAndroid Build Coastguard Worker    return pdraw;
359*61046927SAndroid Build Coastguard Worker }
360*61046927SAndroid Build Coastguard Worker 
361*61046927SAndroid Build Coastguard Worker static int
discardGLXBadDrawableHandler(Display * display,xError * err,XExtCodes * codes,int * ret_code)362*61046927SAndroid Build Coastguard Worker discardGLXBadDrawableHandler(Display *display, xError *err, XExtCodes *codes,
363*61046927SAndroid Build Coastguard Worker                              int *ret_code)
364*61046927SAndroid Build Coastguard Worker {
365*61046927SAndroid Build Coastguard Worker    int code = codes->first_error + GLXBadDrawable;
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker    /* Only discard error which is expected. */
368*61046927SAndroid Build Coastguard Worker    if (err->majorCode == codes->major_opcode &&
369*61046927SAndroid Build Coastguard Worker        err->minorCode == X_GLXGetDrawableAttributes &&
370*61046927SAndroid Build Coastguard Worker        /* newer xserver use GLXBadDrawable, old one use BadDrawable */
371*61046927SAndroid Build Coastguard Worker        (err->errorCode == code || err->errorCode == BadDrawable)) {
372*61046927SAndroid Build Coastguard Worker       *ret_code = 1;
373*61046927SAndroid Build Coastguard Worker       return 1;
374*61046927SAndroid Build Coastguard Worker    }
375*61046927SAndroid Build Coastguard Worker 
376*61046927SAndroid Build Coastguard Worker    return 0;
377*61046927SAndroid Build Coastguard Worker }
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker static void
checkServerGLXDrawableAlive(const struct glx_display * priv)380*61046927SAndroid Build Coastguard Worker checkServerGLXDrawableAlive(const struct glx_display *priv)
381*61046927SAndroid Build Coastguard Worker {
382*61046927SAndroid Build Coastguard Worker    ErrorType old = XESetError(priv->dpy, priv->codes.extension,
383*61046927SAndroid Build Coastguard Worker                               discardGLXBadDrawableHandler);
384*61046927SAndroid Build Coastguard Worker 
385*61046927SAndroid Build Coastguard Worker    set_foreach(priv->zombieGLXDrawable, entry) {
386*61046927SAndroid Build Coastguard Worker       __GLXDRIdrawable *pdraw = (__GLXDRIdrawable *)entry->key;
387*61046927SAndroid Build Coastguard Worker       GLXDrawable drawable = pdraw->drawable;
388*61046927SAndroid Build Coastguard Worker       unsigned int dummy;
389*61046927SAndroid Build Coastguard Worker 
390*61046927SAndroid Build Coastguard Worker       /* Fail to query, so the window has been closed. Release the GLXDrawable. */
391*61046927SAndroid Build Coastguard Worker       if (!__glXGetDrawableAttribute(priv->dpy, drawable, GLX_WIDTH, &dummy)) {
392*61046927SAndroid Build Coastguard Worker          pdraw->destroyDrawable(pdraw);
393*61046927SAndroid Build Coastguard Worker          __glxHashDelete(priv->drawHash, drawable);
394*61046927SAndroid Build Coastguard Worker          _mesa_set_remove(priv->zombieGLXDrawable, entry);
395*61046927SAndroid Build Coastguard Worker       }
396*61046927SAndroid Build Coastguard Worker    }
397*61046927SAndroid Build Coastguard Worker 
398*61046927SAndroid Build Coastguard Worker    XESetError(priv->dpy, priv->codes.extension, old);
399*61046927SAndroid Build Coastguard Worker }
400*61046927SAndroid Build Coastguard Worker 
401*61046927SAndroid Build Coastguard Worker static void
releaseDrawable(const struct glx_display * priv,GLXDrawable drawable)402*61046927SAndroid Build Coastguard Worker releaseDrawable(const struct glx_display *priv, GLXDrawable drawable)
403*61046927SAndroid Build Coastguard Worker {
404*61046927SAndroid Build Coastguard Worker    __GLXDRIdrawable *pdraw;
405*61046927SAndroid Build Coastguard Worker 
406*61046927SAndroid Build Coastguard Worker    if (__glxHashLookup(priv->drawHash, drawable, (void *) &pdraw) == 0) {
407*61046927SAndroid Build Coastguard Worker       /* Only native window and pbuffer have same GLX and X11 drawable ID. */
408*61046927SAndroid Build Coastguard Worker       if (pdraw->drawable == pdraw->xDrawable) {
409*61046927SAndroid Build Coastguard Worker          pdraw->refcount --;
410*61046927SAndroid Build Coastguard Worker          /* If pbuffer's refcount reaches 0, it must be imported from other
411*61046927SAndroid Build Coastguard Worker           * display. Because pbuffer created from this display will always
412*61046927SAndroid Build Coastguard Worker           * hold the last refcount until destroy the GLXPbuffer object.
413*61046927SAndroid Build Coastguard Worker           */
414*61046927SAndroid Build Coastguard Worker          if (pdraw->refcount == 0) {
415*61046927SAndroid Build Coastguard Worker             if (pdraw->psc->keep_native_window_glx_drawable) {
416*61046927SAndroid Build Coastguard Worker                checkServerGLXDrawableAlive(priv);
417*61046927SAndroid Build Coastguard Worker                _mesa_set_add(priv->zombieGLXDrawable, pdraw);
418*61046927SAndroid Build Coastguard Worker             } else {
419*61046927SAndroid Build Coastguard Worker                pdraw->destroyDrawable(pdraw);
420*61046927SAndroid Build Coastguard Worker                __glxHashDelete(priv->drawHash, drawable);
421*61046927SAndroid Build Coastguard Worker             }
422*61046927SAndroid Build Coastguard Worker          }
423*61046927SAndroid Build Coastguard Worker       }
424*61046927SAndroid Build Coastguard Worker    }
425*61046927SAndroid Build Coastguard Worker }
426*61046927SAndroid Build Coastguard Worker 
427*61046927SAndroid Build Coastguard Worker _X_HIDDEN void
driReleaseDrawables(struct glx_context * gc)428*61046927SAndroid Build Coastguard Worker driReleaseDrawables(struct glx_context *gc)
429*61046927SAndroid Build Coastguard Worker {
430*61046927SAndroid Build Coastguard Worker    const struct glx_display *priv = gc->psc->display;
431*61046927SAndroid Build Coastguard Worker 
432*61046927SAndroid Build Coastguard Worker    releaseDrawable(priv, gc->currentDrawable);
433*61046927SAndroid Build Coastguard Worker    releaseDrawable(priv, gc->currentReadable);
434*61046927SAndroid Build Coastguard Worker 
435*61046927SAndroid Build Coastguard Worker    gc->currentDrawable = None;
436*61046927SAndroid Build Coastguard Worker    gc->currentReadable = None;
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker }
439*61046927SAndroid Build Coastguard Worker 
440*61046927SAndroid Build Coastguard Worker _X_HIDDEN int
dri_convert_glx_attribs(unsigned num_attribs,const uint32_t * attribs,struct dri_ctx_attribs * dca)441*61046927SAndroid Build Coastguard Worker dri_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs,
442*61046927SAndroid Build Coastguard Worker                         struct dri_ctx_attribs *dca)
443*61046927SAndroid Build Coastguard Worker {
444*61046927SAndroid Build Coastguard Worker    unsigned i;
445*61046927SAndroid Build Coastguard Worker    uint32_t profile = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
446*61046927SAndroid Build Coastguard Worker 
447*61046927SAndroid Build Coastguard Worker    dca->major_ver = 1;
448*61046927SAndroid Build Coastguard Worker    dca->minor_ver = 0;
449*61046927SAndroid Build Coastguard Worker    dca->render_type = GLX_RGBA_TYPE;
450*61046927SAndroid Build Coastguard Worker    dca->reset = __DRI_CTX_RESET_NO_NOTIFICATION;
451*61046927SAndroid Build Coastguard Worker    dca->release = __DRI_CTX_RELEASE_BEHAVIOR_FLUSH;
452*61046927SAndroid Build Coastguard Worker    dca->flags = 0;
453*61046927SAndroid Build Coastguard Worker    dca->api = __DRI_API_OPENGL;
454*61046927SAndroid Build Coastguard Worker    dca->no_error = 0;
455*61046927SAndroid Build Coastguard Worker 
456*61046927SAndroid Build Coastguard Worker    for (i = 0; i < num_attribs; i++) {
457*61046927SAndroid Build Coastguard Worker       switch (attribs[i * 2]) {
458*61046927SAndroid Build Coastguard Worker       case GLX_CONTEXT_MAJOR_VERSION_ARB:
459*61046927SAndroid Build Coastguard Worker     dca->major_ver = attribs[i * 2 + 1];
460*61046927SAndroid Build Coastguard Worker     break;
461*61046927SAndroid Build Coastguard Worker       case GLX_CONTEXT_MINOR_VERSION_ARB:
462*61046927SAndroid Build Coastguard Worker     dca->minor_ver = attribs[i * 2 + 1];
463*61046927SAndroid Build Coastguard Worker     break;
464*61046927SAndroid Build Coastguard Worker       case GLX_CONTEXT_FLAGS_ARB:
465*61046927SAndroid Build Coastguard Worker     dca->flags = attribs[i * 2 + 1];
466*61046927SAndroid Build Coastguard Worker     break;
467*61046927SAndroid Build Coastguard Worker       case GLX_CONTEXT_OPENGL_NO_ERROR_ARB:
468*61046927SAndroid Build Coastguard Worker     dca->no_error = attribs[i * 2 + 1];
469*61046927SAndroid Build Coastguard Worker     break;
470*61046927SAndroid Build Coastguard Worker       case GLX_CONTEXT_PROFILE_MASK_ARB:
471*61046927SAndroid Build Coastguard Worker     profile = attribs[i * 2 + 1];
472*61046927SAndroid Build Coastguard Worker     break;
473*61046927SAndroid Build Coastguard Worker       case GLX_RENDER_TYPE:
474*61046927SAndroid Build Coastguard Worker          dca->render_type = attribs[i * 2 + 1];
475*61046927SAndroid Build Coastguard Worker     break;
476*61046927SAndroid Build Coastguard Worker       case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB:
477*61046927SAndroid Build Coastguard Worker          switch (attribs[i * 2 + 1]) {
478*61046927SAndroid Build Coastguard Worker          case GLX_NO_RESET_NOTIFICATION_ARB:
479*61046927SAndroid Build Coastguard Worker             dca->reset = __DRI_CTX_RESET_NO_NOTIFICATION;
480*61046927SAndroid Build Coastguard Worker             break;
481*61046927SAndroid Build Coastguard Worker          case GLX_LOSE_CONTEXT_ON_RESET_ARB:
482*61046927SAndroid Build Coastguard Worker             dca->reset = __DRI_CTX_RESET_LOSE_CONTEXT;
483*61046927SAndroid Build Coastguard Worker             break;
484*61046927SAndroid Build Coastguard Worker          default:
485*61046927SAndroid Build Coastguard Worker             return BadValue;
486*61046927SAndroid Build Coastguard Worker          }
487*61046927SAndroid Build Coastguard Worker          break;
488*61046927SAndroid Build Coastguard Worker       case GLX_CONTEXT_RELEASE_BEHAVIOR_ARB:
489*61046927SAndroid Build Coastguard Worker          switch (attribs[i * 2 + 1]) {
490*61046927SAndroid Build Coastguard Worker          case GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB:
491*61046927SAndroid Build Coastguard Worker             dca->release = __DRI_CTX_RELEASE_BEHAVIOR_NONE;
492*61046927SAndroid Build Coastguard Worker             break;
493*61046927SAndroid Build Coastguard Worker          case GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB:
494*61046927SAndroid Build Coastguard Worker             dca->release = __DRI_CTX_RELEASE_BEHAVIOR_FLUSH;
495*61046927SAndroid Build Coastguard Worker             break;
496*61046927SAndroid Build Coastguard Worker          default:
497*61046927SAndroid Build Coastguard Worker             return BadValue;
498*61046927SAndroid Build Coastguard Worker          }
499*61046927SAndroid Build Coastguard Worker          break;
500*61046927SAndroid Build Coastguard Worker       case GLX_SCREEN:
501*61046927SAndroid Build Coastguard Worker          /* Implies GLX_EXT_no_config_context */
502*61046927SAndroid Build Coastguard Worker          dca->render_type = GLX_DONT_CARE;
503*61046927SAndroid Build Coastguard Worker          break;
504*61046927SAndroid Build Coastguard Worker       default:
505*61046927SAndroid Build Coastguard Worker     /* If an unknown attribute is received, fail.
506*61046927SAndroid Build Coastguard Worker      */
507*61046927SAndroid Build Coastguard Worker     return BadValue;
508*61046927SAndroid Build Coastguard Worker       }
509*61046927SAndroid Build Coastguard Worker    }
510*61046927SAndroid Build Coastguard Worker 
511*61046927SAndroid Build Coastguard Worker    switch (profile) {
512*61046927SAndroid Build Coastguard Worker    case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
513*61046927SAndroid Build Coastguard Worker       /* This is the default value, but there are no profiles before OpenGL
514*61046927SAndroid Build Coastguard Worker        * 3.2. The GLX_ARB_create_context_profile spec says:
515*61046927SAndroid Build Coastguard Worker        *
516*61046927SAndroid Build Coastguard Worker        *     "If the requested OpenGL version is less than 3.2,
517*61046927SAndroid Build Coastguard Worker        *     GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality
518*61046927SAndroid Build Coastguard Worker        *     of the context is determined solely by the requested version."
519*61046927SAndroid Build Coastguard Worker        */
520*61046927SAndroid Build Coastguard Worker       dca->api = (dca->major_ver > 3 || (dca->major_ver == 3 && dca->minor_ver >= 2))
521*61046927SAndroid Build Coastguard Worker          ? __DRI_API_OPENGL_CORE : __DRI_API_OPENGL;
522*61046927SAndroid Build Coastguard Worker       break;
523*61046927SAndroid Build Coastguard Worker    case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
524*61046927SAndroid Build Coastguard Worker       dca->api = __DRI_API_OPENGL;
525*61046927SAndroid Build Coastguard Worker       break;
526*61046927SAndroid Build Coastguard Worker    case GLX_CONTEXT_ES_PROFILE_BIT_EXT:
527*61046927SAndroid Build Coastguard Worker       if (dca->major_ver >= 3)
528*61046927SAndroid Build Coastguard Worker          dca->api = __DRI_API_GLES3;
529*61046927SAndroid Build Coastguard Worker       else if (dca->major_ver == 2 && dca->minor_ver == 0)
530*61046927SAndroid Build Coastguard Worker          dca->api = __DRI_API_GLES2;
531*61046927SAndroid Build Coastguard Worker       else if (dca->major_ver == 1 && dca->minor_ver < 2)
532*61046927SAndroid Build Coastguard Worker          dca->api = __DRI_API_GLES;
533*61046927SAndroid Build Coastguard Worker       else {
534*61046927SAndroid Build Coastguard Worker          return BadValue;
535*61046927SAndroid Build Coastguard Worker       }
536*61046927SAndroid Build Coastguard Worker       break;
537*61046927SAndroid Build Coastguard Worker    default:
538*61046927SAndroid Build Coastguard Worker       return GLXBadProfileARB;
539*61046927SAndroid Build Coastguard Worker    }
540*61046927SAndroid Build Coastguard Worker 
541*61046927SAndroid Build Coastguard Worker    /* Unknown flag value */
542*61046927SAndroid Build Coastguard Worker    if (dca->flags & ~(__DRI_CTX_FLAG_DEBUG |
543*61046927SAndroid Build Coastguard Worker                       __DRI_CTX_FLAG_FORWARD_COMPATIBLE |
544*61046927SAndroid Build Coastguard Worker                       __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS |
545*61046927SAndroid Build Coastguard Worker                       __DRI_CTX_FLAG_RESET_ISOLATION))
546*61046927SAndroid Build Coastguard Worker       return BadValue;
547*61046927SAndroid Build Coastguard Worker 
548*61046927SAndroid Build Coastguard Worker    /* There are no forward-compatible contexts before OpenGL 3.0.  The
549*61046927SAndroid Build Coastguard Worker     * GLX_ARB_create_context spec says:
550*61046927SAndroid Build Coastguard Worker     *
551*61046927SAndroid Build Coastguard Worker     *     "Forward-compatible contexts are defined only for OpenGL versions
552*61046927SAndroid Build Coastguard Worker     *     3.0 and later."
553*61046927SAndroid Build Coastguard Worker     */
554*61046927SAndroid Build Coastguard Worker    if (dca->major_ver < 3 && (dca->flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0)
555*61046927SAndroid Build Coastguard Worker       return BadMatch;
556*61046927SAndroid Build Coastguard Worker 
557*61046927SAndroid Build Coastguard Worker    /* It also says:
558*61046927SAndroid Build Coastguard Worker     *
559*61046927SAndroid Build Coastguard Worker     *    "OpenGL contexts supporting version 3.0 or later of the API do not
560*61046927SAndroid Build Coastguard Worker     *    support color index rendering, even if a color index <config> is
561*61046927SAndroid Build Coastguard Worker     *    available."
562*61046927SAndroid Build Coastguard Worker     */
563*61046927SAndroid Build Coastguard Worker    if (dca->major_ver >= 3 && dca->render_type == GLX_COLOR_INDEX_TYPE)
564*61046927SAndroid Build Coastguard Worker       return BadMatch;
565*61046927SAndroid Build Coastguard Worker 
566*61046927SAndroid Build Coastguard Worker    /* The KHR_no_error specs say:
567*61046927SAndroid Build Coastguard Worker     *
568*61046927SAndroid Build Coastguard Worker     *    Requires OpenGL ES 2.0 or OpenGL 2.0.
569*61046927SAndroid Build Coastguard Worker     */
570*61046927SAndroid Build Coastguard Worker    if (dca->no_error && dca->major_ver < 2)
571*61046927SAndroid Build Coastguard Worker       return BadMatch;
572*61046927SAndroid Build Coastguard Worker 
573*61046927SAndroid Build Coastguard Worker    /* The GLX_ARB_create_context_no_error specs say:
574*61046927SAndroid Build Coastguard Worker     *
575*61046927SAndroid Build Coastguard Worker     *    BadMatch is generated if the GLX_CONTEXT_OPENGL_NO_ERROR_ARB is TRUE at
576*61046927SAndroid Build Coastguard Worker     *    the same time as a debug or robustness context is specified.
577*61046927SAndroid Build Coastguard Worker     *
578*61046927SAndroid Build Coastguard Worker     */
579*61046927SAndroid Build Coastguard Worker    if (dca->no_error && ((dca->flags & __DRI_CTX_FLAG_DEBUG) ||
580*61046927SAndroid Build Coastguard Worker                          (dca->flags & __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS)))
581*61046927SAndroid Build Coastguard Worker       return BadMatch;
582*61046927SAndroid Build Coastguard Worker 
583*61046927SAndroid Build Coastguard Worker    return Success;
584*61046927SAndroid Build Coastguard Worker }
585*61046927SAndroid Build Coastguard Worker 
586*61046927SAndroid Build Coastguard Worker unsigned
dri_context_error_to_glx_error(unsigned error)587*61046927SAndroid Build Coastguard Worker dri_context_error_to_glx_error(unsigned error)
588*61046927SAndroid Build Coastguard Worker {
589*61046927SAndroid Build Coastguard Worker    if (error == __DRI_CTX_ERROR_SUCCESS)
590*61046927SAndroid Build Coastguard Worker       return Success;
591*61046927SAndroid Build Coastguard Worker    if (error == __DRI_CTX_ERROR_NO_MEMORY)
592*61046927SAndroid Build Coastguard Worker       return BadAlloc;
593*61046927SAndroid Build Coastguard Worker    else if (error == __DRI_CTX_ERROR_BAD_API)
594*61046927SAndroid Build Coastguard Worker       return BadMatch;
595*61046927SAndroid Build Coastguard Worker    else if (error == __DRI_CTX_ERROR_BAD_VERSION)
596*61046927SAndroid Build Coastguard Worker       return GLXBadFBConfig;
597*61046927SAndroid Build Coastguard Worker    else if (error == __DRI_CTX_ERROR_BAD_FLAG)
598*61046927SAndroid Build Coastguard Worker       return BadMatch;
599*61046927SAndroid Build Coastguard Worker    else if (error == __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE)
600*61046927SAndroid Build Coastguard Worker       return BadValue;
601*61046927SAndroid Build Coastguard Worker    else if (error == __DRI_CTX_ERROR_UNKNOWN_FLAG)
602*61046927SAndroid Build Coastguard Worker       return BadValue;
603*61046927SAndroid Build Coastguard Worker    else
604*61046927SAndroid Build Coastguard Worker       unreachable("Impossible DRI context error");
605*61046927SAndroid Build Coastguard Worker }
606*61046927SAndroid Build Coastguard Worker 
607*61046927SAndroid Build Coastguard Worker struct glx_context *
dri_common_create_context(struct glx_screen * base,struct glx_config * config_base,struct glx_context * shareList,int renderType)608*61046927SAndroid Build Coastguard Worker dri_common_create_context(struct glx_screen *base,
609*61046927SAndroid Build Coastguard Worker                           struct glx_config *config_base,
610*61046927SAndroid Build Coastguard Worker                           struct glx_context *shareList,
611*61046927SAndroid Build Coastguard Worker                           int renderType)
612*61046927SAndroid Build Coastguard Worker {
613*61046927SAndroid Build Coastguard Worker    unsigned int error;
614*61046927SAndroid Build Coastguard Worker    uint32_t attribs[2] = { GLX_RENDER_TYPE, renderType };
615*61046927SAndroid Build Coastguard Worker 
616*61046927SAndroid Build Coastguard Worker    return base->vtable->create_context_attribs(base, config_base, shareList,
617*61046927SAndroid Build Coastguard Worker                                                1, attribs, &error);
618*61046927SAndroid Build Coastguard Worker }
619*61046927SAndroid Build Coastguard Worker 
620*61046927SAndroid Build Coastguard Worker 
621*61046927SAndroid Build Coastguard Worker /*
622*61046927SAndroid Build Coastguard Worker  * Given a display pointer and screen number, determine the name of
623*61046927SAndroid Build Coastguard Worker  * the DRI driver for the screen (i.e., "i965", "radeon", "nouveau", etc).
624*61046927SAndroid Build Coastguard Worker  * Return True for success, False for failure.
625*61046927SAndroid Build Coastguard Worker  */
626*61046927SAndroid Build Coastguard Worker static Bool
driGetDriverName(Display * dpy,int scrNum,char ** driverName)627*61046927SAndroid Build Coastguard Worker driGetDriverName(Display * dpy, int scrNum, char **driverName)
628*61046927SAndroid Build Coastguard Worker {
629*61046927SAndroid Build Coastguard Worker    struct glx_screen *glx_screen = GetGLXScreenConfigs(dpy, scrNum);
630*61046927SAndroid Build Coastguard Worker 
631*61046927SAndroid Build Coastguard Worker    if (!glx_screen || !glx_screen->vtable->get_driver_name)
632*61046927SAndroid Build Coastguard Worker       return False;
633*61046927SAndroid Build Coastguard Worker 
634*61046927SAndroid Build Coastguard Worker    *driverName = glx_screen->vtable->get_driver_name(glx_screen);
635*61046927SAndroid Build Coastguard Worker    return True;
636*61046927SAndroid Build Coastguard Worker }
637*61046927SAndroid Build Coastguard Worker 
638*61046927SAndroid Build Coastguard Worker /*
639*61046927SAndroid Build Coastguard Worker  * Exported function for querying the DRI driver for a given screen.
640*61046927SAndroid Build Coastguard Worker  *
641*61046927SAndroid Build Coastguard Worker  * The returned char pointer points to a static array that will be
642*61046927SAndroid Build Coastguard Worker  * overwritten by subsequent calls.
643*61046927SAndroid Build Coastguard Worker  */
644*61046927SAndroid Build Coastguard Worker _GLX_PUBLIC const char *
glXGetScreenDriver(Display * dpy,int scrNum)645*61046927SAndroid Build Coastguard Worker glXGetScreenDriver(Display * dpy, int scrNum)
646*61046927SAndroid Build Coastguard Worker {
647*61046927SAndroid Build Coastguard Worker    static char ret[32];
648*61046927SAndroid Build Coastguard Worker    char *driverName;
649*61046927SAndroid Build Coastguard Worker 
650*61046927SAndroid Build Coastguard Worker    if (driGetDriverName(dpy, scrNum, &driverName)) {
651*61046927SAndroid Build Coastguard Worker       int len;
652*61046927SAndroid Build Coastguard Worker       if (!driverName)
653*61046927SAndroid Build Coastguard Worker          return NULL;
654*61046927SAndroid Build Coastguard Worker       len = strlen(driverName);
655*61046927SAndroid Build Coastguard Worker       if (len >= 31)
656*61046927SAndroid Build Coastguard Worker          return NULL;
657*61046927SAndroid Build Coastguard Worker       memcpy(ret, driverName, len + 1);
658*61046927SAndroid Build Coastguard Worker       free(driverName);
659*61046927SAndroid Build Coastguard Worker       return ret;
660*61046927SAndroid Build Coastguard Worker    }
661*61046927SAndroid Build Coastguard Worker    return NULL;
662*61046927SAndroid Build Coastguard Worker }
663*61046927SAndroid Build Coastguard Worker 
664*61046927SAndroid Build Coastguard Worker /* glXGetDriverConfig must return a pointer with a static lifetime. To avoid
665*61046927SAndroid Build Coastguard Worker  * keeping drivers loaded and other leaks, we keep a cache of results here that
666*61046927SAndroid Build Coastguard Worker  * is cleared by an atexit handler.
667*61046927SAndroid Build Coastguard Worker  */
668*61046927SAndroid Build Coastguard Worker struct driver_config_entry {
669*61046927SAndroid Build Coastguard Worker    struct driver_config_entry *next;
670*61046927SAndroid Build Coastguard Worker    char *driverName;
671*61046927SAndroid Build Coastguard Worker    char *config;
672*61046927SAndroid Build Coastguard Worker };
673*61046927SAndroid Build Coastguard Worker 
674*61046927SAndroid Build Coastguard Worker static pthread_mutex_t driver_config_mutex = PTHREAD_MUTEX_INITIALIZER;
675*61046927SAndroid Build Coastguard Worker static struct driver_config_entry *driver_config_cache = NULL;
676*61046927SAndroid Build Coastguard Worker 
677*61046927SAndroid Build Coastguard Worker /* Called as an atexit function. Otherwise, this would have to be called with
678*61046927SAndroid Build Coastguard Worker  * driver_config_mutex locked.
679*61046927SAndroid Build Coastguard Worker  */
680*61046927SAndroid Build Coastguard Worker static void
clear_driver_config_cache()681*61046927SAndroid Build Coastguard Worker clear_driver_config_cache()
682*61046927SAndroid Build Coastguard Worker {
683*61046927SAndroid Build Coastguard Worker    while (driver_config_cache) {
684*61046927SAndroid Build Coastguard Worker       struct driver_config_entry *e = driver_config_cache;
685*61046927SAndroid Build Coastguard Worker       driver_config_cache = e->next;
686*61046927SAndroid Build Coastguard Worker 
687*61046927SAndroid Build Coastguard Worker       free(e->driverName);
688*61046927SAndroid Build Coastguard Worker       free(e->config);
689*61046927SAndroid Build Coastguard Worker       free(e);
690*61046927SAndroid Build Coastguard Worker    }
691*61046927SAndroid Build Coastguard Worker }
692*61046927SAndroid Build Coastguard Worker 
693*61046927SAndroid Build Coastguard Worker /*
694*61046927SAndroid Build Coastguard Worker  * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
695*61046927SAndroid Build Coastguard Worker  *
696*61046927SAndroid Build Coastguard Worker  * The returned char pointer points directly into the driver. Therefore
697*61046927SAndroid Build Coastguard Worker  * it should be treated as a constant.
698*61046927SAndroid Build Coastguard Worker  *
699*61046927SAndroid Build Coastguard Worker  * If the driver was not found or does not support configuration NULL is
700*61046927SAndroid Build Coastguard Worker  * returned.
701*61046927SAndroid Build Coastguard Worker  */
702*61046927SAndroid Build Coastguard Worker _GLX_PUBLIC const char *
glXGetDriverConfig(const char * driverName)703*61046927SAndroid Build Coastguard Worker glXGetDriverConfig(const char *driverName)
704*61046927SAndroid Build Coastguard Worker {
705*61046927SAndroid Build Coastguard Worker    struct driver_config_entry *e;
706*61046927SAndroid Build Coastguard Worker 
707*61046927SAndroid Build Coastguard Worker    pthread_mutex_lock(&driver_config_mutex);
708*61046927SAndroid Build Coastguard Worker 
709*61046927SAndroid Build Coastguard Worker    for (e = driver_config_cache; e; e = e->next) {
710*61046927SAndroid Build Coastguard Worker       if (strcmp(e->driverName, driverName) == 0)
711*61046927SAndroid Build Coastguard Worker          goto out;
712*61046927SAndroid Build Coastguard Worker    }
713*61046927SAndroid Build Coastguard Worker 
714*61046927SAndroid Build Coastguard Worker    e = malloc(sizeof(*e));
715*61046927SAndroid Build Coastguard Worker    if (!e)
716*61046927SAndroid Build Coastguard Worker       goto out;
717*61046927SAndroid Build Coastguard Worker 
718*61046927SAndroid Build Coastguard Worker    e->config = pipe_loader_get_driinfo_xml(driverName);
719*61046927SAndroid Build Coastguard Worker    e->driverName = strdup(driverName);
720*61046927SAndroid Build Coastguard Worker    if (!e->config || !e->driverName) {
721*61046927SAndroid Build Coastguard Worker       free(e->config);
722*61046927SAndroid Build Coastguard Worker       free(e->driverName);
723*61046927SAndroid Build Coastguard Worker       free(e);
724*61046927SAndroid Build Coastguard Worker       e = NULL;
725*61046927SAndroid Build Coastguard Worker       goto out;
726*61046927SAndroid Build Coastguard Worker    }
727*61046927SAndroid Build Coastguard Worker 
728*61046927SAndroid Build Coastguard Worker    e->next = driver_config_cache;
729*61046927SAndroid Build Coastguard Worker    driver_config_cache = e;
730*61046927SAndroid Build Coastguard Worker 
731*61046927SAndroid Build Coastguard Worker    if (!e->next)
732*61046927SAndroid Build Coastguard Worker       atexit(clear_driver_config_cache);
733*61046927SAndroid Build Coastguard Worker 
734*61046927SAndroid Build Coastguard Worker out:
735*61046927SAndroid Build Coastguard Worker    pthread_mutex_unlock(&driver_config_mutex);
736*61046927SAndroid Build Coastguard Worker 
737*61046927SAndroid Build Coastguard Worker    return e ? e->config : NULL;
738*61046927SAndroid Build Coastguard Worker }
739*61046927SAndroid Build Coastguard Worker 
740*61046927SAndroid Build Coastguard Worker static void
driSetBackgroundContext(void * loaderPrivate)741*61046927SAndroid Build Coastguard Worker driSetBackgroundContext(void *loaderPrivate)
742*61046927SAndroid Build Coastguard Worker {
743*61046927SAndroid Build Coastguard Worker    __glXSetCurrentContext(loaderPrivate);
744*61046927SAndroid Build Coastguard Worker }
745*61046927SAndroid Build Coastguard Worker 
746*61046927SAndroid Build Coastguard Worker static GLboolean
driIsThreadSafe(void * loaderPrivate)747*61046927SAndroid Build Coastguard Worker driIsThreadSafe(void *loaderPrivate)
748*61046927SAndroid Build Coastguard Worker {
749*61046927SAndroid Build Coastguard Worker    struct glx_context *pcp = (struct glx_context *) loaderPrivate;
750*61046927SAndroid Build Coastguard Worker    /* Check Xlib is running in thread safe mode
751*61046927SAndroid Build Coastguard Worker     *
752*61046927SAndroid Build Coastguard Worker     * 'lock_fns' is the XLockDisplay function pointer of the X11 display 'dpy'.
753*61046927SAndroid Build Coastguard Worker     * It will be NULL if XInitThreads wasn't called.
754*61046927SAndroid Build Coastguard Worker     */
755*61046927SAndroid Build Coastguard Worker    return pcp->psc->dpy->lock_fns != NULL;
756*61046927SAndroid Build Coastguard Worker }
757*61046927SAndroid Build Coastguard Worker 
758*61046927SAndroid Build Coastguard Worker const __DRIbackgroundCallableExtension driBackgroundCallable = {
759*61046927SAndroid Build Coastguard Worker    .base = { __DRI_BACKGROUND_CALLABLE, 2 },
760*61046927SAndroid Build Coastguard Worker 
761*61046927SAndroid Build Coastguard Worker    .setBackgroundContext    = driSetBackgroundContext,
762*61046927SAndroid Build Coastguard Worker    .isThreadSafe            = driIsThreadSafe,
763*61046927SAndroid Build Coastguard Worker };
764*61046927SAndroid Build Coastguard Worker 
765*61046927SAndroid Build Coastguard Worker const __DRIuseInvalidateExtension dri2UseInvalidate = {
766*61046927SAndroid Build Coastguard Worker    .base = { __DRI_USE_INVALIDATE, 1 }
767*61046927SAndroid Build Coastguard Worker };
768*61046927SAndroid Build Coastguard Worker 
769*61046927SAndroid Build Coastguard Worker Bool
dri_bind_context(struct glx_context * context,GLXDrawable draw,GLXDrawable read)770*61046927SAndroid Build Coastguard Worker dri_bind_context(struct glx_context *context, GLXDrawable draw, GLXDrawable read)
771*61046927SAndroid Build Coastguard Worker {
772*61046927SAndroid Build Coastguard Worker    __GLXDRIdrawable *pdraw, *pread;
773*61046927SAndroid Build Coastguard Worker    __DRIdrawable *dri_draw = NULL, *dri_read = NULL;
774*61046927SAndroid Build Coastguard Worker 
775*61046927SAndroid Build Coastguard Worker    pdraw = driFetchDrawable(context, draw);
776*61046927SAndroid Build Coastguard Worker    pread = driFetchDrawable(context, read);
777*61046927SAndroid Build Coastguard Worker 
778*61046927SAndroid Build Coastguard Worker    driReleaseDrawables(context);
779*61046927SAndroid Build Coastguard Worker 
780*61046927SAndroid Build Coastguard Worker    if (pdraw)
781*61046927SAndroid Build Coastguard Worker       dri_draw = pdraw->dri_drawable;
782*61046927SAndroid Build Coastguard Worker    else if (draw != None)
783*61046927SAndroid Build Coastguard Worker       return GLXBadDrawable;
784*61046927SAndroid Build Coastguard Worker 
785*61046927SAndroid Build Coastguard Worker    if (pread)
786*61046927SAndroid Build Coastguard Worker       dri_read = pread->dri_drawable;
787*61046927SAndroid Build Coastguard Worker    else if (read != None)
788*61046927SAndroid Build Coastguard Worker       return GLXBadDrawable;
789*61046927SAndroid Build Coastguard Worker 
790*61046927SAndroid Build Coastguard Worker    if (!driBindContext(context->driContext, dri_draw, dri_read))
791*61046927SAndroid Build Coastguard Worker       return GLXBadContext;
792*61046927SAndroid Build Coastguard Worker 
793*61046927SAndroid Build Coastguard Worker    if (context->psc->display->driver == GLX_DRIVER_DRI3 ||
794*61046927SAndroid Build Coastguard Worker        context->psc->display->driver == GLX_DRIVER_ZINK_YES) {
795*61046927SAndroid Build Coastguard Worker       if (dri_draw)
796*61046927SAndroid Build Coastguard Worker          dri_invalidate_drawable(dri_draw);
797*61046927SAndroid Build Coastguard Worker       if (dri_read && dri_read != dri_draw)
798*61046927SAndroid Build Coastguard Worker          dri_invalidate_drawable(dri_read);
799*61046927SAndroid Build Coastguard Worker    }
800*61046927SAndroid Build Coastguard Worker 
801*61046927SAndroid Build Coastguard Worker    return Success;
802*61046927SAndroid Build Coastguard Worker }
803*61046927SAndroid Build Coastguard Worker 
804*61046927SAndroid Build Coastguard Worker void
dri_unbind_context(struct glx_context * context)805*61046927SAndroid Build Coastguard Worker dri_unbind_context(struct glx_context *context)
806*61046927SAndroid Build Coastguard Worker {
807*61046927SAndroid Build Coastguard Worker    driUnbindContext(context->driContext);
808*61046927SAndroid Build Coastguard Worker }
809*61046927SAndroid Build Coastguard Worker 
810*61046927SAndroid Build Coastguard Worker void
dri_destroy_context(struct glx_context * context)811*61046927SAndroid Build Coastguard Worker dri_destroy_context(struct glx_context *context)
812*61046927SAndroid Build Coastguard Worker {
813*61046927SAndroid Build Coastguard Worker    driReleaseDrawables(context);
814*61046927SAndroid Build Coastguard Worker 
815*61046927SAndroid Build Coastguard Worker    free((char *) context->extensions);
816*61046927SAndroid Build Coastguard Worker 
817*61046927SAndroid Build Coastguard Worker    driDestroyContext(context->driContext);
818*61046927SAndroid Build Coastguard Worker 
819*61046927SAndroid Build Coastguard Worker    free(context);
820*61046927SAndroid Build Coastguard Worker }
821*61046927SAndroid Build Coastguard Worker 
822*61046927SAndroid Build Coastguard Worker struct glx_context *
dri_create_context_attribs(struct glx_screen * base,struct glx_config * config_base,struct glx_context * shareList,unsigned num_attribs,const uint32_t * attribs,unsigned * error)823*61046927SAndroid Build Coastguard Worker dri_create_context_attribs(struct glx_screen *base,
824*61046927SAndroid Build Coastguard Worker                            struct glx_config *config_base,
825*61046927SAndroid Build Coastguard Worker                            struct glx_context *shareList,
826*61046927SAndroid Build Coastguard Worker                            unsigned num_attribs,
827*61046927SAndroid Build Coastguard Worker                            const uint32_t *attribs,
828*61046927SAndroid Build Coastguard Worker                            unsigned *error)
829*61046927SAndroid Build Coastguard Worker {
830*61046927SAndroid Build Coastguard Worker    struct glx_context *pcp = NULL;
831*61046927SAndroid Build Coastguard Worker    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
832*61046927SAndroid Build Coastguard Worker    __DRIcontext *shared = NULL;
833*61046927SAndroid Build Coastguard Worker 
834*61046927SAndroid Build Coastguard Worker    struct dri_ctx_attribs dca;
835*61046927SAndroid Build Coastguard Worker    uint32_t ctx_attribs[2 * 6];
836*61046927SAndroid Build Coastguard Worker    unsigned num_ctx_attribs = 0;
837*61046927SAndroid Build Coastguard Worker 
838*61046927SAndroid Build Coastguard Worker    *error = dri_convert_glx_attribs(num_attribs, attribs, &dca);
839*61046927SAndroid Build Coastguard Worker    if (*error != __DRI_CTX_ERROR_SUCCESS)
840*61046927SAndroid Build Coastguard Worker       goto error_exit;
841*61046927SAndroid Build Coastguard Worker 
842*61046927SAndroid Build Coastguard Worker    /* Check the renderType value */
843*61046927SAndroid Build Coastguard Worker    if (!validate_renderType_against_config(config_base, dca.render_type)) {
844*61046927SAndroid Build Coastguard Worker       *error = BadValue;
845*61046927SAndroid Build Coastguard Worker       goto error_exit;
846*61046927SAndroid Build Coastguard Worker    }
847*61046927SAndroid Build Coastguard Worker 
848*61046927SAndroid Build Coastguard Worker    if (shareList) {
849*61046927SAndroid Build Coastguard Worker       /* We can't share with an indirect context */
850*61046927SAndroid Build Coastguard Worker       if (!shareList->isDirect)
851*61046927SAndroid Build Coastguard Worker          return NULL;
852*61046927SAndroid Build Coastguard Worker 
853*61046927SAndroid Build Coastguard Worker       /* The GLX_ARB_create_context_no_error specs say:
854*61046927SAndroid Build Coastguard Worker        *
855*61046927SAndroid Build Coastguard Worker        *    BadMatch is generated if the value of GLX_CONTEXT_OPENGL_NO_ERROR_ARB
856*61046927SAndroid Build Coastguard Worker        *    used to create <share_context> does not match the value of
857*61046927SAndroid Build Coastguard Worker        *    GLX_CONTEXT_OPENGL_NO_ERROR_ARB for the context being created.
858*61046927SAndroid Build Coastguard Worker        */
859*61046927SAndroid Build Coastguard Worker       if (!!shareList->noError != !!dca.no_error) {
860*61046927SAndroid Build Coastguard Worker          *error = BadMatch;
861*61046927SAndroid Build Coastguard Worker          return NULL;
862*61046927SAndroid Build Coastguard Worker       }
863*61046927SAndroid Build Coastguard Worker 
864*61046927SAndroid Build Coastguard Worker       shared = shareList->driContext;
865*61046927SAndroid Build Coastguard Worker    }
866*61046927SAndroid Build Coastguard Worker 
867*61046927SAndroid Build Coastguard Worker    pcp = calloc(1, sizeof *pcp);
868*61046927SAndroid Build Coastguard Worker    if (pcp == NULL) {
869*61046927SAndroid Build Coastguard Worker       *error = BadAlloc;
870*61046927SAndroid Build Coastguard Worker       goto error_exit;
871*61046927SAndroid Build Coastguard Worker    }
872*61046927SAndroid Build Coastguard Worker 
873*61046927SAndroid Build Coastguard Worker    if (!glx_context_init(pcp, base, config_base))
874*61046927SAndroid Build Coastguard Worker       goto error_exit;
875*61046927SAndroid Build Coastguard Worker 
876*61046927SAndroid Build Coastguard Worker    ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
877*61046927SAndroid Build Coastguard Worker    ctx_attribs[num_ctx_attribs++] = dca.major_ver;
878*61046927SAndroid Build Coastguard Worker    ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
879*61046927SAndroid Build Coastguard Worker    ctx_attribs[num_ctx_attribs++] = dca.minor_ver;
880*61046927SAndroid Build Coastguard Worker 
881*61046927SAndroid Build Coastguard Worker    /* Only send a value when the non-default value is requested.  By doing
882*61046927SAndroid Build Coastguard Worker     * this we don't have to check the driver's DRI3 version before sending the
883*61046927SAndroid Build Coastguard Worker     * default value.
884*61046927SAndroid Build Coastguard Worker     */
885*61046927SAndroid Build Coastguard Worker    if (dca.reset != __DRI_CTX_RESET_NO_NOTIFICATION) {
886*61046927SAndroid Build Coastguard Worker       ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
887*61046927SAndroid Build Coastguard Worker       ctx_attribs[num_ctx_attribs++] = dca.reset;
888*61046927SAndroid Build Coastguard Worker    }
889*61046927SAndroid Build Coastguard Worker 
890*61046927SAndroid Build Coastguard Worker    if (dca.release != __DRI_CTX_RELEASE_BEHAVIOR_FLUSH) {
891*61046927SAndroid Build Coastguard Worker       ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR;
892*61046927SAndroid Build Coastguard Worker       ctx_attribs[num_ctx_attribs++] = dca.release;
893*61046927SAndroid Build Coastguard Worker    }
894*61046927SAndroid Build Coastguard Worker 
895*61046927SAndroid Build Coastguard Worker    if (dca.no_error) {
896*61046927SAndroid Build Coastguard Worker       ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_NO_ERROR;
897*61046927SAndroid Build Coastguard Worker       ctx_attribs[num_ctx_attribs++] = dca.no_error;
898*61046927SAndroid Build Coastguard Worker       pcp->noError = GL_TRUE;
899*61046927SAndroid Build Coastguard Worker    }
900*61046927SAndroid Build Coastguard Worker 
901*61046927SAndroid Build Coastguard Worker    if (dca.flags != 0) {
902*61046927SAndroid Build Coastguard Worker       ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
903*61046927SAndroid Build Coastguard Worker       ctx_attribs[num_ctx_attribs++] = dca.flags;
904*61046927SAndroid Build Coastguard Worker    }
905*61046927SAndroid Build Coastguard Worker 
906*61046927SAndroid Build Coastguard Worker    /* The renderType is retrieved from attribs, or set to default
907*61046927SAndroid Build Coastguard Worker     *  of GLX_RGBA_TYPE.
908*61046927SAndroid Build Coastguard Worker     */
909*61046927SAndroid Build Coastguard Worker    pcp->renderType = dca.render_type;
910*61046927SAndroid Build Coastguard Worker 
911*61046927SAndroid Build Coastguard Worker    pcp->driContext =
912*61046927SAndroid Build Coastguard Worker       driCreateContextAttribs(base->frontend_screen,
913*61046927SAndroid Build Coastguard Worker                               dca.api,
914*61046927SAndroid Build Coastguard Worker                               config ? config->driConfig : NULL,
915*61046927SAndroid Build Coastguard Worker                               shared,
916*61046927SAndroid Build Coastguard Worker                               num_ctx_attribs / 2,
917*61046927SAndroid Build Coastguard Worker                               ctx_attribs,
918*61046927SAndroid Build Coastguard Worker                               error,
919*61046927SAndroid Build Coastguard Worker                               pcp);
920*61046927SAndroid Build Coastguard Worker 
921*61046927SAndroid Build Coastguard Worker    *error = dri_context_error_to_glx_error(*error);
922*61046927SAndroid Build Coastguard Worker 
923*61046927SAndroid Build Coastguard Worker    if (pcp->driContext == NULL)
924*61046927SAndroid Build Coastguard Worker       goto error_exit;
925*61046927SAndroid Build Coastguard Worker 
926*61046927SAndroid Build Coastguard Worker    pcp->vtable = base->context_vtable;
927*61046927SAndroid Build Coastguard Worker 
928*61046927SAndroid Build Coastguard Worker    return pcp;
929*61046927SAndroid Build Coastguard Worker 
930*61046927SAndroid Build Coastguard Worker error_exit:
931*61046927SAndroid Build Coastguard Worker    free(pcp);
932*61046927SAndroid Build Coastguard Worker 
933*61046927SAndroid Build Coastguard Worker    return NULL;
934*61046927SAndroid Build Coastguard Worker }
935*61046927SAndroid Build Coastguard Worker 
936*61046927SAndroid Build Coastguard Worker char *
dri_get_driver_name(struct glx_screen * glx_screen)937*61046927SAndroid Build Coastguard Worker dri_get_driver_name(struct glx_screen *glx_screen)
938*61046927SAndroid Build Coastguard Worker {
939*61046927SAndroid Build Coastguard Worker     return strdup(glx_screen->driverName);
940*61046927SAndroid Build Coastguard Worker }
941*61046927SAndroid Build Coastguard Worker 
942*61046927SAndroid Build Coastguard Worker const struct glx_screen_vtable dri_screen_vtable = {
943*61046927SAndroid Build Coastguard Worker    .create_context         = dri_common_create_context,
944*61046927SAndroid Build Coastguard Worker    .create_context_attribs = dri_create_context_attribs,
945*61046927SAndroid Build Coastguard Worker    .query_renderer_integer = glx_dri_query_renderer_integer,
946*61046927SAndroid Build Coastguard Worker    .query_renderer_string  = glx_dri_query_renderer_string,
947*61046927SAndroid Build Coastguard Worker    .get_driver_name        = dri_get_driver_name,
948*61046927SAndroid Build Coastguard Worker };
949*61046927SAndroid Build Coastguard Worker 
950*61046927SAndroid Build Coastguard Worker void
dri_bind_tex_image(__GLXDRIdrawable * base,int buffer,const int * attrib_list)951*61046927SAndroid Build Coastguard Worker dri_bind_tex_image(__GLXDRIdrawable *base, int buffer, const int *attrib_list)
952*61046927SAndroid Build Coastguard Worker {
953*61046927SAndroid Build Coastguard Worker    struct glx_context *gc = __glXGetCurrentContext();
954*61046927SAndroid Build Coastguard Worker 
955*61046927SAndroid Build Coastguard Worker    if (!base)
956*61046927SAndroid Build Coastguard Worker       return;
957*61046927SAndroid Build Coastguard Worker 
958*61046927SAndroid Build Coastguard Worker    if (base->psc->display->driver == GLX_DRIVER_DRI3) {
959*61046927SAndroid Build Coastguard Worker       dri_invalidate_drawable(base->dri_drawable);
960*61046927SAndroid Build Coastguard Worker 
961*61046927SAndroid Build Coastguard Worker       XSync(gc->currentDpy, false);
962*61046927SAndroid Build Coastguard Worker    }
963*61046927SAndroid Build Coastguard Worker 
964*61046927SAndroid Build Coastguard Worker    dri_set_tex_buffer2(gc->driContext,
965*61046927SAndroid Build Coastguard Worker                         base->textureTarget,
966*61046927SAndroid Build Coastguard Worker                         base->textureFormat,
967*61046927SAndroid Build Coastguard Worker                         base->dri_drawable);
968*61046927SAndroid Build Coastguard Worker }
969*61046927SAndroid Build Coastguard Worker 
970*61046927SAndroid Build Coastguard Worker bool
dri_screen_init(struct glx_screen * psc,struct glx_display * priv,int screen,int fd,const __DRIextension ** loader_extensions,bool driver_name_is_inferred)971*61046927SAndroid Build Coastguard Worker dri_screen_init(struct glx_screen *psc, struct glx_display *priv, int screen, int fd, const __DRIextension **loader_extensions, bool driver_name_is_inferred)
972*61046927SAndroid Build Coastguard Worker {
973*61046927SAndroid Build Coastguard Worker    const __DRIconfig **driver_configs;
974*61046927SAndroid Build Coastguard Worker    struct glx_config *configs = NULL, *visuals = NULL;
975*61046927SAndroid Build Coastguard Worker 
976*61046927SAndroid Build Coastguard Worker    if (!glx_screen_init(psc, screen, priv))
977*61046927SAndroid Build Coastguard Worker       return false;
978*61046927SAndroid Build Coastguard Worker 
979*61046927SAndroid Build Coastguard Worker    enum dri_screen_type type;
980*61046927SAndroid Build Coastguard Worker    switch (psc->display->driver) {
981*61046927SAndroid Build Coastguard Worker    case GLX_DRIVER_DRI3:
982*61046927SAndroid Build Coastguard Worker    case GLX_DRIVER_DRI2:
983*61046927SAndroid Build Coastguard Worker       type = DRI_SCREEN_DRI3;
984*61046927SAndroid Build Coastguard Worker       break;
985*61046927SAndroid Build Coastguard Worker    case GLX_DRIVER_ZINK_YES:
986*61046927SAndroid Build Coastguard Worker       type = DRI_SCREEN_KOPPER;
987*61046927SAndroid Build Coastguard Worker       break;
988*61046927SAndroid Build Coastguard Worker    case GLX_DRIVER_SW:
989*61046927SAndroid Build Coastguard Worker       type = DRI_SCREEN_SWRAST;
990*61046927SAndroid Build Coastguard Worker       break;
991*61046927SAndroid Build Coastguard Worker    default:
992*61046927SAndroid Build Coastguard Worker       unreachable("unknown glx driver type");
993*61046927SAndroid Build Coastguard Worker    }
994*61046927SAndroid Build Coastguard Worker 
995*61046927SAndroid Build Coastguard Worker    psc->frontend_screen = driCreateNewScreen3(screen, fd,
996*61046927SAndroid Build Coastguard Worker                                                  loader_extensions,
997*61046927SAndroid Build Coastguard Worker                                                  type,
998*61046927SAndroid Build Coastguard Worker                                                  &driver_configs, driver_name_is_inferred,
999*61046927SAndroid Build Coastguard Worker                                                  psc->display->has_multibuffer, psc);
1000*61046927SAndroid Build Coastguard Worker 
1001*61046927SAndroid Build Coastguard Worker    if (psc->frontend_screen == NULL) {
1002*61046927SAndroid Build Coastguard Worker       goto handle_error;
1003*61046927SAndroid Build Coastguard Worker    }
1004*61046927SAndroid Build Coastguard Worker 
1005*61046927SAndroid Build Coastguard Worker    configs = driConvertConfigs(psc->configs, driver_configs);
1006*61046927SAndroid Build Coastguard Worker    visuals = driConvertConfigs(psc->visuals, driver_configs);
1007*61046927SAndroid Build Coastguard Worker 
1008*61046927SAndroid Build Coastguard Worker    if (!configs || !visuals) {
1009*61046927SAndroid Build Coastguard Worker        ErrorMessageF("No matching fbConfigs or visuals found\n");
1010*61046927SAndroid Build Coastguard Worker        goto handle_error;
1011*61046927SAndroid Build Coastguard Worker    }
1012*61046927SAndroid Build Coastguard Worker 
1013*61046927SAndroid Build Coastguard Worker    glx_config_destroy_list(psc->configs);
1014*61046927SAndroid Build Coastguard Worker    psc->configs = configs;
1015*61046927SAndroid Build Coastguard Worker    glx_config_destroy_list(psc->visuals);
1016*61046927SAndroid Build Coastguard Worker    psc->visuals = visuals;
1017*61046927SAndroid Build Coastguard Worker 
1018*61046927SAndroid Build Coastguard Worker    psc->driver_configs = driver_configs;
1019*61046927SAndroid Build Coastguard Worker 
1020*61046927SAndroid Build Coastguard Worker    psc->vtable = &dri_screen_vtable;
1021*61046927SAndroid Build Coastguard Worker    psc->driScreen.bindTexImage = dri_bind_tex_image;
1022*61046927SAndroid Build Coastguard Worker 
1023*61046927SAndroid Build Coastguard Worker    return true;
1024*61046927SAndroid Build Coastguard Worker 
1025*61046927SAndroid Build Coastguard Worker handle_error:
1026*61046927SAndroid Build Coastguard Worker    if (configs)
1027*61046927SAndroid Build Coastguard Worker        glx_config_destroy_list(configs);
1028*61046927SAndroid Build Coastguard Worker    if (visuals)
1029*61046927SAndroid Build Coastguard Worker        glx_config_destroy_list(visuals);
1030*61046927SAndroid Build Coastguard Worker 
1031*61046927SAndroid Build Coastguard Worker    return false;
1032*61046927SAndroid Build Coastguard Worker }
1033*61046927SAndroid Build Coastguard Worker #endif /* GLX_DIRECT_RENDERING */
1034