Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 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 
31
 *   Brian Paul 
32
 *
33
 */
34
 
35
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
36
 
37
#include 
38
#include 
39
#include 
40
#include "glxclient.h"
41
#include "xf86dri.h"
42
#include "dri2.h"
43
#include "sarea.h"
44
#include 
45
#include 
46
#include 
47
#include "xf86drm.h"
48
#include "dri_common.h"
49
 
50
struct dri_display
51
{
52
   __GLXDRIdisplay base;
53
 
54
   /*
55
    ** XFree86-DRI version information
56
    */
57
   int driMajor;
58
   int driMinor;
59
   int driPatch;
60
};
61
 
62
struct dri_screen
63
{
64
   struct glx_screen base;
65
 
66
   __DRIscreen *driScreen;
67
   __GLXDRIscreen vtable;
68
   const __DRIlegacyExtension *legacy;
69
   const __DRIcoreExtension *core;
70
   const __DRIswapControlExtension *swapControl;
71
   const __DRImediaStreamCounterExtension *msc;
72
   const __DRIconfig **driver_configs;
73
   const __DRIcopySubBufferExtension *driCopySubBuffer;
74
 
75
   void *driver;
76
   int fd;
77
};
78
 
79
struct dri_context
80
{
81
   struct glx_context base;
82
   __DRIcontext *driContext;
83
   XID hwContextID;
84
};
85
 
86
struct dri_drawable
87
{
88
   __GLXDRIdrawable base;
89
 
90
   __DRIdrawable *driDrawable;
91
};
92
 
93
static const struct glx_context_vtable dri_context_vtable;
94
 
95
/*
96
 * Given a display pointer and screen number, determine the name of
97
 * the DRI driver for the screen (i.e., "i965", "radeon", "nouveau", etc).
98
 * Return True for success, False for failure.
99
 */
100
static Bool
101
driGetDriverName(Display * dpy, int scrNum, char **driverName)
102
{
103
   int directCapable;
104
   Bool b;
105
   int event, error;
106
   int driverMajor, driverMinor, driverPatch;
107
 
108
   *driverName = NULL;
109
 
110
   if (XF86DRIQueryExtension(dpy, &event, &error)) {    /* DRI1 */
111
      if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
112
         ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
113
         return False;
114
      }
115
      if (!directCapable) {
116
         ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
117
         return False;
118
      }
119
 
120
      b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
121
                                     &driverPatch, driverName);
122
      if (!b) {
123
         ErrorMessageF("Cannot determine driver name for screen %d\n",
124
                       scrNum);
125
         return False;
126
      }
127
 
128
      InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
129
                   driverMajor, driverMinor, driverPatch, *driverName,
130
                   scrNum);
131
 
132
      return True;
133
   }
134
   else if (DRI2QueryExtension(dpy, &event, &error)) {  /* DRI2 */
135
      char *dev;
136
      Bool ret = DRI2Connect(dpy, RootWindow(dpy, scrNum), driverName, &dev);
137
 
138
      if (ret)
139
         free(dev);
140
 
141
      return ret;
142
   }
143
 
144
   return False;
145
}
146
 
147
/*
148
 * Exported function for querying the DRI driver for a given screen.
149
 *
150
 * The returned char pointer points to a static array that will be
151
 * overwritten by subsequent calls.
152
 */
153
_X_EXPORT const char *
154
glXGetScreenDriver(Display * dpy, int scrNum)
155
{
156
   static char ret[32];
157
   char *driverName;
158
   if (driGetDriverName(dpy, scrNum, &driverName)) {
159
      int len;
160
      if (!driverName)
161
         return NULL;
162
      len = strlen(driverName);
163
      if (len >= 31)
164
         return NULL;
165
      memcpy(ret, driverName, len + 1);
166
      free(driverName);
167
      return ret;
168
   }
169
   return NULL;
170
}
171
 
172
/*
173
 * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
174
 *
175
 * The returned char pointer points directly into the driver. Therefore
176
 * it should be treated as a constant.
177
 *
178
 * If the driver was not found or does not support configuration NULL is
179
 * returned.
180
 *
181
 * Note: The driver remains opened after this function returns.
182
 */
183
_X_EXPORT const char *
184
glXGetDriverConfig(const char *driverName)
185
{
186
   void *handle = driOpenDriver(driverName);
187
   if (handle)
188
      return dlsym(handle, "__driConfigOptions");
189
   else
190
      return NULL;
191
}
192
 
193
#ifdef XDAMAGE_1_1_INTERFACE
194
 
195
static GLboolean
196
has_damage_post(Display * dpy)
197
{
198
   static GLboolean inited = GL_FALSE;
199
   static GLboolean has_damage;
200
 
201
   if (!inited) {
202
      int major, minor;
203
 
204
      if (XDamageQueryVersion(dpy, &major, &minor) &&
205
          major == 1 && minor >= 1) {
206
         has_damage = GL_TRUE;
207
      }
208
      else {
209
         has_damage = GL_FALSE;
210
      }
211
      inited = GL_TRUE;
212
   }
213
 
214
   return has_damage;
215
}
216
 
217
static void
218
__glXReportDamage(__DRIdrawable * driDraw,
219
                  int x, int y,
220
                  drm_clip_rect_t * rects, int num_rects,
221
                  GLboolean front_buffer, void *loaderPrivate)
222
{
223
   XRectangle *xrects;
224
   XserverRegion region;
225
   int i;
226
   int x_off, y_off;
227
   __GLXDRIdrawable *glxDraw = loaderPrivate;
228
   struct glx_screen *psc = glxDraw->psc;
229
   Display *dpy = psc->dpy;
230
   Drawable drawable;
231
 
232
   if (!has_damage_post(dpy))
233
      return;
234
 
235
   if (front_buffer) {
236
      x_off = x;
237
      y_off = y;
238
      drawable = RootWindow(dpy, psc->scr);
239
   }
240
   else {
241
      x_off = 0;
242
      y_off = 0;
243
      drawable = glxDraw->xDrawable;
244
   }
245
 
246
   xrects = malloc(sizeof(XRectangle) * num_rects);
247
   if (xrects == NULL)
248
      return;
249
 
250
   for (i = 0; i < num_rects; i++) {
251
      xrects[i].x = rects[i].x1 + x_off;
252
      xrects[i].y = rects[i].y1 + y_off;
253
      xrects[i].width = rects[i].x2 - rects[i].x1;
254
      xrects[i].height = rects[i].y2 - rects[i].y1;
255
   }
256
   region = XFixesCreateRegion(dpy, xrects, num_rects);
257
   free(xrects);
258
   XDamageAdd(dpy, drawable, region);
259
   XFixesDestroyRegion(dpy, region);
260
}
261
 
262
static const __DRIdamageExtension damageExtension = {
263
   {__DRI_DAMAGE, __DRI_DAMAGE_VERSION},
264
   __glXReportDamage,
265
};
266
 
267
#endif
268
 
269
static GLboolean
270
__glXDRIGetDrawableInfo(__DRIdrawable * drawable,
271
                        unsigned int *index, unsigned int *stamp,
272
                        int *X, int *Y, int *W, int *H,
273
                        int *numClipRects, drm_clip_rect_t ** pClipRects,
274
                        int *backX, int *backY,
275
                        int *numBackClipRects,
276
                        drm_clip_rect_t ** pBackClipRects,
277
                        void *loaderPrivate)
278
{
279
   __GLXDRIdrawable *glxDraw = loaderPrivate;
280
   struct glx_screen *psc = glxDraw->psc;
281
   Display *dpy = psc->dpy;
282
 
283
   return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable,
284
                                 index, stamp, X, Y, W, H,
285
                                 numClipRects, pClipRects,
286
                                 backX, backY,
287
                                 numBackClipRects, pBackClipRects);
288
}
289
 
290
static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = {
291
   {__DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION},
292
   __glXDRIGetDrawableInfo
293
};
294
 
295
static const __DRIextension *loader_extensions[] = {
296
   &systemTimeExtension.base,
297
   &getDrawableInfoExtension.base,
298
#ifdef XDAMAGE_1_1_INTERFACE
299
   &damageExtension.base,
300
#endif
301
   NULL
302
};
303
 
304
/**
305
 * Perform the required libGL-side initialization and call the client-side
306
 * driver's \c __driCreateNewScreen function.
307
 *
308
 * \param dpy    Display pointer.
309
 * \param scrn   Screen number on the display.
310
 * \param psc    DRI screen information.
311
 * \param driDpy DRI display information.
312
 * \param createNewScreen  Pointer to the client-side driver's
313
 *               \c __driCreateNewScreen function.
314
 * \returns A pointer to the \c __DRIscreen structure returned by
315
 *          the client-side driver on success, or \c NULL on failure.
316
 */
317
static void *
318
CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc,
319
                    struct dri_display * driDpy)
320
{
321
   void *psp = NULL;
322
   drm_handle_t hSAREA;
323
   drmAddress pSAREA = MAP_FAILED;
324
   char *BusID;
325
   __DRIversion ddx_version;
326
   __DRIversion dri_version;
327
   __DRIversion drm_version;
328
   __DRIframebuffer framebuffer;
329
   int fd = -1;
330
   int status;
331
 
332
   drm_magic_t magic;
333
   drmVersionPtr version;
334
   int newlyopened;
335
   char *driverName;
336
   drm_handle_t hFB;
337
   int junk;
338
   const __DRIconfig **driver_configs;
339
   struct glx_config *visual, *configs = NULL, *visuals = NULL;
340
 
341
   /* DRI protocol version. */
342
   dri_version.major = driDpy->driMajor;
343
   dri_version.minor = driDpy->driMinor;
344
   dri_version.patch = driDpy->driPatch;
345
 
346
   framebuffer.base = MAP_FAILED;
347
   framebuffer.dev_priv = NULL;
348
   framebuffer.size = 0;
349
 
350
   if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
351
      ErrorMessageF("XF86DRIOpenConnection failed\n");
352
      goto handle_error;
353
   }
354
 
355
   fd = drmOpenOnce(NULL, BusID, &newlyopened);
356
 
357
   free(BusID);                /* No longer needed */
358
 
359
   if (fd < 0) {
360
      ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd));
361
      goto handle_error;
362
   }
363
 
364
   if (drmGetMagic(fd, &magic)) {
365
      ErrorMessageF("drmGetMagic failed\n");
366
      goto handle_error;
367
   }
368
 
369
   version = drmGetVersion(fd);
370
   if (version) {
371
      drm_version.major = version->version_major;
372
      drm_version.minor = version->version_minor;
373
      drm_version.patch = version->version_patchlevel;
374
      drmFreeVersion(version);
375
   }
376
   else {
377
      drm_version.major = -1;
378
      drm_version.minor = -1;
379
      drm_version.patch = -1;
380
   }
381
 
382
   if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) {
383
      ErrorMessageF("XF86DRIAuthConnection failed\n");
384
      goto handle_error;
385
   }
386
 
387
   /* Get device name (like "radeon") and the ddx version numbers.
388
    * We'll check the version in each DRI driver's "createNewScreen"
389
    * function. */
390
   if (!XF86DRIGetClientDriverName(dpy, scrn,
391
                                   &ddx_version.major,
392
                                   &ddx_version.minor,
393
                                   &ddx_version.patch, &driverName)) {
394
      ErrorMessageF("XF86DRIGetClientDriverName failed\n");
395
      goto handle_error;
396
   }
397
 
398
   free(driverName);           /* No longer needed. */
399
 
400
   /*
401
    * Get device-specific info.  pDevPriv will point to a struct
402
    * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
403
    * has information about the screen size, depth, pitch, ancilliary
404
    * buffers, DRM mmap handles, etc.
405
    */
406
   if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk,
407
                             &framebuffer.size, &framebuffer.stride,
408
                             &framebuffer.dev_priv_size,
409
                             &framebuffer.dev_priv)) {
410
      ErrorMessageF("XF86DRIGetDeviceInfo failed");
411
      goto handle_error;
412
   }
413
 
414
   framebuffer.width = DisplayWidth(dpy, scrn);
415
   framebuffer.height = DisplayHeight(dpy, scrn);
416
 
417
   /* Map the framebuffer region. */
418
   status = drmMap(fd, hFB, framebuffer.size,
419
                   (drmAddressPtr) & framebuffer.base);
420
   if (status != 0) {
421
      ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status));
422
      goto handle_error;
423
   }
424
 
425
   /* Map the SAREA region.  Further mmap regions may be setup in
426
    * each DRI driver's "createNewScreen" function.
427
    */
428
   status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
429
   if (status != 0) {
430
      ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status));
431
      goto handle_error;
432
   }
433
 
434
   psp = (*psc->legacy->createNewScreen) (scrn,
435
                                          &ddx_version,
436
                                          &dri_version,
437
                                          &drm_version,
438
                                          &framebuffer,
439
                                          pSAREA,
440
                                          fd,
441
                                          loader_extensions,
442
                                          &driver_configs, psc);
443
 
444
   if (psp == NULL) {
445
      ErrorMessageF("Calling driver entry point failed");
446
      goto handle_error;
447
   }
448
 
449
   configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
450
   visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
451
 
452
   if (!configs || !visuals)
453
       goto handle_error;
454
 
455
   glx_config_destroy_list(psc->base.configs);
456
   psc->base.configs = configs;
457
   glx_config_destroy_list(psc->base.visuals);
458
   psc->base.visuals = visuals;
459
 
460
   psc->driver_configs = driver_configs;
461
 
462
   /* Visuals with depth != screen depth are subject to automatic compositing
463
    * in the X server, so DRI1 can't render to them properly. Mark them as
464
    * non-conformant to prevent apps from picking them up accidentally.
465
    */
466
   for (visual = psc->base.visuals; visual; visual = visual->next) {
467
      XVisualInfo template;
468
      XVisualInfo *visuals;
469
      int num_visuals;
470
      long mask;
471
 
472
      template.visualid = visual->visualID;
473
      mask = VisualIDMask;
474
      visuals = XGetVisualInfo(dpy, mask, &template, &num_visuals);
475
 
476
      if (visuals) {
477
         if (num_visuals > 0 && visuals->depth != DefaultDepth(dpy, scrn))
478
            visual->visualRating = GLX_NON_CONFORMANT_CONFIG;
479
 
480
         free(visuals);
481
      }
482
   }
483
 
484
   return psp;
485
 
486
 handle_error:
487
   if (configs)
488
       glx_config_destroy_list(configs);
489
   if (visuals)
490
       glx_config_destroy_list(visuals);
491
 
492
   if (pSAREA != MAP_FAILED)
493
      drmUnmap(pSAREA, SAREA_MAX);
494
 
495
   if (framebuffer.base != MAP_FAILED)
496
      drmUnmap((drmAddress) framebuffer.base, framebuffer.size);
497
 
498
   free(framebuffer.dev_priv);
499
 
500
   if (fd >= 0)
501
      drmCloseOnce(fd);
502
 
503
   XF86DRICloseConnection(dpy, scrn);
504
 
505
   ErrorMessageF("reverting to software direct rendering\n");
506
 
507
   return NULL;
508
}
509
 
510
static void
511
dri_destroy_context(struct glx_context * context)
512
{
513
   struct dri_context *pcp = (struct dri_context *) context;
514
   struct dri_screen *psc = (struct dri_screen *) context->psc;
515
 
516
   driReleaseDrawables(&pcp->base);
517
 
518
   free((char *) context->extensions);
519
 
520
   (*psc->core->destroyContext) (pcp->driContext);
521
 
522
   XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
523
   free(pcp);
524
}
525
 
526
static int
527
dri_bind_context(struct glx_context *context, struct glx_context *old,
528
		 GLXDrawable draw, GLXDrawable read)
529
{
530
   struct dri_context *pcp = (struct dri_context *) context;
531
   struct dri_screen *psc = (struct dri_screen *) pcp->base.psc;
532
   struct dri_drawable *pdraw, *pread;
533
 
534
   pdraw = (struct dri_drawable *) driFetchDrawable(context, draw);
535
   pread = (struct dri_drawable *) driFetchDrawable(context, read);
536
 
537
   driReleaseDrawables(&pcp->base);
538
 
539
   if (pdraw == NULL || pread == NULL)
540
      return GLXBadDrawable;
541
 
542
   if ((*psc->core->bindContext) (pcp->driContext,
543
				  pdraw->driDrawable, pread->driDrawable))
544
      return Success;
545
 
546
   return GLXBadContext;
547
}
548
 
549
static void
550
dri_unbind_context(struct glx_context *context, struct glx_context *new)
551
{
552
   struct dri_context *pcp = (struct dri_context *) context;
553
   struct dri_screen *psc = (struct dri_screen *) pcp->base.psc;
554
 
555
   (*psc->core->unbindContext) (pcp->driContext);
556
}
557
 
558
static const struct glx_context_vtable dri_context_vtable = {
559
   dri_destroy_context,
560
   dri_bind_context,
561
   dri_unbind_context,
562
   NULL,
563
   NULL,
564
   DRI_glXUseXFont,
565
   NULL,
566
   NULL,
567
   NULL, /* get_proc_address */
568
};
569
 
570
static struct glx_context *
571
dri_create_context(struct glx_screen *base,
572
		   struct glx_config *config_base,
573
		   struct glx_context *shareList, int renderType)
574
{
575
   struct dri_context *pcp, *pcp_shared;
576
   struct dri_screen *psc = (struct dri_screen *) base;
577
   drm_context_t hwContext;
578
   __DRIcontext *shared = NULL;
579
   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
580
 
581
   if (!psc->base.driScreen)
582
      return NULL;
583
 
584
   /* Check the renderType value */
585
   if (!validate_renderType_against_config(config_base, renderType))
586
       return NULL;
587
 
588
   if (shareList) {
589
      /* If the shareList context is not a DRI context, we cannot possibly
590
       * create a DRI context that shares it.
591
       */
592
      if (shareList->vtable->destroy != dri_destroy_context) {
593
	 return NULL;
594
      }
595
 
596
      pcp_shared = (struct dri_context *) shareList;
597
      shared = pcp_shared->driContext;
598
   }
599
 
600
   pcp = calloc(1, sizeof *pcp);
601
   if (pcp == NULL)
602
      return NULL;
603
 
604
   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
605
      free(pcp);
606
      return NULL;
607
   }
608
 
609
   pcp->base.renderType = renderType;
610
 
611
   if (!XF86DRICreateContextWithConfig(psc->base.dpy, psc->base.scr,
612
                                       config->base.visualID,
613
                                       &pcp->hwContextID, &hwContext)) {
614
      free(pcp);
615
      return NULL;
616
   }
617
 
618
   pcp->driContext =
619
      (*psc->legacy->createNewContext) (psc->driScreen,
620
                                        config->driConfig,
621
                                        renderType, shared, hwContext, pcp);
622
   if (pcp->driContext == NULL) {
623
      XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
624
      free(pcp);
625
      return NULL;
626
   }
627
 
628
   pcp->base.vtable = &dri_context_vtable;
629
 
630
   return &pcp->base;
631
}
632
 
633
static void
634
driDestroyDrawable(__GLXDRIdrawable * pdraw)
635
{
636
   struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
637
   struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
638
 
639
   (*psc->core->destroyDrawable) (pdp->driDrawable);
640
   XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, pdraw->drawable);
641
   free(pdraw);
642
}
643
 
644
static __GLXDRIdrawable *
645
driCreateDrawable(struct glx_screen *base,
646
                  XID xDrawable,
647
                  GLXDrawable drawable, struct glx_config *config_base)
648
{
649
   drm_drawable_t hwDrawable;
650
   void *empty_attribute_list = NULL;
651
   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
652
   struct dri_screen *psc = (struct dri_screen *) base;
653
   struct dri_drawable *pdp;
654
 
655
   /* Old dri can't handle GLX 1.3+ drawable constructors. */
656
   if (xDrawable != drawable)
657
      return NULL;
658
 
659
   pdp = calloc(1, sizeof *pdp);
660
   if (!pdp)
661
      return NULL;
662
 
663
   pdp->base.drawable = drawable;
664
   pdp->base.psc = &psc->base;
665
 
666
   if (!XF86DRICreateDrawable(psc->base.dpy, psc->base.scr,
667
			      drawable, &hwDrawable)) {
668
      free(pdp);
669
      return NULL;
670
   }
671
 
672
   /* Create a new drawable */
673
   pdp->driDrawable =
674
      (*psc->legacy->createNewDrawable) (psc->driScreen,
675
                                         config->driConfig,
676
                                         hwDrawable,
677
                                         GLX_WINDOW_BIT,
678
                                         empty_attribute_list, pdp);
679
 
680
   if (!pdp->driDrawable) {
681
      XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, drawable);
682
      free(pdp);
683
      return NULL;
684
   }
685
 
686
   pdp->base.destroyDrawable = driDestroyDrawable;
687
 
688
   return &pdp->base;
689
}
690
 
691
static int64_t
692
driSwapBuffers(__GLXDRIdrawable * pdraw, int64_t unused1, int64_t unused2,
693
	       int64_t unused3, Bool flush)
694
{
695
   struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
696
   struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
697
 
698
   if (flush) {
699
      glFlush();
700
   }
701
 
702
   (*psc->core->swapBuffers) (pdp->driDrawable);
703
   return 0;
704
}
705
 
706
static void
707
driCopySubBuffer(__GLXDRIdrawable * pdraw,
708
                 int x, int y, int width, int height, Bool flush)
709
{
710
   struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
711
   struct dri_screen *psc = (struct dri_screen *) pdp->base.psc;
712
 
713
   if (flush) {
714
      glFlush();
715
   }
716
 
717
   (*psc->driCopySubBuffer->copySubBuffer) (pdp->driDrawable,
718
					    x, y, width, height);
719
}
720
 
721
static void
722
driDestroyScreen(struct glx_screen *base)
723
{
724
   struct dri_screen *psc = (struct dri_screen *) base;
725
 
726
   /* Free the direct rendering per screen data */
727
   if (psc->driScreen)
728
      (*psc->core->destroyScreen) (psc->driScreen);
729
   driDestroyConfigs(psc->driver_configs);
730
   psc->driScreen = NULL;
731
   if (psc->driver)
732
      dlclose(psc->driver);
733
}
734
 
735
static int
736
driSetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
737
{
738
   struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
739
   struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
740
 
741
   if (psc->swapControl != NULL && pdraw != NULL) {
742
      psc->swapControl->setSwapInterval(pdp->driDrawable, interval);
743
      return 0;
744
   }
745
 
746
   return GLX_BAD_CONTEXT;
747
}
748
 
749
static int
750
driGetSwapInterval(__GLXDRIdrawable *pdraw)
751
{
752
   struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
753
   struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
754
 
755
   if (psc->swapControl != NULL && pdraw != NULL)
756
      return psc->swapControl->getSwapInterval(pdp->driDrawable);
757
 
758
   return 0;
759
}
760
 
761
/* Bind DRI1 specific extensions */
762
static void
763
driBindExtensions(struct dri_screen *psc, const __DRIextension **extensions)
764
{
765
   int i;
766
 
767
   for (i = 0; extensions[i]; i++) {
768
      /* No DRI2 support for swap_control at the moment, since SwapBuffers
769
       * is done by the X server */
770
      if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) {
771
	 psc->swapControl = (__DRIswapControlExtension *) extensions[i];
772
	 __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
773
	 __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
774
      }
775
 
776
      if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) {
777
         psc->msc = (__DRImediaStreamCounterExtension *) extensions[i];
778
         __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
779
      }
780
 
781
      if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
782
	 psc->driCopySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
783
	 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
784
      }
785
 
786
      if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
787
	 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
788
      }
789
      /* Ignore unknown extensions */
790
   }
791
}
792
 
793
static const struct glx_screen_vtable dri_screen_vtable = {
794
   dri_create_context,
795
   NULL
796
};
797
 
798
static struct glx_screen *
799
driCreateScreen(int screen, struct glx_display *priv)
800
{
801
   struct dri_display *pdp;
802
   __GLXDRIscreen *psp;
803
   const __DRIextension **extensions;
804
   struct dri_screen *psc;
805
   char *driverName;
806
   int i;
807
 
808
   psc = calloc(1, sizeof *psc);
809
   if (psc == NULL)
810
      return NULL;
811
 
812
   if (!glx_screen_init(&psc->base, screen, priv)) {
813
      free(psc);
814
      return NULL;
815
   }
816
 
817
   if (!driGetDriverName(priv->dpy, screen, &driverName)) {
818
      goto cleanup;
819
   }
820
 
821
   psc->driver = driOpenDriver(driverName);
822
   if (psc->driver == NULL)
823
      goto cleanup;
824
 
825
   extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
826
   if (extensions == NULL) {
827
      ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
828
      goto cleanup;
829
   }
830
 
831
   for (i = 0; extensions[i]; i++) {
832
      if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
833
	 psc->core = (__DRIcoreExtension *) extensions[i];
834
      if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0)
835
	 psc->legacy = (__DRIlegacyExtension *) extensions[i];
836
   }
837
 
838
   if (psc->core == NULL || psc->legacy == NULL)
839
      goto cleanup;
840
 
841
   pdp = (struct dri_display *) priv->driDisplay;
842
   psc->driScreen =
843
      CallCreateNewScreen(psc->base.dpy, screen, psc, pdp);
844
   if (psc->driScreen == NULL)
845
      goto cleanup;
846
 
847
   extensions = psc->core->getExtensions(psc->driScreen);
848
   driBindExtensions(psc, extensions);
849
 
850
   psc->base.vtable = &dri_screen_vtable;
851
   psp = &psc->vtable;
852
   psc->base.driScreen = psp;
853
   if (psc->driCopySubBuffer)
854
      psp->copySubBuffer = driCopySubBuffer;
855
 
856
   psp->destroyScreen = driDestroyScreen;
857
   psp->createDrawable = driCreateDrawable;
858
   psp->swapBuffers = driSwapBuffers;
859
 
860
   psp->setSwapInterval = driSetSwapInterval;
861
   psp->getSwapInterval = driGetSwapInterval;
862
 
863
   free(driverName);
864
 
865
   return &psc->base;
866
 
867
cleanup:
868
   CriticalErrorMessageF("failed to load driver: %s\n", driverName);
869
 
870
   free(driverName);
871
 
872
   if (psc->driver)
873
      dlclose(psc->driver);
874
   glx_screen_cleanup(&psc->base);
875
   free(psc);
876
 
877
   return NULL;
878
}
879
 
880
/* Called from __glXFreeDisplayPrivate.
881
 */
882
static void
883
driDestroyDisplay(__GLXDRIdisplay * dpy)
884
{
885
   free(dpy);
886
}
887
 
888
/*
889
 * Allocate, initialize and return a __DRIdisplayPrivate object.
890
 * This is called from __glXInitialize() when we are given a new
891
 * display pointer.
892
 */
893
_X_HIDDEN __GLXDRIdisplay *
894
driCreateDisplay(Display * dpy)
895
{
896
   struct dri_display *pdpyp;
897
   int eventBase, errorBase;
898
   int major, minor, patch;
899
 
900
   if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
901
      return NULL;
902
   }
903
 
904
   if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
905
      return NULL;
906
   }
907
 
908
   pdpyp = malloc(sizeof *pdpyp);
909
   if (!pdpyp) {
910
      return NULL;
911
   }
912
 
913
   pdpyp->driMajor = major;
914
   pdpyp->driMinor = minor;
915
   pdpyp->driPatch = patch;
916
 
917
   pdpyp->base.destroyDisplay = driDestroyDisplay;
918
   pdpyp->base.createScreen = driCreateScreen;
919
 
920
   return &pdpyp->base;
921
}
922
 
923
#endif /* GLX_DIRECT_RENDERING */