xref: /aosp_15_r20/external/mesa3d/src/glx/drisw_glx.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2008 George Sapountzis
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*61046927SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #if defined(GLX_DIRECT_RENDERING) && (!defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE))
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker #include <xcb/xcb.h>
27*61046927SAndroid Build Coastguard Worker #include <xcb/xproto.h>
28*61046927SAndroid Build Coastguard Worker #include <xcb/shm.h>
29*61046927SAndroid Build Coastguard Worker #include <X11/Xlib.h>
30*61046927SAndroid Build Coastguard Worker #include <X11/Xlib-xcb.h>
31*61046927SAndroid Build Coastguard Worker #include "glxclient.h"
32*61046927SAndroid Build Coastguard Worker #include <dlfcn.h>
33*61046927SAndroid Build Coastguard Worker #include "dri_common.h"
34*61046927SAndroid Build Coastguard Worker #include "drisw_priv.h"
35*61046927SAndroid Build Coastguard Worker #ifdef HAVE_LIBDRM
36*61046927SAndroid Build Coastguard Worker #include "dri3_priv.h"
37*61046927SAndroid Build Coastguard Worker #endif
38*61046927SAndroid Build Coastguard Worker #include <X11/extensions/shmproto.h>
39*61046927SAndroid Build Coastguard Worker #include <assert.h>
40*61046927SAndroid Build Coastguard Worker #include <vulkan/vulkan_core.h>
41*61046927SAndroid Build Coastguard Worker #include <vulkan/vulkan_xcb.h>
42*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
43*61046927SAndroid Build Coastguard Worker #include "kopper_interface.h"
44*61046927SAndroid Build Coastguard Worker #include "loader_dri_helper.h"
45*61046927SAndroid Build Coastguard Worker #include "dri_util.h"
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker static int xshm_error = 0;
48*61046927SAndroid Build Coastguard Worker static int xshm_opcode = -1;
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker /**
51*61046927SAndroid Build Coastguard Worker  * Catches potential Xlib errors.
52*61046927SAndroid Build Coastguard Worker  */
53*61046927SAndroid Build Coastguard Worker static int
handle_xerror(Display * dpy,XErrorEvent * event)54*61046927SAndroid Build Coastguard Worker handle_xerror(Display *dpy, XErrorEvent *event)
55*61046927SAndroid Build Coastguard Worker {
56*61046927SAndroid Build Coastguard Worker    (void) dpy;
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker    assert(xshm_opcode != -1);
59*61046927SAndroid Build Coastguard Worker    if (event->request_code != xshm_opcode)
60*61046927SAndroid Build Coastguard Worker       return 0;
61*61046927SAndroid Build Coastguard Worker 
62*61046927SAndroid Build Coastguard Worker    xshm_error = event->error_code;
63*61046927SAndroid Build Coastguard Worker    return 0;
64*61046927SAndroid Build Coastguard Worker }
65*61046927SAndroid Build Coastguard Worker 
66*61046927SAndroid Build Coastguard Worker static Bool
XCreateDrawable(struct drisw_drawable * pdp,int shmid,Display * dpy)67*61046927SAndroid Build Coastguard Worker XCreateDrawable(struct drisw_drawable * pdp, int shmid, Display * dpy)
68*61046927SAndroid Build Coastguard Worker {
69*61046927SAndroid Build Coastguard Worker    if (pdp->ximage) {
70*61046927SAndroid Build Coastguard Worker       XDestroyImage(pdp->ximage);
71*61046927SAndroid Build Coastguard Worker       pdp->ximage = NULL;
72*61046927SAndroid Build Coastguard Worker       if ((pdp->shminfo.shmid > 0) && (shmid != pdp->shminfo.shmid))
73*61046927SAndroid Build Coastguard Worker          XShmDetach(dpy, &pdp->shminfo);
74*61046927SAndroid Build Coastguard Worker    }
75*61046927SAndroid Build Coastguard Worker 
76*61046927SAndroid Build Coastguard Worker    if (!xshm_error && shmid >= 0) {
77*61046927SAndroid Build Coastguard Worker       pdp->shminfo.shmid = shmid;
78*61046927SAndroid Build Coastguard Worker       pdp->ximage = XShmCreateImage(dpy,
79*61046927SAndroid Build Coastguard Worker                                     NULL,
80*61046927SAndroid Build Coastguard Worker                                     pdp->xDepth,
81*61046927SAndroid Build Coastguard Worker                                     ZPixmap,              /* format */
82*61046927SAndroid Build Coastguard Worker                                     NULL,                 /* data */
83*61046927SAndroid Build Coastguard Worker                                     &pdp->shminfo,        /* shminfo */
84*61046927SAndroid Build Coastguard Worker                                     0, 0);                /* width, height */
85*61046927SAndroid Build Coastguard Worker       if (pdp->ximage != NULL) {
86*61046927SAndroid Build Coastguard Worker          int (*old_handler)(Display *, XErrorEvent *);
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker          /* dispatch pending errors */
89*61046927SAndroid Build Coastguard Worker          XSync(dpy, False);
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker          old_handler = XSetErrorHandler(handle_xerror);
92*61046927SAndroid Build Coastguard Worker          /* This may trigger the X protocol error we're ready to catch: */
93*61046927SAndroid Build Coastguard Worker          XShmAttach(dpy, &pdp->shminfo);
94*61046927SAndroid Build Coastguard Worker          XSync(dpy, False);
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker          if (xshm_error) {
97*61046927SAndroid Build Coastguard Worker          /* we are on a remote display, this error is normal, don't print it */
98*61046927SAndroid Build Coastguard Worker             XDestroyImage(pdp->ximage);
99*61046927SAndroid Build Coastguard Worker             pdp->ximage = NULL;
100*61046927SAndroid Build Coastguard Worker          }
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker          (void) XSetErrorHandler(old_handler);
103*61046927SAndroid Build Coastguard Worker       }
104*61046927SAndroid Build Coastguard Worker    }
105*61046927SAndroid Build Coastguard Worker 
106*61046927SAndroid Build Coastguard Worker    if (pdp->ximage == NULL) {
107*61046927SAndroid Build Coastguard Worker       pdp->shminfo.shmid = -1;
108*61046927SAndroid Build Coastguard Worker       pdp->ximage = XCreateImage(dpy,
109*61046927SAndroid Build Coastguard Worker                                  NULL,
110*61046927SAndroid Build Coastguard Worker                                  pdp->xDepth,
111*61046927SAndroid Build Coastguard Worker                                  ZPixmap, 0,             /* format, offset */
112*61046927SAndroid Build Coastguard Worker                                  NULL,                   /* data */
113*61046927SAndroid Build Coastguard Worker                                  0, 0,                   /* width, height */
114*61046927SAndroid Build Coastguard Worker                                  32,                     /* bitmap_pad */
115*61046927SAndroid Build Coastguard Worker                                  0);                     /* bytes_per_line */
116*61046927SAndroid Build Coastguard Worker    }
117*61046927SAndroid Build Coastguard Worker 
118*61046927SAndroid Build Coastguard Worker   /**
119*61046927SAndroid Build Coastguard Worker    * swrast does not handle 24-bit depth with 24 bpp, so let X do the
120*61046927SAndroid Build Coastguard Worker    * the conversion for us.
121*61046927SAndroid Build Coastguard Worker    */
122*61046927SAndroid Build Coastguard Worker   if (pdp->ximage->bits_per_pixel == 24)
123*61046927SAndroid Build Coastguard Worker      pdp->ximage->bits_per_pixel = 32;
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker    return True;
126*61046927SAndroid Build Coastguard Worker }
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker static void
XDestroyDrawable(struct drisw_drawable * pdp,Display * dpy,XID drawable)129*61046927SAndroid Build Coastguard Worker XDestroyDrawable(struct drisw_drawable * pdp, Display * dpy, XID drawable)
130*61046927SAndroid Build Coastguard Worker {
131*61046927SAndroid Build Coastguard Worker    if (pdp->ximage)
132*61046927SAndroid Build Coastguard Worker       XDestroyImage(pdp->ximage);
133*61046927SAndroid Build Coastguard Worker 
134*61046927SAndroid Build Coastguard Worker    if (pdp->shminfo.shmid > 0)
135*61046927SAndroid Build Coastguard Worker       XShmDetach(dpy, &pdp->shminfo);
136*61046927SAndroid Build Coastguard Worker 
137*61046927SAndroid Build Coastguard Worker    XFreeGC(dpy, pdp->gc);
138*61046927SAndroid Build Coastguard Worker }
139*61046927SAndroid Build Coastguard Worker 
140*61046927SAndroid Build Coastguard Worker /**
141*61046927SAndroid Build Coastguard Worker  * swrast loader functions
142*61046927SAndroid Build Coastguard Worker  */
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker static void
swrastGetDrawableInfo(__DRIdrawable * draw,int * x,int * y,int * w,int * h,void * loaderPrivate)145*61046927SAndroid Build Coastguard Worker swrastGetDrawableInfo(__DRIdrawable * draw,
146*61046927SAndroid Build Coastguard Worker                       int *x, int *y, int *w, int *h,
147*61046927SAndroid Build Coastguard Worker                       void *loaderPrivate)
148*61046927SAndroid Build Coastguard Worker {
149*61046927SAndroid Build Coastguard Worker    struct drisw_drawable *pdp = loaderPrivate;
150*61046927SAndroid Build Coastguard Worker    __GLXDRIdrawable *pdraw = &(pdp->base);
151*61046927SAndroid Build Coastguard Worker    Display *dpy = pdraw->psc->dpy;
152*61046927SAndroid Build Coastguard Worker    Drawable drawable;
153*61046927SAndroid Build Coastguard Worker 
154*61046927SAndroid Build Coastguard Worker    Window root;
155*61046927SAndroid Build Coastguard Worker    unsigned uw, uh, bw, depth;
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    drawable = pdraw->xDrawable;
158*61046927SAndroid Build Coastguard Worker 
159*61046927SAndroid Build Coastguard Worker    XGetGeometry(dpy, drawable, &root, x, y, &uw, &uh, &bw, &depth);
160*61046927SAndroid Build Coastguard Worker    *w = uw;
161*61046927SAndroid Build Coastguard Worker    *h = uh;
162*61046927SAndroid Build Coastguard Worker }
163*61046927SAndroid Build Coastguard Worker 
164*61046927SAndroid Build Coastguard Worker /**
165*61046927SAndroid Build Coastguard Worker  * Align renderbuffer pitch.
166*61046927SAndroid Build Coastguard Worker  *
167*61046927SAndroid Build Coastguard Worker  * This should be chosen by the driver and the loader (libGL, xserver/glx)
168*61046927SAndroid Build Coastguard Worker  * should use the driver provided pitch.
169*61046927SAndroid Build Coastguard Worker  *
170*61046927SAndroid Build Coastguard Worker  * It seems that the xorg loader (that is the xserver loading swrast_dri for
171*61046927SAndroid Build Coastguard Worker  * indirect rendering, not client-side libGL) requires that the pitch is
172*61046927SAndroid Build Coastguard Worker  * exactly the image width padded to 32 bits. XXX
173*61046927SAndroid Build Coastguard Worker  *
174*61046927SAndroid Build Coastguard Worker  * The above restriction can probably be overcome by using ScratchPixmap and
175*61046927SAndroid Build Coastguard Worker  * CopyArea in the xserver, similar to ShmPutImage, and setting the width of
176*61046927SAndroid Build Coastguard Worker  * the scratch pixmap to 'pitch / cpp'.
177*61046927SAndroid Build Coastguard Worker  */
178*61046927SAndroid Build Coastguard Worker static inline int
bytes_per_line(unsigned pitch_bits,unsigned mul)179*61046927SAndroid Build Coastguard Worker bytes_per_line(unsigned pitch_bits, unsigned mul)
180*61046927SAndroid Build Coastguard Worker {
181*61046927SAndroid Build Coastguard Worker    unsigned mask = mul - 1;
182*61046927SAndroid Build Coastguard Worker 
183*61046927SAndroid Build Coastguard Worker    return ((pitch_bits + mask) & ~mask) / 8;
184*61046927SAndroid Build Coastguard Worker }
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker static void
swrastXPutImage(__DRIdrawable * draw,int op,int srcx,int srcy,int x,int y,int w,int h,int stride,int shmid,char * data,void * loaderPrivate)187*61046927SAndroid Build Coastguard Worker swrastXPutImage(__DRIdrawable * draw, int op,
188*61046927SAndroid Build Coastguard Worker                 int srcx, int srcy, int x, int y,
189*61046927SAndroid Build Coastguard Worker                 int w, int h, int stride,
190*61046927SAndroid Build Coastguard Worker                 int shmid, char *data, void *loaderPrivate)
191*61046927SAndroid Build Coastguard Worker {
192*61046927SAndroid Build Coastguard Worker    struct drisw_drawable *pdp = loaderPrivate;
193*61046927SAndroid Build Coastguard Worker    __GLXDRIdrawable *pdraw = &(pdp->base);
194*61046927SAndroid Build Coastguard Worker    Display *dpy = pdraw->psc->dpy;
195*61046927SAndroid Build Coastguard Worker    Drawable drawable;
196*61046927SAndroid Build Coastguard Worker    XImage *ximage;
197*61046927SAndroid Build Coastguard Worker    GC gc = pdp->gc;
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker    if (!pdp->ximage || shmid != pdp->shminfo.shmid) {
200*61046927SAndroid Build Coastguard Worker       if (!XCreateDrawable(pdp, shmid, dpy))
201*61046927SAndroid Build Coastguard Worker          return;
202*61046927SAndroid Build Coastguard Worker    }
203*61046927SAndroid Build Coastguard Worker 
204*61046927SAndroid Build Coastguard Worker    drawable = pdraw->xDrawable;
205*61046927SAndroid Build Coastguard Worker    ximage = pdp->ximage;
206*61046927SAndroid Build Coastguard Worker    ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32);
207*61046927SAndroid Build Coastguard Worker    ximage->data = data;
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker    ximage->width = ximage->bytes_per_line / ((ximage->bits_per_pixel + 7)/ 8);
210*61046927SAndroid Build Coastguard Worker    ximage->height = h;
211*61046927SAndroid Build Coastguard Worker 
212*61046927SAndroid Build Coastguard Worker    if (pdp->shminfo.shmid >= 0) {
213*61046927SAndroid Build Coastguard Worker       XShmPutImage(dpy, drawable, gc, ximage, srcx, srcy, x, y, w, h, False);
214*61046927SAndroid Build Coastguard Worker       XSync(dpy, False);
215*61046927SAndroid Build Coastguard Worker    } else {
216*61046927SAndroid Build Coastguard Worker       XPutImage(dpy, drawable, gc, ximage, srcx, srcy, x, y, w, h);
217*61046927SAndroid Build Coastguard Worker    }
218*61046927SAndroid Build Coastguard Worker    ximage->data = NULL;
219*61046927SAndroid Build Coastguard Worker }
220*61046927SAndroid Build Coastguard Worker 
221*61046927SAndroid Build Coastguard Worker static void
swrastPutImageShm(__DRIdrawable * draw,int op,int x,int y,int w,int h,int stride,int shmid,char * shmaddr,unsigned offset,void * loaderPrivate)222*61046927SAndroid Build Coastguard Worker swrastPutImageShm(__DRIdrawable * draw, int op,
223*61046927SAndroid Build Coastguard Worker                   int x, int y, int w, int h, int stride,
224*61046927SAndroid Build Coastguard Worker                   int shmid, char *shmaddr, unsigned offset,
225*61046927SAndroid Build Coastguard Worker                   void *loaderPrivate)
226*61046927SAndroid Build Coastguard Worker {
227*61046927SAndroid Build Coastguard Worker    struct drisw_drawable *pdp = loaderPrivate;
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker    if (!pdp)
230*61046927SAndroid Build Coastguard Worker       return;
231*61046927SAndroid Build Coastguard Worker 
232*61046927SAndroid Build Coastguard Worker    pdp->shminfo.shmaddr = shmaddr;
233*61046927SAndroid Build Coastguard Worker    swrastXPutImage(draw, op, 0, 0, x, y, w, h, stride, shmid,
234*61046927SAndroid Build Coastguard Worker                    shmaddr + offset, loaderPrivate);
235*61046927SAndroid Build Coastguard Worker }
236*61046927SAndroid Build Coastguard Worker 
237*61046927SAndroid Build Coastguard Worker static void
swrastPutImageShm2(__DRIdrawable * draw,int op,int x,int y,int w,int h,int stride,int shmid,char * shmaddr,unsigned offset,void * loaderPrivate)238*61046927SAndroid Build Coastguard Worker swrastPutImageShm2(__DRIdrawable * draw, int op,
239*61046927SAndroid Build Coastguard Worker                    int x, int y,
240*61046927SAndroid Build Coastguard Worker                    int w, int h, int stride,
241*61046927SAndroid Build Coastguard Worker                    int shmid, char *shmaddr, unsigned offset,
242*61046927SAndroid Build Coastguard Worker                    void *loaderPrivate)
243*61046927SAndroid Build Coastguard Worker {
244*61046927SAndroid Build Coastguard Worker    struct drisw_drawable *pdp = loaderPrivate;
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker    if (!pdp)
247*61046927SAndroid Build Coastguard Worker       return;
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker    pdp->shminfo.shmaddr = shmaddr;
250*61046927SAndroid Build Coastguard Worker    swrastXPutImage(draw, op, x, 0, x, y, w, h, stride, shmid,
251*61046927SAndroid Build Coastguard Worker                    shmaddr + offset, loaderPrivate);
252*61046927SAndroid Build Coastguard Worker }
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker static void
swrastPutImage2(__DRIdrawable * draw,int op,int x,int y,int w,int h,int stride,char * data,void * loaderPrivate)255*61046927SAndroid Build Coastguard Worker swrastPutImage2(__DRIdrawable * draw, int op,
256*61046927SAndroid Build Coastguard Worker                 int x, int y, int w, int h, int stride,
257*61046927SAndroid Build Coastguard Worker                 char *data, void *loaderPrivate)
258*61046927SAndroid Build Coastguard Worker {
259*61046927SAndroid Build Coastguard Worker    if (!loaderPrivate)
260*61046927SAndroid Build Coastguard Worker       return;
261*61046927SAndroid Build Coastguard Worker 
262*61046927SAndroid Build Coastguard Worker    swrastXPutImage(draw, op, 0, 0, x, y, w, h, stride, -1,
263*61046927SAndroid Build Coastguard Worker                    data, loaderPrivate);
264*61046927SAndroid Build Coastguard Worker }
265*61046927SAndroid Build Coastguard Worker 
266*61046927SAndroid Build Coastguard Worker static void
swrastPutImage(__DRIdrawable * draw,int op,int x,int y,int w,int h,char * data,void * loaderPrivate)267*61046927SAndroid Build Coastguard Worker swrastPutImage(__DRIdrawable * draw, int op,
268*61046927SAndroid Build Coastguard Worker                int x, int y, int w, int h,
269*61046927SAndroid Build Coastguard Worker                char *data, void *loaderPrivate)
270*61046927SAndroid Build Coastguard Worker {
271*61046927SAndroid Build Coastguard Worker    if (!loaderPrivate)
272*61046927SAndroid Build Coastguard Worker       return;
273*61046927SAndroid Build Coastguard Worker 
274*61046927SAndroid Build Coastguard Worker    swrastXPutImage(draw, op, 0, 0, x, y, w, h, 0, -1,
275*61046927SAndroid Build Coastguard Worker                    data, loaderPrivate);
276*61046927SAndroid Build Coastguard Worker }
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker static void
swrastGetImage2(__DRIdrawable * read,int x,int y,int w,int h,int stride,char * data,void * loaderPrivate)279*61046927SAndroid Build Coastguard Worker swrastGetImage2(__DRIdrawable * read,
280*61046927SAndroid Build Coastguard Worker                 int x, int y, int w, int h, int stride,
281*61046927SAndroid Build Coastguard Worker                 char *data, void *loaderPrivate)
282*61046927SAndroid Build Coastguard Worker {
283*61046927SAndroid Build Coastguard Worker    struct drisw_drawable *prp = loaderPrivate;
284*61046927SAndroid Build Coastguard Worker    __GLXDRIdrawable *pread = &(prp->base);
285*61046927SAndroid Build Coastguard Worker    Display *dpy = pread->psc->dpy;
286*61046927SAndroid Build Coastguard Worker    Drawable readable;
287*61046927SAndroid Build Coastguard Worker    XImage *ximage;
288*61046927SAndroid Build Coastguard Worker 
289*61046927SAndroid Build Coastguard Worker    if (!prp->ximage || prp->shminfo.shmid >= 0) {
290*61046927SAndroid Build Coastguard Worker       if (!XCreateDrawable(prp, -1, dpy))
291*61046927SAndroid Build Coastguard Worker          return;
292*61046927SAndroid Build Coastguard Worker    }
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker    readable = pread->xDrawable;
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker    ximage = prp->ximage;
297*61046927SAndroid Build Coastguard Worker    ximage->data = data;
298*61046927SAndroid Build Coastguard Worker    ximage->width = w;
299*61046927SAndroid Build Coastguard Worker    ximage->height = h;
300*61046927SAndroid Build Coastguard Worker    ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32);
301*61046927SAndroid Build Coastguard Worker 
302*61046927SAndroid Build Coastguard Worker    XGetSubImage(dpy, readable, x, y, w, h, ~0L, ZPixmap, ximage, 0, 0);
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker    ximage->data = NULL;
305*61046927SAndroid Build Coastguard Worker }
306*61046927SAndroid Build Coastguard Worker 
307*61046927SAndroid Build Coastguard Worker static void
swrastGetImage(__DRIdrawable * read,int x,int y,int w,int h,char * data,void * loaderPrivate)308*61046927SAndroid Build Coastguard Worker swrastGetImage(__DRIdrawable * read,
309*61046927SAndroid Build Coastguard Worker                int x, int y, int w, int h,
310*61046927SAndroid Build Coastguard Worker                char *data, void *loaderPrivate)
311*61046927SAndroid Build Coastguard Worker {
312*61046927SAndroid Build Coastguard Worker    swrastGetImage2(read, x, y, w, h, 0, data, loaderPrivate);
313*61046927SAndroid Build Coastguard Worker }
314*61046927SAndroid Build Coastguard Worker 
315*61046927SAndroid Build Coastguard Worker static GLboolean
swrastGetImageShm2(__DRIdrawable * read,int x,int y,int w,int h,int shmid,void * loaderPrivate)316*61046927SAndroid Build Coastguard Worker swrastGetImageShm2(__DRIdrawable * read,
317*61046927SAndroid Build Coastguard Worker                    int x, int y, int w, int h,
318*61046927SAndroid Build Coastguard Worker                    int shmid, void *loaderPrivate)
319*61046927SAndroid Build Coastguard Worker {
320*61046927SAndroid Build Coastguard Worker    struct drisw_drawable *prp = loaderPrivate;
321*61046927SAndroid Build Coastguard Worker    __GLXDRIdrawable *pread = &(prp->base);
322*61046927SAndroid Build Coastguard Worker    Display *dpy = pread->psc->dpy;
323*61046927SAndroid Build Coastguard Worker    Drawable readable;
324*61046927SAndroid Build Coastguard Worker    XImage *ximage;
325*61046927SAndroid Build Coastguard Worker 
326*61046927SAndroid Build Coastguard Worker    if (!prp->ximage || shmid != prp->shminfo.shmid) {
327*61046927SAndroid Build Coastguard Worker       if (!XCreateDrawable(prp, shmid, dpy))
328*61046927SAndroid Build Coastguard Worker          return GL_FALSE;
329*61046927SAndroid Build Coastguard Worker    }
330*61046927SAndroid Build Coastguard Worker 
331*61046927SAndroid Build Coastguard Worker    if (prp->shminfo.shmid == -1)
332*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
333*61046927SAndroid Build Coastguard Worker    readable = pread->xDrawable;
334*61046927SAndroid Build Coastguard Worker 
335*61046927SAndroid Build Coastguard Worker    ximage = prp->ximage;
336*61046927SAndroid Build Coastguard Worker    ximage->data = prp->shminfo.shmaddr; /* no offset */
337*61046927SAndroid Build Coastguard Worker    ximage->width = w;
338*61046927SAndroid Build Coastguard Worker    ximage->height = h;
339*61046927SAndroid Build Coastguard Worker    ximage->bytes_per_line = bytes_per_line(w * ximage->bits_per_pixel, 32);
340*61046927SAndroid Build Coastguard Worker 
341*61046927SAndroid Build Coastguard Worker    XShmGetImage(dpy, readable, ximage, x, y, ~0L);
342*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
343*61046927SAndroid Build Coastguard Worker }
344*61046927SAndroid Build Coastguard Worker 
345*61046927SAndroid Build Coastguard Worker static void
swrastGetImageShm(__DRIdrawable * read,int x,int y,int w,int h,int shmid,void * loaderPrivate)346*61046927SAndroid Build Coastguard Worker swrastGetImageShm(__DRIdrawable * read,
347*61046927SAndroid Build Coastguard Worker                   int x, int y, int w, int h,
348*61046927SAndroid Build Coastguard Worker                   int shmid, void *loaderPrivate)
349*61046927SAndroid Build Coastguard Worker {
350*61046927SAndroid Build Coastguard Worker    swrastGetImageShm2(read, x, y, w, h, shmid, loaderPrivate);
351*61046927SAndroid Build Coastguard Worker }
352*61046927SAndroid Build Coastguard Worker 
353*61046927SAndroid Build Coastguard Worker static const __DRIswrastLoaderExtension swrastLoaderExtension_shm = {
354*61046927SAndroid Build Coastguard Worker    .base = {__DRI_SWRAST_LOADER, 6 },
355*61046927SAndroid Build Coastguard Worker 
356*61046927SAndroid Build Coastguard Worker    .getDrawableInfo     = swrastGetDrawableInfo,
357*61046927SAndroid Build Coastguard Worker    .putImage            = swrastPutImage,
358*61046927SAndroid Build Coastguard Worker    .getImage            = swrastGetImage,
359*61046927SAndroid Build Coastguard Worker    .putImage2           = swrastPutImage2,
360*61046927SAndroid Build Coastguard Worker    .getImage2           = swrastGetImage2,
361*61046927SAndroid Build Coastguard Worker    .putImageShm         = swrastPutImageShm,
362*61046927SAndroid Build Coastguard Worker    .getImageShm         = swrastGetImageShm,
363*61046927SAndroid Build Coastguard Worker    .putImageShm2        = swrastPutImageShm2,
364*61046927SAndroid Build Coastguard Worker    .getImageShm2        = swrastGetImageShm2,
365*61046927SAndroid Build Coastguard Worker };
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker static const __DRIswrastLoaderExtension swrastLoaderExtension = {
368*61046927SAndroid Build Coastguard Worker    .base = {__DRI_SWRAST_LOADER, 3 },
369*61046927SAndroid Build Coastguard Worker 
370*61046927SAndroid Build Coastguard Worker    .getDrawableInfo     = swrastGetDrawableInfo,
371*61046927SAndroid Build Coastguard Worker    .putImage            = swrastPutImage,
372*61046927SAndroid Build Coastguard Worker    .getImage            = swrastGetImage,
373*61046927SAndroid Build Coastguard Worker    .putImage2           = swrastPutImage2,
374*61046927SAndroid Build Coastguard Worker    .getImage2           = swrastGetImage2,
375*61046927SAndroid Build Coastguard Worker };
376*61046927SAndroid Build Coastguard Worker 
377*61046927SAndroid Build Coastguard Worker static_assert(sizeof(struct kopper_vk_surface_create_storage) >= sizeof(VkXcbSurfaceCreateInfoKHR), "");
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker static void
kopperSetSurfaceCreateInfo(void * _draw,struct kopper_loader_info * out)380*61046927SAndroid Build Coastguard Worker kopperSetSurfaceCreateInfo(void *_draw, struct kopper_loader_info *out)
381*61046927SAndroid Build Coastguard Worker {
382*61046927SAndroid Build Coastguard Worker     __GLXDRIdrawable *draw = _draw;
383*61046927SAndroid Build Coastguard Worker     VkXcbSurfaceCreateInfoKHR *xcb = (VkXcbSurfaceCreateInfoKHR *)&out->bos;
384*61046927SAndroid Build Coastguard Worker 
385*61046927SAndroid Build Coastguard Worker     xcb->sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
386*61046927SAndroid Build Coastguard Worker     xcb->pNext = NULL;
387*61046927SAndroid Build Coastguard Worker     xcb->flags = 0;
388*61046927SAndroid Build Coastguard Worker     xcb->connection = XGetXCBConnection(draw->psc->dpy);
389*61046927SAndroid Build Coastguard Worker     xcb->window = draw->xDrawable;
390*61046927SAndroid Build Coastguard Worker }
391*61046927SAndroid Build Coastguard Worker 
392*61046927SAndroid Build Coastguard Worker static const __DRIkopperLoaderExtension kopperLoaderExtension = {
393*61046927SAndroid Build Coastguard Worker     .base = { __DRI_KOPPER_LOADER, 1 },
394*61046927SAndroid Build Coastguard Worker 
395*61046927SAndroid Build Coastguard Worker     .SetSurfaceCreateInfo   = kopperSetSurfaceCreateInfo,
396*61046927SAndroid Build Coastguard Worker };
397*61046927SAndroid Build Coastguard Worker 
398*61046927SAndroid Build Coastguard Worker static const __DRIextension *loader_extensions_shm[] = {
399*61046927SAndroid Build Coastguard Worker    &swrastLoaderExtension_shm.base,
400*61046927SAndroid Build Coastguard Worker    &kopperLoaderExtension.base,
401*61046927SAndroid Build Coastguard Worker    NULL
402*61046927SAndroid Build Coastguard Worker };
403*61046927SAndroid Build Coastguard Worker 
404*61046927SAndroid Build Coastguard Worker static const __DRIextension *loader_extensions_noshm[] = {
405*61046927SAndroid Build Coastguard Worker    &swrastLoaderExtension.base,
406*61046927SAndroid Build Coastguard Worker    &kopperLoaderExtension.base,
407*61046927SAndroid Build Coastguard Worker    NULL
408*61046927SAndroid Build Coastguard Worker };
409*61046927SAndroid Build Coastguard Worker 
410*61046927SAndroid Build Coastguard Worker static const __DRIextension *kopper_extensions_noshm[] = {
411*61046927SAndroid Build Coastguard Worker    &swrastLoaderExtension.base,
412*61046927SAndroid Build Coastguard Worker    &kopperLoaderExtension.base,
413*61046927SAndroid Build Coastguard Worker    &dri2UseInvalidate.base,
414*61046927SAndroid Build Coastguard Worker    &driBackgroundCallable.base,
415*61046927SAndroid Build Coastguard Worker    NULL
416*61046927SAndroid Build Coastguard Worker };
417*61046927SAndroid Build Coastguard Worker 
418*61046927SAndroid Build Coastguard Worker /**
419*61046927SAndroid Build Coastguard Worker  * GLXDRI functions
420*61046927SAndroid Build Coastguard Worker  */
421*61046927SAndroid Build Coastguard Worker 
422*61046927SAndroid Build Coastguard Worker 
423*61046927SAndroid Build Coastguard Worker static void
drisw_wait_gl(struct glx_context * context)424*61046927SAndroid Build Coastguard Worker drisw_wait_gl(struct glx_context *context)
425*61046927SAndroid Build Coastguard Worker {
426*61046927SAndroid Build Coastguard Worker    glFinish();
427*61046927SAndroid Build Coastguard Worker }
428*61046927SAndroid Build Coastguard Worker 
429*61046927SAndroid Build Coastguard Worker static void
drisw_wait_x(struct glx_context * context)430*61046927SAndroid Build Coastguard Worker drisw_wait_x(struct glx_context *context)
431*61046927SAndroid Build Coastguard Worker {
432*61046927SAndroid Build Coastguard Worker    XSync(context->currentDpy, False);
433*61046927SAndroid Build Coastguard Worker }
434*61046927SAndroid Build Coastguard Worker 
435*61046927SAndroid Build Coastguard Worker int
436*61046927SAndroid Build Coastguard Worker kopper_get_buffer_age(__GLXDRIdrawable *pdraw);
437*61046927SAndroid Build Coastguard Worker int
kopper_get_buffer_age(__GLXDRIdrawable * pdraw)438*61046927SAndroid Build Coastguard Worker kopper_get_buffer_age(__GLXDRIdrawable *pdraw)
439*61046927SAndroid Build Coastguard Worker {
440*61046927SAndroid Build Coastguard Worker    return kopperQueryBufferAge(pdraw->dri_drawable);
441*61046927SAndroid Build Coastguard Worker }
442*61046927SAndroid Build Coastguard Worker 
443*61046927SAndroid Build Coastguard Worker static const struct glx_context_vtable drisw_context_vtable = {
444*61046927SAndroid Build Coastguard Worker    .destroy             = dri_destroy_context,
445*61046927SAndroid Build Coastguard Worker    .bind                = dri_bind_context,
446*61046927SAndroid Build Coastguard Worker    .unbind              = dri_unbind_context,
447*61046927SAndroid Build Coastguard Worker    .wait_gl             = drisw_wait_gl,
448*61046927SAndroid Build Coastguard Worker    .wait_x              = drisw_wait_x,
449*61046927SAndroid Build Coastguard Worker };
450*61046927SAndroid Build Coastguard Worker 
451*61046927SAndroid Build Coastguard Worker static void
driswDestroyDrawable(__GLXDRIdrawable * pdraw)452*61046927SAndroid Build Coastguard Worker driswDestroyDrawable(__GLXDRIdrawable * pdraw)
453*61046927SAndroid Build Coastguard Worker {
454*61046927SAndroid Build Coastguard Worker    struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
455*61046927SAndroid Build Coastguard Worker 
456*61046927SAndroid Build Coastguard Worker    driDestroyDrawable(pdp->base.dri_drawable);
457*61046927SAndroid Build Coastguard Worker 
458*61046927SAndroid Build Coastguard Worker    XDestroyDrawable(pdp, pdraw->psc->dpy, pdraw->drawable);
459*61046927SAndroid Build Coastguard Worker    free(pdp);
460*61046927SAndroid Build Coastguard Worker }
461*61046927SAndroid Build Coastguard Worker 
462*61046927SAndroid Build Coastguard Worker static __GLXDRIdrawable *
driswCreateDrawable(struct glx_screen * base,XID xDrawable,GLXDrawable drawable,int type,struct glx_config * modes)463*61046927SAndroid Build Coastguard Worker driswCreateDrawable(struct glx_screen *base, XID xDrawable,
464*61046927SAndroid Build Coastguard Worker                     GLXDrawable drawable, int type,
465*61046927SAndroid Build Coastguard Worker                     struct glx_config *modes)
466*61046927SAndroid Build Coastguard Worker {
467*61046927SAndroid Build Coastguard Worker    struct drisw_drawable *pdp;
468*61046927SAndroid Build Coastguard Worker    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
469*61046927SAndroid Build Coastguard Worker    unsigned depth;
470*61046927SAndroid Build Coastguard Worker    struct drisw_screen *psc = (struct drisw_screen *) base;
471*61046927SAndroid Build Coastguard Worker    Display *dpy = psc->base.dpy;
472*61046927SAndroid Build Coastguard Worker 
473*61046927SAndroid Build Coastguard Worker    xcb_connection_t *conn = XGetXCBConnection(dpy);
474*61046927SAndroid Build Coastguard Worker    xcb_generic_error_t *error;
475*61046927SAndroid Build Coastguard Worker    xcb_get_geometry_cookie_t cookie = xcb_get_geometry(conn, xDrawable);
476*61046927SAndroid Build Coastguard Worker    xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(conn, cookie, &error);
477*61046927SAndroid Build Coastguard Worker    if (reply)
478*61046927SAndroid Build Coastguard Worker       depth = reply->depth;
479*61046927SAndroid Build Coastguard Worker    free(reply);
480*61046927SAndroid Build Coastguard Worker    if (!reply || error)
481*61046927SAndroid Build Coastguard Worker       return NULL;
482*61046927SAndroid Build Coastguard Worker 
483*61046927SAndroid Build Coastguard Worker    pdp = calloc(1, sizeof(*pdp));
484*61046927SAndroid Build Coastguard Worker    if (!pdp)
485*61046927SAndroid Build Coastguard Worker       return NULL;
486*61046927SAndroid Build Coastguard Worker 
487*61046927SAndroid Build Coastguard Worker    pdp->base.xDrawable = xDrawable;
488*61046927SAndroid Build Coastguard Worker    pdp->base.drawable = drawable;
489*61046927SAndroid Build Coastguard Worker    pdp->base.psc = &psc->base;
490*61046927SAndroid Build Coastguard Worker    pdp->config = modes;
491*61046927SAndroid Build Coastguard Worker    pdp->gc = XCreateGC(dpy, xDrawable, 0, NULL);
492*61046927SAndroid Build Coastguard Worker    pdp->xDepth = 0;
493*61046927SAndroid Build Coastguard Worker 
494*61046927SAndroid Build Coastguard Worker    /* Use the visual depth, if this fbconfig corresponds to a visual */
495*61046927SAndroid Build Coastguard Worker    if (pdp->config->visualID != 0) {
496*61046927SAndroid Build Coastguard Worker       int matches = 0;
497*61046927SAndroid Build Coastguard Worker       XVisualInfo *visinfo, template;
498*61046927SAndroid Build Coastguard Worker 
499*61046927SAndroid Build Coastguard Worker       template.visualid = pdp->config->visualID;
500*61046927SAndroid Build Coastguard Worker       template.screen = pdp->config->screen;
501*61046927SAndroid Build Coastguard Worker       visinfo = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask,
502*61046927SAndroid Build Coastguard Worker                                &template, &matches);
503*61046927SAndroid Build Coastguard Worker 
504*61046927SAndroid Build Coastguard Worker       if (visinfo && matches) {
505*61046927SAndroid Build Coastguard Worker          pdp->xDepth = visinfo->depth;
506*61046927SAndroid Build Coastguard Worker          XFree(visinfo);
507*61046927SAndroid Build Coastguard Worker       }
508*61046927SAndroid Build Coastguard Worker    }
509*61046927SAndroid Build Coastguard Worker 
510*61046927SAndroid Build Coastguard Worker    /* Otherwise, or if XGetVisualInfo failed, ask the server */
511*61046927SAndroid Build Coastguard Worker    if (pdp->xDepth == 0) {
512*61046927SAndroid Build Coastguard Worker       pdp->xDepth = depth;
513*61046927SAndroid Build Coastguard Worker    }
514*61046927SAndroid Build Coastguard Worker 
515*61046927SAndroid Build Coastguard Worker    pdp->swapInterval = dri_get_initial_swap_interval(psc->base.frontend_screen);
516*61046927SAndroid Build Coastguard Worker    /* Create a new drawable */
517*61046927SAndroid Build Coastguard Worker    pdp->base.dri_drawable = dri_create_drawable(psc->base.frontend_screen, config->driConfig, !(type & GLX_WINDOW_BIT), pdp);
518*61046927SAndroid Build Coastguard Worker    if (psc->kopper)
519*61046927SAndroid Build Coastguard Worker       kopperSetSwapInterval(pdp->base.dri_drawable, pdp->swapInterval);
520*61046927SAndroid Build Coastguard Worker 
521*61046927SAndroid Build Coastguard Worker    if (!pdp->base.dri_drawable) {
522*61046927SAndroid Build Coastguard Worker       XDestroyDrawable(pdp, psc->base.dpy, xDrawable);
523*61046927SAndroid Build Coastguard Worker       free(pdp);
524*61046927SAndroid Build Coastguard Worker       return NULL;
525*61046927SAndroid Build Coastguard Worker    }
526*61046927SAndroid Build Coastguard Worker 
527*61046927SAndroid Build Coastguard Worker    pdp->base.destroyDrawable = driswDestroyDrawable;
528*61046927SAndroid Build Coastguard Worker 
529*61046927SAndroid Build Coastguard Worker    return &pdp->base;
530*61046927SAndroid Build Coastguard Worker }
531*61046927SAndroid Build Coastguard Worker 
532*61046927SAndroid Build Coastguard Worker static int64_t
driswSwapBuffers(__GLXDRIdrawable * pdraw,int64_t target_msc,int64_t divisor,int64_t remainder,Bool flush)533*61046927SAndroid Build Coastguard Worker driswSwapBuffers(__GLXDRIdrawable * pdraw,
534*61046927SAndroid Build Coastguard Worker                  int64_t target_msc, int64_t divisor, int64_t remainder,
535*61046927SAndroid Build Coastguard Worker                  Bool flush)
536*61046927SAndroid Build Coastguard Worker {
537*61046927SAndroid Build Coastguard Worker    struct drisw_screen *psc = (struct drisw_screen *) pdraw->psc;
538*61046927SAndroid Build Coastguard Worker 
539*61046927SAndroid Build Coastguard Worker    (void) target_msc;
540*61046927SAndroid Build Coastguard Worker    (void) divisor;
541*61046927SAndroid Build Coastguard Worker    (void) remainder;
542*61046927SAndroid Build Coastguard Worker 
543*61046927SAndroid Build Coastguard Worker    if (flush) {
544*61046927SAndroid Build Coastguard Worker       glFlush();
545*61046927SAndroid Build Coastguard Worker    }
546*61046927SAndroid Build Coastguard Worker 
547*61046927SAndroid Build Coastguard Worker    if (psc->kopper)
548*61046927SAndroid Build Coastguard Worker        return kopperSwapBuffers(pdraw->dri_drawable, 0);
549*61046927SAndroid Build Coastguard Worker 
550*61046927SAndroid Build Coastguard Worker    driSwapBuffers(pdraw->dri_drawable);
551*61046927SAndroid Build Coastguard Worker 
552*61046927SAndroid Build Coastguard Worker    return 0;
553*61046927SAndroid Build Coastguard Worker }
554*61046927SAndroid Build Coastguard Worker 
555*61046927SAndroid Build Coastguard Worker static void
drisw_copy_sub_buffer(__GLXDRIdrawable * pdraw,int x,int y,int width,int height,Bool flush)556*61046927SAndroid Build Coastguard Worker drisw_copy_sub_buffer(__GLXDRIdrawable * pdraw,
557*61046927SAndroid Build Coastguard Worker                       int x, int y, int width, int height, Bool flush)
558*61046927SAndroid Build Coastguard Worker {
559*61046927SAndroid Build Coastguard Worker    if (flush) {
560*61046927SAndroid Build Coastguard Worker       glFlush();
561*61046927SAndroid Build Coastguard Worker    }
562*61046927SAndroid Build Coastguard Worker 
563*61046927SAndroid Build Coastguard Worker    driswCopySubBuffer(pdraw->dri_drawable, x, y, width, height);
564*61046927SAndroid Build Coastguard Worker }
565*61046927SAndroid Build Coastguard Worker 
566*61046927SAndroid Build Coastguard Worker static int
check_xshm(Display * dpy)567*61046927SAndroid Build Coastguard Worker check_xshm(Display *dpy)
568*61046927SAndroid Build Coastguard Worker {
569*61046927SAndroid Build Coastguard Worker    xcb_connection_t *c = XGetXCBConnection(dpy);
570*61046927SAndroid Build Coastguard Worker    xcb_void_cookie_t cookie;
571*61046927SAndroid Build Coastguard Worker    xcb_generic_error_t *error;
572*61046927SAndroid Build Coastguard Worker    int ret = True;
573*61046927SAndroid Build Coastguard Worker    xcb_query_extension_cookie_t shm_cookie;
574*61046927SAndroid Build Coastguard Worker    xcb_query_extension_reply_t *shm_reply;
575*61046927SAndroid Build Coastguard Worker    bool has_mit_shm;
576*61046927SAndroid Build Coastguard Worker 
577*61046927SAndroid Build Coastguard Worker    shm_cookie = xcb_query_extension(c, 7, "MIT-SHM");
578*61046927SAndroid Build Coastguard Worker    shm_reply = xcb_query_extension_reply(c, shm_cookie, NULL);
579*61046927SAndroid Build Coastguard Worker    xshm_opcode = shm_reply->major_opcode;
580*61046927SAndroid Build Coastguard Worker 
581*61046927SAndroid Build Coastguard Worker    has_mit_shm = shm_reply->present;
582*61046927SAndroid Build Coastguard Worker    free(shm_reply);
583*61046927SAndroid Build Coastguard Worker    if (!has_mit_shm)
584*61046927SAndroid Build Coastguard Worker       return False;
585*61046927SAndroid Build Coastguard Worker 
586*61046927SAndroid Build Coastguard Worker    cookie = xcb_shm_detach_checked(c, 0);
587*61046927SAndroid Build Coastguard Worker    if ((error = xcb_request_check(c, cookie))) {
588*61046927SAndroid Build Coastguard Worker       /* BadRequest means we're a remote client. If we were local we'd
589*61046927SAndroid Build Coastguard Worker        * expect BadValue since 'info' has an invalid segment name.
590*61046927SAndroid Build Coastguard Worker        */
591*61046927SAndroid Build Coastguard Worker       if (error->error_code == BadRequest)
592*61046927SAndroid Build Coastguard Worker          ret = False;
593*61046927SAndroid Build Coastguard Worker       free(error);
594*61046927SAndroid Build Coastguard Worker    }
595*61046927SAndroid Build Coastguard Worker 
596*61046927SAndroid Build Coastguard Worker    return ret;
597*61046927SAndroid Build Coastguard Worker }
598*61046927SAndroid Build Coastguard Worker 
599*61046927SAndroid Build Coastguard Worker static int
driswKopperSetSwapInterval(__GLXDRIdrawable * pdraw,int interval)600*61046927SAndroid Build Coastguard Worker driswKopperSetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
601*61046927SAndroid Build Coastguard Worker {
602*61046927SAndroid Build Coastguard Worker    struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
603*61046927SAndroid Build Coastguard Worker    struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
604*61046927SAndroid Build Coastguard Worker 
605*61046927SAndroid Build Coastguard Worker    if (!dri_valid_swap_interval(psc->base.frontend_screen, interval))
606*61046927SAndroid Build Coastguard Worker       return GLX_BAD_VALUE;
607*61046927SAndroid Build Coastguard Worker 
608*61046927SAndroid Build Coastguard Worker    kopperSetSwapInterval(pdp->base.dri_drawable, interval);
609*61046927SAndroid Build Coastguard Worker    pdp->swapInterval = interval;
610*61046927SAndroid Build Coastguard Worker 
611*61046927SAndroid Build Coastguard Worker    return 0;
612*61046927SAndroid Build Coastguard Worker }
613*61046927SAndroid Build Coastguard Worker 
614*61046927SAndroid Build Coastguard Worker static int
kopperGetSwapInterval(__GLXDRIdrawable * pdraw)615*61046927SAndroid Build Coastguard Worker kopperGetSwapInterval(__GLXDRIdrawable *pdraw)
616*61046927SAndroid Build Coastguard Worker {
617*61046927SAndroid Build Coastguard Worker    struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
618*61046927SAndroid Build Coastguard Worker 
619*61046927SAndroid Build Coastguard Worker    return pdp->swapInterval;
620*61046927SAndroid Build Coastguard Worker }
621*61046927SAndroid Build Coastguard Worker 
622*61046927SAndroid Build Coastguard Worker struct glx_screen *
driswCreateScreen(int screen,struct glx_display * priv,enum glx_driver glx_driver,bool driver_name_is_inferred)623*61046927SAndroid Build Coastguard Worker driswCreateScreen(int screen, struct glx_display *priv, enum glx_driver glx_driver, bool driver_name_is_inferred)
624*61046927SAndroid Build Coastguard Worker {
625*61046927SAndroid Build Coastguard Worker    __GLXDRIscreen *psp;
626*61046927SAndroid Build Coastguard Worker    struct drisw_screen *psc;
627*61046927SAndroid Build Coastguard Worker    const __DRIextension **loader_extensions_local;
628*61046927SAndroid Build Coastguard Worker    bool kopper_disable = debug_get_bool_option("LIBGL_KOPPER_DISABLE", false);
629*61046927SAndroid Build Coastguard Worker 
630*61046927SAndroid Build Coastguard Worker    /* this is only relevant if zink bits are set */
631*61046927SAndroid Build Coastguard Worker    glx_driver &= (GLX_DRIVER_ZINK_INFER | GLX_DRIVER_ZINK_YES);
632*61046927SAndroid Build Coastguard Worker    const char *driver = glx_driver && !kopper_disable ? "zink" : "swrast";
633*61046927SAndroid Build Coastguard Worker 
634*61046927SAndroid Build Coastguard Worker    psc = calloc(1, sizeof *psc);
635*61046927SAndroid Build Coastguard Worker    if (psc == NULL)
636*61046927SAndroid Build Coastguard Worker       return NULL;
637*61046927SAndroid Build Coastguard Worker    psc->kopper = !strcmp(driver, "zink");
638*61046927SAndroid Build Coastguard Worker 
639*61046927SAndroid Build Coastguard Worker    if (!glx_screen_init(&psc->base, screen, priv)) {
640*61046927SAndroid Build Coastguard Worker       free(psc);
641*61046927SAndroid Build Coastguard Worker       return NULL;
642*61046927SAndroid Build Coastguard Worker    }
643*61046927SAndroid Build Coastguard Worker 
644*61046927SAndroid Build Coastguard Worker    psc->base.driverName = strdup(driver);
645*61046927SAndroid Build Coastguard Worker 
646*61046927SAndroid Build Coastguard Worker    if (glx_driver)
647*61046927SAndroid Build Coastguard Worker       loader_extensions_local = kopper_extensions_noshm;
648*61046927SAndroid Build Coastguard Worker    else if (!check_xshm(psc->base.dpy))
649*61046927SAndroid Build Coastguard Worker       loader_extensions_local = loader_extensions_noshm;
650*61046927SAndroid Build Coastguard Worker    else
651*61046927SAndroid Build Coastguard Worker       loader_extensions_local = loader_extensions_shm;
652*61046927SAndroid Build Coastguard Worker    priv->driver = glx_driver ? GLX_DRIVER_ZINK_YES : GLX_DRIVER_SW;
653*61046927SAndroid Build Coastguard Worker 
654*61046927SAndroid Build Coastguard Worker    if (!dri_screen_init(&psc->base, priv, screen, -1, loader_extensions_local, driver_name_is_inferred)) {
655*61046927SAndroid Build Coastguard Worker       if (!glx_driver || !driver_name_is_inferred)
656*61046927SAndroid Build Coastguard Worker          ErrorMessageF("glx: failed to create drisw screen\n");
657*61046927SAndroid Build Coastguard Worker       goto handle_error;
658*61046927SAndroid Build Coastguard Worker    }
659*61046927SAndroid Build Coastguard Worker 
660*61046927SAndroid Build Coastguard Worker    psc->base.context_vtable = &drisw_context_vtable;
661*61046927SAndroid Build Coastguard Worker    psp = &psc->base.driScreen;
662*61046927SAndroid Build Coastguard Worker    psc->base.can_EXT_texture_from_pixmap = true;
663*61046927SAndroid Build Coastguard Worker    psp->createDrawable = driswCreateDrawable;
664*61046927SAndroid Build Coastguard Worker    psp->swapBuffers = driswSwapBuffers;
665*61046927SAndroid Build Coastguard Worker 
666*61046927SAndroid Build Coastguard Worker    if (!glx_driver)
667*61046927SAndroid Build Coastguard Worker       psp->copySubBuffer = drisw_copy_sub_buffer;
668*61046927SAndroid Build Coastguard Worker 
669*61046927SAndroid Build Coastguard Worker    if (psc->kopper) {
670*61046927SAndroid Build Coastguard Worker       psp->setSwapInterval = driswKopperSetSwapInterval;
671*61046927SAndroid Build Coastguard Worker       psp->getSwapInterval = kopperGetSwapInterval;
672*61046927SAndroid Build Coastguard Worker       psp->maxSwapInterval = 1;
673*61046927SAndroid Build Coastguard Worker    }
674*61046927SAndroid Build Coastguard Worker 
675*61046927SAndroid Build Coastguard Worker    return &psc->base;
676*61046927SAndroid Build Coastguard Worker 
677*61046927SAndroid Build Coastguard Worker  handle_error:
678*61046927SAndroid Build Coastguard Worker 
679*61046927SAndroid Build Coastguard Worker    glx_screen_cleanup(&psc->base);
680*61046927SAndroid Build Coastguard Worker    free(psc);
681*61046927SAndroid Build Coastguard Worker 
682*61046927SAndroid Build Coastguard Worker    if (glx_driver & GLX_DRIVER_ZINK_YES && !driver_name_is_inferred)
683*61046927SAndroid Build Coastguard Worker       CriticalErrorMessageF("failed to load driver: %s\n", driver);
684*61046927SAndroid Build Coastguard Worker 
685*61046927SAndroid Build Coastguard Worker    return NULL;
686*61046927SAndroid Build Coastguard Worker }
687*61046927SAndroid Build Coastguard Worker 
688*61046927SAndroid Build Coastguard Worker #endif /* GLX_DIRECT_RENDERING */
689