DRI2/GLX: check for vblank_mode in DRI2 GLX code
[mesa.git] / src / glx / dri2_glx.c
1 /*
2 * Copyright © 2008 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Soft-
6 * ware"), to deal in the Software without restriction, including without
7 * limitation the rights to use, copy, modify, merge, publish, distribute,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, provided that the above copyright
10 * notice(s) and this permission notice appear in all copies of the Soft-
11 * ware and that both the above copyright notice(s) and this permission
12 * notice appear in supporting documentation.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
17 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
18 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
19 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
22 * MANCE OF THIS SOFTWARE.
23 *
24 * Except as contained in this notice, the name of a copyright holder shall
25 * not be used in advertising or otherwise to promote the sale, use or
26 * other dealings in this Software without prior written authorization of
27 * the copyright holder.
28 *
29 * Authors:
30 * Kristian Høgsberg (krh@redhat.com)
31 */
32
33 #ifdef GLX_DIRECT_RENDERING
34
35 #include <X11/Xlib.h>
36 #include <X11/extensions/Xfixes.h>
37 #include <X11/extensions/Xdamage.h>
38 #include "glapi.h"
39 #include "glxclient.h"
40 #include <X11/extensions/dri2proto.h>
41 #include "xf86dri.h"
42 #include <dlfcn.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45 #include <sys/types.h>
46 #include <sys/mman.h>
47 #include "xf86drm.h"
48 #include "dri2.h"
49 #include "dri_common.h"
50
51 /* From xmlpool/options.h, user exposed so should be stable */
52 #define DRI_CONF_VBLANK_NEVER 0
53 #define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
54 #define DRI_CONF_VBLANK_DEF_INTERVAL_1 2
55 #define DRI_CONF_VBLANK_ALWAYS_SYNC 3
56
57 #undef DRI2_MINOR
58 #define DRI2_MINOR 1
59
60 typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
61 typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
62 typedef struct __GLXDRIdrawablePrivateRec __GLXDRIdrawablePrivate;
63
64 struct __GLXDRIdisplayPrivateRec
65 {
66 __GLXDRIdisplay base;
67
68 /*
69 ** XFree86-DRI version information
70 */
71 int driMajor;
72 int driMinor;
73 int driPatch;
74 int swapAvailable;
75 int invalidateAvailable;
76 };
77
78 struct __GLXDRIcontextPrivateRec
79 {
80 __GLXDRIcontext base;
81 __DRIcontext *driContext;
82 __GLXscreenConfigs *psc;
83 };
84
85 struct __GLXDRIdrawablePrivateRec
86 {
87 __GLXDRIdrawable base;
88 __DRIbuffer buffers[5];
89 int bufferCount;
90 int width, height;
91 int have_back;
92 int have_fake_front;
93 int swap_interval;
94 };
95
96 static void dri2WaitX(__GLXDRIdrawable * pdraw);
97
98 static void
99 dri2DestroyContext(__GLXDRIcontext * context,
100 __GLXscreenConfigs * psc, Display * dpy)
101 {
102 __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
103 const __DRIcoreExtension *core = pcp->psc->core;
104
105 (*core->destroyContext) (pcp->driContext);
106
107 Xfree(pcp);
108 }
109
110 static Bool
111 dri2BindContext(__GLXDRIcontext * context,
112 __GLXDRIdrawable * draw, __GLXDRIdrawable * read)
113 {
114 __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
115 const __DRIcoreExtension *core = pcp->psc->core;
116
117 return (*core->bindContext) (pcp->driContext,
118 draw->driDrawable, read->driDrawable);
119 }
120
121 static void
122 dri2UnbindContext(__GLXDRIcontext * context)
123 {
124 __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
125 const __DRIcoreExtension *core = pcp->psc->core;
126
127 (*core->unbindContext) (pcp->driContext);
128 }
129
130 static __GLXDRIcontext *
131 dri2CreateContext(__GLXscreenConfigs * psc,
132 const __GLcontextModes * mode,
133 GLXContext gc, GLXContext shareList, int renderType)
134 {
135 __GLXDRIcontextPrivate *pcp, *pcp_shared;
136 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
137 __DRIcontext *shared = NULL;
138
139 if (shareList) {
140 pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
141 shared = pcp_shared->driContext;
142 }
143
144 pcp = Xmalloc(sizeof *pcp);
145 if (pcp == NULL)
146 return NULL;
147
148 pcp->psc = psc;
149 pcp->driContext =
150 (*psc->dri2->createNewContext) (psc->__driScreen,
151 config->driConfig, shared, pcp);
152 gc->__driContext = pcp->driContext;
153
154 if (pcp->driContext == NULL) {
155 Xfree(pcp);
156 return NULL;
157 }
158
159 pcp->base.destroyContext = dri2DestroyContext;
160 pcp->base.bindContext = dri2BindContext;
161 pcp->base.unbindContext = dri2UnbindContext;
162
163 return &pcp->base;
164 }
165
166 static void
167 dri2DestroyDrawable(__GLXDRIdrawable * pdraw)
168 {
169 const __DRIcoreExtension *core = pdraw->psc->core;
170
171 (*core->destroyDrawable) (pdraw->driDrawable);
172 DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->xDrawable);
173 Xfree(pdraw);
174 }
175
176 static __GLXDRIdrawable *
177 dri2CreateDrawable(__GLXscreenConfigs * psc,
178 XID xDrawable,
179 GLXDrawable drawable, const __GLcontextModes * modes)
180 {
181 __GLXDRIdrawablePrivate *pdraw;
182 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
183 __GLXdisplayPrivate *dpyPriv;
184 __GLXDRIdisplayPrivate *pdp;
185 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
186
187 pdraw = Xmalloc(sizeof(*pdraw));
188 if (!pdraw)
189 return NULL;
190
191 pdraw->base.destroyDrawable = dri2DestroyDrawable;
192 pdraw->base.xDrawable = xDrawable;
193 pdraw->base.drawable = drawable;
194 pdraw->base.psc = psc;
195 pdraw->bufferCount = 0;
196 pdraw->swap_interval = 1; /* default may be overridden below */
197
198 if (psc->config)
199 psc->config->configQueryi(psc->__driScreen, "vblank_mode", &vblank_mode);
200
201 switch (vblank_mode) {
202 case DRI_CONF_VBLANK_NEVER:
203 case DRI_CONF_VBLANK_DEF_INTERVAL_0:
204 pdraw->swap_interval = 0;
205 break;
206 case DRI_CONF_VBLANK_DEF_INTERVAL_1:
207 case DRI_CONF_VBLANK_ALWAYS_SYNC:
208 default:
209 pdraw->swap_interval = 1;
210 break;
211 }
212
213 DRI2CreateDrawable(psc->dpy, xDrawable);
214
215 dpyPriv = __glXInitialize(psc->dpy);
216 pdp = (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display;;
217 /* Create a new drawable */
218 pdraw->base.driDrawable =
219 (*psc->dri2->createNewDrawable) (psc->__driScreen,
220 config->driConfig, pdraw);
221
222 if (!pdraw->base.driDrawable) {
223 DRI2DestroyDrawable(psc->dpy, xDrawable);
224 Xfree(pdraw);
225 return NULL;
226 }
227
228 /*
229 * Make sure server has the same swap interval we do for the new
230 * drawable.
231 */
232 if (pdp->swapAvailable)
233 DRI2SwapInterval(psc->dpy, xDrawable, pdraw->swap_interval);
234
235 return &pdraw->base;
236 }
237
238 #ifdef X_DRI2GetMSC
239
240 static int
241 dri2DrawableGetMSC(__GLXscreenConfigs *psc, __GLXDRIdrawable *pdraw,
242 int64_t *ust, int64_t *msc, int64_t *sbc)
243 {
244 return DRI2GetMSC(psc->dpy, pdraw->xDrawable, ust, msc, sbc);
245 }
246
247 #endif
248
249
250 #ifdef X_DRI2WaitMSC
251
252 static int
253 dri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
254 int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
255 {
256 return DRI2WaitMSC(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor,
257 remainder, ust, msc, sbc);
258 }
259
260 static int
261 dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
262 int64_t *msc, int64_t *sbc)
263 {
264 return DRI2WaitSBC(pdraw->psc->dpy, pdraw->xDrawable, target_sbc, ust, msc,
265 sbc);
266 }
267
268 #endif /* X_DRI2WaitMSC */
269
270 static void
271 dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height)
272 {
273 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
274 XRectangle xrect;
275 XserverRegion region;
276
277 /* Check we have the right attachments */
278 if (!priv->have_back)
279 return;
280
281 xrect.x = x;
282 xrect.y = priv->height - y - height;
283 xrect.width = width;
284 xrect.height = height;
285
286 #ifdef __DRI2_FLUSH
287 if (pdraw->psc->f)
288 (*pdraw->psc->f->flush) (pdraw->driDrawable);
289 #endif
290
291 region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
292 /* should get a fence ID back from here at some point */
293 DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
294 DRI2BufferFrontLeft, DRI2BufferBackLeft);
295 XFixesDestroyRegion(pdraw->psc->dpy, region);
296
297 /* Refresh the fake front (if present) after we just damaged the real
298 * front.
299 */
300 dri2WaitX(pdraw);
301 }
302
303 static void
304 dri2WaitX(__GLXDRIdrawable *pdraw)
305 {
306 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
307 XRectangle xrect;
308 XserverRegion region;
309
310 /* Check we have the right attachments */
311 if (!priv->have_fake_front)
312 return;
313
314 xrect.x = 0;
315 xrect.y = 0;
316 xrect.width = priv->width;
317 xrect.height = priv->height;
318
319 #ifdef __DRI2_FLUSH
320 if (pdraw->psc->f)
321 (*pdraw->psc->f->flush) (pdraw->driDrawable);
322 #endif
323
324 region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
325 DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
326 DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
327 XFixesDestroyRegion(pdraw->psc->dpy, region);
328 }
329
330 static void
331 dri2WaitGL(__GLXDRIdrawable * pdraw)
332 {
333 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
334 XRectangle xrect;
335 XserverRegion region;
336
337 if (!priv->have_fake_front)
338 return;
339
340 xrect.x = 0;
341 xrect.y = 0;
342 xrect.width = priv->width;
343 xrect.height = priv->height;
344
345 #ifdef __DRI2_FLUSH
346 if (pdraw->psc->f)
347 (*pdraw->psc->f->flush) (pdraw->driDrawable);
348 #endif
349
350 region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
351 DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
352 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
353 XFixesDestroyRegion(pdraw->psc->dpy, region);
354 }
355
356 static void
357 dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
358 {
359 __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
360 __GLXdisplayPrivate *priv = __glXInitialize(pdraw->base.psc->dpy);
361 __GLXDRIdisplayPrivate *pdp = (__GLXDRIdisplayPrivate *)priv->dri2Display;
362
363 /* Old servers don't send invalidate events */
364 if (!pdp->invalidateAvailable)
365 dri2InvalidateBuffers(priv->dpy, pdraw->base.drawable);
366
367 dri2WaitGL(loaderPrivate);
368 }
369
370
371 static void
372 dri2DestroyScreen(__GLXscreenConfigs * psc)
373 {
374 /* Free the direct rendering per screen data */
375 (*psc->core->destroyScreen) (psc->__driScreen);
376 close(psc->fd);
377 psc->__driScreen = NULL;
378 }
379
380 /**
381 * Process list of buffer received from the server
382 *
383 * Processes the list of buffers received in a reply from the server to either
384 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
385 */
386 static void
387 process_buffers(__GLXDRIdrawablePrivate * pdraw, DRI2Buffer * buffers,
388 unsigned count)
389 {
390 int i;
391
392 pdraw->bufferCount = count;
393 pdraw->have_fake_front = 0;
394 pdraw->have_back = 0;
395
396 /* This assumes the DRI2 buffer attachment tokens matches the
397 * __DRIbuffer tokens. */
398 for (i = 0; i < count; i++) {
399 pdraw->buffers[i].attachment = buffers[i].attachment;
400 pdraw->buffers[i].name = buffers[i].name;
401 pdraw->buffers[i].pitch = buffers[i].pitch;
402 pdraw->buffers[i].cpp = buffers[i].cpp;
403 pdraw->buffers[i].flags = buffers[i].flags;
404 if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
405 pdraw->have_fake_front = 1;
406 if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT)
407 pdraw->have_back = 1;
408 }
409
410 }
411
412 static int64_t
413 dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
414 int64_t remainder)
415 {
416 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
417 __GLXdisplayPrivate *dpyPriv = __glXInitialize(priv->base.psc->dpy);
418 __GLXDRIdisplayPrivate *pdp =
419 (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display;
420 int64_t ret;
421
422 #ifdef __DRI2_FLUSH
423 if (pdraw->psc->f)
424 (*pdraw->psc->f->flush)(pdraw->driDrawable);
425 #endif
426
427 /* Old servers don't send invalidate events */
428 if (!pdp->invalidateAvailable)
429 dri2InvalidateBuffers(dpyPriv->dpy, pdraw->drawable);
430
431 /* Old servers can't handle swapbuffers */
432 if (!pdp->swapAvailable) {
433 dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
434 return 0;
435 }
436
437 #ifdef X_DRI2SwapBuffers
438 DRI2SwapBuffers(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor,
439 remainder, &ret);
440 #endif
441
442 return ret;
443 }
444
445 static __DRIbuffer *
446 dri2GetBuffers(__DRIdrawable * driDrawable,
447 int *width, int *height,
448 unsigned int *attachments, int count,
449 int *out_count, void *loaderPrivate)
450 {
451 __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
452 DRI2Buffer *buffers;
453
454 buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable,
455 width, height, attachments, count, out_count);
456 if (buffers == NULL)
457 return NULL;
458
459 pdraw->width = *width;
460 pdraw->height = *height;
461 process_buffers(pdraw, buffers, *out_count);
462
463 Xfree(buffers);
464
465 return pdraw->buffers;
466 }
467
468 static __DRIbuffer *
469 dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
470 int *width, int *height,
471 unsigned int *attachments, int count,
472 int *out_count, void *loaderPrivate)
473 {
474 __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
475 DRI2Buffer *buffers;
476
477 buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy,
478 pdraw->base.xDrawable,
479 width, height, attachments,
480 count, out_count);
481 if (buffers == NULL)
482 return NULL;
483
484 pdraw->width = *width;
485 pdraw->height = *height;
486 process_buffers(pdraw, buffers, *out_count);
487
488 Xfree(buffers);
489
490 return pdraw->buffers;
491 }
492
493 #ifdef X_DRI2SwapInterval
494
495 static void
496 dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
497 {
498 __GLXscreenConfigs *psc = pdraw->psc;
499 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
500 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
501
502 if (psc->config)
503 psc->config->configQueryi(psc->__driScreen, "vblank_mode", &vblank_mode);
504
505 switch (vblank_mode) {
506 case DRI_CONF_VBLANK_NEVER:
507 return;
508 case DRI_CONF_VBLANK_ALWAYS_SYNC:
509 if (interval <= 0)
510 return;
511 break;
512 default:
513 break;
514 }
515
516 DRI2SwapInterval(priv->base.psc->dpy, pdraw->xDrawable, interval);
517 priv->swap_interval = interval;
518 }
519
520 static unsigned int
521 dri2GetSwapInterval(__GLXDRIdrawable *pdraw)
522 {
523 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
524
525 return priv->swap_interval;
526 }
527
528 #endif /* X_DRI2SwapInterval */
529
530 static const __DRIdri2LoaderExtension dri2LoaderExtension = {
531 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION},
532 dri2GetBuffers,
533 dri2FlushFrontBuffer,
534 dri2GetBuffersWithFormat,
535 };
536
537 static const __DRIdri2LoaderExtension dri2LoaderExtension_old = {
538 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION},
539 dri2GetBuffers,
540 dri2FlushFrontBuffer,
541 NULL,
542 };
543
544 static const __DRIextension *loader_extensions[] = {
545 &dri2LoaderExtension.base,
546 &systemTimeExtension.base,
547 NULL
548 };
549
550 static const __DRIextension *loader_extensions_old[] = {
551 &dri2LoaderExtension_old.base,
552 &systemTimeExtension.base,
553 NULL
554 };
555
556 _X_HIDDEN void
557 dri2InvalidateBuffers(Display *dpy, XID drawable)
558 {
559 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
560
561 #if __DRI2_FLUSH_VERSION >= 3
562 if (pdraw && pdraw->psc->f)
563 pdraw->psc->f->invalidate(pdraw->driDrawable);
564 #endif
565 }
566
567 static __GLXDRIscreen *
568 dri2CreateScreen(__GLXscreenConfigs * psc, int screen,
569 __GLXdisplayPrivate * priv)
570 {
571 const __DRIconfig **driver_configs;
572 const __DRIextension **extensions;
573 const __GLXDRIdisplayPrivate *const pdp = (__GLXDRIdisplayPrivate *)
574 priv->dri2Display;
575 __GLXDRIscreen *psp;
576 char *driverName, *deviceName;
577 drm_magic_t magic;
578 int i;
579
580 psp = Xmalloc(sizeof *psp);
581 if (psp == NULL)
582 return NULL;
583
584 if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen),
585 &driverName, &deviceName)) {
586 XFree(psp);
587 return NULL;
588 }
589
590 psc->driver = driOpenDriver(driverName);
591 if (psc->driver == NULL) {
592 ErrorMessageF("driver pointer missing\n");
593 goto handle_error;
594 }
595
596 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
597 if (extensions == NULL) {
598 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
599 goto handle_error;
600 }
601
602 for (i = 0; extensions[i]; i++) {
603 if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
604 psc->core = (__DRIcoreExtension *) extensions[i];
605 if (strcmp(extensions[i]->name, __DRI_DRI2) == 0)
606 psc->dri2 = (__DRIdri2Extension *) extensions[i];
607 }
608
609 if (psc->core == NULL || psc->dri2 == NULL) {
610 ErrorMessageF("core dri or dri2 extension not found\n");
611 goto handle_error;
612 }
613
614 psc->fd = open(deviceName, O_RDWR);
615 if (psc->fd < 0) {
616 ErrorMessageF("failed to open drm device: %s\n", strerror(errno));
617 goto handle_error;
618 }
619
620 if (drmGetMagic(psc->fd, &magic)) {
621 ErrorMessageF("failed to get magic\n");
622 goto handle_error;
623 }
624
625 if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) {
626 ErrorMessageF("failed to authenticate magic %d\n", magic);
627 goto handle_error;
628 }
629
630 /* If the server does not support the protocol for
631 * DRI2GetBuffersWithFormat, don't supply that interface to the driver.
632 */
633 psc->__driScreen =
634 psc->dri2->createNewScreen(screen, psc->fd, ((pdp->driMinor < 1)
635 ? loader_extensions_old
636 : loader_extensions),
637 &driver_configs, psc);
638
639 if (psc->__driScreen == NULL) {
640 ErrorMessageF("failed to create dri screen\n");
641 goto handle_error;
642 }
643
644 driBindCommonExtensions(psc);
645 dri2BindExtensions(psc);
646
647 psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
648 psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
649
650 psc->driver_configs = driver_configs;
651
652 psp->destroyScreen = dri2DestroyScreen;
653 psp->createContext = dri2CreateContext;
654 psp->createDrawable = dri2CreateDrawable;
655 psp->swapBuffers = dri2SwapBuffers;
656 psp->waitGL = dri2WaitGL;
657 psp->waitX = dri2WaitX;
658 psp->getDrawableMSC = NULL;
659 psp->waitForMSC = NULL;
660 psp->waitForSBC = NULL;
661 psp->setSwapInterval = NULL;
662 psp->getSwapInterval = NULL;
663
664 if (pdp->driMinor >= 2) {
665 #ifdef X_DRI2GetMSC
666 psp->getDrawableMSC = dri2DrawableGetMSC;
667 #endif
668 #ifdef X_DRI2WaitMSC
669 psp->waitForMSC = dri2WaitForMSC;
670 psp->waitForSBC = dri2WaitForSBC;
671 #endif
672 #ifdef X_DRI2SwapInterval
673 psp->setSwapInterval = dri2SetSwapInterval;
674 psp->getSwapInterval = dri2GetSwapInterval;
675 #endif
676 #if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval)
677 __glXEnableDirectExtension(psc, "GLX_OML_sync_control");
678 #endif
679 }
680
681 /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always
682 * available.*/
683 psp->copySubBuffer = dri2CopySubBuffer;
684 __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer");
685
686 Xfree(driverName);
687 Xfree(deviceName);
688
689 return psp;
690
691 handle_error:
692 Xfree(driverName);
693 Xfree(deviceName);
694 XFree(psp);
695
696 /* FIXME: clean up here */
697
698 return NULL;
699 }
700
701 /* Called from __glXFreeDisplayPrivate.
702 */
703 static void
704 dri2DestroyDisplay(__GLXDRIdisplay * dpy)
705 {
706 Xfree(dpy);
707 }
708
709 /*
710 * Allocate, initialize and return a __DRIdisplayPrivate object.
711 * This is called from __glXInitialize() when we are given a new
712 * display pointer.
713 */
714 _X_HIDDEN __GLXDRIdisplay *
715 dri2CreateDisplay(Display * dpy)
716 {
717 __GLXDRIdisplayPrivate *pdp;
718 int eventBase, errorBase;
719
720 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase))
721 return NULL;
722
723 pdp = Xmalloc(sizeof *pdp);
724 if (pdp == NULL)
725 return NULL;
726
727 if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) {
728 Xfree(pdp);
729 return NULL;
730 }
731
732 pdp->driPatch = 0;
733 pdp->swapAvailable = (pdp->driMinor >= 2);
734 pdp->invalidateAvailable = (pdp->driMinor >= 3);
735
736 pdp->base.destroyDisplay = dri2DestroyDisplay;
737 pdp->base.createScreen = dri2CreateScreen;
738
739 return &pdp->base;
740 }
741
742 #endif /* GLX_DIRECT_RENDERING */