diff options
Diffstat (limited to 'xorg-server/hw/xquartz/xpr/dri.c')
-rw-r--r-- | xorg-server/hw/xquartz/xpr/dri.c | 1768 |
1 files changed, 884 insertions, 884 deletions
diff --git a/xorg-server/hw/xquartz/xpr/dri.c b/xorg-server/hw/xquartz/xpr/dri.c index 63fcabe38..8bae6b009 100644 --- a/xorg-server/hw/xquartz/xpr/dri.c +++ b/xorg-server/hw/xquartz/xpr/dri.c @@ -1,884 +1,884 @@ -/**************************************************************************
-
-Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
-Copyright 2000 VA Linux Systems, Inc.
-Copyright (c) 2002, 2009 Apple Computer, Inc.
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sub license, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
-ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Jens Owen <jens@valinux.com>
- * Rickard E. (Rik) Faith <faith@valinux.com>
- *
- */
-
-#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
-
-#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 DevPrivateKeyRec DRIScreenPrivKeyRec;
-#define DRIScreenPrivKey (&DRIScreenPrivKeyRec)
-static DevPrivateKeyRec DRIWindowPrivKeyRec;
-#define DRIWindowPrivKey (&DRIWindowPrivKeyRec)
-static DevPrivateKeyRec DRIPixmapPrivKeyRec;
-#define DRIPixmapPrivKey (&DRIPixmapPrivKeyRec)
-static DevPrivateKeyRec DRIPixmapBufferPrivKeyRec;
-#define DRIPixmapBufferPrivKey (&DRIPixmapBufferPrivKeyRec)
-
-static RESTYPE DRIDrawablePrivResType;
-
-static x_hash_table *surface_hash; /* maps surface ids -> drawablePrivs */
-
-static Bool DRIFreePixmapImp(DrawablePtr pDrawable);
-
-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;
-
-Bool
-DRIScreenInit(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv;
- int i;
-
- if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
- if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0))
- return FALSE;
- if (!dixRegisterPrivateKey(&DRIPixmapPrivKeyRec, PRIVATE_PIXMAP, 0))
- return FALSE;
- if (!dixRegisterPrivateKey(&DRIPixmapBufferPrivKeyRec, PRIVATE_PIXMAP, 0))
- return FALSE;
-
- pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec));
- if (!pDRIPriv) {
- dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
- return FALSE;
- }
-
- dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv);
- pDRIPriv->directRenderingSupport = TRUE;
- pDRIPriv->nrWindows = 0;
-
- /* Initialize drawable tables */
- for (i = 0; i < DRI_MAX_DRAWABLES; i++) {
- pDRIPriv->DRIDrawables[i] = NULL;
- }
-
- return TRUE;
-}
-
-Bool
-DRIFinishScreenInit(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- /* Wrap DRI support */
- 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;
-
- // ErrorF("[DRI] screen %d installation complete\n", pScreen->myNum);
-
- return DRIWrapInit(pScreen);
-}
-
-void
-DRICloseScreen(ScreenPtr pScreen)
-{
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-
- if (pDRIPriv && pDRIPriv->directRenderingSupport) {
- free(pDRIPriv);
- dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
- }
-}
-
-Bool
-DRIExtensionInit(void)
-{
- DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete,
- "DRIDrawable");
-
- return DRIDrawablePrivResType != 0;
-}
-
-void
-DRIReset(void)
-{
- /*
- * This stub routine is called when the X Server recycles, resources
- * allocated by DRIExtensionInit need to be managed here.
- *
- * Currently this routine is a stub because all the interesting resources
- * are managed via the screen init process.
- */
-}
-
-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
- /* FIXME: something? */
-
- 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 = RegionNumRects(&pWin->clipList);
- wc.shape_rects = RegionRects(&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);
-}
-
-/* Return NULL if an error occurs. */
-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;
-
- /* allocate a DRI Window Private record */
- if (!(pDRIDrawablePriv = malloc(sizeof(*pDRIDrawablePriv)))) {
- return NULL;
- }
-
- pDRIDrawablePriv->pDraw = (DrawablePtr)pWin;
- pDRIDrawablePriv->pScreen = pScreen;
- pDRIDrawablePriv->refCount = 0;
- pDRIDrawablePriv->drawableIndex = -1;
- pDRIDrawablePriv->notifiers = NULL;
-
- /* find the physical window */
- wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWin, TRUE));
-
- if (wid == 0) {
- free(pDRIDrawablePriv);
- return NULL;
- }
-
- /* allocate the physical surface */
- err = xp_create_surface(wid, &pDRIDrawablePriv->sid);
-
- if (err != Success) {
- free(pDRIDrawablePriv);
- return NULL;
- }
-
- /* Make it visible */
- 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);
- free(pDRIDrawablePriv);
- return NULL;
- }
-
- /* save private off of preallocated index */
- dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey,
- pDRIDrawablePriv);
- }
-
- *widPtr = wid;
-
- return pDRIDrawablePriv;
-}
-
-/* Return NULL if an error occurs. */
-static DRIDrawablePrivPtr
-CreateSurfaceForPixmap(ScreenPtr pScreen, PixmapPtr pPix) {
- DRIDrawablePrivPtr pDRIDrawablePriv;
-
- pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix);
-
- if (pDRIDrawablePriv == NULL) {
- xp_error err;
-
- /* allocate a DRI Window Private record */
- if (!(pDRIDrawablePriv = calloc(1, sizeof(*pDRIDrawablePriv)))) {
- return NULL;
- }
-
- pDRIDrawablePriv->pDraw = (DrawablePtr)pPix;
- pDRIDrawablePriv->pScreen = pScreen;
- pDRIDrawablePriv->refCount = 0;
- pDRIDrawablePriv->drawableIndex = -1;
- pDRIDrawablePriv->notifiers = NULL;
-
- /* Passing a null window id to Xplugin in 10.3+ asks for
- an accelerated offscreen surface. */
-
- err = xp_create_surface(0, &pDRIDrawablePriv->sid);
- if (err != Success) {
- free(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,
- 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; /*error*/
- }
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
- else if (pDrawable->type == DRAWABLE_PIXMAP) {
- pDRIDrawablePriv = CreateSurfaceForPixmap(pScreen,
- (PixmapPtr)pDrawable);
-
- if(NULL == pDRIDrawablePriv)
- return FALSE; /*error*/
- }
-#endif
- else {
- /* We handle GLXPbuffers in a different way (via CGL). */
- 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) {
- /*
- * 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);
- free(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;
- }
- }
-
- pDRIDrawablePriv->key[0] = key[0];
- pDRIDrawablePriv->key[1] = key[1];
-
- ++pDRIPriv->nrWindows;
-
- /* and stash it by surface id */
- 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);
-
- /* track this in case this window is destroyed */
- AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable);
-
- /* Initialize shape */
- 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) {
- /*
- * This doesn't seem to be used, because notify is NULL in all callers.
- */
-
- if (notify != NULL) {
- pDRIDrawablePriv->notifiers = x_hook_remove(pDRIDrawablePriv->notifiers,
- notify, notify_data);
- }
-
- --pDRIDrawablePriv->refCount;
-
- /*
- * Check if the drawable privates still have a reference to the
- * surface.
- */
-
- if (pDRIDrawablePriv->refCount <= 0) {
- /*
- * This calls back to DRIDrawablePrivDelete which
- * frees the private area and dispatches events, if needed.
- */
- FreeResourceByType(id, DRIDrawablePrivResType, FALSE);
- }
- }
-
- return TRUE;
-}
-
-/*
- * The assumption is that this is called when the refCount of a surface
- * drops to <= 0, or the window/pixmap is destroyed.
- */
-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) {
- /*
- * We reuse __func__ and the resource type for the GLXPixmap code.
- * Attempt to free a pixmap buffer associated with the resource
- * if possible.
- */
- return DRIFreePixmapImp(pDrawable);
- }
-
- if (pDRIDrawablePriv->drawableIndex != -1) {
- /* release drawable table entry */
- pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL;
- }
-
- if (pDRIDrawablePriv->sid != 0) {
- DRISurfaceNotify(pDRIDrawablePriv->sid, AppleDRISurfaceNotifyDestroyed);
- }
-
-
- if (pDRIDrawablePriv->notifiers != NULL)
- x_hook_free(pDRIDrawablePriv->notifiers);
-
- free(pDRIDrawablePriv);
-
- if (pDrawable->type == DRAWABLE_WINDOW) {
- dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL);
- } else if (pDrawable->type == DRAWABLE_PIXMAP) {
- dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, 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) {
- /* FIXME: something? */
- }
-
- pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures;
-
- (*pScreen->WindowExposures)(pWin, prgn, bsreg);
-
- 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);
- }
- }
-
- /* unwrap */
- pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
-
- /* call lower layers */
- (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
-
- /* rewrap */
- pScreen->CopyWindow = DRICopyWindow;
-}
-
-int
-DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
-{
- ScreenPtr pScreen = pParent->drawable.pScreen;
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- int returnValue;
-
- /* unwrap */
- pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree;
-
- /* call lower layers */
- returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind);
-
- /* rewrap */
- 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) {
- /* unwrap */
- pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree;
-
- /* call lower layers */
- (*pScreen->PostValidateTree)(pParent, pChild, kind);
-
- /* rewrap */
- 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);
-
- pScreen->ClipNotify = DRIClipNotify;
- }
-}
-
-/* This lets us get at the unwrapped functions so that they can correctly
- * call the lower level functions, and choose whether they will be
- * called at every level of recursion (eg in validatetree).
- */
-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;
-}
-
-/*
- * Note: this also cleans up the hash table in addition to notifying clients.
- * The sid/surface-id should not be used after this, because it will be
- * invalid.
- */
-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);
-
- /* Guard against reuse, even though we are freeing after this. */
- pDRIDrawablePriv->sid = 0;
-
- FreeResourceByType(pDRIDrawablePriv->pDraw->id,
- DRIDrawablePrivResType, FALSE);
- }
-}
-
-/*
- * This creates a shared memory buffer for use with GLXPixmaps
- * and AppleSGLX.
- */
-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 = malloc(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) {
- free(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);
- free(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);
- free(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);
- free(shared);
-
- dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, (pointer)NULL);
-
- return TRUE;
-}
-
-void
-DRIDestroyPixmap(DrawablePtr pDrawable) {
- if(DRIFreePixmapImp(pDrawable))
- FreeResourceByType(pDrawable->id, DRIDrawablePrivResType, FALSE);
-
-}
+/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +Copyright (c) 2002, 2009 Apple Computer, Inc. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Jens Owen <jens@valinux.com> + * Rickard E. (Rik) Faith <faith@valinux.com> + * + */ + +#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 + +#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 DevPrivateKeyRec DRIScreenPrivKeyRec; +#define DRIScreenPrivKey (&DRIScreenPrivKeyRec) +static DevPrivateKeyRec DRIWindowPrivKeyRec; +#define DRIWindowPrivKey (&DRIWindowPrivKeyRec) +static DevPrivateKeyRec DRIPixmapPrivKeyRec; +#define DRIPixmapPrivKey (&DRIPixmapPrivKeyRec) +static DevPrivateKeyRec DRIPixmapBufferPrivKeyRec; +#define DRIPixmapBufferPrivKey (&DRIPixmapBufferPrivKeyRec) + +static RESTYPE DRIDrawablePrivResType; + +static x_hash_table *surface_hash; /* maps surface ids -> drawablePrivs */ + +static Bool DRIFreePixmapImp(DrawablePtr pDrawable); + +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; + +Bool +DRIScreenInit(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv; + int i; + + if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0)) + return FALSE; + if (!dixRegisterPrivateKey(&DRIPixmapPrivKeyRec, PRIVATE_PIXMAP, 0)) + return FALSE; + if (!dixRegisterPrivateKey(&DRIPixmapBufferPrivKeyRec, PRIVATE_PIXMAP, 0)) + return FALSE; + + pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec)); + if (!pDRIPriv) { + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); + return FALSE; + } + + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv); + pDRIPriv->directRenderingSupport = TRUE; + pDRIPriv->nrWindows = 0; + + /* Initialize drawable tables */ + for (i = 0; i < DRI_MAX_DRAWABLES; i++) { + pDRIPriv->DRIDrawables[i] = NULL; + } + + return TRUE; +} + +Bool +DRIFinishScreenInit(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + /* Wrap DRI support */ + 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; + + // ErrorF("[DRI] screen %d installation complete\n", pScreen->myNum); + + return DRIWrapInit(pScreen); +} + +void +DRICloseScreen(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv && pDRIPriv->directRenderingSupport) { + free(pDRIPriv); + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); + } +} + +Bool +DRIExtensionInit(void) +{ + DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete, + "DRIDrawable"); + + return DRIDrawablePrivResType != 0; +} + +void +DRIReset(void) +{ + /* + * This stub routine is called when the X Server recycles, resources + * allocated by DRIExtensionInit need to be managed here. + * + * Currently this routine is a stub because all the interesting resources + * are managed via the screen init process. + */ +} + +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 + /* FIXME: something? */ + + 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 = RegionNumRects(&pWin->clipList); + wc.shape_rects = RegionRects(&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); +} + +/* Return NULL if an error occurs. */ +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; + + /* allocate a DRI Window Private record */ + if (!(pDRIDrawablePriv = malloc(sizeof(*pDRIDrawablePriv)))) { + return NULL; + } + + pDRIDrawablePriv->pDraw = (DrawablePtr)pWin; + pDRIDrawablePriv->pScreen = pScreen; + pDRIDrawablePriv->refCount = 0; + pDRIDrawablePriv->drawableIndex = -1; + pDRIDrawablePriv->notifiers = NULL; + + /* find the physical window */ + wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWin, TRUE)); + + if (wid == 0) { + free(pDRIDrawablePriv); + return NULL; + } + + /* allocate the physical surface */ + err = xp_create_surface(wid, &pDRIDrawablePriv->sid); + + if (err != Success) { + free(pDRIDrawablePriv); + return NULL; + } + + /* Make it visible */ + 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); + free(pDRIDrawablePriv); + return NULL; + } + + /* save private off of preallocated index */ + dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, + pDRIDrawablePriv); + } + + *widPtr = wid; + + return pDRIDrawablePriv; +} + +/* Return NULL if an error occurs. */ +static DRIDrawablePrivPtr +CreateSurfaceForPixmap(ScreenPtr pScreen, PixmapPtr pPix) { + DRIDrawablePrivPtr pDRIDrawablePriv; + + pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix); + + if (pDRIDrawablePriv == NULL) { + xp_error err; + + /* allocate a DRI Window Private record */ + if (!(pDRIDrawablePriv = calloc(1, sizeof(*pDRIDrawablePriv)))) { + return NULL; + } + + pDRIDrawablePriv->pDraw = (DrawablePtr)pPix; + pDRIDrawablePriv->pScreen = pScreen; + pDRIDrawablePriv->refCount = 0; + pDRIDrawablePriv->drawableIndex = -1; + pDRIDrawablePriv->notifiers = NULL; + + /* Passing a null window id to Xplugin in 10.3+ asks for + an accelerated offscreen surface. */ + + err = xp_create_surface(0, &pDRIDrawablePriv->sid); + if (err != Success) { + free(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, + 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; /*error*/ + } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 + else if (pDrawable->type == DRAWABLE_PIXMAP) { + pDRIDrawablePriv = CreateSurfaceForPixmap(pScreen, + (PixmapPtr)pDrawable); + + if(NULL == pDRIDrawablePriv) + return FALSE; /*error*/ + } +#endif + else { + /* We handle GLXPbuffers in a different way (via CGL). */ + 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) { + /* + * 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); + free(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; + } + } + + pDRIDrawablePriv->key[0] = key[0]; + pDRIDrawablePriv->key[1] = key[1]; + + ++pDRIPriv->nrWindows; + + /* and stash it by surface id */ + 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); + + /* track this in case this window is destroyed */ + AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable); + + /* Initialize shape */ + 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) { + /* + * This doesn't seem to be used, because notify is NULL in all callers. + */ + + if (notify != NULL) { + pDRIDrawablePriv->notifiers = x_hook_remove(pDRIDrawablePriv->notifiers, + notify, notify_data); + } + + --pDRIDrawablePriv->refCount; + + /* + * Check if the drawable privates still have a reference to the + * surface. + */ + + if (pDRIDrawablePriv->refCount <= 0) { + /* + * This calls back to DRIDrawablePrivDelete which + * frees the private area and dispatches events, if needed. + */ + FreeResourceByType(id, DRIDrawablePrivResType, FALSE); + } + } + + return TRUE; +} + +/* + * The assumption is that this is called when the refCount of a surface + * drops to <= 0, or the window/pixmap is destroyed. + */ +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) { + /* + * We reuse __func__ and the resource type for the GLXPixmap code. + * Attempt to free a pixmap buffer associated with the resource + * if possible. + */ + return DRIFreePixmapImp(pDrawable); + } + + if (pDRIDrawablePriv->drawableIndex != -1) { + /* release drawable table entry */ + pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL; + } + + if (pDRIDrawablePriv->sid != 0) { + DRISurfaceNotify(pDRIDrawablePriv->sid, AppleDRISurfaceNotifyDestroyed); + } + + + if (pDRIDrawablePriv->notifiers != NULL) + x_hook_free(pDRIDrawablePriv->notifiers); + + free(pDRIDrawablePriv); + + if (pDrawable->type == DRAWABLE_WINDOW) { + dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); + } else if (pDrawable->type == DRAWABLE_PIXMAP) { + dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, 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) { + /* FIXME: something? */ + } + + pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; + + (*pScreen->WindowExposures)(pWin, prgn, bsreg); + + 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); + } + } + + /* unwrap */ + pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; + + /* call lower layers */ + (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); + + /* rewrap */ + pScreen->CopyWindow = DRICopyWindow; +} + +int +DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) +{ + ScreenPtr pScreen = pParent->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + int returnValue; + + /* unwrap */ + pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; + + /* call lower layers */ + returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind); + + /* rewrap */ + 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) { + /* unwrap */ + pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; + + /* call lower layers */ + (*pScreen->PostValidateTree)(pParent, pChild, kind); + + /* rewrap */ + 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); + + pScreen->ClipNotify = DRIClipNotify; + } +} + +/* This lets us get at the unwrapped functions so that they can correctly + * call the lower level functions, and choose whether they will be + * called at every level of recursion (eg in validatetree). + */ +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; +} + +/* + * Note: this also cleans up the hash table in addition to notifying clients. + * The sid/surface-id should not be used after this, because it will be + * invalid. + */ +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); + + /* Guard against reuse, even though we are freeing after this. */ + pDRIDrawablePriv->sid = 0; + + FreeResourceByType(pDRIDrawablePriv->pDraw->id, + DRIDrawablePrivResType, FALSE); + } +} + +/* + * This creates a shared memory buffer for use with GLXPixmaps + * and AppleSGLX. + */ +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 = malloc(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) { + free(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); + free(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); + free(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); + free(shared); + + dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, (pointer)NULL); + + return TRUE; +} + +void +DRIDestroyPixmap(DrawablePtr pDrawable) { + if(DRIFreePixmapImp(pDrawable)) + FreeResourceByType(pDrawable->id, DRIDrawablePrivResType, FALSE); + +} |