diff options
author | Izik Eidus <ieidus@redhat.com> | 2010-02-16 20:30:14 +0200 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2010-02-17 11:14:38 +0100 |
commit | a7fb50d6c2395c32b236e42eac84b79be653c2cb (patch) | |
tree | f41663eba59784b1a531306daa0297edc947397b | |
parent | 3dbe9ce052efd576ff883436793403ab0c9d0757 (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.c | 72 | ||||
-rw-r--r-- | display/res.h | 1 | ||||
-rw-r--r-- | display/rop.c | 130 |
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); |