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