Imported Upstream version 1.15.1
[deb_xorg-server.git] / glx / glxdri2.c
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
54 typedef struct __GLXDRIscreen __GLXDRIscreen;
55 typedef struct __GLXDRIcontext __GLXDRIcontext;
56 typedef 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
67 struct __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
87 struct __GLXDRIcontext {
88 __GLXcontext base;
89 __DRIcontext *driContext;
90 };
91
92 #define MAX_DRAWABLE_BUFFERS 5
93
94 struct __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
107 static 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
122 static 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
140 static 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
157 static 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
174 static 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 */
206 static 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
230 static 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
241 static 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
252 static 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
264 static 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
273 static 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
285 static 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
299 static 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
326 static 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
336 static int
337 __glXDRIbindTexImage(__GLXcontext * baseContext,
338 int buffer, __GLXdrawable * glxPixmap)
339 {
340 return Success;
341 }
342
343 static int
344 __glXDRIreleaseTexImage(__GLXcontext * baseContext,
345 int buffer, __GLXdrawable * pixmap)
346 {
347 return Success;
348 }
349
350 #endif
351
352 static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
353 __glXDRIbindTexImage,
354 __glXDRIreleaseTexImage
355 };
356
357 static 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
383 static Bool
384 dri2_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
485 static void
486 create_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
583 static __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
625 static 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
637 static __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
679 static __DRIbuffer *
680 dri2GetBuffers(__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
723 static __DRIbuffer *
724 dri2GetBuffersWithFormat(__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
767 static void
768 dri2FlushFrontBuffer(__DRIdrawable * driDrawable, void *loaderPrivate)
769 {
770 (void) driDrawable;
771 __glXDRIdrawableWaitGL((__GLXdrawable *) loaderPrivate);
772 }
773
774 static const __DRIdri2LoaderExtension loaderExtension = {
775 {__DRI_DRI2_LOADER, 3},
776 dri2GetBuffers,
777 dri2FlushFrontBuffer,
778 dri2GetBuffersWithFormat,
779 };
780
781 #ifdef __DRI_USE_INVALIDATE
782 static const __DRIuseInvalidateExtension dri2UseInvalidate = {
783 {__DRI_USE_INVALIDATE, 1}
784 };
785 #endif
786
787 static const __DRIextension *loader_extensions[] = {
788 &systemTimeExtension.base,
789 &loaderExtension.base,
790 #ifdef __DRI_USE_INVALIDATE
791 &dri2UseInvalidate.base,
792 #endif
793 NULL
794 };
795
796 static Bool
797 glxDRIEnterVT(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
820 static void
821 glxDRILeaveVT(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 */
841 static void
842 initializeExtensions(__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 */
932 extern glx_func_ptr glXGetProcAddressARB(const char *);
933
934 static __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 };