diff options
Diffstat (limited to 'xorg-server/hw/xquartz/xpr/dri.c')
-rw-r--r-- | xorg-server/hw/xquartz/xpr/dri.c | 211 |
1 files changed, 188 insertions, 23 deletions
diff --git a/xorg-server/hw/xquartz/xpr/dri.c b/xorg-server/hw/xquartz/xpr/dri.c index 50b478b9c..f570bee5d 100644 --- a/xorg-server/hw/xquartz/xpr/dri.c +++ b/xorg-server/hw/xquartz/xpr/dri.c @@ -2,7 +2,7 @@ Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. Copyright 2000 VA Linux Systems, Inc. -Copyright (c) 2002 Apple Computer, Inc. +Copyright (c) 2002, 2009 Apple Computer, Inc. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -46,10 +46,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <unistd.h> #endif -#define NEED_REPLIES -#define NEED_EVENTS #include <X11/X.h> #include <X11/Xproto.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> #include "misc.h" #include "dixstruct.h" #include "extnsionst.h" @@ -68,6 +70,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rootless.h" #include "x-hash.h" #include "x-hook.h" +#include "driWrap.h" #include <AvailabilityMacros.h> @@ -77,11 +80,15 @@ static int DRIWindowPrivKeyIndex; static DevPrivateKey DRIWindowPrivKey = &DRIWindowPrivKeyIndex; static int DRIPixmapPrivKeyIndex; static DevPrivateKey DRIPixmapPrivKey = &DRIPixmapPrivKeyIndex; +static int DRIPixmapBufferPrivKeyIndex; +static DevPrivateKey DRIPixmapBufferPrivKey = &DRIPixmapBufferPrivKeyIndex; static RESTYPE DRIDrawablePrivResType; static x_hash_table *surface_hash; /* maps surface ids -> drawablePrivs */ +static Bool DRIFreePixmapImp(DrawablePtr pDrawable); + /* FIXME: don't hardcode this? */ #define CG_INFO_FILE "/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Resources/Info-macos.plist" @@ -90,6 +97,18 @@ static x_hash_table *surface_hash; /* maps surface ids -> drawablePrivs */ #define CG_REQUIRED_MINOR 157 #define CG_REQUIRED_MICRO 11 +typedef struct { + DrawablePtr pDrawable; + int refCount; + int bytesPerPixel; + int width; + int height; + char shmPath[PATH_MAX]; + int fd; /* From shm_open (for now) */ + size_t length; /* length of buffer */ + void *buffer; +} DRIPixmapBuffer, *DRIPixmapBufferPtr; + /* Returns version as major.minor.micro in 10.10.10 fixed form */ static unsigned int get_cg_version (void) @@ -241,7 +260,7 @@ DRIFinishScreenInit(ScreenPtr pScreen) // ErrorF("[DRI] screen %d installation complete\n", pScreen->myNum); - return TRUE; + return DRIWrapInit(pScreen); } void @@ -408,7 +427,7 @@ CreateSurfaceForWindow(ScreenPtr pScreen, WindowPtr pWin, xp_window_id *widPtr) return pDRIDrawablePriv; } -/* Return FALSE if an error occurs. */ +/* Return NULL if an error occurs. */ static DRIDrawablePrivPtr CreateSurfaceForPixmap(ScreenPtr pScreen, PixmapPtr pPix) { DRIDrawablePrivPtr pDRIDrawablePriv; @@ -417,7 +436,6 @@ CreateSurfaceForPixmap(ScreenPtr pScreen, PixmapPtr pPix) { if (pDRIDrawablePriv == NULL) { xp_error err; - xp_window_changes wc; /* allocate a DRI Window Private record */ if (!(pDRIDrawablePriv = xcalloc(1, sizeof(*pDRIDrawablePriv)))) { @@ -439,18 +457,10 @@ CreateSurfaceForPixmap(ScreenPtr pScreen, PixmapPtr pPix) { return NULL; } - wc.x = 0; - wc.y = 0; - wc.width = pPix->drawable.width; - wc.height = pPix->drawable.height; - - err = xp_configure_surface(pDRIDrawablePriv->sid, XP_BOUNDS, &wc); - - if(err != Success) { - xp_destroy_surface(pDRIDrawablePriv->sid); - xfree(pDRIDrawablePriv); - return NULL; - } + /* + * The DRIUpdateSurface will be called to resize the surface + * after this function, if the export is successful. + */ /* save private off of preallocated index */ dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, @@ -491,21 +501,39 @@ DRICreateSurface(ScreenPtr pScreen, Drawable id, /* NOT_DONE */ return FALSE; } - - + /* Finish initialization of new surfaces */ if (pDRIDrawablePriv->refCount == 0) { unsigned int key[2] = {0}; xp_error err; /* try to give the client access to the surface */ - if (client_id != 0 && wid != 0) { + if (client_id != 0) { + /* + * Xplugin accepts a 0 wid if the surface id is offscreen, such + * as for a pixmap. + */ err = xp_export_surface(wid, pDRIDrawablePriv->sid, client_id, key); if (err != Success) { xp_destroy_surface(pDRIDrawablePriv->sid); xfree(pDRIDrawablePriv); + + /* + * Now set the dix privates to NULL that were previously set. + * This prevents reusing an invalid pointer. + */ + if(pDrawable->type == DRAWABLE_WINDOW) { + WindowPtr pWin = (WindowPtr)pDrawable; + + dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); + } else if(pDrawable->type == DRAWABLE_PIXMAP) { + PixmapPtr pPix = (PixmapPtr)pDrawable; + + dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL); + } + return FALSE; } } @@ -591,8 +619,9 @@ DRIDrawablePrivDelete(pointer pResource, XID id) pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix); } - if (pDRIDrawablePriv == NULL) - return FALSE; + if (pDRIDrawablePriv == NULL) { + return DRIFreePixmapImp(pDrawable); + } if (pDRIDrawablePriv->drawableIndex != -1) { /* release drawable table entry */ @@ -785,3 +814,139 @@ DRISurfaceNotify(xp_surface_id id, int kind) DRIDrawablePrivResType, FALSE); } } + +Bool DRICreatePixmap(ScreenPtr pScreen, Drawable id, + DrawablePtr pDrawable, char *path, + size_t pathmax) +{ + DRIPixmapBufferPtr shared; + PixmapPtr pPix; + + if(pDrawable->type != DRAWABLE_PIXMAP) + return FALSE; + + pPix = (PixmapPtr)pDrawable; + + shared = xalloc(sizeof(*shared)); + if(NULL == shared) { + FatalError("failed to allocate DRIPixmapBuffer in %s\n", __func__); + } + + shared->pDrawable = pDrawable; + shared->refCount = 1; + + if(pDrawable->bitsPerPixel >= 24) { + shared->bytesPerPixel = 4; + } else if(pDrawable->bitsPerPixel <= 16) { + shared->bytesPerPixel = 2; + } + + shared->width = pDrawable->width; + shared->height = pDrawable->height; + + if(-1 == snprintf(shared->shmPath, sizeof(shared->shmPath), + "%d_0x%lx", getpid(), + (unsigned long)id)) { + FatalError("buffer overflow in %s\n", __func__); + } + + shared->fd = shm_open(shared->shmPath, + O_RDWR | O_EXCL | O_CREAT, + S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH); + + if(-1 == shared->fd) { + xfree(shared); + return FALSE; + } + + shared->length = shared->width * shared->height * shared->bytesPerPixel; + + if(-1 == ftruncate(shared->fd, shared->length)) { + ErrorF("failed to ftruncate (extend) file."); + shm_unlink(shared->shmPath); + close(shared->fd); + xfree(shared); + return FALSE; + } + + shared->buffer = mmap(NULL, shared->length, + PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, shared->fd, 0); + + if(MAP_FAILED == shared->buffer) { + ErrorF("failed to mmap shared memory."); + shm_unlink(shared->shmPath); + close(shared->fd); + xfree(shared); + return FALSE; + } + + strncpy(path, shared->shmPath, pathmax); + path[pathmax - 1] = '\0'; + + dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, shared); + + AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable); + + return TRUE; +} + + +Bool DRIGetPixmapData(DrawablePtr pDrawable, int *width, int *height, + int *pitch, int *bpp, void **ptr) { + PixmapPtr pPix; + DRIPixmapBufferPtr shared; + + if(pDrawable->type != DRAWABLE_PIXMAP) + return FALSE; + + pPix = (PixmapPtr)pDrawable; + + shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey); + + if(NULL == shared) + return FALSE; + + assert(pDrawable->width == shared->width); + assert(pDrawable->height == shared->height); + + *width = shared->width; + *height = shared->height; + *bpp = shared->bytesPerPixel; + *pitch = shared->width * shared->bytesPerPixel; + *ptr = shared->buffer; + + return TRUE; +} + +static Bool +DRIFreePixmapImp(DrawablePtr pDrawable) { + DRIPixmapBufferPtr shared; + PixmapPtr pPix; + + if(pDrawable->type != DRAWABLE_PIXMAP) + return FALSE; + + pPix = (PixmapPtr)pDrawable; + + shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey); + + if(NULL == shared) + return FALSE; + + close(shared->fd); + munmap(shared->buffer, shared->length); + shm_unlink(shared->shmPath); + xfree(shared); + + dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, (pointer)NULL); + + return TRUE; +} + +void +DRIDestroyPixmap(DrawablePtr pDrawable) { + if(DRIFreePixmapImp(pDrawable)) + FreeResourceByType(pDrawable->id, DRIDrawablePrivResType, FALSE); + +} |