vmwgfx: Make a list of scanout bounding boxes available to each scanout pixmap
authorThomas Hellstrom <thellstrom@vmware.com>
Mon, 20 Jun 2011 07:58:44 +0000 (09:58 +0200)
committerThomas Hellstrom <thellstrom@vmware.com>
Wed, 22 Jun 2011 20:34:43 +0000 (22:34 +0200)
This info is needed for present readback.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
vmwgfx/vmwgfx_crtc.c
vmwgfx/vmwgfx_saa.c
vmwgfx/vmwgfx_saa.h

index 49e84e8..8f8ced4 100644 (file)
@@ -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: */
index f733328..55b5fea 100644 (file)
@@ -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);
 }
index c7aae79..90fa728 100644 (file)
@@ -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);