1/************************************************************************** 2 3Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 4Copyright 2000 VA Linux Systems, Inc. 5Copyright (c) 2002, 2009 Apple Computer, Inc. 6All Rights Reserved. 7 8Permission is hereby granted, free of charge, to any person obtaining a 9copy of this software and associated documentation files (the 10"Software"), to deal in the Software without restriction, including 11without limitation the rights to use, copy, modify, merge, publish, 12distribute, sub license, and/or sell copies of the Software, and to 13permit persons to whom the Software is furnished to do so, subject to 14the following conditions: 15 16The above copyright notice and this permission notice (including the 17next paragraph) shall be included in all copies or substantial portions 18of the Software. 19 20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 23IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 24ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 28**************************************************************************/ 29 30/* 31 * Authors: 32 * Jens Owen <jens@valinux.com> 33 * Rickard E. (Rik) Faith <faith@valinux.com> 34 * 35 */ 36 37#ifdef HAVE_DIX_CONFIG_H 38#include <dix-config.h> 39#endif 40 41#ifdef XFree86LOADER 42#include "xf86.h" 43#include "xf86_ansic.h" 44#else 45#include <sys/time.h> 46#include <unistd.h> 47#endif 48 49#include <X11/X.h> 50#include <X11/Xproto.h> 51#include <fcntl.h> 52#include <sys/mman.h> 53#include <sys/types.h> 54#include <sys/stat.h> 55#include "misc.h" 56#include "dixstruct.h" 57#include "extnsionst.h" 58#include "colormapst.h" 59#include "cursorstr.h" 60#include "scrnintstr.h" 61#include "windowstr.h" 62#include "servermd.h" 63#define _APPLEDRI_SERVER_ 64#include "appledristr.h" 65#include "swaprep.h" 66#include "dri.h" 67#include "dristruct.h" 68#include "mi.h" 69#include "mipointer.h" 70#include "rootless.h" 71#include "x-hash.h" 72#include "x-hook.h" 73#include "driWrap.h" 74 75#include <AvailabilityMacros.h> 76 77static DevPrivateKeyRec DRIScreenPrivKeyRec; 78#define DRIScreenPrivKey (&DRIScreenPrivKeyRec) 79static DevPrivateKeyRec DRIWindowPrivKeyRec; 80#define DRIWindowPrivKey (&DRIWindowPrivKeyRec) 81static DevPrivateKeyRec DRIPixmapPrivKeyRec; 82#define DRIPixmapPrivKey (&DRIPixmapPrivKeyRec) 83static DevPrivateKeyRec DRIPixmapBufferPrivKeyRec; 84#define DRIPixmapBufferPrivKey (&DRIPixmapBufferPrivKeyRec) 85 86static RESTYPE DRIDrawablePrivResType; 87 88static x_hash_table *surface_hash; /* maps surface ids -> drawablePrivs */ 89 90static Bool DRIFreePixmapImp(DrawablePtr pDrawable); 91 92typedef struct { 93 DrawablePtr pDrawable; 94 int refCount; 95 int bytesPerPixel; 96 int width; 97 int height; 98 char shmPath[PATH_MAX]; 99 int fd; /* From shm_open (for now) */ 100 size_t length; /* length of buffer */ 101 void *buffer; 102} DRIPixmapBuffer, *DRIPixmapBufferPtr; 103 104Bool 105DRIScreenInit(ScreenPtr pScreen) 106{ 107 DRIScreenPrivPtr pDRIPriv; 108 int i; 109 110 if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0)) 111 return FALSE; 112 if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0)) 113 return FALSE; 114 if (!dixRegisterPrivateKey(&DRIPixmapPrivKeyRec, PRIVATE_PIXMAP, 0)) 115 return FALSE; 116 if (!dixRegisterPrivateKey(&DRIPixmapBufferPrivKeyRec, PRIVATE_PIXMAP, 0)) 117 return FALSE; 118 119 pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec)); 120 if (!pDRIPriv) { 121 dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 122 return FALSE; 123 } 124 125 dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv); 126 pDRIPriv->directRenderingSupport = TRUE; 127 pDRIPriv->nrWindows = 0; 128 129 /* Initialize drawable tables */ 130 for (i = 0; i < DRI_MAX_DRAWABLES; i++) { 131 pDRIPriv->DRIDrawables[i] = NULL; 132 } 133 134 return TRUE; 135} 136 137Bool 138DRIFinishScreenInit(ScreenPtr pScreen) 139{ 140 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 141 142 /* Wrap DRI support */ 143 pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; 144 pScreen->ValidateTree = DRIValidateTree; 145 146 pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; 147 pScreen->PostValidateTree = DRIPostValidateTree; 148 149 pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; 150 pScreen->WindowExposures = DRIWindowExposures; 151 152 pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; 153 pScreen->CopyWindow = DRICopyWindow; 154 155 pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; 156 pScreen->ClipNotify = DRIClipNotify; 157 158 // ErrorF("[DRI] screen %d installation complete\n", pScreen->myNum); 159 160 return DRIWrapInit(pScreen); 161} 162 163void 164DRICloseScreen(ScreenPtr pScreen) 165{ 166 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 167 168 if (pDRIPriv && pDRIPriv->directRenderingSupport) { 169 free(pDRIPriv); 170 dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); 171 } 172} 173 174Bool 175DRIExtensionInit(void) 176{ 177 DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete, 178 "DRIDrawable"); 179 180 return DRIDrawablePrivResType != 0; 181} 182 183void 184DRIReset(void) 185{ 186 /* 187 * This stub routine is called when the X Server recycles, resources 188 * allocated by DRIExtensionInit need to be managed here. 189 * 190 * Currently this routine is a stub because all the interesting resources 191 * are managed via the screen init process. 192 */ 193} 194 195Bool 196DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable) 197{ 198 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 199 200 if (pDRIPriv) 201 *isCapable = pDRIPriv->directRenderingSupport; 202 else 203 *isCapable = FALSE; 204 205 return TRUE; 206} 207 208Bool 209DRIAuthConnection(ScreenPtr pScreen, unsigned int magic) 210{ 211#if 0 212 /* FIXME: something? */ 213 214 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 215 216 if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE; 217#endif 218 return TRUE; 219} 220 221static void 222DRIUpdateSurface(DRIDrawablePrivPtr pDRIDrawablePriv, DrawablePtr pDraw) 223{ 224 xp_window_changes wc; 225 unsigned int flags = 0; 226 227 if (pDRIDrawablePriv->sid == 0) 228 return; 229 230#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 231 wc.depth = (pDraw->bitsPerPixel == 32 ? XP_DEPTH_ARGB8888 232 : pDraw->bitsPerPixel == 16 ? XP_DEPTH_RGB555 : XP_DEPTH_NIL); 233 if (wc.depth != XP_DEPTH_NIL) 234 flags |= XP_DEPTH; 235#endif 236 237 if (pDraw->type == DRAWABLE_WINDOW) { 238 WindowPtr pWin = (WindowPtr) pDraw; 239 WindowPtr pTopWin = TopLevelParent(pWin); 240 241 wc.x = pWin->drawable.x - (pTopWin->drawable.x - pTopWin->borderWidth); 242 wc.y = pWin->drawable.y - (pTopWin->drawable.y - pTopWin->borderWidth); 243 wc.width = pWin->drawable.width + 2 * pWin->borderWidth; 244 wc.height = pWin->drawable.height + 2 * pWin->borderWidth; 245 wc.bit_gravity = XP_GRAVITY_NONE; 246 247 wc.shape_nrects = RegionNumRects(&pWin->clipList); 248 wc.shape_rects = RegionRects(&pWin->clipList); 249 wc.shape_tx = - (pTopWin->drawable.x - pTopWin->borderWidth); 250 wc.shape_ty = - (pTopWin->drawable.y - pTopWin->borderWidth); 251 252 flags |= XP_BOUNDS | XP_SHAPE; 253 254 } else if (pDraw->type == DRAWABLE_PIXMAP) { 255 wc.x = 0; 256 wc.y = 0; 257 wc.width = pDraw->width; 258 wc.height = pDraw->height; 259 wc.bit_gravity = XP_GRAVITY_NONE; 260 flags |= XP_BOUNDS; 261 } 262 263 xp_configure_surface(pDRIDrawablePriv->sid, flags, &wc); 264} 265 266/* Return NULL if an error occurs. */ 267static DRIDrawablePrivPtr 268CreateSurfaceForWindow(ScreenPtr pScreen, WindowPtr pWin, xp_window_id *widPtr) { 269 DRIDrawablePrivPtr pDRIDrawablePriv; 270 xp_window_id wid = 0; 271 272 *widPtr = 0; 273 274 pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 275 276 if (pDRIDrawablePriv == NULL) { 277 xp_error err; 278 xp_window_changes wc; 279 280 /* allocate a DRI Window Private record */ 281 if (!(pDRIDrawablePriv = malloc(sizeof(*pDRIDrawablePriv)))) { 282 return NULL; 283 } 284 285 pDRIDrawablePriv->pDraw = (DrawablePtr)pWin; 286 pDRIDrawablePriv->pScreen = pScreen; 287 pDRIDrawablePriv->refCount = 0; 288 pDRIDrawablePriv->drawableIndex = -1; 289 pDRIDrawablePriv->notifiers = NULL; 290 291 /* find the physical window */ 292 wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWin, TRUE)); 293 294 if (wid == 0) { 295 free(pDRIDrawablePriv); 296 return NULL; 297 } 298 299 /* allocate the physical surface */ 300 err = xp_create_surface(wid, &pDRIDrawablePriv->sid); 301 302 if (err != Success) { 303 free(pDRIDrawablePriv); 304 return NULL; 305 } 306 307 /* Make it visible */ 308 wc.stack_mode = XP_MAPPED_ABOVE; 309 wc.sibling = 0; 310 err = xp_configure_surface(pDRIDrawablePriv->sid, XP_STACKING, &wc); 311 312 if (err != Success) { 313 xp_destroy_surface(pDRIDrawablePriv->sid); 314 free(pDRIDrawablePriv); 315 return NULL; 316 } 317 318 /* save private off of preallocated index */ 319 dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, 320 pDRIDrawablePriv); 321 } 322 323 *widPtr = wid; 324 325 return pDRIDrawablePriv; 326} 327 328/* Return NULL if an error occurs. */ 329static DRIDrawablePrivPtr 330CreateSurfaceForPixmap(ScreenPtr pScreen, PixmapPtr pPix) { 331 DRIDrawablePrivPtr pDRIDrawablePriv; 332 333 pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix); 334 335 if (pDRIDrawablePriv == NULL) { 336 xp_error err; 337 338 /* allocate a DRI Window Private record */ 339 if (!(pDRIDrawablePriv = calloc(1, sizeof(*pDRIDrawablePriv)))) { 340 return NULL; 341 } 342 343 pDRIDrawablePriv->pDraw = (DrawablePtr)pPix; 344 pDRIDrawablePriv->pScreen = pScreen; 345 pDRIDrawablePriv->refCount = 0; 346 pDRIDrawablePriv->drawableIndex = -1; 347 pDRIDrawablePriv->notifiers = NULL; 348 349 /* Passing a null window id to Xplugin in 10.3+ asks for 350 an accelerated offscreen surface. */ 351 352 err = xp_create_surface(0, &pDRIDrawablePriv->sid); 353 if (err != Success) { 354 free(pDRIDrawablePriv); 355 return NULL; 356 } 357 358 /* 359 * The DRIUpdateSurface will be called to resize the surface 360 * after this function, if the export is successful. 361 */ 362 363 /* save private off of preallocated index */ 364 dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, 365 pDRIDrawablePriv); 366 } 367 368 return pDRIDrawablePriv; 369} 370 371 372Bool 373DRICreateSurface(ScreenPtr pScreen, Drawable id, 374 DrawablePtr pDrawable, xp_client_id client_id, 375 xp_surface_id *surface_id, unsigned int ret_key[2], 376 void (*notify) (void *arg, void *data), void *notify_data) 377{ 378 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 379 xp_window_id wid = 0; 380 DRIDrawablePrivPtr pDRIDrawablePriv; 381 382 if (pDrawable->type == DRAWABLE_WINDOW) { 383 pDRIDrawablePriv = CreateSurfaceForWindow(pScreen, 384 (WindowPtr)pDrawable, &wid); 385 386 if(NULL == pDRIDrawablePriv) 387 return FALSE; /*error*/ 388 } 389#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 390 else if (pDrawable->type == DRAWABLE_PIXMAP) { 391 pDRIDrawablePriv = CreateSurfaceForPixmap(pScreen, 392 (PixmapPtr)pDrawable); 393 394 if(NULL == pDRIDrawablePriv) 395 return FALSE; /*error*/ 396 } 397#endif 398 else { 399 /* We handle GLXPbuffers in a different way (via CGL). */ 400 return FALSE; 401 } 402 403 404 /* Finish initialization of new surfaces */ 405 if (pDRIDrawablePriv->refCount == 0) { 406 unsigned int key[2] = {0}; 407 xp_error err; 408 409 /* try to give the client access to the surface */ 410 if (client_id != 0) { 411 /* 412 * Xplugin accepts a 0 wid if the surface id is offscreen, such 413 * as for a pixmap. 414 */ 415 err = xp_export_surface(wid, pDRIDrawablePriv->sid, 416 client_id, key); 417 if (err != Success) { 418 xp_destroy_surface(pDRIDrawablePriv->sid); 419 free(pDRIDrawablePriv); 420 421 /* 422 * Now set the dix privates to NULL that were previously set. 423 * This prevents reusing an invalid pointer. 424 */ 425 if(pDrawable->type == DRAWABLE_WINDOW) { 426 WindowPtr pWin = (WindowPtr)pDrawable; 427 428 dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); 429 } else if(pDrawable->type == DRAWABLE_PIXMAP) { 430 PixmapPtr pPix = (PixmapPtr)pDrawable; 431 432 dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL); 433 } 434 435 return FALSE; 436 } 437 } 438 439 pDRIDrawablePriv->key[0] = key[0]; 440 pDRIDrawablePriv->key[1] = key[1]; 441 442 ++pDRIPriv->nrWindows; 443 444 /* and stash it by surface id */ 445 if (surface_hash == NULL) 446 surface_hash = x_hash_table_new(NULL, NULL, NULL, NULL); 447 x_hash_table_insert(surface_hash, 448 x_cvt_uint_to_vptr(pDRIDrawablePriv->sid), pDRIDrawablePriv); 449 450 /* track this in case this window is destroyed */ 451 AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable); 452 453 /* Initialize shape */ 454 DRIUpdateSurface(pDRIDrawablePriv, pDrawable); 455 } 456 457 pDRIDrawablePriv->refCount++; 458 459 *surface_id = pDRIDrawablePriv->sid; 460 461 if (ret_key != NULL) { 462 ret_key[0] = pDRIDrawablePriv->key[0]; 463 ret_key[1] = pDRIDrawablePriv->key[1]; 464 } 465 466 if (notify != NULL) { 467 pDRIDrawablePriv->notifiers = x_hook_add(pDRIDrawablePriv->notifiers, 468 notify, notify_data); 469 } 470 471 return TRUE; 472} 473 474Bool 475DRIDestroySurface(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable, 476 void (*notify) (void *, void *), void *notify_data) 477{ 478 DRIDrawablePrivPtr pDRIDrawablePriv; 479 480 if (pDrawable->type == DRAWABLE_WINDOW) { 481 pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW((WindowPtr)pDrawable); 482 } else if (pDrawable->type == DRAWABLE_PIXMAP) { 483 pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP((PixmapPtr)pDrawable); 484 } else { 485 return FALSE; 486 } 487 488 if (pDRIDrawablePriv != NULL) { 489 /* 490 * This doesn't seem to be used, because notify is NULL in all callers. 491 */ 492 493 if (notify != NULL) { 494 pDRIDrawablePriv->notifiers = x_hook_remove(pDRIDrawablePriv->notifiers, 495 notify, notify_data); 496 } 497 498 --pDRIDrawablePriv->refCount; 499 500 /* 501 * Check if the drawable privates still have a reference to the 502 * surface. 503 */ 504 505 if (pDRIDrawablePriv->refCount <= 0) { 506 /* 507 * This calls back to DRIDrawablePrivDelete which 508 * frees the private area and dispatches events, if needed. 509 */ 510 FreeResourceByType(id, DRIDrawablePrivResType, FALSE); 511 } 512 } 513 514 return TRUE; 515} 516 517/* 518 * The assumption is that this is called when the refCount of a surface 519 * drops to <= 0, or the window/pixmap is destroyed. 520 */ 521Bool 522DRIDrawablePrivDelete(pointer pResource, XID id) 523{ 524 DrawablePtr pDrawable = (DrawablePtr)pResource; 525 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pDrawable->pScreen); 526 DRIDrawablePrivPtr pDRIDrawablePriv = NULL; 527 WindowPtr pWin = NULL; 528 PixmapPtr pPix = NULL; 529 530 if (pDrawable->type == DRAWABLE_WINDOW) { 531 pWin = (WindowPtr)pDrawable; 532 pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 533 } else if (pDrawable->type == DRAWABLE_PIXMAP) { 534 pPix = (PixmapPtr)pDrawable; 535 pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix); 536 } 537 538 if (pDRIDrawablePriv == NULL) { 539 /* 540 * We reuse __func__ and the resource type for the GLXPixmap code. 541 * Attempt to free a pixmap buffer associated with the resource 542 * if possible. 543 */ 544 return DRIFreePixmapImp(pDrawable); 545 } 546 547 if (pDRIDrawablePriv->drawableIndex != -1) { 548 /* release drawable table entry */ 549 pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL; 550 } 551 552 if (pDRIDrawablePriv->sid != 0) { 553 DRISurfaceNotify(pDRIDrawablePriv->sid, AppleDRISurfaceNotifyDestroyed); 554 } 555 556 557 if (pDRIDrawablePriv->notifiers != NULL) 558 x_hook_free(pDRIDrawablePriv->notifiers); 559 560 free(pDRIDrawablePriv); 561 562 if (pDrawable->type == DRAWABLE_WINDOW) { 563 dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); 564 } else if (pDrawable->type == DRAWABLE_PIXMAP) { 565 dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL); 566 } 567 568 --pDRIPriv->nrWindows; 569 570 return TRUE; 571} 572 573void 574DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg) 575{ 576 ScreenPtr pScreen = pWin->drawable.pScreen; 577 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 578 DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 579 580 if (pDRIDrawablePriv) { 581 /* FIXME: something? */ 582 } 583 584 pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; 585 586 (*pScreen->WindowExposures)(pWin, prgn, bsreg); 587 588 pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; 589 pScreen->WindowExposures = DRIWindowExposures; 590} 591 592void 593DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 594{ 595 ScreenPtr pScreen = pWin->drawable.pScreen; 596 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 597 DRIDrawablePrivPtr pDRIDrawablePriv; 598 599 if (pDRIPriv->nrWindows > 0) { 600 pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); 601 if (pDRIDrawablePriv != NULL) { 602 DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable); 603 } 604 } 605 606 /* unwrap */ 607 pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; 608 609 /* call lower layers */ 610 (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); 611 612 /* rewrap */ 613 pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; 614 pScreen->CopyWindow = DRICopyWindow; 615} 616 617int 618DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) 619{ 620 ScreenPtr pScreen = pParent->drawable.pScreen; 621 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 622 int returnValue; 623 624 /* unwrap */ 625 pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; 626 627 /* call lower layers */ 628 returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind); 629 630 /* rewrap */ 631 pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; 632 pScreen->ValidateTree = DRIValidateTree; 633 634 return returnValue; 635} 636 637void 638DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) 639{ 640 ScreenPtr pScreen; 641 DRIScreenPrivPtr pDRIPriv; 642 643 if (pParent) { 644 pScreen = pParent->drawable.pScreen; 645 } else { 646 pScreen = pChild->drawable.pScreen; 647 } 648 pDRIPriv = DRI_SCREEN_PRIV(pScreen); 649 650 if (pDRIPriv->wrap.PostValidateTree) { 651 /* unwrap */ 652 pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; 653 654 /* call lower layers */ 655 (*pScreen->PostValidateTree)(pParent, pChild, kind); 656 657 /* rewrap */ 658 pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; 659 pScreen->PostValidateTree = DRIPostValidateTree; 660 } 661} 662 663void 664DRIClipNotify(WindowPtr pWin, int dx, int dy) 665{ 666 ScreenPtr pScreen = pWin->drawable.pScreen; 667 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); 668 DRIDrawablePrivPtr pDRIDrawablePriv; 669 670 if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { 671 DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable); 672 } 673 674 if (pDRIPriv->wrap.ClipNotify) { 675 pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; 676 677 (*pScreen->ClipNotify)(pWin, dx, dy); 678 679 pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; 680 pScreen->ClipNotify = DRIClipNotify; 681 } 682} 683 684/* This lets us get at the unwrapped functions so that they can correctly 685 * call the lower level functions, and choose whether they will be 686 * called at every level of recursion (eg in validatetree). 687 */ 688DRIWrappedFuncsRec * 689DRIGetWrappedFuncs(ScreenPtr pScreen) 690{ 691 return &(DRI_SCREEN_PRIV(pScreen)->wrap); 692} 693 694void 695DRIQueryVersion(int *majorVersion, 696 int *minorVersion, 697 int *patchVersion) 698{ 699 *majorVersion = APPLE_DRI_MAJOR_VERSION; 700 *minorVersion = APPLE_DRI_MINOR_VERSION; 701 *patchVersion = APPLE_DRI_PATCH_VERSION; 702} 703 704/* 705 * Note: this also cleans up the hash table in addition to notifying clients. 706 * The sid/surface-id should not be used after this, because it will be 707 * invalid. 708 */ 709void 710DRISurfaceNotify(xp_surface_id id, int kind) 711{ 712 DRIDrawablePrivPtr pDRIDrawablePriv = NULL; 713 DRISurfaceNotifyArg arg; 714 715 arg.id = id; 716 arg.kind = kind; 717 718 if (surface_hash != NULL) 719 { 720 pDRIDrawablePriv = x_hash_table_lookup(surface_hash, 721 x_cvt_uint_to_vptr(id), NULL); 722 } 723 724 if (pDRIDrawablePriv == NULL) 725 return; 726 727 if (kind == AppleDRISurfaceNotifyDestroyed) 728 { 729 x_hash_table_remove(surface_hash, x_cvt_uint_to_vptr(id)); 730 } 731 732 x_hook_run(pDRIDrawablePriv->notifiers, &arg); 733 734 if (kind == AppleDRISurfaceNotifyDestroyed) 735 { 736 xp_error error; 737 738 error = xp_destroy_surface(pDRIDrawablePriv->sid); 739 740 if(error) 741 ErrorF("%s: xp_destroy_surface failed: %d\n", __func__, error); 742 743 /* Guard against reuse, even though we are freeing after this. */ 744 pDRIDrawablePriv->sid = 0; 745 746 FreeResourceByType(pDRIDrawablePriv->pDraw->id, 747 DRIDrawablePrivResType, FALSE); 748 } 749} 750 751/* 752 * This creates a shared memory buffer for use with GLXPixmaps 753 * and AppleSGLX. 754 */ 755Bool DRICreatePixmap(ScreenPtr pScreen, Drawable id, 756 DrawablePtr pDrawable, char *path, 757 size_t pathmax) 758{ 759 DRIPixmapBufferPtr shared; 760 PixmapPtr pPix; 761 762 if(pDrawable->type != DRAWABLE_PIXMAP) 763 return FALSE; 764 765 pPix = (PixmapPtr)pDrawable; 766 767 shared = malloc(sizeof(*shared)); 768 if(NULL == shared) { 769 FatalError("failed to allocate DRIPixmapBuffer in %s\n", __func__); 770 } 771 772 shared->pDrawable = pDrawable; 773 shared->refCount = 1; 774 775 if(pDrawable->bitsPerPixel >= 24) { 776 shared->bytesPerPixel = 4; 777 } else if(pDrawable->bitsPerPixel <= 16) { 778 shared->bytesPerPixel = 2; 779 } 780 781 shared->width = pDrawable->width; 782 shared->height = pDrawable->height; 783 784 if(-1 == snprintf(shared->shmPath, sizeof(shared->shmPath), 785 "%d_0x%lx", getpid(), 786 (unsigned long)id)) { 787 FatalError("buffer overflow in %s\n", __func__); 788 } 789 790 shared->fd = shm_open(shared->shmPath, 791 O_RDWR | O_EXCL | O_CREAT, 792 S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH); 793 794 if(-1 == shared->fd) { 795 free(shared); 796 return FALSE; 797 } 798 799 shared->length = shared->width * shared->height * shared->bytesPerPixel; 800 801 if(-1 == ftruncate(shared->fd, shared->length)) { 802 ErrorF("failed to ftruncate (extend) file."); 803 shm_unlink(shared->shmPath); 804 close(shared->fd); 805 free(shared); 806 return FALSE; 807 } 808 809 shared->buffer = mmap(NULL, shared->length, 810 PROT_READ | PROT_WRITE, 811 MAP_FILE | MAP_SHARED, shared->fd, 0); 812 813 if(MAP_FAILED == shared->buffer) { 814 ErrorF("failed to mmap shared memory."); 815 shm_unlink(shared->shmPath); 816 close(shared->fd); 817 free(shared); 818 return FALSE; 819 } 820 821 strncpy(path, shared->shmPath, pathmax); 822 path[pathmax - 1] = '\0'; 823 824 dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, shared); 825 826 AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable); 827 828 return TRUE; 829} 830 831 832Bool DRIGetPixmapData(DrawablePtr pDrawable, int *width, int *height, 833 int *pitch, int *bpp, void **ptr) { 834 PixmapPtr pPix; 835 DRIPixmapBufferPtr shared; 836 837 if(pDrawable->type != DRAWABLE_PIXMAP) 838 return FALSE; 839 840 pPix = (PixmapPtr)pDrawable; 841 842 shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey); 843 844 if(NULL == shared) 845 return FALSE; 846 847 assert(pDrawable->width == shared->width); 848 assert(pDrawable->height == shared->height); 849 850 *width = shared->width; 851 *height = shared->height; 852 *bpp = shared->bytesPerPixel; 853 *pitch = shared->width * shared->bytesPerPixel; 854 *ptr = shared->buffer; 855 856 return TRUE; 857} 858 859static Bool 860DRIFreePixmapImp(DrawablePtr pDrawable) { 861 DRIPixmapBufferPtr shared; 862 PixmapPtr pPix; 863 864 if(pDrawable->type != DRAWABLE_PIXMAP) 865 return FALSE; 866 867 pPix = (PixmapPtr)pDrawable; 868 869 shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey); 870 871 if(NULL == shared) 872 return FALSE; 873 874 close(shared->fd); 875 munmap(shared->buffer, shared->length); 876 shm_unlink(shared->shmPath); 877 free(shared); 878 879 dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, (pointer)NULL); 880 881 return TRUE; 882} 883 884void 885DRIDestroyPixmap(DrawablePtr pDrawable) { 886 if(DRIFreePixmapImp(pDrawable)) 887 FreeResourceByType(pDrawable->id, DRIDrawablePrivResType, FALSE); 888 889} 890