Index: src/gpu/SkGpuDevice.cpp |
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp |
index e978bafa7e43ace2c889586241a855ba38863fd2..6a8b82a9e23797bd471f918e98267e9c10fa1b79 100644 |
--- a/src/gpu/SkGpuDevice.cpp |
+++ b/src/gpu/SkGpuDevice.cpp |
@@ -33,6 +33,7 @@ |
#include "SkRasterClip.h" |
#include "SkRRect.h" |
#include "SkRecord.h" |
+#include "SkSpecialImage.h" |
#include "SkStroke.h" |
#include "SkSurface.h" |
#include "SkSurface_Gpu.h" |
@@ -230,47 +231,34 @@ sk_sp<GrDrawContext> SkGpuDevice::CreateDrawContext(GrContext* context, |
origInfo.width(), origInfo.height(), |
config, sampleCount, |
kDefault_GrSurfaceOrigin, surfaceProps, budgeted); |
+} |
+sk_sp<SkSpecialImage> SkGpuDevice::filterTexture(const SkDraw& draw, |
+ SkSpecialImage* srcImg, |
+ int left, int top, |
+ SkIPoint* offset, |
+ const SkImageFilter* filter) { |
+ SkASSERT(srcImg->isTextureBacked()); |
+ 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()); |
+ |
+ return filter->filterImage(srcImg, ctx, offset); |
} |
-// 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) { |
+ int left, int top, const SkPaint& paint) { |
ASSERT_SINGLE_OWNER |
+ CHECK_SHOULD_DRAW(draw); |
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; |
- } |
- |
- GrTexture* texture; |
- // draw sprite neither filters nor tiles. |
- AutoBitmapTexture abt(fContext, bitmap, GrTextureParams::ClampNoFilter(), |
- SkSourceGammaTreatment::kRespect, &texture); |
- if (!texture) { |
- return; |
- } |
- |
- SkBitmap newBitmap; |
- |
- GrWrapTextureInBitmap(texture, texture->width(), texture->height(), |
- bitmap.isOpaque(), &newBitmap); |
- |
- INHERITED::drawSpriteWithFilter(draw, newBitmap, x, y, paint); |
+ SkASSERT(paint.getImageFilter()); |
+ this->drawSprite(draw, bitmap, left, top, paint); |
} |
/////////////////////////////////////////////////////////////////////////////// |
@@ -1233,54 +1221,93 @@ 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()); |
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()); |
+ sk_sp<SkSpecialImage> srcImg(SkSpecialImage::MakeFromGpu(srcRect, |
+ bitmap.getGenerationID(), |
+ std::move(texture), |
+ &fDrawContext->surfaceProps())); |
+ |
+ this->drawSpecial(draw, srcImg.get(), left, top, paint); |
+} |
+ |
+ |
+void SkGpuDevice::drawSpecial(const SkDraw& draw, |
+ SkSpecialImage* special1, |
+ int left, int top, |
+ const SkPaint& paint) { |
+ |
+ SkIPoint offset = { 0, 0 }; |
+ |
+ sk_sp<SkSpecialImage> result; |
+ if (paint.getImageFilter()) { |
+ result = this->filterTexture(draw, special1, left, top, |
+ &offset, |
+ paint.getImageFilter()); |
+ if (!result) { |
+ return; |
+ } |
+ } else { |
+ result = sk_ref_sp(special1); |
+ } |
+ |
+ SkASSERT(result->isTextureBacked()); |
+ sk_sp<GrTexture> texture = result->asTextureRef(fContext); |
+ |
+ 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; |
} |
+ const SkIRect& subset = result->subset(); |
+ |
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, |