From f6a4690832143b01d419b52a4cb74350cdfa38bf Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 20 Jun 2011 09:58:44 +0200 Subject: [PATCH] vmwgfx: Make a list of scanout bounding boxes available to each scanout pixmap This info is needed for present readback. Signed-off-by: Thomas Hellstrom --- vmwgfx/vmwgfx_crtc.c | 46 +++++++++++++++++++++++++--------------------- vmwgfx/vmwgfx_saa.c | 30 +++++++++++++++++++++--------- vmwgfx/vmwgfx_saa.h | 12 +++++++++--- 3 files changed, 55 insertions(+), 33 deletions(-) diff --git a/vmwgfx/vmwgfx_crtc.c b/vmwgfx/vmwgfx_crtc.c index 49e84e8..8f8ced4 100644 --- a/vmwgfx/vmwgfx_crtc.c +++ b/vmwgfx/vmwgfx_crtc.c @@ -58,9 +58,11 @@ struct crtc_private /* hwcursor */ struct vmwgfx_dmabuf *cursor_bo; - PixmapPtr scanout; uint32_t scanout_id; unsigned cursor_handle; + + /* Scanout info for pixmaps */ + struct vmwgfx_screen_box box; }; static void @@ -87,14 +89,8 @@ crtc_dpms(xf86CrtcPtr crtc, int mode) * the crtc may be turned on again by * another dpms call, so don't release the scanout pixmap ref. */ - if (!crtc->enabled && crtcp->scanout) { - PixmapPtr pixmap = crtcp->scanout; - ScreenPtr pScreen = pixmap->drawable.pScreen; - - vmwgfx_scanout_unref(pixmap); - pScreen->DestroyPixmap(pixmap); - crtcp->scanout = NULL; - crtcp->scanout_id = -1; + if (!crtc->enabled && crtcp->box.pixmap) { + vmwgfx_scanout_unref(&crtcp->box); } break; } @@ -138,6 +134,7 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, int i, ret; unsigned int connector_id; PixmapPtr pixmap; + BoxPtr screen_box; for (i = 0; i < config->num_output; output = NULL, i++) { output = config->output[i]; @@ -188,17 +185,13 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, else pixmap = pScreen->GetScreenPixmap(pScreen); - if (crtcp->scanout != pixmap) { - if (crtcp->scanout) { - vmwgfx_scanout_unref(crtcp->scanout); - pScreen->DestroyPixmap(crtcp->scanout); - } - crtcp->scanout_id = vmwgfx_scanout_ref(pixmap); - if (crtcp->scanout_id != -1) { - pixmap->refcnt += 1; - crtcp->scanout = pixmap; - } else { - crtcp->scanout = NULL; + if (crtcp->box.pixmap != pixmap) { + if (crtcp->box.pixmap) + vmwgfx_scanout_unref(&crtcp->box); + + crtcp->box.pixmap = pixmap; + crtcp->scanout_id = vmwgfx_scanout_ref(&crtcp->box); + if (crtcp->scanout_id == -1) { LogMessage(X_ERROR, "Failed to convert pixmap to scanout.\n"); return FALSE; } @@ -208,6 +201,12 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, if (ret) return FALSE; + screen_box = &crtcp->box.box; + screen_box->x1 = crtc->x; + screen_box->y1 = crtc->y; + screen_box->x2 = screen_box->x1 + mode->HDisplay; + screen_box->y2 = screen_box->y1 + mode->VDisplay; + vmwgfx_scanout_refresh(pixmap); /* Only set gamma when needed, to avoid unneeded delays. */ @@ -379,6 +378,9 @@ crtc_destroy(xf86CrtcPtr crtc) { struct crtc_private *crtcp = crtc->driver_private; + if (!WSBMLISTEMPTY(&crtcp->box.scanout_head)) + vmwgfx_scanout_unref(&crtcp->box); + xorg_crtc_cursor_destroy(crtc); drmModeFreeCrtc(crtcp->drm_crtc); @@ -438,6 +440,8 @@ xorg_crtc_init(ScrnInfoPtr pScrn) } crtcp->drm_crtc = drm_crtc; + crtcp->box.pixmap = NULL; + WSBMINITLISTHEAD(&crtcp->box.scanout_head); crtc->driver_private = crtcp; } @@ -450,7 +454,7 @@ PixmapPtr crtc_get_scanout(xf86CrtcPtr crtc) { struct crtc_private *crtcp = crtc->driver_private; - return crtcp->scanout; + return crtcp->box.pixmap; } /* vim: set sw=4 ts=8 sts=4: */ diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index f733328..55b5fea 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -246,7 +246,6 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa, struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); RegionRec intersection; - if (!spix->damage || !REGION_NOTEMPTY(vsaa->pScreen, &spix->dirty_hw) || !vpix->dirty_present) return TRUE; @@ -266,6 +265,7 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa, if (!vmwgfx_pixmap_create_gmr(vsaa, pixmap)) goto out_err; + /* * FIXME: Cliprects may not overlap screen boundaries. */ @@ -431,6 +431,8 @@ vmwgfx_create_pixmap(struct saa_driver *driver, struct saa_pixmap *spix, *new_pitch = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); WSBMINITLISTHEAD(&vpix->sync_x_head); + WSBMINITLISTHEAD(&vpix->scanout_list); + return TRUE; } @@ -1126,14 +1128,15 @@ vmwgfx_scanout_refresh(PixmapPtr pixmap) */ uint32_t -vmwgfx_scanout_ref(PixmapPtr pixmap) +vmwgfx_scanout_ref(struct vmwgfx_screen_box *box) { + PixmapPtr pixmap = box->pixmap; struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); int ret; - if (vpix->scanout_refcnt++ == 0) { + if (WSBMLISTEMPTY(&vpix->scanout_list)) { ret = !vmwgfx_pixmap_create_gmr(vsaa, pixmap); if (!ret) ret = !vmwgfx_pixmap_add_present(pixmap); @@ -1146,14 +1149,17 @@ vmwgfx_scanout_ref(PixmapPtr pixmap) pixmap->devKind, vpix->gmr->handle, &vpix->fb_id); - if (!ret) { -// vmwgfx_scanout_refresh(pixmap); - } if (ret) { + box->pixmap = NULL; vpix->fb_id = -1; - --vpix->scanout_refcnt; + goto out_err; } + } + pixmap->refcnt += 1; + WSBMLISTADDTAIL(&box->scanout_head, &vpix->scanout_list); + + out_err: return vpix->fb_id; } @@ -1163,17 +1169,20 @@ vmwgfx_scanout_ref(PixmapPtr pixmap) * damage tracking and kms fbs. */ void -vmwgfx_scanout_unref(PixmapPtr pixmap) +vmwgfx_scanout_unref(struct vmwgfx_screen_box *box) { struct vmwgfx_saa *vsaa; struct vmwgfx_saa_pixmap *vpix; + PixmapPtr pixmap = box->pixmap; if (!pixmap) return; vsaa = to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); vpix = vmwgfx_saa_pixmap(pixmap); - if (--vpix->scanout_refcnt == 0) { + WSBMLISTDELINIT(&box->scanout_head); + + if (WSBMLISTEMPTY(&vpix->scanout_list)) { REGION_EMPTY(vsaa->pScreen, vpix->pending_update); drmModeRmFB(vsaa->drm_fd, vpix->fb_id); vpix->fb_id = -1; @@ -1181,4 +1190,7 @@ vmwgfx_scanout_unref(PixmapPtr pixmap) vmwgfx_pixmap_remove_present(vpix); vmwgfx_pixmap_remove_damage(pixmap); } + + box->pixmap = NULL; + pixmap->drawable.pScreen->DestroyPixmap(pixmap); } diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h index c7aae79..90fa728 100644 --- a/vmwgfx/vmwgfx_saa.h +++ b/vmwgfx/vmwgfx_saa.h @@ -49,10 +49,16 @@ struct vmwgfx_saa_pixmap { void *malloc; struct vmwgfx_dmabuf *gmr; struct xa_surface *hw; - int scanout_refcnt; uint32_t fb_id; int hw_is_dri2_fronts; struct _WsbmListHead sync_x_head; + struct _WsbmListHead scanout_list; +}; + +struct vmwgfx_screen_box { + BoxRec box; + struct _WsbmListHead scanout_head; + PixmapPtr pixmap; }; static inline struct vmwgfx_saa_pixmap * @@ -77,10 +83,10 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, void (*present_flush)(ScreenPtr pScreen)); extern uint32_t -vmwgfx_scanout_ref(PixmapPtr pixmap); +vmwgfx_scanout_ref(struct vmwgfx_screen_box *box); extern void -vmwgfx_scanout_unref(PixmapPtr pixmap); +vmwgfx_scanout_unref(struct vmwgfx_screen_box *box); extern void vmwgfx_scanout_refresh(PixmapPtr pixmap); -- 2.7.4