Edit

IABSD.fr/xenocara/xserver/glx/glxdriswrast.c

Branch :

  • Show log

    Commit

  • Author : mpi
    Date : 2012-11-11 12:18:31
    Hash : 5675f61d
    Message : Try to load the gallium3d "swrastg" driver if available before falling back to the default mesa "swrast" one for software rendering. ok matthieu@

  • xserver/glx/glxdriswrast.c
  • /*
     * Copyright © 2008 George Sapountzis <gsap7@yahoo.gr>
     * Copyright © 2008 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 the
     * copyright holders not be used in advertising or publicity
     * pertaining to distribution of the software without specific,
     * written prior permission.  The copyright holders make no
     * representations about the suitability of this software for any
     * purpose.  It is provided "as is" without express or implied
     * warranty.
     *
     * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
     * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
     * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 <sys/time.h>
    #include <dlfcn.h>
    
    #include <GL/gl.h>
    #include <GL/internal/dri_interface.h>
    #include <GL/glxtokens.h>
    
    #include "scrnintstr.h"
    #include "pixmapstr.h"
    #include "gcstruct.h"
    #include "os.h"
    
    #include "glxserver.h"
    #include "glxutil.h"
    #include "glxdricommon.h"
    
    #include "glapitable.h"
    #include "glapi.h"
    #include "glthread.h"
    #include "dispatch.h"
    #include "extension_string.h"
    
    /* RTLD_LOCAL is not defined on Cygwin */
    #ifdef __CYGWIN__
    #ifndef RTLD_LOCAL
    #define RTLD_LOCAL 0
    #endif
    #endif
    
    typedef struct __GLXDRIscreen __GLXDRIscreen;
    typedef struct __GLXDRIcontext __GLXDRIcontext;
    typedef struct __GLXDRIdrawable __GLXDRIdrawable;
    
    struct __GLXDRIscreen {
        __GLXscreen base;
        __DRIscreen *driScreen;
        void *driver;
    
        const __DRIcoreExtension *core;
        const __DRIswrastExtension *swrast;
        const __DRIcopySubBufferExtension *copySubBuffer;
        const __DRItexBufferExtension *texBuffer;
        const __DRIconfig **driConfigs;
    };
    
    struct __GLXDRIcontext {
        __GLXcontext base;
        __DRIcontext *driContext;
    };
    
    struct __GLXDRIdrawable {
        __GLXdrawable base;
        __DRIdrawable *driDrawable;
        __GLXDRIscreen *screen;
    
        GCPtr gc;                   /* scratch GC for span drawing */
        GCPtr swapgc;               /* GC for swapping the color buffers */
    };
    
    static void
    __glXDRIdrawableDestroy(__GLXdrawable * drawable)
    {
        __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
        const __DRIcoreExtension *core = private->screen->core;
    
        (*core->destroyDrawable) (private->driDrawable);
    
        FreeGC(private->gc, (GContext) 0);
        FreeGC(private->swapgc, (GContext) 0);
    
        __glXDrawableRelease(drawable);
    
        free(private);
    }
    
    static GLboolean
    __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable * drawable)
    {
        __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
        const __DRIcoreExtension *core = private->screen->core;
    
        (*core->swapBuffers) (private->driDrawable);
    
        return TRUE;
    }
    
    static void
    __glXDRIdrawableCopySubBuffer(__GLXdrawable * basePrivate,
                                  int x, int y, int w, int h)
    {
        __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
        const __DRIcopySubBufferExtension *copySubBuffer =
            private->screen->copySubBuffer;
    
        if (copySubBuffer)
            (*copySubBuffer->copySubBuffer) (private->driDrawable, x, y, w, h);
    }
    
    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);
    }
    
    #ifdef __DRI_TEX_BUFFER
    
    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 __DRI_TEX_BUFFER_VERSION >= 2
        if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
            (*texBuffer->setTexBuffer2) (context->driContext,
                                         glxPixmap->target,
                                         glxPixmap->format, drawable->driDrawable);
        }
        else
    #endif
            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;
    }
    
    #else
    
    static int
    __glXDRIbindTexImage(__GLXcontext * baseContext,
                         int buffer, __GLXdrawable * glxPixmap)
    {
        return Success;
    }
    
    static int
    __glXDRIreleaseTexImage(__GLXcontext * baseContext,
                            int buffer, __GLXdrawable * pixmap)
    {
        return Success;
    }
    
    #endif
    
    static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
        __glXDRIbindTexImage,
        __glXDRIreleaseTexImage
    };
    
    static void
    __glXDRIscreenDestroy(__GLXscreen * baseScreen)
    {
        int i;
    
        __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);
        }
    
        free(screen);
    }
    
    static __GLXcontext *
    __glXDRIscreenCreateContext(__GLXscreen * baseScreen,
                                __GLXconfig * glxConfig,
                                __GLXcontext * baseShareContext)
    {
        __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
        __GLXDRIcontext *context, *shareContext;
        __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
        const __DRIcoreExtension *core = screen->core;
        __DRIcontext *driShare;
    
        shareContext = (__GLXDRIcontext *) baseShareContext;
        if (shareContext)
            driShare = shareContext->driContext;
        else
            driShare = NULL;
    
        context = calloc(1, sizeof *context);
        if (context == NULL)
            return NULL;
    
        context->base.destroy = __glXDRIcontextDestroy;
        context->base.makeCurrent = __glXDRIcontextMakeCurrent;
        context->base.loseCurrent = __glXDRIcontextLoseCurrent;
        context->base.copy = __glXDRIcontextCopy;
        context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
    
        context->driContext =
            (*core->createNewContext) (screen->driScreen,
                                       config->driConfig, driShare, context);
    
        return &context->base;
    }
    
    static __GLXdrawable *
    __glXDRIscreenCreateDrawable(ClientPtr client,
                                 __GLXscreen * screen,
                                 DrawablePtr pDraw,
                                 XID drawId,
                                 int type, XID glxDrawId, __GLXconfig * glxConfig)
    {
        XID gcvals[2];
        int status;
        __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
        __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
        __GLXDRIdrawable *private;
    
        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;
    
        gcvals[0] = GXcopy;
        private->gc =
            CreateGC(pDraw, GCFunction, gcvals, &status, (XID) 0, serverClient);
        gcvals[1] = FALSE;
        private->swapgc =
            CreateGC(pDraw, GCFunction | GCGraphicsExposures, gcvals, &status,
                     (XID) 0, serverClient);
    
        private->driDrawable =
            (*driScreen->swrast->createNewDrawable) (driScreen->driScreen,
                                                     config->driConfig, private);
    
        return &private->base;
    }
    
    static void
    swrastGetDrawableInfo(__DRIdrawable * draw,
                          int *x, int *y, int *w, int *h, void *loaderPrivate)
    {
        __GLXDRIdrawable *drawable = loaderPrivate;
        DrawablePtr pDraw = drawable->base.pDraw;
    
        *x = pDraw->x;
        *y = pDraw->x;
        *w = pDraw->width;
        *h = pDraw->height;
    }
    
    static void
    swrastPutImage(__DRIdrawable * draw, int op,
                   int x, int y, int w, int h, char *data, void *loaderPrivate)
    {
        __GLXDRIdrawable *drawable = loaderPrivate;
        DrawablePtr pDraw = drawable->base.pDraw;
        GCPtr gc;
    
        switch (op) {
        case __DRI_SWRAST_IMAGE_OP_DRAW:
            gc = drawable->gc;
            break;
        case __DRI_SWRAST_IMAGE_OP_SWAP:
            gc = drawable->swapgc;
            break;
        default:
            return;
        }
    
        ValidateGC(pDraw, gc);
    
        gc->ops->PutImage(pDraw, gc, pDraw->depth, x, y, w, h, 0, ZPixmap, data);
    }
    
    static void
    swrastGetImage(__DRIdrawable * draw,
                   int x, int y, int w, int h, char *data, void *loaderPrivate)
    {
        __GLXDRIdrawable *drawable = loaderPrivate;
        DrawablePtr pDraw = drawable->base.pDraw;
        ScreenPtr pScreen = pDraw->pScreen;
    
        pScreen->GetImage(pDraw, x, y, w, h, ZPixmap, ~0L, data);
    }
    
    static const __DRIswrastLoaderExtension swrastLoaderExtension = {
        {__DRI_SWRAST_LOADER, __DRI_SWRAST_LOADER_VERSION},
        swrastGetDrawableInfo,
        swrastPutImage,
        swrastGetImage
    };
    
    static const __DRIextension *loader_extensions[] = {
        &systemTimeExtension.base,
        &swrastLoaderExtension.base,
        NULL
    };
    
    static void
    initializeExtensions(__GLXDRIscreen * screen)
    {
        const __DRIextension **extensions;
        int i;
    
        extensions = screen->core->getExtensions(screen->driScreen);
    
        for (i = 0; extensions[i]; i++) {
    #ifdef __DRI_COPY_SUB_BUFFER
            if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
                screen->copySubBuffer =
                    (const __DRIcopySubBufferExtension *) extensions[i];
                /* GLX_MESA_copy_sub_buffer is always enabled. */
            }
    #endif
    
    #ifdef __DRI_TEX_BUFFER
            if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
                screen->texBuffer = (const __DRItexBufferExtension *) extensions[i];
                /* GLX_EXT_texture_from_pixmap is always enabled. */
            }
    #endif
            /* Ignore unknown extensions */
        }
    }
    
    static __GLXscreen *
    __glXDRIscreenProbe(ScreenPtr pScreen)
    {
        const char *driverName = "swrastg";
        __GLXDRIscreen *screen;
    
        screen = calloc(1, sizeof *screen);
        if (screen == NULL)
            return NULL;
    
        screen->base.destroy = __glXDRIscreenDestroy;
        screen->base.createContext = __glXDRIscreenCreateContext;
        screen->base.createDrawable = __glXDRIscreenCreateDrawable;
        screen->base.swapInterval = NULL;
        screen->base.pScreen = pScreen;
    
        screen->driver = glxProbeDriver(driverName,
                                        (void **) &screen->core,
                                        __DRI_CORE, __DRI_CORE_VERSION,
                                        (void **) &screen->swrast,
                                        __DRI_SWRAST, __DRI_SWRAST_VERSION);
    
        if (screen->driver == NULL) {
        	    driverName = "swrast";
    	    screen->driver = glxProbeDriver(driverName,
    					    (void **) &screen->core,
    					    __DRI_CORE, __DRI_CORE_VERSION,
    					    (void **) &screen->swrast,
    					    __DRI_SWRAST, __DRI_SWRAST_VERSION);
        }
    
        if (screen->driver == NULL) {
            goto handle_error;
        }
    
        screen->driScreen =
            (*screen->swrast->createNewScreen) (pScreen->myNum,
                                                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);
    
        screen->base.GLXmajor = 1;
        screen->base.GLXminor = 4;
    
        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, "GLX: could not load software renderer\n");
    
        return NULL;
    }
    
    _X_EXPORT __GLXprovider __glXDRISWRastProvider = {
        __glXDRIscreenProbe,
        "DRISWRAST",
        NULL
    };