diff options
author | Kristian Høgsberg <krh@redhat.com> | 2008-05-21 13:33:36 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@redhat.com> | 2008-05-21 13:33:36 -0400 |
commit | c3eb5b80d8cc7ca6a425ccf359718d1ef3d5af55 (patch) | |
tree | 02bedd78921c0950f39cf951dee4dcee7dcde6ae /glx/glxdriswrast.c | |
parent | a8a9b40e554dd0c184866978889a39519afc466a (diff) |
Move GL/glx on level up now that it's the only thing left under GL.
Diffstat (limited to 'glx/glxdriswrast.c')
-rw-r--r-- | glx/glxdriswrast.c | 544 |
1 files changed, 544 insertions, 0 deletions
diff --git a/glx/glxdriswrast.c b/glx/glxdriswrast.c new file mode 100644 index 000000000..50dee5111 --- /dev/null +++ b/glx/glxdriswrast.c @@ -0,0 +1,544 @@ +/* + * 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 "g_disptab.h" +#include "glapitable.h" +#include "glapi.h" +#include "glthread.h" +#include "dispatch.h" +#include "extension_string.h" + +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; +}; + +struct __GLXDRIcontext { + __GLXcontext base; + __DRIcontext *driContext; +}; + +struct __GLXDRIdrawable { + __GLXdrawable base; + __DRIdrawable *driDrawable; + __GLXDRIscreen *screen; + + GCPtr gc; /* scratch GC for span drawing */ + GCPtr cleargc; /* GC for clearing the color buffer */ + 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); + + FreeScratchGC(private->gc); + FreeScratchGC(private->cleargc); + FreeScratchGC(private->swapgc); + + xfree(private); +} + +static GLboolean +__glXDRIdrawableResize(__GLXdrawable *drawable) +{ + /* Nothing to do here, the DRI driver asks the server for drawable + * geometry appropriately. */ + + return GL_TRUE; +} + +static GLboolean +__glXDRIdrawableSwapBuffers(__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); + xfree(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 int +__glXDRIcontextForceCurrent(__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); +} + +#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; + + 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) +{ + __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen; + + (*screen->core->destroyScreen)(screen->driScreen); + + dlclose(screen->driver); + + __glXScreenDestroy(baseScreen); + + xfree(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 = xalloc(sizeof *context); + if (context == NULL) + return NULL; + + memset(context, 0, sizeof *context); + context->base.destroy = __glXDRIcontextDestroy; + context->base.makeCurrent = __glXDRIcontextMakeCurrent; + context->base.loseCurrent = __glXDRIcontextLoseCurrent; + context->base.copy = __glXDRIcontextCopy; + context->base.forceCurrent = __glXDRIcontextForceCurrent; + context->base.textureFromPixmap = &__glXDRItextureFromPixmap; + + context->driContext = + (*core->createNewContext)(screen->driScreen, + config->driConfig, driShare, context); + + return &context->base; +} + +static void +glxChangeGC(GCPtr gc, BITS32 mask, CARD32 val) +{ + CARD32 v[1]; + v[0] = val; + dixChangeGC(NullClient, gc, mask, v, NULL); +} + +static __GLXdrawable * +__glXDRIscreenCreateDrawable(__GLXscreen *screen, + DrawablePtr pDraw, + int type, + XID drawId, + __GLXconfig *glxConfig) +{ + __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; + __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig; + __GLXDRIdrawable *private; + + ScreenPtr pScreen = driScreen->base.pScreen; + + private = xalloc(sizeof *private); + if (private == NULL) + return NULL; + + memset(private, 0, sizeof *private); + + private->screen = driScreen; + if (!__glXDrawableInit(&private->base, screen, + pDraw, type, drawId, glxConfig)) { + xfree(private); + return NULL; + } + + private->base.destroy = __glXDRIdrawableDestroy; + private->base.resize = __glXDRIdrawableResize; + private->base.swapBuffers = __glXDRIdrawableSwapBuffers; + private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer; + + private->gc = CreateScratchGC(pScreen, pDraw->depth); + private->cleargc = CreateScratchGC(pScreen, pDraw->depth); + private->swapgc = CreateScratchGC(pScreen, pDraw->depth); + + glxChangeGC(private->gc, GCFunction, GXcopy); + glxChangeGC(private->cleargc, GCFunction, GXcopy); + glxChangeGC(private->swapgc, GCFunction, GXcopy); + glxChangeGC(private->swapgc, GCGraphicsExposures, FALSE); + + 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_CLEAR: + gc = drawable->cleargc; + 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 const char dri_driver_path[] = DRI_DRIVER_PATH; + +static __GLXscreen * +__glXDRIscreenProbe(ScreenPtr pScreen) +{ + const char *driverName = "swrast"; + __GLXDRIscreen *screen; + char filename[128]; + const __DRIextension **extensions; + const __DRIconfig **driConfigs; + int i; + + screen = xalloc(sizeof *screen); + if (screen == NULL) + return NULL; + memset(screen, 0, sizeof *screen); + + screen->base.destroy = __glXDRIscreenDestroy; + screen->base.createContext = __glXDRIscreenCreateContext; + screen->base.createDrawable = __glXDRIscreenCreateDrawable; + screen->base.swapInterval = NULL; + screen->base.pScreen = pScreen; + + snprintf(filename, sizeof filename, + "%s/%s_dri.so", dri_driver_path, driverName); + + screen->driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL); + if (screen->driver == NULL) { + LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n", + filename, dlerror()); + goto handle_error; + } + + extensions = dlsym(screen->driver, __DRI_DRIVER_EXTENSIONS); + if (extensions == NULL) { + LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n", + driverName, dlerror()); + goto handle_error; + } + + for (i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, __DRI_CORE) == 0 && + extensions[i]->version >= __DRI_CORE_VERSION) { + screen->core = (const __DRIcoreExtension *) extensions[i]; + } + if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0 && + extensions[i]->version >= __DRI_SWRAST_VERSION) { + screen->swrast = (const __DRIswrastExtension *) extensions[i]; + } + } + + if (screen->core == NULL || screen->swrast == NULL) { + LogMessage(X_ERROR, "AIGLX error: %s exports no DRI extension\n", + driverName); + goto handle_error; + } + + screen->driScreen = + (*screen->swrast->createNewScreen)(pScreen->myNum, + loader_extensions, + &driConfigs, + screen); + + if (screen->driScreen == NULL) { + LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed"); + goto handle_error; + } + + initializeExtensions(screen); + + screen->base.fbconfigs = glxConvertConfigs(screen->core, driConfigs); + + __glXScreenInit(&screen->base, pScreen); + + LogMessage(X_INFO, + "AIGLX: Loaded and initialized %s\n", filename); + + return &screen->base; + + handle_error: + if (screen->driver) + dlclose(screen->driver); + + xfree(screen); + + LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n"); + + return NULL; +} + +__GLXprovider __glXDRISWRastProvider = { + __glXDRIscreenProbe, + "DRISWRAST", + NULL +}; |