1706f2543Smrg/************************************************************************** 2706f2543Smrg 3706f2543SmrgCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 4706f2543SmrgCopyright 2000 VA Linux Systems, Inc. 5706f2543SmrgCopyright (c) 2002, 2009 Apple Computer, Inc. 6706f2543SmrgAll Rights Reserved. 7706f2543Smrg 8706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a 9706f2543Smrgcopy of this software and associated documentation files (the 10706f2543Smrg"Software"), to deal in the Software without restriction, including 11706f2543Smrgwithout limitation the rights to use, copy, modify, merge, publish, 12706f2543Smrgdistribute, sub license, and/or sell copies of the Software, and to 13706f2543Smrgpermit persons to whom the Software is furnished to do so, subject to 14706f2543Smrgthe following conditions: 15706f2543Smrg 16706f2543SmrgThe above copyright notice and this permission notice (including the 17706f2543Smrgnext paragraph) shall be included in all copies or substantial portions 18706f2543Smrgof the Software. 19706f2543Smrg 20706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21706f2543SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22706f2543SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 23706f2543SmrgIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 24706f2543SmrgANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25706f2543SmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26706f2543SmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27706f2543Smrg 28706f2543Smrg**************************************************************************/ 29706f2543Smrg 30706f2543Smrg/* 31706f2543Smrg * Authors: 32706f2543Smrg * Jens Owen <jens@valinux.com> 33706f2543Smrg * Rickard E. (Rik) Faith <faith@valinux.com> 34706f2543Smrg * 35706f2543Smrg */ 36706f2543Smrg 37706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 38706f2543Smrg#include <dix-config.h> 39706f2543Smrg#endif 40706f2543Smrg 41706f2543Smrg#ifdef XFree86LOADER 42706f2543Smrg#include "xf86.h" 43706f2543Smrg#include "xf86_ansic.h" 44706f2543Smrg#else 45706f2543Smrg#include <sys/time.h> 46706f2543Smrg#include <unistd.h> 47706f2543Smrg#endif 48706f2543Smrg 49706f2543Smrg#include <X11/X.h> 50706f2543Smrg#include <X11/Xproto.h> 51706f2543Smrg#include <fcntl.h> 52706f2543Smrg#include <sys/mman.h> 53706f2543Smrg#include <sys/types.h> 54706f2543Smrg#include <sys/stat.h> 55706f2543Smrg#include "misc.h" 56706f2543Smrg#include "dixstruct.h" 57706f2543Smrg#include "extnsionst.h" 58706f2543Smrg#include "colormapst.h" 59706f2543Smrg#include "cursorstr.h" 60706f2543Smrg#include "scrnintstr.h" 61706f2543Smrg#include "windowstr.h" 62706f2543Smrg#include "servermd.h" 63706f2543Smrg#define _APPLEDRI_SERVER_ 64706f2543Smrg#include "appledristr.h" 65706f2543Smrg#include "swaprep.h" 66706f2543Smrg#include "dri.h" 67706f2543Smrg#include "dristruct.h" 68706f2543Smrg#include "mi.h" 69706f2543Smrg#include "mipointer.h" 70706f2543Smrg#include "rootless.h" 71706f2543Smrg#include "x-hash.h" 72706f2543Smrg#include "x-hook.h" 73706f2543Smrg#include "driWrap.h" 74706f2543Smrg 75706f2543Smrg#include <AvailabilityMacros.h> 76706f2543Smrg 77706f2543Smrgstatic DevPrivateKeyRec DRIScreenPrivKeyRec; 78706f2543Smrg#define DRIScreenPrivKey (&DRIScreenPrivKeyRec) 79706f2543Smrgstatic DevPrivateKeyRec DRIWindowPrivKeyRec; 80706f2543Smrg#define DRIWindowPrivKey (&DRIWindowPrivKeyRec) 81706f2543Smrgstatic DevPrivateKeyRec DRIPixmapPrivKeyRec; 82706f2543Smrg#define DRIPixmapPrivKey (&DRIPixmapPrivKeyRec) 83706f2543Smrgstatic DevPrivateKeyRec DRIPixmapBufferPrivKeyRec; 84706f2543Smrg#define DRIPixmapBufferPrivKey (&DRIPixmapBufferPrivKeyRec) 85706f2543Smrg 86706f2543Smrgstatic RESTYPE DRIDrawablePrivResType; 87706f2543Smrg 88706f2543Smrgstatic x_hash_table *surface_hash; /* maps surface ids -> drawablePrivs */ 89706f2543Smrg 90706f2543Smrgstatic Bool DRIFreePixmapImp(DrawablePtr pDrawable); 91706f2543Smrg 92706f2543Smrgtypedef struct { 93706f2543Smrg DrawablePtr pDrawable; 94706f2543Smrg int refCount; 95706f2543Smrg int bytesPerPixel; 96706f2543Smrg int width; 97706f2543Smrg int height; 98706f2543Smrg char shmPath[PATH_MAX]; 99706f2543Smrg int fd; /* From shm_open (for now) */ 100706f2543Smrg size_t length; /* length of buffer */ 101706f2543Smrg void *buffer; 102706f2543Smrg} DRIPixmapBuffer, *DRIPixmapBufferPtr; 103706f2543Smrg 104706f2543SmrgBool 105706f2543SmrgDRIScreenInit(ScreenPtr pScreen) 106706f2543Smrg{ 107706f2543Smrg DRIScreenPrivPtr pDRIPriv; 108706f2543Smrg int i; 109706f2543Smrg 110706f2543Smrg if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0)) 111706f2543Smrg return FALSE; 112706f2543Smrg if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0)) 113706f2543Smrg return FALSE; 114706f2543Smrg if (!dixRegisterPrivateKey(&DRIPixmapPrivKeyRec, PRIVATE_PIXMAP, 0)) 115706f2543Smrg return FALSE; 116706f2543Smrg if (!dixRegisterPrivateKey(&DRIPixmapBufferPrivKeyRec, PRIVATE_PIXMAP, 0)) 117706f2543Smrg return FALSE; 118706f2543Smrg 119706f2543Smrg pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec)); 120706f2543Smrg if (!pDRIPriv) { 121706f2543Smrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 122706f2543Smrg return FALSE; 123706f2543Smrg } 124706f2543Smrg 125706f2543Smrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv); 126706f2543Smrg pDRIPriv->directRenderingSupport = TRUE; 127706f2543Smrg pDRIPriv->nrWindows = 0; 128706f2543Smrg 129706f2543Smrg /* Initialize drawable tables */ 130706f2543Smrg for (i = 0; i < DRI_MAX_DRAWABLES; i++) { 131706f2543Smrg pDRIPriv->DRIDrawables[i] = NULL; 132706f2543Smrg } 133706f2543Smrg 134706f2543Smrg return TRUE; 135706f2543Smrg} 136706f2543Smrg 137706f2543SmrgBool 138706f2543SmrgDRIFinishScreenInit(ScreenPtr pScreen) 139706f2543Smrg{ 140706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 141706f2543Smrg 142706f2543Smrg /* Wrap DRI support */ 143706f2543Smrg pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; 144706f2543Smrg pScreen->ValidateTree = DRIValidateTree; 145706f2543Smrg 146706f2543Smrg pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; 147706f2543Smrg pScreen->PostValidateTree = DRIPostValidateTree; 148706f2543Smrg 149706f2543Smrg pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; 150706f2543Smrg pScreen->WindowExposures = DRIWindowExposures; 151706f2543Smrg 152706f2543Smrg pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; 153706f2543Smrg pScreen->CopyWindow = DRICopyWindow; 154706f2543Smrg 155706f2543Smrg pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; 156706f2543Smrg pScreen->ClipNotify = DRIClipNotify; 157706f2543Smrg 158706f2543Smrg // ErrorF("[DRI] screen %d installation complete\n", pScreen->myNum); 159706f2543Smrg 160706f2543Smrg return DRIWrapInit(pScreen); 161706f2543Smrg} 162706f2543Smrg 163706f2543Smrgvoid 164706f2543SmrgDRICloseScreen(ScreenPtr pScreen) 165706f2543Smrg{ 166706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 167706f2543Smrg 168706f2543Smrg if (pDRIPriv && pDRIPriv->directRenderingSupport) { 169706f2543Smrg free(pDRIPriv); 170706f2543Smrg dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 171706f2543Smrg } 172706f2543Smrg} 173706f2543Smrg 174706f2543SmrgBool 175706f2543SmrgDRIExtensionInit(void) 176706f2543Smrg{ 177706f2543Smrg DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete, 178706f2543Smrg "DRIDrawable"); 179706f2543Smrg 180706f2543Smrg return DRIDrawablePrivResType != 0; 181706f2543Smrg} 182706f2543Smrg 183706f2543Smrgvoid 184706f2543SmrgDRIReset(void) 185706f2543Smrg{ 186706f2543Smrg /* 187706f2543Smrg * This stub routine is called when the X Server recycles, resources 188706f2543Smrg * allocated by DRIExtensionInit need to be managed here. 189706f2543Smrg * 190706f2543Smrg * Currently this routine is a stub because all the interesting resources 191706f2543Smrg * are managed via the screen init process. 192706f2543Smrg */ 193706f2543Smrg} 194706f2543Smrg 195706f2543SmrgBool 196706f2543SmrgDRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable) 197706f2543Smrg{ 198706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 199706f2543Smrg 200706f2543Smrg if (pDRIPriv) 201706f2543Smrg *isCapable = pDRIPriv->directRenderingSupport; 202706f2543Smrg else 203706f2543Smrg *isCapable = FALSE; 204706f2543Smrg 205706f2543Smrg return TRUE; 206706f2543Smrg} 207706f2543Smrg 208706f2543SmrgBool 209706f2543SmrgDRIAuthConnection(ScreenPtr pScreen, unsigned int magic) 210706f2543Smrg{ 211706f2543Smrg#if 0 212706f2543Smrg /* FIXME: something? */ 213706f2543Smrg 214706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 215706f2543Smrg 216706f2543Smrg if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE; 217706f2543Smrg#endif 218706f2543Smrg return TRUE; 219706f2543Smrg} 220706f2543Smrg 221706f2543Smrgstatic void 222706f2543SmrgDRIUpdateSurface(DRIDrawablePrivPtr pDRIDrawablePriv, DrawablePtr pDraw) 223706f2543Smrg{ 224706f2543Smrg xp_window_changes wc; 225706f2543Smrg unsigned int flags = 0; 226706f2543Smrg 227706f2543Smrg if (pDRIDrawablePriv->sid == 0) 228706f2543Smrg return; 229706f2543Smrg 230706f2543Smrg#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 231706f2543Smrg wc.depth = (pDraw->bitsPerPixel == 32 ? XP_DEPTH_ARGB8888 232706f2543Smrg : pDraw->bitsPerPixel == 16 ? XP_DEPTH_RGB555 : XP_DEPTH_NIL); 233706f2543Smrg if (wc.depth != XP_DEPTH_NIL) 234706f2543Smrg flags |= XP_DEPTH; 235706f2543Smrg#endif 236706f2543Smrg 237706f2543Smrg if (pDraw->type == DRAWABLE_WINDOW) { 238706f2543Smrg WindowPtr pWin = (WindowPtr) pDraw; 239706f2543Smrg WindowPtr pTopWin = TopLevelParent(pWin); 240706f2543Smrg 241706f2543Smrg wc.x = pWin->drawable.x - (pTopWin->drawable.x - pTopWin->borderWidth); 242706f2543Smrg wc.y = pWin->drawable.y - (pTopWin->drawable.y - pTopWin->borderWidth); 243706f2543Smrg wc.width = pWin->drawable.width + 2 * pWin->borderWidth; 244706f2543Smrg wc.height = pWin->drawable.height + 2 * pWin->borderWidth; 245706f2543Smrg wc.bit_gravity = XP_GRAVITY_NONE; 246706f2543Smrg 247706f2543Smrg wc.shape_nrects = RegionNumRects(&pWin->clipList); 248706f2543Smrg wc.shape_rects = RegionRects(&pWin->clipList); 249706f2543Smrg wc.shape_tx = - (pTopWin->drawable.x - pTopWin->borderWidth); 250706f2543Smrg wc.shape_ty = - (pTopWin->drawable.y - pTopWin->borderWidth); 251706f2543Smrg 252706f2543Smrg flags |= XP_BOUNDS | XP_SHAPE; 253706f2543Smrg 254706f2543Smrg } else if (pDraw->type == DRAWABLE_PIXMAP) { 255706f2543Smrg wc.x = 0; 256706f2543Smrg wc.y = 0; 257706f2543Smrg wc.width = pDraw->width; 258706f2543Smrg wc.height = pDraw->height; 259706f2543Smrg wc.bit_gravity = XP_GRAVITY_NONE; 260706f2543Smrg flags |= XP_BOUNDS; 261706f2543Smrg } 262706f2543Smrg 263706f2543Smrg xp_configure_surface(pDRIDrawablePriv->sid, flags, &wc); 264706f2543Smrg} 265706f2543Smrg 266706f2543Smrg/* Return NULL if an error occurs. */ 267706f2543Smrgstatic DRIDrawablePrivPtr 268706f2543SmrgCreateSurfaceForWindow(ScreenPtr pScreen, WindowPtr pWin, xp_window_id *widPtr) { 269706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv; 270706f2543Smrg xp_window_id wid = 0; 271706f2543Smrg 272706f2543Smrg *widPtr = 0; 273706f2543Smrg 274706f2543Smrg pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 275706f2543Smrg 276706f2543Smrg if (pDRIDrawablePriv == NULL) { 277706f2543Smrg xp_error err; 278706f2543Smrg xp_window_changes wc; 279706f2543Smrg 280706f2543Smrg /* allocate a DRI Window Private record */ 281706f2543Smrg if (!(pDRIDrawablePriv = malloc(sizeof(*pDRIDrawablePriv)))) { 282706f2543Smrg return NULL; 283706f2543Smrg } 284706f2543Smrg 285706f2543Smrg pDRIDrawablePriv->pDraw = (DrawablePtr)pWin; 286706f2543Smrg pDRIDrawablePriv->pScreen = pScreen; 287706f2543Smrg pDRIDrawablePriv->refCount = 0; 288706f2543Smrg pDRIDrawablePriv->drawableIndex = -1; 289706f2543Smrg pDRIDrawablePriv->notifiers = NULL; 290706f2543Smrg 291706f2543Smrg /* find the physical window */ 292706f2543Smrg wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWin, TRUE)); 293706f2543Smrg 294706f2543Smrg if (wid == 0) { 295706f2543Smrg free(pDRIDrawablePriv); 296706f2543Smrg return NULL; 297706f2543Smrg } 298706f2543Smrg 299706f2543Smrg /* allocate the physical surface */ 300706f2543Smrg err = xp_create_surface(wid, &pDRIDrawablePriv->sid); 301706f2543Smrg 302706f2543Smrg if (err != Success) { 303706f2543Smrg free(pDRIDrawablePriv); 304706f2543Smrg return NULL; 305706f2543Smrg } 306706f2543Smrg 307706f2543Smrg /* Make it visible */ 308706f2543Smrg wc.stack_mode = XP_MAPPED_ABOVE; 309706f2543Smrg wc.sibling = 0; 310706f2543Smrg err = xp_configure_surface(pDRIDrawablePriv->sid, XP_STACKING, &wc); 311706f2543Smrg 312706f2543Smrg if (err != Success) { 313706f2543Smrg xp_destroy_surface(pDRIDrawablePriv->sid); 314706f2543Smrg free(pDRIDrawablePriv); 315706f2543Smrg return NULL; 316706f2543Smrg } 317706f2543Smrg 318706f2543Smrg /* save private off of preallocated index */ 319706f2543Smrg dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, 320706f2543Smrg pDRIDrawablePriv); 321706f2543Smrg } 322706f2543Smrg 323706f2543Smrg *widPtr = wid; 324706f2543Smrg 325706f2543Smrg return pDRIDrawablePriv; 326706f2543Smrg} 327706f2543Smrg 328706f2543Smrg/* Return NULL if an error occurs. */ 329706f2543Smrgstatic DRIDrawablePrivPtr 330706f2543SmrgCreateSurfaceForPixmap(ScreenPtr pScreen, PixmapPtr pPix) { 331706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv; 332706f2543Smrg 333706f2543Smrg pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix); 334706f2543Smrg 335706f2543Smrg if (pDRIDrawablePriv == NULL) { 336706f2543Smrg xp_error err; 337706f2543Smrg 338706f2543Smrg /* allocate a DRI Window Private record */ 339706f2543Smrg if (!(pDRIDrawablePriv = calloc(1, sizeof(*pDRIDrawablePriv)))) { 340706f2543Smrg return NULL; 341706f2543Smrg } 342706f2543Smrg 343706f2543Smrg pDRIDrawablePriv->pDraw = (DrawablePtr)pPix; 344706f2543Smrg pDRIDrawablePriv->pScreen = pScreen; 345706f2543Smrg pDRIDrawablePriv->refCount = 0; 346706f2543Smrg pDRIDrawablePriv->drawableIndex = -1; 347706f2543Smrg pDRIDrawablePriv->notifiers = NULL; 348706f2543Smrg 349706f2543Smrg /* Passing a null window id to Xplugin in 10.3+ asks for 350706f2543Smrg an accelerated offscreen surface. */ 351706f2543Smrg 352706f2543Smrg err = xp_create_surface(0, &pDRIDrawablePriv->sid); 353706f2543Smrg if (err != Success) { 354706f2543Smrg free(pDRIDrawablePriv); 355706f2543Smrg return NULL; 356706f2543Smrg } 357706f2543Smrg 358706f2543Smrg /* 359706f2543Smrg * The DRIUpdateSurface will be called to resize the surface 360706f2543Smrg * after this function, if the export is successful. 361706f2543Smrg */ 362706f2543Smrg 363706f2543Smrg /* save private off of preallocated index */ 364706f2543Smrg dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, 365706f2543Smrg pDRIDrawablePriv); 366706f2543Smrg } 367706f2543Smrg 368706f2543Smrg return pDRIDrawablePriv; 369706f2543Smrg} 370706f2543Smrg 371706f2543Smrg 372706f2543SmrgBool 373706f2543SmrgDRICreateSurface(ScreenPtr pScreen, Drawable id, 374706f2543Smrg DrawablePtr pDrawable, xp_client_id client_id, 375706f2543Smrg xp_surface_id *surface_id, unsigned int ret_key[2], 376706f2543Smrg void (*notify) (void *arg, void *data), void *notify_data) 377706f2543Smrg{ 378706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 379706f2543Smrg xp_window_id wid = 0; 380706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv; 381706f2543Smrg 382706f2543Smrg if (pDrawable->type == DRAWABLE_WINDOW) { 383706f2543Smrg pDRIDrawablePriv = CreateSurfaceForWindow(pScreen, 384706f2543Smrg (WindowPtr)pDrawable, &wid); 385706f2543Smrg 386706f2543Smrg if(NULL == pDRIDrawablePriv) 387706f2543Smrg return FALSE; /*error*/ 388706f2543Smrg } 389706f2543Smrg#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 390706f2543Smrg else if (pDrawable->type == DRAWABLE_PIXMAP) { 391706f2543Smrg pDRIDrawablePriv = CreateSurfaceForPixmap(pScreen, 392706f2543Smrg (PixmapPtr)pDrawable); 393706f2543Smrg 394706f2543Smrg if(NULL == pDRIDrawablePriv) 395706f2543Smrg return FALSE; /*error*/ 396706f2543Smrg } 397706f2543Smrg#endif 398706f2543Smrg else { 399706f2543Smrg /* We handle GLXPbuffers in a different way (via CGL). */ 400706f2543Smrg return FALSE; 401706f2543Smrg } 402706f2543Smrg 403706f2543Smrg 404706f2543Smrg /* Finish initialization of new surfaces */ 405706f2543Smrg if (pDRIDrawablePriv->refCount == 0) { 406706f2543Smrg unsigned int key[2] = {0}; 407706f2543Smrg xp_error err; 408706f2543Smrg 409706f2543Smrg /* try to give the client access to the surface */ 410706f2543Smrg if (client_id != 0) { 411706f2543Smrg /* 412706f2543Smrg * Xplugin accepts a 0 wid if the surface id is offscreen, such 413706f2543Smrg * as for a pixmap. 414706f2543Smrg */ 415706f2543Smrg err = xp_export_surface(wid, pDRIDrawablePriv->sid, 416706f2543Smrg client_id, key); 417706f2543Smrg if (err != Success) { 418706f2543Smrg xp_destroy_surface(pDRIDrawablePriv->sid); 419706f2543Smrg free(pDRIDrawablePriv); 420706f2543Smrg 421706f2543Smrg /* 422706f2543Smrg * Now set the dix privates to NULL that were previously set. 423706f2543Smrg * This prevents reusing an invalid pointer. 424706f2543Smrg */ 425706f2543Smrg if(pDrawable->type == DRAWABLE_WINDOW) { 426706f2543Smrg WindowPtr pWin = (WindowPtr)pDrawable; 427706f2543Smrg 428706f2543Smrg dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); 429706f2543Smrg } else if(pDrawable->type == DRAWABLE_PIXMAP) { 430706f2543Smrg PixmapPtr pPix = (PixmapPtr)pDrawable; 431706f2543Smrg 432706f2543Smrg dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL); 433706f2543Smrg } 434706f2543Smrg 435706f2543Smrg return FALSE; 436706f2543Smrg } 437706f2543Smrg } 438706f2543Smrg 439706f2543Smrg pDRIDrawablePriv->key[0] = key[0]; 440706f2543Smrg pDRIDrawablePriv->key[1] = key[1]; 441706f2543Smrg 442706f2543Smrg ++pDRIPriv->nrWindows; 443706f2543Smrg 444706f2543Smrg /* and stash it by surface id */ 445706f2543Smrg if (surface_hash == NULL) 446706f2543Smrg surface_hash = x_hash_table_new(NULL, NULL, NULL, NULL); 447706f2543Smrg x_hash_table_insert(surface_hash, 448706f2543Smrg x_cvt_uint_to_vptr(pDRIDrawablePriv->sid), pDRIDrawablePriv); 449706f2543Smrg 450706f2543Smrg /* track this in case this window is destroyed */ 451706f2543Smrg AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable); 452706f2543Smrg 453706f2543Smrg /* Initialize shape */ 454706f2543Smrg DRIUpdateSurface(pDRIDrawablePriv, pDrawable); 455706f2543Smrg } 456706f2543Smrg 457706f2543Smrg pDRIDrawablePriv->refCount++; 458706f2543Smrg 459706f2543Smrg *surface_id = pDRIDrawablePriv->sid; 460706f2543Smrg 461706f2543Smrg if (ret_key != NULL) { 462706f2543Smrg ret_key[0] = pDRIDrawablePriv->key[0]; 463706f2543Smrg ret_key[1] = pDRIDrawablePriv->key[1]; 464706f2543Smrg } 465706f2543Smrg 466706f2543Smrg if (notify != NULL) { 467706f2543Smrg pDRIDrawablePriv->notifiers = x_hook_add(pDRIDrawablePriv->notifiers, 468706f2543Smrg notify, notify_data); 469706f2543Smrg } 470706f2543Smrg 471706f2543Smrg return TRUE; 472706f2543Smrg} 473706f2543Smrg 474706f2543SmrgBool 475706f2543SmrgDRIDestroySurface(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable, 476706f2543Smrg void (*notify) (void *, void *), void *notify_data) 477706f2543Smrg{ 478706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv; 479706f2543Smrg 480706f2543Smrg if (pDrawable->type == DRAWABLE_WINDOW) { 481706f2543Smrg pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW((WindowPtr)pDrawable); 482706f2543Smrg } else if (pDrawable->type == DRAWABLE_PIXMAP) { 483706f2543Smrg pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP((PixmapPtr)pDrawable); 484706f2543Smrg } else { 485706f2543Smrg return FALSE; 486706f2543Smrg } 487706f2543Smrg 488706f2543Smrg if (pDRIDrawablePriv != NULL) { 489706f2543Smrg /* 490706f2543Smrg * This doesn't seem to be used, because notify is NULL in all callers. 491706f2543Smrg */ 492706f2543Smrg 493706f2543Smrg if (notify != NULL) { 494706f2543Smrg pDRIDrawablePriv->notifiers = x_hook_remove(pDRIDrawablePriv->notifiers, 495706f2543Smrg notify, notify_data); 496706f2543Smrg } 497706f2543Smrg 498706f2543Smrg --pDRIDrawablePriv->refCount; 499706f2543Smrg 500706f2543Smrg /* 501706f2543Smrg * Check if the drawable privates still have a reference to the 502706f2543Smrg * surface. 503706f2543Smrg */ 504706f2543Smrg 505706f2543Smrg if (pDRIDrawablePriv->refCount <= 0) { 506706f2543Smrg /* 507706f2543Smrg * This calls back to DRIDrawablePrivDelete which 508706f2543Smrg * frees the private area and dispatches events, if needed. 509706f2543Smrg */ 510706f2543Smrg FreeResourceByType(id, DRIDrawablePrivResType, FALSE); 511706f2543Smrg } 512706f2543Smrg } 513706f2543Smrg 514706f2543Smrg return TRUE; 515706f2543Smrg} 516706f2543Smrg 517706f2543Smrg/* 518706f2543Smrg * The assumption is that this is called when the refCount of a surface 519706f2543Smrg * drops to <= 0, or the window/pixmap is destroyed. 520706f2543Smrg */ 521706f2543SmrgBool 522706f2543SmrgDRIDrawablePrivDelete(pointer pResource, XID id) 523706f2543Smrg{ 524706f2543Smrg DrawablePtr pDrawable = (DrawablePtr)pResource; 525706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pDrawable->pScreen); 526706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv = NULL; 527706f2543Smrg WindowPtr pWin = NULL; 528706f2543Smrg PixmapPtr pPix = NULL; 529706f2543Smrg 530706f2543Smrg if (pDrawable->type == DRAWABLE_WINDOW) { 531706f2543Smrg pWin = (WindowPtr)pDrawable; 532706f2543Smrg pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 533706f2543Smrg } else if (pDrawable->type == DRAWABLE_PIXMAP) { 534706f2543Smrg pPix = (PixmapPtr)pDrawable; 535706f2543Smrg pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix); 536706f2543Smrg } 537706f2543Smrg 538706f2543Smrg if (pDRIDrawablePriv == NULL) { 539706f2543Smrg /* 540706f2543Smrg * We reuse __func__ and the resource type for the GLXPixmap code. 541706f2543Smrg * Attempt to free a pixmap buffer associated with the resource 542706f2543Smrg * if possible. 543706f2543Smrg */ 544706f2543Smrg return DRIFreePixmapImp(pDrawable); 545706f2543Smrg } 546706f2543Smrg 547706f2543Smrg if (pDRIDrawablePriv->drawableIndex != -1) { 548706f2543Smrg /* release drawable table entry */ 549706f2543Smrg pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL; 550706f2543Smrg } 551706f2543Smrg 552706f2543Smrg if (pDRIDrawablePriv->sid != 0) { 553706f2543Smrg DRISurfaceNotify(pDRIDrawablePriv->sid, AppleDRISurfaceNotifyDestroyed); 554706f2543Smrg } 555706f2543Smrg 556706f2543Smrg 557706f2543Smrg if (pDRIDrawablePriv->notifiers != NULL) 558706f2543Smrg x_hook_free(pDRIDrawablePriv->notifiers); 559706f2543Smrg 560706f2543Smrg free(pDRIDrawablePriv); 561706f2543Smrg 562706f2543Smrg if (pDrawable->type == DRAWABLE_WINDOW) { 563706f2543Smrg dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); 564706f2543Smrg } else if (pDrawable->type == DRAWABLE_PIXMAP) { 565706f2543Smrg dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL); 566706f2543Smrg } 567706f2543Smrg 568706f2543Smrg --pDRIPriv->nrWindows; 569706f2543Smrg 570706f2543Smrg return TRUE; 571706f2543Smrg} 572706f2543Smrg 573706f2543Smrgvoid 574706f2543SmrgDRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg) 575706f2543Smrg{ 576706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 577706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 578706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 579706f2543Smrg 580706f2543Smrg if (pDRIDrawablePriv) { 581706f2543Smrg /* FIXME: something? */ 582706f2543Smrg } 583706f2543Smrg 584706f2543Smrg pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; 585706f2543Smrg 586706f2543Smrg (*pScreen->WindowExposures)(pWin, prgn, bsreg); 587706f2543Smrg 588706f2543Smrg pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; 589706f2543Smrg pScreen->WindowExposures = DRIWindowExposures; 590706f2543Smrg} 591706f2543Smrg 592706f2543Smrgvoid 593706f2543SmrgDRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 594706f2543Smrg{ 595706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 596706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 597706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv; 598706f2543Smrg 599706f2543Smrg if (pDRIPriv->nrWindows > 0) { 600706f2543Smrg pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 601706f2543Smrg if (pDRIDrawablePriv != NULL) { 602706f2543Smrg DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable); 603706f2543Smrg } 604706f2543Smrg } 605706f2543Smrg 606706f2543Smrg /* unwrap */ 607706f2543Smrg pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; 608706f2543Smrg 609706f2543Smrg /* call lower layers */ 610706f2543Smrg (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); 611706f2543Smrg 612706f2543Smrg /* rewrap */ 613706f2543Smrg pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; 614706f2543Smrg pScreen->CopyWindow = DRICopyWindow; 615706f2543Smrg} 616706f2543Smrg 617706f2543Smrgint 618706f2543SmrgDRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) 619706f2543Smrg{ 620706f2543Smrg ScreenPtr pScreen = pParent->drawable.pScreen; 621706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 622706f2543Smrg int returnValue; 623706f2543Smrg 624706f2543Smrg /* unwrap */ 625706f2543Smrg pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; 626706f2543Smrg 627706f2543Smrg /* call lower layers */ 628706f2543Smrg returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind); 629706f2543Smrg 630706f2543Smrg /* rewrap */ 631706f2543Smrg pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; 632706f2543Smrg pScreen->ValidateTree = DRIValidateTree; 633706f2543Smrg 634706f2543Smrg return returnValue; 635706f2543Smrg} 636706f2543Smrg 637706f2543Smrgvoid 638706f2543SmrgDRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) 639706f2543Smrg{ 640706f2543Smrg ScreenPtr pScreen; 641706f2543Smrg DRIScreenPrivPtr pDRIPriv; 642706f2543Smrg 643706f2543Smrg if (pParent) { 644706f2543Smrg pScreen = pParent->drawable.pScreen; 645706f2543Smrg } else { 646706f2543Smrg pScreen = pChild->drawable.pScreen; 647706f2543Smrg } 648706f2543Smrg pDRIPriv = DRI_SCREEN_PRIV(pScreen); 649706f2543Smrg 650706f2543Smrg if (pDRIPriv->wrap.PostValidateTree) { 651706f2543Smrg /* unwrap */ 652706f2543Smrg pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; 653706f2543Smrg 654706f2543Smrg /* call lower layers */ 655706f2543Smrg (*pScreen->PostValidateTree)(pParent, pChild, kind); 656706f2543Smrg 657706f2543Smrg /* rewrap */ 658706f2543Smrg pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; 659706f2543Smrg pScreen->PostValidateTree = DRIPostValidateTree; 660706f2543Smrg } 661706f2543Smrg} 662706f2543Smrg 663706f2543Smrgvoid 664706f2543SmrgDRIClipNotify(WindowPtr pWin, int dx, int dy) 665706f2543Smrg{ 666706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 667706f2543Smrg DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 668706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv; 669706f2543Smrg 670706f2543Smrg if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { 671706f2543Smrg DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable); 672706f2543Smrg } 673706f2543Smrg 674706f2543Smrg if (pDRIPriv->wrap.ClipNotify) { 675706f2543Smrg pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; 676706f2543Smrg 677706f2543Smrg (*pScreen->ClipNotify)(pWin, dx, dy); 678706f2543Smrg 679706f2543Smrg pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; 680706f2543Smrg pScreen->ClipNotify = DRIClipNotify; 681706f2543Smrg } 682706f2543Smrg} 683706f2543Smrg 684706f2543Smrg/* This lets us get at the unwrapped functions so that they can correctly 685706f2543Smrg * call the lower level functions, and choose whether they will be 686706f2543Smrg * called at every level of recursion (eg in validatetree). 687706f2543Smrg */ 688706f2543SmrgDRIWrappedFuncsRec * 689706f2543SmrgDRIGetWrappedFuncs(ScreenPtr pScreen) 690706f2543Smrg{ 691706f2543Smrg return &(DRI_SCREEN_PRIV(pScreen)->wrap); 692706f2543Smrg} 693706f2543Smrg 694706f2543Smrgvoid 695706f2543SmrgDRIQueryVersion(int *majorVersion, 696706f2543Smrg int *minorVersion, 697706f2543Smrg int *patchVersion) 698706f2543Smrg{ 699706f2543Smrg *majorVersion = APPLE_DRI_MAJOR_VERSION; 700706f2543Smrg *minorVersion = APPLE_DRI_MINOR_VERSION; 701706f2543Smrg *patchVersion = APPLE_DRI_PATCH_VERSION; 702706f2543Smrg} 703706f2543Smrg 704706f2543Smrg/* 705706f2543Smrg * Note: this also cleans up the hash table in addition to notifying clients. 706706f2543Smrg * The sid/surface-id should not be used after this, because it will be 707706f2543Smrg * invalid. 708706f2543Smrg */ 709706f2543Smrgvoid 710706f2543SmrgDRISurfaceNotify(xp_surface_id id, int kind) 711706f2543Smrg{ 712706f2543Smrg DRIDrawablePrivPtr pDRIDrawablePriv = NULL; 713706f2543Smrg DRISurfaceNotifyArg arg; 714706f2543Smrg 715706f2543Smrg arg.id = id; 716706f2543Smrg arg.kind = kind; 717706f2543Smrg 718706f2543Smrg if (surface_hash != NULL) 719706f2543Smrg { 720706f2543Smrg pDRIDrawablePriv = x_hash_table_lookup(surface_hash, 721706f2543Smrg x_cvt_uint_to_vptr(id), NULL); 722706f2543Smrg } 723706f2543Smrg 724706f2543Smrg if (pDRIDrawablePriv == NULL) 725706f2543Smrg return; 726706f2543Smrg 727706f2543Smrg if (kind == AppleDRISurfaceNotifyDestroyed) 728706f2543Smrg { 729706f2543Smrg x_hash_table_remove(surface_hash, x_cvt_uint_to_vptr(id)); 730706f2543Smrg } 731706f2543Smrg 732706f2543Smrg x_hook_run(pDRIDrawablePriv->notifiers, &arg); 733706f2543Smrg 734706f2543Smrg if (kind == AppleDRISurfaceNotifyDestroyed) 735706f2543Smrg { 736706f2543Smrg xp_error error; 737706f2543Smrg 738706f2543Smrg error = xp_destroy_surface(pDRIDrawablePriv->sid); 739706f2543Smrg 740706f2543Smrg if(error) 741706f2543Smrg ErrorF("%s: xp_destroy_surface failed: %d\n", __func__, error); 742706f2543Smrg 743706f2543Smrg /* Guard against reuse, even though we are freeing after this. */ 744706f2543Smrg pDRIDrawablePriv->sid = 0; 745706f2543Smrg 746706f2543Smrg FreeResourceByType(pDRIDrawablePriv->pDraw->id, 747706f2543Smrg DRIDrawablePrivResType, FALSE); 748706f2543Smrg } 749706f2543Smrg} 750706f2543Smrg 751706f2543Smrg/* 752706f2543Smrg * This creates a shared memory buffer for use with GLXPixmaps 753706f2543Smrg * and AppleSGLX. 754706f2543Smrg */ 755706f2543SmrgBool DRICreatePixmap(ScreenPtr pScreen, Drawable id, 756706f2543Smrg DrawablePtr pDrawable, char *path, 757706f2543Smrg size_t pathmax) 758706f2543Smrg{ 759706f2543Smrg DRIPixmapBufferPtr shared; 760706f2543Smrg PixmapPtr pPix; 761706f2543Smrg 762706f2543Smrg if(pDrawable->type != DRAWABLE_PIXMAP) 763706f2543Smrg return FALSE; 764706f2543Smrg 765706f2543Smrg pPix = (PixmapPtr)pDrawable; 766706f2543Smrg 767706f2543Smrg shared = malloc(sizeof(*shared)); 768706f2543Smrg if(NULL == shared) { 769706f2543Smrg FatalError("failed to allocate DRIPixmapBuffer in %s\n", __func__); 770706f2543Smrg } 771706f2543Smrg 772706f2543Smrg shared->pDrawable = pDrawable; 773706f2543Smrg shared->refCount = 1; 774706f2543Smrg 775706f2543Smrg if(pDrawable->bitsPerPixel >= 24) { 776706f2543Smrg shared->bytesPerPixel = 4; 777706f2543Smrg } else if(pDrawable->bitsPerPixel <= 16) { 778706f2543Smrg shared->bytesPerPixel = 2; 779706f2543Smrg } 780706f2543Smrg 781706f2543Smrg shared->width = pDrawable->width; 782706f2543Smrg shared->height = pDrawable->height; 783706f2543Smrg 784706f2543Smrg if(-1 == snprintf(shared->shmPath, sizeof(shared->shmPath), 785706f2543Smrg "%d_0x%lx", getpid(), 786706f2543Smrg (unsigned long)id)) { 787706f2543Smrg FatalError("buffer overflow in %s\n", __func__); 788706f2543Smrg } 789706f2543Smrg 790706f2543Smrg shared->fd = shm_open(shared->shmPath, 791706f2543Smrg O_RDWR | O_EXCL | O_CREAT, 792706f2543Smrg S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH); 793706f2543Smrg 794706f2543Smrg if(-1 == shared->fd) { 795706f2543Smrg free(shared); 796706f2543Smrg return FALSE; 797706f2543Smrg } 798706f2543Smrg 799706f2543Smrg shared->length = shared->width * shared->height * shared->bytesPerPixel; 800706f2543Smrg 801706f2543Smrg if(-1 == ftruncate(shared->fd, shared->length)) { 802706f2543Smrg ErrorF("failed to ftruncate (extend) file."); 803706f2543Smrg shm_unlink(shared->shmPath); 804706f2543Smrg close(shared->fd); 805706f2543Smrg free(shared); 806706f2543Smrg return FALSE; 807706f2543Smrg } 808706f2543Smrg 809706f2543Smrg shared->buffer = mmap(NULL, shared->length, 810706f2543Smrg PROT_READ | PROT_WRITE, 811706f2543Smrg MAP_FILE | MAP_SHARED, shared->fd, 0); 812706f2543Smrg 813706f2543Smrg if(MAP_FAILED == shared->buffer) { 814706f2543Smrg ErrorF("failed to mmap shared memory."); 815706f2543Smrg shm_unlink(shared->shmPath); 816706f2543Smrg close(shared->fd); 817706f2543Smrg free(shared); 818706f2543Smrg return FALSE; 819706f2543Smrg } 820706f2543Smrg 821706f2543Smrg strncpy(path, shared->shmPath, pathmax); 822706f2543Smrg path[pathmax - 1] = '\0'; 823706f2543Smrg 824706f2543Smrg dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, shared); 825706f2543Smrg 826706f2543Smrg AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable); 827706f2543Smrg 828706f2543Smrg return TRUE; 829706f2543Smrg} 830706f2543Smrg 831706f2543Smrg 832706f2543SmrgBool DRIGetPixmapData(DrawablePtr pDrawable, int *width, int *height, 833706f2543Smrg int *pitch, int *bpp, void **ptr) { 834706f2543Smrg PixmapPtr pPix; 835706f2543Smrg DRIPixmapBufferPtr shared; 836706f2543Smrg 837706f2543Smrg if(pDrawable->type != DRAWABLE_PIXMAP) 838706f2543Smrg return FALSE; 839706f2543Smrg 840706f2543Smrg pPix = (PixmapPtr)pDrawable; 841706f2543Smrg 842706f2543Smrg shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey); 843706f2543Smrg 844706f2543Smrg if(NULL == shared) 845706f2543Smrg return FALSE; 846706f2543Smrg 847706f2543Smrg assert(pDrawable->width == shared->width); 848706f2543Smrg assert(pDrawable->height == shared->height); 849706f2543Smrg 850706f2543Smrg *width = shared->width; 851706f2543Smrg *height = shared->height; 852706f2543Smrg *bpp = shared->bytesPerPixel; 853706f2543Smrg *pitch = shared->width * shared->bytesPerPixel; 854706f2543Smrg *ptr = shared->buffer; 855706f2543Smrg 856706f2543Smrg return TRUE; 857706f2543Smrg} 858706f2543Smrg 859706f2543Smrgstatic Bool 860706f2543SmrgDRIFreePixmapImp(DrawablePtr pDrawable) { 861706f2543Smrg DRIPixmapBufferPtr shared; 862706f2543Smrg PixmapPtr pPix; 863706f2543Smrg 864706f2543Smrg if(pDrawable->type != DRAWABLE_PIXMAP) 865706f2543Smrg return FALSE; 866706f2543Smrg 867706f2543Smrg pPix = (PixmapPtr)pDrawable; 868706f2543Smrg 869706f2543Smrg shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey); 870706f2543Smrg 871706f2543Smrg if(NULL == shared) 872706f2543Smrg return FALSE; 873706f2543Smrg 874706f2543Smrg close(shared->fd); 875706f2543Smrg munmap(shared->buffer, shared->length); 876706f2543Smrg shm_unlink(shared->shmPath); 877706f2543Smrg free(shared); 878706f2543Smrg 879706f2543Smrg dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, (pointer)NULL); 880706f2543Smrg 881706f2543Smrg return TRUE; 882706f2543Smrg} 883706f2543Smrg 884706f2543Smrgvoid 885706f2543SmrgDRIDestroyPixmap(DrawablePtr pDrawable) { 886706f2543Smrg if(DRIFreePixmapImp(pDrawable)) 887706f2543Smrg FreeResourceByType(pDrawable->id, DRIDrawablePrivResType, FALSE); 888706f2543Smrg 889706f2543Smrg} 890