#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#ifdef XFree86LOADER
#include "xf86.h"
#include "xf86_ansic.h"
#else
#include <sys/time.h>
#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"
#include "colormapst.h"
#include "cursorstr.h"
#include "scrnintstr.h"
#include "windowstr.h"
#include "servermd.h"
#define _APPLEDRI_SERVER_
#include "appledristr.h"
#include "swaprep.h"
#include "dri.h"
#include "dristruct.h"
#include "mi.h"
#include "mipointer.h"
#include "rootless.h"
#include "x-hash.h"
#include "x-hook.h"
#include "driWrap.h"
#include <AvailabilityMacros.h>
static int DRIScreenPrivIndex = -1;
static int DRIWindowPrivIndex = -1;
static int DRIPixmapPrivIndex = -1;
static int DRIPixmapBufferPrivIndex = -1;
static RESTYPE DRIDrawablePrivResType;
static x_hash_table *surface_hash;
static Bool DRIFreePixmapImp(DrawablePtr pDrawable);
#define CG_INFO_FILE "/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Resources/Info-macos.plist"
#define CG_REQUIRED_MAJOR 1
#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;
size_t length;
void *buffer;
} DRIPixmapBuffer, *DRIPixmapBufferPtr;
static unsigned int
get_cg_version (void)
{
static unsigned int version;
FILE *fh;
char *ptr;
if (version != 0)
return version;
fh = fopen (CG_INFO_FILE, "r");
if (fh != NULL)
{
char buf[256];
while (fgets (buf, sizeof (buf), fh) != NULL)
{
unsigned char c;
if (!strstr (buf, "<key>CFBundleShortVersionString</key>")
|| fgets (buf, sizeof (buf), fh) == NULL)
{
continue;
}
ptr = strstr (buf, "<string>");
if (ptr == NULL)
continue;
ptr += strlen ("<string>");
version = 0;
again:
switch ((c = *ptr++))
{
case '.':
version = version * 1024;
goto again;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
version = ((version & ~0x3ff)
+ (version & 0x3ff) * 10 + (c - '0'));
goto again;
}
break;
}
fclose (fh);
}
return version;
}
static Bool
test_cg_version (unsigned int major, unsigned int minor, unsigned int micro)
{
unsigned int cg_ver = get_cg_version ();
unsigned int cg_major = (cg_ver >> 20) & 0x3ff;
unsigned int cg_minor = (cg_ver >> 10) & 0x3ff;
unsigned int cg_micro = cg_ver & 0x3ff;
if (cg_major > major)
return TRUE;
else if (cg_major < major)
return FALSE;
if (cg_minor > minor)
return TRUE;
else if (cg_minor < minor)
return FALSE;
if (cg_micro < micro)
return FALSE;
return TRUE;
}
Bool
DRIScreenInit(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv;
int i;
pDRIPriv = (DRIScreenPrivPtr) xcalloc(1, sizeof(DRIScreenPrivRec));
if (!pDRIPriv) {
pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
return FALSE;
}
pScreen->devPrivates[DRIScreenPrivIndex].ptr = (pointer) pDRIPriv;
pDRIPriv->directRenderingSupport = TRUE;
pDRIPriv->nrWindows = 0;
if (!test_cg_version (CG_REQUIRED_MAJOR,
CG_REQUIRED_MINOR,
CG_REQUIRED_MICRO))
{
ErrorF ("[DRI] disabled direct rendering; requires CoreGraphics %d.%d.%d\n",
CG_REQUIRED_MAJOR, CG_REQUIRED_MINOR, CG_REQUIRED_MICRO);
pDRIPriv->directRenderingSupport = FALSE;
}
for (i = 0; i < DRI_MAX_DRAWABLES; i++) {
pDRIPriv->DRIDrawables[i] = NULL;
}
return TRUE;
}
Bool
DRIFinishScreenInit(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (!AllocateWindowPrivate(pScreen, DRIWindowPrivIndex, 0))
return FALSE;
pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
pScreen->ValidateTree = DRIValidateTree;
pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
pScreen->PostValidateTree = DRIPostValidateTree;
pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
pScreen->WindowExposures = DRIWindowExposures;
pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
pScreen->CopyWindow = DRICopyWindow;
pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
pScreen->ClipNotify = DRIClipNotify;
return DRIWrapInit(pScreen);
}
void
DRICloseScreen(ScreenPtr pScreen)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (pDRIPriv && pDRIPriv->directRenderingSupport) {
xfree(pDRIPriv);
pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
}
}
Bool
DRIExtensionInit(void)
{
static unsigned long DRIGeneration = 0;
if (DRIGeneration != serverGeneration) {
if ((DRIScreenPrivIndex = AllocateScreenPrivateIndex()) < 0)
return FALSE;
DRIGeneration = serverGeneration;
}
if ((DRIWindowPrivIndex = AllocateWindowPrivateIndex()) < 0)
return FALSE;
if ((DRIPixmapPrivIndex = AllocatePixmapPrivateIndex()) < 0)
return FALSE;
if ((DRIPixmapBufferPrivIndex = AllocatePixmapPrivateIndex()) < 0)
return FALSE;
DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete);
return TRUE;
}
void
DRIReset(void)
{
}
Bool
DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (pDRIPriv)
*isCapable = pDRIPriv->directRenderingSupport;
else
*isCapable = FALSE;
return TRUE;
}
Bool
DRIAuthConnection(ScreenPtr pScreen, unsigned int magic)
{
#if 0
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE;
#endif
return TRUE;
}
static void
DRIUpdateSurface(DRIDrawablePrivPtr pDRIDrawablePriv, DrawablePtr pDraw)
{
xp_window_changes wc;
unsigned int flags = 0;
if (pDRIDrawablePriv->sid == 0)
return;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
wc.depth = (pDraw->bitsPerPixel == 32 ? XP_DEPTH_ARGB8888
: pDraw->bitsPerPixel == 16 ? XP_DEPTH_RGB555 : XP_DEPTH_NIL);
if (wc.depth != XP_DEPTH_NIL)
flags |= XP_DEPTH;
#endif
if (pDraw->type == DRAWABLE_WINDOW) {
WindowPtr pWin = (WindowPtr) pDraw;
WindowPtr pTopWin = TopLevelParent(pWin);
wc.x = pWin->drawable.x - (pTopWin->drawable.x - pTopWin->borderWidth);
wc.y = pWin->drawable.y - (pTopWin->drawable.y - pTopWin->borderWidth);
wc.width = pWin->drawable.width + 2 * pWin->borderWidth;
wc.height = pWin->drawable.height + 2 * pWin->borderWidth;
wc.bit_gravity = XP_GRAVITY_NONE;
wc.shape_nrects = REGION_NUM_RECTS(&pWin->clipList);
wc.shape_rects = REGION_RECTS(&pWin->clipList);
wc.shape_tx = - (pTopWin->drawable.x - pTopWin->borderWidth);
wc.shape_ty = - (pTopWin->drawable.y - pTopWin->borderWidth);
flags |= XP_BOUNDS | XP_SHAPE;
} else if (pDraw->type == DRAWABLE_PIXMAP) {
wc.x = 0;
wc.y = 0;
wc.width = pDraw->width;
wc.height = pDraw->height;
wc.bit_gravity = XP_GRAVITY_NONE;
flags |= XP_BOUNDS;
}
xp_configure_surface(pDRIDrawablePriv->sid, flags, &wc);
}
static DRIDrawablePrivPtr
CreateSurfaceForWindow(ScreenPtr pScreen, WindowPtr pWin, xp_window_id *widPtr) {
DRIDrawablePrivPtr pDRIDrawablePriv;
xp_window_id wid = 0;
*widPtr = 0;
pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
if (pDRIDrawablePriv == NULL) {
xp_error err;
xp_window_changes wc;
if (!(pDRIDrawablePriv = xalloc(sizeof(*pDRIDrawablePriv)))) {
return NULL;
}
pDRIDrawablePriv->pDraw = (DrawablePtr)pWin;
pDRIDrawablePriv->pScreen = pScreen;
pDRIDrawablePriv->refCount = 0;
pDRIDrawablePriv->drawableIndex = -1;
pDRIDrawablePriv->notifiers = NULL;
wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWin, TRUE));
if (wid == 0) {
xfree(pDRIDrawablePriv);
return NULL;
}
err = xp_create_surface(wid, &pDRIDrawablePriv->sid);
if (err != Success) {
xfree(pDRIDrawablePriv);
return NULL;
}
wc.stack_mode = XP_MAPPED_ABOVE;
wc.sibling = 0;
err = xp_configure_surface(pDRIDrawablePriv->sid, XP_STACKING, &wc);
if (err != Success) {
xp_destroy_surface(pDRIDrawablePriv->sid);
xfree(pDRIDrawablePriv);
return NULL;
}
pWin->devPrivates[DRIWindowPrivIndex].ptr = pDRIDrawablePriv;
}
*widPtr = wid;
return pDRIDrawablePriv;
}
static DRIDrawablePrivPtr
CreateSurfaceForPixmap(ScreenPtr pScreen, PixmapPtr pPix) {
DRIDrawablePrivPtr pDRIDrawablePriv;
pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix);
if (pDRIDrawablePriv == NULL) {
xp_error err;
if (!(pDRIDrawablePriv = xcalloc(1, sizeof(*pDRIDrawablePriv)))) {
return NULL;
}
pDRIDrawablePriv->pDraw = (DrawablePtr)pPix;
pDRIDrawablePriv->pScreen = pScreen;
pDRIDrawablePriv->refCount = 0;
pDRIDrawablePriv->drawableIndex = -1;
pDRIDrawablePriv->notifiers = NULL;
err = xp_create_surface(0, &pDRIDrawablePriv->sid);
if (err != Success) {
xfree(pDRIDrawablePriv);
return NULL;
}
pPix->devPrivates[DRIPixmapPrivIndex].ptr = pDRIDrawablePriv;
}
return pDRIDrawablePriv;
}
Bool
DRICreateSurface(ScreenPtr pScreen, Drawable id,
DrawablePtr pDrawable, xp_client_id client_id,
xp_surface_id *surface_id, unsigned int ret_key[2],
void (*notify) (void *arg, void *data), void *notify_data)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
xp_window_id wid = 0;
DRIDrawablePrivPtr pDRIDrawablePriv;
if (pDrawable->type == DRAWABLE_WINDOW) {
pDRIDrawablePriv = CreateSurfaceForWindow(pScreen,
(WindowPtr)pDrawable, &wid);
if(NULL == pDRIDrawablePriv)
return FALSE;
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
else if (pDrawable->type == DRAWABLE_PIXMAP) {
pDRIDrawablePriv = CreateSurfaceForPixmap(pScreen,
(PixmapPtr)pDrawable);
if(NULL == pDRIDrawablePriv)
return FALSE;
}
#endif
else {
return FALSE;
}
if (pDRIDrawablePriv->refCount == 0) {
unsigned int key[2] = {0};
xp_error err;
if (client_id != 0) {
err = xp_export_surface(wid, pDRIDrawablePriv->sid,
client_id, key);
if (err != Success) {
xp_destroy_surface(pDRIDrawablePriv->sid);
xfree(pDRIDrawablePriv);
if(pDrawable->type == DRAWABLE_WINDOW) {
WindowPtr pWin = (WindowPtr)pDrawable;
pWin->devPrivates[DRIWindowPrivIndex].ptr = NULL;
} else if(pDrawable->type == DRAWABLE_PIXMAP) {
PixmapPtr pPix = (PixmapPtr)pDrawable;
pPix->devPrivates[DRIPixmapPrivIndex].ptr = NULL;
}
return FALSE;
}
}
pDRIDrawablePriv->key[0] = key[0];
pDRIDrawablePriv->key[1] = key[1];
++pDRIPriv->nrWindows;
if (surface_hash == NULL)
surface_hash = x_hash_table_new(NULL, NULL, NULL, NULL);
x_hash_table_insert(surface_hash,
x_cvt_uint_to_vptr(pDRIDrawablePriv->sid), pDRIDrawablePriv);
AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable);
DRIUpdateSurface(pDRIDrawablePriv, pDrawable);
}
pDRIDrawablePriv->refCount++;
*surface_id = pDRIDrawablePriv->sid;
if (ret_key != NULL) {
ret_key[0] = pDRIDrawablePriv->key[0];
ret_key[1] = pDRIDrawablePriv->key[1];
}
if (notify != NULL) {
pDRIDrawablePriv->notifiers = x_hook_add(pDRIDrawablePriv->notifiers,
notify, notify_data);
}
return TRUE;
}
Bool
DRIDestroySurface(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable,
void (*notify) (void *, void *), void *notify_data)
{
DRIDrawablePrivPtr pDRIDrawablePriv;
if (pDrawable->type == DRAWABLE_WINDOW) {
pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW((WindowPtr)pDrawable);
} else if (pDrawable->type == DRAWABLE_PIXMAP) {
pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP((PixmapPtr)pDrawable);
} else {
return FALSE;
}
if (pDRIDrawablePriv != NULL) {
if (notify != NULL) {
pDRIDrawablePriv->notifiers = x_hook_remove(pDRIDrawablePriv->notifiers,
notify, notify_data);
}
--pDRIDrawablePriv->refCount;
if (pDRIDrawablePriv->refCount <= 0) {
FreeResourceByType(id, DRIDrawablePrivResType, FALSE);
}
}
return TRUE;
}
Bool
DRIDrawablePrivDelete(pointer pResource, XID id)
{
DrawablePtr pDrawable = (DrawablePtr)pResource;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pDrawable->pScreen);
DRIDrawablePrivPtr pDRIDrawablePriv = NULL;
WindowPtr pWin = NULL;
PixmapPtr pPix = NULL;
if (pDrawable->type == DRAWABLE_WINDOW) {
pWin = (WindowPtr)pDrawable;
pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
} else if (pDrawable->type == DRAWABLE_PIXMAP) {
pPix = (PixmapPtr)pDrawable;
pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix);
}
if (pDRIDrawablePriv == NULL) {
return DRIFreePixmapImp(pDrawable);
}
if (pDRIDrawablePriv->drawableIndex != -1) {
pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL;
}
if (pDRIDrawablePriv->sid != 0) {
DRISurfaceNotify(pDRIDrawablePriv->sid, AppleDRISurfaceNotifyDestroyed);
}
if (pDRIDrawablePriv->notifiers != NULL)
x_hook_free(pDRIDrawablePriv->notifiers);
xfree(pDRIDrawablePriv);
if (pDrawable->type == DRAWABLE_WINDOW) {
pWin->devPrivates[DRIWindowPrivIndex].ptr = NULL;
} else if (pDrawable->type == DRAWABLE_PIXMAP) {
pPix->devPrivates[DRIPixmapPrivIndex].ptr = NULL;
}
--pDRIPriv->nrWindows;
return TRUE;
}
void
DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
if (pDRIDrawablePriv) {
}
pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures;
(*pScreen->WindowExposures)(pWin, prgn, bsreg);
pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
pScreen->WindowExposures = DRIWindowExposures;
}
void
DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIDrawablePrivPtr pDRIDrawablePriv;
if (pDRIPriv->nrWindows > 0) {
pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
if (pDRIDrawablePriv != NULL) {
DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable);
}
}
pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
(*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
pScreen->CopyWindow = DRICopyWindow;
}
int
DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
{
ScreenPtr pScreen = pParent->drawable.pScreen;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
int returnValue;
pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree;
returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind);
pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
pScreen->ValidateTree = DRIValidateTree;
return returnValue;
}
void
DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
{
ScreenPtr pScreen;
DRIScreenPrivPtr pDRIPriv;
if (pParent) {
pScreen = pParent->drawable.pScreen;
} else {
pScreen = pChild->drawable.pScreen;
}
pDRIPriv = DRI_SCREEN_PRIV(pScreen);
if (pDRIPriv->wrap.PostValidateTree) {
pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree;
(*pScreen->PostValidateTree)(pParent, pChild, kind);
pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
pScreen->PostValidateTree = DRIPostValidateTree;
}
}
void
DRIClipNotify(WindowPtr pWin, int dx, int dy)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIDrawablePrivPtr pDRIDrawablePriv;
if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable);
}
if (pDRIPriv->wrap.ClipNotify) {
pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify;
(*pScreen->ClipNotify)(pWin, dx, dy);
pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
pScreen->ClipNotify = DRIClipNotify;
}
}
DRIWrappedFuncsRec *
DRIGetWrappedFuncs(ScreenPtr pScreen)
{
return &(DRI_SCREEN_PRIV(pScreen)->wrap);
}
void
DRIQueryVersion(int *majorVersion,
int *minorVersion,
int *patchVersion)
{
*majorVersion = APPLE_DRI_MAJOR_VERSION;
*minorVersion = APPLE_DRI_MINOR_VERSION;
*patchVersion = APPLE_DRI_PATCH_VERSION;
}
void
DRISurfaceNotify(xp_surface_id id, int kind)
{
DRIDrawablePrivPtr pDRIDrawablePriv = NULL;
DRISurfaceNotifyArg arg;
arg.id = id;
arg.kind = kind;
if (surface_hash != NULL)
{
pDRIDrawablePriv = x_hash_table_lookup(surface_hash,
x_cvt_uint_to_vptr(id), NULL);
}
if (pDRIDrawablePriv == NULL)
return;
if (kind == AppleDRISurfaceNotifyDestroyed)
{
x_hash_table_remove(surface_hash, x_cvt_uint_to_vptr(id));
}
x_hook_run(pDRIDrawablePriv->notifiers, &arg);
if (kind == AppleDRISurfaceNotifyDestroyed)
{
xp_error error;
error = xp_destroy_surface(pDRIDrawablePriv->sid);
if(error)
ErrorF("%s: xp_destroy_surface failed: %d\n", __func__, error);
pDRIDrawablePriv->sid = 0;
FreeResourceByType(pDRIDrawablePriv->pDraw->id,
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';
pPix->devPrivates[DRIPixmapBufferPrivIndex].ptr = 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 = pPix->devPrivates[DRIPixmapBufferPrivIndex].ptr;
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 = pPix->devPrivates[DRIPixmapBufferPrivIndex].ptr;
if(NULL == shared)
return FALSE;
close(shared->fd);
munmap(shared->buffer, shared->length);
shm_unlink(shared->shmPath);
xfree(shared);
pPix->devPrivates[DRIPixmapBufferPrivIndex].ptr = NULL;
return TRUE;
}
void
DRIDestroyPixmap(DrawablePtr pDrawable) {
if(DRIFreePixmapImp(pDrawable))
FreeResourceByType(pDrawable->id, DRIDrawablePrivResType, FALSE);
}