aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xquartz/xpr/dri.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xquartz/xpr/dri.c')
-rw-r--r--xorg-server/hw/xquartz/xpr/dri.c211
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);
+
+}