~ubuntu-branches/ubuntu/edgy/xorg-server/edgy-updates

« back to all changes in this revision

Viewing changes to GL/glx/glxdri.c

  • Committer: Bazaar Package Importer
  • Author(s): Rodrigo Parra Novo
  • Date: 2006-07-25 20:06:28 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20060725200628-gjmmd9gxfxdc4ejs
Tags: 1:1.1.1-0ubuntu1
* New Upstream version
* Changed Build-Depends from mesa-swrast-source to mesa-swx11-source,
  following Debian package nomenclature
* Re-did 12_security_policy_in_etc.diff for 1.1.1
* Dropped 15_security_allocate_local.diff (applied upstream)
* Dropped 16_SECURITY_setuid.diff (applied upstream)
* Dropped 000_ubuntu_fix_read_kernel_mapping.patch (applied upstream)
* Dropped 002_ubuntu_fix_for_certain_intel_chipsets.patch (applied upstream)
* Updated versioned Build-Depends on mesa-swx11-source to version
  6.5.0.cvs.20060725-0ubuntu1
* Added arrayobj.c, arrayobj.h, bitset.h & rbadaptors.h to
  GL/symlink-mesa.sh (linked from mesa-swx11-source)
* Added arrayobj.c to default build target on GL/mesa/main

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2006 Red Hat, Inc
 
3
 *
 
4
 * Permission to use, copy, modify, distribute, and sell this software
 
5
 * and its documentation for any purpose is hereby granted without
 
6
 * fee, provided that the above copyright notice appear in all copies
 
7
 * and that both that copyright notice and this permission notice
 
8
 * appear in supporting documentation, and that the name of Red Hat,
 
9
 * Inc not be used in advertising or publicity pertaining to
 
10
 * distribution of the software without specific, written prior
 
11
 * permission.  Red Hat, Inc makes no representations about the
 
12
 * suitability of this software for any purpose.  It is provided "as
 
13
 * is" without express or implied warranty.
 
14
 *
 
15
 * RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
16
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
 
17
 * NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
18
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
 
19
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 
20
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 
21
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
22
 */
 
23
 
 
24
#ifdef HAVE_DIX_CONFIG_H
 
25
#include <dix-config.h>
 
26
#endif
 
27
 
 
28
#include <stdint.h>
 
29
#include <stdio.h>
 
30
#include <string.h>
 
31
#include <errno.h>
 
32
#include <sys/time.h>
 
33
#include <dlfcn.h>
 
34
 
 
35
#include <drm.h>
 
36
#include <GL/gl.h>
 
37
#include <GL/internal/dri_interface.h>
 
38
 
 
39
#include <windowstr.h>
 
40
#include <os.h>
 
41
 
 
42
#define _XF86DRI_SERVER_
 
43
#include <drm_sarea.h>
 
44
#include <xf86drm.h>
 
45
#include <xf86dristr.h>
 
46
#include <xf86str.h>
 
47
#include <xf86.h>
 
48
#include <dri.h>
 
49
 
 
50
#define DRI_NEW_INTERFACE_ONLY
 
51
#include "glxserver.h"
 
52
#include "glxutil.h"
 
53
#include "glcontextmodes.h"
 
54
 
 
55
#include "g_disptab.h"
 
56
#include "g_disptab_EXT.h"
 
57
#include "glapitable.h"
 
58
#include "glapi.h"
 
59
#include "glthread.h"
 
60
#include "dispatch.h"
 
61
 
 
62
 
 
63
#define STRINGIFY(macro_or_string)      STRINGIFY_ARG (macro_or_string)
 
64
#define STRINGIFY_ARG(contents) #contents
 
65
 
 
66
typedef struct __GLXDRIscreen      __GLXDRIscreen;
 
67
typedef struct __GLXDRIcontext         __GLXDRIcontext;
 
68
typedef struct __GLXDRIdrawable __GLXDRIdrawable;
 
69
 
 
70
struct __GLXDRIscreen {
 
71
    __GLXscreen          base;
 
72
 
 
73
    __DRIscreen                  driScreen;
 
74
    void                        *driver;
 
75
};
 
76
 
 
77
struct __GLXDRIcontext {
 
78
    __GLXcontext                 base;
 
79
 
 
80
    __DRIcontext                 driContext;
 
81
};
 
82
 
 
83
struct __GLXDRIdrawable {
 
84
    __GLXdrawable        base;
 
85
 
 
86
    __DRIdrawable               *driDrawable;
 
87
};
 
88
 
 
89
/* History:
 
90
 * 20021121 - Initial version
 
91
 * 20021128 - Added __glXWindowExists() function
 
92
 * 20021207 - Added support for dynamic GLX extensions,
 
93
 *            GLX_SGI_swap_control, GLX_SGI_video_sync,
 
94
 *            GLX_OML_sync_control, and GLX_MESA_swap_control.
 
95
 *            Never officially released.  Do NOT test against
 
96
 *            this version.  Use 20030317 instead.
 
97
 * 20030317 - Added support GLX_SGIX_fbconfig,
 
98
 *            GLX_MESA_swap_frame_usage, GLX_OML_swap_method,
 
99
 *            GLX_{ARB,SGIS}_multisample, and
 
100
 *            GLX_SGIX_visual_select_group.
 
101
 * 20030606 - Added support for GLX_SGI_make_current_read.
 
102
 * 20030813 - Made support for dynamic extensions multi-head aware.
 
103
 * 20030818 - Added support for GLX_MESA_allocate_memory in place of the
 
104
 *            deprecated GLX_NV_vertex_array_range & GLX_MESA_agp_offset
 
105
 *            interfaces.
 
106
 * 20031201 - Added support for the first round of DRI interface changes.
 
107
 *            Do NOT test against this version!  It has binary
 
108
 *            compatibility bugs, use 20040317 instead.
 
109
 * 20040317 - Added the 'mode' field to __DRIcontextRec.
 
110
 * 20040415 - Added support for bindContext3 and unbindContext3.
 
111
 * 20040602 - Add __glXGetDrawableInfo.  I though that was there
 
112
 *            months ago. :(
 
113
 * 20050727 - Gut all the old interfaces.  This breaks compatability with
 
114
 *            any DRI driver built to any previous version.
 
115
 */
 
116
#define INTERNAL_VERSION 20050727
 
117
 
 
118
static const char CREATE_NEW_SCREEN_FUNC[] =
 
119
    "__driCreateNewScreen_" STRINGIFY (INTERNAL_VERSION);
 
120
 
 
121
static void
 
122
__glXDRIleaveServer(void)
 
123
{
 
124
  int i;
 
125
 
 
126
  for (i = 0; i < screenInfo.numScreens; i++)
 
127
    DRIDoBlockHandler(i, NULL, NULL, NULL);
 
128
}
 
129
    
 
130
static void
 
131
__glXDRIenterServer(void)
 
132
{
 
133
  int i;
 
134
 
 
135
  for (i = 0; i < screenInfo.numScreens; i++)
 
136
    DRIDoWakeupHandler(i, NULL, 0, NULL);
 
137
}
 
138
 
 
139
static void
 
140
__glXDRIdrawableDestroy(__GLXdrawable *private)
 
141
{
 
142
#if 0
 
143
    (*glxPriv->driDrawable.destroyDrawable)(NULL,
 
144
                                            glxPriv->driDrawable.private);
 
145
#endif
 
146
 
 
147
    xfree(private);
 
148
}
 
149
 
 
150
static GLboolean
 
151
__glXDRIdrawableResize(__GLXdrawable *glxPriv)
 
152
{
 
153
    /* Nothing to do here, the DRI driver asks the server for drawable
 
154
     * geometry when it sess the SAREA timestamps change.*/
 
155
 
 
156
    return GL_TRUE;
 
157
}
 
158
 
 
159
static GLboolean
 
160
__glXDRIdrawableSwapBuffers(__GLXdrawable *basePrivate)
 
161
{
 
162
    __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
 
163
    __GLXDRIscreen *screen;
 
164
 
 
165
    /* FIXME: We're jumping through hoops here to get the DRIdrawable
 
166
     * which the dri driver tries to keep to it self...  cf. FIXME in
 
167
     * createDrawable. */
 
168
 
 
169
    screen = (__GLXDRIscreen *) __glXgetActiveScreen(private->base.pDraw->pScreen->myNum);
 
170
    private->driDrawable = (screen->driScreen.getDrawable)(NULL,
 
171
                                                           private->base.drawId,
 
172
                                                           screen->driScreen.private);
 
173
 
 
174
    (*private->driDrawable->swapBuffers)(NULL,
 
175
                                         private->driDrawable->private);
 
176
 
 
177
    return TRUE;
 
178
}
 
179
 
 
180
static __GLXdrawable *
 
181
__glXDRIcontextCreateDrawable(__GLXcontext *context,
 
182
                              DrawablePtr pDraw,
 
183
                              XID drawId)
 
184
{
 
185
    __GLXDRIdrawable *private;
 
186
 
 
187
    private = xalloc(sizeof *private);
 
188
    if (private == NULL)
 
189
        return NULL;
 
190
 
 
191
    memset(private, 0, sizeof *private);
 
192
 
 
193
    if (!__glXDrawableInit(&private->base, context, pDraw, drawId)) {
 
194
        xfree(private);
 
195
        return NULL;
 
196
    }
 
197
 
 
198
    private->base.destroy     = __glXDRIdrawableDestroy;
 
199
    private->base.resize      = __glXDRIdrawableResize;
 
200
    private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
 
201
    
 
202
#if 0
 
203
    /* FIXME: It would only be natural that we called
 
204
     * driScreen->createNewDrawable here but the DRI drivers manage
 
205
     * them a little oddly. FIXME: describe this better.*/
 
206
 
 
207
    /* The last argument is 'attrs', which is used with pbuffers which
 
208
     * we currently don't support. */
 
209
 
 
210
    glxPriv->driDrawable.private =
 
211
        (pGlxScreen->driScreen.createNewDrawable)(NULL, modes,
 
212
                                                  drawId,
 
213
                                                  &glxPriv->driDrawable,
 
214
                                                  0,
 
215
                                                  NULL);
 
216
#endif
 
217
 
 
218
    return &private->base;
 
219
}
 
220
 
 
221
 
 
222
static void
 
223
__glXDRIcontextDestroy(__GLXcontext *baseContext)
 
224
{
 
225
    __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
 
226
 
 
227
    context->driContext.destroyContext(NULL,
 
228
                                       context->base.pScreen->myNum,
 
229
                                       context->driContext.private);
 
230
    __glXContextDestroy(&context->base);
 
231
    xfree(context);
 
232
}
 
233
 
 
234
static int
 
235
__glXDRIcontextMakeCurrent(__GLXcontext *baseContext)
 
236
{
 
237
    __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
 
238
 
 
239
    return (*context->driContext.bindContext)(NULL,
 
240
                                              context->base.pScreen->myNum,
 
241
                                              baseContext->drawPriv->drawId,
 
242
                                              baseContext->readPriv->drawId,
 
243
                                              &context->driContext);
 
244
}
 
245
 
 
246
static int
 
247
__glXDRIcontextLoseCurrent(__GLXcontext *baseContext)
 
248
{
 
249
    __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
 
250
 
 
251
    return (*context->driContext.unbindContext)(NULL,
 
252
                                                context->base.pScreen->myNum,
 
253
                                                baseContext->drawPriv->drawId,
 
254
                                                baseContext->readPriv->drawId,
 
255
                                                &context->driContext);
 
256
}
 
257
 
 
258
static int
 
259
__glXDRIcontextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
 
260
                    unsigned long mask)
 
261
{
 
262
    __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
 
263
    __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
 
264
 
 
265
    /* FIXME: We will need to add DRIcontext::copyContext for this. */
 
266
 
 
267
    (void) dst;
 
268
    (void) src;
 
269
 
 
270
    return FALSE;
 
271
}
 
272
 
 
273
static int
 
274
__glXDRIcontextForceCurrent(__GLXcontext *baseContext)
 
275
{
 
276
    __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
 
277
 
 
278
    return (*context->driContext.bindContext)(NULL,
 
279
                                              context->base.pScreen->myNum,
 
280
                                              baseContext->drawPriv->drawId,
 
281
                                              baseContext->readPriv->drawId,
 
282
                                              &context->driContext);
 
283
}
 
284
 
 
285
static int
 
286
glxCountBits(int word)
 
287
{
 
288
    int ret = 0;
 
289
 
 
290
    while (word) {
 
291
        ret += (word & 1);
 
292
        word >>= 1;
 
293
    }
 
294
 
 
295
    return ret;
 
296
}
 
297
 
 
298
static void
 
299
glxFillAlphaChannel (PixmapPtr pixmap)
 
300
{
 
301
    int i, j;
 
302
    CARD32 *pixels = (CARD32 *)pixmap->devPrivate.ptr;
 
303
    CARD32 rowstride = pixmap->devKind / 4;
 
304
    CARD32 x, y;
 
305
 
 
306
    x = pixmap->drawable.x;
 
307
    y = pixmap->drawable.y;
 
308
    
 
309
    for (i = y; i < pixmap->drawable.height + y; ++i)
 
310
    {
 
311
        for (j = x; j < pixmap->drawable.width + x; ++j)
 
312
        {
 
313
            int index = i * rowstride + j;
 
314
 
 
315
            pixels[index] |= 0xFF000000;
 
316
        }
 
317
    }
 
318
}
 
319
 
 
320
/*
 
321
 * (sticking this here for lack of a better place)
 
322
 * Known issues with the GLX_EXT_texture_from_pixmap implementation:
 
323
 * - In general we ignore the fbconfig, lots of examples follow
 
324
 * - No fbconfig handling for multiple mipmap levels
 
325
 * - No fbconfig handling for 1D textures
 
326
 * - No fbconfig handling for TEXTURE_TARGET
 
327
 * - No fbconfig exposure of Y inversion state
 
328
 * - No GenerateMipmapEXT support (due to no FBO support)
 
329
 * - No damage tracking between binds
 
330
 * - No support for anything but 16bpp and 32bpp-sparse pixmaps
 
331
 */
 
332
 
 
333
static int
 
334
__glXDRIbindTexImage(__GLXcontext *baseContext,
 
335
                     int buffer,
 
336
                     __GLXpixmap *glxPixmap)
 
337
{
 
338
    PixmapPtr   pixmap;
 
339
    int         bpp;
 
340
    Bool        npot;
 
341
 
 
342
    pixmap = (PixmapPtr) glxPixmap->pDraw;
 
343
    bpp = pixmap->drawable.depth >= 24 ? 4 : 2; /* XXX 24bpp packed, 8, etc */
 
344
    
 
345
    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH,
 
346
                                       pixmap->devKind / bpp) );
 
347
    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS,
 
348
                                       pixmap->drawable.y) );
 
349
    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS,
 
350
                                       pixmap->drawable.x) );
 
351
 
 
352
    if (pixmap->drawable.depth == 24)
 
353
        glxFillAlphaChannel(pixmap);
 
354
 
 
355
    npot = !(glxCountBits(pixmap->drawable.width) == 1 &&
 
356
             glxCountBits(pixmap->drawable.height) == 1) /* ||
 
357
             strstr(CALL_GetString(GL_EXTENSIONS,
 
358
                    "GL_ARB_texture_non_power_of_two")) */ ;
 
359
    
 
360
    CALL_TexImage2D( GET_DISPATCH(),
 
361
                     ( npot ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D,
 
362
                       0,
 
363
                       bpp == 4 ? 4 : 3,
 
364
                       pixmap->drawable.width,
 
365
                       pixmap->drawable.height,
 
366
                       0,
 
367
                       bpp == 4 ? GL_BGRA : GL_RGB,
 
368
                       bpp == 4 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
 
369
                       pixmap->devPrivate.ptr ) );
 
370
 
 
371
    return Success;
 
372
}
 
373
 
 
374
static int
 
375
__glXDRIreleaseTexImage(__GLXcontext *baseContext,
 
376
                        int buffer,
 
377
                        __GLXpixmap *pixmap)
 
378
{
 
379
    return Success;
 
380
}
 
381
 
 
382
static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
 
383
    __glXDRIbindTexImage,
 
384
    __glXDRIreleaseTexImage
 
385
};
 
386
 
 
387
static void
 
388
__glXDRIscreenDestroy(__GLXscreen *baseScreen)
 
389
{
 
390
    __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
 
391
 
 
392
    screen->driScreen.destroyScreen(NULL,
 
393
                                    screen->base.pScreen->myNum,
 
394
                                    screen->driScreen.private);
 
395
 
 
396
    dlclose(screen->driver);
 
397
 
 
398
    __glXScreenDestroy(baseScreen);
 
399
 
 
400
    xfree(screen);
 
401
}
 
402
 
 
403
static __GLXcontext *
 
404
__glXDRIscreenCreateContext(__GLXscreen *baseScreen,
 
405
                            __GLcontextModes *modes,
 
406
                            __GLXcontext *baseShareContext)
 
407
{
 
408
    __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
 
409
    __GLXDRIcontext *context, *shareContext;
 
410
    void *sharePrivate;
 
411
 
 
412
    shareContext = (__GLXDRIcontext *) baseShareContext;
 
413
    if (shareContext)
 
414
        sharePrivate = shareContext->driContext.private;
 
415
    else
 
416
        sharePrivate = NULL;
 
417
 
 
418
    context = xalloc(sizeof *context);
 
419
    if (context == NULL)
 
420
        return NULL;
 
421
 
 
422
    memset(context, 0, sizeof *context);
 
423
    context->base.destroy           = __glXDRIcontextDestroy;
 
424
    context->base.makeCurrent       = __glXDRIcontextMakeCurrent;
 
425
    context->base.loseCurrent       = __glXDRIcontextLoseCurrent;
 
426
    context->base.copy              = __glXDRIcontextCopy;
 
427
    context->base.forceCurrent      = __glXDRIcontextForceCurrent;
 
428
    context->base.createDrawable    = __glXDRIcontextCreateDrawable;
 
429
 
 
430
    context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
 
431
 
 
432
    context->driContext.private =
 
433
        screen->driScreen.createNewContext(NULL, modes,
 
434
                                           0, /* render type */
 
435
                                           sharePrivate,
 
436
                                           &context->driContext);
 
437
 
 
438
    context->driContext.mode = modes;
 
439
 
 
440
    return &context->base;
 
441
}
 
442
 
 
443
static unsigned
 
444
filter_modes(__GLcontextModes **server_modes,
 
445
             const __GLcontextModes *driver_modes)
 
446
{
 
447
    __GLcontextModes * m;
 
448
    __GLcontextModes ** prev_next;
 
449
    const __GLcontextModes * check;
 
450
    unsigned modes_count = 0;
 
451
 
 
452
    if ( driver_modes == NULL ) {
 
453
        LogMessage(X_WARNING,
 
454
                   "AIGLX: 3D driver returned no fbconfigs.\n");
 
455
        return 0;
 
456
    }
 
457
 
 
458
    /* For each mode in server_modes, check to see if a matching mode exists
 
459
     * in driver_modes.  If not, then the mode is not available.
 
460
     */
 
461
 
 
462
    prev_next = server_modes;
 
463
    for ( m = *prev_next ; m != NULL ; m = *prev_next ) {
 
464
        GLboolean do_delete = GL_TRUE;
 
465
 
 
466
        for ( check = driver_modes ; check != NULL ; check = check->next ) {
 
467
            if ( _gl_context_modes_are_same( m, check ) ) {
 
468
                do_delete = GL_FALSE;
 
469
                break;
 
470
            }
 
471
        }
 
472
 
 
473
        /* The 3D has to support all the modes that match the GLX visuals
 
474
         * sent from the X server.
 
475
         */
 
476
        if ( do_delete && (m->visualID != 0) ) {
 
477
            do_delete = GL_FALSE;
 
478
 
 
479
            LogMessage(X_WARNING,
 
480
                       "AIGLX: 3D driver claims to not support "
 
481
                       "visual 0x%02x\n", m->visualID);
 
482
        }
 
483
 
 
484
        if ( do_delete ) {
 
485
            *prev_next = m->next;
 
486
 
 
487
            m->next = NULL;
 
488
            _gl_context_modes_destroy( m );
 
489
        }
 
490
        else {
 
491
            modes_count++;
 
492
            prev_next = & m->next;
 
493
        }
 
494
    }
 
495
 
 
496
    return modes_count;
 
497
}
 
498
 
 
499
 
 
500
static __DRIfuncPtr getProcAddress(const char *proc_name)
 
501
{
 
502
    return NULL;
 
503
}
 
504
 
 
505
static __DRIscreen *findScreen(__DRInativeDisplay *dpy, int scrn)
 
506
{
 
507
    __GLXDRIscreen *screen =
 
508
        (__GLXDRIscreen *) __glXgetActiveScreen(scrn);
 
509
 
 
510
    return &screen->driScreen;
 
511
}
 
512
 
 
513
static GLboolean windowExists(__DRInativeDisplay *dpy, __DRIid draw)
 
514
{
 
515
    WindowPtr pWin = (WindowPtr) LookupIDByType(draw, RT_WINDOW);
 
516
 
 
517
    return pWin == NULL ? GL_FALSE : GL_TRUE;
 
518
}
 
519
 
 
520
static GLboolean createContext(__DRInativeDisplay *dpy, int screen,
 
521
                               int configID, void *contextID,
 
522
                               drm_context_t *hw_context)
 
523
{
 
524
    XID fakeID;
 
525
    VisualPtr visual;
 
526
    int i;
 
527
    ScreenPtr pScreen;
 
528
    GLboolean retval;
 
529
 
 
530
    pScreen = screenInfo.screens[screen];
 
531
 
 
532
    /* Find the requested X visual */
 
533
    visual = pScreen->visuals;
 
534
    for (i = 0; i < pScreen->numVisuals; i++, visual++)
 
535
        if (visual->vid == configID)
 
536
            break;
 
537
    if (i == pScreen->numVisuals)
 
538
        return GL_FALSE;
 
539
 
 
540
    fakeID = FakeClientID(0);
 
541
    *(XID *) contextID = fakeID;
 
542
 
 
543
    __glXDRIenterServer();
 
544
    retval = DRICreateContext(pScreen, visual, fakeID, hw_context);
 
545
    __glXDRIleaveServer();
 
546
    return retval;
 
547
}
 
548
 
 
549
static GLboolean destroyContext(__DRInativeDisplay *dpy, int screen,
 
550
                                __DRIid context)
 
551
{
 
552
    GLboolean retval;
 
553
 
 
554
    __glXDRIenterServer();
 
555
    retval = DRIDestroyContext(screenInfo.screens[screen], context);
 
556
    __glXDRIleaveServer();
 
557
    return retval;
 
558
}
 
559
 
 
560
static GLboolean
 
561
createDrawable(__DRInativeDisplay *dpy, int screen,
 
562
               __DRIid drawable, drm_drawable_t *hHWDrawable)
 
563
{
 
564
    DrawablePtr pDrawable;
 
565
    GLboolean retval;
 
566
 
 
567
    pDrawable = (DrawablePtr) LookupIDByClass(drawable, RC_DRAWABLE);
 
568
    if (!pDrawable)
 
569
        return GL_FALSE;
 
570
 
 
571
    __glXDRIenterServer();
 
572
    retval = DRICreateDrawable(screenInfo.screens[screen],
 
573
                            drawable,
 
574
                            pDrawable,
 
575
                            hHWDrawable);
 
576
    __glXDRIleaveServer();
 
577
    return retval;
 
578
}
 
579
 
 
580
static GLboolean
 
581
destroyDrawable(__DRInativeDisplay *dpy, int screen, __DRIid drawable)
 
582
{
 
583
    DrawablePtr pDrawable;
 
584
    GLboolean retval;
 
585
 
 
586
    pDrawable = (DrawablePtr) LookupIDByClass(drawable, RC_DRAWABLE);
 
587
    if (!pDrawable)
 
588
        return GL_FALSE;
 
589
 
 
590
    __glXDRIenterServer();
 
591
    retval = DRIDestroyDrawable(screenInfo.screens[screen],
 
592
                             drawable,
 
593
                             pDrawable);
 
594
    __glXDRIleaveServer();
 
595
    return retval;
 
596
}
 
597
 
 
598
static GLboolean
 
599
getDrawableInfo(__DRInativeDisplay *dpy, int screen,
 
600
                __DRIid drawable, unsigned int *index, unsigned int *stamp,
 
601
                int *x, int *y, int *width, int *height,
 
602
                int *numClipRects, drm_clip_rect_t **ppClipRects,
 
603
                int *backX, int *backY,
 
604
                int *numBackClipRects, drm_clip_rect_t **ppBackClipRects)
 
605
{
 
606
    DrawablePtr pDrawable;
 
607
    drm_clip_rect_t *pClipRects, *pBackClipRects;
 
608
    GLboolean retval;
 
609
    size_t size;
 
610
 
 
611
    pDrawable = (DrawablePtr) LookupIDByClass(drawable, RC_DRAWABLE);
 
612
    if (!pDrawable) {
 
613
        ErrorF("getDrawableInfo failed to look up window\n");
 
614
 
 
615
        *index = 0;
 
616
        *stamp = 0;
 
617
        *x = 0;
 
618
        *y = 0;
 
619
        *width = 0;
 
620
        *height = 0;
 
621
        *numClipRects = 0;
 
622
        *ppClipRects = NULL;
 
623
        *backX = 0;
 
624
        *backY = 0;
 
625
        *numBackClipRects = 0;
 
626
        *ppBackClipRects = NULL;
 
627
 
 
628
        return GL_FALSE;
 
629
    }
 
630
 
 
631
    __glXDRIenterServer();
 
632
    retval = DRIGetDrawableInfo(screenInfo.screens[screen],
 
633
                                pDrawable, index, stamp,
 
634
                                x, y, width, height,
 
635
                                numClipRects, &pClipRects,
 
636
                                backX, backY,
 
637
                                numBackClipRects, &pBackClipRects);
 
638
    __glXDRIleaveServer();
 
639
 
 
640
    if (*numClipRects > 0) {
 
641
        size = sizeof (drm_clip_rect_t) * *numClipRects;
 
642
        *ppClipRects = xalloc (size);
 
643
        if (*ppClipRects != NULL)
 
644
            memcpy (*ppClipRects, pClipRects, size);
 
645
    }
 
646
    else {
 
647
      *ppClipRects = NULL;
 
648
    }
 
649
      
 
650
    if (*numBackClipRects > 0) {
 
651
        size = sizeof (drm_clip_rect_t) * *numBackClipRects;
 
652
        *ppBackClipRects = xalloc (size);
 
653
        if (*ppBackClipRects != NULL)
 
654
            memcpy (*ppBackClipRects, pBackClipRects, size);
 
655
    }
 
656
    else {
 
657
      *ppBackClipRects = NULL;
 
658
    }
 
659
 
 
660
    return GL_TRUE;
 
661
}
 
662
 
 
663
static int
 
664
getUST(int64_t *ust)
 
665
{
 
666
    struct timeval  tv;
 
667
    
 
668
    if (ust == NULL)
 
669
        return -EFAULT;
 
670
 
 
671
    if (gettimeofday(&tv, NULL) == 0) {
 
672
        ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
 
673
        return 0;
 
674
    } else {
 
675
        return -errno;
 
676
    }
 
677
}
 
678
 
 
679
/* Table of functions that we export to the driver. */
 
680
static const __DRIinterfaceMethods interface_methods = {
 
681
    getProcAddress,
 
682
 
 
683
    _gl_context_modes_create,
 
684
    _gl_context_modes_destroy,
 
685
      
 
686
    findScreen,
 
687
    windowExists,
 
688
      
 
689
    createContext,
 
690
    destroyContext,
 
691
 
 
692
    createDrawable,
 
693
    destroyDrawable,
 
694
    getDrawableInfo,
 
695
 
 
696
    getUST,
 
697
    NULL, /* glXGetMscRateOML, */
 
698
};
 
699
 
 
700
static const char dri_driver_path[] = DRI_DRIVER_PATH;
 
701
 
 
702
static __GLXscreen *
 
703
__glXDRIscreenProbe(ScreenPtr pScreen)
 
704
{
 
705
    PFNCREATENEWSCREENFUNC createNewScreen;
 
706
    drm_handle_t hSAREA;
 
707
    drmAddress pSAREA = NULL;
 
708
    char *BusID;
 
709
    __DRIversion   ddx_version;
 
710
    __DRIversion   dri_version;
 
711
    __DRIversion   drm_version;
 
712
    __DRIframebuffer  framebuffer;
 
713
    int   fd = -1;
 
714
    int   status;
 
715
    int api_ver = INTERNAL_VERSION;
 
716
    drm_magic_t magic;
 
717
    drmVersionPtr version;
 
718
    char *driverName;
 
719
    drm_handle_t  hFB;
 
720
    int        junk;
 
721
    __GLcontextModes * driver_modes;
 
722
    __GLXDRIscreen *screen;
 
723
    void *dev_priv = NULL;
 
724
    char filename[128];
 
725
    Bool isCapable;
 
726
 
 
727
    if (!xf86LoaderCheckSymbol("DRIQueryDirectRenderingCapable")) {
 
728
        LogMessage(X_ERROR, "AIGLX: DRI module not loaded\n");
 
729
        return NULL;
 
730
    }
 
731
 
 
732
    if (!DRIQueryDirectRenderingCapable(pScreen, &isCapable) || !isCapable) {
 
733
        LogMessage(X_ERROR,
 
734
                   "AIGLX: Screen %d is not DRI capable\n", pScreen->myNum);
 
735
        return NULL;
 
736
    }
 
737
 
 
738
    screen = xalloc(sizeof *screen);
 
739
    if (screen == NULL)
 
740
      return NULL;
 
741
    memset(screen, 0, sizeof *screen);
 
742
 
 
743
    screen->base.destroy       = __glXDRIscreenDestroy;
 
744
    screen->base.createContext = __glXDRIscreenCreateContext;
 
745
    screen->base.pScreen       = pScreen;
 
746
 
 
747
    /* DRI protocol version. */
 
748
    dri_version.major = XF86DRI_MAJOR_VERSION;
 
749
    dri_version.minor = XF86DRI_MINOR_VERSION;
 
750
    dri_version.patch = XF86DRI_PATCH_VERSION;
 
751
 
 
752
    framebuffer.base = NULL;
 
753
    framebuffer.dev_priv = NULL;
 
754
 
 
755
    if (!DRIOpenConnection(pScreen, &hSAREA, &BusID)) {
 
756
        LogMessage(X_ERROR, "AIGLX error: DRIOpenConnection failed\n");
 
757
        goto handle_error;
 
758
    }
 
759
 
 
760
    fd = drmOpen(NULL, BusID);
 
761
 
 
762
    if (fd < 0) {
 
763
        LogMessage(X_ERROR, "AIGLX error: drmOpen failed (%s)\n",
 
764
                   strerror(-fd));
 
765
        goto handle_error;
 
766
    }
 
767
 
 
768
    if (drmGetMagic(fd, &magic)) {
 
769
        LogMessage(X_ERROR, "AIGLX error: drmGetMagic failed\n");
 
770
        goto handle_error;
 
771
    }
 
772
 
 
773
    version = drmGetVersion(fd);
 
774
    if (version) {
 
775
        drm_version.major = version->version_major;
 
776
        drm_version.minor = version->version_minor;
 
777
        drm_version.patch = version->version_patchlevel;
 
778
        drmFreeVersion(version);
 
779
    }
 
780
    else {
 
781
        drm_version.major = -1;
 
782
        drm_version.minor = -1;
 
783
        drm_version.patch = -1;
 
784
    }
 
785
 
 
786
    if (!DRIAuthConnection(pScreen, magic)) {
 
787
        LogMessage(X_ERROR, "AIGLX error: DRIAuthConnection failed\n");
 
788
        goto handle_error;
 
789
    }
 
790
 
 
791
    /* Get device name (like "tdfx") and the ddx version numbers.
 
792
     * We'll check the version in each DRI driver's "createNewScreen"
 
793
     * function. */
 
794
    if (!DRIGetClientDriverName(pScreen,
 
795
                                &ddx_version.major,
 
796
                                &ddx_version.minor,
 
797
                                &ddx_version.patch,
 
798
                                &driverName)) {
 
799
        LogMessage(X_ERROR, "AIGLX error: DRIGetClientDriverName failed\n");
 
800
        goto handle_error;
 
801
    }
 
802
 
 
803
    snprintf(filename, sizeof filename, "%s/%s_dri.so",
 
804
             dri_driver_path, driverName);
 
805
 
 
806
    screen->driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
 
807
    if (screen->driver == NULL) {
 
808
        LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n",
 
809
                   filename, dlerror());
 
810
        goto handle_error;
 
811
    }
 
812
 
 
813
    createNewScreen = dlsym(screen->driver, CREATE_NEW_SCREEN_FUNC);
 
814
    if (createNewScreen == NULL) {
 
815
        LogMessage(X_ERROR, "AIGLX error: dlsym for %s failed (%s)\n",
 
816
                   CREATE_NEW_SCREEN_FUNC, dlerror());
 
817
      goto handle_error;
 
818
    }
 
819
 
 
820
    /*
 
821
     * Get device-specific info.  pDevPriv will point to a struct
 
822
     * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
 
823
     * has information about the screen size, depth, pitch, ancilliary
 
824
     * buffers, DRM mmap handles, etc.
 
825
     */
 
826
    if (!DRIGetDeviceInfo(pScreen, &hFB, &junk,
 
827
                          &framebuffer.size, &framebuffer.stride,
 
828
                          &framebuffer.dev_priv_size, &framebuffer.dev_priv)) {
 
829
        LogMessage(X_ERROR, "AIGLX error: XF86DRIGetDeviceInfo failed");
 
830
        goto handle_error;
 
831
    }
 
832
 
 
833
    /* Sigh... the DRI interface is broken; the DRI driver will free
 
834
     * the dev private pointer using _mesa_free() on screen destroy,
 
835
     * but we can't use _mesa_malloc() here.  In fact, the DRI driver
 
836
     * shouldn't free data it didn't allocate itself, but what can you
 
837
     * do... */
 
838
    dev_priv = xalloc(framebuffer.dev_priv_size);
 
839
    if (dev_priv == NULL) {
 
840
        LogMessage(X_ERROR, "AIGLX error: dev_priv allocation failed");
 
841
        goto handle_error;
 
842
    }
 
843
    memcpy(dev_priv, framebuffer.dev_priv, framebuffer.dev_priv_size);
 
844
    framebuffer.dev_priv = dev_priv;
 
845
 
 
846
    framebuffer.width = pScreen->width;
 
847
    framebuffer.height = pScreen->height;
 
848
 
 
849
    /* Map the framebuffer region. */
 
850
    status = drmMap(fd, hFB, framebuffer.size, 
 
851
                    (drmAddressPtr)&framebuffer.base);
 
852
    if (status != 0) {
 
853
        LogMessage(X_ERROR, "AIGLX error: drmMap of framebuffer failed (%s)",
 
854
                   strerror(-status));
 
855
        goto handle_error;
 
856
    }
 
857
 
 
858
    /* Map the SAREA region.  Further mmap regions may be setup in
 
859
     * each DRI driver's "createNewScreen" function.
 
860
     */
 
861
    status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
 
862
    if (status != 0) {
 
863
        LogMessage(X_ERROR, "AIGLX error: drmMap of SAREA failed (%s)",
 
864
                   strerror(-status));
 
865
        goto handle_error;
 
866
    }
 
867
    
 
868
    driver_modes = NULL;
 
869
    screen->driScreen.private =
 
870
        (*createNewScreen)(NULL, pScreen->myNum,
 
871
                           &screen->driScreen,
 
872
                           screen->base.modes,
 
873
                           &ddx_version,
 
874
                           &dri_version,
 
875
                           &drm_version,
 
876
                           &framebuffer,
 
877
                           pSAREA,
 
878
                           fd,
 
879
                           api_ver,
 
880
                           &interface_methods,
 
881
                           &driver_modes);
 
882
 
 
883
    if (screen->driScreen.private == NULL) {
 
884
        LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed");
 
885
        goto handle_error;
 
886
    }
 
887
 
 
888
    __glXScreenInit(&screen->base, pScreen);
 
889
 
 
890
    filter_modes(&screen->base.modes, driver_modes);
 
891
    _gl_context_modes_destroy(driver_modes);
 
892
 
 
893
    __glXsetEnterLeaveServerFuncs(__glXDRIenterServer, __glXDRIleaveServer);
 
894
 
 
895
    LogMessage(X_INFO,
 
896
               "AIGLX: Loaded and initialized %s\n", filename);
 
897
 
 
898
    return &screen->base;
 
899
 
 
900
 handle_error:
 
901
    if (pSAREA != NULL)
 
902
        drmUnmap(pSAREA, SAREA_MAX);
 
903
 
 
904
    if (framebuffer.base != NULL)
 
905
        drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
 
906
 
 
907
    if (dev_priv != NULL)
 
908
        xfree(dev_priv);
 
909
 
 
910
    if (fd >= 0)
 
911
        drmClose(fd);
 
912
 
 
913
    DRICloseConnection(pScreen);
 
914
 
 
915
    if (screen->driver)
 
916
        dlclose(screen->driver);
 
917
 
 
918
    xfree(screen);
 
919
 
 
920
    LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n");
 
921
 
 
922
    return NULL;
 
923
}
 
924
 
 
925
__GLXprovider __glXDRIProvider = {
 
926
    __glXDRIscreenProbe,
 
927
    "DRI",
 
928
    NULL
 
929
};