Merge branch '7.8'
[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 #ifdef X_DRI2SwapInterval
229 /*
230 * Make sure server has the same swap interval we do for the new
231 * drawable.
232 */
233 if (pdp->swapAvailable)
234 DRI2SwapInterval(psc->dpy, xDrawable, pdraw->swap_interval);
235 #endif
236
237 return &pdraw->base;
238 }
239
240 #ifdef X_DRI2GetMSC
241
242 static int
243 dri2DrawableGetMSC(__GLXscreenConfigs *psc, __GLXDRIdrawable *pdraw,
244 int64_t *ust, int64_t *msc, int64_t *sbc)
245 {
246 return DRI2GetMSC(psc->dpy, pdraw->xDrawable, ust, msc, sbc);
247 }
248
249 #endif
250
251
252 #ifdef X_DRI2WaitMSC
253
254 static int
255 dri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
256 int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
257 {
258 return DRI2WaitMSC(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor,
259 remainder, ust, msc, sbc);
260 }
261
262 static int
263 dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
264 int64_t *msc, int64_t *sbc)
265 {
266 return DRI2WaitSBC(pdraw->psc->dpy, pdraw->xDrawable, target_sbc, ust, msc,
267 sbc);
268 }
269
270 #endif /* X_DRI2WaitMSC */
271
272 static void
273 dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height)
274 {
275 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
276 XRectangle xrect;
277 XserverRegion region;
278
279 /* Check we have the right attachments */
280 if (!priv->have_back)
281 return;
282
283 xrect.x = x;
284 xrect.y = priv->height - y - height;
285 xrect.width = width;
286 xrect.height = height;
287
288 #ifdef __DRI2_FLUSH
289 if (pdraw->psc->f)
290 (*pdraw->psc->f->flush) (pdraw->driDrawable);
291 #endif
292
293 region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
294 /* should get a fence ID back from here at some point */
295 DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
296 DRI2BufferFrontLeft, DRI2BufferBackLeft);
297 XFixesDestroyRegion(pdraw->psc->dpy, region);
298
299 /* Refresh the fake front (if present) after we just damaged the real
300 * front.
301 */
302 dri2WaitX(pdraw);
303 }
304
305 static void
306 dri2WaitX(__GLXDRIdrawable *pdraw)
307 {
308 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
309 XRectangle xrect;
310 XserverRegion region;
311
312 /* Check we have the right attachments */
313 if (!priv->have_fake_front)
314 return;
315
316 xrect.x = 0;
317 xrect.y = 0;
318 xrect.width = priv->width;
319 xrect.height = priv->height;
320
321 #ifdef __DRI2_FLUSH
322 if (pdraw->psc->f)
323 (*pdraw->psc->f->flush) (pdraw->driDrawable);
324 #endif
325
326 region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
327 DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
328 DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
329 XFixesDestroyRegion(pdraw->psc->dpy, region);
330 }
331
332 static void
333 dri2WaitGL(__GLXDRIdrawable * pdraw)
334 {
335 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
336 XRectangle xrect;
337 XserverRegion region;
338
339 if (!priv->have_fake_front)
340 return;
341
342 xrect.x = 0;
343 xrect.y = 0;
344 xrect.width = priv->width;
345 xrect.height = priv->height;
346
347 #ifdef __DRI2_FLUSH
348 if (pdraw->psc->f)
349 (*pdraw->psc->f->flush) (pdraw->driDrawable);
350 #endif
351
352 region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
353 DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
354 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
355 XFixesDestroyRegion(pdraw->psc->dpy, region);
356 }
357
358 static void
359 dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
360 {
361 __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
362 __GLXdisplayPrivate *priv = __glXInitialize(pdraw->base.psc->dpy);
363 __GLXDRIdisplayPrivate *pdp = (__GLXDRIdisplayPrivate *)priv->dri2Display;
364
365 /* Old servers don't send invalidate events */
366 if (!pdp->invalidateAvailable)
367 dri2InvalidateBuffers(priv->dpy, pdraw->base.drawable);
368
369 dri2WaitGL(loaderPrivate);
370 }
371
372
373 static void
374 dri2DestroyScreen(__GLXscreenConfigs * psc)
375 {
376 /* Free the direct rendering per screen data */
377 (*psc->core->destroyScreen) (psc->__driScreen);
378 close(psc->fd);
379 psc->__driScreen = NULL;
380 }
381
382 /**
383 * Process list of buffer received from the server
384 *
385 * Processes the list of buffers received in a reply from the server to either
386 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
387 */
388 static void
389 process_buffers(__GLXDRIdrawablePrivate * pdraw, DRI2Buffer * buffers,
390 unsigned count)
391 {
392 int i;
393
394 pdraw->bufferCount = count;
395 pdraw->have_fake_front = 0;
396 pdraw->have_back = 0;
397
398 /* This assumes the DRI2 buffer attachment tokens matches the
399 * __DRIbuffer tokens. */
400 for (i = 0; i < count; i++) {
401 pdraw->buffers[i].attachment = buffers[i].attachment;
402 pdraw->buffers[i].name = buffers[i].name;
403 pdraw->buffers[i].pitch = buffers[i].pitch;
404 pdraw->buffers[i].cpp = buffers[i].cpp;
405 pdraw->buffers[i].flags = buffers[i].flags;
406 if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
407 pdraw->have_fake_front = 1;
408 if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT)
409 pdraw->have_back = 1;
410 }
411
412 }
413
414 static int64_t
415 dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
416 int64_t remainder)
417 {
418 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
419 __GLXdisplayPrivate *dpyPriv = __glXInitialize(priv->base.psc->dpy);
420 __GLXDRIdisplayPrivate *pdp =
421 (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display;
422 int64_t ret;
423
424 #ifdef __DRI2_FLUSH
425 if (pdraw->psc->f)
426 (*pdraw->psc->f->flush)(pdraw->driDrawable);
427 #endif
428
429 /* Old servers don't send invalidate events */
430 if (!pdp->invalidateAvailable)
431 dri2InvalidateBuffers(dpyPriv->dpy, pdraw->drawable);
432
433 /* Old servers can't handle swapbuffers */
434 if (!pdp->swapAvailable) {
435 dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
436 return 0;
437 }
438
439 #ifdef X_DRI2SwapBuffers
440 DRI2SwapBuffers(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor,
441 remainder, &ret);
442 #endif
443
444 return ret;
445 }
446
447 static __DRIbuffer *
448 dri2GetBuffers(__DRIdrawable * driDrawable,
449 int *width, int *height,
450 unsigned int *attachments, int count,
451 int *out_count, void *loaderPrivate)
452 {
453 __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
454 DRI2Buffer *buffers;
455
456 buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable,
457 width, height, attachments, count, out_count);
458 if (buffers == NULL)
459 return NULL;
460
461 pdraw->width = *width;
462 pdraw->height = *height;
463 process_buffers(pdraw, buffers, *out_count);
464
465 Xfree(buffers);
466
467 return pdraw->buffers;
468 }
469
470 static __DRIbuffer *
471 dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
472 int *width, int *height,
473 unsigned int *attachments, int count,
474 int *out_count, void *loaderPrivate)
475 {
476 __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
477 DRI2Buffer *buffers;
478
479 buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy,
480 pdraw->base.xDrawable,
481 width, height, attachments,
482 count, out_count);
483 if (buffers == NULL)
484 return NULL;
485
486 pdraw->width = *width;
487 pdraw->height = *height;
488 process_buffers(pdraw, buffers, *out_count);
489
490 Xfree(buffers);
491
492 return pdraw->buffers;
493 }
494
495 #ifdef X_DRI2SwapInterval
496
497 static void
498 dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
499 {
500 __GLXscreenConfigs *psc = pdraw->psc;
501 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
502 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
503
504 if (psc->config)
505 psc->config->configQueryi(psc->__driScreen, "vblank_mode", &vblank_mode);
506
507 switch (vblank_mode) {
508 case DRI_CONF_VBLANK_NEVER:
509 return;
510 case DRI_CONF_VBLANK_ALWAYS_SYNC:
511 if (interval <= 0)
512 return;
513 break;
514 default:
515 break;
516 }
517
518 DRI2SwapInterval(priv->base.psc->dpy, pdraw->xDrawable, interval);
519 priv->swap_interval = interval;
520 }
521
522 static unsigned int
523 dri2GetSwapInterval(__GLXDRIdrawable *pdraw)
524 {
525 __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
526
527 return priv->swap_interval;
528 }
529
530 #endif /* X_DRI2SwapInterval */
531
532 static const __DRIdri2LoaderExtension dri2LoaderExtension = {
533 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION},
534 dri2GetBuffers,
535 dri2FlushFrontBuffer,
536 dri2GetBuffersWithFormat,
537 };
538
539 static const __DRIdri2LoaderExtension dri2LoaderExtension_old = {
540 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION},
541 dri2GetBuffers,
542 dri2FlushFrontBuffer,
543 NULL,
544 };
545
546 static const __DRIextension *loader_extensions[] = {
547 &dri2LoaderExtension.base,
548 &systemTimeExtension.base,
549 NULL
550 };
551
552 static const __DRIextension *loader_extensions_old[] = {
553 &dri2LoaderExtension_old.base,
554 &systemTimeExtension.base,
555 NULL
556 };
557
558 _X_HIDDEN void
559 dri2InvalidateBuffers(Display *dpy, XID drawable)
560 {
561 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
562
563 #if __DRI2_FLUSH_VERSION >= 3
564 if (pdraw && pdraw->psc->f)
565 pdraw->psc->f->invalidate(pdraw->driDrawable);
566 #endif
567 }
568
569 static __GLXDRIscreen *
570 dri2CreateScreen(__GLXscreenConfigs * psc, int screen,
571 __GLXdisplayPrivate * priv)
572 {
573 const __DRIconfig **driver_configs;
574 const __DRIextension **extensions;
575 const __GLXDRIdisplayPrivate *const pdp = (__GLXDRIdisplayPrivate *)
576 priv->dri2Display;
577 __GLXDRIscreen *psp;
578 char *driverName, *deviceName;
579 drm_magic_t magic;
580 int i;
581
582 psp = Xmalloc(sizeof *psp);
583 if (psp == NULL)
584 return NULL;
585
586 if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen),
587 &driverName, &deviceName)) {
588 XFree(psp);
589 return NULL;
590 }
591
592 psc->driver = driOpenDriver(driverName);
593 if (psc->driver == NULL) {
594 ErrorMessageF("driver pointer missing\n");
595 goto handle_error;
596 }
597
598 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
599 if (extensions == NULL) {
600 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
601 goto handle_error;
602 }
603
604 for (i = 0; extensions[i]; i++) {
605 if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
606 psc->core = (__DRIcoreExtension *) extensions[i];
607 if (strcmp(extensions[i]->name, __DRI_DRI2) == 0)
608 psc->dri2 = (__DRIdri2Extension *) extensions[i];
609 }
610
611 if (psc->core == NULL || psc->dri2 == NULL) {
612 ErrorMessageF("core dri or dri2 extension not found\n");
613 goto handle_error;
614 }
615
616 psc->fd = open(deviceName, O_RDWR);
617 if (psc->fd < 0) {
618 ErrorMessageF("failed to open drm device: %s\n", strerror(errno));
619 goto handle_error;
620 }
621
622 if (drmGetMagic(psc->fd, &magic)) {
623 ErrorMessageF("failed to get magic\n");
624 goto handle_error;
625 }
626
627 if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) {
628 ErrorMessageF("failed to authenticate magic %d\n", magic);
629 goto handle_error;
630 }
631
632 /* If the server does not support the protocol for
633 * DRI2GetBuffersWithFormat, don't supply that interface to the driver.
634 */
635 psc->__driScreen =
636 psc->dri2->createNewScreen(screen, psc->fd, ((pdp->driMinor < 1)
637 ? loader_extensions_old
638 : loader_extensions),
639 &driver_configs, psc);
640
641 if (psc->__driScreen == NULL) {
642 ErrorMessageF("failed to create dri screen\n");
643 goto handle_error;
644 }
645
646 driBindCommonExtensions(psc);
647 dri2BindExtensions(psc);
648
649 psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
650 psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
651
652 psc->driver_configs = driver_configs;
653
654 psp->destroyScreen = dri2DestroyScreen;
655 psp->createContext = dri2CreateContext;
656 psp->createDrawable = dri2CreateDrawable;
657 psp->swapBuffers = dri2SwapBuffers;
658 psp->waitGL = dri2WaitGL;
659 psp->waitX = dri2WaitX;
660 psp->getDrawableMSC = NULL;
661 psp->waitForMSC = NULL;
662 psp->waitForSBC = NULL;
663 psp->setSwapInterval = NULL;
664 psp->getSwapInterval = NULL;
665
666 if (pdp->driMinor >= 2) {
667 #ifdef X_DRI2GetMSC
668 psp->getDrawableMSC = dri2DrawableGetMSC;
669 #endif
670 #ifdef X_DRI2WaitMSC
671 psp->waitForMSC = dri2WaitForMSC;
672 psp->waitForSBC = dri2WaitForSBC;
673 #endif
674 #ifdef X_DRI2SwapInterval
675 psp->setSwapInterval = dri2SetSwapInterval;
676 psp->getSwapInterval = dri2GetSwapInterval;
677 #endif
678 #if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval)
679 __glXEnableDirectExtension(psc, "GLX_OML_sync_control");
680 #endif
681 }
682
683 /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always
684 * available.*/
685 psp->copySubBuffer = dri2CopySubBuffer;
686 __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer");
687
688 Xfree(driverName);
689 Xfree(deviceName);
690
691 return psp;
692
693 handle_error:
694 Xfree(driverName);
695 Xfree(deviceName);
696 XFree(psp);
697
698 /* FIXME: clean up here */
699
700 return NULL;
701 }
702
703 /* Called from __glXFreeDisplayPrivate.
704 */
705 static void
706 dri2DestroyDisplay(__GLXDRIdisplay * dpy)
707 {
708 Xfree(dpy);
709 }
710
711 /*
712 * Allocate, initialize and return a __DRIdisplayPrivate object.
713 * This is called from __glXInitialize() when we are given a new
714 * display pointer.
715 */
716 _X_HIDDEN __GLXDRIdisplay *
717 dri2CreateDisplay(Display * dpy)
718 {
719 __GLXDRIdisplayPrivate *pdp;
720 int eventBase, errorBase;
721
722 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase))
723 return NULL;
724
725 pdp = Xmalloc(sizeof *pdp);
726 if (pdp == NULL)
727 return NULL;
728
729 if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) {
730 Xfree(pdp);
731 return NULL;
732 }
733
734 pdp->driPatch = 0;
735 pdp->swapAvailable = (pdp->driMinor >= 2);
736 pdp->invalidateAvailable = (pdp->driMinor >= 3);
737
738 pdp->base.destroyDisplay = dri2DestroyDisplay;
739 pdp->base.createScreen = dri2CreateScreen;
740
741 return &pdp->base;
742 }
743
744 #endif /* GLX_DIRECT_RENDERING */