1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright © 2007 Red Hat, Inc
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Permission to use, copy, modify, distribute, and sell this software
5*4882a593Smuzhiyun * and its documentation for any purpose is hereby granted without
6*4882a593Smuzhiyun * fee, provided that the above copyright notice appear in all copies
7*4882a593Smuzhiyun * and that both that copyright notice and this permission notice
8*4882a593Smuzhiyun * appear in supporting documentation, and that the name of Red Hat,
9*4882a593Smuzhiyun * Inc not be used in advertising or publicity pertaining to
10*4882a593Smuzhiyun * distribution of the software without specific, written prior
11*4882a593Smuzhiyun * permission. Red Hat, Inc makes no representations about the
12*4882a593Smuzhiyun * suitability of this software for any purpose. It is provided "as
13*4882a593Smuzhiyun * is" without express or implied warranty.
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16*4882a593Smuzhiyun * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17*4882a593Smuzhiyun * NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18*4882a593Smuzhiyun * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19*4882a593Smuzhiyun * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20*4882a593Smuzhiyun * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21*4882a593Smuzhiyun * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
25*4882a593Smuzhiyun #include <dix-config.h>
26*4882a593Smuzhiyun #endif
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #include <stdint.h>
29*4882a593Smuzhiyun #include <stdio.h>
30*4882a593Smuzhiyun #include <string.h>
31*4882a593Smuzhiyun #include <errno.h>
32*4882a593Smuzhiyun #include <dlfcn.h>
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #include <GL/gl.h>
35*4882a593Smuzhiyun #include <GL/internal/dri_interface.h>
36*4882a593Smuzhiyun #include <GL/glxtokens.h>
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #include <windowstr.h>
39*4882a593Smuzhiyun #include <os.h>
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun #define _XF86DRI_SERVER_
42*4882a593Smuzhiyun #include <xf86.h>
43*4882a593Smuzhiyun #include <dri2.h>
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #include <GL/glxtokens.h>
46*4882a593Smuzhiyun #include "glxserver.h"
47*4882a593Smuzhiyun #include "glxutil.h"
48*4882a593Smuzhiyun #include "glxdricommon.h"
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #include "extension_string.h"
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun typedef struct __GLXDRIscreen __GLXDRIscreen;
53*4882a593Smuzhiyun typedef struct __GLXDRIcontext __GLXDRIcontext;
54*4882a593Smuzhiyun typedef struct __GLXDRIdrawable __GLXDRIdrawable;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #define ALL_DRI_CTX_FLAGS (__DRI_CTX_FLAG_DEBUG \
57*4882a593Smuzhiyun | __DRI_CTX_FLAG_FORWARD_COMPATIBLE \
58*4882a593Smuzhiyun | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS)
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun struct __GLXDRIscreen {
61*4882a593Smuzhiyun __GLXscreen base;
62*4882a593Smuzhiyun __DRIscreen *driScreen;
63*4882a593Smuzhiyun void *driver;
64*4882a593Smuzhiyun int fd;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun xf86EnterVTProc *enterVT;
67*4882a593Smuzhiyun xf86LeaveVTProc *leaveVT;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun const __DRIcoreExtension *core;
70*4882a593Smuzhiyun const __DRIdri2Extension *dri2;
71*4882a593Smuzhiyun const __DRI2flushExtension *flush;
72*4882a593Smuzhiyun const __DRIcopySubBufferExtension *copySubBuffer;
73*4882a593Smuzhiyun const __DRIswapControlExtension *swapControl;
74*4882a593Smuzhiyun const __DRItexBufferExtension *texBuffer;
75*4882a593Smuzhiyun const __DRIconfig **driConfigs;
76*4882a593Smuzhiyun };
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun struct __GLXDRIcontext {
79*4882a593Smuzhiyun __GLXcontext base;
80*4882a593Smuzhiyun __DRIcontext *driContext;
81*4882a593Smuzhiyun };
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun #define MAX_DRAWABLE_BUFFERS 5
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun struct __GLXDRIdrawable {
86*4882a593Smuzhiyun __GLXdrawable base;
87*4882a593Smuzhiyun __DRIdrawable *driDrawable;
88*4882a593Smuzhiyun __GLXDRIscreen *screen;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /* Dimensions as last reported by DRI2GetBuffers. */
91*4882a593Smuzhiyun int width;
92*4882a593Smuzhiyun int height;
93*4882a593Smuzhiyun __DRIbuffer buffers[MAX_DRAWABLE_BUFFERS];
94*4882a593Smuzhiyun int count;
95*4882a593Smuzhiyun XID dri2_id;
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun static void
copy_box(__GLXdrawable * drawable,int dst,int src,int x,int y,int w,int h)99*4882a593Smuzhiyun copy_box(__GLXdrawable * drawable,
100*4882a593Smuzhiyun int dst, int src,
101*4882a593Smuzhiyun int x, int y, int w, int h)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun BoxRec box;
104*4882a593Smuzhiyun RegionRec region;
105*4882a593Smuzhiyun __GLXcontext *cx = lastGLContext;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun box.x1 = x;
108*4882a593Smuzhiyun box.y1 = y;
109*4882a593Smuzhiyun box.x2 = x + w;
110*4882a593Smuzhiyun box.y2 = y + h;
111*4882a593Smuzhiyun RegionInit(®ion, &box, 0);
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun DRI2CopyRegion(drawable->pDraw, ®ion, dst, src);
114*4882a593Smuzhiyun if (cx != lastGLContext) {
115*4882a593Smuzhiyun lastGLContext = cx;
116*4882a593Smuzhiyun cx->makeCurrent(cx);
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun /* white lie */
121*4882a593Smuzhiyun extern glx_func_ptr glXGetProcAddressARB(const char *);
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun static void
__glXDRIdrawableDestroy(__GLXdrawable * drawable)124*4882a593Smuzhiyun __glXDRIdrawableDestroy(__GLXdrawable * drawable)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
127*4882a593Smuzhiyun const __DRIcoreExtension *core = private->screen->core;
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun FreeResource(private->dri2_id, FALSE);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun (*core->destroyDrawable) (private->driDrawable);
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun __glXDrawableRelease(drawable);
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun free(private);
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun static void
__glXDRIdrawableCopySubBuffer(__GLXdrawable * drawable,int x,int y,int w,int h)139*4882a593Smuzhiyun __glXDRIdrawableCopySubBuffer(__GLXdrawable * drawable,
140*4882a593Smuzhiyun int x, int y, int w, int h)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun copy_box(drawable, x, private->height - y - h,
145*4882a593Smuzhiyun w, h,
146*4882a593Smuzhiyun DRI2BufferFrontLeft, DRI2BufferBackLeft);
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun static void
__glXDRIdrawableWaitX(__GLXdrawable * drawable)150*4882a593Smuzhiyun __glXDRIdrawableWaitX(__GLXdrawable * drawable)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun copy_box(drawable, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft,
155*4882a593Smuzhiyun 0, 0, private->width, private->height);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun static void
__glXDRIdrawableWaitGL(__GLXdrawable * drawable)159*4882a593Smuzhiyun __glXDRIdrawableWaitGL(__GLXdrawable * drawable)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun copy_box(drawable, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft,
164*4882a593Smuzhiyun 0, 0, private->width, private->height);
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun static void
__glXdriSwapEvent(ClientPtr client,void * data,int type,CARD64 ust,CARD64 msc,CARD32 sbc)168*4882a593Smuzhiyun __glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
169*4882a593Smuzhiyun CARD64 msc, CARD32 sbc)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun __GLXdrawable *drawable = data;
172*4882a593Smuzhiyun int glx_type;
173*4882a593Smuzhiyun switch (type) {
174*4882a593Smuzhiyun case DRI2_EXCHANGE_COMPLETE:
175*4882a593Smuzhiyun glx_type = GLX_EXCHANGE_COMPLETE_INTEL;
176*4882a593Smuzhiyun break;
177*4882a593Smuzhiyun default:
178*4882a593Smuzhiyun /* unknown swap completion type,
179*4882a593Smuzhiyun * BLIT is a reasonable default, so
180*4882a593Smuzhiyun * fall through ...
181*4882a593Smuzhiyun */
182*4882a593Smuzhiyun case DRI2_BLIT_COMPLETE:
183*4882a593Smuzhiyun glx_type = GLX_BLIT_COMPLETE_INTEL;
184*4882a593Smuzhiyun break;
185*4882a593Smuzhiyun case DRI2_FLIP_COMPLETE:
186*4882a593Smuzhiyun glx_type = GLX_FLIP_COMPLETE_INTEL;
187*4882a593Smuzhiyun break;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun __glXsendSwapEvent(drawable, glx_type, ust, msc, sbc);
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun /*
194*4882a593Smuzhiyun * Copy or flip back to front, honoring the swap interval if possible.
195*4882a593Smuzhiyun *
196*4882a593Smuzhiyun * If the kernel supports it, we request an event for the frame when the
197*4882a593Smuzhiyun * swap should happen, then perform the copy when we receive it.
198*4882a593Smuzhiyun */
199*4882a593Smuzhiyun static GLboolean
__glXDRIdrawableSwapBuffers(ClientPtr client,__GLXdrawable * drawable)200*4882a593Smuzhiyun __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable * drawable)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
203*4882a593Smuzhiyun __GLXDRIscreen *screen = priv->screen;
204*4882a593Smuzhiyun CARD64 unused;
205*4882a593Smuzhiyun __GLXcontext *cx = lastGLContext;
206*4882a593Smuzhiyun int status;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun if (screen->flush) {
209*4882a593Smuzhiyun (*screen->flush->flush) (priv->driDrawable);
210*4882a593Smuzhiyun (*screen->flush->invalidate) (priv->driDrawable);
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun status = DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
214*4882a593Smuzhiyun __glXdriSwapEvent, drawable);
215*4882a593Smuzhiyun if (cx != lastGLContext) {
216*4882a593Smuzhiyun lastGLContext = cx;
217*4882a593Smuzhiyun cx->makeCurrent(cx);
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun return status == Success;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun static int
__glXDRIdrawableSwapInterval(__GLXdrawable * drawable,int interval)224*4882a593Smuzhiyun __glXDRIdrawableSwapInterval(__GLXdrawable * drawable, int interval)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun __GLXcontext *cx = lastGLContext;
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun if (interval <= 0) /* || interval > BIGNUM? */
229*4882a593Smuzhiyun return GLX_BAD_VALUE;
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun DRI2SwapInterval(drawable->pDraw, interval);
232*4882a593Smuzhiyun if (cx != lastGLContext) {
233*4882a593Smuzhiyun lastGLContext = cx;
234*4882a593Smuzhiyun cx->makeCurrent(cx);
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun return 0;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun static void
__glXDRIcontextDestroy(__GLXcontext * baseContext)241*4882a593Smuzhiyun __glXDRIcontextDestroy(__GLXcontext * baseContext)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
244*4882a593Smuzhiyun __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun (*screen->core->destroyContext) (context->driContext);
247*4882a593Smuzhiyun __glXContextDestroy(&context->base);
248*4882a593Smuzhiyun free(context);
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun static int
__glXDRIcontextMakeCurrent(__GLXcontext * baseContext)252*4882a593Smuzhiyun __glXDRIcontextMakeCurrent(__GLXcontext * baseContext)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
255*4882a593Smuzhiyun __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
256*4882a593Smuzhiyun __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
257*4882a593Smuzhiyun __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun return (*screen->core->bindContext) (context->driContext,
260*4882a593Smuzhiyun draw->driDrawable, read->driDrawable);
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun static int
__glXDRIcontextLoseCurrent(__GLXcontext * baseContext)264*4882a593Smuzhiyun __glXDRIcontextLoseCurrent(__GLXcontext * baseContext)
265*4882a593Smuzhiyun {
266*4882a593Smuzhiyun __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
267*4882a593Smuzhiyun __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun return (*screen->core->unbindContext) (context->driContext);
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun static int
__glXDRIcontextCopy(__GLXcontext * baseDst,__GLXcontext * baseSrc,unsigned long mask)273*4882a593Smuzhiyun __glXDRIcontextCopy(__GLXcontext * baseDst, __GLXcontext * baseSrc,
274*4882a593Smuzhiyun unsigned long mask)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
277*4882a593Smuzhiyun __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
278*4882a593Smuzhiyun __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun return (*screen->core->copyContext) (dst->driContext,
281*4882a593Smuzhiyun src->driContext, mask);
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun static Bool
__glXDRIcontextWait(__GLXcontext * baseContext,__GLXclientState * cl,int * error)285*4882a593Smuzhiyun __glXDRIcontextWait(__GLXcontext * baseContext,
286*4882a593Smuzhiyun __GLXclientState * cl, int *error)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun __GLXcontext *cx = lastGLContext;
289*4882a593Smuzhiyun Bool ret;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun ret = DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw);
292*4882a593Smuzhiyun if (cx != lastGLContext) {
293*4882a593Smuzhiyun lastGLContext = cx;
294*4882a593Smuzhiyun cx->makeCurrent(cx);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun if (ret) {
298*4882a593Smuzhiyun *error = cl->client->noClientException;
299*4882a593Smuzhiyun return TRUE;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun return FALSE;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun static int
__glXDRIbindTexImage(__GLXcontext * baseContext,int buffer,__GLXdrawable * glxPixmap)306*4882a593Smuzhiyun __glXDRIbindTexImage(__GLXcontext * baseContext,
307*4882a593Smuzhiyun int buffer, __GLXdrawable * glxPixmap)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
310*4882a593Smuzhiyun const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
311*4882a593Smuzhiyun __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun if (texBuffer == NULL)
314*4882a593Smuzhiyun return Success;
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
317*4882a593Smuzhiyun (*texBuffer->setTexBuffer2) (context->driContext,
318*4882a593Smuzhiyun glxPixmap->target,
319*4882a593Smuzhiyun glxPixmap->format, drawable->driDrawable);
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun else
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun texBuffer->setTexBuffer(context->driContext,
324*4882a593Smuzhiyun glxPixmap->target, drawable->driDrawable);
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun return Success;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun static int
__glXDRIreleaseTexImage(__GLXcontext * baseContext,int buffer,__GLXdrawable * pixmap)331*4882a593Smuzhiyun __glXDRIreleaseTexImage(__GLXcontext * baseContext,
332*4882a593Smuzhiyun int buffer, __GLXdrawable * pixmap)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun /* FIXME: Just unbind the texture? */
335*4882a593Smuzhiyun return Success;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun static Bool
dri2_convert_glx_attribs(__GLXDRIscreen * screen,unsigned num_attribs,const uint32_t * attribs,unsigned * major_ver,unsigned * minor_ver,uint32_t * flags,int * api,int * reset,unsigned * error)339*4882a593Smuzhiyun dri2_convert_glx_attribs(__GLXDRIscreen *screen, unsigned num_attribs,
340*4882a593Smuzhiyun const uint32_t *attribs,
341*4882a593Smuzhiyun unsigned *major_ver, unsigned *minor_ver,
342*4882a593Smuzhiyun uint32_t *flags, int *api, int *reset, unsigned *error)
343*4882a593Smuzhiyun {
344*4882a593Smuzhiyun unsigned i;
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun if (num_attribs == 0)
347*4882a593Smuzhiyun return TRUE;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun if (attribs == NULL) {
350*4882a593Smuzhiyun *error = BadImplementation;
351*4882a593Smuzhiyun return FALSE;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun *major_ver = 1;
355*4882a593Smuzhiyun *minor_ver = 0;
356*4882a593Smuzhiyun *reset = __DRI_CTX_RESET_NO_NOTIFICATION;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun for (i = 0; i < num_attribs; i++) {
359*4882a593Smuzhiyun switch (attribs[i * 2]) {
360*4882a593Smuzhiyun case GLX_CONTEXT_MAJOR_VERSION_ARB:
361*4882a593Smuzhiyun *major_ver = attribs[i * 2 + 1];
362*4882a593Smuzhiyun break;
363*4882a593Smuzhiyun case GLX_CONTEXT_MINOR_VERSION_ARB:
364*4882a593Smuzhiyun *minor_ver = attribs[i * 2 + 1];
365*4882a593Smuzhiyun break;
366*4882a593Smuzhiyun case GLX_CONTEXT_FLAGS_ARB:
367*4882a593Smuzhiyun *flags = attribs[i * 2 + 1];
368*4882a593Smuzhiyun break;
369*4882a593Smuzhiyun case GLX_RENDER_TYPE:
370*4882a593Smuzhiyun break;
371*4882a593Smuzhiyun case GLX_CONTEXT_PROFILE_MASK_ARB:
372*4882a593Smuzhiyun switch (attribs[i * 2 + 1]) {
373*4882a593Smuzhiyun case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
374*4882a593Smuzhiyun *api = __DRI_API_OPENGL_CORE;
375*4882a593Smuzhiyun break;
376*4882a593Smuzhiyun case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
377*4882a593Smuzhiyun *api = __DRI_API_OPENGL;
378*4882a593Smuzhiyun break;
379*4882a593Smuzhiyun case GLX_CONTEXT_ES2_PROFILE_BIT_EXT:
380*4882a593Smuzhiyun *api = __DRI_API_GLES2;
381*4882a593Smuzhiyun break;
382*4882a593Smuzhiyun default:
383*4882a593Smuzhiyun *error = __glXError(GLXBadProfileARB);
384*4882a593Smuzhiyun return FALSE;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun break;
387*4882a593Smuzhiyun case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB:
388*4882a593Smuzhiyun if (screen->dri2->base.version >= 4) {
389*4882a593Smuzhiyun *error = BadValue;
390*4882a593Smuzhiyun return FALSE;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun switch (attribs[i * 2 + 1]) {
394*4882a593Smuzhiyun case GLX_NO_RESET_NOTIFICATION_ARB:
395*4882a593Smuzhiyun *reset = __DRI_CTX_RESET_NO_NOTIFICATION;
396*4882a593Smuzhiyun break;
397*4882a593Smuzhiyun case GLX_LOSE_CONTEXT_ON_RESET_ARB:
398*4882a593Smuzhiyun *reset = __DRI_CTX_RESET_LOSE_CONTEXT;
399*4882a593Smuzhiyun break;
400*4882a593Smuzhiyun default:
401*4882a593Smuzhiyun *error = BadValue;
402*4882a593Smuzhiyun return FALSE;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun break;
405*4882a593Smuzhiyun case GLX_SCREEN:
406*4882a593Smuzhiyun /* already checked for us */
407*4882a593Smuzhiyun break;
408*4882a593Smuzhiyun case GLX_CONTEXT_OPENGL_NO_ERROR_ARB:
409*4882a593Smuzhiyun /* ignore */
410*4882a593Smuzhiyun break;
411*4882a593Smuzhiyun default:
412*4882a593Smuzhiyun /* If an unknown attribute is received, fail.
413*4882a593Smuzhiyun */
414*4882a593Smuzhiyun *error = BadValue;
415*4882a593Smuzhiyun return FALSE;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun /* Unknown flag value.
420*4882a593Smuzhiyun */
421*4882a593Smuzhiyun if ((*flags & ~ALL_DRI_CTX_FLAGS) != 0) {
422*4882a593Smuzhiyun *error = BadValue;
423*4882a593Smuzhiyun return FALSE;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun /* If the core profile is requested for a GL version is less than 3.2,
427*4882a593Smuzhiyun * request the non-core profile from the DRI driver. The core profile
428*4882a593Smuzhiyun * only makes sense for GL versions >= 3.2, and many DRI drivers that
429*4882a593Smuzhiyun * don't support OpenGL 3.2 may fail the request for a core profile.
430*4882a593Smuzhiyun */
431*4882a593Smuzhiyun if (*api == __DRI_API_OPENGL_CORE
432*4882a593Smuzhiyun && (*major_ver < 3 || (*major_ver == 3 && *minor_ver < 2))) {
433*4882a593Smuzhiyun *api = __DRI_API_OPENGL;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun *error = Success;
437*4882a593Smuzhiyun return TRUE;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun static void
create_driver_context(__GLXDRIcontext * context,__GLXDRIscreen * screen,__GLXDRIconfig * config,__DRIcontext * driShare,unsigned num_attribs,const uint32_t * attribs,int * error)441*4882a593Smuzhiyun create_driver_context(__GLXDRIcontext * context,
442*4882a593Smuzhiyun __GLXDRIscreen * screen,
443*4882a593Smuzhiyun __GLXDRIconfig * config,
444*4882a593Smuzhiyun __DRIcontext * driShare,
445*4882a593Smuzhiyun unsigned num_attribs,
446*4882a593Smuzhiyun const uint32_t *attribs,
447*4882a593Smuzhiyun int *error)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun const __DRIconfig *driConfig = config ? config->driConfig : NULL;
450*4882a593Smuzhiyun context->driContext = NULL;
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun if (screen->dri2->base.version >= 3) {
453*4882a593Smuzhiyun uint32_t ctx_attribs[4 * 2];
454*4882a593Smuzhiyun unsigned num_ctx_attribs = 0;
455*4882a593Smuzhiyun unsigned dri_err = 0;
456*4882a593Smuzhiyun unsigned major_ver;
457*4882a593Smuzhiyun unsigned minor_ver;
458*4882a593Smuzhiyun uint32_t flags = 0;
459*4882a593Smuzhiyun int reset;
460*4882a593Smuzhiyun int api = __DRI_API_OPENGL;
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun if (num_attribs != 0) {
463*4882a593Smuzhiyun if (!dri2_convert_glx_attribs(screen, num_attribs, attribs,
464*4882a593Smuzhiyun &major_ver, &minor_ver,
465*4882a593Smuzhiyun &flags, &api, &reset,
466*4882a593Smuzhiyun (unsigned *) error))
467*4882a593Smuzhiyun return;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
470*4882a593Smuzhiyun ctx_attribs[num_ctx_attribs++] = major_ver;
471*4882a593Smuzhiyun ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
472*4882a593Smuzhiyun ctx_attribs[num_ctx_attribs++] = minor_ver;
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun if (flags != 0) {
475*4882a593Smuzhiyun ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun /* The current __DRI_CTX_FLAG_* values are identical to the
478*4882a593Smuzhiyun * GLX_CONTEXT_*_BIT values.
479*4882a593Smuzhiyun */
480*4882a593Smuzhiyun ctx_attribs[num_ctx_attribs++] = flags;
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) {
484*4882a593Smuzhiyun ctx_attribs[num_ctx_attribs++] =
485*4882a593Smuzhiyun __DRI_CTX_ATTRIB_RESET_STRATEGY;
486*4882a593Smuzhiyun ctx_attribs[num_ctx_attribs++] = reset;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun assert(num_ctx_attribs <= ARRAY_SIZE(ctx_attribs));
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun context->driContext =
493*4882a593Smuzhiyun (*screen->dri2->createContextAttribs)(screen->driScreen, api,
494*4882a593Smuzhiyun driConfig, driShare,
495*4882a593Smuzhiyun num_ctx_attribs / 2,
496*4882a593Smuzhiyun ctx_attribs,
497*4882a593Smuzhiyun &dri_err,
498*4882a593Smuzhiyun context);
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun switch (dri_err) {
501*4882a593Smuzhiyun case __DRI_CTX_ERROR_SUCCESS:
502*4882a593Smuzhiyun *error = Success;
503*4882a593Smuzhiyun break;
504*4882a593Smuzhiyun case __DRI_CTX_ERROR_NO_MEMORY:
505*4882a593Smuzhiyun *error = BadAlloc;
506*4882a593Smuzhiyun break;
507*4882a593Smuzhiyun case __DRI_CTX_ERROR_BAD_API:
508*4882a593Smuzhiyun *error = __glXError(GLXBadProfileARB);
509*4882a593Smuzhiyun break;
510*4882a593Smuzhiyun case __DRI_CTX_ERROR_BAD_VERSION:
511*4882a593Smuzhiyun case __DRI_CTX_ERROR_BAD_FLAG:
512*4882a593Smuzhiyun *error = __glXError(GLXBadFBConfig);
513*4882a593Smuzhiyun break;
514*4882a593Smuzhiyun case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
515*4882a593Smuzhiyun case __DRI_CTX_ERROR_UNKNOWN_FLAG:
516*4882a593Smuzhiyun default:
517*4882a593Smuzhiyun *error = BadValue;
518*4882a593Smuzhiyun break;
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun return;
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun if (num_attribs != 0) {
525*4882a593Smuzhiyun *error = BadValue;
526*4882a593Smuzhiyun return;
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun context->driContext =
530*4882a593Smuzhiyun (*screen->dri2->createNewContext) (screen->driScreen, driConfig,
531*4882a593Smuzhiyun driShare, context);
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun static __GLXcontext *
__glXDRIscreenCreateContext(__GLXscreen * baseScreen,__GLXconfig * glxConfig,__GLXcontext * baseShareContext,unsigned num_attribs,const uint32_t * attribs,int * error)535*4882a593Smuzhiyun __glXDRIscreenCreateContext(__GLXscreen * baseScreen,
536*4882a593Smuzhiyun __GLXconfig * glxConfig,
537*4882a593Smuzhiyun __GLXcontext * baseShareContext,
538*4882a593Smuzhiyun unsigned num_attribs,
539*4882a593Smuzhiyun const uint32_t *attribs,
540*4882a593Smuzhiyun int *error)
541*4882a593Smuzhiyun {
542*4882a593Smuzhiyun __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
543*4882a593Smuzhiyun __GLXDRIcontext *context, *shareContext;
544*4882a593Smuzhiyun __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
545*4882a593Smuzhiyun __DRIcontext *driShare;
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun shareContext = (__GLXDRIcontext *) baseShareContext;
548*4882a593Smuzhiyun if (shareContext)
549*4882a593Smuzhiyun driShare = shareContext->driContext;
550*4882a593Smuzhiyun else
551*4882a593Smuzhiyun driShare = NULL;
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun context = calloc(1, sizeof *context);
554*4882a593Smuzhiyun if (context == NULL) {
555*4882a593Smuzhiyun *error = BadAlloc;
556*4882a593Smuzhiyun return NULL;
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun context->base.config = glxConfig;
560*4882a593Smuzhiyun context->base.destroy = __glXDRIcontextDestroy;
561*4882a593Smuzhiyun context->base.makeCurrent = __glXDRIcontextMakeCurrent;
562*4882a593Smuzhiyun context->base.loseCurrent = __glXDRIcontextLoseCurrent;
563*4882a593Smuzhiyun context->base.copy = __glXDRIcontextCopy;
564*4882a593Smuzhiyun context->base.bindTexImage = __glXDRIbindTexImage;
565*4882a593Smuzhiyun context->base.releaseTexImage = __glXDRIreleaseTexImage;
566*4882a593Smuzhiyun context->base.wait = __glXDRIcontextWait;
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun create_driver_context(context, screen, config, driShare, num_attribs,
569*4882a593Smuzhiyun attribs, error);
570*4882a593Smuzhiyun if (context->driContext == NULL) {
571*4882a593Smuzhiyun free(context);
572*4882a593Smuzhiyun return NULL;
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun return &context->base;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun static void
__glXDRIinvalidateBuffers(DrawablePtr pDraw,void * priv,XID id)579*4882a593Smuzhiyun __glXDRIinvalidateBuffers(DrawablePtr pDraw, void *priv, XID id)
580*4882a593Smuzhiyun {
581*4882a593Smuzhiyun __GLXDRIdrawable *private = priv;
582*4882a593Smuzhiyun __GLXDRIscreen *screen = private->screen;
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun if (screen->flush)
585*4882a593Smuzhiyun (*screen->flush->invalidate) (private->driDrawable);
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun static __GLXdrawable *
__glXDRIscreenCreateDrawable(ClientPtr client,__GLXscreen * screen,DrawablePtr pDraw,XID drawId,int type,XID glxDrawId,__GLXconfig * glxConfig)589*4882a593Smuzhiyun __glXDRIscreenCreateDrawable(ClientPtr client,
590*4882a593Smuzhiyun __GLXscreen * screen,
591*4882a593Smuzhiyun DrawablePtr pDraw,
592*4882a593Smuzhiyun XID drawId,
593*4882a593Smuzhiyun int type, XID glxDrawId, __GLXconfig * glxConfig)
594*4882a593Smuzhiyun {
595*4882a593Smuzhiyun __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
596*4882a593Smuzhiyun __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
597*4882a593Smuzhiyun __GLXDRIdrawable *private;
598*4882a593Smuzhiyun __GLXcontext *cx = lastGLContext;
599*4882a593Smuzhiyun Bool ret;
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun private = calloc(1, sizeof *private);
602*4882a593Smuzhiyun if (private == NULL)
603*4882a593Smuzhiyun return NULL;
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun private->screen = driScreen;
606*4882a593Smuzhiyun if (!__glXDrawableInit(&private->base, screen,
607*4882a593Smuzhiyun pDraw, type, glxDrawId, glxConfig)) {
608*4882a593Smuzhiyun free(private);
609*4882a593Smuzhiyun return NULL;
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun private->base.destroy = __glXDRIdrawableDestroy;
613*4882a593Smuzhiyun private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
614*4882a593Smuzhiyun private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
615*4882a593Smuzhiyun private->base.waitGL = __glXDRIdrawableWaitGL;
616*4882a593Smuzhiyun private->base.waitX = __glXDRIdrawableWaitX;
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun ret = DRI2CreateDrawable2(client, pDraw, drawId,
619*4882a593Smuzhiyun __glXDRIinvalidateBuffers, private,
620*4882a593Smuzhiyun &private->dri2_id);
621*4882a593Smuzhiyun if (cx != lastGLContext) {
622*4882a593Smuzhiyun lastGLContext = cx;
623*4882a593Smuzhiyun cx->makeCurrent(cx);
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun if (ret) {
627*4882a593Smuzhiyun free(private);
628*4882a593Smuzhiyun return NULL;
629*4882a593Smuzhiyun }
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun private->driDrawable =
632*4882a593Smuzhiyun (*driScreen->dri2->createNewDrawable) (driScreen->driScreen,
633*4882a593Smuzhiyun config->driConfig, private);
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun return &private->base;
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun static __DRIbuffer *
dri2GetBuffers(__DRIdrawable * driDrawable,int * width,int * height,unsigned int * attachments,int count,int * out_count,void * loaderPrivate)639*4882a593Smuzhiyun dri2GetBuffers(__DRIdrawable * driDrawable,
640*4882a593Smuzhiyun int *width, int *height,
641*4882a593Smuzhiyun unsigned int *attachments, int count,
642*4882a593Smuzhiyun int *out_count, void *loaderPrivate)
643*4882a593Smuzhiyun {
644*4882a593Smuzhiyun __GLXDRIdrawable *private = loaderPrivate;
645*4882a593Smuzhiyun DRI2BufferPtr *buffers;
646*4882a593Smuzhiyun int i;
647*4882a593Smuzhiyun int j;
648*4882a593Smuzhiyun __GLXcontext *cx = lastGLContext;
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun buffers = DRI2GetBuffers(private->base.pDraw,
651*4882a593Smuzhiyun width, height, attachments, count, out_count);
652*4882a593Smuzhiyun if (cx != lastGLContext) {
653*4882a593Smuzhiyun lastGLContext = cx;
654*4882a593Smuzhiyun cx->makeCurrent(cx);
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun /* If DRI2GetBuffers() changed the GL context, it may also have
657*4882a593Smuzhiyun * invalidated the DRI2 buffers, so let's get them again
658*4882a593Smuzhiyun */
659*4882a593Smuzhiyun buffers = DRI2GetBuffers(private->base.pDraw,
660*4882a593Smuzhiyun width, height, attachments, count, out_count);
661*4882a593Smuzhiyun assert(lastGLContext == cx);
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun if (*out_count > MAX_DRAWABLE_BUFFERS) {
665*4882a593Smuzhiyun *out_count = 0;
666*4882a593Smuzhiyun return NULL;
667*4882a593Smuzhiyun }
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun private->width = *width;
670*4882a593Smuzhiyun private->height = *height;
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun /* This assumes the DRI2 buffer attachment tokens matches the
673*4882a593Smuzhiyun * __DRIbuffer tokens. */
674*4882a593Smuzhiyun j = 0;
675*4882a593Smuzhiyun for (i = 0; i < *out_count; i++) {
676*4882a593Smuzhiyun /* Do not send the real front buffer of a window to the client.
677*4882a593Smuzhiyun */
678*4882a593Smuzhiyun if ((private->base.pDraw->type == DRAWABLE_WINDOW)
679*4882a593Smuzhiyun && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
680*4882a593Smuzhiyun continue;
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun private->buffers[j].attachment = buffers[i]->attachment;
684*4882a593Smuzhiyun private->buffers[j].name = buffers[i]->name;
685*4882a593Smuzhiyun private->buffers[j].pitch = buffers[i]->pitch;
686*4882a593Smuzhiyun private->buffers[j].cpp = buffers[i]->cpp;
687*4882a593Smuzhiyun private->buffers[j].flags = buffers[i]->flags;
688*4882a593Smuzhiyun j++;
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun *out_count = j;
692*4882a593Smuzhiyun return private->buffers;
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun static __DRIbuffer *
dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,int * width,int * height,unsigned int * attachments,int count,int * out_count,void * loaderPrivate)696*4882a593Smuzhiyun dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
697*4882a593Smuzhiyun int *width, int *height,
698*4882a593Smuzhiyun unsigned int *attachments, int count,
699*4882a593Smuzhiyun int *out_count, void *loaderPrivate)
700*4882a593Smuzhiyun {
701*4882a593Smuzhiyun __GLXDRIdrawable *private = loaderPrivate;
702*4882a593Smuzhiyun DRI2BufferPtr *buffers;
703*4882a593Smuzhiyun int i;
704*4882a593Smuzhiyun int j = 0;
705*4882a593Smuzhiyun __GLXcontext *cx = lastGLContext;
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
708*4882a593Smuzhiyun width, height, attachments, count,
709*4882a593Smuzhiyun out_count);
710*4882a593Smuzhiyun if (cx != lastGLContext) {
711*4882a593Smuzhiyun lastGLContext = cx;
712*4882a593Smuzhiyun cx->makeCurrent(cx);
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun /* If DRI2GetBuffersWithFormat() changed the GL context, it may also have
715*4882a593Smuzhiyun * invalidated the DRI2 buffers, so let's get them again
716*4882a593Smuzhiyun */
717*4882a593Smuzhiyun buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
718*4882a593Smuzhiyun width, height, attachments, count,
719*4882a593Smuzhiyun out_count);
720*4882a593Smuzhiyun assert(lastGLContext == cx);
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun if (*out_count > MAX_DRAWABLE_BUFFERS) {
724*4882a593Smuzhiyun *out_count = 0;
725*4882a593Smuzhiyun return NULL;
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun private->width = *width;
729*4882a593Smuzhiyun private->height = *height;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun /* This assumes the DRI2 buffer attachment tokens matches the
732*4882a593Smuzhiyun * __DRIbuffer tokens. */
733*4882a593Smuzhiyun for (i = 0; i < *out_count; i++) {
734*4882a593Smuzhiyun /* Do not send the real front buffer of a window to the client.
735*4882a593Smuzhiyun */
736*4882a593Smuzhiyun if ((private->base.pDraw->type == DRAWABLE_WINDOW)
737*4882a593Smuzhiyun && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
738*4882a593Smuzhiyun continue;
739*4882a593Smuzhiyun }
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun private->buffers[j].attachment = buffers[i]->attachment;
742*4882a593Smuzhiyun private->buffers[j].name = buffers[i]->name;
743*4882a593Smuzhiyun private->buffers[j].pitch = buffers[i]->pitch;
744*4882a593Smuzhiyun private->buffers[j].cpp = buffers[i]->cpp;
745*4882a593Smuzhiyun private->buffers[j].flags = buffers[i]->flags;
746*4882a593Smuzhiyun j++;
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun *out_count = j;
750*4882a593Smuzhiyun return private->buffers;
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun static void
dri2FlushFrontBuffer(__DRIdrawable * driDrawable,void * loaderPrivate)754*4882a593Smuzhiyun dri2FlushFrontBuffer(__DRIdrawable * driDrawable, void *loaderPrivate)
755*4882a593Smuzhiyun {
756*4882a593Smuzhiyun __GLXDRIdrawable *private = (__GLXDRIdrawable *) loaderPrivate;
757*4882a593Smuzhiyun (void) driDrawable;
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun copy_box(loaderPrivate, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft,
760*4882a593Smuzhiyun 0, 0, private->width, private->height);
761*4882a593Smuzhiyun }
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun static const __DRIdri2LoaderExtension loaderExtension = {
764*4882a593Smuzhiyun {__DRI_DRI2_LOADER, 3},
765*4882a593Smuzhiyun dri2GetBuffers,
766*4882a593Smuzhiyun dri2FlushFrontBuffer,
767*4882a593Smuzhiyun dri2GetBuffersWithFormat,
768*4882a593Smuzhiyun };
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun static const __DRIuseInvalidateExtension dri2UseInvalidate = {
771*4882a593Smuzhiyun {__DRI_USE_INVALIDATE, 1}
772*4882a593Smuzhiyun };
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun static const __DRIextension *loader_extensions[] = {
775*4882a593Smuzhiyun &loaderExtension.base,
776*4882a593Smuzhiyun &dri2UseInvalidate.base,
777*4882a593Smuzhiyun NULL
778*4882a593Smuzhiyun };
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun static Bool
glxDRIEnterVT(ScrnInfoPtr scrn)781*4882a593Smuzhiyun glxDRIEnterVT(ScrnInfoPtr scrn)
782*4882a593Smuzhiyun {
783*4882a593Smuzhiyun Bool ret;
784*4882a593Smuzhiyun __GLXDRIscreen *screen = (__GLXDRIscreen *)
785*4882a593Smuzhiyun glxGetScreen(xf86ScrnToScreen(scrn));
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n");
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun scrn->EnterVT = screen->enterVT;
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun ret = scrn->EnterVT(scrn);
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun screen->enterVT = scrn->EnterVT;
794*4882a593Smuzhiyun scrn->EnterVT = glxDRIEnterVT;
795*4882a593Smuzhiyun
796*4882a593Smuzhiyun if (!ret)
797*4882a593Smuzhiyun return FALSE;
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun glxResumeClients();
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun return TRUE;
802*4882a593Smuzhiyun }
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun static void
glxDRILeaveVT(ScrnInfoPtr scrn)805*4882a593Smuzhiyun glxDRILeaveVT(ScrnInfoPtr scrn)
806*4882a593Smuzhiyun {
807*4882a593Smuzhiyun __GLXDRIscreen *screen = (__GLXDRIscreen *)
808*4882a593Smuzhiyun glxGetScreen(xf86ScrnToScreen(scrn));
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun LogMessageVerbSigSafe(X_INFO, -1, "AIGLX: Suspending AIGLX clients for VT switch\n");
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun glxSuspendClients();
813*4882a593Smuzhiyun
814*4882a593Smuzhiyun scrn->LeaveVT = screen->leaveVT;
815*4882a593Smuzhiyun (*screen->leaveVT) (scrn);
816*4882a593Smuzhiyun screen->leaveVT = scrn->LeaveVT;
817*4882a593Smuzhiyun scrn->LeaveVT = glxDRILeaveVT;
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun /**
821*4882a593Smuzhiyun * Initialize extension flags in glx_enable_bits when a new screen is created
822*4882a593Smuzhiyun *
823*4882a593Smuzhiyun * @param screen The screen where glx_enable_bits are to be set.
824*4882a593Smuzhiyun */
825*4882a593Smuzhiyun static void
initializeExtensions(__GLXscreen * screen)826*4882a593Smuzhiyun initializeExtensions(__GLXscreen * screen)
827*4882a593Smuzhiyun {
828*4882a593Smuzhiyun ScreenPtr pScreen = screen->pScreen;
829*4882a593Smuzhiyun __GLXDRIscreen *dri = (__GLXDRIscreen *)screen;
830*4882a593Smuzhiyun const __DRIextension **extensions;
831*4882a593Smuzhiyun int i;
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun extensions = dri->core->getExtensions(dri->driScreen);
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer");
836*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_no_config_context");
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun if (dri->dri2->base.version >= 3) {
839*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits,
840*4882a593Smuzhiyun "GLX_ARB_create_context");
841*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits,
842*4882a593Smuzhiyun "GLX_ARB_create_context_no_error");
843*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits,
844*4882a593Smuzhiyun "GLX_ARB_create_context_profile");
845*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits,
846*4882a593Smuzhiyun "GLX_EXT_create_context_es_profile");
847*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits,
848*4882a593Smuzhiyun "GLX_EXT_create_context_es2_profile");
849*4882a593Smuzhiyun }
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun if (DRI2HasSwapControl(pScreen)) {
852*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
853*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits, "GLX_SGI_swap_control");
854*4882a593Smuzhiyun }
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun /* enable EXT_framebuffer_sRGB extension (even if there are no sRGB capable fbconfigs) */
857*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_framebuffer_sRGB");
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun /* enable ARB_fbconfig_float extension (even if there are no float fbconfigs) */
860*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_fbconfig_float");
861*4882a593Smuzhiyun
862*4882a593Smuzhiyun /* enable EXT_fbconfig_packed_float (even if there are no packed float fbconfigs) */
863*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_fbconfig_packed_float");
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun for (i = 0; extensions[i]; i++) {
866*4882a593Smuzhiyun if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
867*4882a593Smuzhiyun dri->texBuffer = (const __DRItexBufferExtension *) extensions[i];
868*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits,
869*4882a593Smuzhiyun "GLX_EXT_texture_from_pixmap");
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
873*4882a593Smuzhiyun extensions[i]->version >= 3) {
874*4882a593Smuzhiyun dri->flush = (__DRI2flushExtension *) extensions[i];
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0 &&
878*4882a593Smuzhiyun dri->dri2->base.version >= 3) {
879*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits,
880*4882a593Smuzhiyun "GLX_ARB_create_context_robustness");
881*4882a593Smuzhiyun }
882*4882a593Smuzhiyun
883*4882a593Smuzhiyun #ifdef __DRI2_FLUSH_CONTROL
884*4882a593Smuzhiyun if (strcmp(extensions[i]->name, __DRI2_FLUSH_CONTROL) == 0) {
885*4882a593Smuzhiyun __glXEnableExtension(screen->glx_enable_bits,
886*4882a593Smuzhiyun "GLX_ARB_context_flush_control");
887*4882a593Smuzhiyun }
888*4882a593Smuzhiyun #endif
889*4882a593Smuzhiyun
890*4882a593Smuzhiyun /* Ignore unknown extensions */
891*4882a593Smuzhiyun }
892*4882a593Smuzhiyun }
893*4882a593Smuzhiyun
894*4882a593Smuzhiyun static void
__glXDRIscreenDestroy(__GLXscreen * baseScreen)895*4882a593Smuzhiyun __glXDRIscreenDestroy(__GLXscreen * baseScreen)
896*4882a593Smuzhiyun {
897*4882a593Smuzhiyun int i;
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun ScrnInfoPtr pScrn = xf86ScreenToScrn(baseScreen->pScreen);
900*4882a593Smuzhiyun __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun (*screen->core->destroyScreen) (screen->driScreen);
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun dlclose(screen->driver);
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun __glXScreenDestroy(baseScreen);
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun if (screen->driConfigs) {
909*4882a593Smuzhiyun for (i = 0; screen->driConfigs[i] != NULL; i++)
910*4882a593Smuzhiyun free((__DRIconfig **) screen->driConfigs[i]);
911*4882a593Smuzhiyun free(screen->driConfigs);
912*4882a593Smuzhiyun }
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun pScrn->EnterVT = screen->enterVT;
915*4882a593Smuzhiyun pScrn->LeaveVT = screen->leaveVT;
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun free(screen);
918*4882a593Smuzhiyun }
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun enum {
921*4882a593Smuzhiyun GLXOPT_VENDOR_LIBRARY,
922*4882a593Smuzhiyun };
923*4882a593Smuzhiyun
924*4882a593Smuzhiyun static const OptionInfoRec GLXOptions[] = {
925*4882a593Smuzhiyun { GLXOPT_VENDOR_LIBRARY, "GlxVendorLibrary", OPTV_STRING, {0}, FALSE },
926*4882a593Smuzhiyun { -1, NULL, OPTV_NONE, {0}, FALSE },
927*4882a593Smuzhiyun };
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun static __GLXscreen *
__glXDRIscreenProbe(ScreenPtr pScreen)930*4882a593Smuzhiyun __glXDRIscreenProbe(ScreenPtr pScreen)
931*4882a593Smuzhiyun {
932*4882a593Smuzhiyun const char *driverName, *deviceName;
933*4882a593Smuzhiyun __GLXDRIscreen *screen;
934*4882a593Smuzhiyun ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
935*4882a593Smuzhiyun const char *glvnd = NULL;
936*4882a593Smuzhiyun OptionInfoPtr options;
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun screen = calloc(1, sizeof *screen);
939*4882a593Smuzhiyun if (screen == NULL)
940*4882a593Smuzhiyun return NULL;
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun if (!DRI2Connect(serverClient, pScreen, DRI2DriverDRI,
943*4882a593Smuzhiyun &screen->fd, &driverName, &deviceName)) {
944*4882a593Smuzhiyun LogMessage(X_INFO,
945*4882a593Smuzhiyun "AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum);
946*4882a593Smuzhiyun goto handle_error;
947*4882a593Smuzhiyun }
948*4882a593Smuzhiyun
949*4882a593Smuzhiyun screen->base.destroy = __glXDRIscreenDestroy;
950*4882a593Smuzhiyun screen->base.createContext = __glXDRIscreenCreateContext;
951*4882a593Smuzhiyun screen->base.createDrawable = __glXDRIscreenCreateDrawable;
952*4882a593Smuzhiyun screen->base.swapInterval = __glXDRIdrawableSwapInterval;
953*4882a593Smuzhiyun screen->base.pScreen = pScreen;
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun __glXInitExtensionEnableBits(screen->base.glx_enable_bits);
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun screen->driver =
958*4882a593Smuzhiyun glxProbeDriver(driverName, (void **) &screen->core, __DRI_CORE, 1,
959*4882a593Smuzhiyun (void **) &screen->dri2, __DRI_DRI2, 1);
960*4882a593Smuzhiyun if (screen->driver == NULL) {
961*4882a593Smuzhiyun goto handle_error;
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun screen->driScreen =
965*4882a593Smuzhiyun (*screen->dri2->createNewScreen) (pScreen->myNum,
966*4882a593Smuzhiyun screen->fd,
967*4882a593Smuzhiyun loader_extensions,
968*4882a593Smuzhiyun &screen->driConfigs, screen);
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun if (screen->driScreen == NULL) {
971*4882a593Smuzhiyun LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed\n");
972*4882a593Smuzhiyun goto handle_error;
973*4882a593Smuzhiyun }
974*4882a593Smuzhiyun
975*4882a593Smuzhiyun initializeExtensions(&screen->base);
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun screen->base.fbconfigs = glxConvertConfigs(screen->core,
978*4882a593Smuzhiyun screen->driConfigs);
979*4882a593Smuzhiyun
980*4882a593Smuzhiyun options = xnfalloc(sizeof(GLXOptions));
981*4882a593Smuzhiyun memcpy(options, GLXOptions, sizeof(GLXOptions));
982*4882a593Smuzhiyun xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
983*4882a593Smuzhiyun glvnd = xf86GetOptValString(options, GLXOPT_VENDOR_LIBRARY);
984*4882a593Smuzhiyun if (glvnd)
985*4882a593Smuzhiyun screen->base.glvnd = xnfstrdup(glvnd);
986*4882a593Smuzhiyun free(options);
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun if (!screen->base.glvnd)
989*4882a593Smuzhiyun screen->base.glvnd = strdup("mesa");
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun __glXScreenInit(&screen->base, pScreen);
992*4882a593Smuzhiyun
993*4882a593Smuzhiyun screen->enterVT = pScrn->EnterVT;
994*4882a593Smuzhiyun pScrn->EnterVT = glxDRIEnterVT;
995*4882a593Smuzhiyun screen->leaveVT = pScrn->LeaveVT;
996*4882a593Smuzhiyun pScrn->LeaveVT = glxDRILeaveVT;
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun __glXsetGetProcAddress(glXGetProcAddressARB);
999*4882a593Smuzhiyun
1000*4882a593Smuzhiyun LogMessage(X_INFO, "AIGLX: Loaded and initialized %s\n", driverName);
1001*4882a593Smuzhiyun
1002*4882a593Smuzhiyun return &screen->base;
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun handle_error:
1005*4882a593Smuzhiyun if (screen->driver)
1006*4882a593Smuzhiyun dlclose(screen->driver);
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun free(screen);
1009*4882a593Smuzhiyun
1010*4882a593Smuzhiyun return NULL;
1011*4882a593Smuzhiyun }
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun _X_EXPORT __GLXprovider __glXDRI2Provider = {
1014*4882a593Smuzhiyun __glXDRIscreenProbe,
1015*4882a593Smuzhiyun "DRI2",
1016*4882a593Smuzhiyun NULL
1017*4882a593Smuzhiyun };
1018