/* 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 = xalloc(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) { xfree(pDRIDrawablePriv); return NULL; } /* allocate the physical surface */ err = xp_create_surface(wid, &pDRIDrawablePriv->sid); if (err != Success) { xfree(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); xfree(pDRIDrawablePriv); return NULL; } /* save private off of preallocated index */ dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, pDRIDrawablePriv); } *widPtr = wid; return pDRIDrawablePriv; }
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); }
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; xp_window_id wid = 0; if (pDrawable->type == DRAWABLE_WINDOW) { WindowPtr pWin = (WindowPtr)pDrawable; 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 = xalloc(sizeof(DRIDrawablePrivRec)))) { return FALSE; } pDRIDrawablePriv->pDraw = pDrawable; pDRIDrawablePriv->pScreen = pScreen; pDRIDrawablePriv->refCount = 0; pDRIDrawablePriv->drawableIndex = -1; pDRIDrawablePriv->notifiers = NULL; /* find the physical window */ wid = (xp_window_id) RootlessFrameForWindow(pWin, 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) { PixmapPtr 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 */ 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; }