vmwgfx_ctrl.c \
vmwgfx_ctrl.h \
vmwgfx_xa_composite.c \
+ vmwgfx_xa_surface.c \
wsbm_util.h
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;
/* 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 &&
#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)
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)
{
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;
-}
/**
* 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,
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;
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,
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;
}
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
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;
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 = ∅
- 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 = ∅
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 = ∅
- 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;
/*
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;
}
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 {
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)
{
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
--- /dev/null
+/*
+ * 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
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;
REGION_NULL(pScreen, ®);
- if (!vmwgfx_pixmap_validate_hw(pPixmap, ®, 0, XA_FLAG_RENDER_TARGET, 0))
+ if (!vmwgfx_hw_accel_validate(pPixmap, 0, XA_FLAG_RENDER_TARGET, 0, ®))
goto out_no_dst;
hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y));
--- /dev/null
+/*
+ * 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));
+}