vmwgfx: Try to sort out format handling with composite.
authorThomas Hellstrom <thellstrom@vmware.com>
Fri, 1 Jul 2011 09:28:52 +0000 (11:28 +0200)
committerThomas Hellstrom <thellstrom@vmware.com>
Fri, 1 Jul 2011 09:35:40 +0000 (11:35 +0200)
Try to catch all cases where we have to do readbacks or format conversions
due to composite formats not being compatible with ordinary accel formats.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
vmwgfx/Makefile.am
vmwgfx/vmwgfx_dri2.c
vmwgfx/vmwgfx_saa.c
vmwgfx/vmwgfx_saa.h
vmwgfx/vmwgfx_saa_priv.h [new file with mode: 0644]
vmwgfx/vmwgfx_tex_video.c
vmwgfx/vmwgfx_xa_surface.c [new file with mode: 0644]

index 03dbf6a..e956b64 100644 (file)
@@ -21,6 +21,7 @@ vmwgfx_drv_la_SOURCES = \
        vmwgfx_ctrl.c \
        vmwgfx_ctrl.h \
        vmwgfx_xa_composite.c \
+       vmwgfx_xa_surface.c \
        wsbm_util.h
 
 
index 07d538f..be5bd51 100644 (file)
@@ -167,9 +167,8 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for
     if (!srf) {
        depth = (format) ? vmwgfx_color_format_to_depth(format) :
            pDraw->depth;
-       if (!vmwgfx_pixmap_validate_hw(pPixmap, NULL, depth,
-                                      XA_FLAG_SHARED | XA_FLAG_RENDER_TARGET,
-                                      0))
+
+       if (!vmwgfx_hw_dri2_validate(pPixmap, depth))
            return FALSE;
 
        srf = vpix->hw;
@@ -308,12 +307,9 @@ dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
        /* pixmap glXWaitX */
        if (pSrcBuffer->attachment == DRI2BufferFrontLeft &&
            pDestBuffer->attachment == DRI2BufferFakeFrontLeft) {
-           LogMessage(X_INFO, "dri2 Validate hw.\n");
-           vmwgfx_pixmap_validate_hw(src_priv->pPixmap, NULL,
-                                     0,
-                                     XA_FLAG_SHARED | XA_FLAG_RENDER_TARGET,
-                                     0);
-           return;
+
+           if (!vmwgfx_hw_dri2_validate(src_priv->pPixmap, 0))
+               return;
        }
        /* pixmap glXWaitGL */
        if (pDestBuffer->attachment == DRI2BufferFrontLeft &&
index 48c327d..635fb37 100644 (file)
 #include <xa_context.h>
 #include "vmwgfx_saa.h"
 #include "vmwgfx_drmi.h"
-
-#define VMWGFX_PIX_MALLOC  (1 << 0)
-#define VMWGFX_PIX_GMR     (1 << 1)
-#define VMWGFX_PIX_SURFACE (1 << 2)
-
-struct vmwgfx_saa {
-    struct saa_driver driver;
-    struct vmwgfx_dma_ctx *ctx;
-    struct xa_tracker *xat;
-    struct xa_context *xa_ctx;
-    ScreenPtr pScreen;
-    int drm_fd;
-    struct vmwgfx_saa_pixmap *src_vpix;
-    struct vmwgfx_saa_pixmap *dst_vpix;
-    Bool present_copy;
-    Bool diff_valid;
-    int xdiff;
-    int ydiff;
-    RegionRec present_region;
-    uint32_t src_handle;
-    Bool can_optimize_dma;
-    void (*present_flush) (ScreenPtr pScreen);
-    struct _WsbmListHead sync_x_list;
-    struct vmwgfx_composite *vcomp;
-};
-
-static inline struct vmwgfx_saa *
-to_vmwgfx_saa(struct saa_driver *driver) {
-    return (struct vmwgfx_saa *) driver;
-}
-
-static enum xa_formats
-vmwgfx_choose_xa_format(unsigned int depth)
-{
-  /*
-   * For a given depth, choose the same format as the
-   * dri state tracker.
-   */
-
-  switch(depth) {
-  case 32:
-  case 24: /* The dri state tracker never uses 24. */
-      return xa_format_a8r8g8b8;
-  case 16:
-      return xa_format_r5g6b5;
-  case 15: /* No dri. */
-      return xa_format_x1r5g5b5;
-  default:
-      break;
-  }
-
-  return xa_format_unknown;
-}
-
+#include "vmwgfx_saa_priv.h"
 
 static Bool
 vmwgfx_pixmap_add_damage(PixmapPtr pixmap)
@@ -486,6 +433,33 @@ vmwgfx_create_pixmap(struct saa_driver *driver, struct saa_pixmap *spix,
     return TRUE;
 }
 
+Bool
+vmwgfx_hw_kill(struct vmwgfx_saa *vsaa,
+              struct saa_pixmap *spix)
+{
+    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
+
+    /*
+     * Read back any dirty regions from hardware.
+     */
+
+    if (!vmwgfx_download_from_hw(&vsaa->driver, spix->pixmap,
+                                &spix->dirty_hw))
+       return FALSE;
+
+    xa_surface_destroy(vpix->hw);
+    vpix->hw = NULL;
+
+    /*
+     * Remove damage tracking if this is not a scanout pixmap.
+     */
+
+    if (WSBMLISTEMPTY(&vpix->scanout_list))
+       vmwgfx_pixmap_remove_damage(spix->pixmap);
+
+    return TRUE;
+}
+
 void
 vmwgfx_flush_dri2(ScreenPtr pScreen)
 {
@@ -530,51 +504,6 @@ vmwgfx_destroy_pixmap(struct saa_driver *driver, PixmapPtr pixmap)
        LogMessage(X_ERROR, "Incorrect dri2 front count.\n");
 }
 
-static Bool
-vmwgfx_pixmap_create_hw(struct vmwgfx_saa *vsaa,
-                       PixmapPtr pixmap, unsigned int depth,
-                       unsigned int flags)
-{
-    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
-    struct xa_surface *hw;
-
-    if (!vsaa->xat)
-       return FALSE;
-
-    if (vpix->hw)
-       return TRUE;
-
-    if (!depth)
-       depth = pixmap->drawable.depth;
-
-    hw = xa_surface_create(vsaa->xat,
-                          pixmap->drawable.width,
-                          pixmap->drawable.height,
-                          depth,
-                          xa_type_argb,
-                          vmwgfx_choose_xa_format(depth),
-                          XA_FLAG_RENDER_TARGET | flags);
-    if (hw == NULL)
-       return FALSE;
-
-    if ((vpix->gmr || vpix->malloc) && !vmwgfx_pixmap_add_damage(pixmap))
-       goto out_no_damage;
-
-    /*
-     * Even if we don't have a GMR yet, indicate that when needed it
-     * should be created.
-     */
-
-    vpix->hw = hw;
-    vpix->backing |= VMWGFX_PIX_SURFACE;
-    vmwgfx_pixmap_free_storage(vpix);
-
-    return TRUE;
-
-out_no_damage:
-    xa_surface_destroy(hw);
-    return FALSE;
-}
 
 
 /**
@@ -582,79 +511,6 @@ out_no_damage:
  * Makes sure we have a surface with valid contents.
  */
 
-Bool
-vmwgfx_pixmap_validate_hw(PixmapPtr pixmap, RegionPtr region,
-                         unsigned int depth,
-                         unsigned int add_flags,
-                         unsigned int remove_flags)
-{
-    struct vmwgfx_saa *vsaa =
-       to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
-    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
-    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
-    RegionRec intersection;
-
-    if (!vsaa->xat)
-       return FALSE;
-
-    if (vpix->hw) {
-       if (!depth)
-           depth = pixmap->drawable.depth;
-
-       if (xa_surface_redefine(vpix->hw,
-                               pixmap->drawable.width,
-                               pixmap->drawable.height,
-                               depth,
-                               xa_type_argb,
-                               vmwgfx_choose_xa_format(depth),
-                               XA_FLAG_RENDER_TARGET | add_flags,
-                               remove_flags, 1) != 0)
-           return FALSE;
-    } else if (!vmwgfx_pixmap_create_hw(vsaa, pixmap, depth, add_flags))
-       return FALSE;
-
-
-    if (!vmwgfx_pixmap_present_readback(vsaa, pixmap, region))
-       return FALSE;
-
-    REGION_NULL(vsaa->pScreen, &intersection);
-    REGION_COPY(vsaa->pScreen, &intersection, &spix->dirty_shadow);
-
-    if (vpix->dirty_present)
-       REGION_UNION(vsaa->pScreen, &intersection, vpix->dirty_present,
-                    &spix->dirty_shadow);
-
-    if (spix->damage && REGION_NOTEMPTY(vsaa->pScreen, &intersection)) {
-       RegionPtr upload = &intersection;
-
-       /*
-        * Check whether we need to upload from GMR.
-        */
-
-       if (region) {
-           REGION_INTERSECT(vsaa->pScreen, &intersection, region,
-                            &intersection);
-           upload = &intersection;
-       }
-
-       if (REGION_NOTEMPTY(vsaa->pScreen, upload)) {
-           Bool ret = vmwgfx_upload_to_hw(&vsaa->driver, pixmap, upload);
-           if (ret) {
-               REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_shadow,
-                               &spix->dirty_shadow, upload);
-               if (vpix->dirty_present)
-                   REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present,
-                                   vpix->dirty_present, upload);
-           } else {
-               REGION_UNINIT(vsaa->pScreen, &intersection);
-               return FALSE;
-           }
-       }
-    }
-    REGION_UNINIT(vsaa->pScreen, &intersection);
-    return TRUE;
-}
-
 static void
 vmwgfx_copy_stride(uint8_t *dst, uint8_t *src, unsigned int dst_pitch,
                   unsigned int src_pitch, unsigned int dst_height,
@@ -730,7 +586,7 @@ vmwgfx_pix_resize(PixmapPtr pixmap, unsigned int old_pitch,
     if (vpix->hw) {
        if (xa_surface_redefine(vpix->hw, draw->width, draw->height,
                                draw->depth, xa_type_argb,
-                               xa_format_unknown, 0, 0, 1) != 0)
+                               xa_format_unknown, vpix->xa_flags, 1) != 0)
            return FALSE;
     }
     return TRUE;
@@ -858,6 +714,106 @@ vmwgfx_check_hw_contents(struct vmwgfx_saa *vsaa,
     REGION_UNINIT(vsaa->pScreen, &intersection);
 }
 
+
+Bool
+vmwgfx_create_hw(struct vmwgfx_saa *vsaa,
+                PixmapPtr pixmap)
+{
+    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
+    struct xa_surface *hw;
+    uint32_t new_flags;
+
+    if (!vsaa->xat)
+       return FALSE;
+
+    if (vpix->hw)
+       return TRUE;
+
+    new_flags = (vpix->xa_flags & ~vpix->staging_remove_flags) |
+       vpix->staging_add_flags;
+
+    hw = xa_surface_create(vsaa->xat,
+                          pixmap->drawable.width,
+                          pixmap->drawable.height,
+                          0,
+                          xa_type_other,
+                          vpix->staging_format,
+                          new_flags);
+    if (hw == NULL)
+       return FALSE;
+
+    vpix->xa_flags = new_flags;
+
+    if ((vpix->gmr || vpix->malloc) && !vmwgfx_pixmap_add_damage(pixmap))
+       goto out_no_damage;
+
+    /*
+     * Even if we don't have a GMR yet, indicate that when needed it
+     * should be created.
+     */
+
+    vpix->hw = hw;
+    vpix->backing |= VMWGFX_PIX_SURFACE;
+    vmwgfx_pixmap_free_storage(vpix);
+
+    return TRUE;
+
+out_no_damage:
+    xa_surface_destroy(hw);
+    return FALSE;
+}
+
+
+Bool
+vmwgfx_hw_validate(PixmapPtr pixmap, RegionPtr region)
+{
+    struct vmwgfx_saa *vsaa =
+       to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
+    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
+    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
+    RegionRec intersection;
+
+    if (!vmwgfx_pixmap_present_readback(vsaa, pixmap, region))
+       return FALSE;
+
+    REGION_NULL(vsaa->pScreen, &intersection);
+    REGION_COPY(vsaa->pScreen, &intersection, &spix->dirty_shadow);
+
+    if (vpix->dirty_present)
+       REGION_UNION(vsaa->pScreen, &intersection, vpix->dirty_present,
+                    &spix->dirty_shadow);
+
+    if (spix->damage && REGION_NOTEMPTY(vsaa->pScreen, &intersection)) {
+       RegionPtr upload = &intersection;
+
+       /*
+        * Check whether we need to upload from GMR.
+        */
+
+       if (region) {
+           REGION_INTERSECT(vsaa->pScreen, &intersection, region,
+                            &intersection);
+           upload = &intersection;
+       }
+
+       if (REGION_NOTEMPTY(vsaa->pScreen, upload)) {
+           Bool ret = vmwgfx_upload_to_hw(&vsaa->driver, pixmap, upload);
+           if (ret) {
+               REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_shadow,
+                               &spix->dirty_shadow, upload);
+               if (vpix->dirty_present)
+                   REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present,
+                                   vpix->dirty_present, upload);
+           } else {
+               REGION_UNINIT(vsaa->pScreen, &intersection);
+               return FALSE;
+           }
+       }
+    }
+    REGION_UNINIT(vsaa->pScreen, &intersection);
+    return TRUE;
+}
+
 static Bool
 vmwgfx_copy_prepare(struct saa_driver *driver,
                    PixmapPtr src_pixmap,
@@ -891,7 +847,7 @@ vmwgfx_copy_prepare(struct saa_driver *driver,
            return FALSE;
 
        if (vmwgfx_present_prepare(vsaa, src_vpix, dst_vpix)) {
-           if (!vmwgfx_pixmap_validate_hw(src_pixmap, src_reg, 0, 0, 0))
+         if (!vmwgfx_hw_accel_validate(src_pixmap, 0, 0, 0, src_reg))
                return FALSE;
            vsaa->present_copy = TRUE;
            return TRUE;
@@ -900,7 +856,7 @@ vmwgfx_copy_prepare(struct saa_driver *driver,
     }
 
     vsaa->present_copy = FALSE;
-    if (src_vpix->hw != NULL && src_vpix != dst_vpix) {
+    if (src_vpix != dst_vpix) {
 
        /*
         * Use hardware acceleration either if source is partially only
@@ -910,14 +866,43 @@ vmwgfx_copy_prepare(struct saa_driver *driver,
 
        if (!has_dirty_hw && !(has_valid_hw && (dst_vpix->hw != NULL)))
            return FALSE;
-       if (!vmwgfx_pixmap_validate_hw(src_pixmap, src_reg, 0, 0, 0))
+
+       /*
+        * Determine surface formats.
+        */
+
+       if (!vmwgfx_hw_accel_stage(src_pixmap, 0, XA_FLAG_RENDER_TARGET, 0))
            return FALSE;
-       if (!vmwgfx_pixmap_create_hw(vsaa, dst_pixmap, 0,
-                                    XA_FLAG_RENDER_TARGET))
+       if (!vmwgfx_hw_accel_stage(dst_pixmap, 0, XA_FLAG_RENDER_TARGET, 0))
            return FALSE;
 
-       if (xa_copy_prepare(vsaa->xa_ctx, dst_vpix->hw, src_vpix->hw) == 0)
-           return TRUE;
+       /*
+        * Create hardware surfaces.
+        */
+
+       if (!vmwgfx_hw_commit(src_pixmap))
+           return FALSE;
+       if (!vmwgfx_hw_commit(dst_pixmap))
+           return FALSE;
+
+       /*
+        * Setup copy state.
+        */
+
+       if (xa_copy_prepare(vsaa->xa_ctx, dst_vpix->hw, src_vpix->hw) !=
+           XA_ERR_NONE)
+           return FALSE;
+
+       /*
+        * Migrate data.
+        */
+
+       if (!vmwgfx_hw_validate(src_pixmap, src_reg)) {
+           xa_copy_done(vsaa->xa_ctx);
+           return FALSE;
+       }
+
+       return TRUE;
     }
 
     return FALSE;
@@ -1077,24 +1062,26 @@ vmwgfx_composite_prepare(struct saa_driver *driver, CARD8 op,
        goto out_err;
 
     /*
-     * Create hw surfaces and migrate data needed for HW compositing.
+     * Check that we can create the needed hardware surfaces.
      */
 
-    if (src_region == NULL)
-       src_region = &empty;
-    if (src_pix &&
-       !vmwgfx_pixmap_validate_hw(src_pix, src_region, 0, 0, 0))
+    if (src_pix && !vmwgfx_hw_composite_src_stage(src_pix, src_pict->format))
        goto out_err;
-
-    if (mask_region == NULL)
-       mask_region = &empty;
     if (mask_pict && mask_pix &&
-       !vmwgfx_pixmap_validate_hw(mask_pix, mask_region, 0, 0, 0))
+       !vmwgfx_hw_composite_src_stage(mask_pix, mask_pict->format))
+       goto out_err;
+    if (!vmwgfx_hw_composite_dst_stage(dst_pix, dst_pict->format))
        goto out_err;
 
-    if (dst_region == NULL)
-       dst_region = &empty;
-    if (!vmwgfx_pixmap_validate_hw(dst_pix, dst_region, 0, 0, 0))
+    /*
+     * Seems OK. Commit the changes, creating hardware surfaces.
+     */
+
+    if (src_pix && !vmwgfx_hw_commit(src_pix))
+       goto out_err;
+    if (mask_pict && mask_pix && !vmwgfx_hw_commit(mask_pix))
+       goto out_err;
+    if (!vmwgfx_hw_commit(dst_pix))
        goto out_err;
 
     /*
@@ -1108,9 +1095,26 @@ vmwgfx_composite_prepare(struct saa_driver *driver, CARD8 op,
     if (xa_composite_prepare(vsaa->xa_ctx, xa_comp))
        goto out_err;
 
+    /*
+     * Migrate data to surfaces, now that we know that the hardware can indeed
+     * accelerate.
+     */
+
+    if (src_pix && src_region && !vmwgfx_hw_validate(src_pix, src_region))
+       goto out_err_migrate;
+    if (mask_pict && mask_pix && mask_region &&
+       !vmwgfx_hw_validate(mask_pix, mask_region))
+       goto out_err_migrate;
+    if (dst_region && !vmwgfx_hw_validate(dst_pix, dst_region))
+       goto out_err_migrate;
+
+
     REGION_UNINIT(pScreen, &empty);
     return TRUE;
- out_err:
+
+  out_err_migrate:
+    xa_composite_done(vsaa->xa_ctx);
+  out_err:
     REGION_UNINIT(pScreen, &empty);
     return FALSE;
 }
index deb3f37..41c6de3 100644 (file)
@@ -54,6 +54,11 @@ struct vmwgfx_saa_pixmap {
     int hw_is_dri2_fronts;
     struct _WsbmListHead sync_x_head;
     struct _WsbmListHead scanout_list;
+
+    uint32_t xa_flags;
+    uint32_t staging_add_flags;
+    uint32_t staging_remove_flags;
+    enum xa_formats staging_format;
 };
 
 struct vmwgfx_screen_box {
@@ -68,12 +73,6 @@ to_vmwgfx_saa_pixmap(struct saa_pixmap *spix)
     return (struct vmwgfx_saa_pixmap *) spix;
 }
 
-extern Bool
-vmwgfx_pixmap_validate_hw(PixmapPtr pixmap, RegionPtr region,
-                         unsigned int depth,
-                         unsigned int add_flags,
-                         unsigned int remove_flags);
-
 static inline struct vmwgfx_saa_pixmap*
 vmwgfx_saa_pixmap(PixmapPtr pix)
 {
@@ -99,28 +98,11 @@ vmwgfx_remove_dri2_list(struct vmwgfx_saa_pixmap *vpix);
 extern void
 vmwgfx_flush_dri2(ScreenPtr pScreen);
 
-/*
- * vmwgfx_xa_composite.c
- */
-
-struct vmwgfx_composite;
-
-void
-vmwgfx_free_composite(struct vmwgfx_composite *vcomp);
-struct vmwgfx_composite *
-vmwgfx_alloc_composite(void);
+extern Bool
+vmwgfx_hw_dri2_validate(PixmapPtr pixmap, unsigned int depth);
 
 Bool
-vmwgfx_xa_update_comp(struct xa_composite *comp,
-                     PixmapPtr src_pix,
-                     PixmapPtr mask_pix,
-                     PixmapPtr dst_pix);
-
-struct xa_composite *
-vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp,
-                    int op,
-                    PicturePtr src_pict,
-                    PicturePtr mask_pict,
-                    PicturePtr dst_pict);
-
+vmwgfx_hw_accel_validate(PixmapPtr pixmap, unsigned int depth,
+                        uint32_t add_flags, uint32_t remove_flags,
+                        RegionPtr region);
 #endif
diff --git a/vmwgfx/vmwgfx_saa_priv.h b/vmwgfx/vmwgfx_saa_priv.h
new file mode 100644 (file)
index 0000000..5080047
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2011 VMWare, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Thomas Hellstrom <thellstrom@vmware.com>
+ */
+#ifndef _VMWGFX_SAA_PRIV_H_
+#define _VMWGFX_SAA_PRIV_H_
+
+#define VMWGFX_PIX_MALLOC  (1 << 0)
+#define VMWGFX_PIX_GMR     (1 << 1)
+#define VMWGFX_PIX_SURFACE (1 << 2)
+
+#include <xorg-server.h>
+#include <picturestr.h>
+#include "vmwgfx_saa.h"
+
+struct vmwgfx_saa {
+    struct saa_driver driver;
+    struct vmwgfx_dma_ctx *ctx;
+    struct xa_tracker *xat;
+    struct xa_context *xa_ctx;
+    ScreenPtr pScreen;
+    int drm_fd;
+    struct vmwgfx_saa_pixmap *src_vpix;
+    struct vmwgfx_saa_pixmap *dst_vpix;
+    Bool present_copy;
+    Bool diff_valid;
+    int xdiff;
+    int ydiff;
+    RegionRec present_region;
+    uint32_t src_handle;
+    Bool can_optimize_dma;
+    void (*present_flush) (ScreenPtr pScreen);
+    struct _WsbmListHead sync_x_list;
+    struct vmwgfx_composite *vcomp;
+};
+
+static inline struct vmwgfx_saa *
+to_vmwgfx_saa(struct saa_driver *driver) {
+    return (struct vmwgfx_saa *) driver;
+}
+
+/*
+ * In vmwgfx_saa.c
+ */
+
+Bool
+vmwgfx_hw_kill(struct vmwgfx_saa *vsaa,
+              struct saa_pixmap *spix);
+Bool
+vmwgfx_create_hw(struct vmwgfx_saa *vsaa,
+                PixmapPtr pixmap);
+
+
+/*
+ * vmwgfx_xa_surface.c
+ */
+
+enum xa_formats
+vmwgfx_xa_format(enum _PictFormatShort format);
+Bool
+vmwgfx_hw_validate(PixmapPtr pixmap, RegionPtr region);
+
+Bool
+vmwgfx_hw_accel_stage(PixmapPtr pixmap, unsigned int depth,
+                     uint32_t add_flags, uint32_t remove_flags);
+Bool
+vmwgfx_hw_composite_src_stage(PixmapPtr pixmap,
+                             enum _PictFormatShort pict_format);
+Bool
+vmwgfx_hw_composite_dst_stage(PixmapPtr pixmap,
+                             enum _PictFormatShort pict_format);
+Bool
+vmwgfx_hw_commit(PixmapPtr pixmap);
+
+/*
+ * vmwgfx_xa_composite.c
+ */
+
+struct vmwgfx_composite;
+
+void
+vmwgfx_free_composite(struct vmwgfx_composite *vcomp);
+struct vmwgfx_composite *
+vmwgfx_alloc_composite(void);
+
+Bool
+vmwgfx_xa_update_comp(struct xa_composite *comp,
+                     PixmapPtr src_pix,
+                     PixmapPtr mask_pix,
+                     PixmapPtr dst_pix);
+
+struct xa_composite *
+vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp,
+                    int op,
+                    PicturePtr src_pict,
+                    PicturePtr mask_pict,
+                    PicturePtr dst_pict);
+
+
+#endif
index c357f06..801b066 100644 (file)
@@ -223,7 +223,7 @@ check_yuv_surfaces(struct xorg_xv_port_priv *priv,  int width, int height)
        else
            ret = xa_surface_redefine(yuv[i], width, height, 8,
                                      xa_type_yuv_component,
-                                     xa_format_unknown, 0, 0, 0);
+                                     xa_format_unknown, 0, 0);
        if (ret || !yuv[i])
            return BadAlloc;
 
@@ -455,7 +455,7 @@ display_video(ScreenPtr pScreen, struct xorg_xv_port_priv *pPriv, int id,
 
     REGION_NULL(pScreen, &reg);
 
-    if (!vmwgfx_pixmap_validate_hw(pPixmap, &reg, 0, XA_FLAG_RENDER_TARGET, 0))
+    if (!vmwgfx_hw_accel_validate(pPixmap, 0, XA_FLAG_RENDER_TARGET, 0, &reg))
        goto out_no_dst;
 
    hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y));
diff --git a/vmwgfx/vmwgfx_xa_surface.c b/vmwgfx/vmwgfx_xa_surface.c
new file mode 100644 (file)
index 0000000..6c4ab85
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Copyright 2011 VMWare, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Thomas Hellstrom <thellstrom@vmware.com>
+ */
+#ifdef _HAVE_CONFIG_H_
+#include "config.h"
+#endif
+
+#include <xorg-server.h>
+#include "vmwgfx_saa_priv.h"
+
+
+static const enum xa_surface_type vmwgfx_stype_map[] = {
+  [PICT_TYPE_OTHER] = xa_type_other,
+  [PICT_TYPE_A] = xa_type_a,
+  [PICT_TYPE_ARGB] = xa_type_argb,
+  [PICT_TYPE_ABGR] = xa_type_abgr,
+  [PICT_TYPE_BGRA] = xa_type_bgra
+};
+
+static const unsigned int vmwgfx_stype_map_size =
+    sizeof(vmwgfx_stype_map) / sizeof(enum xa_surface_type);
+
+
+/*
+ * Create an xa format from a PICT format.
+ */
+enum xa_formats
+vmwgfx_xa_format(enum _PictFormatShort format)
+{
+    uint32_t ptype = PICT_FORMAT_TYPE(format);
+
+    if (ptype >= vmwgfx_stype_map_size ||
+       vmwgfx_stype_map[ptype] == 0 ||
+       vmwgfx_stype_map[ptype] == xa_type_other)
+       return xa_format_unknown;
+
+    return xa_format(PICT_FORMAT_BPP(format),
+                    vmwgfx_stype_map[ptype],
+                    PICT_FORMAT_A(format),
+                    PICT_FORMAT_R(format),
+                    PICT_FORMAT_G(format),
+                    PICT_FORMAT_B(format));
+}
+
+/*
+ * Choose formats and flags for a dri2 surface.
+ */
+static Bool
+vmwgfx_hw_dri2_stage(PixmapPtr pixmap, unsigned int depth)
+{
+    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
+    enum xa_formats format;
+
+    if (depth == 0)
+       depth = pixmap->drawable.depth;
+
+    switch(depth) {
+    case 32:
+       format = xa_format_a8r8g8b8;
+       break;
+    case 24:
+        format = xa_format_x8r8g8b8;
+       break;
+    case 16:
+       format = xa_format_r5g6b5;
+       break;
+    case 15:
+       format = xa_format_x1r5g5b5;
+       break;
+    default:
+       return FALSE;
+    }
+
+    vpix->staging_format = format;
+    vpix->staging_remove_flags = 0;
+    vpix->staging_add_flags = XA_FLAG_RENDER_TARGET | XA_FLAG_SHARED;
+
+    return TRUE;
+}
+
+/*
+ * Is composite old format compatible? Only difference is that old format
+ * has more alpha bits?
+ */
+static inline Bool
+vmwgfx_old_format_compatible(enum xa_formats format,
+                            enum xa_formats old_format)
+{
+    return (format == old_format ||
+           (xa_format_type(old_format) == xa_format_type(old_format) &&
+            xa_format_a(format) <= xa_format_a(old_format) &&
+            xa_format_r(format) == xa_format_r(old_format) &&
+            xa_format_g(format) == xa_format_g(old_format) &&
+            xa_format_b(format) == xa_format_b(old_format)));
+}
+
+
+/*
+ * Choose format and flags for a composite dst surface.
+ */
+Bool
+vmwgfx_hw_composite_dst_stage(PixmapPtr pixmap,
+                             enum _PictFormatShort pict_format)
+{
+    struct vmwgfx_saa *vsaa =
+       to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
+    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
+    enum xa_formats format = vmwgfx_xa_format(pict_format);
+
+    /*
+     * Check if we can reuse old hardware format.
+     */
+
+    if (vpix->hw) {
+       enum xa_formats old_format = xa_surface_format(vpix->hw);
+
+       if (vmwgfx_old_format_compatible(format, old_format))
+           format = old_format;
+    }
+
+    if (xa_format_check_supported(vsaa->xat, format,
+                                 vpix->xa_flags | XA_FLAG_RENDER_TARGET) !=
+       XA_ERR_NONE) {
+       return FALSE;
+    }
+
+    vpix->staging_format = format;
+    vpix->staging_remove_flags = 0;
+    vpix->staging_add_flags = XA_FLAG_RENDER_TARGET;
+    return TRUE;
+}
+
+/*
+ * Choose format and flags for a composite src surface.
+ */
+Bool
+vmwgfx_hw_composite_src_stage(PixmapPtr pixmap,
+                             enum _PictFormatShort pict_format)
+{
+    struct vmwgfx_saa *vsaa =
+       to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
+    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
+    enum xa_formats format = vmwgfx_xa_format(pict_format);
+    enum xa_formats swizzle_format = xa_format_unknown;
+    enum xa_surface_type ftype;
+
+    if (format == xa_format_unknown)
+       return FALSE;
+
+    ftype = xa_format_type(format);
+    if (ftype == xa_type_abgr) {
+
+       swizzle_format = xa_format(xa_format_bpp(format),
+                                  xa_type_argb,
+                                  xa_format_a(format),
+                                  xa_format_r(format),
+                                  xa_format_g(format),
+                                  xa_format_b(format));
+    }
+
+    /*
+     * Check if we can reuse old format.
+     */
+
+    if (vpix->hw) {
+       enum xa_formats old_format = xa_surface_format(vpix->hw);
+
+       if (vmwgfx_old_format_compatible(format, old_format) ||
+           (swizzle_format != xa_format_unknown &&
+            vmwgfx_old_format_compatible(swizzle_format, old_format))) {
+           format = old_format;
+           goto have_format;
+       }
+    }
+
+    if (swizzle_format != xa_format_unknown &&
+       xa_format_check_supported(vsaa->xat, swizzle_format, vpix->xa_flags) ==
+       XA_ERR_NONE) {
+       format = swizzle_format;
+       goto have_format;
+    }
+
+    if (xa_format_check_supported(vsaa->xat, format, vpix->xa_flags) ==
+       XA_ERR_NONE) {
+       goto have_format;
+    }
+
+    return FALSE;
+  have_format:
+    vpix->staging_format = format;
+    vpix->staging_remove_flags = 0;
+    vpix->staging_add_flags = 0;
+
+    return TRUE;
+}
+
+/*
+ * Choose accel format given depth.
+ */
+static enum xa_formats
+vmwgfx_choose_accel_format(unsigned int depth)
+{
+    switch(depth) {
+    case 32:
+    case 24:
+       return xa_format_a8r8g8b8;
+    case 16:
+       return xa_format_r5g6b5;
+    case 15:
+       return xa_format_x1r5g5b5;
+    case 8:
+       return xa_format_a8;
+    default:
+       break;
+    }
+    return xa_format_unknown;
+}
+
+
+/*
+ * Determine xa format and flags for an ordinary accel surface.
+ */
+Bool
+vmwgfx_hw_accel_stage(PixmapPtr pixmap, unsigned int depth,
+                     uint32_t add_flags, uint32_t remove_flags)
+{
+    struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
+    enum xa_formats format = xa_format_unknown;
+
+    if (depth == 0)
+       depth = pixmap->drawable.depth;
+
+    if (vpix->hw) {
+       enum xa_formats old_format = xa_surface_format(vpix->hw);
+       enum xa_surface_type ftype = xa_format_type(old_format);
+
+       if (ftype != xa_type_argb &&
+           ftype != xa_type_a) {
+           LogMessage(X_ERROR,
+                      "Acceleration fallback due to strange hw format.\n");
+           return FALSE;
+       }
+
+       if (xa_format_depth(old_format) == depth ||
+           (xa_format_depth(old_format) == 32 &&
+            depth == 24))
+           format = old_format;
+    }
+
+    if (format == xa_format_unknown)
+       format = vmwgfx_choose_accel_format(depth);
+
+    if (format == xa_format_unknown)
+       return FALSE;
+
+    vpix->staging_add_flags = add_flags;
+    vpix->staging_remove_flags = remove_flags;
+    vpix->staging_format = format;
+
+    return TRUE;
+}
+
+/*
+ * Create a surface with a format and flags determined by one of
+ * the staging functions.
+ */
+Bool
+vmwgfx_hw_commit(PixmapPtr pixmap)
+{
+    struct vmwgfx_saa *vsaa =
+       to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
+    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
+    struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
+    enum xa_formats format = vpix->staging_format;
+
+    if (vpix->hw) {
+       enum xa_formats old_format = xa_surface_format(vpix->hw);
+
+       if (vpix->staging_format != old_format) {
+           if (xa_format_type(format) != xa_format_type(old_format) ||
+               xa_format_r(format) != xa_format_r(old_format) ||
+               xa_format_g(format) != xa_format_g(old_format) ||
+               xa_format_b(format) != xa_format_b(old_format)) {
+
+               LogMessage(X_INFO, "Killing old hw surface.\n");
+
+               if (!vmwgfx_hw_kill(vsaa, spix))
+                   return FALSE;
+           }
+       }
+    }
+
+    if (vpix->hw) {
+       uint32_t new_flags;
+
+       new_flags = (vpix->xa_flags & ~vpix->staging_remove_flags) |
+           vpix->staging_add_flags;
+
+       if (vpix->staging_format != xa_surface_format(vpix->hw))
+           LogMessage(X_INFO, "Changing hardware format.\n");
+
+       if (xa_surface_redefine(vpix->hw,
+                               pixmap->drawable.width,
+                               pixmap->drawable.height,
+                               0,
+                               xa_type_other,
+                               vpix->staging_format,
+                               new_flags, 1) != XA_ERR_NONE)
+           return FALSE;
+       vpix->xa_flags = new_flags;
+    } else if (!vmwgfx_create_hw(vsaa, pixmap))
+       return FALSE;
+
+    return TRUE;
+}
+
+/*
+ * Create an accel surface if there is none, and make sure the region
+ * given by @region is valid. If @region is NULL, the whole surface
+ * will be valid. This is a utility convenience function only.
+ */
+Bool
+vmwgfx_hw_accel_validate(PixmapPtr pixmap, unsigned int depth,
+                        uint32_t add_flags, uint32_t remove_flags,
+                        RegionPtr region)
+{
+    return (vmwgfx_hw_accel_stage(pixmap, depth, add_flags, remove_flags) &&
+           vmwgfx_hw_commit(pixmap) &&
+           vmwgfx_hw_validate(pixmap, region));
+}
+
+
+/*
+ * Create a dri2 surface if there is none,
+ * and make sure the whole surfade is valid.
+ * This is a utility convenience function only.
+ */
+Bool
+vmwgfx_hw_dri2_validate(PixmapPtr pixmap, unsigned int depth)
+{
+    return (vmwgfx_hw_dri2_stage(pixmap, depth) &&
+           vmwgfx_hw_commit(pixmap) &&
+           vmwgfx_hw_validate(pixmap, NULL));
+}