X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-osx%2Ftrunk%2Flauncher%2Fdri-surface.c;fp=synfig-osx%2Ftrunk%2Flauncher%2Fdri-surface.c;h=f7249cfe5f714380298f2283d25fe6271fec1bf3;hb=4f638c4f8e5dc642a92d62da31233654eca397b2;hp=0000000000000000000000000000000000000000;hpb=7bf63b38a939d592d8a7c0c1f52aadfda2229427;p=synfig.git diff --git a/synfig-osx/trunk/launcher/dri-surface.c b/synfig-osx/trunk/launcher/dri-surface.c new file mode 100644 index 0000000..f7249cf --- /dev/null +++ b/synfig-osx/trunk/launcher/dri-surface.c @@ -0,0 +1,940 @@ +/* $XFree86: xc/programs/Xserver/GL/dri/dri.c,v 1.34 2001/12/10 19:07:19 dawes Exp $ */ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +Copyright (c) 2002 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 + * Rickard E. (Rik) Faith + * + */ + +#ifdef XFree86LOADER +#include "xf86.h" +#include "xf86_ansic.h" +#else +#include +#include +#endif + +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.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-surface.h" +#include "dristruct.h" +#include "mi.h" +#include "mipointer.h" +#include "rootless-common.h" +#include "x-hash.h" +#include "x-hook.h" + +#include + +static int DRIScreenPrivIndex = -1; +static int DRIWindowPrivIndex = -1; +static int DRIPixmapPrivIndex = -1; +static unsigned long DRIGeneration = 0; + +static RESTYPE DRIDrawablePrivResType; + +static x_hash_table *surface_hash; /* maps surface ids -> drawablePrivs */ + +Bool +DRIScreenInit(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv; + int i; + + if (DRIGeneration != serverGeneration) { + if ((DRIScreenPrivIndex = AllocateScreenPrivateIndex()) < 0) + return FALSE; + DRIGeneration = serverGeneration; + } + + 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; + + /* 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 TRUE; +} + +void +DRICloseScreen(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv && pDRIPriv->directRenderingSupport) { + xfree(pDRIPriv); + pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; + } +} + +Bool +DRIExtensionInit(void) +{ + int i; + ScreenPtr pScreen; + + if (DRIScreenPrivIndex < 0) { + return FALSE; + } + + /* Allocate a window private index with a zero sized private area for + * each window, then should a window become a DRI window, we'll hang + * a DRIWindowPrivateRec off of this private index. + */ + if ((DRIWindowPrivIndex = AllocateWindowPrivateIndex()) < 0) + return FALSE; + if ((DRIPixmapPrivIndex = AllocatePixmapPrivateIndex()) < 0) + return FALSE; + + DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete); + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + if (!AllocateWindowPrivate(pScreen, DRIWindowPrivIndex, 0)) + return FALSE; + if (!AllocatePixmapPrivate(pScreen, DRIPixmapPrivIndex, 0)) + return FALSE; + } + + return TRUE; +} + +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) +{ + WindowPtr pTopWin; + 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; + + DRIStopDrawing (&pWin->drawable, FALSE); + + 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; + wc.height = pWin->drawable.height; + 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; + + pDRIDrawablePriv->x = pWin->drawable.x - pTopWin->borderWidth; + pDRIDrawablePriv->y = pWin->drawable.y - pTopWin->borderWidth; + + } 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); +} + +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); + DRIDrawablePrivPtr pDRIDrawablePriv; + WindowPtr pWin; + PixmapPtr pPix; + xp_window_id wid = 0; + + if (pDrawable->type == DRAWABLE_WINDOW) { + pWin = (WindowPtr)pDrawable; + pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + if (pDRIDrawablePriv == NULL) { + WindowPtr pTopWin; + xp_error err; + xp_window_changes wc; + + pTopWin = TopLevelParent (pWin); + + /* allocate a DRI Window Private record */ + if (!(pDRIDrawablePriv = xcalloc(1, sizeof(DRIDrawablePrivRec)))) { + return FALSE; + } + + pDRIDrawablePriv->pDraw = pDrawable; + pDRIDrawablePriv->pScreen = pScreen; + pDRIDrawablePriv->refCount = 0; + pDRIDrawablePriv->drawableIndex = -1; + pDRIDrawablePriv->notifiers = NULL; + + /* find the physical window */ + wid = RootlessGetPhysicalWindow (pTopWin, TRUE); + if (wid == 0) { + xfree (pDRIDrawablePriv); + return FALSE; + } + + /* allocate the physical surface */ + err = xp_create_surface (wid, &pDRIDrawablePriv->sid); + if (err != Success) { + xfree (pDRIDrawablePriv); + return FALSE; + } + + /* 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); + xfree (pDRIDrawablePriv); + return FALSE; + } + + /* save private off of preallocated index */ + pWin->devPrivates[DRIWindowPrivIndex].ptr = (pointer)pDRIDrawablePriv; + } + } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 + else if (pDrawable->type == DRAWABLE_PIXMAP) { + pPix = (PixmapPtr)pDrawable; + pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix); + if (pDRIDrawablePriv == NULL) { + xp_error err; + + /* allocate a DRI Window Private record */ + if (!(pDRIDrawablePriv = xcalloc(1, sizeof(DRIDrawablePrivRec)))) { + return FALSE; + } + + pDRIDrawablePriv->pDraw = pDrawable; + 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) { + xfree (pDRIDrawablePriv); + return FALSE; + } + + /* save private off of preallocated index */ + pPix->devPrivates[DRIPixmapPrivIndex].ptr = (pointer)pDRIDrawablePriv; + } + } +#endif + else { /* for GLX 1.3, a PBuffer */ + /* 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 + FIXME: how to export pixmaps? */ + if (client_id != 0 && wid != 0) + { + err = xp_export_surface (wid, pDRIDrawablePriv->sid, + client_id, key); + if (err != Success) { + xp_destroy_surface (pDRIDrawablePriv->sid); + xfree (pDRIDrawablePriv); + 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, + (void *) 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) { + if (notify != NULL) { + pDRIDrawablePriv->notifiers = x_hook_remove (pDRIDrawablePriv->notifiers, + notify, notify_data); + } + if (--pDRIDrawablePriv->refCount <= 0) { + /* This calls back to DRIDrawablePrivDelete + which frees the private area */ + 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); + DRIStopDrawing (pDrawable, FALSE); + pDRIPriv->drawing = x_list_remove (pDRIPriv->drawing, + pDRIDrawablePriv); + } else if (pDrawable->type == DRAWABLE_PIXMAP) { + pPix = (PixmapPtr)pDrawable; + pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix); + } + + if (pDRIDrawablePriv == NULL) + return FALSE; + + if (pDRIDrawablePriv->drawableIndex != -1) { + /* release drawable table entry */ + pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL; + } + + if (pDRIDrawablePriv->sid != 0) { + xp_destroy_surface (pDRIDrawablePriv->sid); + x_hash_table_remove (surface_hash, (void *) pDRIDrawablePriv->sid); + } + + 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) { + /* FIXME: something? */ + } + + 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); + } + } + + /* unwrap */ + pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; + + /* call lower layers */ + (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); + + /* rewrap */ + 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; + + /* unwrap */ + pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; + + /* call lower layers */ + returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind); + + /* rewrap */ + 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) { + /* unwrap */ + pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; + + /* call lower layers */ + (*pScreen->PostValidateTree)(pParent, pChild, kind); + + /* rewrap */ + 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; + } +} + +/* This lets get at the unwrapped functions so that they can correctly + * call the lowerlevel 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; +} + +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, + (void *) id, NULL); + } + + if (pDRIDrawablePriv == NULL) + return; + + if (kind == AppleDRISurfaceNotifyDestroyed) + { + pDRIDrawablePriv->sid = 0; + x_hash_table_remove (surface_hash, (void *) id); + } + + x_hook_run (pDRIDrawablePriv->notifiers, &arg); + + if (kind == AppleDRISurfaceNotifyDestroyed) + { + /* Kill off the handle. */ + + FreeResourceByType (pDRIDrawablePriv->pDraw->id, + DRIDrawablePrivResType, FALSE); + } +} + + +/* Experimental support for X drawing directly into VRAM surfaces. */ + +Bool +DRIStartDrawing (DrawablePtr pDraw) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 + return FALSE; +#else + DRIDrawablePrivPtr priv = NULL; + DRIScreenPrivPtr pDRIPriv; + + if (pDraw->type == DRAWABLE_WINDOW) + priv = DRI_DRAWABLE_PRIV_FROM_WINDOW ((WindowPtr)pDraw); +#if 0 + /* FIXME: support pixmaps */ + else if (pDraw->type == DRAWABLE_PIXMAP) + priv = DRI_DRAWABLE_PRIV_FROM_PIXMAP ((PixmapPtr)pDraw); +#endif + + if (priv == NULL) + return FALSE; + + pDRIPriv = DRI_SCREEN_PRIV(priv->pScreen); + + if (!priv->is_drawing) + { + xp_error err; + xp_box r; + + err = xp_lock_window (priv->sid, NULL, NULL, + &priv->data, &priv->rowbytes, &r); + if (err != Success) + return FALSE; + + if (pDraw->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr) pDraw; + int bw = wBorderWidth (pWin); + + priv->pixmap = + GetScratchPixmapHeader(pWin->drawable.pScreen, r.x2 - r.x1, + r.y2 - r.y1, pWin->drawable.depth, + pWin->drawable.bitsPerPixel, + priv->rowbytes, priv->data); + TranslatePixmapBase (priv->pixmap, + - (pWin->drawable.x - bw), + - (pWin->drawable.y - bw)); + } + + priv->is_drawing = TRUE; + pDRIPriv->drawing = x_list_prepend (pDRIPriv->drawing, priv); + } + + if (pDraw->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr) pDraw; + + priv->oldPixmap = pWin->drawable.pScreen->GetWindowPixmap (pWin); + pWin->drawable.pScreen->SetWindowPixmap (pWin, priv->pixmap); + } + + return TRUE; +#endif +} + +Bool +DRIStopDrawing (DrawablePtr pDraw, Bool flush) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 + return FALSE; +#else + DRIDrawablePrivPtr priv = NULL; + ScreenPtr pScreen; + DRIScreenPrivPtr pDRIPriv; + + if (pDraw->type == DRAWABLE_WINDOW) + priv = DRI_DRAWABLE_PRIV_FROM_WINDOW ((WindowPtr)pDraw); + else if (pDraw->type == DRAWABLE_PIXMAP) + priv = DRI_DRAWABLE_PRIV_FROM_PIXMAP ((PixmapPtr)pDraw); + + if (priv == NULL) + return FALSE; + + pScreen = priv->pScreen; + pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (priv->is_drawing) + { + xp_unlock_window (priv->sid, flush); + + if (pDraw->type == DRAWABLE_WINDOW) + { + FreeScratchPixmapHeader (priv->pixmap); + pScreen->SetWindowPixmap ((WindowPtr)pDraw, priv->oldPixmap); + } + + priv->pixmap = NULL; + + /* If we didn't flush don't forget that we still need to.. */ + if (flush) + pDRIPriv->drawing = x_list_remove (pDRIPriv->drawing, priv); + + priv->is_drawing = FALSE; + } + else if (flush) + { + xp_flush_window (priv->sid); + } + + return TRUE; +#endif /* 10.3 */ +} + +/* true iff two Boxes overlap */ +#define EXTENTCHECK(r1,r2) \ + (!( ((r1)->x2 <= (r2)->x1) || \ + ((r1)->x1 >= (r2)->x2) || \ + ((r1)->y2 <= (r2)->y1) || \ + ((r1)->y1 >= (r2)->y2) ) ) + +Bool +DRIDamageRegion (DrawablePtr pDraw, RegionPtr pRegion) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 + return FALSE; +#else + DRIDrawablePrivPtr priv = NULL; + RegionRec clipped; + BoxPtr b1, b2; + + if (pDraw->type == DRAWABLE_WINDOW) + priv = DRI_DRAWABLE_PRIV_FROM_WINDOW ((WindowPtr)pDraw); + + if (priv == NULL) + return FALSE; + + /* adapted from RootlessDamageRegion () */ + + if (pDraw->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr) pDraw; + + b1 = REGION_EXTENTS (pWin->drawable.pScreen, &pWin->borderClip); + b2 = REGION_EXTENTS (pWin->drawable.pScreen, pRegion); + + if (EXTENTCHECK (b1, b2)) + { + /* Regions may overlap. */ + + if (REGION_NUM_RECTS (pRegion) == 1) + { + int in; + + /* Damaged region only has a single rect, so we can + just compare that against the region */ + + in = RECT_IN_REGION (pWin->drawable.pScreen, &pWin->borderClip, + REGION_RECTS (pRegion)); + if (in == rgnIN) + { + /* clip totally contains pRegion */ + + xp_mark_window (priv->sid, REGION_NUM_RECTS (pRegion), + REGION_RECTS (pRegion), + -priv->x, -priv->y); + + RootlessQueueRedisplay (pWin->drawable.pScreen); + goto out; + } + else if (in == rgnOUT) + { + /* clip doesn't contain pRegion */ + + goto out; + } + } + + /* clip overlaps pRegion, need to intersect */ + + REGION_INIT (pWin->drawable.pScreen, &clipped, NullBox, 0); + REGION_INTERSECT (pWin->drawable.pScreen, &clipped, + &pWin->borderClip, pRegion); + + xp_mark_window (priv->sid, REGION_NUM_RECTS (&clipped), + REGION_RECTS (&clipped), -priv->x, -priv->y); + + REGION_UNINIT (pWin->drawable.pScreen, &clipped); + + RootlessQueueRedisplay (pWin->drawable.pScreen); + } + } + +out: + return TRUE; +#endif /* 10.3 */ +} + +void +DRISynchronizeDrawable (DrawablePtr pDraw, Bool flush) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 + ScreenPtr pScreen; + DRIScreenPrivPtr pDRIPriv; + DRIDrawablePrivPtr priv; + x_list *node, *copy; + + pScreen = pDraw->pScreen; + pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv == NULL || pDRIPriv->drawing == NULL) + return; + + if (pDraw->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = TopLevelParent ((WindowPtr) pDraw); + + /* need to find _any_ window under pWin that is drawing. Scan the + list looking for candidates. */ + + copy = x_list_copy (pDRIPriv->drawing); + + for (node = copy; node != NULL; node = node->next) + { + priv = node->data; + + if (priv->pDraw->type == DRAWABLE_WINDOW + && TopLevelParent ((WindowPtr) priv->pDraw) == pWin) + { + DRIStopDrawing (priv->pDraw, flush); + } + } + + x_list_free (copy); + } + else + { + DRIStopDrawing (pDraw, flush); + } +#endif /* 10.3 */ +} + +void +DRISynchronize (Bool flush) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 + int i; + ScreenPtr pScreen; + DRIScreenPrivPtr pDRIPriv; + DRIDrawablePrivPtr priv; + x_list *node, *copy; + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv == NULL || pDRIPriv->drawing == NULL) + continue; + + copy = x_list_copy (pDRIPriv->drawing); + + for (node = copy; node != NULL; node = node->next) + { + priv = node->data; + + DRIStopDrawing (priv->pDraw, flush); + } + + x_list_free (copy); + } +#endif /* 10.3 */ +}