1706f2543Smrg/*
2706f2543Smrg * Copyright © 2008 George Sapountzis <gsap7@yahoo.gr>
3706f2543Smrg * Copyright © 2008 Red Hat, Inc
4706f2543Smrg *
5706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software
6706f2543Smrg * and its documentation for any purpose is hereby granted without
7706f2543Smrg * fee, provided that the above copyright notice appear in all copies
8706f2543Smrg * and that both that copyright notice and this permission notice
9706f2543Smrg * appear in supporting documentation, and that the name of the
10706f2543Smrg * copyright holders not be used in advertising or publicity
11706f2543Smrg * pertaining to distribution of the software without specific,
12706f2543Smrg * written prior permission.  The copyright holders make no
13706f2543Smrg * representations about the suitability of this software for any
14706f2543Smrg * purpose.  It is provided "as is" without express or implied
15706f2543Smrg * warranty.
16706f2543Smrg *
17706f2543Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
18706f2543Smrg * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
19706f2543Smrg * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
20706f2543Smrg * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21706f2543Smrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
22706f2543Smrg * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
23706f2543Smrg * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
24706f2543Smrg * SOFTWARE.
25706f2543Smrg */
26706f2543Smrg
27706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
28706f2543Smrg#include <dix-config.h>
29706f2543Smrg#endif
30706f2543Smrg
31706f2543Smrg#include <stdint.h>
32706f2543Smrg#include <stdio.h>
33706f2543Smrg#include <string.h>
34706f2543Smrg#include <errno.h>
35706f2543Smrg#include <sys/time.h>
36706f2543Smrg#include <dlfcn.h>
37706f2543Smrg
38706f2543Smrg#include <GL/gl.h>
39706f2543Smrg#include <GL/internal/dri_interface.h>
40706f2543Smrg#include <GL/glxtokens.h>
41706f2543Smrg
42706f2543Smrg#include "scrnintstr.h"
43706f2543Smrg#include "pixmapstr.h"
44706f2543Smrg#include "gcstruct.h"
45706f2543Smrg#include "os.h"
46706f2543Smrg
47706f2543Smrg#include "glxserver.h"
48706f2543Smrg#include "glxutil.h"
49706f2543Smrg#include "glxdricommon.h"
50706f2543Smrg
51706f2543Smrg#include "glapitable.h"
52706f2543Smrg#include "glapi.h"
53706f2543Smrg#include "glthread.h"
54706f2543Smrg#include "dispatch.h"
55706f2543Smrg#include "extension_string.h"
56706f2543Smrg
57706f2543Smrg/* RTLD_LOCAL is not defined on Cygwin */
58706f2543Smrg#ifdef __CYGWIN__
59706f2543Smrg#ifndef RTLD_LOCAL
60706f2543Smrg#define RTLD_LOCAL 0
61706f2543Smrg#endif
62706f2543Smrg#endif
63706f2543Smrg
64706f2543Smrgtypedef struct __GLXDRIscreen   __GLXDRIscreen;
65706f2543Smrgtypedef struct __GLXDRIcontext  __GLXDRIcontext;
66706f2543Smrgtypedef struct __GLXDRIdrawable __GLXDRIdrawable;
67706f2543Smrg
68706f2543Smrgstruct __GLXDRIscreen {
69706f2543Smrg    __GLXscreen		 base;
70706f2543Smrg    __DRIscreen		*driScreen;
71706f2543Smrg    void		*driver;
72706f2543Smrg
73706f2543Smrg    const __DRIcoreExtension *core;
74706f2543Smrg    const __DRIswrastExtension *swrast;
75706f2543Smrg    const __DRIcopySubBufferExtension *copySubBuffer;
76706f2543Smrg    const __DRItexBufferExtension *texBuffer;
77706f2543Smrg};
78706f2543Smrg
79706f2543Smrgstruct __GLXDRIcontext {
80706f2543Smrg    __GLXcontext	 base;
81706f2543Smrg    __DRIcontext	*driContext;
82706f2543Smrg};
83706f2543Smrg
84706f2543Smrgstruct __GLXDRIdrawable {
85706f2543Smrg    __GLXdrawable	 base;
86706f2543Smrg    __DRIdrawable	*driDrawable;
87706f2543Smrg    __GLXDRIscreen	*screen;
88706f2543Smrg
89706f2543Smrg    GCPtr gc;		/* scratch GC for span drawing */
90706f2543Smrg    GCPtr swapgc;	/* GC for swapping the color buffers */
91706f2543Smrg};
92706f2543Smrg
93706f2543Smrgstatic void
94706f2543Smrg__glXDRIdrawableDestroy(__GLXdrawable *drawable)
95706f2543Smrg{
96706f2543Smrg    __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
97706f2543Smrg    const __DRIcoreExtension *core = private->screen->core;
98706f2543Smrg
99706f2543Smrg    (*core->destroyDrawable)(private->driDrawable);
100706f2543Smrg
101706f2543Smrg    FreeGC(private->gc, (GContext)0);
102706f2543Smrg    FreeGC(private->swapgc, (GContext)0);
103706f2543Smrg
104706f2543Smrg    __glXDrawableRelease(drawable);
105706f2543Smrg
106706f2543Smrg    free(private);
107706f2543Smrg}
108706f2543Smrg
109706f2543Smrgstatic GLboolean
110706f2543Smrg__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
111706f2543Smrg{
112706f2543Smrg    __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
113706f2543Smrg    const __DRIcoreExtension *core = private->screen->core;
114706f2543Smrg
115706f2543Smrg    (*core->swapBuffers)(private->driDrawable);
116706f2543Smrg
117706f2543Smrg    return TRUE;
118706f2543Smrg}
119706f2543Smrg
120706f2543Smrgstatic void
121706f2543Smrg__glXDRIdrawableCopySubBuffer(__GLXdrawable *basePrivate,
122706f2543Smrg			       int x, int y, int w, int h)
123706f2543Smrg{
124706f2543Smrg    __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
125706f2543Smrg    const __DRIcopySubBufferExtension *copySubBuffer =
126706f2543Smrg	    private->screen->copySubBuffer;
127706f2543Smrg
128706f2543Smrg    if (copySubBuffer)
129706f2543Smrg	(*copySubBuffer->copySubBuffer)(private->driDrawable, x, y, w, h);
130706f2543Smrg}
131706f2543Smrg
132706f2543Smrgstatic void
133706f2543Smrg__glXDRIcontextDestroy(__GLXcontext *baseContext)
134706f2543Smrg{
135706f2543Smrg    __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
136706f2543Smrg    __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
137706f2543Smrg
138706f2543Smrg    (*screen->core->destroyContext)(context->driContext);
139706f2543Smrg    __glXContextDestroy(&context->base);
140706f2543Smrg    free(context);
141706f2543Smrg}
142706f2543Smrg
143706f2543Smrgstatic int
144706f2543Smrg__glXDRIcontextMakeCurrent(__GLXcontext *baseContext)
145706f2543Smrg{
146706f2543Smrg    __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
147706f2543Smrg    __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
148706f2543Smrg    __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
149706f2543Smrg    __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
150706f2543Smrg
151706f2543Smrg    return (*screen->core->bindContext)(context->driContext,
152706f2543Smrg					draw->driDrawable,
153706f2543Smrg					read->driDrawable);
154706f2543Smrg}
155706f2543Smrg
156706f2543Smrgstatic int
157706f2543Smrg__glXDRIcontextLoseCurrent(__GLXcontext *baseContext)
158706f2543Smrg{
159706f2543Smrg    __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
160706f2543Smrg    __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
161706f2543Smrg
162706f2543Smrg    return (*screen->core->unbindContext)(context->driContext);
163706f2543Smrg}
164706f2543Smrg
165706f2543Smrgstatic int
166706f2543Smrg__glXDRIcontextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
167706f2543Smrg		    unsigned long mask)
168706f2543Smrg{
169706f2543Smrg    __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
170706f2543Smrg    __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
171706f2543Smrg    __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
172706f2543Smrg
173706f2543Smrg    return (*screen->core->copyContext)(dst->driContext,
174706f2543Smrg					src->driContext, mask);
175706f2543Smrg}
176706f2543Smrg
177706f2543Smrgstatic int
178706f2543Smrg__glXDRIcontextForceCurrent(__GLXcontext *baseContext)
179706f2543Smrg{
180706f2543Smrg    __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
181706f2543Smrg    __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
182706f2543Smrg    __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
183706f2543Smrg    __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
184706f2543Smrg
185706f2543Smrg    return (*screen->core->bindContext)(context->driContext,
186706f2543Smrg					draw->driDrawable,
187706f2543Smrg					read->driDrawable);
188706f2543Smrg}
189706f2543Smrg
190706f2543Smrg#ifdef __DRI_TEX_BUFFER
191706f2543Smrg
192706f2543Smrgstatic int
193706f2543Smrg__glXDRIbindTexImage(__GLXcontext *baseContext,
194706f2543Smrg		     int buffer,
195706f2543Smrg		     __GLXdrawable *glxPixmap)
196706f2543Smrg{
197706f2543Smrg    __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
198706f2543Smrg    const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
199706f2543Smrg    __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
200706f2543Smrg
201706f2543Smrg    if (texBuffer == NULL)
202706f2543Smrg        return Success;
203706f2543Smrg
204706f2543Smrg#if __DRI_TEX_BUFFER_VERSION >= 2
205706f2543Smrg    if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
206706f2543Smrg	(*texBuffer->setTexBuffer2)(context->driContext,
207706f2543Smrg				    glxPixmap->target,
208706f2543Smrg				    glxPixmap->format,
209706f2543Smrg				    drawable->driDrawable);
210706f2543Smrg    } else
211706f2543Smrg#endif
212706f2543Smrg    texBuffer->setTexBuffer(context->driContext,
213706f2543Smrg			    glxPixmap->target,
214706f2543Smrg			    drawable->driDrawable);
215706f2543Smrg
216706f2543Smrg    return Success;
217706f2543Smrg}
218706f2543Smrg
219706f2543Smrgstatic int
220706f2543Smrg__glXDRIreleaseTexImage(__GLXcontext *baseContext,
221706f2543Smrg			int buffer,
222706f2543Smrg			__GLXdrawable *pixmap)
223706f2543Smrg{
224706f2543Smrg    /* FIXME: Just unbind the texture? */
225706f2543Smrg    return Success;
226706f2543Smrg}
227706f2543Smrg
228706f2543Smrg#else
229706f2543Smrg
230706f2543Smrgstatic int
231706f2543Smrg__glXDRIbindTexImage(__GLXcontext *baseContext,
232706f2543Smrg		     int buffer,
233706f2543Smrg		     __GLXdrawable *glxPixmap)
234706f2543Smrg{
235706f2543Smrg    return Success;
236706f2543Smrg}
237706f2543Smrg
238706f2543Smrgstatic int
239706f2543Smrg__glXDRIreleaseTexImage(__GLXcontext *baseContext,
240706f2543Smrg			int buffer,
241706f2543Smrg			__GLXdrawable *pixmap)
242706f2543Smrg{
243706f2543Smrg    return Success;
244706f2543Smrg}
245706f2543Smrg
246706f2543Smrg#endif
247706f2543Smrg
248706f2543Smrgstatic __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
249706f2543Smrg    __glXDRIbindTexImage,
250706f2543Smrg    __glXDRIreleaseTexImage
251706f2543Smrg};
252706f2543Smrg
253706f2543Smrgstatic void
254706f2543Smrg__glXDRIscreenDestroy(__GLXscreen *baseScreen)
255706f2543Smrg{
256706f2543Smrg    __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
257706f2543Smrg
258706f2543Smrg    (*screen->core->destroyScreen)(screen->driScreen);
259706f2543Smrg
260706f2543Smrg    dlclose(screen->driver);
261706f2543Smrg
262706f2543Smrg    __glXScreenDestroy(baseScreen);
263706f2543Smrg
264706f2543Smrg    free(screen);
265706f2543Smrg}
266706f2543Smrg
267706f2543Smrgstatic __GLXcontext *
268706f2543Smrg__glXDRIscreenCreateContext(__GLXscreen *baseScreen,
269706f2543Smrg			    __GLXconfig *glxConfig,
270706f2543Smrg			    __GLXcontext *baseShareContext)
271706f2543Smrg{
272706f2543Smrg    __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
273706f2543Smrg    __GLXDRIcontext *context, *shareContext;
274706f2543Smrg    __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
275706f2543Smrg    const __DRIcoreExtension *core = screen->core;
276706f2543Smrg    __DRIcontext *driShare;
277706f2543Smrg
278706f2543Smrg    shareContext = (__GLXDRIcontext *) baseShareContext;
279706f2543Smrg    if (shareContext)
280706f2543Smrg	driShare = shareContext->driContext;
281706f2543Smrg    else
282706f2543Smrg	driShare = NULL;
283706f2543Smrg
284706f2543Smrg    context = calloc(1, sizeof *context);
285706f2543Smrg    if (context == NULL)
286706f2543Smrg	return NULL;
287706f2543Smrg
288706f2543Smrg    context->base.destroy           = __glXDRIcontextDestroy;
289706f2543Smrg    context->base.makeCurrent       = __glXDRIcontextMakeCurrent;
290706f2543Smrg    context->base.loseCurrent       = __glXDRIcontextLoseCurrent;
291706f2543Smrg    context->base.copy              = __glXDRIcontextCopy;
292706f2543Smrg    context->base.forceCurrent      = __glXDRIcontextForceCurrent;
293706f2543Smrg    context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
294706f2543Smrg
295706f2543Smrg    context->driContext =
296706f2543Smrg	(*core->createNewContext)(screen->driScreen,
297706f2543Smrg				  config->driConfig, driShare, context);
298706f2543Smrg
299706f2543Smrg    return &context->base;
300706f2543Smrg}
301706f2543Smrg
302706f2543Smrgstatic __GLXdrawable *
303706f2543Smrg__glXDRIscreenCreateDrawable(ClientPtr client,
304706f2543Smrg			     __GLXscreen *screen,
305706f2543Smrg			     DrawablePtr pDraw,
306706f2543Smrg			     XID drawId,
307706f2543Smrg			     int type,
308706f2543Smrg			     XID glxDrawId,
309706f2543Smrg			     __GLXconfig *glxConfig)
310706f2543Smrg{
311706f2543Smrg    XID gcvals[2];
312706f2543Smrg    int status;
313706f2543Smrg    __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
314706f2543Smrg    __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
315706f2543Smrg    __GLXDRIdrawable *private;
316706f2543Smrg
317706f2543Smrg    private = calloc(1, sizeof *private);
318706f2543Smrg    if (private == NULL)
319706f2543Smrg	return NULL;
320706f2543Smrg
321706f2543Smrg    private->screen = driScreen;
322706f2543Smrg    if (!__glXDrawableInit(&private->base, screen,
323706f2543Smrg			   pDraw, type, glxDrawId, glxConfig)) {
324706f2543Smrg        free(private);
325706f2543Smrg	return NULL;
326706f2543Smrg    }
327706f2543Smrg
328706f2543Smrg    private->base.destroy       = __glXDRIdrawableDestroy;
329706f2543Smrg    private->base.swapBuffers   = __glXDRIdrawableSwapBuffers;
330706f2543Smrg    private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
331706f2543Smrg
332706f2543Smrg    gcvals[0] = GXcopy;
333706f2543Smrg    private->gc = CreateGC(pDraw, GCFunction, gcvals, &status, (XID)0, serverClient);
334706f2543Smrg    gcvals[1] = FALSE;
335706f2543Smrg    private->swapgc = CreateGC(pDraw, GCFunction | GCGraphicsExposures, gcvals, &status, (XID)0, serverClient);
336706f2543Smrg
337706f2543Smrg    private->driDrawable =
338706f2543Smrg	(*driScreen->swrast->createNewDrawable)(driScreen->driScreen,
339706f2543Smrg						config->driConfig,
340706f2543Smrg						private);
341706f2543Smrg
342706f2543Smrg    return &private->base;
343706f2543Smrg}
344706f2543Smrg
345706f2543Smrgstatic void
346706f2543SmrgswrastGetDrawableInfo(__DRIdrawable *draw,
347706f2543Smrg		      int *x, int *y, int *w, int *h,
348706f2543Smrg		      void *loaderPrivate)
349706f2543Smrg{
350706f2543Smrg    __GLXDRIdrawable *drawable = loaderPrivate;
351706f2543Smrg    DrawablePtr pDraw = drawable->base.pDraw;
352706f2543Smrg
353706f2543Smrg    *x = pDraw->x;
354706f2543Smrg    *y = pDraw->x;
355706f2543Smrg    *w = pDraw->width;
356706f2543Smrg    *h = pDraw->height;
357706f2543Smrg}
358706f2543Smrg
359706f2543Smrgstatic void
360706f2543SmrgswrastPutImage(__DRIdrawable *draw, int op,
361706f2543Smrg	     int x, int y, int w, int h, char *data,
362706f2543Smrg	     void *loaderPrivate)
363706f2543Smrg{
364706f2543Smrg    __GLXDRIdrawable *drawable = loaderPrivate;
365706f2543Smrg    DrawablePtr pDraw = drawable->base.pDraw;
366706f2543Smrg    GCPtr gc;
367706f2543Smrg
368706f2543Smrg    switch (op) {
369706f2543Smrg    case __DRI_SWRAST_IMAGE_OP_DRAW:
370706f2543Smrg	gc = drawable->gc;
371706f2543Smrg	break;
372706f2543Smrg    case __DRI_SWRAST_IMAGE_OP_SWAP:
373706f2543Smrg	gc = drawable->swapgc;
374706f2543Smrg	break;
375706f2543Smrg    default:
376706f2543Smrg	return;
377706f2543Smrg    }
378706f2543Smrg
379706f2543Smrg    ValidateGC(pDraw, gc);
380706f2543Smrg
381706f2543Smrg    gc->ops->PutImage(pDraw, gc, pDraw->depth,
382706f2543Smrg		      x, y, w, h, 0, ZPixmap, data);
383706f2543Smrg}
384706f2543Smrg
385706f2543Smrgstatic void
386706f2543SmrgswrastGetImage(__DRIdrawable *draw,
387706f2543Smrg	     int x, int y, int w, int h, char *data,
388706f2543Smrg	     void *loaderPrivate)
389706f2543Smrg{
390706f2543Smrg    __GLXDRIdrawable *drawable = loaderPrivate;
391706f2543Smrg    DrawablePtr pDraw = drawable->base.pDraw;
392706f2543Smrg    ScreenPtr pScreen = pDraw->pScreen;
393706f2543Smrg
394706f2543Smrg    pScreen->GetImage(pDraw, x, y, w, h, ZPixmap, ~0L, data);
395706f2543Smrg}
396706f2543Smrg
397706f2543Smrgstatic const __DRIswrastLoaderExtension swrastLoaderExtension = {
398706f2543Smrg    { __DRI_SWRAST_LOADER, __DRI_SWRAST_LOADER_VERSION },
399706f2543Smrg    swrastGetDrawableInfo,
400706f2543Smrg    swrastPutImage,
401706f2543Smrg    swrastGetImage
402706f2543Smrg};
403706f2543Smrg
404706f2543Smrgstatic const __DRIextension *loader_extensions[] = {
405706f2543Smrg    &systemTimeExtension.base,
406706f2543Smrg    &swrastLoaderExtension.base,
407706f2543Smrg    NULL
408706f2543Smrg};
409706f2543Smrg
410706f2543Smrgstatic void
411706f2543SmrginitializeExtensions(__GLXDRIscreen *screen)
412706f2543Smrg{
413706f2543Smrg    const __DRIextension **extensions;
414706f2543Smrg    int i;
415706f2543Smrg
416706f2543Smrg    extensions = screen->core->getExtensions(screen->driScreen);
417706f2543Smrg
418706f2543Smrg    for (i = 0; extensions[i]; i++) {
419706f2543Smrg#ifdef __DRI_COPY_SUB_BUFFER
420706f2543Smrg	if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
421706f2543Smrg	    screen->copySubBuffer =
422706f2543Smrg		(const __DRIcopySubBufferExtension *) extensions[i];
423706f2543Smrg	    /* GLX_MESA_copy_sub_buffer is always enabled. */
424706f2543Smrg	}
425706f2543Smrg#endif
426706f2543Smrg
427706f2543Smrg#ifdef __DRI_TEX_BUFFER
428706f2543Smrg	if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
429706f2543Smrg	    screen->texBuffer =
430706f2543Smrg		(const __DRItexBufferExtension *) extensions[i];
431706f2543Smrg	    /* GLX_EXT_texture_from_pixmap is always enabled. */
432706f2543Smrg	}
433706f2543Smrg#endif
434706f2543Smrg	/* Ignore unknown extensions */
435706f2543Smrg    }
436706f2543Smrg}
437706f2543Smrg
438706f2543Smrgstatic const char dri_driver_path[] = DRI_DRIVER_PATH;
439706f2543Smrg
440706f2543Smrgstatic __GLXscreen *
441706f2543Smrg__glXDRIscreenProbe(ScreenPtr pScreen)
442706f2543Smrg{
443706f2543Smrg    const char *driverName = "swrast";
444706f2543Smrg    __GLXDRIscreen *screen;
445706f2543Smrg    char filename[128];
446706f2543Smrg    const __DRIextension **extensions;
447706f2543Smrg    const __DRIconfig **driConfigs;
448706f2543Smrg    int i;
449706f2543Smrg
450706f2543Smrg    screen = calloc(1, sizeof *screen);
451706f2543Smrg    if (screen == NULL)
452706f2543Smrg	return NULL;
453706f2543Smrg
454706f2543Smrg    screen->base.destroy        = __glXDRIscreenDestroy;
455706f2543Smrg    screen->base.createContext  = __glXDRIscreenCreateContext;
456706f2543Smrg    screen->base.createDrawable = __glXDRIscreenCreateDrawable;
457706f2543Smrg    screen->base.swapInterval   = NULL;
458706f2543Smrg    screen->base.pScreen       = pScreen;
459706f2543Smrg
460706f2543Smrg    snprintf(filename, sizeof filename,
461706f2543Smrg	     "%s/%s_dri.so", dri_driver_path, driverName);
462706f2543Smrg
463706f2543Smrg    screen->driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
464706f2543Smrg    if (screen->driver == NULL) {
465706f2543Smrg	LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n",
466706f2543Smrg		   filename, dlerror());
467706f2543Smrg        goto handle_error;
468706f2543Smrg    }
469706f2543Smrg
470706f2543Smrg    extensions = dlsym(screen->driver, __DRI_DRIVER_EXTENSIONS);
471706f2543Smrg    if (extensions == NULL) {
472706f2543Smrg	LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n",
473706f2543Smrg		   driverName, dlerror());
474706f2543Smrg	goto handle_error;
475706f2543Smrg    }
476706f2543Smrg
477706f2543Smrg    for (i = 0; extensions[i]; i++) {
478706f2543Smrg        if (strcmp(extensions[i]->name, __DRI_CORE) == 0 &&
479706f2543Smrg	    extensions[i]->version >= __DRI_CORE_VERSION) {
480706f2543Smrg		screen->core = (const __DRIcoreExtension *) extensions[i];
481706f2543Smrg	}
482706f2543Smrg        if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0 &&
483706f2543Smrg	    extensions[i]->version >= __DRI_SWRAST_VERSION) {
484706f2543Smrg		screen->swrast = (const __DRIswrastExtension *) extensions[i];
485706f2543Smrg	}
486706f2543Smrg    }
487706f2543Smrg
488706f2543Smrg    if (screen->core == NULL || screen->swrast == NULL) {
489706f2543Smrg	LogMessage(X_ERROR, "AIGLX error: %s exports no DRI extension\n",
490706f2543Smrg		   driverName);
491706f2543Smrg	goto handle_error;
492706f2543Smrg    }
493706f2543Smrg
494706f2543Smrg    screen->driScreen =
495706f2543Smrg	(*screen->swrast->createNewScreen)(pScreen->myNum,
496706f2543Smrg					   loader_extensions,
497706f2543Smrg					   &driConfigs,
498706f2543Smrg					   screen);
499706f2543Smrg
500706f2543Smrg    if (screen->driScreen == NULL) {
501706f2543Smrg	LogMessage(X_ERROR,
502706f2543Smrg		   "AIGLX error: Calling driver entry point failed\n");
503706f2543Smrg	goto handle_error;
504706f2543Smrg    }
505706f2543Smrg
506706f2543Smrg    initializeExtensions(screen);
507706f2543Smrg
508706f2543Smrg    screen->base.fbconfigs = glxConvertConfigs(screen->core, driConfigs,
509706f2543Smrg					       GLX_WINDOW_BIT |
510706f2543Smrg					       GLX_PIXMAP_BIT |
511706f2543Smrg					       GLX_PBUFFER_BIT);
512706f2543Smrg
513706f2543Smrg    __glXScreenInit(&screen->base, pScreen);
514706f2543Smrg
515706f2543Smrg    screen->base.GLXmajor = 1;
516706f2543Smrg    screen->base.GLXminor = 4;
517706f2543Smrg
518706f2543Smrg    LogMessage(X_INFO,
519706f2543Smrg	       "AIGLX: Loaded and initialized %s\n", filename);
520706f2543Smrg
521706f2543Smrg    return &screen->base;
522706f2543Smrg
523706f2543Smrg handle_error:
524706f2543Smrg    if (screen->driver)
525706f2543Smrg        dlclose(screen->driver);
526706f2543Smrg
527706f2543Smrg    free(screen);
528706f2543Smrg
529706f2543Smrg    LogMessage(X_ERROR, "GLX: could not load software renderer\n");
530706f2543Smrg
531706f2543Smrg    return NULL;
532706f2543Smrg}
533706f2543Smrg
534706f2543Smrg_X_EXPORT __GLXprovider __glXDRISWRastProvider = {
535706f2543Smrg    __glXDRIscreenProbe,
536706f2543Smrg    "DRISWRAST",
537706f2543Smrg    NULL
538706f2543Smrg};
539