| Index: src/gpu/SkGpuDevice.cpp
|
| diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
|
| index fd03acc24012dc6a2a50e58778c645749a080d59..ea24c8d6d74fb8b1b720bf1c92523684fce1a273 100644
|
| --- a/src/gpu/SkGpuDevice.cpp
|
| +++ b/src/gpu/SkGpuDevice.cpp
|
| @@ -693,7 +693,7 @@ static inline int get_tile_count(const SkIRect& srcRect, int tileSize) {
|
| return tilesX * tilesY;
|
| }
|
|
|
| -static int determine_tile_size(const SkBitmap& bitmap, const SkIRect& src, int maxTileSize) {
|
| +static int determine_tile_size(const SkIRect& src, int maxTileSize) {
|
| if (maxTileSize <= kBmpSmallTileSize) {
|
| return maxTileSize;
|
| }
|
| @@ -716,7 +716,7 @@ static int determine_tile_size(const SkBitmap& bitmap, const SkIRect& src, int m
|
| static void determine_clipped_src_rect(const GrRenderTarget* rt,
|
| const GrClip& clip,
|
| const SkMatrix& viewMatrix,
|
| - const SkBitmap& bitmap,
|
| + const SkISize& imageSize,
|
| const SkRect* srcRectPtr,
|
| SkIRect* clippedSrcIRect) {
|
| clip.getConservativeBounds(rt, clippedSrcIRect, nullptr);
|
| @@ -736,38 +736,34 @@ static void determine_clipped_src_rect(const GrRenderTarget* rt,
|
| }
|
| }
|
| clippedSrcRect.roundOut(clippedSrcIRect);
|
| - SkIRect bmpBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
|
| + SkIRect bmpBounds = SkIRect::MakeSize(imageSize);
|
| if (!clippedSrcIRect->intersect(bmpBounds)) {
|
| clippedSrcIRect->setEmpty();
|
| }
|
| }
|
|
|
| -bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
|
| - const SkMatrix& viewMatrix,
|
| - const GrTextureParams& params,
|
| - const SkRect* srcRectPtr,
|
| - int maxTileSize,
|
| - int* tileSize,
|
| - SkIRect* clippedSrcRect) const {
|
| - // if bitmap is explictly texture backed then just use the texture
|
| - if (bitmap.getTexture()) {
|
| - return false;
|
| - }
|
| -
|
| +bool SkGpuDevice::shouldTileImageID(uint32_t imageID, const SkIRect& imageRect,
|
| + const SkMatrix& viewMatrix,
|
| + const GrTextureParams& params,
|
| + const SkRect* srcRectPtr,
|
| + int maxTileSize,
|
| + int* tileSize,
|
| + SkIRect* clippedSubset) const {
|
| // if it's larger than the max tile size, then we have no choice but tiling.
|
| - if (bitmap.width() > maxTileSize || bitmap.height() > maxTileSize) {
|
| - determine_clipped_src_rect(fRenderTarget, fClip, viewMatrix, bitmap,
|
| - srcRectPtr, clippedSrcRect);
|
| - *tileSize = determine_tile_size(bitmap, *clippedSrcRect, maxTileSize);
|
| + if (imageRect.width() > maxTileSize || imageRect.height() > maxTileSize) {
|
| + determine_clipped_src_rect(fRenderTarget, fClip, viewMatrix, imageRect.size(),
|
| + srcRectPtr, clippedSubset);
|
| + *tileSize = determine_tile_size(*clippedSubset, maxTileSize);
|
| return true;
|
| }
|
|
|
| - if (bitmap.width() * bitmap.height() < 4 * kBmpSmallTileSize * kBmpSmallTileSize) {
|
| + const size_t area = imageRect.width() * imageRect.height();
|
| + if (area < 4 * kBmpSmallTileSize * kBmpSmallTileSize) {
|
| return false;
|
| }
|
|
|
| - // if the entire texture is already in our cache then no reason to tile it
|
| - if (GrIsBitmapInCache(fContext, bitmap, ¶ms)) {
|
| + // if the entire image/bitmap is already in our cache then no reason to tile it
|
| + if (GrIsImageInCache(fContext, imageID, imageRect, nullptr, ¶ms)) {
|
| return false;
|
| }
|
|
|
| @@ -778,7 +774,7 @@ bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
|
|
|
| // assumption here is that sw bitmap size is a good proxy for its size as
|
| // a texture
|
| - size_t bmpSize = bitmap.getSize();
|
| + size_t bmpSize = area * sizeof(SkPMColor); // assume 32bit pixels
|
| size_t cacheSize;
|
| fContext->getResourceCacheLimits(nullptr, &cacheSize);
|
| if (bmpSize < cacheSize / 2) {
|
| @@ -786,15 +782,64 @@ bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
|
| }
|
|
|
| // Figure out how much of the src we will need based on the src rect and clipping.
|
| - determine_clipped_src_rect(fRenderTarget, fClip, viewMatrix, bitmap, srcRectPtr,
|
| - clippedSrcRect);
|
| + determine_clipped_src_rect(fRenderTarget, fClip, viewMatrix, imageRect.size(), srcRectPtr,
|
| + clippedSubset);
|
| *tileSize = kBmpSmallTileSize; // already know whole bitmap fits in one max sized tile.
|
| - size_t usedTileBytes = get_tile_count(*clippedSrcRect, kBmpSmallTileSize) *
|
| + size_t usedTileBytes = get_tile_count(*clippedSubset, kBmpSmallTileSize) *
|
| kBmpSmallTileSize * kBmpSmallTileSize;
|
|
|
| return usedTileBytes < 2 * bmpSize;
|
| }
|
|
|
| +bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
|
| + const SkMatrix& viewMatrix,
|
| + const GrTextureParams& params,
|
| + const SkRect* srcRectPtr,
|
| + int maxTileSize,
|
| + int* tileSize,
|
| + SkIRect* clippedSrcRect) const {
|
| + // if bitmap is explictly texture backed then just use the texture
|
| + if (bitmap.getTexture()) {
|
| + return false;
|
| + }
|
| +
|
| + return this->shouldTileImageID(bitmap.getGenerationID(), bitmap.getSubset(), viewMatrix, params,
|
| + srcRectPtr, maxTileSize, tileSize, clippedSrcRect);
|
| +}
|
| +
|
| +bool SkGpuDevice::shouldTileImage(const SkImage* image, const SkRect* srcRectPtr,
|
| + SkCanvas::SrcRectConstraint constraint, SkFilterQuality quality,
|
| + const SkMatrix& viewMatrix) const {
|
| + // if image is explictly texture backed then just use the texture
|
| + if (as_IB(image)->peekTexture()) {
|
| + return false;
|
| + }
|
| +
|
| + GrTextureParams params;
|
| + bool doBicubic;
|
| + GrTextureParams::FilterMode textureFilterMode =
|
| + GrSkFilterQualityToGrFilterMode(quality, viewMatrix, SkMatrix::I(), &doBicubic);
|
| +
|
| + int tileFilterPad;
|
| + if (doBicubic) {
|
| + tileFilterPad = GrBicubicEffect::kFilterTexelPad;
|
| + } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) {
|
| + tileFilterPad = 0;
|
| + } else {
|
| + tileFilterPad = 1;
|
| + }
|
| + params.setFilterMode(textureFilterMode);
|
| +
|
| + int maxTileSize = fContext->caps()->maxTextureSize() - 2 * tileFilterPad;
|
| +
|
| + // these are output, which we safely ignore, as we just want to know the predicate
|
| + int outTileSize;
|
| + SkIRect outClippedSrcRect;
|
| +
|
| + return this->shouldTileImageID(image->unique(), image->bounds(), viewMatrix, params, srcRectPtr,
|
| + maxTileSize, &outTileSize, &outClippedSrcRect);
|
| +}
|
| +
|
| void SkGpuDevice::drawBitmap(const SkDraw& origDraw,
|
| const SkBitmap& bitmap,
|
| const SkMatrix& m,
|
| @@ -1090,11 +1135,9 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
|
|
|
| // If there is no mask filter than it is OK to handle the src rect -> dst rect scaling using
|
| // the view matrix rather than a local matrix.
|
| - SkMatrix m;
|
| - m.setScale(dstSize.fWidth / srcRect.width(),
|
| - dstSize.fHeight / srcRect.height());
|
| SkMatrix viewM = *draw.fMatrix;
|
| - viewM.preConcat(m);
|
| + viewM.preScale(dstSize.fWidth / srcRect.width(),
|
| + dstSize.fHeight / srcRect.height());
|
|
|
| GrTextureParams params;
|
| bool doBicubic;
|
| @@ -1546,8 +1589,8 @@ bool SkGpuDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src,
|
| filter, ctx, result, offset);
|
| }
|
|
|
| -static bool wrap_as_bm(const SkImage* image, SkBitmap* bm) {
|
| - GrTexture* tex = as_IB(image)->getTexture();
|
| +static bool wrap_as_bm(GrContext* ctx, const SkImage* image, SkBitmap* bm) {
|
| + SkAutoTUnref<GrTexture> tex(as_IB(image)->asTextureRef(ctx, kUntiled_SkImageUsageType));
|
| if (tex) {
|
| GrWrapTextureInBitmap(tex, image->width(), image->height(), image->isOpaque(), bm);
|
| return true;
|
| @@ -1559,18 +1602,47 @@ static bool wrap_as_bm(const SkImage* image, SkBitmap* bm) {
|
| void SkGpuDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x, SkScalar y,
|
| const SkPaint& paint) {
|
| SkBitmap bm;
|
| - if (wrap_as_bm(image, &bm)) {
|
| - this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
|
| + if (GrTexture* tex = as_IB(image)->peekTexture()) {
|
| + GrWrapTextureInBitmap(tex, image->width(), image->height(), image->isOpaque(), &bm);
|
| + } else {
|
| + if (this->shouldTileImage(image, nullptr, SkCanvas::kFast_SrcRectConstraint,
|
| + paint.getFilterQuality(), *draw.fMatrix)) {
|
| + // only support tiling as bitmap at the moment, so force raster-version
|
| + if (!as_IB(image)->getROPixels(&bm)) {
|
| + return;
|
| + }
|
| + } else {
|
| + if (!wrap_as_bm(this->context(), image, &bm)) {
|
| + return;
|
| + }
|
| + }
|
| }
|
| + this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
|
| }
|
|
|
| void SkGpuDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const SkRect* src,
|
| const SkRect& dst, const SkPaint& paint,
|
| SkCanvas::SrcRectConstraint constraint) {
|
| SkBitmap bm;
|
| - if (wrap_as_bm(image, &bm)) {
|
| - this->drawBitmapRect(draw, bm, src, dst, paint, constraint);
|
| + if (GrTexture* tex = as_IB(image)->peekTexture()) {
|
| + GrWrapTextureInBitmap(tex, image->width(), image->height(), image->isOpaque(), &bm);
|
| + } else {
|
| + SkMatrix viewMatrix = *draw.fMatrix;
|
| + viewMatrix.preScale(dst.width() / (src ? src->width() : image->width()),
|
| + dst.height() / (src ? src->height() : image->height()));
|
| +
|
| + if (this->shouldTileImage(image, src, constraint, paint.getFilterQuality(), viewMatrix)) {
|
| + // only support tiling as bitmap at the moment, so force raster-version
|
| + if (!as_IB(image)->getROPixels(&bm)) {
|
| + return;
|
| + }
|
| + } else {
|
| + if (!wrap_as_bm(this->context(), image, &bm)) {
|
| + return;
|
| + }
|
| + }
|
| }
|
| + this->drawBitmapRect(draw, bm, src, dst, paint, constraint);
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|