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