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