123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035 |
- /*
- * Copyright © 2007 Red Hat, Inc
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without
- * fee, provided that the above copyright notice appear in all copies
- * and that both that copyright notice and this permission notice
- * appear in supporting documentation, and that the name of Red Hat,
- * Inc not be used in advertising or publicity pertaining to
- * distribution of the software without specific, written prior
- * permission. Red Hat, Inc makes no representations about the
- * suitability of this software for any purpose. It is provided "as
- * is" without express or implied warranty.
- *
- * RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
- * NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include <stdint.h>
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <dlfcn.h>
- #include <drm.h>
- #include <GL/gl.h>
- #include <GL/internal/dri_interface.h>
- #include <GL/glxtokens.h>
- #include <windowstr.h>
- #include <os.h>
- #define _XF86DRI_SERVER_
- #include <xf86drm.h>
- #include <xf86.h>
- #include <dri2.h>
- #include "glxserver.h"
- #include "glxutil.h"
- #include "glxdricommon.h"
- #include <GL/glxtokens.h>
- #include "extension_string.h"
- typedef struct __GLXDRIscreen __GLXDRIscreen;
- typedef struct __GLXDRIcontext __GLXDRIcontext;
- typedef struct __GLXDRIdrawable __GLXDRIdrawable;
- #define ALL_DRI_CTX_FLAGS (__DRI_CTX_FLAG_DEBUG \
- | __DRI_CTX_FLAG_FORWARD_COMPATIBLE \
- | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS)
- struct __GLXDRIscreen {
- __GLXscreen base;
- __DRIscreen *driScreen;
- void *driver;
- int fd;
- xf86EnterVTProc *enterVT;
- xf86LeaveVTProc *leaveVT;
- const __DRIcoreExtension *core;
- const __DRIdri2Extension *dri2;
- const __DRI2flushExtension *flush;
- const __DRIcopySubBufferExtension *copySubBuffer;
- const __DRIswapControlExtension *swapControl;
- const __DRItexBufferExtension *texBuffer;
- const __DRIconfig **driConfigs;
- unsigned char glx_enable_bits[__GLX_EXT_BYTES];
- };
- struct __GLXDRIcontext {
- __GLXcontext base;
- __DRIcontext *driContext;
- };
- #define MAX_DRAWABLE_BUFFERS 5
- struct __GLXDRIdrawable {
- __GLXdrawable base;
- __DRIdrawable *driDrawable;
- __GLXDRIscreen *screen;
- /* Dimensions as last reported by DRI2GetBuffers. */
- int width;
- int height;
- __DRIbuffer buffers[MAX_DRAWABLE_BUFFERS];
- int count;
- XID dri2_id;
- };
- static void
- __glXDRIdrawableDestroy(__GLXdrawable * drawable)
- {
- __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
- const __DRIcoreExtension *core = private->screen->core;
- FreeResource(private->dri2_id, FALSE);
- (*core->destroyDrawable) (private->driDrawable);
- __glXDrawableRelease(drawable);
- free(private);
- }
- static void
- copy_box(__GLXdrawable * drawable,
- int dst, int src,
- int x, int y, int w, int h)
- {
- BoxRec box;
- RegionRec region;
- __GLXcontext *cx = lastGLContext;
- box.x1 = x;
- box.y1 = y;
- box.x2 = x + w;
- box.y2 = y + h;
- RegionInit(®ion, &box, 0);
- DRI2CopyRegion(drawable->pDraw, ®ion, dst, src);
- if (cx != lastGLContext) {
- lastGLContext = cx;
- cx->makeCurrent(cx);
- }
- }
- static void
- __glXDRIdrawableCopySubBuffer(__GLXdrawable * drawable,
- int x, int y, int w, int h)
- {
- __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
- copy_box(drawable, x, private->height - y - h,
- w, h,
- DRI2BufferFrontLeft, DRI2BufferBackLeft);
- }
- static void
- __glXDRIdrawableWaitX(__GLXdrawable * drawable)
- {
- __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
- copy_box(drawable, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft,
- 0, 0, private->width, private->height);
- }
- static void
- __glXDRIdrawableWaitGL(__GLXdrawable * drawable)
- {
- __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
- copy_box(drawable, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft,
- 0, 0, private->width, private->height);
- }
- static void
- __glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
- CARD64 msc, CARD32 sbc)
- {
- __GLXdrawable *drawable = data;
- int glx_type;
- switch (type) {
- case DRI2_EXCHANGE_COMPLETE:
- glx_type = GLX_EXCHANGE_COMPLETE_INTEL;
- break;
- default:
- /* unknown swap completion type,
- * BLIT is a reasonable default, so
- * fall through ...
- */
- case DRI2_BLIT_COMPLETE:
- glx_type = GLX_BLIT_COMPLETE_INTEL;
- break;
- case DRI2_FLIP_COMPLETE:
- glx_type = GLX_FLIP_COMPLETE_INTEL;
- break;
- }
-
- __glXsendSwapEvent(drawable, glx_type, ust, msc, sbc);
- }
- /*
- * Copy or flip back to front, honoring the swap interval if possible.
- *
- * If the kernel supports it, we request an event for the frame when the
- * swap should happen, then perform the copy when we receive it.
- */
- static GLboolean
- __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable * drawable)
- {
- __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
- __GLXDRIscreen *screen = priv->screen;
- CARD64 unused;
- __GLXcontext *cx = lastGLContext;
- int status;
- if (screen->flush) {
- (*screen->flush->flush) (priv->driDrawable);
- (*screen->flush->invalidate) (priv->driDrawable);
- }
- status = DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
- __glXdriSwapEvent, drawable);
- if (cx != lastGLContext) {
- lastGLContext = cx;
- cx->makeCurrent(cx);
- }
- return status == Success;
- }
- static int
- __glXDRIdrawableSwapInterval(__GLXdrawable * drawable, int interval)
- {
- __GLXcontext *cx = lastGLContext;
- if (interval <= 0) /* || interval > BIGNUM? */
- return GLX_BAD_VALUE;
- DRI2SwapInterval(drawable->pDraw, interval);
- if (cx != lastGLContext) {
- lastGLContext = cx;
- cx->makeCurrent(cx);
- }
- return 0;
- }
- static void
- __glXDRIcontextDestroy(__GLXcontext * baseContext)
- {
- __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
- __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
- (*screen->core->destroyContext) (context->driContext);
- __glXContextDestroy(&context->base);
- free(context);
- }
- static int
- __glXDRIcontextMakeCurrent(__GLXcontext * baseContext)
- {
- __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
- __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
- __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
- __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
- return (*screen->core->bindContext) (context->driContext,
- draw->driDrawable, read->driDrawable);
- }
- static int
- __glXDRIcontextLoseCurrent(__GLXcontext * baseContext)
- {
- __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
- __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
- return (*screen->core->unbindContext) (context->driContext);
- }
- static int
- __glXDRIcontextCopy(__GLXcontext * baseDst, __GLXcontext * baseSrc,
- unsigned long mask)
- {
- __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
- __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
- __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
- return (*screen->core->copyContext) (dst->driContext,
- src->driContext, mask);
- }
- static Bool
- __glXDRIcontextWait(__GLXcontext * baseContext,
- __GLXclientState * cl, int *error)
- {
- __GLXcontext *cx = lastGLContext;
- Bool ret;
- ret = DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw);
- if (cx != lastGLContext) {
- lastGLContext = cx;
- cx->makeCurrent(cx);
- }
- if (ret) {
- *error = cl->client->noClientException;
- return TRUE;
- }
- return FALSE;
- }
- static int
- __glXDRIbindTexImage(__GLXcontext * baseContext,
- int buffer, __GLXdrawable * glxPixmap)
- {
- __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
- const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
- __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
- if (texBuffer == NULL)
- return Success;
- if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
- (*texBuffer->setTexBuffer2) (context->driContext,
- glxPixmap->target,
- glxPixmap->format, drawable->driDrawable);
- }
- else
- {
- texBuffer->setTexBuffer(context->driContext,
- glxPixmap->target, drawable->driDrawable);
- }
- return Success;
- }
- static int
- __glXDRIreleaseTexImage(__GLXcontext * baseContext,
- int buffer, __GLXdrawable * pixmap)
- {
- /* FIXME: Just unbind the texture? */
- return Success;
- }
- static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
- __glXDRIbindTexImage,
- __glXDRIreleaseTexImage
- };
- static void
- __glXDRIscreenDestroy(__GLXscreen * baseScreen)
- {
- int i;
- ScrnInfoPtr pScrn = xf86ScreenToScrn(baseScreen->pScreen);
- __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
- (*screen->core->destroyScreen) (screen->driScreen);
- dlclose(screen->driver);
- __glXScreenDestroy(baseScreen);
- if (screen->driConfigs) {
- for (i = 0; screen->driConfigs[i] != NULL; i++)
- free((__DRIconfig **) screen->driConfigs[i]);
- free(screen->driConfigs);
- }
- pScrn->EnterVT = screen->enterVT;
- pScrn->LeaveVT = screen->leaveVT;
- free(screen);
- }
- static Bool
- dri2_convert_glx_attribs(__GLXDRIscreen *screen, unsigned num_attribs,
- const uint32_t *attribs,
- unsigned *major_ver, unsigned *minor_ver,
- uint32_t *flags, int *api, int *reset, unsigned *error)
- {
- unsigned i;
- if (num_attribs == 0)
- return True;
- if (attribs == NULL) {
- *error = BadImplementation;
- return False;
- }
- *major_ver = 1;
- *minor_ver = 0;
- *reset = __DRI_CTX_RESET_NO_NOTIFICATION;
- for (i = 0; i < num_attribs; i++) {
- switch (attribs[i * 2]) {
- case GLX_CONTEXT_MAJOR_VERSION_ARB:
- *major_ver = attribs[i * 2 + 1];
- break;
- case GLX_CONTEXT_MINOR_VERSION_ARB:
- *minor_ver = attribs[i * 2 + 1];
- break;
- case GLX_CONTEXT_FLAGS_ARB:
- *flags = attribs[i * 2 + 1];
- break;
- case GLX_RENDER_TYPE:
- break;
- case GLX_CONTEXT_PROFILE_MASK_ARB:
- switch (attribs[i * 2 + 1]) {
- case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
- *api = __DRI_API_OPENGL_CORE;
- break;
- case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
- *api = __DRI_API_OPENGL;
- break;
- case GLX_CONTEXT_ES2_PROFILE_BIT_EXT:
- *api = __DRI_API_GLES2;
- break;
- default:
- *error = __glXError(GLXBadProfileARB);
- return False;
- }
- break;
- case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB:
- if (screen->dri2->base.version >= 4) {
- *error = BadValue;
- return False;
- }
- switch (attribs[i * 2 + 1]) {
- case GLX_NO_RESET_NOTIFICATION_ARB:
- *reset = __DRI_CTX_RESET_NO_NOTIFICATION;
- break;
- case GLX_LOSE_CONTEXT_ON_RESET_ARB:
- *reset = __DRI_CTX_RESET_LOSE_CONTEXT;
- break;
- default:
- *error = BadValue;
- return False;
- }
- break;
- default:
- /* If an unknown attribute is received, fail.
- */
- *error = BadValue;
- return False;
- }
- }
- /* Unknown flag value.
- */
- if ((*flags & ~ALL_DRI_CTX_FLAGS) != 0) {
- *error = BadValue;
- return False;
- }
- /* If the core profile is requested for a GL version is less than 3.2,
- * request the non-core profile from the DRI driver. The core profile
- * only makes sense for GL versions >= 3.2, and many DRI drivers that
- * don't support OpenGL 3.2 may fail the request for a core profile.
- */
- if (*api == __DRI_API_OPENGL_CORE
- && (*major_ver < 3 || (*major_ver == 3 && *minor_ver < 2))) {
- *api = __DRI_API_OPENGL;
- }
- *error = Success;
- return True;
- }
- static void
- create_driver_context(__GLXDRIcontext * context,
- __GLXDRIscreen * screen,
- __GLXDRIconfig * config,
- __DRIcontext * driShare,
- unsigned num_attribs,
- const uint32_t *attribs,
- int *error)
- {
- context->driContext = NULL;
- if (screen->dri2->base.version >= 3) {
- uint32_t ctx_attribs[3 * 2];
- unsigned num_ctx_attribs = 0;
- unsigned dri_err = 0;
- unsigned major_ver;
- unsigned minor_ver;
- uint32_t flags = 0;
- int reset;
- int api = __DRI_API_OPENGL;
- if (num_attribs != 0) {
- if (!dri2_convert_glx_attribs(screen, num_attribs, attribs,
- &major_ver, &minor_ver,
- &flags, &api, &reset,
- (unsigned *) error))
- return;
- ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
- ctx_attribs[num_ctx_attribs++] = major_ver;
- ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
- ctx_attribs[num_ctx_attribs++] = minor_ver;
- if (flags != 0) {
- ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
- /* The current __DRI_CTX_FLAG_* values are identical to the
- * GLX_CONTEXT_*_BIT values.
- */
- ctx_attribs[num_ctx_attribs++] = flags;
- }
- if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) {
- ctx_attribs[num_ctx_attribs++] =
- __DRI_CTX_ATTRIB_RESET_STRATEGY;
- ctx_attribs[num_ctx_attribs++] = reset;
- }
- }
- context->driContext =
- (*screen->dri2->createContextAttribs)(screen->driScreen,
- api,
- config->driConfig,
- driShare,
- num_ctx_attribs / 2,
- ctx_attribs,
- &dri_err,
- context);
- switch (dri_err) {
- case __DRI_CTX_ERROR_SUCCESS:
- *error = Success;
- break;
- case __DRI_CTX_ERROR_NO_MEMORY:
- *error = BadAlloc;
- break;
- case __DRI_CTX_ERROR_BAD_API:
- *error = __glXError(GLXBadProfileARB);
- break;
- case __DRI_CTX_ERROR_BAD_VERSION:
- case __DRI_CTX_ERROR_BAD_FLAG:
- *error = __glXError(GLXBadFBConfig);
- break;
- case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
- case __DRI_CTX_ERROR_UNKNOWN_FLAG:
- default:
- *error = BadValue;
- break;
- }
- return;
- }
- if (num_attribs != 0) {
- *error = BadValue;
- return;
- }
- context->driContext =
- (*screen->dri2->createNewContext) (screen->driScreen,
- config->driConfig,
- driShare, context);
- }
- static __GLXcontext *
- __glXDRIscreenCreateContext(__GLXscreen * baseScreen,
- __GLXconfig * glxConfig,
- __GLXcontext * baseShareContext,
- unsigned num_attribs,
- const uint32_t *attribs,
- int *error)
- {
- __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
- __GLXDRIcontext *context, *shareContext;
- __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
- __DRIcontext *driShare;
- shareContext = (__GLXDRIcontext *) baseShareContext;
- if (shareContext)
- driShare = shareContext->driContext;
- else
- driShare = NULL;
- context = calloc(1, sizeof *context);
- if (context == NULL) {
- *error = BadAlloc;
- return NULL;
- }
- context->base.destroy = __glXDRIcontextDestroy;
- context->base.makeCurrent = __glXDRIcontextMakeCurrent;
- context->base.loseCurrent = __glXDRIcontextLoseCurrent;
- context->base.copy = __glXDRIcontextCopy;
- context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
- context->base.wait = __glXDRIcontextWait;
- create_driver_context(context, screen, config, driShare, num_attribs,
- attribs, error);
- if (context->driContext == NULL) {
- free(context);
- return NULL;
- }
- return &context->base;
- }
- static void
- __glXDRIinvalidateBuffers(DrawablePtr pDraw, void *priv, XID id)
- {
- __GLXDRIdrawable *private = priv;
- __GLXDRIscreen *screen = private->screen;
- if (screen->flush)
- (*screen->flush->invalidate) (private->driDrawable);
- }
- static __GLXdrawable *
- __glXDRIscreenCreateDrawable(ClientPtr client,
- __GLXscreen * screen,
- DrawablePtr pDraw,
- XID drawId,
- int type, XID glxDrawId, __GLXconfig * glxConfig)
- {
- __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
- __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
- __GLXDRIdrawable *private;
- __GLXcontext *cx = lastGLContext;
- Bool ret;
- private = calloc(1, sizeof *private);
- if (private == NULL)
- return NULL;
- private->screen = driScreen;
- if (!__glXDrawableInit(&private->base, screen,
- pDraw, type, glxDrawId, glxConfig)) {
- free(private);
- return NULL;
- }
- private->base.destroy = __glXDRIdrawableDestroy;
- private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
- private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
- private->base.waitGL = __glXDRIdrawableWaitGL;
- private->base.waitX = __glXDRIdrawableWaitX;
- ret = DRI2CreateDrawable2(client, pDraw, drawId,
- __glXDRIinvalidateBuffers, private,
- &private->dri2_id);
- if (cx != lastGLContext) {
- lastGLContext = cx;
- cx->makeCurrent(cx);
- }
- if (ret) {
- free(private);
- return NULL;
- }
- private->driDrawable =
- (*driScreen->dri2->createNewDrawable) (driScreen->driScreen,
- config->driConfig, private);
- return &private->base;
- }
- static __DRIbuffer *
- dri2GetBuffers(__DRIdrawable * driDrawable,
- int *width, int *height,
- unsigned int *attachments, int count,
- int *out_count, void *loaderPrivate)
- {
- __GLXDRIdrawable *private = loaderPrivate;
- DRI2BufferPtr *buffers;
- int i;
- int j;
- __GLXcontext *cx = lastGLContext;
- buffers = DRI2GetBuffers(private->base.pDraw,
- width, height, attachments, count, out_count);
- if (cx != lastGLContext) {
- lastGLContext = cx;
- cx->makeCurrent(cx);
- /* If DRI2GetBuffers() changed the GL context, it may also have
- * invalidated the DRI2 buffers, so let's get them again
- */
- buffers = DRI2GetBuffers(private->base.pDraw,
- width, height, attachments, count, out_count);
- assert(lastGLContext == cx);
- }
- if (*out_count > MAX_DRAWABLE_BUFFERS) {
- *out_count = 0;
- return NULL;
- }
- private->width = *width;
- private->height = *height;
- /* This assumes the DRI2 buffer attachment tokens matches the
- * __DRIbuffer tokens. */
- j = 0;
- for (i = 0; i < *out_count; i++) {
- /* Do not send the real front buffer of a window to the client.
- */
- if ((private->base.pDraw->type == DRAWABLE_WINDOW)
- && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
- continue;
- }
- private->buffers[j].attachment = buffers[i]->attachment;
- private->buffers[j].name = buffers[i]->name;
- private->buffers[j].pitch = buffers[i]->pitch;
- private->buffers[j].cpp = buffers[i]->cpp;
- private->buffers[j].flags = buffers[i]->flags;
- j++;
- }
- *out_count = j;
- return private->buffers;
- }
- static __DRIbuffer *
- dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
- int *width, int *height,
- unsigned int *attachments, int count,
- int *out_count, void *loaderPrivate)
- {
- __GLXDRIdrawable *private = loaderPrivate;
- DRI2BufferPtr *buffers;
- int i;
- int j = 0;
- __GLXcontext *cx = lastGLContext;
- buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
- width, height, attachments, count,
- out_count);
- if (cx != lastGLContext) {
- lastGLContext = cx;
- cx->makeCurrent(cx);
- /* If DRI2GetBuffersWithFormat() changed the GL context, it may also have
- * invalidated the DRI2 buffers, so let's get them again
- */
- buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
- width, height, attachments, count,
- out_count);
- assert(lastGLContext == cx);
- }
- if (*out_count > MAX_DRAWABLE_BUFFERS) {
- *out_count = 0;
- return NULL;
- }
- private->width = *width;
- private->height = *height;
- /* This assumes the DRI2 buffer attachment tokens matches the
- * __DRIbuffer tokens. */
- for (i = 0; i < *out_count; i++) {
- /* Do not send the real front buffer of a window to the client.
- */
- if ((private->base.pDraw->type == DRAWABLE_WINDOW)
- && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
- continue;
- }
- private->buffers[j].attachment = buffers[i]->attachment;
- private->buffers[j].name = buffers[i]->name;
- private->buffers[j].pitch = buffers[i]->pitch;
- private->buffers[j].cpp = buffers[i]->cpp;
- private->buffers[j].flags = buffers[i]->flags;
- j++;
- }
- *out_count = j;
- return private->buffers;
- }
- static void
- dri2FlushFrontBuffer(__DRIdrawable * driDrawable, void *loaderPrivate)
- {
- (void) driDrawable;
- __glXDRIdrawableWaitGL((__GLXdrawable *) loaderPrivate);
- }
- static const __DRIdri2LoaderExtension loaderExtension = {
- {__DRI_DRI2_LOADER, 3},
- dri2GetBuffers,
- dri2FlushFrontBuffer,
- dri2GetBuffersWithFormat,
- };
- static const __DRIuseInvalidateExtension dri2UseInvalidate = {
- {__DRI_USE_INVALIDATE, 1}
- };
- static const __DRIextension *loader_extensions[] = {
- &systemTimeExtension.base,
- &loaderExtension.base,
- &dri2UseInvalidate.base,
- NULL
- };
- static Bool
- glxDRIEnterVT(ScrnInfoPtr scrn)
- {
- Bool ret;
- __GLXDRIscreen *screen = (__GLXDRIscreen *)
- glxGetScreen(xf86ScrnToScreen(scrn));
- LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n");
- scrn->EnterVT = screen->enterVT;
- ret = scrn->EnterVT(scrn);
- screen->enterVT = scrn->EnterVT;
- scrn->EnterVT = glxDRIEnterVT;
- if (!ret)
- return FALSE;
- glxResumeClients();
- return TRUE;
- }
- static void
- glxDRILeaveVT(ScrnInfoPtr scrn)
- {
- __GLXDRIscreen *screen = (__GLXDRIscreen *)
- glxGetScreen(xf86ScrnToScreen(scrn));
- LogMessageVerbSigSafe(X_INFO, -1, "AIGLX: Suspending AIGLX clients for VT switch\n");
- glxSuspendClients();
- scrn->LeaveVT = screen->leaveVT;
- (*screen->leaveVT) (scrn);
- screen->leaveVT = scrn->LeaveVT;
- scrn->LeaveVT = glxDRILeaveVT;
- }
- /**
- * Initialize extension flags in glx_enable_bits when a new screen is created
- *
- * @param screen The screen where glx_enable_bits are to be set.
- */
- static void
- initializeExtensions(__GLXDRIscreen * screen)
- {
- ScreenPtr pScreen = screen->base.pScreen;
- const __DRIextension **extensions;
- int i;
- extensions = screen->core->getExtensions(screen->driScreen);
- __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer");
- LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
- if (screen->dri2->base.version >= 3) {
- __glXEnableExtension(screen->glx_enable_bits,
- "GLX_ARB_create_context");
- __glXEnableExtension(screen->glx_enable_bits,
- "GLX_ARB_create_context_profile");
- __glXEnableExtension(screen->glx_enable_bits,
- "GLX_EXT_create_context_es2_profile");
- LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_create_context\n");
- LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_create_context_profile\n");
- LogMessage(X_INFO,
- "AIGLX: enabled GLX_EXT_create_context_es2_profile\n");
- }
- if (DRI2HasSwapControl(pScreen)) {
- __glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
- __glXEnableExtension(screen->glx_enable_bits, "GLX_SGI_swap_control");
- __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_swap_control");
- LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n");
- LogMessage(X_INFO,
- "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
- }
- /* enable EXT_framebuffer_sRGB extension (even if there are no sRGB capable fbconfigs) */
- {
- __glXEnableExtension(screen->glx_enable_bits,
- "GLX_EXT_framebuffer_sRGB");
- LogMessage(X_INFO, "AIGLX: enabled GLX_EXT_framebuffer_sRGB\n");
- }
- /* enable ARB_fbconfig_float extension (even if there are no float fbconfigs) */
- {
- __glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_fbconfig_float");
- LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_fbconfig_float\n");
- }
- for (i = 0; extensions[i]; i++) {
- if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
- __glXEnableExtension(screen->glx_enable_bits,
- "GLX_SGI_make_current_read");
- LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n");
- }
- if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
- screen->texBuffer = (const __DRItexBufferExtension *) extensions[i];
- /* GLX_EXT_texture_from_pixmap is always enabled. */
- LogMessage(X_INFO,
- "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n");
- }
- if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
- extensions[i]->version >= 3) {
- screen->flush = (__DRI2flushExtension *) extensions[i];
- }
- if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0 &&
- screen->dri2->base.version >= 3) {
- __glXEnableExtension(screen->glx_enable_bits,
- "GLX_ARB_create_context_robustness");
- LogMessage(X_INFO,
- "AIGLX: enabled GLX_ARB_create_context_robustness\n");
- }
- /* Ignore unknown extensions */
- }
- }
- /* white lie */
- extern glx_func_ptr glXGetProcAddressARB(const char *);
- static __GLXscreen *
- __glXDRIscreenProbe(ScreenPtr pScreen)
- {
- const char *driverName, *deviceName;
- __GLXDRIscreen *screen;
- size_t buffer_size;
- ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
- screen = calloc(1, sizeof *screen);
- if (screen == NULL)
- return NULL;
- if (!DRI2Connect(serverClient, pScreen, DRI2DriverDRI,
- &screen->fd, &driverName, &deviceName)) {
- LogMessage(X_INFO,
- "AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum);
- goto handle_error;
- }
- screen->base.destroy = __glXDRIscreenDestroy;
- screen->base.createContext = __glXDRIscreenCreateContext;
- screen->base.createDrawable = __glXDRIscreenCreateDrawable;
- screen->base.swapInterval = __glXDRIdrawableSwapInterval;
- screen->base.pScreen = pScreen;
- __glXInitExtensionEnableBits(screen->glx_enable_bits);
- screen->driver =
- glxProbeDriver(driverName, (void **) &screen->core, __DRI_CORE, 1,
- (void **) &screen->dri2, __DRI_DRI2, 1);
- if (screen->driver == NULL) {
- goto handle_error;
- }
- screen->driScreen =
- (*screen->dri2->createNewScreen) (pScreen->myNum,
- screen->fd,
- loader_extensions,
- &screen->driConfigs, screen);
- if (screen->driScreen == NULL) {
- LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed\n");
- goto handle_error;
- }
- initializeExtensions(screen);
- screen->base.fbconfigs = glxConvertConfigs(screen->core, screen->driConfigs,
- GLX_WINDOW_BIT |
- GLX_PIXMAP_BIT |
- GLX_PBUFFER_BIT);
- __glXScreenInit(&screen->base, pScreen);
- /* The first call simply determines the length of the extension string.
- * This allows us to allocate some memory to hold the extension string,
- * but it requires that we call __glXGetExtensionString a second time.
- */
- buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL);
- if (buffer_size > 0) {
- free(screen->base.GLXextensions);
- screen->base.GLXextensions = xnfalloc(buffer_size);
- (void) __glXGetExtensionString(screen->glx_enable_bits,
- screen->base.GLXextensions);
- }
- /* We're going to assume (perhaps incorrectly?) that all DRI2-enabled
- * drivers support the required extensions for GLX 1.4. The extensions
- * we're assuming are:
- *
- * - GLX_SGI_make_current_read (1.3)
- * - GLX_SGIX_fbconfig (1.3)
- * - GLX_SGIX_pbuffer (1.3)
- * - GLX_ARB_multisample (1.4)
- */
- screen->base.GLXmajor = 1;
- screen->base.GLXminor = 4;
- screen->enterVT = pScrn->EnterVT;
- pScrn->EnterVT = glxDRIEnterVT;
- screen->leaveVT = pScrn->LeaveVT;
- pScrn->LeaveVT = glxDRILeaveVT;
- __glXsetGetProcAddress(glXGetProcAddressARB);
- LogMessage(X_INFO, "AIGLX: Loaded and initialized %s\n", driverName);
- return &screen->base;
- handle_error:
- if (screen->driver)
- dlclose(screen->driver);
- free(screen);
- LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n");
- return NULL;
- }
- _X_EXPORT __GLXprovider __glXDRI2Provider = {
- __glXDRIscreenProbe,
- "DRI2",
- NULL
- };
|