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