static Bool TegraCloseScreen(CLOSE_SCREEN_ARGS_DECL) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TegraPtr tegra = TegraPTR(pScrn); if (tegra->damage) { DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, tegra->damage); DamageDestroy(tegra->damage); tegra->damage = NULL; } if (tegra->drmmode.shadow_enable) { shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen)); free(tegra->drmmode.shadow_fb); tegra->drmmode.shadow_fb = NULL; } drmmode_uevent_fini(pScrn, &tegra->drmmode); drmmode_free_bos(pScrn, &tegra->drmmode); if (pScrn->vtSema) TegraLeaveVT(VT_FUNC_ARGS); pScreen->CreateScreenResources = tegra->createScreenResources; pScreen->BlockHandler = tegra->BlockHandler; pScrn->vtSema = FALSE; pScreen->CloseScreen = tegra->CloseScreen; return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); }
void compFreePixmap (WindowPtr pWin) { ScreenPtr pScreen = pWin->drawable.pScreen; PixmapPtr pRedirectPixmap, pParentPixmap; CompWindowPtr cw = GetCompWindow (pWin); if (cw->damageRegistered) { DamageUnregister (&pWin->drawable, cw->damage); cw->damageRegistered = FALSE; DamageEmpty (cw->damage); } /* * Move the parent-constrained border clip region back into * the window so that ValidateTree will handle the unmap * case correctly. Unmap adds the window borderClip to the * parent exposed area; regions beyond the parent cause crashes */ RegionCopy(&pWin->borderClip, &cw->borderClip); pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin); pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent); pWin->redirectDraw = RedirectDrawNone; compSetPixmap (pWin, pParentPixmap); (*pScreen->DestroyPixmap) (pRedirectPixmap); }
void shadowRemove(ScreenPtr pScreen, PixmapPtr pPixmap) { shadowBuf(pScreen); if (pBuf->pPixmap) { DamageUnregister(&pBuf->pPixmap->drawable, pBuf->pDamage); pBuf->update = 0; pBuf->window = 0; pBuf->randr = 0; pBuf->closure = 0; pBuf->pPixmap = 0; } RemoveBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler, (pointer) pScreen); }
static void dispatch_dirty(ScreenPtr pScreen) { ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); modesettingPtr ms = modesettingPTR(scrn); PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen); int fb_id = ms->drmmode.fb_id; int ret; ret = dispatch_dirty_region(scrn, pixmap, ms->damage, fb_id); if (ret == -EINVAL || ret == -ENOSYS) { ms->dirty_enabled = FALSE; DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage); DamageDestroy(ms->damage); ms->damage = NULL; xf86DrvMsg(scrn->scrnIndex, X_INFO, "Disabling kernel dirty updates, not required.\n"); return; } }
static int FreeDamageExt(pointer value, XID did) { DamageExtPtr pDamageExt = (DamageExtPtr) value; /* * Get rid of the resource table entry hanging from the window id */ pDamageExt->id = 0; if (WindowDrawable(pDamageExt->pDrawable->type)) FreeResourceByType(pDamageExt->pDrawable->id, DamageExtWinType, TRUE); if (pDamageExt->pDamage) { DamageUnregister(pDamageExt->pDrawable, pDamageExt->pDamage); DamageDestroy(pDamageExt->pDamage); } free(pDamageExt); return Success; }
static void xf86RotateDestroy (xf86CrtcPtr crtc) { ScrnInfoPtr pScrn = crtc->scrn; ScreenPtr pScreen = pScrn->pScreen; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int c; /* Free memory from rotation */ if (crtc->rotatedPixmap || crtc->rotatedData) { crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap, crtc->rotatedData); crtc->rotatedPixmap = NULL; crtc->rotatedData = NULL; } for (c = 0; c < xf86_config->num_crtc; c++) if (xf86_config->crtc[c]->rotatedPixmap || xf86_config->crtc[c]->rotatedData) return; /* * Clean up damage structures when no crtcs are rotated */ if (xf86_config->rotation_damage) { /* Free damage structure */ if (xf86_config->rotation_damage_registered) { DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, xf86_config->rotation_damage); xf86_config->rotation_damage_registered = FALSE; } DamageDestroy (xf86_config->rotation_damage); xf86_config->rotation_damage = NULL; } }
/* * Redirect one window for one client */ int compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) { CompWindowPtr cw = GetCompWindow (pWin); CompClientWindowPtr ccw; Bool wasMapped = pWin->mapped; CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); if (pWin == cs->pOverlayWin) { return Success; } if (!pWin->parent) return BadMatch; /* * Only one Manual update is allowed */ if (cw && update == CompositeRedirectManual) for (ccw = cw->clients; ccw; ccw = ccw->next) if (ccw->update == CompositeRedirectManual) return BadAccess; /* * Allocate per-client per-window structure * The client *could* allocate multiple, but while supported, * it is not expected to be common */ ccw = malloc(sizeof (CompClientWindowRec)); if (!ccw) return BadAlloc; ccw->id = FakeClientID (pClient->index); ccw->update = update; /* * Now make sure there's a per-window structure to hang this from */ if (!cw) { cw = malloc(sizeof (CompWindowRec)); if (!cw) { free(ccw); return BadAlloc; } cw->damage = DamageCreate (compReportDamage, compDestroyDamage, DamageReportNonEmpty, FALSE, pWin->drawable.pScreen, pWin); if (!cw->damage) { free(ccw); free(cw); return BadAlloc; } if (wasMapped) { DisableMapUnmapEvents (pWin); UnmapWindow (pWin, FALSE); EnableMapUnmapEvents (pWin); } RegionNull(&cw->borderClip); cw->borderClipX = 0; cw->borderClipY = 0; cw->update = CompositeRedirectAutomatic; cw->clients = 0; cw->oldx = COMP_ORIGIN_INVALID; cw->oldy = COMP_ORIGIN_INVALID; cw->damageRegistered = FALSE; cw->damaged = FALSE; cw->pOldPixmap = NullPixmap; dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw); } ccw->next = cw->clients; cw->clients = ccw; if (!AddResource (ccw->id, CompositeClientWindowType, pWin)) return BadAlloc; if (ccw->update == CompositeRedirectManual) { /* If the window was CompositeRedirectAutomatic, then * unmap the window so that the parent clip list will * be correctly recomputed. */ if (pWin->mapped) { DisableMapUnmapEvents (pWin); UnmapWindow (pWin, FALSE); EnableMapUnmapEvents (pWin); } if (cw->damageRegistered) { DamageUnregister (&pWin->drawable, cw->damage); cw->damageRegistered = FALSE; } cw->update = CompositeRedirectManual; } if (!compCheckRedirect (pWin)) { FreeResource (ccw->id, RT_NONE); return BadAlloc; } if (wasMapped && !pWin->mapped) { Bool overrideRedirect = pWin->overrideRedirect; pWin->overrideRedirect = TRUE; DisableMapUnmapEvents (pWin); MapWindow (pWin, pClient); EnableMapUnmapEvents (pWin); pWin->overrideRedirect = overrideRedirect; } return Success; }
/* * Redirect one window for one client */ int compRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update) { CompWindowPtr cw = GetCompWindow(pWin); CompClientWindowPtr ccw; CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); WindowPtr pLayerWin = NULL; Bool anyMarked = FALSE; if (pWin == cs->pOverlayWin) { return Success; } if (!pWin->parent) return BadMatch; /* * Only one Manual update is allowed */ if (cw && update == CompositeRedirectManual) for (ccw = cw->clients; ccw; ccw = ccw->next) if (ccw->update == CompositeRedirectManual) return BadAccess; /* * Allocate per-client per-window structure * The client *could* allocate multiple, but while supported, * it is not expected to be common */ ccw = malloc(sizeof(CompClientWindowRec)); if (!ccw) return BadAlloc; ccw->id = FakeClientID(pClient->index); ccw->update = update; /* * Now make sure there's a per-window structure to hang this from */ if (!cw) { cw = malloc(sizeof(CompWindowRec)); if (!cw) { free(ccw); return BadAlloc; } cw->damage = DamageCreate(compReportDamage, compDestroyDamage, DamageReportNonEmpty, FALSE, pWin->drawable.pScreen, pWin); if (!cw->damage) { free(ccw); free(cw); return BadAlloc; } anyMarked = compMarkWindows(pWin, &pLayerWin); RegionNull(&cw->borderClip); cw->update = CompositeRedirectAutomatic; cw->clients = 0; cw->oldx = COMP_ORIGIN_INVALID; cw->oldy = COMP_ORIGIN_INVALID; cw->damageRegistered = FALSE; cw->damaged = FALSE; cw->pOldPixmap = NullPixmap; dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw); } ccw->next = cw->clients; cw->clients = ccw; if (!AddResource(ccw->id, CompositeClientWindowType, pWin)) return BadAlloc; if (ccw->update == CompositeRedirectManual) { if (!anyMarked) anyMarked = compMarkWindows(pWin, &pLayerWin); if (cw->damageRegistered) { DamageUnregister(&pWin->drawable, cw->damage); cw->damageRegistered = FALSE; } cw->update = CompositeRedirectManual; } else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) { if (!anyMarked) anyMarked = compMarkWindows(pWin, &pLayerWin); } if (!compCheckRedirect(pWin)) { FreeResource(ccw->id, RT_NONE); return BadAlloc; } if (anyMarked) compHandleMarkedWindows(pWin, pLayerWin); return Success; }
Bool xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) { ScrnInfoPtr pScrn = crtc->scrn; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); ScreenPtr pScreen = pScrn->pScreen; if (rotation == RR_Rotate_0) { /* Free memory from rotation */ if (crtc->rotatedPixmap || crtc->rotatedData) { crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap, crtc->rotatedData); crtc->rotatedPixmap = NULL; crtc->rotatedData = NULL; } if (xf86_config->rotation_damage) { /* Free damage structure */ DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, xf86_config->rotation_damage); xf86_config->rotation_damage_registered = FALSE; DamageDestroy (xf86_config->rotation_damage); xf86_config->rotation_damage = NULL; /* Free block/wakeup handler */ RemoveBlockAndWakeupHandlers (xf86RotateBlockHandler, xf86RotateWakeupHandler, (pointer) pScreen); } } else { /* * these are the size of the shadow pixmap, which * matches the mode, not the pre-rotated copy in the * frame buffer */ int width = mode->HDisplay; int height = mode->VDisplay; void *shadowData = crtc->rotatedData; PixmapPtr shadow = crtc->rotatedPixmap; int old_width = shadow ? shadow->drawable.width : 0; int old_height = shadow ? shadow->drawable.height : 0; /* Allocate memory for rotation */ if (old_width != width || old_height != height) { if (shadow || shadowData) { crtc->funcs->shadow_destroy (crtc, shadow, shadowData); crtc->rotatedPixmap = NULL; crtc->rotatedData = NULL; } shadowData = crtc->funcs->shadow_allocate (crtc, width, height); if (!shadowData) goto bail1; crtc->rotatedData = shadowData; /* shadow will be damaged in xf86RotatePrepare */ } else { /* mark shadowed area as damaged so it will be repainted */ xf86CrtcDamageShadow (crtc); } if (!xf86_config->rotation_damage) { /* Create damage structure */ xf86_config->rotation_damage = DamageCreate (NULL, NULL, DamageReportNone, TRUE, pScreen, pScreen); if (!xf86_config->rotation_damage) goto bail2; /* Assign block/wakeup handler */ if (!RegisterBlockAndWakeupHandlers (xf86RotateBlockHandler, xf86RotateWakeupHandler, (pointer) pScreen)) { goto bail3; } } if (0) { bail3: DamageDestroy (xf86_config->rotation_damage); xf86_config->rotation_damage = NULL; bail2: if (shadow || shadowData) { crtc->funcs->shadow_destroy (crtc, shadow, shadowData); crtc->rotatedPixmap = NULL; crtc->rotatedData = NULL; } bail1: if (old_width && old_height) crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc, NULL, old_width, old_height); return FALSE; } } /* All done */ return TRUE; }
/* With mixed pixmaps, if we fail to get direct access to the driver pixmap, we * use the DownloadFromScreen hook to retrieve contents to a copy in system * memory, perform software rendering on that and move back the results with the * UploadToScreen hook (see exaDamageReport_mixed). */ void exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg) { ExaPixmapPriv(pPixmap); Bool has_gpu_copy = exaPixmapHasGpuCopy(pPixmap); Bool success; success = ExaDoPrepareAccess(pPixmap, index); if (success && has_gpu_copy && pExaPixmap->pDamage) { /* You cannot do accelerated operations while a buffer is mapped. */ exaFinishAccess(&pPixmap->drawable, index); /* Update the gpu view of both deferred destination pixmaps and of * source pixmaps that were migrated with a bounding region. */ exaMoveInPixmap_mixed(pPixmap); success = ExaDoPrepareAccess(pPixmap, index); if (success) { /* We have a gpu pixmap that can be accessed, we don't need the cpu * copy anymore. Drivers that prefer DFS, should fail prepare * access. */ DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage); DamageDestroy(pExaPixmap->pDamage); pExaPixmap->pDamage = NULL; free(pExaPixmap->sys_ptr); pExaPixmap->sys_ptr = NULL; return; } } if (!success) { ExaMigrationRec pixmaps[1]; /* Do we need to allocate our system buffer? */ if (!pExaPixmap->sys_ptr) { pExaPixmap->sys_ptr = malloc(pExaPixmap->sys_pitch * pPixmap->drawable.height); if (!pExaPixmap->sys_ptr) FatalError("EXA: malloc failed for size %d bytes\n", pExaPixmap->sys_pitch * pPixmap->drawable.height); } if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) { pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; } else { pixmaps[0].as_dst = FALSE; pixmaps[0].as_src = TRUE; } pixmaps[0].pPix = pPixmap; pixmaps[0].pReg = pReg; if (!pExaPixmap->pDamage && (has_gpu_copy || !exaPixmapIsPinned(pPixmap))) { Bool as_dst = pixmaps[0].as_dst; /* Set up damage tracking */ pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL, DamageReportNonEmpty, TRUE, pPixmap->drawable.pScreen, pPixmap); DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage); /* This ensures that pending damage reflects the current operation. */ /* This is used by exa to optimize migration. */ DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE); if (has_gpu_copy) { exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width, pPixmap->drawable.height); /* We don't know which region of the destination will be damaged, * have to assume all of it */ if (as_dst) { pixmaps[0].as_dst = FALSE; pixmaps[0].as_src = TRUE; pixmaps[0].pReg = NULL; } exaCopyDirtyToSys(pixmaps); } if (as_dst) exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width, pPixmap->drawable.height); } else if (has_gpu_copy) exaCopyDirtyToSys(pixmaps); pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; pPixmap->devKind = pExaPixmap->sys_pitch; pExaPixmap->use_gpu_copy = FALSE; } }