~gma500/+junk/gma500-maverick

« back to all changes in this revision

Viewing changes to xpsb-glx/mesa/src/glx/x11/dri_glx.c

  • Committer: Luca Forina
  • Date: 2011-02-14 09:55:00 UTC
  • Revision ID: luca.forina@gmail.com-20110214095500-kq7o333fbjuoquqs
new commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**************************************************************************
 
2
 
 
3
Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
 
4
All Rights Reserved.
 
5
 
 
6
Permission is hereby granted, free of charge, to any person obtaining a
 
7
copy of this software and associated documentation files (the
 
8
"Software"), to deal in the Software without restriction, including
 
9
without limitation the rights to use, copy, modify, merge, publish,
 
10
distribute, sub license, and/or sell copies of the Software, and to
 
11
permit persons to whom the Software is furnished to do so, subject to
 
12
the following conditions:
 
13
 
 
14
The above copyright notice and this permission notice (including the
 
15
next paragraph) shall be included in all copies or substantial portions
 
16
of the Software.
 
17
 
 
18
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
19
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
20
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 
21
IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
 
22
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 
23
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 
24
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
25
 
 
26
**************************************************************************/
 
27
 
 
28
/*
 
29
 * Authors:
 
30
 *   Kevin E. Martin <kevin@precisioninsight.com>
 
31
 *   Brian Paul <brian@precisioninsight.com>
 
32
 *
 
33
 */
 
34
 
 
35
#ifdef GLX_DIRECT_RENDERING
 
36
 
 
37
#include <X11/Xlib.h>
 
38
#include <X11/extensions/Xfixes.h>
 
39
#include <X11/extensions/Xdamage.h>
 
40
#include "glxclient.h"
 
41
#include "glcontextmodes.h"
 
42
#include "xf86dri.h"
 
43
#include "sarea.h"
 
44
#include <dlfcn.h>
 
45
#include <sys/types.h>
 
46
#include <sys/mman.h>
 
47
#include "xf86drm.h"
 
48
#include "dri_common.h"
 
49
 
 
50
typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
 
51
typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
 
52
 
 
53
struct __GLXDRIdisplayPrivateRec {
 
54
    __GLXDRIdisplay base;
 
55
 
 
56
    /*
 
57
    ** XFree86-DRI version information
 
58
    */
 
59
    int driMajor;
 
60
    int driMinor;
 
61
    int driPatch;
 
62
};
 
63
 
 
64
struct __GLXDRIcontextPrivateRec {
 
65
    __GLXDRIcontext base;
 
66
    __DRIcontext *driContext;
 
67
    XID hwContextID;
 
68
    __GLXscreenConfigs *psc;
 
69
};
 
70
 
 
71
/*
 
72
 * Given a display pointer and screen number, determine the name of
 
73
 * the DRI driver for the screen. (I.e. "r128", "tdfx", etc).
 
74
 * Return True for success, False for failure.
 
75
 */
 
76
static Bool driGetDriverName(Display *dpy, int scrNum, char **driverName)
 
77
{
 
78
   int directCapable;
 
79
   Bool b;
 
80
   int driverMajor, driverMinor, driverPatch;
 
81
 
 
82
   *driverName = NULL;
 
83
 
 
84
   if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
 
85
      ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
 
86
      return False;
 
87
   }
 
88
   if (!directCapable) {
 
89
      ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
 
90
      return False;
 
91
   }
 
92
 
 
93
   b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
 
94
                                  &driverPatch, driverName);
 
95
   if (!b) {
 
96
      ErrorMessageF("Cannot determine driver name for screen %d\n", scrNum);
 
97
      return False;
 
98
   }
 
99
 
 
100
   InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
 
101
             driverMajor, driverMinor, driverPatch, *driverName, scrNum);
 
102
 
 
103
   return True;
 
104
}
 
105
 
 
106
/*
 
107
 * Exported function for querying the DRI driver for a given screen.
 
108
 *
 
109
 * The returned char pointer points to a static array that will be
 
110
 * overwritten by subsequent calls.
 
111
 */
 
112
PUBLIC const char *glXGetScreenDriver (Display *dpy, int scrNum) {
 
113
   static char ret[32];
 
114
   char *driverName;
 
115
   if (driGetDriverName(dpy, scrNum, &driverName)) {
 
116
      int len;
 
117
      if (!driverName)
 
118
         return NULL;
 
119
      len = strlen (driverName);
 
120
      if (len >= 31)
 
121
         return NULL;
 
122
      memcpy (ret, driverName, len+1);
 
123
      Xfree(driverName);
 
124
      return ret;
 
125
   }
 
126
   return NULL;
 
127
}
 
128
 
 
129
/*
 
130
 * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
 
131
 *
 
132
 * The returned char pointer points directly into the driver. Therefore
 
133
 * it should be treated as a constant.
 
134
 *
 
135
 * If the driver was not found or does not support configuration NULL is
 
136
 * returned.
 
137
 *
 
138
 * Note: The driver remains opened after this function returns.
 
139
 */
 
140
PUBLIC const char *glXGetDriverConfig (const char *driverName)
 
141
{
 
142
   void *handle = driOpenDriver (driverName);
 
143
   if (handle)
 
144
      return dlsym (handle, "__driConfigOptions");
 
145
   else
 
146
      return NULL;
 
147
}
 
148
 
 
149
#ifdef XDAMAGE_1_1_INTERFACE
 
150
 
 
151
static GLboolean has_damage_post(Display *dpy)
 
152
{
 
153
    static GLboolean inited = GL_FALSE;
 
154
    static GLboolean has_damage;
 
155
 
 
156
    if (!inited) {
 
157
        int major, minor;
 
158
 
 
159
        if (XDamageQueryVersion(dpy, &major, &minor) &&
 
160
            major == 1 && minor >= 1)
 
161
        {
 
162
            has_damage = GL_TRUE;
 
163
        } else {
 
164
            has_damage = GL_FALSE;
 
165
        }
 
166
        inited = GL_TRUE;
 
167
    }
 
168
 
 
169
    return has_damage;
 
170
}
 
171
 
 
172
static void __glXReportDamage(__DRIdrawable *driDraw,
 
173
                              int x, int y,
 
174
                              drm_clip_rect_t *rects, int num_rects,
 
175
                              GLboolean front_buffer,
 
176
                              void *loaderPrivate)
 
177
{
 
178
    XRectangle *xrects;
 
179
    XserverRegion region;
 
180
    int i;
 
181
    int x_off, y_off;
 
182
    __GLXDRIdrawable *glxDraw = loaderPrivate;
 
183
    __GLXscreenConfigs *psc = glxDraw->psc;
 
184
    Display *dpy = psc->dpy;
 
185
    Drawable drawable;
 
186
 
 
187
    if (!has_damage_post(dpy))
 
188
        return;
 
189
 
 
190
    if (front_buffer) {
 
191
        x_off = x;
 
192
        y_off = y;
 
193
        drawable = RootWindow(dpy, psc->scr);
 
194
    } else{
 
195
        x_off = 0;
 
196
        y_off = 0;
 
197
        drawable = glxDraw->xDrawable;
 
198
    }
 
199
 
 
200
    xrects = malloc(sizeof(XRectangle) * num_rects);
 
201
    if (xrects == NULL)
 
202
        return;
 
203
 
 
204
    for (i = 0; i < num_rects; i++) {
 
205
        xrects[i].x = rects[i].x1 + x_off;
 
206
        xrects[i].y = rects[i].y1 + y_off;
 
207
        xrects[i].width = rects[i].x2 - rects[i].x1;
 
208
        xrects[i].height = rects[i].y2 - rects[i].y1;
 
209
    }
 
210
    region = XFixesCreateRegion(dpy, xrects, num_rects);
 
211
    free(xrects);
 
212
    XDamageAdd(dpy, drawable, region);
 
213
    XFixesDestroyRegion(dpy, region);
 
214
}
 
215
 
 
216
static const __DRIdamageExtension damageExtension = {
 
217
    { __DRI_DAMAGE, __DRI_DAMAGE_VERSION },
 
218
    __glXReportDamage,
 
219
};
 
220
 
 
221
#endif
 
222
 
 
223
static GLboolean
 
224
__glXDRIGetDrawableInfo(__DRIdrawable *drawable,
 
225
                        unsigned int *index, unsigned int *stamp, 
 
226
                        int *X, int *Y, int *W, int *H,
 
227
                        int *numClipRects, drm_clip_rect_t ** pClipRects,
 
228
                        int *backX, int *backY,
 
229
                        int *numBackClipRects, drm_clip_rect_t **pBackClipRects,
 
230
                        void *loaderPrivate)
 
231
{
 
232
    __GLXDRIdrawable *glxDraw = loaderPrivate;
 
233
    __GLXscreenConfigs *psc = glxDraw->psc;
 
234
    Display *dpy = psc->dpy;
 
235
 
 
236
    return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable,
 
237
                                  index, stamp, X, Y, W, H,
 
238
                                  numClipRects, pClipRects,
 
239
                                  backX, backY,
 
240
                                  numBackClipRects, pBackClipRects);
 
241
}
 
242
 
 
243
static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = {
 
244
    { __DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION },
 
245
    __glXDRIGetDrawableInfo
 
246
};
 
247
 
 
248
static const __DRIextension *loader_extensions[] = {
 
249
    &systemTimeExtension.base,
 
250
    &getDrawableInfoExtension.base,
 
251
#ifdef XDAMAGE_1_1_INTERFACE
 
252
    &damageExtension.base,
 
253
#endif
 
254
    NULL
 
255
};
 
256
 
 
257
#ifndef GLX_USE_APPLEGL
 
258
 
 
259
/**
 
260
 * Perform the required libGL-side initialization and call the client-side
 
261
 * driver's \c __driCreateNewScreen function.
 
262
 * 
 
263
 * \param dpy    Display pointer.
 
264
 * \param scrn   Screen number on the display.
 
265
 * \param psc    DRI screen information.
 
266
 * \param driDpy DRI display information.
 
267
 * \param createNewScreen  Pointer to the client-side driver's
 
268
 *               \c __driCreateNewScreen function.
 
269
 * \returns A pointer to the \c __DRIscreenPrivate structure returned by
 
270
 *          the client-side driver on success, or \c NULL on failure.
 
271
 */
 
272
static void *
 
273
CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
 
274
                    __GLXDRIdisplayPrivate * driDpy)
 
275
{
 
276
    void *psp = NULL;
 
277
    drm_handle_t hSAREA;
 
278
    drmAddress pSAREA = MAP_FAILED;
 
279
    char *BusID;
 
280
    __DRIversion   ddx_version;
 
281
    __DRIversion   dri_version;
 
282
    __DRIversion   drm_version;
 
283
    __DRIframebuffer  framebuffer;
 
284
    int   fd = -1;
 
285
    int   status;
 
286
 
 
287
    drm_magic_t magic;
 
288
    drmVersionPtr version;
 
289
    int newlyopened;
 
290
    char *driverName;
 
291
    drm_handle_t  hFB;
 
292
    int        junk;
 
293
    const __DRIconfig **driver_configs;
 
294
 
 
295
    /* DRI protocol version. */
 
296
    dri_version.major = driDpy->driMajor;
 
297
    dri_version.minor = driDpy->driMinor;
 
298
    dri_version.patch = driDpy->driPatch;
 
299
 
 
300
    framebuffer.base = MAP_FAILED;
 
301
    framebuffer.dev_priv = NULL;
 
302
 
 
303
    if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
 
304
        ErrorMessageF("XF86DRIOpenConnection failed\n");
 
305
        goto handle_error;
 
306
    }
 
307
 
 
308
    fd = drmOpenOnce(NULL, BusID, &newlyopened);
 
309
 
 
310
    Xfree(BusID); /* No longer needed */
 
311
 
 
312
    if (fd < 0) {
 
313
        ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd));
 
314
        goto handle_error;
 
315
    }
 
316
 
 
317
    if (drmGetMagic(fd, &magic)) {
 
318
        ErrorMessageF("drmGetMagic failed\n");
 
319
        goto handle_error;
 
320
    }
 
321
 
 
322
    version = drmGetVersion(fd);
 
323
    if (version) {
 
324
        drm_version.major = version->version_major;
 
325
        drm_version.minor = version->version_minor;
 
326
        drm_version.patch = version->version_patchlevel;
 
327
        drmFreeVersion(version);
 
328
    }
 
329
    else {
 
330
        drm_version.major = -1;
 
331
        drm_version.minor = -1;
 
332
        drm_version.patch = -1;
 
333
    }
 
334
 
 
335
    if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) {
 
336
        ErrorMessageF("XF86DRIAuthConnection failed\n");
 
337
        goto handle_error;
 
338
    }
 
339
 
 
340
    /* Get device name (like "tdfx") and the ddx version numbers.
 
341
     * We'll check the version in each DRI driver's "createNewScreen"
 
342
     * function. */
 
343
    if (!XF86DRIGetClientDriverName(dpy, scrn,
 
344
                                    &ddx_version.major,
 
345
                                    &ddx_version.minor,
 
346
                                    &ddx_version.patch,
 
347
                                    &driverName)) {
 
348
        ErrorMessageF("XF86DRIGetClientDriverName failed\n");
 
349
        goto handle_error;
 
350
    }
 
351
 
 
352
    Xfree(driverName); /* No longer needed. */
 
353
 
 
354
    /*
 
355
     * Get device-specific info.  pDevPriv will point to a struct
 
356
     * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
 
357
     * has information about the screen size, depth, pitch, ancilliary
 
358
     * buffers, DRM mmap handles, etc.
 
359
     */
 
360
    if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk,
 
361
                              &framebuffer.size, &framebuffer.stride,
 
362
                              &framebuffer.dev_priv_size, &framebuffer.dev_priv)) {
 
363
        ErrorMessageF("XF86DRIGetDeviceInfo failed");
 
364
        goto handle_error;
 
365
    }
 
366
 
 
367
    framebuffer.width = DisplayWidth(dpy, scrn);
 
368
    framebuffer.height = DisplayHeight(dpy, scrn);
 
369
 
 
370
    /* Map the framebuffer region. */
 
371
    status = drmMap(fd, hFB, framebuffer.size, 
 
372
                    (drmAddressPtr)&framebuffer.base);
 
373
    if (status != 0) {
 
374
        ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status));
 
375
        goto handle_error;
 
376
    }
 
377
 
 
378
    /* Map the SAREA region.  Further mmap regions may be setup in
 
379
     * each DRI driver's "createNewScreen" function.
 
380
     */
 
381
    status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
 
382
    if (status != 0) {
 
383
        ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status));
 
384
        goto handle_error;
 
385
    }
 
386
 
 
387
    psp = (*psc->legacy->createNewScreen)(scrn,
 
388
                                          &ddx_version,
 
389
                                          &dri_version,
 
390
                                          &drm_version,
 
391
                                          &framebuffer,
 
392
                                          pSAREA,
 
393
                                          fd,
 
394
                                          loader_extensions,
 
395
                                          &driver_configs,
 
396
                                          psc);
 
397
 
 
398
    if (psp == NULL) {
 
399
        ErrorMessageF("Calling driver entry point failed");
 
400
        goto handle_error;
 
401
    }
 
402
 
 
403
    psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
 
404
    psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
 
405
 
 
406
    return psp;
 
407
 
 
408
 handle_error:
 
409
    if (pSAREA != MAP_FAILED)
 
410
        drmUnmap(pSAREA, SAREA_MAX);
 
411
 
 
412
    if (framebuffer.base != MAP_FAILED)
 
413
        drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
 
414
 
 
415
    if (framebuffer.dev_priv != NULL)
 
416
        Xfree(framebuffer.dev_priv);
 
417
 
 
418
    if (fd >= 0)
 
419
        drmCloseOnce(fd);
 
420
 
 
421
    XF86DRICloseConnection(dpy, scrn);
 
422
 
 
423
    ErrorMessageF("reverting to software direct rendering\n");
 
424
 
 
425
    return NULL;
 
426
}
 
427
 
 
428
#else /* !GLX_USE_APPLEGL */
 
429
 
 
430
static void *
 
431
CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
 
432
                    __GLXDRIdisplayPrivate * driDpy)
 
433
{
 
434
    return NULL;
 
435
}
 
436
 
 
437
#endif /* !GLX_USE_APPLEGL */
 
438
 
 
439
static void driDestroyContext(__GLXDRIcontext *context,
 
440
                              __GLXscreenConfigs *psc, Display *dpy)
 
441
{
 
442
    __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
 
443
                        
 
444
    (*psc->core->destroyContext)(pcp->driContext);
 
445
 
 
446
    XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
 
447
    Xfree(pcp);
 
448
}
 
449
 
 
450
static Bool driBindContext(__GLXDRIcontext *context,
 
451
                           __GLXDRIdrawable *draw, __GLXDRIdrawable *read)
 
452
{
 
453
    __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
 
454
    const __DRIcoreExtension *core = pcp->psc->core;
 
455
 
 
456
    return (*core->bindContext)(pcp->driContext,
 
457
                                draw->driDrawable,
 
458
                                read->driDrawable);
 
459
}
 
460
 
 
461
static void driUnbindContext(__GLXDRIcontext *context)
 
462
{
 
463
    __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
 
464
    const __DRIcoreExtension *core = pcp->psc->core;
 
465
 
 
466
    (*core->unbindContext)(pcp->driContext);
 
467
}
 
468
 
 
469
static __GLXDRIcontext *driCreateContext(__GLXscreenConfigs *psc,
 
470
                                         const __GLcontextModes *mode,
 
471
                                         GLXContext gc,
 
472
                                         GLXContext shareList, int renderType)
 
473
{
 
474
    __GLXDRIcontextPrivate *pcp, *pcp_shared;
 
475
    drm_context_t hwContext;
 
476
    __DRIcontext *shared = NULL;
 
477
    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
 
478
 
 
479
    if (!psc || !psc->driScreen)
 
480
        return NULL;
 
481
 
 
482
    if (shareList) {
 
483
        pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
 
484
        shared = pcp_shared->driContext;
 
485
    }
 
486
 
 
487
    pcp = Xmalloc(sizeof *pcp);
 
488
    if (pcp == NULL)
 
489
        return NULL;
 
490
 
 
491
    pcp->psc = psc;
 
492
    if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr,
 
493
                                        mode->visualID,
 
494
                                        &pcp->hwContextID, &hwContext)) {
 
495
        Xfree(pcp);
 
496
        return NULL;
 
497
    }
 
498
 
 
499
    pcp->driContext =
 
500
        (*psc->legacy->createNewContext)(psc->__driScreen,
 
501
                                         config->driConfig,
 
502
                                         renderType,
 
503
                                         shared,
 
504
                                         hwContext,
 
505
                                         pcp);
 
506
    if (pcp->driContext == NULL) {
 
507
        XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
 
508
        Xfree(pcp);
 
509
        return NULL;
 
510
    }
 
511
 
 
512
    pcp->base.destroyContext = driDestroyContext;
 
513
    pcp->base.bindContext = driBindContext;
 
514
    pcp->base.unbindContext = driUnbindContext;
 
515
 
 
516
    return &pcp->base;
 
517
}
 
518
 
 
519
static void driDestroyDrawable(__GLXDRIdrawable *pdraw)
 
520
{
 
521
    __GLXscreenConfigs *psc = pdraw->psc;
 
522
 
 
523
    (*psc->core->destroyDrawable)(pdraw->driDrawable);
 
524
    XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable);
 
525
    Xfree(pdraw);
 
526
}
 
527
 
 
528
static __GLXDRIdrawable *driCreateDrawable(__GLXscreenConfigs *psc,
 
529
                                           XID xDrawable,
 
530
                                           GLXDrawable drawable,
 
531
                                           const __GLcontextModes *modes)
 
532
{
 
533
    __GLXDRIdrawable *pdraw;
 
534
    drm_drawable_t hwDrawable;
 
535
    void *empty_attribute_list = NULL;
 
536
    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
 
537
 
 
538
    /* Old dri can't handle GLX 1.3+ drawable constructors. */
 
539
    if (xDrawable != drawable)
 
540
        return NULL;
 
541
 
 
542
    pdraw = Xmalloc(sizeof(*pdraw));
 
543
    if (!pdraw)
 
544
        return NULL;
 
545
 
 
546
    pdraw->drawable = drawable;
 
547
    pdraw->psc = psc;
 
548
 
 
549
    if (!XF86DRICreateDrawable(psc->dpy, psc->scr, drawable, &hwDrawable))
 
550
        return NULL;
 
551
 
 
552
    /* Create a new drawable */
 
553
    pdraw->driDrawable =
 
554
        (*psc->legacy->createNewDrawable)(psc->__driScreen,
 
555
                                          config->driConfig,
 
556
                                          hwDrawable,
 
557
                                          GLX_WINDOW_BIT,
 
558
                                          empty_attribute_list,
 
559
                                          pdraw);
 
560
 
 
561
    if (!pdraw->driDrawable) {
 
562
        XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable);
 
563
        Xfree(pdraw);
 
564
        return NULL;
 
565
    }
 
566
 
 
567
    pdraw->destroyDrawable = driDestroyDrawable;
 
568
 
 
569
    return pdraw;
 
570
}
 
571
 
 
572
static void driSwapBuffers(__GLXDRIdrawable *pdraw)
 
573
{
 
574
   (*pdraw->psc->core->swapBuffers)(pdraw->driDrawable);
 
575
}
 
576
 
 
577
static void driCopySubBuffer(__GLXDRIdrawable *pdraw,
 
578
                             int x, int y, int width, int height)
 
579
{
 
580
    (*pdraw->psc->driCopySubBuffer->copySubBuffer)(pdraw->driDrawable,
 
581
                                                   x, y, width, height);
 
582
}
 
583
 
 
584
static void driDestroyScreen(__GLXscreenConfigs *psc)
 
585
{
 
586
    /* Free the direct rendering per screen data */
 
587
    if (psc->__driScreen)
 
588
        (*psc->core->destroyScreen)(psc->__driScreen);
 
589
    psc->__driScreen = NULL;
 
590
    if (psc->driver)
 
591
        dlclose(psc->driver);
 
592
}
 
593
 
 
594
static __GLXDRIscreen *driCreateScreen(__GLXscreenConfigs *psc, int screen,
 
595
                                       __GLXdisplayPrivate *priv)
 
596
{
 
597
    __GLXDRIdisplayPrivate *pdp;
 
598
    __GLXDRIscreen *psp;
 
599
    const __DRIextension **extensions;
 
600
    char *driverName;
 
601
    int i;
 
602
 
 
603
    psp = Xmalloc(sizeof *psp);
 
604
    if (psp == NULL)
 
605
        return NULL;
 
606
 
 
607
    /* Initialize per screen dynamic client GLX extensions */
 
608
    psc->ext_list_first_time = GL_TRUE;
 
609
 
 
610
    if (!driGetDriverName(priv->dpy, screen, &driverName)) {
 
611
        Xfree(psp);
 
612
        return NULL;
 
613
    }
 
614
 
 
615
    psc->driver = driOpenDriver(driverName);
 
616
    Xfree(driverName);
 
617
    if (psc->driver == NULL) {
 
618
        Xfree(psp);
 
619
        return NULL;
 
620
    }
 
621
 
 
622
    extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
 
623
    if (extensions == NULL) {
 
624
        ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
 
625
        Xfree(psp);
 
626
        return NULL;
 
627
    }
 
628
 
 
629
    for (i = 0; extensions[i]; i++) {
 
630
        if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
 
631
            psc->core = (__DRIcoreExtension *) extensions[i];
 
632
        if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0)
 
633
            psc->legacy = (__DRIlegacyExtension *) extensions[i];
 
634
    }
 
635
 
 
636
    if (psc->core == NULL || psc->legacy == NULL) {
 
637
        Xfree(psp);
 
638
        return NULL;
 
639
    }
 
640
  
 
641
    pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay;
 
642
    psc->__driScreen =
 
643
        CallCreateNewScreen(psc->dpy, screen, psc, pdp);
 
644
    if (psc->__driScreen == NULL) {
 
645
        dlclose(psc->driver);
 
646
        Xfree(psp);
 
647
        return NULL;
 
648
    }
 
649
 
 
650
    driBindExtensions(psc, 0);
 
651
    if (psc->driCopySubBuffer)
 
652
        psp->copySubBuffer = driCopySubBuffer;
 
653
 
 
654
    psp->destroyScreen = driDestroyScreen;
 
655
    psp->createContext = driCreateContext;
 
656
    psp->createDrawable = driCreateDrawable;
 
657
    psp->swapBuffers = driSwapBuffers;
 
658
    psp->waitX = NULL;
 
659
    psp->waitGL = NULL;
 
660
 
 
661
    return psp;
 
662
}
 
663
 
 
664
/* Called from __glXFreeDisplayPrivate.
 
665
 */
 
666
static void driDestroyDisplay(__GLXDRIdisplay *dpy)
 
667
{
 
668
    Xfree(dpy);
 
669
}
 
670
 
 
671
/*
 
672
 * Allocate, initialize and return a __DRIdisplayPrivate object.
 
673
 * This is called from __glXInitialize() when we are given a new
 
674
 * display pointer.
 
675
 */
 
676
_X_HIDDEN __GLXDRIdisplay *driCreateDisplay(Display *dpy)
 
677
{
 
678
    __GLXDRIdisplayPrivate *pdpyp;
 
679
    int eventBase, errorBase;
 
680
    int major, minor, patch;
 
681
 
 
682
    if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
 
683
        return NULL;
 
684
    }
 
685
 
 
686
    if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
 
687
        return NULL;
 
688
    }
 
689
 
 
690
    pdpyp = Xmalloc(sizeof *pdpyp);
 
691
    if (!pdpyp) {
 
692
        return NULL;
 
693
    }
 
694
 
 
695
    pdpyp->driMajor = major;
 
696
    pdpyp->driMinor = minor;
 
697
    pdpyp->driPatch = patch;
 
698
 
 
699
    pdpyp->base.destroyDisplay = driDestroyDisplay;
 
700
    pdpyp->base.createScreen = driCreateScreen;
 
701
 
 
702
    return &pdpyp->base;
 
703
}
 
704
 
 
705
#endif /* GLX_DIRECT_RENDERING */