Chromium Code Reviews| Index: src/gpu/SkGpuDevice.cpp |
| diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp |
| index f6851f18126bd120b436ed5ec6f1bda2b7aa87a7..bb403c06ddc97fc4fa7cdea724bbc5e716dc8423 100644 |
| --- a/src/gpu/SkGpuDevice.cpp |
| +++ b/src/gpu/SkGpuDevice.cpp |
| @@ -36,6 +36,7 @@ |
| #include "SkRasterClip.h" |
| #include "SkRRect.h" |
| #include "SkRecord.h" |
| +#include "SkSpecialImage.h" |
| #include "SkStroke.h" |
| #include "SkSurface.h" |
| #include "SkSurface_Gpu.h" |
| @@ -236,44 +237,47 @@ sk_sp<GrDrawContext> SkGpuDevice::CreateDrawContext(GrContext* context, |
| } |
| -// This method ensures that we always have a texture-backed "bitmap" when we finally |
| -// call through to the base impl so that the image filtering code will take the |
| -// gpu-specific paths. This mirrors SkCanvas::internalDrawDevice (the other |
| -// use of SkImageFilter::filterImage) in that the source and dest will have |
| -// homogenous backing (e.g., raster or gpu). |
| -void SkGpuDevice::drawSpriteWithFilter(const SkDraw& draw, const SkBitmap& bitmap, |
| - int x, int y, const SkPaint& paint) { |
| - ASSERT_SINGLE_OWNER |
| - GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawSpriteWithFilter", fContext); |
| - |
| - if (fContext->abandoned()) { |
| - return; |
| - } |
| - |
| - if (bitmap.getTexture()) { |
| - INHERITED::drawSpriteWithFilter(draw, bitmap, x, y, paint); |
| - return; |
| - } |
| - |
| - SkAutoLockPixels alp(bitmap, !bitmap.getTexture()); |
| - if (!bitmap.getTexture() && !bitmap.readyToDraw()) { |
| - return; |
| +sk_sp<GrTexture> SkGpuDevice::filterTexture(const SkDraw& draw, |
| + sk_sp<GrTexture> texture, |
| + uint32_t generationID, |
| + const SkIRect& srcSubset, |
| + int left, int top, |
| + SkIRect* subset, SkIPoint* offset, |
| + const SkImageFilter* filter) { |
| + SkASSERT(filter); |
| + |
| + SkMatrix matrix = *draw.fMatrix; |
| + matrix.postTranslate(SkIntToScalar(-left), SkIntToScalar(-top)); |
| + const SkIRect clipBounds = draw.fRC->getBounds().makeOffset(-left, -top); |
| + SkAutoTUnref<SkImageFilterCache> cache(this->getImageFilterCache()); |
| + SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); |
| + |
| + sk_sp<SkSpecialImage> srcImg(SkSpecialImage::MakeFromGpu(srcSubset, |
| + generationID, |
| + std::move(texture), |
| + &fDrawContext->surfaceProps())); |
| + if (!srcImg) { |
| + return nullptr; // something disastrous happened |
| + } |
| + |
| + sk_sp<SkSpecialImage> resultImg(filter->filterImage(srcImg.get(), ctx, offset)); |
| + if (!resultImg) { |
| + return nullptr; |
| } |
| - GrTexture* texture; |
| - // draw sprite neither filters nor tiles. |
| - AutoBitmapTexture abt(fContext, bitmap, GrTextureParams::ClampNoFilter(), |
| - SkSourceGammaTreatment::kRespect, &texture); |
| - if (!texture) { |
| - return; |
| - } |
| + *subset = resultImg->subset(); |
| + return srcImg->asTextureRef(fContext); |
| +} |
| - SkBitmap newBitmap; |
| - GrWrapTextureInBitmap(texture, texture->width(), texture->height(), |
| - bitmap.isOpaque(), &newBitmap); |
| +void SkGpuDevice::drawSpriteWithFilter(const SkDraw& draw, const SkBitmap& bitmap, |
| + int left, int top, const SkPaint& paint) { |
| + ASSERT_SINGLE_OWNER |
| + CHECK_SHOULD_DRAW(draw); |
| + GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawSpriteWithFilter", fContext); |
| - INHERITED::drawSpriteWithFilter(draw, newBitmap, x, y, paint); |
| + SkASSERT(paint.getImageFilter()); |
| + this->drawSprite(draw, bitmap, left, top, paint); |
| } |
| /////////////////////////////////////////////////////////////////////////////// |
| @@ -1236,39 +1240,71 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap, |
| void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, |
| int left, int top, const SkPaint& paint) { |
| ASSERT_SINGLE_OWNER |
| - // drawSprite is defined to be in device coords. |
| CHECK_SHOULD_DRAW(draw); |
| + GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawSprite", fContext); |
| - SkAutoLockPixels alp(bitmap, !bitmap.getTexture()); |
| - if (!bitmap.getTexture() && !bitmap.readyToDraw()) { |
| + if (fContext->abandoned()) { |
| return; |
| } |
| - int offX = bitmap.pixelRefOrigin().fX; |
| - int offY = bitmap.pixelRefOrigin().fY; |
| - int w = bitmap.width(); |
| - int h = bitmap.height(); |
| - |
| - GrTexture* texture; |
| - // draw sprite neither filters nor tiles. |
| - AutoBitmapTexture abt(fContext, bitmap, GrTextureParams::ClampNoFilter(), |
| - SkSourceGammaTreatment::kRespect, &texture); |
| + sk_sp<GrTexture> texture = sk_ref_sp(bitmap.getTexture()); |
|
bsalomon
2016/07/14 17:19:33
I think I'm missing something. Once there is no Sk
|
| if (!texture) { |
| - return; |
| + SkAutoLockPixels alp(bitmap, true); |
| + if (!bitmap.readyToDraw()) { |
| + return; |
| + } |
| + |
| + // draw sprite neither filters nor tiles. |
| + texture.reset(GrRefCachedBitmapTexture(fContext, bitmap, |
| + GrTextureParams::ClampNoFilter(), |
| + SkSourceGammaTreatment::kRespect)); |
| + if (!texture) { |
| + return; |
| + } |
| } |
| - bool alphaOnly = kAlpha_8_SkColorType == bitmap.colorType(); |
| + SkIRect srcRect = SkIRect::MakeXYWH(bitmap.pixelRefOrigin().fX, |
| + bitmap.pixelRefOrigin().fY, |
| + bitmap.width(), |
| + bitmap.height()); |
| - SkASSERT(!paint.getImageFilter()); |
| + this->internalDrawSprite(draw, std::move(texture), bitmap.getGenerationID(), |
| + srcRect, left, top, paint); |
| +} |
| + |
| + |
| +void SkGpuDevice::internalDrawSprite(const SkDraw& draw, |
| + sk_sp<GrTexture> texture, |
| + uint32_t generationID, |
| + const SkIRect& srcRect, |
| + int left, int top, |
| + const SkPaint& paint) { |
| + |
| + SkIRect subset = srcRect; |
| + SkIPoint offset = { 0, 0 }; |
| + |
| + if (paint.getImageFilter()) { |
| + texture = this->filterTexture(draw, std::move(texture), generationID, srcRect, left, top, |
| + &subset, &offset, |
| + paint.getImageFilter()); |
| + if (!texture) { |
| + return; |
| + } |
| + } |
| + |
| + SkPaint tmpUnfiltered(paint); |
| + tmpUnfiltered.setImageFilter(nullptr); |
| + |
| + bool alphaOnly = kAlpha_8_GrPixelConfig == texture->config(); |
| GrPaint grPaint; |
| - sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(texture, SkMatrix::I())); |
| + sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(texture.get(), SkMatrix::I())); |
| if (alphaOnly) { |
| fp = GrFragmentProcessor::MulOutputByInputUnpremulColor(std::move(fp)); |
| } else { |
| fp = GrFragmentProcessor::MulOutputByInputAlpha(std::move(fp)); |
| } |
| - if (!SkPaintToGrPaintReplaceShader(this->context(), paint, std::move(fp), |
| + if (!SkPaintToGrPaintReplaceShader(this->context(), tmpUnfiltered, std::move(fp), |
| this->surfaceProps().isGammaCorrect(), &grPaint)) { |
| return; |
| } |
| @@ -1276,14 +1312,12 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, |
| fDrawContext->fillRectToRect(fClip, |
| grPaint, |
| SkMatrix::I(), |
| - SkRect::MakeXYWH(SkIntToScalar(left), |
| - SkIntToScalar(top), |
| - SkIntToScalar(w), |
| - SkIntToScalar(h)), |
| - SkRect::MakeXYWH(SkIntToScalar(offX) / texture->width(), |
| - SkIntToScalar(offY) / texture->height(), |
| - SkIntToScalar(w) / texture->width(), |
| - SkIntToScalar(h) / texture->height())); |
| + SkRect::Make(SkIRect::MakeXYWH(left + offset.fX, top + offset.fY, |
| + subset.width(), subset.height())), |
| + SkRect::MakeXYWH(SkIntToScalar(subset.fLeft) / texture->width(), |
| + SkIntToScalar(subset.fTop) / texture->height(), |
| + SkIntToScalar(subset.width()) / texture->width(), |
| + SkIntToScalar(subset.height()) / texture->height())); |
| } |
| void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, |