From 8a9997f060487c0aef07b8e8a95bb3a862de264f Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 1 Jul 2011 11:28:52 +0200 Subject: [PATCH] vmwgfx: Try to sort out format handling with composite. 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 --- vmwgfx/Makefile.am | 1 + vmwgfx/vmwgfx_dri2.c | 14 +- vmwgfx/vmwgfx_saa.c | 390 +++++++++++++++++++++++---------------------- vmwgfx/vmwgfx_saa.h | 38 ++--- vmwgfx/vmwgfx_saa_priv.h | 122 ++++++++++++++ vmwgfx/vmwgfx_tex_video.c | 4 +- vmwgfx/vmwgfx_xa_surface.c | 367 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 704 insertions(+), 232 deletions(-) create mode 100644 vmwgfx/vmwgfx_saa_priv.h create mode 100644 vmwgfx/vmwgfx_xa_surface.c diff --git a/vmwgfx/Makefile.am b/vmwgfx/Makefile.am index 03dbf6a..e956b64 100644 --- a/vmwgfx/Makefile.am +++ b/vmwgfx/Makefile.am @@ -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 diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c index 07d538f..be5bd51 100644 --- a/vmwgfx/vmwgfx_dri2.c +++ b/vmwgfx/vmwgfx_dri2.c @@ -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 && diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 48c327d..635fb37 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -32,60 +32,7 @@ #include #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 = ∅ - 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; /* @@ -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; } diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h index deb3f37..41c6de3 100644 --- a/vmwgfx/vmwgfx_saa.h +++ b/vmwgfx/vmwgfx_saa.h @@ -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 index 0000000..5080047 --- /dev/null +++ b/vmwgfx/vmwgfx_saa_priv.h @@ -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 + */ +#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 +#include +#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 diff --git a/vmwgfx/vmwgfx_tex_video.c b/vmwgfx/vmwgfx_tex_video.c index c357f06..801b066 100644 --- a/vmwgfx/vmwgfx_tex_video.c +++ b/vmwgfx/vmwgfx_tex_video.c @@ -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, ®); - 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)); diff --git a/vmwgfx/vmwgfx_xa_surface.c b/vmwgfx/vmwgfx_xa_surface.c new file mode 100644 index 0000000..6c4ab85 --- /dev/null +++ b/vmwgfx/vmwgfx_xa_surface.c @@ -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 + */ +#ifdef _HAVE_CONFIG_H_ +#include "config.h" +#endif + +#include +#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)); +} -- 2.7.4