Imported Upstream version 1.15.1
[deb_xorg-server.git] / glx / glxdri2.c
CommitLineData
a09e091a
JB
1/*
2 * Copyright © 2007 Red Hat, Inc
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of Red Hat,
9 * Inc not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior
11 * permission. Red Hat, Inc makes no representations about the
12 * suitability of this software for any purpose. It is provided "as
13 * is" without express or implied warranty.
14 *
15 * RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23
24#ifdef HAVE_DIX_CONFIG_H
25#include <dix-config.h>
26#endif
27
28#include <stdint.h>
29#include <stdio.h>
30#include <string.h>
31#include <errno.h>
32#include <dlfcn.h>
33
34#include <drm.h>
35#include <GL/gl.h>
36#include <GL/internal/dri_interface.h>
37#include <GL/glxtokens.h>
38
39#include <windowstr.h>
40#include <os.h>
41
42#define _XF86DRI_SERVER_
43#include <xf86drm.h>
44#include <xf86.h>
45#include <dri2.h>
46
47#include "glxserver.h"
48#include "glxutil.h"
49#include "glxdricommon.h"
50#include <GL/glxtokens.h>
51
52#include "extension_string.h"
53
54typedef struct __GLXDRIscreen __GLXDRIscreen;
55typedef struct __GLXDRIcontext __GLXDRIcontext;
56typedef struct __GLXDRIdrawable __GLXDRIdrawable;
57
58#ifdef __DRI2_ROBUSTNESS
59#define ALL_DRI_CTX_FLAGS (__DRI_CTX_FLAG_DEBUG \
60 | __DRI_CTX_FLAG_FORWARD_COMPATIBLE \
61 | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS)
62#else
63#define ALL_DRI_CTX_FLAGS (__DRI_CTX_FLAG_DEBUG \
64 | __DRI_CTX_FLAG_FORWARD_COMPATIBLE)
65#endif
66
67struct __GLXDRIscreen {
68 __GLXscreen base;
69 __DRIscreen *driScreen;
70 void *driver;
71 int fd;
72
73 xf86EnterVTProc *enterVT;
74 xf86LeaveVTProc *leaveVT;
75
76 const __DRIcoreExtension *core;
77 const __DRIdri2Extension *dri2;
78 const __DRI2flushExtension *flush;
79 const __DRIcopySubBufferExtension *copySubBuffer;
80 const __DRIswapControlExtension *swapControl;
81 const __DRItexBufferExtension *texBuffer;
82 const __DRIconfig **driConfigs;
83
84 unsigned char glx_enable_bits[__GLX_EXT_BYTES];
85};
86
87struct __GLXDRIcontext {
88 __GLXcontext base;
89 __DRIcontext *driContext;
90};
91
92#define MAX_DRAWABLE_BUFFERS 5
93
94struct __GLXDRIdrawable {
95 __GLXdrawable base;
96 __DRIdrawable *driDrawable;
97 __GLXDRIscreen *screen;
98
99 /* Dimensions as last reported by DRI2GetBuffers. */
100 int width;
101 int height;
102 __DRIbuffer buffers[MAX_DRAWABLE_BUFFERS];
103 int count;
104 XID dri2_id;
105};
106
107static void
108__glXDRIdrawableDestroy(__GLXdrawable * drawable)
109{
110 __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
111 const __DRIcoreExtension *core = private->screen->core;
112
113 FreeResource(private->dri2_id, FALSE);
114
115 (*core->destroyDrawable) (private->driDrawable);
116
117 __glXDrawableRelease(drawable);
118
119 free(private);
120}
121
122static void
123__glXDRIdrawableCopySubBuffer(__GLXdrawable * drawable,
124 int x, int y, int w, int h)
125{
126 __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
127 BoxRec box;
128 RegionRec region;
129
130 box.x1 = x;
131 box.y1 = private->height - y - h;
132 box.x2 = x + w;
133 box.y2 = private->height - y;
134 RegionInit(&region, &box, 0);
135
136 DRI2CopyRegion(drawable->pDraw, &region,
137 DRI2BufferFrontLeft, DRI2BufferBackLeft);
138}
139
140static void
141__glXDRIdrawableWaitX(__GLXdrawable * drawable)
142{
143 __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
144 BoxRec box;
145 RegionRec region;
146
147 box.x1 = 0;
148 box.y1 = 0;
149 box.x2 = private->width;
150 box.y2 = private->height;
151 RegionInit(&region, &box, 0);
152
153 DRI2CopyRegion(drawable->pDraw, &region,
154 DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
155}
156
157static void
158__glXDRIdrawableWaitGL(__GLXdrawable * drawable)
159{
160 __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
161 BoxRec box;
162 RegionRec region;
163
164 box.x1 = 0;
165 box.y1 = 0;
166 box.x2 = private->width;
167 box.y2 = private->height;
168 RegionInit(&region, &box, 0);
169
170 DRI2CopyRegion(drawable->pDraw, &region,
171 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
172}
173
174static void
175__glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
176 CARD64 msc, CARD32 sbc)
177{
178 __GLXdrawable *drawable = data;
179 int glx_type;
180 switch (type) {
181 case DRI2_EXCHANGE_COMPLETE:
182 glx_type = GLX_EXCHANGE_COMPLETE_INTEL;
183 break;
184 default:
185 /* unknown swap completion type,
186 * BLIT is a reasonable default, so
187 * fall through ...
188 */
189 case DRI2_BLIT_COMPLETE:
190 glx_type = GLX_BLIT_COMPLETE_INTEL;
191 break;
192 case DRI2_FLIP_COMPLETE:
193 glx_type = GLX_FLIP_COMPLETE_INTEL;
194 break;
195 }
196
197 __glXsendSwapEvent(drawable, glx_type, ust, msc, sbc);
198}
199
200/*
201 * Copy or flip back to front, honoring the swap interval if possible.
202 *
203 * If the kernel supports it, we request an event for the frame when the
204 * swap should happen, then perform the copy when we receive it.
205 */
206static GLboolean
207__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable * drawable)
208{
209 __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
210 __GLXDRIscreen *screen = priv->screen;
211 CARD64 unused;
212
213#if __DRI2_FLUSH_VERSION >= 3
214 if (screen->flush) {
215 (*screen->flush->flush) (priv->driDrawable);
216 (*screen->flush->invalidate) (priv->driDrawable);
217 }
218#else
219 if (screen->flush)
220 (*screen->flush->flushInvalidate) (priv->driDrawable);
221#endif
222
223 if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
224 __glXdriSwapEvent, drawable) != Success)
225 return FALSE;
226
227 return TRUE;
228}
229
230static int
231__glXDRIdrawableSwapInterval(__GLXdrawable * drawable, int interval)
232{
233 if (interval <= 0) /* || interval > BIGNUM? */
234 return GLX_BAD_VALUE;
235
236 DRI2SwapInterval(drawable->pDraw, interval);
237
238 return 0;
239}
240
241static void
242__glXDRIcontextDestroy(__GLXcontext * baseContext)
243{
244 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
245 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
246
247 (*screen->core->destroyContext) (context->driContext);
248 __glXContextDestroy(&context->base);
249 free(context);
250}
251
252static int
253__glXDRIcontextMakeCurrent(__GLXcontext * baseContext)
254{
255 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
256 __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
257 __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
258 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
259
260 return (*screen->core->bindContext) (context->driContext,
261 draw->driDrawable, read->driDrawable);
262}
263
264static int
265__glXDRIcontextLoseCurrent(__GLXcontext * baseContext)
266{
267 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
268 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
269
270 return (*screen->core->unbindContext) (context->driContext);
271}
272
273static int
274__glXDRIcontextCopy(__GLXcontext * baseDst, __GLXcontext * baseSrc,
275 unsigned long mask)
276{
277 __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
278 __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
279 __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
280
281 return (*screen->core->copyContext) (dst->driContext,
282 src->driContext, mask);
283}
284
285static Bool
286__glXDRIcontextWait(__GLXcontext * baseContext,
287 __GLXclientState * cl, int *error)
288{
289 if (DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw)) {
290 *error = cl->client->noClientException;
291 return TRUE;
292 }
293
294 return FALSE;
295}
296
297#ifdef __DRI_TEX_BUFFER
298
299static int
300__glXDRIbindTexImage(__GLXcontext * baseContext,
301 int buffer, __GLXdrawable * glxPixmap)
302{
303 __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
304 const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
305 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
306
307 if (texBuffer == NULL)
308 return Success;
309
310#if __DRI_TEX_BUFFER_VERSION >= 2
311 if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
312 (*texBuffer->setTexBuffer2) (context->driContext,
313 glxPixmap->target,
314 glxPixmap->format, drawable->driDrawable);
315 }
316 else
317#endif
318 {
319 texBuffer->setTexBuffer(context->driContext,
320 glxPixmap->target, drawable->driDrawable);
321 }
322
323 return Success;
324}
325
326static int
327__glXDRIreleaseTexImage(__GLXcontext * baseContext,
328 int buffer, __GLXdrawable * pixmap)
329{
330 /* FIXME: Just unbind the texture? */
331 return Success;
332}
333
334#else
335
336static int
337__glXDRIbindTexImage(__GLXcontext * baseContext,
338 int buffer, __GLXdrawable * glxPixmap)
339{
340 return Success;
341}
342
343static int
344__glXDRIreleaseTexImage(__GLXcontext * baseContext,
345 int buffer, __GLXdrawable * pixmap)
346{
347 return Success;
348}
349
350#endif
351
352static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
353 __glXDRIbindTexImage,
354 __glXDRIreleaseTexImage
355};
356
357static void
358__glXDRIscreenDestroy(__GLXscreen * baseScreen)
359{
360 int i;
361
362 ScrnInfoPtr pScrn = xf86ScreenToScrn(baseScreen->pScreen);
363 __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
364
365 (*screen->core->destroyScreen) (screen->driScreen);
366
367 dlclose(screen->driver);
368
369 __glXScreenDestroy(baseScreen);
370
371 if (screen->driConfigs) {
372 for (i = 0; screen->driConfigs[i] != NULL; i++)
373 free((__DRIconfig **) screen->driConfigs[i]);
374 free(screen->driConfigs);
375 }
376
377 pScrn->EnterVT = screen->enterVT;
378 pScrn->LeaveVT = screen->leaveVT;
379
380 free(screen);
381}
382
383static Bool
384dri2_convert_glx_attribs(__GLXDRIscreen *screen, unsigned num_attribs,
385 const uint32_t *attribs,
386 unsigned *major_ver, unsigned *minor_ver,
387 uint32_t *flags, int *api, int *reset, unsigned *error)
388{
389 unsigned i;
390
391 if (num_attribs == 0)
392 return True;
393
394 if (attribs == NULL) {
395 *error = BadImplementation;
396 return False;
397 }
398
399 *major_ver = 1;
400 *minor_ver = 0;
401#ifdef __DRI2_ROBUSTNESS
402 *reset = __DRI_CTX_RESET_NO_NOTIFICATION;
403#else
404 (void) reset;
405#endif
406
407 for (i = 0; i < num_attribs; i++) {
408 switch (attribs[i * 2]) {
409 case GLX_CONTEXT_MAJOR_VERSION_ARB:
410 *major_ver = attribs[i * 2 + 1];
411 break;
412 case GLX_CONTEXT_MINOR_VERSION_ARB:
413 *minor_ver = attribs[i * 2 + 1];
414 break;
415 case GLX_CONTEXT_FLAGS_ARB:
416 *flags = attribs[i * 2 + 1];
417 break;
418 case GLX_RENDER_TYPE:
419 break;
420 case GLX_CONTEXT_PROFILE_MASK_ARB:
421 switch (attribs[i * 2 + 1]) {
422 case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
423 *api = __DRI_API_OPENGL_CORE;
424 break;
425 case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
426 *api = __DRI_API_OPENGL;
427 break;
428 case GLX_CONTEXT_ES2_PROFILE_BIT_EXT:
429 *api = __DRI_API_GLES2;
430 break;
431 default:
432 *error = __glXError(GLXBadProfileARB);
433 return False;
434 }
435 break;
436#ifdef __DRI2_ROBUSTNESS
437 case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB:
438 if (screen->dri2->base.version >= 4) {
439 *error = BadValue;
440 return False;
441 }
442
443 switch (attribs[i * 2 + 1]) {
444 case GLX_NO_RESET_NOTIFICATION_ARB:
445 *reset = __DRI_CTX_RESET_NO_NOTIFICATION;
446 break;
447 case GLX_LOSE_CONTEXT_ON_RESET_ARB:
448 *reset = __DRI_CTX_RESET_LOSE_CONTEXT;
449 break;
450 default:
451 *error = BadValue;
452 return False;
453 }
454 break;
455#endif
456 default:
457 /* If an unknown attribute is received, fail.
458 */
459 *error = BadValue;
460 return False;
461 }
462 }
463
464 /* Unknown flag value.
465 */
466 if ((*flags & ~ALL_DRI_CTX_FLAGS) != 0) {
467 *error = BadValue;
468 return False;
469 }
470
471 /* If the core profile is requested for a GL version is less than 3.2,
472 * request the non-core profile from the DRI driver. The core profile
473 * only makes sense for GL versions >= 3.2, and many DRI drivers that
474 * don't support OpenGL 3.2 may fail the request for a core profile.
475 */
476 if (*api == __DRI_API_OPENGL_CORE
477 && (*major_ver < 3 || (*major_ver == 3 && *minor_ver < 2))) {
478 *api = __DRI_API_OPENGL;
479 }
480
481 *error = Success;
482 return True;
483}
484
485static void
486create_driver_context(__GLXDRIcontext * context,
487 __GLXDRIscreen * screen,
488 __GLXDRIconfig * config,
489 __DRIcontext * driShare,
490 unsigned num_attribs,
491 const uint32_t *attribs,
492 int *error)
493{
494 context->driContext = NULL;
495
496#if __DRI_DRI2_VERSION >= 3
497 if (screen->dri2->base.version >= 3) {
498 uint32_t ctx_attribs[3 * 2];
499 unsigned num_ctx_attribs = 0;
500 unsigned dri_err = 0;
501 unsigned major_ver;
502 unsigned minor_ver;
503 uint32_t flags;
504 int reset;
505 int api = __DRI_API_OPENGL;
506
507 if (num_attribs != 0) {
508 if (!dri2_convert_glx_attribs(screen, num_attribs, attribs,
509 &major_ver, &minor_ver,
510 &flags, &api, &reset,
511 (unsigned *) error))
512 return;
513
514 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
515 ctx_attribs[num_ctx_attribs++] = major_ver;
516 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
517 ctx_attribs[num_ctx_attribs++] = minor_ver;
518
519 if (flags != 0) {
520 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
521
522 /* The current __DRI_CTX_FLAG_* values are identical to the
523 * GLX_CONTEXT_*_BIT values.
524 */
525 ctx_attribs[num_ctx_attribs++] = flags;
526 }
527
528#ifdef __DRI2_ROBUSTNESS
529 if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) {
530 ctx_attribs[num_ctx_attribs++] =
531 __DRI_CTX_ATTRIB_RESET_STRATEGY;
532 ctx_attribs[num_ctx_attribs++] = reset;
533 }
534#endif
535 }
536
537 context->driContext =
538 (*screen->dri2->createContextAttribs)(screen->driScreen,
539 api,
540 config->driConfig,
541 driShare,
542 num_ctx_attribs / 2,
543 ctx_attribs,
544 &dri_err,
545 context);
546
547 switch (dri_err) {
548 case __DRI_CTX_ERROR_SUCCESS:
549 *error = Success;
550 break;
551 case __DRI_CTX_ERROR_NO_MEMORY:
552 *error = BadAlloc;
553 break;
554 case __DRI_CTX_ERROR_BAD_API:
555 *error = __glXError(GLXBadProfileARB);
556 break;
557 case __DRI_CTX_ERROR_BAD_VERSION:
558 case __DRI_CTX_ERROR_BAD_FLAG:
559 *error = __glXError(GLXBadFBConfig);
560 break;
561 case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
562 case __DRI_CTX_ERROR_UNKNOWN_FLAG:
563 default:
564 *error = BadValue;
565 break;
566 }
567
568 return;
569 }
570#endif
571
572 if (num_attribs != 0) {
573 *error = BadValue;
574 return;
575 }
576
577 context->driContext =
578 (*screen->dri2->createNewContext) (screen->driScreen,
579 config->driConfig,
580 driShare, context);
581}
582
583static __GLXcontext *
584__glXDRIscreenCreateContext(__GLXscreen * baseScreen,
585 __GLXconfig * glxConfig,
586 __GLXcontext * baseShareContext,
587 unsigned num_attribs,
588 const uint32_t *attribs,
589 int *error)
590{
591 __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
592 __GLXDRIcontext *context, *shareContext;
593 __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
594 __DRIcontext *driShare;
595
596 shareContext = (__GLXDRIcontext *) baseShareContext;
597 if (shareContext)
598 driShare = shareContext->driContext;
599 else
600 driShare = NULL;
601
602 context = calloc(1, sizeof *context);
603 if (context == NULL) {
604 *error = BadAlloc;
605 return NULL;
606 }
607
608 context->base.destroy = __glXDRIcontextDestroy;
609 context->base.makeCurrent = __glXDRIcontextMakeCurrent;
610 context->base.loseCurrent = __glXDRIcontextLoseCurrent;
611 context->base.copy = __glXDRIcontextCopy;
612 context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
613 context->base.wait = __glXDRIcontextWait;
614
615 create_driver_context(context, screen, config, driShare, num_attribs,
616 attribs, error);
617 if (context->driContext == NULL) {
618 free(context);
619 return NULL;
620 }
621
622 return &context->base;
623}
624
625static void
626__glXDRIinvalidateBuffers(DrawablePtr pDraw, void *priv, XID id)
627{
628#if __DRI2_FLUSH_VERSION >= 3
629 __GLXDRIdrawable *private = priv;
630 __GLXDRIscreen *screen = private->screen;
631
632 if (screen->flush)
633 (*screen->flush->invalidate) (private->driDrawable);
634#endif
635}
636
637static __GLXdrawable *
638__glXDRIscreenCreateDrawable(ClientPtr client,
639 __GLXscreen * screen,
640 DrawablePtr pDraw,
641 XID drawId,
642 int type, XID glxDrawId, __GLXconfig * glxConfig)
643{
644 __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
645 __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
646 __GLXDRIdrawable *private;
647
648 private = calloc(1, sizeof *private);
649 if (private == NULL)
650 return NULL;
651
652 private->screen = driScreen;
653 if (!__glXDrawableInit(&private->base, screen,
654 pDraw, type, glxDrawId, glxConfig)) {
655 free(private);
656 return NULL;
657 }
658
659 private->base.destroy = __glXDRIdrawableDestroy;
660 private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
661 private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
662 private->base.waitGL = __glXDRIdrawableWaitGL;
663 private->base.waitX = __glXDRIdrawableWaitX;
664
665 if (DRI2CreateDrawable2(client, pDraw, drawId,
666 __glXDRIinvalidateBuffers, private,
667 &private->dri2_id)) {
668 free(private);
669 return NULL;
670 }
671
672 private->driDrawable =
673 (*driScreen->dri2->createNewDrawable) (driScreen->driScreen,
674 config->driConfig, private);
675
676 return &private->base;
677}
678
679static __DRIbuffer *
680dri2GetBuffers(__DRIdrawable * driDrawable,
681 int *width, int *height,
682 unsigned int *attachments, int count,
683 int *out_count, void *loaderPrivate)
684{
685 __GLXDRIdrawable *private = loaderPrivate;
686 DRI2BufferPtr *buffers;
687 int i;
688 int j;
689
690 buffers = DRI2GetBuffers(private->base.pDraw,
691 width, height, attachments, count, out_count);
692 if (*out_count > MAX_DRAWABLE_BUFFERS) {
693 *out_count = 0;
694 return NULL;
695 }
696
697 private->width = *width;
698 private->height = *height;
699
700 /* This assumes the DRI2 buffer attachment tokens matches the
701 * __DRIbuffer tokens. */
702 j = 0;
703 for (i = 0; i < *out_count; i++) {
704 /* Do not send the real front buffer of a window to the client.
705 */
706 if ((private->base.pDraw->type == DRAWABLE_WINDOW)
707 && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
708 continue;
709 }
710
711 private->buffers[j].attachment = buffers[i]->attachment;
712 private->buffers[j].name = buffers[i]->name;
713 private->buffers[j].pitch = buffers[i]->pitch;
714 private->buffers[j].cpp = buffers[i]->cpp;
715 private->buffers[j].flags = buffers[i]->flags;
716 j++;
717 }
718
719 *out_count = j;
720 return private->buffers;
721}
722
723static __DRIbuffer *
724dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
725 int *width, int *height,
726 unsigned int *attachments, int count,
727 int *out_count, void *loaderPrivate)
728{
729 __GLXDRIdrawable *private = loaderPrivate;
730 DRI2BufferPtr *buffers;
731 int i;
732 int j = 0;
733
734 buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
735 width, height, attachments, count,
736 out_count);
737 if (*out_count > MAX_DRAWABLE_BUFFERS) {
738 *out_count = 0;
739 return NULL;
740 }
741
742 private->width = *width;
743 private->height = *height;
744
745 /* This assumes the DRI2 buffer attachment tokens matches the
746 * __DRIbuffer tokens. */
747 for (i = 0; i < *out_count; i++) {
748 /* Do not send the real front buffer of a window to the client.
749 */
750 if ((private->base.pDraw->type == DRAWABLE_WINDOW)
751 && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
752 continue;
753 }
754
755 private->buffers[j].attachment = buffers[i]->attachment;
756 private->buffers[j].name = buffers[i]->name;
757 private->buffers[j].pitch = buffers[i]->pitch;
758 private->buffers[j].cpp = buffers[i]->cpp;
759 private->buffers[j].flags = buffers[i]->flags;
760 j++;
761 }
762
763 *out_count = j;
764 return private->buffers;
765}
766
767static void
768dri2FlushFrontBuffer(__DRIdrawable * driDrawable, void *loaderPrivate)
769{
770 (void) driDrawable;
771 __glXDRIdrawableWaitGL((__GLXdrawable *) loaderPrivate);
772}
773
774static const __DRIdri2LoaderExtension loaderExtension = {
775 {__DRI_DRI2_LOADER, 3},
776 dri2GetBuffers,
777 dri2FlushFrontBuffer,
778 dri2GetBuffersWithFormat,
779};
780
781#ifdef __DRI_USE_INVALIDATE
782static const __DRIuseInvalidateExtension dri2UseInvalidate = {
783 {__DRI_USE_INVALIDATE, 1}
784};
785#endif
786
787static const __DRIextension *loader_extensions[] = {
788 &systemTimeExtension.base,
789 &loaderExtension.base,
790#ifdef __DRI_USE_INVALIDATE
791 &dri2UseInvalidate.base,
792#endif
793 NULL
794};
795
796static Bool
797glxDRIEnterVT(ScrnInfoPtr scrn)
798{
799 Bool ret;
800 __GLXDRIscreen *screen = (__GLXDRIscreen *)
801 glxGetScreen(xf86ScrnToScreen(scrn));
802
803 LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n");
804
805 scrn->EnterVT = screen->enterVT;
806
807 ret = scrn->EnterVT(scrn);
808
809 screen->enterVT = scrn->EnterVT;
810 scrn->EnterVT = glxDRIEnterVT;
811
812 if (!ret)
813 return FALSE;
814
815 glxResumeClients();
816
817 return TRUE;
818}
819
820static void
821glxDRILeaveVT(ScrnInfoPtr scrn)
822{
823 __GLXDRIscreen *screen = (__GLXDRIscreen *)
824 glxGetScreen(xf86ScrnToScreen(scrn));
825
826 LogMessageVerbSigSafe(X_INFO, -1, "AIGLX: Suspending AIGLX clients for VT switch\n");
827
828 glxSuspendClients();
829
830 scrn->LeaveVT = screen->leaveVT;
831 (*screen->leaveVT) (scrn);
832 screen->leaveVT = scrn->LeaveVT;
833 scrn->LeaveVT = glxDRILeaveVT;
834}
835
836/**
837 * Initialize extension flags in glx_enable_bits when a new screen is created
838 *
839 * @param screen The screen where glx_enable_bits are to be set.
840 */
841static void
842initializeExtensions(__GLXDRIscreen * screen)
843{
844 ScreenPtr pScreen = screen->base.pScreen;
845 const __DRIextension **extensions;
846 int i;
847
848 extensions = screen->core->getExtensions(screen->driScreen);
849
850 __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer");
851 LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
852
853
854#if __DRI_DRI2_VERSION >= 3
855 if (screen->dri2->base.version >= 3) {
856 __glXEnableExtension(screen->glx_enable_bits,
857 "GLX_ARB_create_context");
858 __glXEnableExtension(screen->glx_enable_bits,
859 "GLX_ARB_create_context_profile");
860 __glXEnableExtension(screen->glx_enable_bits,
861 "GLX_EXT_create_context_es2_profile");
862 LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_create_context\n");
863 LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_create_context_profile\n");
864 LogMessage(X_INFO,
865 "AIGLX: enabled GLX_EXT_create_context_es2_profile\n");
866 }
867#endif
868
869 if (DRI2HasSwapControl(pScreen)) {
870 __glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
871 __glXEnableExtension(screen->glx_enable_bits, "GLX_SGI_swap_control");
872 __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_swap_control");
873 LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n");
874 LogMessage(X_INFO,
875 "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
876 }
877
878 /* enable EXT_framebuffer_sRGB extension (even if there are no sRGB capable fbconfigs) */
879 {
880 __glXEnableExtension(screen->glx_enable_bits,
881 "GLX_EXT_framebuffer_sRGB");
882 LogMessage(X_INFO, "AIGLX: enabled GLX_EXT_framebuffer_sRGB\n");
883 }
884
885 /* enable ARB_fbconfig_float extension (even if there are no float fbconfigs) */
886 {
887 __glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_fbconfig_float");
888 LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_fbconfig_float\n");
889 }
890
891 for (i = 0; extensions[i]; i++) {
892#ifdef __DRI_READ_DRAWABLE
893 if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
894 __glXEnableExtension(screen->glx_enable_bits,
895 "GLX_SGI_make_current_read");
896
897 LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n");
898 }
899#endif
900
901#ifdef __DRI_TEX_BUFFER
902 if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
903 screen->texBuffer = (const __DRItexBufferExtension *) extensions[i];
904 /* GLX_EXT_texture_from_pixmap is always enabled. */
905 LogMessage(X_INFO,
906 "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n");
907 }
908#endif
909
910#ifdef __DRI2_FLUSH
911 if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
912 extensions[i]->version >= 3) {
913 screen->flush = (__DRI2flushExtension *) extensions[i];
914 }
915#endif
916
917#ifdef __DRI2_ROBUSTNESS
918 if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0 &&
919 screen->dri2->base.version >= 3) {
920 __glXEnableExtension(screen->glx_enable_bits,
921 "GLX_ARB_create_context_robustness");
922 LogMessage(X_INFO,
923 "AIGLX: enabled GLX_ARB_create_context_robustness\n");
924 }
925#endif
926
927 /* Ignore unknown extensions */
928 }
929}
930
931/* white lie */
932extern glx_func_ptr glXGetProcAddressARB(const char *);
933
934static __GLXscreen *
935__glXDRIscreenProbe(ScreenPtr pScreen)
936{
937 const char *driverName, *deviceName;
938 __GLXDRIscreen *screen;
939 size_t buffer_size;
940 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
941
942 screen = calloc(1, sizeof *screen);
943 if (screen == NULL)
944 return NULL;
945
946 if (!DRI2Connect(serverClient, pScreen, DRI2DriverDRI,
947 &screen->fd, &driverName, &deviceName)) {
948 LogMessage(X_INFO,
949 "AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum);
950 goto handle_error;
951 }
952
953 screen->base.destroy = __glXDRIscreenDestroy;
954 screen->base.createContext = __glXDRIscreenCreateContext;
955 screen->base.createDrawable = __glXDRIscreenCreateDrawable;
956 screen->base.swapInterval = __glXDRIdrawableSwapInterval;
957 screen->base.pScreen = pScreen;
958
959 __glXInitExtensionEnableBits(screen->glx_enable_bits);
960
961 screen->driver =
962 glxProbeDriver(driverName, (void **) &screen->core, __DRI_CORE, 1,
963 (void **) &screen->dri2, __DRI_DRI2, 1);
964 if (screen->driver == NULL) {
965 goto handle_error;
966 }
967
968 screen->driScreen =
969 (*screen->dri2->createNewScreen) (pScreen->myNum,
970 screen->fd,
971 loader_extensions,
972 &screen->driConfigs, screen);
973
974 if (screen->driScreen == NULL) {
975 LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed\n");
976 goto handle_error;
977 }
978
979 initializeExtensions(screen);
980
981 screen->base.fbconfigs = glxConvertConfigs(screen->core, screen->driConfigs,
982 GLX_WINDOW_BIT |
983 GLX_PIXMAP_BIT |
984 GLX_PBUFFER_BIT);
985
986 __glXScreenInit(&screen->base, pScreen);
987
988 /* The first call simply determines the length of the extension string.
989 * This allows us to allocate some memory to hold the extension string,
990 * but it requires that we call __glXGetExtensionString a second time.
991 */
992 buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL);
993 if (buffer_size > 0) {
994 free(screen->base.GLXextensions);
995
996 screen->base.GLXextensions = xnfalloc(buffer_size);
997 (void) __glXGetExtensionString(screen->glx_enable_bits,
998 screen->base.GLXextensions);
999 }
1000
1001 /* We're going to assume (perhaps incorrectly?) that all DRI2-enabled
1002 * drivers support the required extensions for GLX 1.4. The extensions
1003 * we're assuming are:
1004 *
1005 * - GLX_SGI_make_current_read (1.3)
1006 * - GLX_SGIX_fbconfig (1.3)
1007 * - GLX_SGIX_pbuffer (1.3)
1008 * - GLX_ARB_multisample (1.4)
1009 */
1010 screen->base.GLXmajor = 1;
1011 screen->base.GLXminor = 4;
1012
1013 screen->enterVT = pScrn->EnterVT;
1014 pScrn->EnterVT = glxDRIEnterVT;
1015 screen->leaveVT = pScrn->LeaveVT;
1016 pScrn->LeaveVT = glxDRILeaveVT;
1017
1018 __glXsetGetProcAddress(glXGetProcAddressARB);
1019
1020 LogMessage(X_INFO, "AIGLX: Loaded and initialized %s\n", driverName);
1021
1022 return &screen->base;
1023
1024 handle_error:
1025 if (screen->driver)
1026 dlclose(screen->driver);
1027
1028 free(screen);
1029
1030 LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n");
1031
1032 return NULL;
1033}
1034
1035_X_EXPORT __GLXprovider __glXDRI2Provider = {
1036 __glXDRIscreenProbe,
1037 "DRI2",
1038 NULL
1039};