Remove unneeded xdamages header from dri2_glx.c.
[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 "glapi.h"
38 #include "glxclient.h"
39 #include <X11/extensions/dri2proto.h>
40 #include "xf86dri.h"
41 #include <dlfcn.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <sys/types.h>
45 #include <sys/mman.h>
46 #include "xf86drm.h"
47 #include "dri2.h"
48 #include "dri_common.h"
49
50 /* From xmlpool/options.h, user exposed so should be stable */
51 #define DRI_CONF_VBLANK_NEVER 0
52 #define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
53 #define DRI_CONF_VBLANK_DEF_INTERVAL_1 2
54 #define DRI_CONF_VBLANK_ALWAYS_SYNC 3
55
56 #undef DRI2_MINOR
57 #define DRI2_MINOR 1
58
59 struct dri2_display
60 {
61 __GLXDRIdisplay base;
62
63 /*
64 ** XFree86-DRI version information
65 */
66 int driMajor;
67 int driMinor;
68 int driPatch;
69 int swapAvailable;
70 int invalidateAvailable;
71
72 __glxHashTable *dri2Hash;
73
74 const __DRIextension *loader_extensions[4];
75 };
76
77 struct dri2_screen {
78 struct glx_screen base;
79
80 __DRIscreen *driScreen;
81 __GLXDRIscreen vtable;
82 const __DRIdri2Extension *dri2;
83 const __DRIcoreExtension *core;
84
85 const __DRI2flushExtension *f;
86 const __DRI2configQueryExtension *config;
87 const __DRItexBufferExtension *texBuffer;
88 const __DRIconfig **driver_configs;
89
90 void *driver;
91 int fd;
92 };
93
94 struct dri2_context
95 {
96 struct glx_context base;
97 __DRIcontext *driContext;
98 };
99
100 struct dri2_drawable
101 {
102 __GLXDRIdrawable base;
103 __DRIdrawable *driDrawable;
104 __DRIbuffer buffers[5];
105 int bufferCount;
106 int width, height;
107 int have_back;
108 int have_fake_front;
109 int swap_interval;
110 };
111
112 static const struct glx_context_vtable dri2_context_vtable;
113
114 static void
115 dri2_destroy_context(struct glx_context *context)
116 {
117 struct dri2_context *pcp = (struct dri2_context *) context;
118 struct dri2_screen *psc = (struct dri2_screen *) context->psc;
119
120 driReleaseDrawables(&pcp->base);
121
122 if (context->xid)
123 glx_send_destroy_context(psc->base.dpy, context->xid);
124
125 if (context->extensions)
126 XFree((char *) context->extensions);
127
128 (*psc->core->destroyContext) (pcp->driContext);
129
130 Xfree(pcp);
131 }
132
133 static Bool
134 dri2_bind_context(struct glx_context *context, struct glx_context *old,
135 GLXDrawable draw, GLXDrawable read)
136 {
137 struct dri2_context *pcp = (struct dri2_context *) context;
138 struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc;
139 struct dri2_drawable *pdraw, *pread;
140 struct dri2_display *pdp;
141
142 pdraw = (struct dri2_drawable *) driFetchDrawable(context, draw);
143 pread = (struct dri2_drawable *) driFetchDrawable(context, read);
144
145 driReleaseDrawables(&pcp->base);
146
147 if (pdraw == NULL || pread == NULL)
148 return GLXBadDrawable;
149
150 if (!(*psc->core->bindContext) (pcp->driContext,
151 pdraw->driDrawable, pread->driDrawable))
152 return GLXBadContext;
153
154 /* If the server doesn't send invalidate events, we may miss a
155 * resize before the rendering starts. Invalidate the buffers now
156 * so the driver will recheck before rendering starts. */
157 pdp = (struct dri2_display *) psc->base.display;
158 if (!pdp->invalidateAvailable) {
159 dri2InvalidateBuffers(psc->base.dpy, pdraw->base.xDrawable);
160 if (pread != pdraw)
161 dri2InvalidateBuffers(psc->base.dpy, pread->base.xDrawable);
162 }
163
164 return Success;
165 }
166
167 static void
168 dri2_unbind_context(struct glx_context *context, struct glx_context *new)
169 {
170 struct dri2_context *pcp = (struct dri2_context *) context;
171 struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc;
172
173 (*psc->core->unbindContext) (pcp->driContext);
174 }
175
176 static struct glx_context *
177 dri2_create_context(struct glx_screen *base,
178 struct glx_config *config_base,
179 struct glx_context *shareList, int renderType)
180 {
181 struct dri2_context *pcp, *pcp_shared;
182 struct dri2_screen *psc = (struct dri2_screen *) base;
183 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
184 __DRIcontext *shared = NULL;
185
186 if (shareList) {
187 pcp_shared = (struct dri2_context *) shareList;
188 shared = pcp_shared->driContext;
189 }
190
191 pcp = Xmalloc(sizeof *pcp);
192 if (pcp == NULL)
193 return NULL;
194
195 memset(pcp, 0, sizeof *pcp);
196 if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
197 Xfree(pcp);
198 return NULL;
199 }
200
201 pcp->driContext =
202 (*psc->dri2->createNewContext) (psc->driScreen,
203 config->driConfig, shared, pcp);
204
205 if (pcp->driContext == NULL) {
206 Xfree(pcp);
207 return NULL;
208 }
209
210 pcp->base.vtable = &dri2_context_vtable;
211
212 return &pcp->base;
213 }
214
215 static void
216 dri2DestroyDrawable(__GLXDRIdrawable *base)
217 {
218 struct dri2_screen *psc = (struct dri2_screen *) base->psc;
219 struct dri2_drawable *pdraw = (struct dri2_drawable *) base;
220 struct glx_display *dpyPriv = psc->base.display;
221 struct dri2_display *pdp = (struct dri2_display *)dpyPriv->dri2Display;
222
223 __glxHashDelete(pdp->dri2Hash, pdraw->base.xDrawable);
224 (*psc->core->destroyDrawable) (pdraw->driDrawable);
225
226 /* If it's a GLX 1.3 drawables, we can destroy the DRI2 drawable
227 * now, as the application explicitly asked to destroy the GLX
228 * drawable. Otherwise, for legacy drawables, we let the DRI2
229 * drawable linger on the server, since there's no good way of
230 * knowing when the application is done with it. The server will
231 * destroy the DRI2 drawable when it destroys the X drawable or the
232 * client exits anyway. */
233 if (pdraw->base.xDrawable != pdraw->base.drawable)
234 DRI2DestroyDrawable(psc->base.dpy, pdraw->base.xDrawable);
235
236 Xfree(pdraw);
237 }
238
239 static __GLXDRIdrawable *
240 dri2CreateDrawable(struct glx_screen *base, XID xDrawable,
241 GLXDrawable drawable, struct glx_config *config_base)
242 {
243 struct dri2_drawable *pdraw;
244 struct dri2_screen *psc = (struct dri2_screen *) base;
245 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
246 struct glx_display *dpyPriv;
247 struct dri2_display *pdp;
248 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
249
250 pdraw = Xmalloc(sizeof(*pdraw));
251 if (!pdraw)
252 return NULL;
253
254 memset(pdraw, 0, sizeof *pdraw);
255 pdraw->base.destroyDrawable = dri2DestroyDrawable;
256 pdraw->base.xDrawable = xDrawable;
257 pdraw->base.drawable = drawable;
258 pdraw->base.psc = &psc->base;
259 pdraw->bufferCount = 0;
260 pdraw->swap_interval = 1; /* default may be overridden below */
261 pdraw->have_back = 0;
262
263 if (psc->config)
264 psc->config->configQueryi(psc->driScreen,
265 "vblank_mode", &vblank_mode);
266
267 switch (vblank_mode) {
268 case DRI_CONF_VBLANK_NEVER:
269 case DRI_CONF_VBLANK_DEF_INTERVAL_0:
270 pdraw->swap_interval = 0;
271 break;
272 case DRI_CONF_VBLANK_DEF_INTERVAL_1:
273 case DRI_CONF_VBLANK_ALWAYS_SYNC:
274 default:
275 pdraw->swap_interval = 1;
276 break;
277 }
278
279 DRI2CreateDrawable(psc->base.dpy, xDrawable);
280
281 dpyPriv = __glXInitialize(psc->base.dpy);
282 pdp = (struct dri2_display *)dpyPriv->dri2Display;;
283 /* Create a new drawable */
284 pdraw->driDrawable =
285 (*psc->dri2->createNewDrawable) (psc->driScreen,
286 config->driConfig, pdraw);
287
288 if (!pdraw->driDrawable) {
289 DRI2DestroyDrawable(psc->base.dpy, xDrawable);
290 Xfree(pdraw);
291 return NULL;
292 }
293
294 if (__glxHashInsert(pdp->dri2Hash, xDrawable, pdraw)) {
295 (*psc->core->destroyDrawable) (pdraw->driDrawable);
296 DRI2DestroyDrawable(psc->base.dpy, xDrawable);
297 Xfree(pdraw);
298 return None;
299 }
300
301
302 #ifdef X_DRI2SwapInterval
303 /*
304 * Make sure server has the same swap interval we do for the new
305 * drawable.
306 */
307 if (pdp->swapAvailable)
308 DRI2SwapInterval(psc->base.dpy, xDrawable, pdraw->swap_interval);
309 #endif
310
311 return &pdraw->base;
312 }
313
314 #ifdef X_DRI2GetMSC
315
316 static int
317 dri2DrawableGetMSC(struct glx_screen *psc, __GLXDRIdrawable *pdraw,
318 int64_t *ust, int64_t *msc, int64_t *sbc)
319 {
320 CARD64 dri2_ust, dri2_msc, dri2_sbc;
321 int ret;
322
323 ret = DRI2GetMSC(psc->dpy, pdraw->xDrawable,
324 &dri2_ust, &dri2_msc, &dri2_sbc);
325 *ust = dri2_ust;
326 *msc = dri2_msc;
327 *sbc = dri2_sbc;
328
329 return ret;
330 }
331
332 #endif
333
334
335 #ifdef X_DRI2WaitMSC
336
337 static int
338 dri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
339 int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
340 {
341 CARD64 dri2_ust, dri2_msc, dri2_sbc;
342 int ret;
343
344 ret = DRI2WaitMSC(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor,
345 remainder, &dri2_ust, &dri2_msc, &dri2_sbc);
346 *ust = dri2_ust;
347 *msc = dri2_msc;
348 *sbc = dri2_sbc;
349
350 return ret;
351 }
352
353 static int
354 dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
355 int64_t *msc, int64_t *sbc)
356 {
357 CARD64 dri2_ust, dri2_msc, dri2_sbc;
358 int ret;
359
360 ret = DRI2WaitSBC(pdraw->psc->dpy, pdraw->xDrawable,
361 target_sbc, &dri2_ust, &dri2_msc, &dri2_sbc);
362 *ust = dri2_ust;
363 *msc = dri2_msc;
364 *sbc = dri2_sbc;
365
366 return ret;
367 }
368
369 #endif /* X_DRI2WaitMSC */
370
371 static void
372 dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height)
373 {
374 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw;
375 struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc;
376 XRectangle xrect;
377 XserverRegion region;
378
379 /* Check we have the right attachments */
380 if (!priv->have_back)
381 return;
382
383 xrect.x = x;
384 xrect.y = priv->height - y - height;
385 xrect.width = width;
386 xrect.height = height;
387
388 #ifdef __DRI2_FLUSH
389 if (psc->f)
390 (*psc->f->flush) (priv->driDrawable);
391 #endif
392
393 region = XFixesCreateRegion(psc->base.dpy, &xrect, 1);
394 DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region,
395 DRI2BufferFrontLeft, DRI2BufferBackLeft);
396
397 /* Refresh the fake front (if present) after we just damaged the real
398 * front.
399 */
400 if (priv->have_fake_front)
401 DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region,
402 DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
403
404 XFixesDestroyRegion(psc->base.dpy, region);
405 }
406
407 static void
408 dri2_copy_drawable(struct dri2_drawable *priv, int dest, int src)
409 {
410 XRectangle xrect;
411 XserverRegion region;
412 struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc;
413
414 xrect.x = 0;
415 xrect.y = 0;
416 xrect.width = priv->width;
417 xrect.height = priv->height;
418
419 #ifdef __DRI2_FLUSH
420 if (psc->f)
421 (*psc->f->flush) (priv->driDrawable);
422 #endif
423
424 region = XFixesCreateRegion(psc->base.dpy, &xrect, 1);
425 DRI2CopyRegion(psc->base.dpy, priv->base.xDrawable, region, dest, src);
426 XFixesDestroyRegion(psc->base.dpy, region);
427
428 }
429
430 static void
431 dri2_wait_x(struct glx_context *gc)
432 {
433 struct dri2_drawable *priv = (struct dri2_drawable *)
434 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
435
436 if (priv == NULL || !priv->have_fake_front)
437 return;
438
439 dri2_copy_drawable(priv, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
440 }
441
442 static void
443 dri2_wait_gl(struct glx_context *gc)
444 {
445 struct dri2_drawable *priv = (struct dri2_drawable *)
446 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
447
448 if (priv == NULL || !priv->have_fake_front)
449 return;
450
451 dri2_copy_drawable(priv, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
452 }
453
454 static void
455 dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
456 {
457 struct glx_display *priv;
458 struct dri2_display *pdp;
459 struct glx_context *gc;
460 struct dri2_drawable *pdraw = loaderPrivate;
461
462 if (!pdraw)
463 return;
464
465 if (!pdraw->base.psc)
466 return;
467
468 priv = __glXInitialize(pdraw->base.psc->dpy);
469 pdp = (struct dri2_display *) priv->dri2Display;
470 gc = __glXGetCurrentContext();
471
472 /* Old servers don't send invalidate events */
473 if (!pdp->invalidateAvailable)
474 dri2InvalidateBuffers(priv->dpy, pdraw->base.xDrawable);
475
476 dri2_wait_gl(gc);
477 }
478
479
480 static void
481 dri2DestroyScreen(struct glx_screen *base)
482 {
483 struct dri2_screen *psc = (struct dri2_screen *) base;
484
485 /* Free the direct rendering per screen data */
486 (*psc->core->destroyScreen) (psc->driScreen);
487 driDestroyConfigs(psc->driver_configs);
488 close(psc->fd);
489 Xfree(psc);
490 }
491
492 /**
493 * Process list of buffer received from the server
494 *
495 * Processes the list of buffers received in a reply from the server to either
496 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
497 */
498 static void
499 process_buffers(struct dri2_drawable * pdraw, DRI2Buffer * buffers,
500 unsigned count)
501 {
502 int i;
503
504 pdraw->bufferCount = count;
505 pdraw->have_fake_front = 0;
506 pdraw->have_back = 0;
507
508 /* This assumes the DRI2 buffer attachment tokens matches the
509 * __DRIbuffer tokens. */
510 for (i = 0; i < count; i++) {
511 pdraw->buffers[i].attachment = buffers[i].attachment;
512 pdraw->buffers[i].name = buffers[i].name;
513 pdraw->buffers[i].pitch = buffers[i].pitch;
514 pdraw->buffers[i].cpp = buffers[i].cpp;
515 pdraw->buffers[i].flags = buffers[i].flags;
516 if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
517 pdraw->have_fake_front = 1;
518 if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT)
519 pdraw->have_back = 1;
520 }
521
522 }
523
524 unsigned dri2GetSwapEventType(Display* dpy, XID drawable)
525 {
526 struct glx_display *glx_dpy = __glXInitialize(dpy);
527 __GLXDRIdrawable *pdraw;
528 pdraw = dri2GetGlxDrawableFromXDrawableId(dpy, drawable);
529 if (!pdraw || !(pdraw->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK))
530 return 0;
531 return glx_dpy->codes->first_event + GLX_BufferSwapComplete;
532 }
533
534 static int64_t
535 dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
536 int64_t remainder)
537 {
538 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw;
539 struct glx_display *dpyPriv = __glXInitialize(priv->base.psc->dpy);
540 struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc;
541 struct dri2_display *pdp =
542 (struct dri2_display *)dpyPriv->dri2Display;
543 CARD64 ret = 0;
544
545 /* Check we have the right attachments */
546 if (!priv->have_back)
547 return ret;
548
549 /* Old servers can't handle swapbuffers */
550 if (!pdp->swapAvailable) {
551 dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
552 } else {
553 #ifdef X_DRI2SwapBuffers
554 #ifdef __DRI2_FLUSH
555 if (psc->f) {
556 struct glx_context *gc = __glXGetCurrentContext();
557
558 if (gc) {
559 (*psc->f->flush)(priv->driDrawable);
560 }
561 }
562 #endif
563
564 DRI2SwapBuffers(psc->base.dpy, pdraw->xDrawable,
565 target_msc, divisor, remainder, &ret);
566 #endif
567 }
568
569 /* Old servers don't send invalidate events */
570 if (!pdp->invalidateAvailable)
571 dri2InvalidateBuffers(dpyPriv->dpy, pdraw->xDrawable);
572
573 return ret;
574 }
575
576 static __DRIbuffer *
577 dri2GetBuffers(__DRIdrawable * driDrawable,
578 int *width, int *height,
579 unsigned int *attachments, int count,
580 int *out_count, void *loaderPrivate)
581 {
582 struct dri2_drawable *pdraw = loaderPrivate;
583 DRI2Buffer *buffers;
584
585 buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable,
586 width, height, attachments, count, out_count);
587 if (buffers == NULL)
588 return NULL;
589
590 pdraw->width = *width;
591 pdraw->height = *height;
592 process_buffers(pdraw, buffers, *out_count);
593
594 Xfree(buffers);
595
596 return pdraw->buffers;
597 }
598
599 static __DRIbuffer *
600 dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
601 int *width, int *height,
602 unsigned int *attachments, int count,
603 int *out_count, void *loaderPrivate)
604 {
605 struct dri2_drawable *pdraw = loaderPrivate;
606 DRI2Buffer *buffers;
607
608 buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy,
609 pdraw->base.xDrawable,
610 width, height, attachments,
611 count, out_count);
612 if (buffers == NULL)
613 return NULL;
614
615 pdraw->width = *width;
616 pdraw->height = *height;
617 process_buffers(pdraw, buffers, *out_count);
618
619 Xfree(buffers);
620
621 return pdraw->buffers;
622 }
623
624 #ifdef X_DRI2SwapInterval
625
626 static int
627 dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
628 {
629 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw;
630 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
631 struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc;
632
633 if (psc->config)
634 psc->config->configQueryi(psc->driScreen,
635 "vblank_mode", &vblank_mode);
636
637 switch (vblank_mode) {
638 case DRI_CONF_VBLANK_NEVER:
639 return GLX_BAD_VALUE;
640 case DRI_CONF_VBLANK_ALWAYS_SYNC:
641 if (interval <= 0)
642 return GLX_BAD_VALUE;
643 break;
644 default:
645 break;
646 }
647
648 DRI2SwapInterval(priv->base.psc->dpy, priv->base.xDrawable, interval);
649 priv->swap_interval = interval;
650
651 return 0;
652 }
653
654 static int
655 dri2GetSwapInterval(__GLXDRIdrawable *pdraw)
656 {
657 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw;
658
659 return priv->swap_interval;
660 }
661
662 #endif /* X_DRI2SwapInterval */
663
664 static const __DRIdri2LoaderExtension dri2LoaderExtension = {
665 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION},
666 dri2GetBuffers,
667 dri2FlushFrontBuffer,
668 dri2GetBuffersWithFormat,
669 };
670
671 static const __DRIdri2LoaderExtension dri2LoaderExtension_old = {
672 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION},
673 dri2GetBuffers,
674 dri2FlushFrontBuffer,
675 NULL,
676 };
677
678 #ifdef __DRI_USE_INVALIDATE
679 static const __DRIuseInvalidateExtension dri2UseInvalidate = {
680 { __DRI_USE_INVALIDATE, __DRI_USE_INVALIDATE_VERSION }
681 };
682 #endif
683
684 _X_HIDDEN void
685 dri2InvalidateBuffers(Display *dpy, XID drawable)
686 {
687 __GLXDRIdrawable *pdraw =
688 dri2GetGlxDrawableFromXDrawableId(dpy, drawable);
689 struct dri2_screen *psc;
690 struct dri2_drawable *pdp = (struct dri2_drawable *) pdraw;
691
692 if (!pdraw)
693 return;
694
695 psc = (struct dri2_screen *) pdraw->psc;
696
697 #if __DRI2_FLUSH_VERSION >= 3
698 if (pdraw && psc->f && psc->f->base.version >= 3 && psc->f->invalidate)
699 psc->f->invalidate(pdp->driDrawable);
700 #endif
701 }
702
703 static void
704 dri2_bind_tex_image(Display * dpy,
705 GLXDrawable drawable,
706 int buffer, const int *attrib_list)
707 {
708 struct glx_context *gc = __glXGetCurrentContext();
709 struct dri2_context *pcp = (struct dri2_context *) gc;
710 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
711 struct glx_display *dpyPriv = __glXInitialize(dpy);
712 struct dri2_drawable *pdraw = (struct dri2_drawable *) base;
713 struct dri2_display *pdp =
714 (struct dri2_display *) dpyPriv->dri2Display;
715 struct dri2_screen *psc;
716
717 if (pdraw != NULL) {
718 psc = (struct dri2_screen *) base->psc;
719
720 #if __DRI2_FLUSH_VERSION >= 3
721 if (!pdp->invalidateAvailable && psc->f &&
722 psc->f->base.version >= 3 && psc->f->invalidate)
723 psc->f->invalidate(pdraw->driDrawable);
724 #endif
725
726 if (psc->texBuffer->base.version >= 2 &&
727 psc->texBuffer->setTexBuffer2 != NULL) {
728 (*psc->texBuffer->setTexBuffer2) (pcp->driContext,
729 pdraw->base.textureTarget,
730 pdraw->base.textureFormat,
731 pdraw->driDrawable);
732 }
733 else {
734 (*psc->texBuffer->setTexBuffer) (pcp->driContext,
735 pdraw->base.textureTarget,
736 pdraw->driDrawable);
737 }
738 }
739 }
740
741 static void
742 dri2_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
743 {
744 #if __DRI_TEX_BUFFER_VERSION >= 3
745 struct glx_context *gc = __glXGetCurrentContext();
746 struct dri2_context *pcp = (struct dri2_context *) gc;
747 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
748 struct glx_display *dpyPriv = __glXInitialize(dpy);
749 struct dri2_drawable *pdraw = (struct dri2_drawable *) base;
750 struct dri2_display *pdp =
751 (struct dri2_display *) dpyPriv->dri2Display;
752 struct dri2_screen *psc;
753
754 if (pdraw != NULL) {
755 psc = (struct dri2_screen *) base->psc;
756
757 if (psc->texBuffer->base.version >= 3 &&
758 psc->texBuffer->releaseTexBuffer != NULL) {
759 (*psc->texBuffer->releaseTexBuffer) (pcp->driContext,
760 pdraw->base.textureTarget,
761 pdraw->driDrawable);
762 }
763 }
764 #endif
765 }
766
767 static const struct glx_context_vtable dri2_context_vtable = {
768 dri2_destroy_context,
769 dri2_bind_context,
770 dri2_unbind_context,
771 dri2_wait_gl,
772 dri2_wait_x,
773 DRI_glXUseXFont,
774 dri2_bind_tex_image,
775 dri2_release_tex_image,
776 NULL, /* get_proc_address */
777 };
778
779 static void
780 dri2BindExtensions(struct dri2_screen *psc, const __DRIextension **extensions)
781 {
782 int i;
783
784 __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
785 __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
786 __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
787 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
788
789 /* FIXME: if DRI2 version supports it... */
790 __glXEnableDirectExtension(&psc->base, "INTEL_swap_event");
791
792 for (i = 0; extensions[i]; i++) {
793 if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
794 psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
795 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap");
796 }
797
798 if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) {
799 psc->f = (__DRI2flushExtension *) extensions[i];
800 /* internal driver extension, no GL extension exposed */
801 }
802
803 if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0))
804 psc->config = (__DRI2configQueryExtension *) extensions[i];
805 }
806 }
807
808 static const struct glx_screen_vtable dri2_screen_vtable = {
809 dri2_create_context
810 };
811
812 static struct glx_screen *
813 dri2CreateScreen(int screen, struct glx_display * priv)
814 {
815 const __DRIconfig **driver_configs;
816 const __DRIextension **extensions;
817 const struct dri2_display *const pdp = (struct dri2_display *)
818 priv->dri2Display;
819 struct dri2_screen *psc;
820 __GLXDRIscreen *psp;
821 char *driverName, *deviceName;
822 drm_magic_t magic;
823 int i;
824
825 psc = Xmalloc(sizeof *psc);
826 if (psc == NULL)
827 return NULL;
828
829 memset(psc, 0, sizeof *psc);
830 psc->fd = -1;
831
832 if (!glx_screen_init(&psc->base, screen, priv)) {
833 Xfree(psc);
834 return NULL;
835 }
836
837 if (!DRI2Connect(priv->dpy, RootWindow(priv->dpy, screen),
838 &driverName, &deviceName)) {
839 glx_screen_cleanup(&psc->base);
840 XFree(psc);
841 InfoMessageF("screen %d does not appear to be DRI2 capable\n", screen);
842 return NULL;
843 }
844
845 psc->driver = driOpenDriver(driverName);
846 if (psc->driver == NULL) {
847 ErrorMessageF("driver pointer missing\n");
848 goto handle_error;
849 }
850
851 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
852 if (extensions == NULL) {
853 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
854 goto handle_error;
855 }
856
857 for (i = 0; extensions[i]; i++) {
858 if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
859 psc->core = (__DRIcoreExtension *) extensions[i];
860 if (strcmp(extensions[i]->name, __DRI_DRI2) == 0)
861 psc->dri2 = (__DRIdri2Extension *) extensions[i];
862 }
863
864 if (psc->core == NULL || psc->dri2 == NULL) {
865 ErrorMessageF("core dri or dri2 extension not found\n");
866 goto handle_error;
867 }
868
869 psc->fd = open(deviceName, O_RDWR);
870 if (psc->fd < 0) {
871 ErrorMessageF("failed to open drm device: %s\n", strerror(errno));
872 goto handle_error;
873 }
874
875 if (drmGetMagic(psc->fd, &magic)) {
876 ErrorMessageF("failed to get magic\n");
877 goto handle_error;
878 }
879
880 if (!DRI2Authenticate(priv->dpy, RootWindow(priv->dpy, screen), magic)) {
881 ErrorMessageF("failed to authenticate magic %d\n", magic);
882 goto handle_error;
883 }
884
885
886 /* If the server does not support the protocol for
887 * DRI2GetBuffersWithFormat, don't supply that interface to the driver.
888 */
889 psc->driScreen =
890 psc->dri2->createNewScreen(screen, psc->fd,
891 (const __DRIextension **)
892 &pdp->loader_extensions[0],
893 &driver_configs, psc);
894
895 if (psc->driScreen == NULL) {
896 ErrorMessageF("failed to create dri screen\n");
897 goto handle_error;
898 }
899
900 extensions = psc->core->getExtensions(psc->driScreen);
901 dri2BindExtensions(psc, extensions);
902
903 psc->base.configs =
904 driConvertConfigs(psc->core, psc->base.configs, driver_configs);
905 psc->base.visuals =
906 driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
907
908 psc->driver_configs = driver_configs;
909
910 psc->base.vtable = &dri2_screen_vtable;
911 psp = &psc->vtable;
912 psc->base.driScreen = psp;
913 psp->destroyScreen = dri2DestroyScreen;
914 psp->createDrawable = dri2CreateDrawable;
915 psp->swapBuffers = dri2SwapBuffers;
916 psp->getDrawableMSC = NULL;
917 psp->waitForMSC = NULL;
918 psp->waitForSBC = NULL;
919 psp->setSwapInterval = NULL;
920 psp->getSwapInterval = NULL;
921
922 if (pdp->driMinor >= 2) {
923 #ifdef X_DRI2GetMSC
924 psp->getDrawableMSC = dri2DrawableGetMSC;
925 #endif
926 #ifdef X_DRI2WaitMSC
927 psp->waitForMSC = dri2WaitForMSC;
928 psp->waitForSBC = dri2WaitForSBC;
929 #endif
930 #ifdef X_DRI2SwapInterval
931 psp->setSwapInterval = dri2SetSwapInterval;
932 psp->getSwapInterval = dri2GetSwapInterval;
933 #endif
934 #if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval)
935 __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control");
936 #endif
937 }
938
939 /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always
940 * available.*/
941 psp->copySubBuffer = dri2CopySubBuffer;
942 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
943
944 Xfree(driverName);
945 Xfree(deviceName);
946
947 return &psc->base;
948
949 handle_error:
950 if (psc->fd >= 0)
951 close(psc->fd);
952 if (psc->driver)
953 dlclose(psc->driver);
954 Xfree(driverName);
955 Xfree(deviceName);
956 glx_screen_cleanup(&psc->base);
957 XFree(psc);
958
959 return NULL;
960 }
961
962 /* Called from __glXFreeDisplayPrivate.
963 */
964 static void
965 dri2DestroyDisplay(__GLXDRIdisplay * dpy)
966 {
967 struct dri2_display *pdp = (struct dri2_display *) dpy;
968
969 __glxHashDestroy(pdp->dri2Hash);
970 Xfree(dpy);
971 }
972
973 _X_HIDDEN __GLXDRIdrawable *
974 dri2GetGlxDrawableFromXDrawableId(Display *dpy, XID id)
975 {
976 struct glx_display *d = __glXInitialize(dpy);
977 struct dri2_display *pdp = (struct dri2_display *) d->dri2Display;
978 __GLXDRIdrawable *pdraw;
979
980 if (__glxHashLookup(pdp->dri2Hash, id, (void *) &pdraw) == 0)
981 return pdraw;
982
983 return NULL;
984 }
985
986 /*
987 * Allocate, initialize and return a __DRIdisplayPrivate object.
988 * This is called from __glXInitialize() when we are given a new
989 * display pointer.
990 */
991 _X_HIDDEN __GLXDRIdisplay *
992 dri2CreateDisplay(Display * dpy)
993 {
994 struct dri2_display *pdp;
995 int eventBase, errorBase, i;
996
997 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase))
998 return NULL;
999
1000 pdp = Xmalloc(sizeof *pdp);
1001 if (pdp == NULL)
1002 return NULL;
1003
1004 if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) {
1005 Xfree(pdp);
1006 return NULL;
1007 }
1008
1009 pdp->driPatch = 0;
1010 pdp->swapAvailable = (pdp->driMinor >= 2);
1011 pdp->invalidateAvailable = (pdp->driMinor >= 3);
1012
1013 pdp->base.destroyDisplay = dri2DestroyDisplay;
1014 pdp->base.createScreen = dri2CreateScreen;
1015
1016 i = 0;
1017 if (pdp->driMinor < 1)
1018 pdp->loader_extensions[i++] = &dri2LoaderExtension_old.base;
1019 else
1020 pdp->loader_extensions[i++] = &dri2LoaderExtension.base;
1021
1022 pdp->loader_extensions[i++] = &systemTimeExtension.base;
1023
1024 #ifdef __DRI_USE_INVALIDATE
1025 pdp->loader_extensions[i++] = &dri2UseInvalidate.base;
1026 #endif
1027 pdp->loader_extensions[i++] = NULL;
1028
1029 pdp->dri2Hash = __glxHashCreate();
1030 if (pdp->dri2Hash == NULL) {
1031 Xfree(pdp);
1032 return NULL;
1033 }
1034
1035 return &pdp->base;
1036 }
1037
1038 #endif /* GLX_DIRECT_RENDERING */