Remove useless memset after calloc
[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 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 if (shareList) {
585 /* If the shareList context is not a DRI context, we cannot possibly
586 * create a DRI context that shares it.
587 */
588 if (shareList->vtable->destroy != dri_destroy_context) {
589 return NULL;
590 }
591
592 pcp_shared = (struct dri_context *) shareList;
593 shared = pcp_shared->driContext;
594 }
595
596 pcp = calloc(1, sizeof *pcp);
597 if (pcp == NULL)
598 return NULL;
599
600 if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
601 free(pcp);
602 return NULL;
603 }
604
605 if (!XF86DRICreateContextWithConfig(psc->base.dpy, psc->base.scr,
606 config->base.visualID,
607 &pcp->hwContextID, &hwContext)) {
608 free(pcp);
609 return NULL;
610 }
611
612 pcp->driContext =
613 (*psc->legacy->createNewContext) (psc->driScreen,
614 config->driConfig,
615 renderType, shared, hwContext, pcp);
616 if (pcp->driContext == NULL) {
617 XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
618 free(pcp);
619 return NULL;
620 }
621
622 pcp->base.vtable = &dri_context_vtable;
623
624 return &pcp->base;
625 }
626
627 static void
628 driDestroyDrawable(__GLXDRIdrawable * pdraw)
629 {
630 struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
631 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
632
633 (*psc->core->destroyDrawable) (pdp->driDrawable);
634 XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, pdraw->drawable);
635 free(pdraw);
636 }
637
638 static __GLXDRIdrawable *
639 driCreateDrawable(struct glx_screen *base,
640 XID xDrawable,
641 GLXDrawable drawable, struct glx_config *config_base)
642 {
643 drm_drawable_t hwDrawable;
644 void *empty_attribute_list = NULL;
645 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
646 struct dri_screen *psc = (struct dri_screen *) base;
647 struct dri_drawable *pdp;
648
649 /* Old dri can't handle GLX 1.3+ drawable constructors. */
650 if (xDrawable != drawable)
651 return NULL;
652
653 pdp = calloc(1, sizeof *pdp);
654 if (!pdp)
655 return NULL;
656
657 pdp->base.drawable = drawable;
658 pdp->base.psc = &psc->base;
659
660 if (!XF86DRICreateDrawable(psc->base.dpy, psc->base.scr,
661 drawable, &hwDrawable)) {
662 free(pdp);
663 return NULL;
664 }
665
666 /* Create a new drawable */
667 pdp->driDrawable =
668 (*psc->legacy->createNewDrawable) (psc->driScreen,
669 config->driConfig,
670 hwDrawable,
671 GLX_WINDOW_BIT,
672 empty_attribute_list, pdp);
673
674 if (!pdp->driDrawable) {
675 XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, drawable);
676 free(pdp);
677 return NULL;
678 }
679
680 pdp->base.destroyDrawable = driDestroyDrawable;
681
682 return &pdp->base;
683 }
684
685 static int64_t
686 driSwapBuffers(__GLXDRIdrawable * pdraw, int64_t unused1, int64_t unused2,
687 int64_t unused3)
688 {
689 struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
690 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
691
692 (*psc->core->swapBuffers) (pdp->driDrawable);
693 return 0;
694 }
695
696 static void
697 driCopySubBuffer(__GLXDRIdrawable * pdraw,
698 int x, int y, int width, int height)
699 {
700 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
701 struct dri_screen *psc = (struct dri_screen *) pdp->base.psc;
702
703 (*psc->driCopySubBuffer->copySubBuffer) (pdp->driDrawable,
704 x, y, width, height);
705 }
706
707 static void
708 driDestroyScreen(struct glx_screen *base)
709 {
710 struct dri_screen *psc = (struct dri_screen *) base;
711
712 /* Free the direct rendering per screen data */
713 if (psc->driScreen)
714 (*psc->core->destroyScreen) (psc->driScreen);
715 driDestroyConfigs(psc->driver_configs);
716 psc->driScreen = NULL;
717 if (psc->driver)
718 dlclose(psc->driver);
719 }
720
721 #ifdef __DRI_SWAP_BUFFER_COUNTER
722
723 static int
724 driDrawableGetMSC(struct glx_screen *base, __GLXDRIdrawable *pdraw,
725 int64_t *ust, int64_t *msc, int64_t *sbc)
726 {
727 struct dri_screen *psc = (struct dri_screen *) base;
728 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
729
730 if (pdp && psc->sbc && psc->msc)
731 return ( (*psc->msc->getMSC)(psc->driScreen, msc) == 0 &&
732 (*psc->sbc->getSBC)(pdp->driDrawable, sbc) == 0 &&
733 __glXGetUST(ust) == 0 );
734 }
735
736 static int
737 driWaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
738 int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
739 {
740 struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
741 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
742
743 if (pdp != NULL && psc->msc != NULL) {
744 ret = (*psc->msc->waitForMSC) (pdp->driDrawable, target_msc,
745 divisor, remainder, msc, sbc);
746
747 /* __glXGetUST returns zero on success and non-zero on failure.
748 * This function returns True on success and False on failure.
749 */
750 return ret == 0 && __glXGetUST(ust) == 0;
751 }
752 }
753
754 static int
755 driWaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
756 int64_t *msc, int64_t *sbc)
757 {
758 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
759
760 if (pdp != NULL && psc->sbc != NULL) {
761 ret =
762 (*psc->sbc->waitForSBC) (pdp->driDrawable, target_sbc, msc, sbc);
763
764 /* __glXGetUST returns zero on success and non-zero on failure.
765 * This function returns True on success and False on failure.
766 */
767 return ((ret == 0) && (__glXGetUST(ust) == 0));
768 }
769
770 return DRI2WaitSBC(pdp->base.psc->dpy,
771 pdp->base.xDrawable, target_sbc, ust, msc, sbc);
772 }
773
774 #endif
775
776 static int
777 driSetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
778 {
779 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
780 struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
781
782 if (psc->swapControl != NULL && pdraw != NULL) {
783 psc->swapControl->setSwapInterval(pdp->driDrawable, interval);
784 return 0;
785 }
786
787 return GLX_BAD_CONTEXT;
788 }
789
790 static int
791 driGetSwapInterval(__GLXDRIdrawable *pdraw)
792 {
793 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
794 struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
795
796 if (psc->swapControl != NULL && pdraw != NULL)
797 return psc->swapControl->getSwapInterval(pdp->driDrawable);
798
799 return 0;
800 }
801
802 /* Bind DRI1 specific extensions */
803 static void
804 driBindExtensions(struct dri_screen *psc, const __DRIextension **extensions)
805 {
806 int i;
807
808 for (i = 0; extensions[i]; i++) {
809 /* No DRI2 support for swap_control at the moment, since SwapBuffers
810 * is done by the X server */
811 if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) {
812 psc->swapControl = (__DRIswapControlExtension *) extensions[i];
813 __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
814 __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
815 }
816
817 if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) {
818 psc->msc = (__DRImediaStreamCounterExtension *) extensions[i];
819 __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
820 }
821
822 if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
823 psc->driCopySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
824 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
825 }
826
827 if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
828 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
829 }
830 /* Ignore unknown extensions */
831 }
832 }
833
834 static const struct glx_screen_vtable dri_screen_vtable = {
835 dri_create_context,
836 NULL
837 };
838
839 static struct glx_screen *
840 driCreateScreen(int screen, struct glx_display *priv)
841 {
842 struct dri_display *pdp;
843 __GLXDRIscreen *psp;
844 const __DRIextension **extensions;
845 struct dri_screen *psc;
846 char *driverName;
847 int i;
848
849 psc = calloc(1, sizeof *psc);
850 if (psc == NULL)
851 return NULL;
852
853 if (!glx_screen_init(&psc->base, screen, priv)) {
854 free(psc);
855 return NULL;
856 }
857
858 if (!driGetDriverName(priv->dpy, screen, &driverName)) {
859 goto cleanup;
860 }
861
862 psc->driver = driOpenDriver(driverName);
863 free(driverName);
864 if (psc->driver == NULL)
865 goto cleanup;
866
867 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
868 if (extensions == NULL) {
869 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
870 goto cleanup;
871 }
872
873 for (i = 0; extensions[i]; i++) {
874 if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
875 psc->core = (__DRIcoreExtension *) extensions[i];
876 if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0)
877 psc->legacy = (__DRIlegacyExtension *) extensions[i];
878 }
879
880 if (psc->core == NULL || psc->legacy == NULL)
881 goto cleanup;
882
883 pdp = (struct dri_display *) priv->driDisplay;
884 psc->driScreen =
885 CallCreateNewScreen(psc->base.dpy, screen, psc, pdp);
886 if (psc->driScreen == NULL)
887 goto cleanup;
888
889 extensions = psc->core->getExtensions(psc->driScreen);
890 driBindExtensions(psc, extensions);
891
892 psc->base.vtable = &dri_screen_vtable;
893 psp = &psc->vtable;
894 psc->base.driScreen = psp;
895 if (psc->driCopySubBuffer)
896 psp->copySubBuffer = driCopySubBuffer;
897
898 psp->destroyScreen = driDestroyScreen;
899 psp->createDrawable = driCreateDrawable;
900 psp->swapBuffers = driSwapBuffers;
901
902 #ifdef __DRI_SWAP_BUFFER_COUNTER
903 psp->getDrawableMSC = driDrawableGetMSC;
904 psp->waitForMSC = driWaitForMSC;
905 psp->waitForSBC = driWaitForSBC;
906 #endif
907
908 psp->setSwapInterval = driSetSwapInterval;
909 psp->getSwapInterval = driGetSwapInterval;
910
911 return &psc->base;
912
913 cleanup:
914 CriticalErrorMessageF("failed to load driver: %s\n", driverName);
915
916 if (psc->driver)
917 dlclose(psc->driver);
918 glx_screen_cleanup(&psc->base);
919 free(psc);
920
921 return NULL;
922 }
923
924 /* Called from __glXFreeDisplayPrivate.
925 */
926 static void
927 driDestroyDisplay(__GLXDRIdisplay * dpy)
928 {
929 free(dpy);
930 }
931
932 /*
933 * Allocate, initialize and return a __DRIdisplayPrivate object.
934 * This is called from __glXInitialize() when we are given a new
935 * display pointer.
936 */
937 _X_HIDDEN __GLXDRIdisplay *
938 driCreateDisplay(Display * dpy)
939 {
940 struct dri_display *pdpyp;
941 int eventBase, errorBase;
942 int major, minor, patch;
943
944 if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
945 return NULL;
946 }
947
948 if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
949 return NULL;
950 }
951
952 pdpyp = malloc(sizeof *pdpyp);
953 if (!pdpyp) {
954 return NULL;
955 }
956
957 pdpyp->driMajor = major;
958 pdpyp->driMinor = minor;
959 pdpyp->driPatch = patch;
960
961 pdpyp->base.destroyDisplay = driDestroyDisplay;
962 pdpyp->base.createScreen = driCreateScreen;
963
964 return &pdpyp->base;
965 }
966
967 #endif /* GLX_DIRECT_RENDERING */