summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIzik Eidus <ieidus@redhat.com>2010-02-16 20:30:14 +0200
committerAlexander Larsson <alexl@redhat.com>2010-02-17 11:14:38 +0100
commita7fb50d6c2395c32b236e42eac84b79be653c2cb (patch)
treef41663eba59784b1a531306daa0297edc947397b
parent3dbe9ce052efd576ff883436793403ab0c9d0757 (diff)
spice: split heavily clipped images into small images (speed win7)
This really speed up windows 7 Thanks Signed-off-by: Izik Eidus <ieidus@redhat.com>
-rw-r--r--display/res.c72
-rw-r--r--display/res.h1
-rw-r--r--display/rop.c130
3 files changed, 190 insertions, 13 deletions
diff --git a/display/res.c b/display/res.c
index 4b1a2fd..2b0735a 100644
--- a/display/res.c
+++ b/display/res.c
@@ -890,7 +890,6 @@ static CacheImage *ImageCacheGetByKey(PDev *pdev, UINT32 key, BOOL check_rest,
while (cache_image) {
if (cache_image->key == key && (!check_rest || (cache_image->format == format &&
cache_image->width == width && cache_image->height == height))) {
- cache_image->hits++;
return cache_image;
}
cache_image = cache_image->next;
@@ -1411,16 +1410,10 @@ static BOOL ChachSizeTest(PDev *pdev, SURFOBJ *surf)
return ret;
}
-
-static CacheImage *GetChachImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_trans, UINT32 *hash_key)
+static _inline UINT64 get_unique(SURFOBJ *surf, XLATEOBJ *color_trans)
{
- CacheImage *cache_image;
- ULONG pallette_unique;
- UINT64 gdi_unique;
int pallette;
- UINT32 key;
- UINT8 format;
- UINT32 line_size;
+ ULONG pallette_unique;
pallette = color_trans && (color_trans->flXlate & XO_TABLE);
pallette_unique = pallette ? color_trans->iUniq : 0;
@@ -1428,11 +1421,65 @@ static CacheImage *GetChachImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_tran
// NOTE: GDI sometimes gives many instances of the exactly same SURFOBJ (hsurf & iUniq),
// but with (fjBitmap & BMF_DONTCACHE). This opposed to what documented in the MSDN.
if (!surf->iUniq || (surf->fjBitmap & BMF_DONTCACHE) || (pallette && !pallette_unique)) {
- gdi_unique = 0;
+ return 0;
} else {
- gdi_unique = surf->iUniq | ((UINT64)pallette_unique << 32);
+ return (surf->iUniq | ((UINT64)pallette_unique << 32));
+ }
+}
+
+BOOL CheckIfCacheImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_trans)
+{
+ CacheImage *cache_image;
+ UINT64 gdi_unique;
+ UINT32 key;
+ UINT8 format;
+
+ gdi_unique = get_unique(surf, color_trans);
+
+ if (!ImageKeyGet(pdev, surf->hsurf, gdi_unique, &key)) {
+ return FALSE;
+ }
+
+ switch (surf->iBitmapFormat) {
+ case BMF_32BPP:
+ format = SPICE_BITMAP_FMT_32BIT;
+ break;
+ case BMF_24BPP:
+ format = SPICE_BITMAP_FMT_24BIT;
+ break;
+ case BMF_16BPP:
+ format = SPICE_BITMAP_FMT_16BIT;
+ break;
+ case BMF_8BPP:
+ format = SPICE_BITMAP_FMT_8BIT;
+ break;
+ case BMF_4BPP:
+ format = SPICE_BITMAP_FMT_4BIT_BE;
+ break;
+ case BMF_1BPP:
+ format = SPICE_BITMAP_FMT_1BIT_BE;
+ }
+
+
+ if ((cache_image = ImageCacheGetByKey(pdev, key, TRUE, format,
+ surf->sizlBitmap.cx,
+ surf->sizlBitmap.cy))) {
+ return TRUE;
}
+ return FALSE;
+}
+
+static CacheImage *GetChachImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_trans, UINT32 *hash_key)
+{
+ CacheImage *cache_image;
+ UINT64 gdi_unique;
+ UINT32 key;
+ UINT8 format;
+ UINT32 line_size;
+
+ gdi_unique = get_unique(surf, color_trans);
+
if (!(line_size = GetFormatLineSize(surf->sizlBitmap.cx, surf->iBitmapFormat, &format))) {
DEBUG_PRINT((pdev, 0, "%s: bitmap format err\n", __FUNCTION__));
return FALSE;
@@ -1454,6 +1501,7 @@ static CacheImage *GetChachImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_tran
if ((cache_image = ImageCacheGetByKey(pdev, key, TRUE, format,
surf->sizlBitmap.cx,
surf->sizlBitmap.cy))) {
+ cache_image->hits++;
DEBUG_PRINT((pdev, 11, "%s: ImageCacheGetByKey %u hits %u\n", __FUNCTION__,
key, cache_image->hits));
return cache_image;
@@ -1653,6 +1701,7 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phy
surf->sizlBitmap.cx, surf->sizlBitmap.cy)) {
DEBUG_PRINT((pdev, 11, "%s: ImageCacheGetByKey %u hits %u\n", __FUNCTION__,
key, cache_image->hits));
+ cache_image->hits++;
if (internal = cache_image->image) {
DEBUG_PRINT((pdev, 11, "%s: cached image found %u\n", __FUNCTION__, key));
*image_phys = PA(pdev, &internal->image, pdev->main_mem_slot);
@@ -1712,6 +1761,7 @@ BOOL QXLGetBitsFromCache(PDev *pdev, QXLDrawable *drawable, UINT32 hash_key, QXL
if ((cache_image = ImageCacheGetByKey(pdev, hash_key, FALSE, 0, 0, 0)) &&
(internal = cache_image->image)) {
+ cache_image->hits++;
*image_phys = PA(pdev, &internal->image, pdev->main_mem_slot);
image_res = (Resource *)((UINT8 *)internal - sizeof(Resource));
DrawableAddRes(pdev, drawable, image_res);
diff --git a/display/res.h b/display/res.h
index bc18d1f..e181434 100644
--- a/display/res.h
+++ b/display/res.h
@@ -37,6 +37,7 @@ BOOL QXLGetBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phys, SU
BOOL QXLGetBitsFromCache(PDev *pdev, QXLDrawable *drawable, UINT32 hash_key, QXLPHYSICAL *image_phys);
BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phys, SURFOBJ *surf,
SpiceRect *area);
+BOOL CheckIfCacheImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_trans);
UINT8 *QXLGetBuf(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *buf_phys, UINT32 size);
BOOL QXLGetStr(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *str_phys, FONTOBJ *font, STROBJ *str);
diff --git a/display/rop.c b/display/rop.c
index b9b25b8..746dd6a 100644
--- a/display/rop.c
+++ b/display/rop.c
@@ -514,6 +514,96 @@ static BOOL StreamTest(PDev *pdev, SURFOBJ *src_surf, XLATEOBJ *color_trans, REC
return TRUE;
}
+static BOOL TestSplitClips(PDev *pdev, RECTL *src_rect, CLIPOBJ *clip, SURFOBJ *mask)
+{
+ UINT32 width;
+ UINT32 height;
+ UINT32 src_space;
+ UINT32 clip_space = 0;
+ int more;
+
+ if (!clip || mask) {
+ return FALSE;
+ }
+
+ width = src_rect->right - src_rect->left;
+ height = src_rect->bottom - src_rect->top;
+ src_space = width * height;
+
+ if (clip->iDComplexity == DC_RECT) {
+ width = clip->rclBounds.right - clip->rclBounds.left;
+ height = clip->rclBounds.bottom - clip->rclBounds.top;
+ clip_space = width * height;
+
+ if ((src_space / clip_space) > 1) {
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ if (clip->iMode == TC_RECTANGLES) {
+ CLIPOBJ_cEnumStart(clip, TRUE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
+ do {
+ RECTL *now;
+ RECTL *end;
+
+ struct {
+ ULONG count;
+ RECTL rects[20];
+ } buf;
+
+ more = CLIPOBJ_bEnum(clip, sizeof(buf), (ULONG *)&buf);
+ for(now = buf.rects, end = now + buf.count; now < end; now++) {
+ width = now->right - now->left;
+ height = now->bottom - now->top;
+ clip_space += width * height;
+ }
+ } while (more);
+
+ if ((src_space / clip_space) > 1) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static _inline BOOL DoPartialCopy(PDev *pdev, SURFOBJ *src, RECTL *src_rect, RECTL *area_rect,
+ RECTL *clip_rect, XLATEOBJ *color_trans, ULONG scale_mode,
+ UINT16 rop_decriptor)
+{
+ QXLDrawable *drawable;
+ RECTL clip_area;
+
+ SectRect(area_rect, clip_rect, &clip_area);
+ if (IsEmptyRect(&clip_area)) {
+ return TRUE;
+ }
+
+ if (!(drawable = Drawable(pdev, QXL_DRAW_COPY, &clip_area, NULL))) {
+ return FALSE;
+ }
+
+ drawable->effect = QXL_EFFECT_OPAQUE;
+ drawable->u.copy.scale_mode = GdiScaleModeToQxl(scale_mode);
+ drawable->u.copy.mask.bitmap = 0;
+ drawable->u.copy.rop_decriptor = rop_decriptor;
+
+ drawable->u.copy.src_area.top = src_rect->top + (clip_area.top - area_rect->top);
+ drawable->u.copy.src_area.bottom = drawable->u.copy.src_area.top + clip_area.bottom -
+ clip_area.top;
+ drawable->u.copy.src_area.left = src_rect->left + (clip_area.left - area_rect->left);
+ drawable->u.copy.src_area.right = drawable->u.copy.src_area.left + clip_area.right -
+ clip_area.left;
+
+ if(!GetBitmap(pdev, drawable, &drawable->u.copy.src_bitmap, src, &drawable->u.copy.src_area,
+ color_trans, FALSE)) {
+ ReleaseOutput(pdev, drawable->release_info.id);
+ return FALSE;
+ }
+ PushDrawable(pdev, drawable);
+ return TRUE;
+}
+
static BOOL DoCopy(PDev *pdev, RECTL *area, CLIPOBJ *clip, SURFOBJ *src, RECTL *src_rect,
XLATEOBJ *color_trans, UINT16 rop_decriptor, SURFOBJ *mask, POINTL *mask_pos,
BOOL invers_mask, ULONG scale_mode)
@@ -524,16 +614,52 @@ static BOOL DoCopy(PDev *pdev, RECTL *area, CLIPOBJ *clip, SURFOBJ *src, RECTL *
ASSERT(pdev, pdev && area && src_rect && src);
DEBUG_PRINT((pdev, 6, "%s\n", __FUNCTION__));
+ if (mask) {
+ use_cache = TRUE;
+ } else {
+ use_cache = StreamTest(pdev, src, color_trans, src_rect, area);
+ }
+
+ if (use_cache && TestSplitClips(pdev, src_rect, clip, mask) &&
+ !CheckIfCacheImage(pdev, src, color_trans)) {
+
+ if (clip->iDComplexity == DC_RECT) {
+ if (!DoPartialCopy(pdev, src, src_rect, area, &clip->rclBounds, color_trans, scale_mode,
+ rop_decriptor)) {
+ return FALSE;
+ }
+ } else {
+ int more;
+ ASSERT(pdev, clip->iMode == TC_RECTANGLES);
+ CLIPOBJ_cEnumStart(clip, TRUE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
+ do {
+ RECTL *now;
+ RECTL *end;
+
+ struct {
+ ULONG count;
+ RECTL rects[20];
+ } buf;
+ more = CLIPOBJ_bEnum(clip, sizeof(buf), (ULONG *)&buf);
+ for(now = buf.rects, end = now + buf.count; now < end; now++) {
+ if (!DoPartialCopy(pdev, src, src_rect, area, now, color_trans, scale_mode,
+ rop_decriptor)) {
+ return FALSE;
+ }
+ }
+ } while (more);
+ }
+ return TRUE;
+ }
+
if (!(drawable = Drawable(pdev, QXL_DRAW_COPY, area, clip))) {
return FALSE;
}
if (mask) {
drawable->effect = QXL_EFFECT_BLEND;
- use_cache = TRUE;
} else {
drawable->effect = QXL_EFFECT_OPAQUE;
- use_cache = StreamTest(pdev, src, color_trans, src_rect, area);
}
drawable->u.copy.scale_mode = GdiScaleModeToQxl(scale_mode);