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, |