Revert "Add general quad API to SkGpuDevice"
This reverts commit 339e1cc8d4574a5498d9bf13bbbc91377c8b0846.
Reason for revert: compositor GM breaks dm on windows
Original change's description:
> Add general quad API to SkGpuDevice
>
> Heavily refactors SkGpuDevice's internal texturing code in an attempt
> to consolidate entry points for drawing an image. Helps lay the ground
> work for eventually implementing bitmap tiling with per-edge AA.
>
> Bug: skia:
> Change-Id: I9feb86d5315d73119deb21e954c45e45513a63f6
> Reviewed-on: https://skia-review.googlesource.com/c/191571
> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>
TBR=bsalomon@google.com,robertphillips@google.com,michaelludwig@google.com
Change-Id: I74bc7eb08855dff5535cf809fc47ce6f16d2c15d
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/c/195889
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
diff --git a/gm/compositor_quads.cpp b/gm/compositor_quads.cpp
index fd2487f..02fe08d 100644
--- a/gm/compositor_quads.cpp
+++ b/gm/compositor_quads.cpp
@@ -9,16 +9,16 @@
#if SK_SUPPORT_GPU
+#include "GrClip.h"
+#include "GrRect.h"
+#include "GrRenderTargetContextPriv.h"
+
#include "Resources.h"
-#include "SkColorMatrixFilter.h"
#include "SkFont.h"
-#include "SkGpuDevice.h"
+#include "SkGr.h"
#include "SkGradientShader.h"
#include "SkImage_Base.h"
#include "SkLineClipper.h"
-#include "SkMorphologyImageFilter.h"
-#include "SkPaintFilterCanvas.h"
-#include "SkShaderMaskFilter.h"
#include <array>
@@ -172,9 +172,9 @@
// the Chromium quad types, and a generic GM template to arrange renderers x transforms in a grid
/////////////////////////////////////////////////////////////////////////////////////////////////
-class ClipTileRenderer : public SkRefCntBase {
+class TileRenderer : public SkRefCntBase {
public:
- virtual ~ClipTileRenderer() {}
+ virtual ~TileRenderer() {}
// Draw the base rect, possibly clipped by 'clip' if that is not null. The edges to antialias
// are specified in 'edgeAA' (to make manipulation easier than an unsigned bitfield). 'tileID'
@@ -191,18 +191,7 @@
// TODO (michaelludwig) - once the quad APIs are in SkCanvas, drop these
// cached fields, which drawTile() needs
fContext = context;
-
- SkBaseDevice* device = canvas->getDevice();
- if (device->context()) {
- // Pretty sure it's a SkGpuDevice since this is a run as a GPU GM, unfortunately we
- // don't have RTTI for dynamic_cast
- fDevice = static_cast<SkGpuDevice*>(device);
- } else {
- // Assume that we're in viewer and not dm, so the canvas is an SkPaintFilterCanvas
- // and we need the device from its proxy (it always returns an SkNoPixelDevice).
- SkPaintFilterCanvas* filteredCanvas = static_cast<SkPaintFilterCanvas*>(canvas);
- fDevice = static_cast<SkGpuDevice*>(filteredCanvas->proxy()->getDevice());
- }
+ fRTC = rtc;
// All three lines in a list
SkPoint lines[6];
@@ -235,14 +224,15 @@
protected:
// Remembered for convenience in drawTile, set by drawTiles()
GrContext* fContext;
- SkGpuDevice* fDevice;
+ GrRenderTargetContext* fRTC;
- SkCanvas::QuadAAFlags maskToFlags(const bool edgeAA[4]) const {
- unsigned flags = (edgeAA[0] * SkCanvas::kTop_QuadAAFlag) |
- (edgeAA[1] * SkCanvas::kRight_QuadAAFlag) |
- (edgeAA[2] * SkCanvas::kBottom_QuadAAFlag) |
- (edgeAA[3] * SkCanvas::kLeft_QuadAAFlag);
- return static_cast<SkCanvas::QuadAAFlags>(flags);
+ GrQuadAAFlags maskToFlags(const bool edgeAA[4]) const {
+ GrQuadAAFlags flags = GrQuadAAFlags::kNone;
+ flags |= edgeAA[0] ? GrQuadAAFlags::kTop : GrQuadAAFlags::kNone;
+ flags |= edgeAA[1] ? GrQuadAAFlags::kRight : GrQuadAAFlags::kNone;
+ flags |= edgeAA[2] ? GrQuadAAFlags::kBottom : GrQuadAAFlags::kNone;
+ flags |= edgeAA[3] ? GrQuadAAFlags::kLeft : GrQuadAAFlags::kNone;
+ return flags;
}
// Recursively splits the quadrilateral against the segments stored in 'lines', which must be
@@ -402,13 +392,23 @@
class CompositorGM : public skiagm::GpuGM {
public:
- CompositorGM(const char* name, sk_sp<ClipTileRenderer> renderer)
+ CompositorGM(const char* name, sk_sp<TileRenderer> renderer)
: fName(name) {
fRenderers.push_back(std::move(renderer));
}
- CompositorGM(const char* name, const SkTArray<sk_sp<ClipTileRenderer>> renderers)
- : fRenderers(renderers)
- , fName(name) {}
+ CompositorGM(const char* name, sk_sp<TileRenderer> r1, sk_sp<TileRenderer> r2)
+ : fName(name) {
+ fRenderers.push_back(std::move(r1));
+ fRenderers.push_back(std::move(r2));
+ }
+ CompositorGM(const char* name, sk_sp<TileRenderer> r1, sk_sp<TileRenderer> r2,
+ sk_sp<TileRenderer> r3)
+ : fName(name) {
+ fRenderers.push_back(std::move(r1));
+ fRenderers.push_back(std::move(r2));
+ fRenderers.push_back(std::move(r3));
+ }
+ // 3 renderer modes is the max any GM needs right now
protected:
SkISize onISize() override {
@@ -475,7 +475,7 @@
private:
static constexpr int kMatrixCount = 5;
- SkTArray<sk_sp<ClipTileRenderer>> fRenderers;
+ SkTArray<sk_sp<TileRenderer>> fRenderers;
SkTArray<SkMatrix> fMatrices;
SkTArray<SkString> fMatrixNames;
@@ -526,20 +526,20 @@
// Implementations of TileRenderer that color the clipped tiles in various ways
////////////////////////////////////////////////////////////////////////////////////////////////
-class DebugTileRenderer : public ClipTileRenderer {
+class DebugTileRenderer : public TileRenderer {
public:
- static sk_sp<ClipTileRenderer> Make() {
+ static sk_sp<TileRenderer> Make() {
// Since aa override is disabled, the quad flags arg doesn't matter.
- return sk_sp<ClipTileRenderer>(new DebugTileRenderer(SkCanvas::kAll_QuadAAFlags, false));
+ return sk_sp<TileRenderer>(new DebugTileRenderer(GrQuadAAFlags::kAll, false));
}
- static sk_sp<ClipTileRenderer> MakeAA() {
- return sk_sp<ClipTileRenderer>(new DebugTileRenderer(SkCanvas::kAll_QuadAAFlags, true));
+ static sk_sp<TileRenderer> MakeAA() {
+ return sk_sp<TileRenderer>(new DebugTileRenderer(GrQuadAAFlags::kAll, true));
}
- static sk_sp<ClipTileRenderer> MakeNonAA() {
- return sk_sp<ClipTileRenderer>(new DebugTileRenderer(SkCanvas::kNone_QuadAAFlags, true));
+ static sk_sp<TileRenderer> MakeNonAA() {
+ return sk_sp<TileRenderer>(new DebugTileRenderer(GrQuadAAFlags::kNone, true));
}
void drawTile(SkCanvas* canvas, const SkRect& rect, const SkPoint clip[4], const bool edgeAA[4],
@@ -548,16 +548,24 @@
int i = tileID / kColCount;
int j = tileID % kColCount;
- SkColor4f c = {(i + 1.f) / kRowCount, (j + 1.f) / kColCount, .4f, 1.f};
+ SkPMColor4f c = {(i + 1.f) / kRowCount, (j + 1.f) / kColCount, .4f, 1.f};
float alpha = quadID / 10.f;
c.fR = c.fR * (1 - alpha) + alpha;
c.fG = c.fG * (1 - alpha) + alpha;
c.fB = c.fB * (1 - alpha) + alpha;
c.fA = c.fA * (1 - alpha) + alpha;
- SkCanvas::QuadAAFlags aaFlags = fEnableAAOverride ? fAAOverride : this->maskToFlags(edgeAA);
- fDevice->tmp_drawEdgeAAQuad(
- rect, clip, clip ? 4 : 0, aaFlags, c.toSkColor(), SkBlendMode::kSrcOver);
+ GrPaint paint;
+ paint.setColor4f(c);
+
+ GrQuadAAFlags aaFlags = fEnableAAOverride ? fAAOverride : this->maskToFlags(edgeAA);
+ if (clip) {
+ fRTC->fillQuadWithEdgeAA(GrNoClip(), std::move(paint), GrAA::kYes, aaFlags,
+ canvas->getTotalMatrix(), clip, nullptr);
+ } else {
+ fRTC->fillRectWithEdgeAA(GrNoClip(), std::move(paint), GrAA::kYes, aaFlags,
+ canvas->getTotalMatrix(), rect);
+ }
}
void drawBanner(SkCanvas* canvas) override {
@@ -568,9 +576,8 @@
SkString config;
static const char* kFormat = "Ext(%s) - Int(%s)";
if (fEnableAAOverride) {
- SkASSERT(fAAOverride == SkCanvas::kAll_QuadAAFlags ||
- fAAOverride == SkCanvas::kNone_QuadAAFlags);
- if (fAAOverride == SkCanvas::kAll_QuadAAFlags) {
+ SkASSERT(fAAOverride == GrQuadAAFlags::kAll || fAAOverride == GrQuadAAFlags::kNone);
+ if (fAAOverride == GrQuadAAFlags::kAll) {
config.appendf(kFormat, "yes", "yes");
} else {
config.appendf(kFormat, "no", "no");
@@ -584,28 +591,35 @@
}
private:
- SkCanvas::QuadAAFlags fAAOverride;
+ GrQuadAAFlags fAAOverride;
bool fEnableAAOverride;
- DebugTileRenderer(SkCanvas::QuadAAFlags aa, bool enableAAOverrde)
+ DebugTileRenderer(GrQuadAAFlags aa, bool enableAAOverrde)
: fAAOverride(aa)
, fEnableAAOverride(enableAAOverrde) {}
- typedef ClipTileRenderer INHERITED;
+ typedef TileRenderer INHERITED;
};
-// Tests tmp_drawEdgeAAQuad
-class SolidColorRenderer : public ClipTileRenderer {
+class SolidColorRenderer : public TileRenderer {
public:
- static sk_sp<ClipTileRenderer> Make(const SkColor4f& color) {
- return sk_sp<ClipTileRenderer>(new SolidColorRenderer(color));
+ static sk_sp<TileRenderer> Make(const SkPMColor4f& color) {
+ return sk_sp<TileRenderer>(new SolidColorRenderer(color));
}
void drawTile(SkCanvas* canvas, const SkRect& rect, const SkPoint clip[4], const bool edgeAA[4],
int tileID, int quadID) override {
- fDevice->tmp_drawEdgeAAQuad(rect, clip, clip ? 4 : 0, this->maskToFlags(edgeAA),
- fColor.toSkColor(), SkBlendMode::kSrcOver);
+ GrPaint paint;
+ paint.setColor4f(fColor);
+
+ if (clip) {
+ fRTC->fillQuadWithEdgeAA(GrNoClip(), std::move(paint), GrAA::kYes,
+ this->maskToFlags(edgeAA), canvas->getTotalMatrix(), clip, nullptr);
+ } else {
+ fRTC->fillRectWithEdgeAA(GrNoClip(), std::move(paint), GrAA::kYes,
+ this->maskToFlags(edgeAA), canvas->getTotalMatrix(), rect);
+ }
}
void drawBanner(SkCanvas* canvas) override {
@@ -613,69 +627,136 @@
}
private:
- SkColor4f fColor;
+ SkPMColor4f fColor;
- SolidColorRenderer(const SkColor4f& color) : fColor(color) {}
+ SolidColorRenderer(const SkPMColor4f& color) : fColor(color) {}
- typedef ClipTileRenderer INHERITED;
+ typedef TileRenderer INHERITED;
};
-// Tests tmp_drawImageSet(), but can batch the entries together in different ways
-// TODO(michaelludwig) - add transform batching
-class TextureSetRenderer : public ClipTileRenderer {
+class GradientRenderer : public TileRenderer {
public:
- static sk_sp<ClipTileRenderer> MakeUnbatched(sk_sp<SkImage> image) {
- return Make("Texture", "", std::move(image), nullptr, nullptr, nullptr, nullptr, 1.f, true);
+ static sk_sp<TileRenderer> MakeSeamless() {
+ return sk_sp<TileRenderer>(new GradientRenderer(false));
}
- static sk_sp<ClipTileRenderer> MakeBatched(sk_sp<SkImage> image) {
- return Make("Texture Set", "", std::move(image), nullptr, nullptr, nullptr, nullptr, 1.f,
- false);
+ static sk_sp<TileRenderer> MakeLocal() {
+ return sk_sp<TileRenderer>(new GradientRenderer(true));
}
- static sk_sp<ClipTileRenderer> MakeShader(const char* name, sk_sp<SkImage> image,
- sk_sp<SkShader> shader, bool local) {
- return Make("Shader", name, std::move(image), std::move(shader),
- nullptr, nullptr, nullptr, 1.f, local);
+ void drawTile(SkCanvas* canvas, const SkRect& rect, const SkPoint clip[4], const bool edgeAA[4],
+ int tileID, int quadID) override {
+ GrPaint paint;
+ SkPaintToGrPaint(fContext, fRTC->colorSpaceInfo(), fGradient, canvas->getTotalMatrix(),
+ &paint);
+
+ SkRect localRect = SkRect::MakeWH(kTileWidth, kTileHeight);
+ SkPoint localQuad[4];
+ if (fLocal && clip) {
+ GrMapRectPoints(rect, localRect, clip, localQuad, 4);
+ }
+
+ if (clip) {
+ fRTC->fillQuadWithEdgeAA(GrNoClip(), std::move(paint), GrAA::kYes,
+ this->maskToFlags(edgeAA), canvas->getTotalMatrix(), clip,
+ fLocal ? localQuad : nullptr);
+ } else {
+ fRTC->fillRectWithEdgeAA(GrNoClip(), std::move(paint), GrAA::kYes,
+ this->maskToFlags(edgeAA), canvas->getTotalMatrix(), rect,
+ fLocal ? &localRect : nullptr);
+ }
}
- static sk_sp<ClipTileRenderer> MakeColorFilter(const char* name, sk_sp<SkImage> image,
- sk_sp<SkColorFilter> filter) {
- return Make("Color Filter", name, std::move(image), nullptr, std::move(filter), nullptr,
- nullptr, 1.f, false);
+ void drawBanner(SkCanvas* canvas) override {
+ canvas->save();
+ draw_text(canvas, "Gradient");
+ canvas->translate(0.f, 15.f);
+ if (fLocal) {
+ draw_text(canvas, "Local");
+ } else {
+ draw_text(canvas, "Seamless");
+ }
+ canvas->restore();
}
- static sk_sp<ClipTileRenderer> MakeImageFilter(const char* name, sk_sp<SkImage> image,
- sk_sp<SkImageFilter> filter) {
- return Make("Image Filter", name, std::move(image), nullptr, nullptr, std::move(filter),
- nullptr, 1.f, false);
+private:
+ SkPaint fGradient;
+ bool fLocal;
+
+ GradientRenderer(bool local) : fLocal(local) {
+ static constexpr SkPoint pts[] = { {0.f, 0.f}, {0.25f * kTileWidth, 0.25f * kTileHeight} };
+ static constexpr SkColor colors[] = { SK_ColorBLUE, SK_ColorWHITE };
+ auto gradient = SkGradientShader::MakeLinear(pts, colors, nullptr, 2,
+ SkShader::kMirror_TileMode);
+ fGradient.setShader(gradient);
}
- static sk_sp<ClipTileRenderer> MakeMaskFilter(const char* name, sk_sp<SkImage> image,
- sk_sp<SkMaskFilter> filter) {
- return Make("Mask Filter", name, std::move(image), nullptr, nullptr, nullptr,
- std::move(filter), 1.f, false);
+ typedef TileRenderer INHERITED;
+};
+
+static SkRect get_image_local_rect(const sk_sp<SkImage> image, const SkRect& rect) {
+ // This acts like the whole image is rendered over the entire tile grid, so derive local
+ // coordinates from 'rect', based on the grid to image transform.
+ SkMatrix gridToImage = SkMatrix::MakeRectToRect(SkRect::MakeWH(kColCount * kTileWidth,
+ kRowCount * kTileHeight),
+ SkRect::MakeWH(image->width(),
+ image->height()),
+ SkMatrix::kFill_ScaleToFit);
+ return gridToImage.mapRect(rect);
+}
+
+class TextureRenderer : public TileRenderer {
+public:
+
+ static sk_sp<TileRenderer> Make(sk_sp<SkImage> image) {
+ return sk_sp<TileRenderer>(new TextureRenderer(image));
}
- static sk_sp<ClipTileRenderer> MakeAlpha(sk_sp<SkImage> image, SkScalar alpha) {
- return Make("Alpha", SkStringPrintf("a = %.2f", alpha).c_str(), std::move(image), nullptr,
- nullptr, nullptr, nullptr, alpha, false);
+ void drawTile(SkCanvas* canvas, const SkRect& rect, const SkPoint clip[4], const bool edgeAA[4],
+ int tileID, int quadID) override {
+ SkPMColor4f color = {1.f, 1.f, 1.f, 1.f};
+ SkRect localRect = get_image_local_rect(fImage, rect);
+
+ fImage = fImage->makeTextureImage(fContext, nullptr);
+ sk_sp<GrTextureProxy> proxy = as_IB(fImage)->asTextureProxyRef();
+ SkASSERT(proxy);
+ if (clip) {
+ SkPoint localQuad[4];
+ GrMapRectPoints(rect, localRect, clip, localQuad, 4);
+ fRTC->drawTextureQuad(GrNoClip(), std::move(proxy), GrSamplerState::Filter::kBilerp,
+ SkBlendMode::kSrcOver, color, localQuad, clip, GrAA::kYes,
+ this->maskToFlags(edgeAA), nullptr, canvas->getTotalMatrix(), nullptr);
+ } else {
+ fRTC->drawTexture(GrNoClip(), std::move(proxy), GrSamplerState::Filter::kBilerp,
+ SkBlendMode::kSrcOver, color, localRect, rect, GrAA::kYes,
+ this->maskToFlags(edgeAA), SkCanvas::kFast_SrcRectConstraint,
+ canvas->getTotalMatrix(), nullptr);
+ }
}
- static sk_sp<ClipTileRenderer> Make(const char* topBanner, const char* bottomBanner,
- sk_sp<SkImage> image, sk_sp<SkShader> shader,
- sk_sp<SkColorFilter> colorFilter,
- sk_sp<SkImageFilter> imageFilter,
- sk_sp<SkMaskFilter> maskFilter, SkScalar paintAlpha,
- bool resetAfterEachQuad) {
- return sk_sp<ClipTileRenderer>(new TextureSetRenderer(topBanner, bottomBanner,
- std::move(image), std::move(shader), std::move(colorFilter), std::move(imageFilter),
- std::move(maskFilter), paintAlpha, resetAfterEachQuad));
+ void drawBanner(SkCanvas* canvas) override {
+ draw_text(canvas, "Texture");
+ }
+
+private:
+ sk_sp<SkImage> fImage;
+
+ TextureRenderer(sk_sp<SkImage> image)
+ : fImage(image) {}
+
+ typedef TileRenderer INHERITED;
+};
+
+// Looks like TextureRenderer, but bundles tiles into drawTextureSet calls
+class TextureSetRenderer : public TileRenderer {
+public:
+
+ static sk_sp<TileRenderer> Make(sk_sp<SkImage> image) {
+ return sk_sp<TileRenderer>(new TextureSetRenderer(image));
}
void drawTiles(SkCanvas* canvas, GrContext* ctx, GrRenderTargetContext* rtc) override {
- SkASSERT(fImage); // initImage should be called before any drawing
this->INHERITED::drawTiles(canvas, ctx, rtc);
// Push the last tile set
this->drawAndReset(canvas);
@@ -687,219 +768,89 @@
if (tileID != fCurrentTileID) {
this->drawAndReset(canvas);
}
- SkASSERT((fCurrentTileID < 0 && fDstClips.count() == 0 && fDstClipCounts.count() == 0 &&
+ SkASSERT((fCurrentTileID < 0 && fDstClips.count() == 0 && fDstClipIndices.count() == 0 &&
fSetEntries.count() == 0) ||
(fCurrentTileID == tileID && fSetEntries.count() > 0));
// Now don't actually draw the tile, accumulate it in the growing entry set
fCurrentTileID = tileID;
- int clipCount = 0;
+ int clipIndex = -1;
if (clip) {
- // Record the four points into fDstClips
- clipCount = 4;
+ // Record the four points into fDstClips and get the pointer to the first in the array
+ clipIndex = fDstClips.count();
fDstClips.push_back_n(4, clip);
}
- // This acts like the whole image is rendered over the entire tile grid, so derive local
- // coordinates from 'rect', based on the grid to image transform.
- SkMatrix gridToImage = SkMatrix::MakeRectToRect(SkRect::MakeWH(kColCount * kTileWidth,
- kRowCount * kTileHeight),
- SkRect::MakeWH(fImage->width(),
- fImage->height()),
- SkMatrix::kFill_ScaleToFit);
- SkRect localRect = gridToImage.mapRect(rect);
+ SkRect localRect = get_image_local_rect(fImage, rect);
+ fImage = fImage->makeTextureImage(fContext, nullptr);
+ sk_sp<GrTextureProxy> proxy = as_IB(fImage)->asTextureProxyRef();
// drawTextureSet automatically derives appropriate local quad from localRect if clipPtr
// is not null.
- fSetEntries.push_back({fImage, localRect, rect, 1.f, this->maskToFlags(edgeAA)});
- fDstClipCounts.push_back(clipCount);
-
- if (fResetEachQuad) {
- // Only ever draw one entry at a time
- this->drawAndReset(canvas);
- }
+ fSetEntries.push_back({proxy, localRect, rect, nullptr, 1.f, this->maskToFlags(edgeAA)});
+ fDstClipIndices.push_back(clipIndex);
}
void drawBanner(SkCanvas* canvas) override {
- canvas->save();
- if (fTopBanner.size() > 0) {
- draw_text(canvas, fTopBanner.c_str());
- }
- canvas->translate(0.f, 15.f);
- if (fBottomBanner.size() > 0) {
- draw_text(canvas, fBottomBanner.c_str());
- }
- canvas->restore();
+ draw_text(canvas, "Texture Set");
}
private:
- SkString fTopBanner;
- SkString fBottomBanner;
-
sk_sp<SkImage> fImage;
- sk_sp<SkShader> fShader;
- sk_sp<SkColorFilter> fColorFilter;
- sk_sp<SkImageFilter> fImageFilter;
- sk_sp<SkMaskFilter> fMaskFilter;
- SkScalar fPaintAlpha;
- bool fResetEachQuad;
SkTArray<SkPoint> fDstClips;
- // ImageSetEntry does not yet have a fDstClipCount field
- SkTArray<int> fDstClipCounts;
- SkTArray<SkCanvas::ImageSetEntry> fSetEntries;
+ // Since fDstClips will reallocate as needed, can't get the final pointer for the entries'
+ // fDstClip values until submitting the entire set
+ SkTArray<int> fDstClipIndices;
+ SkTArray<GrRenderTargetContext::TextureSetEntry> fSetEntries;
int fCurrentTileID;
- TextureSetRenderer(const char* topBanner,
- const char* bottomBanner,
- sk_sp<SkImage> image,
- sk_sp<SkShader> shader,
- sk_sp<SkColorFilter> colorFilter,
- sk_sp<SkImageFilter> imageFilter,
- sk_sp<SkMaskFilter> maskFilter,
- SkScalar paintAlpha,
- bool resetEachQuad)
- : fTopBanner(topBanner)
- , fBottomBanner(bottomBanner)
- , fImage(std::move(image))
- , fShader(std::move(shader))
- , fColorFilter(std::move(colorFilter))
- , fImageFilter(std::move(imageFilter))
- , fMaskFilter(std::move(maskFilter))
- , fPaintAlpha(paintAlpha)
- , fResetEachQuad(resetEachQuad)
- , fCurrentTileID(-1) {}
-
- void configureTilePaint(const SkRect& rect, int tileID, SkPaint* paint) const {
- paint->setAntiAlias(true);
- paint->setFilterQuality(kLow_SkFilterQuality);
- paint->setBlendMode(SkBlendMode::kSrcOver);
-
- // Send non-white RGB, that should be ignored
- paint->setColor4f({1.f, 0.4f, 0.25f, fPaintAlpha}, nullptr);
-
-
- if (fShader) {
- if (fResetEachQuad) {
- // Apply a local transform in the shader to map from the tile rectangle to (0,0,w,h)
- static const SkRect kTarget = SkRect::MakeWH(kTileWidth, kTileHeight);
- SkMatrix local = SkMatrix::MakeRectToRect(kTarget, rect,
- SkMatrix::kFill_ScaleToFit);
- paint->setShader(fShader->makeWithLocalMatrix(local));
- } else {
- paint->setShader(fShader);
- }
- }
-
- paint->setColorFilter(fColorFilter);
- paint->setImageFilter(fImageFilter);
- paint->setMaskFilter(fMaskFilter);
- }
+ TextureSetRenderer(sk_sp<SkImage> image)
+ : fImage(image)
+ , fCurrentTileID(-1) {}
void drawAndReset(SkCanvas* canvas) {
// Early out if there's nothing to draw
if (fSetEntries.count() == 0) {
- SkASSERT(fCurrentTileID < 0 && fDstClips.count() == 0 && fDstClipCounts.count() == 0);
+ SkASSERT(fCurrentTileID < 0 && fDstClips.count() == 0 && fDstClipIndices.count() == 0);
return;
}
- // NOTE: Eventually fDstClipCounts will just be stored as a field on each entry
- SkASSERT(fDstClipCounts.count() == fSetEntries.count());
-
-#ifdef SK_DEBUG
- int expectedDstClipCount = 0;
- for (int i = 0; i < fDstClipCounts.count(); ++i) {
- expectedDstClipCount += fDstClipCounts[i];
+ // Fill in fDstClip in the entries now that fDstClips' storage won't change until after the
+ // draw is finished.
+ // NOTE: The eventual API in SkGpuDevice will make easier to collect
+ // SkCanvas::ImageSetEntries and dst clips without this extra work, but also internally maps
+ // very cleanly on to the TextureSetEntry fDstClip approach.
+ SkASSERT(fDstClipIndices.count() == fSetEntries.count());
+ for (int i = 0; i < fSetEntries.count(); ++i) {
+ if (fDstClipIndices[i] >= 0) {
+ fSetEntries[i].fDstClip = &fDstClips[fDstClipIndices[i]];
+ }
}
- SkASSERT(expectedDstClipCount == fDstClips.count());
-#endif
- SkPaint paint;
- SkRect lastTileRect = fSetEntries[fSetEntries.count() - 1].fDstRect;
- this->configureTilePaint(lastTileRect, fCurrentTileID, &paint);
-
- fDevice->tmp_drawImageSetV2(fSetEntries.begin(), fDstClipCounts.begin(),
- fSetEntries.count(), fDstClips.begin(), paint,
- SkCanvas::kFast_SrcRectConstraint);
-
+ // Send to GPU
+ fRTC->drawTextureSet(GrNoClip(), fSetEntries.begin(), fSetEntries.count(),
+ GrSamplerState::Filter::kBilerp, SkBlendMode::kSrcOver, GrAA::kYes,
+ canvas->getTotalMatrix(), nullptr);
// Reset for next tile
fCurrentTileID = -1;
fDstClips.reset();
- fDstClipCounts.reset();
+ fDstClipIndices.reset();
fSetEntries.reset();
}
- typedef ClipTileRenderer INHERITED;
+ typedef TileRenderer INHERITED;
};
-static SkTArray<sk_sp<ClipTileRenderer>> make_debug_renderers() {
- SkTArray<sk_sp<ClipTileRenderer>> renderers;
- renderers.push_back(DebugTileRenderer::Make());
- renderers.push_back(DebugTileRenderer::MakeAA());
- renderers.push_back(DebugTileRenderer::MakeNonAA());
- return renderers;
-}
-
-static SkTArray<sk_sp<ClipTileRenderer>> make_shader_renderers() {
- static constexpr SkPoint kPts[] = { {0.f, 0.f}, {0.25f * kTileWidth, 0.25f * kTileHeight} };
- static constexpr SkColor kColors[] = { SK_ColorBLUE, SK_ColorWHITE };
- auto gradient = SkGradientShader::MakeLinear(kPts, kColors, nullptr, 2,
- SkShader::kMirror_TileMode);
-
- auto info = SkImageInfo::Make(1, 1, kAlpha_8_SkColorType, kOpaque_SkAlphaType);
- SkBitmap bm;
- bm.allocPixels(info);
- bm.eraseColor(SK_ColorWHITE);
- sk_sp<SkImage> image = SkImage::MakeFromBitmap(bm);
-
- SkTArray<sk_sp<ClipTileRenderer>> renderers;
- renderers.push_back(TextureSetRenderer::MakeShader("Gradient", image, gradient, false));
- renderers.push_back(TextureSetRenderer::MakeShader("Local Gradient", image, gradient, true));
- return renderers;
-}
-
-static SkTArray<sk_sp<ClipTileRenderer>> make_image_renderers() {
- sk_sp<SkImage> mandrill = GetResourceAsImage("images/mandrill_512.png");
- SkTArray<sk_sp<ClipTileRenderer>> renderers;
- renderers.push_back(TextureSetRenderer::MakeUnbatched(mandrill));
- renderers.push_back(TextureSetRenderer::MakeBatched(mandrill));
- return renderers;
-}
-
-static SkTArray<sk_sp<ClipTileRenderer>> make_filtered_renderers() {
- sk_sp<SkImage> mandrill = GetResourceAsImage("images/mandrill_512.png");
-
- SkColorMatrix cm;
- cm.setSaturation(10);
- sk_sp<SkColorFilter> colorFilter = SkColorFilter::MakeMatrixFilterRowMajor255(cm.fMat);
- sk_sp<SkImageFilter> imageFilter = SkDilateImageFilter::Make(8, 8, nullptr);
-
- static constexpr SkColor kAlphas[] = { SK_ColorTRANSPARENT, SK_ColorBLACK };
- auto alphaGradient = SkGradientShader::MakeRadial(
- {0.5f * kTileWidth * kColCount, 0.5f * kTileHeight * kRowCount},
- 0.25f * kTileWidth * kColCount, kAlphas, nullptr, 2, SkShader::kClamp_TileMode);
- sk_sp<SkMaskFilter> maskFilter = SkShaderMaskFilter::Make(std::move(alphaGradient));
-
- SkTArray<sk_sp<ClipTileRenderer>> renderers;
- renderers.push_back(TextureSetRenderer::MakeAlpha(mandrill, 0.5f));
- renderers.push_back(TextureSetRenderer::MakeColorFilter("Saturation", mandrill,
- std::move(colorFilter)));
- // NOTE: won't draw correctly until SkCanvas' AutoLoopers are used to handle image filters
- renderers.push_back(TextureSetRenderer::MakeImageFilter("Dilate", mandrill,
- std::move(imageFilter)));
-
- renderers.push_back(TextureSetRenderer::MakeMaskFilter("Shader", mandrill,
- std::move(maskFilter)));
- // NOTE: blur mask filters do work (tested locally), but visually they don't make much
- // sense, since each quad is blurred independently
- return renderers;
-}
-
-DEF_GM(return new CompositorGM("debug", make_debug_renderers());)
-DEF_GM(return new CompositorGM("color", SolidColorRenderer::Make({.2f, .8f, .3f, 1.f}));)
-DEF_GM(return new CompositorGM("shader", make_shader_renderers());)
-DEF_GM(return new CompositorGM("image", make_image_renderers());)
-DEF_GM(return new CompositorGM("filter", make_filtered_renderers());)
+DEF_GM(return new CompositorGM("debug",
+ DebugTileRenderer::Make(), DebugTileRenderer::MakeAA(),
+ DebugTileRenderer::MakeNonAA());)
+DEF_GM(return new CompositorGM("color", SolidColorRenderer::Make({.2f, .8f, .3f, 1.f})));
+DEF_GM(return new CompositorGM("shader",
+ GradientRenderer::MakeSeamless(), GradientRenderer::MakeLocal()));
+DEF_GM(return new CompositorGM("image",
+ TextureRenderer::Make(GetResourceAsImage("images/mandrill_512.png")),
+ TextureSetRenderer::Make(GetResourceAsImage("images/mandrill_512.png"))));
#endif // SK_SUPPORT_GPU
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index 42c81a9..4786775 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -2563,7 +2563,7 @@
friend class SkPictureRecord; // predrawNotify (why does it need it? <reed>)
friend class SkOverdrawCanvas;
friend class SkRasterHandleAllocator;
- friend class ClipTileRenderer; // GM needs getTopDevice() until API is in SkCanvas
+
protected:
// For use by SkNoDrawCanvas (via SkCanvasVirtualEnforcer, which can't be a friend)
SkCanvas(const SkIRect& bounds);
diff --git a/include/utils/SkPaintFilterCanvas.h b/include/utils/SkPaintFilterCanvas.h
index 8f6aedb..2781a20 100644
--- a/include/utils/SkPaintFilterCanvas.h
+++ b/include/utils/SkPaintFilterCanvas.h
@@ -114,8 +114,6 @@
bool onGetProps(SkSurfaceProps* props) const override;
private:
- friend class ClipTileRenderer; // GM needs proxy() until API is in SkCanvas
-
class AutoPaintFilter;
SkCanvas* proxy() const { SkASSERT(fList.count() == 1); return fList[0]; }
diff --git a/src/core/SkDevice.h b/src/core/SkDevice.h
index c0796cd..2fd3c15 100644
--- a/src/core/SkDevice.h
+++ b/src/core/SkDevice.h
@@ -341,8 +341,6 @@
friend class SkGlyphRunList;
friend class SkGlyphRunBuilder;
- friend class ClipTileRenderer; // GM needs context() until API is in SkCanvas
-
// used to change the backend's pixels (and possibly config/rowbytes)
// but cannot change the width/height, so there should be no change to
// any clip information.
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 84aa9b4..d488403 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -1074,7 +1074,7 @@
// Draw one at a time with GrFillRectOp and a GrPaint that emulates what GrTextureOp does
for (int i = 0; i < cnt; ++i) {
float alpha = set[i].fAlpha;
- if (set[i].fDstClipQuad == nullptr) {
+ if (set[i].fDstClip == nullptr) {
// Stick with original rectangles, which allows the ops to know more about what's
// being drawn.
this->drawTexture(clip, set[i].fProxy, filter, mode, {alpha, alpha, alpha, alpha},
@@ -1083,12 +1083,12 @@
} else {
// Generate interpolated texture coordinates to match the dst clip
SkPoint srcQuad[4];
- GrMapRectPoints(set[i].fDstRect, set[i].fSrcRect, set[i].fDstClipQuad, srcQuad, 4);
+ GrMapRectPoints(set[i].fDstRect, set[i].fSrcRect, set[i].fDstClip, srcQuad, 4);
// Don't send srcRect as the domain, since the normal case doesn't use a constraint
// with the entire srcRect, so sampling into dstRect outside of dstClip will just
// keep seams look more correct.
this->drawTextureQuad(clip, set[i].fProxy, filter, mode,
- {alpha, alpha, alpha, alpha}, srcQuad, set[i].fDstClipQuad,
+ {alpha, alpha, alpha, alpha}, srcQuad, set[i].fDstClip,
aa, set[i].fAAFlags, nullptr, viewMatrix, texXform);
}
}
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index 8b14e87..8f344cd 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -195,7 +195,7 @@
sk_sp<GrTextureProxy> fProxy;
SkRect fSrcRect;
SkRect fDstRect;
- const SkPoint* fDstClipQuad; // Must be null, or point to an array of 4 points
+ SkPoint* fDstClip; // Must be null, or point to an array of 4 points
float fAlpha;
GrQuadAAFlags fAAFlags;
};
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index d56b2d3..0b790ca 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -10,6 +10,7 @@
#include "../private/SkShadowFlags.h"
#include "GrBitmapTextureMaker.h"
#include "GrBlurUtils.h"
+#include "GrColorSpaceXform.h"
#include "GrContext.h"
#include "GrContextPriv.h"
#include "GrGpu.h"
@@ -19,6 +20,7 @@
#include "GrStyle.h"
#include "GrSurfaceProxyPriv.h"
#include "GrTextureAdjuster.h"
+#include "GrTextureProxy.h"
#include "GrTracing.h"
#include "SkCanvasPriv.h"
#include "SkDraw.h"
@@ -29,6 +31,7 @@
#include "SkImage_Base.h"
#include "SkLatticeIter.h"
#include "SkMakeUnique.h"
+#include "SkMaskFilterBase.h"
#include "SkPathEffect.h"
#include "SkPicture.h"
#include "SkPictureData.h"
@@ -46,7 +49,9 @@
#include "SkVertState.h"
#include "SkVertices.h"
#include "SkWritePixelsRec.h"
+#include "SkYUVAIndex.h"
#include "effects/GrBicubicEffect.h"
+#include "effects/GrSimpleTextureEffect.h"
#include "effects/GrTextureDomain.h"
#include "text/GrTextTarget.h"
@@ -399,18 +404,8 @@
void SkGpuDevice::drawEdgeAARect(const SkRect& r, SkCanvas::QuadAAFlags aa, SkColor color,
SkBlendMode mode) {
- this->tmp_drawEdgeAAQuad(r, nullptr, 0, aa, color, mode);
-}
-
-void SkGpuDevice::tmp_drawEdgeAAQuad(const SkRect& rect, const SkPoint clip[], int clipCount,
- SkCanvas::QuadAAFlags aaFlags, SkColor color,
- SkBlendMode mode) {
ASSERT_SINGLE_OWNER
- GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "tmp_drawEdgeAAQuad", fContext.get());
-
- // Only no clip or a quad clip is currently supported
- SkASSERT(clipCount == 0 || clipCount == 4);
- SkASSERT(clipCount == 0 || clip);
+ GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawEdgeAARect", fContext.get());
SkPMColor4f dstColor = SkColor4fPrepForDst(SkColor4f::FromColor(color),
fRenderTargetContext->colorSpaceInfo(),
@@ -424,16 +419,8 @@
}
// This is exclusively meant for tiling operations, so keep AA enabled to handle MSAA seaming
- GrQuadAAFlags grAA = SkToGrQuadAAFlags(aaFlags);
- if (clipCount > 0) {
- // Use fillQuadWithEdgeAA
- fRenderTargetContext->fillQuadWithEdgeAA(this->clip(), std::move(grPaint), GrAA::kYes, grAA,
- this->ctm(), clip, nullptr);
- } else {
- // Use fillRectWithEdgeAA to preserve mathematical properties of dst being rectangular
- fRenderTargetContext->fillRectWithEdgeAA(this->clip(), std::move(grPaint), GrAA::kYes, grAA,
- this->ctm(), rect);
- }
+ fRenderTargetContext->fillRectWithEdgeAA(this->clip(), std::move(grPaint),
+ GrAA::kYes, SkToGrQuadAAFlags(aa), this->ctm(), r);
}
///////////////////////////////////////////////////////////////////////////////
@@ -1293,9 +1280,42 @@
void SkGpuDevice::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
const SkPaint& paint, SkCanvas::SrcRectConstraint constraint) {
ASSERT_SINGLE_OWNER
- GrQuadAAFlags aaFlags = paint.isAntiAlias() ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
- this->drawImageQuad(
- image, src, &dst, nullptr, GrAA(paint.isAntiAlias()), aaFlags, paint, constraint);
+ if (!src || src->contains(image->bounds())) {
+ constraint = SkCanvas::kFast_SrcRectConstraint;
+ }
+ if (as_IB(image)->isYUVA()) {
+ GrYUVAImageTextureMaker maker(fContext.get(), image);
+ this->drawTextureProducer(&maker, src, &dst, constraint, this->ctm(), paint, false);
+ return;
+ }
+ uint32_t pinnedUniqueID;
+ if (sk_sp<GrTextureProxy> proxy = as_IB(image)->refPinnedTextureProxy(&pinnedUniqueID)) {
+ this->drawPinnedTextureProxy(std::move(proxy), pinnedUniqueID, as_IB(image)->colorSpace(),
+ image->alphaType(), src, &dst, constraint, this->ctm(), paint);
+ return;
+ }
+ SkBitmap bm;
+ SkMatrix srcToDstRect;
+ srcToDstRect.setRectToRect((src ? *src : SkRect::MakeIWH(image->width(), image->height())),
+ dst, SkMatrix::kFill_ScaleToFit);
+ if (this->shouldTileImage(image, src, constraint, paint.getFilterQuality(), this->ctm(),
+ srcToDstRect)) {
+ // only support tiling as bitmap at the moment, so force raster-version
+ if (!as_IB(image)->getROPixels(&bm)) {
+ return;
+ }
+ this->drawBitmapRect(bm, src, dst, paint, constraint);
+ return;
+ }
+ if (image->isLazyGenerated()) {
+ GrImageTextureMaker maker(fContext.get(), image, SkImage::kAllow_CachingHint);
+ this->drawTextureProducer(&maker, src, &dst, constraint, this->ctm(), paint, true);
+ return;
+ }
+ if (as_IB(image)->getROPixels(&bm)) {
+ GrBitmapTextureMaker maker(fContext.get(), bm);
+ this->drawTextureProducer(&maker, src, &dst, constraint, this->ctm(), paint, true);
+ }
}
// When drawing nine-patches or n-patches, cap the filter quality at kBilerp.
@@ -1400,12 +1420,70 @@
void SkGpuDevice::drawImageSet(const SkCanvas::ImageSetEntry set[], int count,
SkFilterQuality filterQuality, SkBlendMode mode) {
- SkPaint paint;
- paint.setBlendMode(mode);
- paint.setFilterQuality(filterQuality);
- paint.setAntiAlias(true);
- this->tmp_drawImageSetV2(set, nullptr, count, nullptr, paint,
- SkCanvas::kFast_SrcRectConstraint);
+ SkASSERT(count > 0);
+
+ GrSamplerState sampler;
+ sampler.setFilterMode(kNone_SkFilterQuality == filterQuality ? GrSamplerState::Filter::kNearest
+ : GrSamplerState::Filter::kBilerp);
+ SkAutoTArray<GrRenderTargetContext::TextureSetEntry> textures(count);
+ // We accumulate compatible proxies until we find an an incompatible one or reach the end and
+ // issue the accumulated 'n' draws starting at 'base'.
+ int base = 0, n = 0;
+ auto draw = [&] {
+ if (n > 0) {
+ auto textureXform = GrColorSpaceXform::Make(
+ set[base].fImage->colorSpace(), set[base].fImage->alphaType(),
+ fRenderTargetContext->colorSpaceInfo().colorSpace(), kPremul_SkAlphaType);
+ // Currently, drawImageSet is only used for tiled images so keep AA to handle MSAA
+ // seams (this will not remain true in the future)
+ fRenderTargetContext->drawTextureSet(this->clip(), textures.get() + base, n,
+ sampler.filter(), mode, GrAA::kYes, this->ctm(),
+ std::move(textureXform));
+ }
+ };
+ for (int i = 0; i < count; ++i) {
+ // The default SkBaseDevice implementation is based on drawImageRect which does not allow
+ // non-sorted src rects. TODO: Decide this is OK or make sure we handle it.
+ if (!set[i].fSrcRect.isSorted()) {
+ draw();
+ base = i + 1;
+ n = 0;
+ continue;
+ }
+ uint32_t uniqueID;
+ textures[i].fProxy = as_IB(set[i].fImage.get())->refPinnedTextureProxy(&uniqueID);
+ if (!textures[i].fProxy) {
+ textures[i].fProxy =
+ as_IB(set[i].fImage.get())
+ ->asTextureProxyRef(fContext.get(), GrSamplerState::ClampBilerp(),
+ nullptr);
+ // If we failed to make a proxy then flush the accumulated set and reset for the next
+ // image.
+ if (!textures[i].fProxy) {
+ draw();
+ base = i + 1;
+ n = 0;
+ continue;
+ }
+ }
+ textures[i].fSrcRect = set[i].fSrcRect;
+ textures[i].fDstRect = set[i].fDstRect;
+ textures[i].fDstClip = nullptr; // TODO(michaelludwig) Not exposed in SkGpuDevice API yet
+ textures[i].fAlpha = set[i].fAlpha;
+ textures[i].fAAFlags = SkToGrQuadAAFlags(set[i].fAAFlags);
+ if (n > 0 &&
+ (!GrTextureProxy::ProxiesAreCompatibleAsDynamicState(textures[i].fProxy.get(),
+ textures[base].fProxy.get()) ||
+ set[i].fImage->alphaType() != set[base].fImage->alphaType() ||
+ !SkColorSpace::Equals(set[i].fImage->colorSpace(), set[base].fImage->colorSpace()))) {
+ draw();
+ base = i;
+ n = 1;
+ } else {
+ ++n;
+ }
+ }
+ draw();
}
static bool init_vertices_paint(GrContext* context, const GrColorSpaceInfo& colorSpaceInfo,
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index 434c766..16c0010 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -124,17 +124,6 @@
bool onAccessPixels(SkPixmap*) override;
- // Temporary interface until it gets lifted up to SkDevice and exposed in SkCanvas
-
- /*
- * dstClipCounts[] is a parallel array to the image entries, acting like the intended
- * dstClipCount field in ImageSetEntry.
- */
- void tmp_drawImageSetV2(const SkCanvas::ImageSetEntry[], int dstClipCounts[], int count,
- const SkPoint dstClips[], const SkPaint& paint,
- SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint);
- void tmp_drawEdgeAAQuad(const SkRect& rect, const SkPoint clip[], int clipCount,
- SkCanvas::QuadAAFlags aaFlags, SkColor color, SkBlendMode mode);
protected:
bool onReadPixels(const SkPixmap&, int, int) override;
bool onWritePixels(const SkPixmap&, int, int) override;
@@ -217,13 +206,16 @@
bool bicubic,
bool needsTextureDomain);
- // If not null, dstClip must be contained inside dst and will also respect the edge AA flags
- void drawImageQuad(const SkImage*, const SkRect* src, const SkRect* dst,
- const SkPoint dstClip[4], GrAA aa, GrQuadAAFlags edgeAA,
- const SkPaint&, SkCanvas::SrcRectConstraint);
+ void drawPinnedTextureProxy(sk_sp<GrTextureProxy>,
+ uint32_t pinnedUniqueID,
+ SkColorSpace*,
+ SkAlphaType alphaType,
+ const SkRect* srcRect,
+ const SkRect* dstRect,
+ SkCanvas::SrcRectConstraint,
+ const SkMatrix& viewMatrix,
+ const SkPaint&);
- // TODO(michaelludwig): This can be removed once drawBitmapRect is removed from SkDevice
- // so that drawImageQuad is the sole entry point into the draw-single-image op
void drawTextureProducer(GrTextureProducer*,
const SkRect* srcRect,
const SkRect* dstRect,
@@ -232,6 +224,14 @@
const SkPaint&,
bool attemptDrawTexture);
+ void drawTextureProducerImpl(GrTextureProducer*,
+ const SkRect& clippedSrcRect,
+ const SkRect& clippedDstRect,
+ SkCanvas::SrcRectConstraint,
+ const SkMatrix& viewMatrix,
+ const SkMatrix& srcToDstMatrix,
+ const SkPaint&);
+
void drawProducerLattice(GrTextureProducer*, std::unique_ptr<SkLatticeIter>, const SkRect& dst,
const SkPaint&);
diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp
index da2c887..21815f7 100644
--- a/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -6,12 +6,9 @@
*/
#include "SkGpuDevice.h"
-
-#include "GrBitmapTextureMaker.h"
#include "GrBlurUtils.h"
#include "GrCaps.h"
#include "GrColorSpaceXform.h"
-#include "GrImageTextureMaker.h"
#include "GrRenderTargetContext.h"
#include "GrShape.h"
#include "GrStyle.h"
@@ -19,15 +16,11 @@
#include "GrTextureMaker.h"
#include "SkDraw.h"
#include "SkGr.h"
-#include "SkImage_Base.h"
#include "SkMaskFilterBase.h"
-#include "SkYUVAIndex.h"
#include "effects/GrBicubicEffect.h"
#include "effects/GrSimpleTextureEffect.h"
#include "effects/GrTextureDomain.h"
-namespace {
-
static inline bool use_shader(bool textureIsAlphaOnly, const SkPaint& paint) {
return textureIsAlphaOnly && paint.getShader();
}
@@ -94,73 +87,6 @@
return false;
}
-enum class ImageDrawMode {
- // Src and dst have been restricted to the image content. May need to clamp, no need to decal.
- kOptimized,
- // Src and dst are their original sizes, requires use of a decal instead of plain clamping.
- // This is used when a dst clip is provided and extends outside of the optimized dst rect.
- kDecal,
- // Src or dst are empty, or do not intersect the image content so don't draw anything.
- kSkip
-};
-
-/**
- * Optimize the src rect sampling area within an image (sized 'width' x 'height') such that
- * 'outSrcRect' will be completely contained in the image's bounds. The corresponding rect
- * to draw will be output to 'outDstRect'. The mapping between src and dst will be cached in
- * 'srcToDst'. Outputs are not always updated when kSkip is returned.
- *
- * If 'origSrcRect' is null, implicitly use the image bounds. If 'origDstRect' is null, use the
- * original src rect. 'dstClip' should be null when there is no additional clipping.
- */
-static ImageDrawMode optimize_sample_area(const SkISize& image, const SkRect* origSrcRect,
- const SkRect* origDstRect, const SkPoint dstClip[4],
- SkRect* outSrcRect, SkRect* outDstRect,
- SkMatrix* srcToDst) {
- SkRect srcBounds = SkRect::MakeIWH(image.fWidth, image.fHeight);
-
- SkRect src = origSrcRect ? *origSrcRect : srcBounds;
- SkRect dst = origDstRect ? *origDstRect : src;
-
- if (src.isEmpty() || dst.isEmpty()) {
- return ImageDrawMode::kSkip;
- }
-
- if (outDstRect) {
- srcToDst->setRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
- } else {
- srcToDst->setIdentity();
- }
-
- if (origSrcRect && !srcBounds.contains(src)) {
- if (!src.intersect(srcBounds)) {
- return ImageDrawMode::kSkip;
- }
- srcToDst->mapRect(&dst, src);
-
- // Both src and dst have gotten smaller. If dstClip is provided, confirm it is still
- // contained in dst, otherwise cannot optimize the sample area and must use a decal instead
- if (dstClip) {
- for (int i = 0; i < 4; ++i) {
- if (!dst.contains(dstClip[i].fX, dstClip[i].fY)) {
- // Must resort to using a decal mode restricted to the clipped 'src', and
- // use the original dst rect (filling in src bounds as needed)
- *outSrcRect = src;
- *outDstRect = (origDstRect ? *origDstRect
- : (origSrcRect ? *origSrcRect : srcBounds));
- return ImageDrawMode::kDecal;
- }
- }
- }
- }
-
- // The original src and dst were fully contained in the image, or there was no dst clip to
- // worry about, or the clip was still contained in the restricted dst rect.
- *outSrcRect = src;
- *outDstRect = dst;
- return ImageDrawMode::kOptimized;
-}
-
/**
* Checks whether the paint is compatible with using GrRenderTargetContext::drawTexture. It is more
* efficient than the GrTextureProducer general case.
@@ -170,12 +96,20 @@
!paint.getImageFilter() && paint.getFilterQuality() < kMedium_SkFilterQuality);
}
-// Assumes srcRect and dstRect have already been optimized to fit the proxy
-static void draw_texture(GrRenderTargetContext* rtc, const GrClip& clip, const SkMatrix& ctm,
- const SkPaint& paint, const SkRect& srcRect, const SkRect& dstRect,
- const SkPoint dstClip[4], GrAA aa, GrQuadAAFlags aaFlags,
- SkCanvas::SrcRectConstraint constraint, sk_sp<GrTextureProxy> proxy,
- SkAlphaType alphaType, SkColorSpace* colorSpace) {
+static void draw_texture(const SkPaint& paint, const SkMatrix& ctm, const SkRect* src,
+ const SkRect* dst, GrAA aa, SkCanvas::SrcRectConstraint constraint,
+ sk_sp<GrTextureProxy> proxy, SkAlphaType alphaType,
+ SkColorSpace* colorSpace, const GrClip& clip, GrRenderTargetContext* rtc) {
+ SkASSERT(!(SkToBool(src) && !SkToBool(dst)));
+ SkRect srcRect = src ? *src : SkRect::MakeWH(proxy->width(), proxy->height());
+ SkRect dstRect = dst ? *dst : srcRect;
+ if (src && !SkRect::MakeIWH(proxy->width(), proxy->height()).contains(srcRect)) {
+ // Shrink the src rect to be within bounds and proportionately shrink the dst rect.
+ SkMatrix srcToDst;
+ srcToDst.setRectToRect(srcRect, dstRect, SkMatrix::kFill_ScaleToFit);
+ SkAssertResult(srcRect.intersect(SkRect::MakeIWH(proxy->width(), proxy->height())));
+ srcToDst.mapRect(&dstRect, srcRect);
+ }
const GrColorSpaceInfo& dstInfo(rtc->colorSpaceInfo());
auto textureXform =
GrColorSpaceXform::Make(colorSpace , alphaType,
@@ -214,42 +148,107 @@
float paintAlpha = paint.getColor4f().fA;
color = { paintAlpha, paintAlpha, paintAlpha, paintAlpha };
}
-
- if (dstClip) {
- // Get source coords corresponding to dstClip
- SkPoint srcQuad[4];
- GrMapRectPoints(dstRect, srcRect, dstClip, srcQuad, 4);
-
- rtc->drawTextureQuad(clip, std::move(proxy), filter, paint.getBlendMode(), color,
- srcQuad, dstClip, aa, aaFlags,
- constraint == SkCanvas::kStrict_SrcRectConstraint ? &srcRect : nullptr,
- ctm, std::move(textureXform));
- } else {
- rtc->drawTexture(clip, std::move(proxy), filter, paint.getBlendMode(), color, srcRect,
- dstRect, aa, aaFlags, constraint, ctm, std::move(textureXform));
- }
+ GrQuadAAFlags aaFlags = aa == GrAA::kYes ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
+ rtc->drawTexture(clip, std::move(proxy), filter, paint.getBlendMode(), color, srcRect, dstRect,
+ aa, aaFlags, constraint, ctm, std::move(textureXform));
}
-// Assumes srcRect and dstRect have already been optimized to fit the proxy.
-static void draw_texture_producer(GrContext* context, GrRenderTargetContext* rtc,
- const GrClip& clip, const SkMatrix& ctm,
- const SkPaint& paint, GrTextureProducer* producer,
- const SkRect& src, const SkRect& dst, const SkPoint dstClip[4],
- const SkMatrix& srcToDst, GrAA aa, GrQuadAAFlags aaFlags,
- SkCanvas::SrcRectConstraint constraint, bool attemptDrawTexture) {
+//////////////////////////////////////////////////////////////////////////////
+
+void SkGpuDevice::drawPinnedTextureProxy(sk_sp<GrTextureProxy> proxy, uint32_t pinnedUniqueID,
+ SkColorSpace* colorSpace, SkAlphaType alphaType,
+ const SkRect* srcRect, const SkRect* dstRect,
+ SkCanvas::SrcRectConstraint constraint,
+ const SkMatrix& viewMatrix, const SkPaint& paint) {
+ GrAA aa = GrAA(paint.isAntiAlias());
+ if (can_use_draw_texture(paint)) {
+ draw_texture(paint, viewMatrix, srcRect, dstRect, aa, constraint, std::move(proxy),
+ alphaType, colorSpace, this->clip(), fRenderTargetContext.get());
+ return;
+ }
+ GrTextureAdjuster adjuster(this->context(), std::move(proxy), alphaType, pinnedUniqueID,
+ colorSpace);
+ this->drawTextureProducer(&adjuster, srcRect, dstRect, constraint, viewMatrix, paint, false);
+}
+
+void SkGpuDevice::drawTextureProducer(GrTextureProducer* producer,
+ const SkRect* srcRect,
+ const SkRect* dstRect,
+ SkCanvas::SrcRectConstraint constraint,
+ const SkMatrix& viewMatrix,
+ const SkPaint& paint,
+ bool attemptDrawTexture) {
if (attemptDrawTexture && can_use_draw_texture(paint)) {
+ GrAA aa = GrAA(paint.isAntiAlias());
// We've done enough checks above to allow us to pass ClampNearest() and not check for
// scaling adjustments.
auto proxy = producer->refTextureProxyForParams(GrSamplerState::ClampNearest(), nullptr);
if (!proxy) {
return;
}
-
- draw_texture(rtc, clip, ctm, paint, src, dst, dstClip, aa, aaFlags, constraint,
- std::move(proxy), producer->alphaType(), producer->colorSpace());
+ draw_texture(paint, viewMatrix, srcRect, dstRect, aa, constraint, std::move(proxy),
+ producer->alphaType(), producer->colorSpace(), this->clip(),
+ fRenderTargetContext.get());
return;
}
+ // This is the funnel for all non-tiled bitmap/image draw calls. Log a histogram entry.
+ SK_HISTOGRAM_BOOLEAN("DrawTiled", false);
+
+ // Figure out the actual dst and src rect by clipping the src rect to the bounds of the
+ // adjuster. If the src rect is clipped then the dst rect must be recomputed. Also determine
+ // the matrix that maps the src rect to the dst rect.
+ SkRect clippedSrcRect;
+ SkRect clippedDstRect;
+ const SkRect srcBounds = SkRect::MakeIWH(producer->width(), producer->height());
+ SkMatrix srcToDstMatrix;
+ if (srcRect) {
+ if (!dstRect) {
+ dstRect = &srcBounds;
+ }
+ if (!srcBounds.contains(*srcRect)) {
+ clippedSrcRect = *srcRect;
+ if (!clippedSrcRect.intersect(srcBounds)) {
+ return;
+ }
+ if (!srcToDstMatrix.setRectToRect(*srcRect, *dstRect, SkMatrix::kFill_ScaleToFit)) {
+ return;
+ }
+ srcToDstMatrix.mapRect(&clippedDstRect, clippedSrcRect);
+ } else {
+ clippedSrcRect = *srcRect;
+ clippedDstRect = *dstRect;
+ if (!srcToDstMatrix.setRectToRect(*srcRect, *dstRect, SkMatrix::kFill_ScaleToFit)) {
+ return;
+ }
+ }
+ } else {
+ clippedSrcRect = srcBounds;
+ if (dstRect) {
+ clippedDstRect = *dstRect;
+ if (!srcToDstMatrix.setRectToRect(srcBounds, *dstRect, SkMatrix::kFill_ScaleToFit)) {
+ return;
+ }
+ } else {
+ clippedDstRect = srcBounds;
+ srcToDstMatrix.reset();
+ }
+ }
+
+ // Now that we have both the view and srcToDst matrices, log our scale factor.
+ LogDrawScaleFactor(viewMatrix, srcToDstMatrix, paint.getFilterQuality());
+
+ this->drawTextureProducerImpl(producer, clippedSrcRect, clippedDstRect, constraint, viewMatrix,
+ srcToDstMatrix, paint);
+}
+
+void SkGpuDevice::drawTextureProducerImpl(GrTextureProducer* producer,
+ const SkRect& clippedSrcRect,
+ const SkRect& clippedDstRect,
+ SkCanvas::SrcRectConstraint constraint,
+ const SkMatrix& viewMatrix,
+ const SkMatrix& srcToDstMatrix,
+ const SkPaint& paint) {
const SkMaskFilter* mf = paint.getMaskFilter();
// The shader expects proper local coords, so we can't replace local coords with texture coords
@@ -258,16 +257,17 @@
bool canUseTextureCoordsAsLocalCoords = !use_shader(producer->isAlphaOnly(), paint) && !mf;
// Specifying the texture coords as local coordinates is an attempt to enable more GrDrawOp
- // combining by not baking anything about the srcRect, dstRect, or ctm, into the texture
+ // combining by not baking anything about the srcRect, dstRect, or viewMatrix, into the texture
// FP. In the future this should be an opaque optimization enabled by the combination of
// GrDrawOp/GP and FP.
if (mf && as_MFB(mf)->hasFragmentProcessor()) {
mf = nullptr;
}
+
bool doBicubic;
GrSamplerState::Filter fm = GrSkFilterQualityToGrFilterMode(
- paint.getFilterQuality(), ctm, srcToDst,
- context->priv().options().fSharpenMipmappedTextures, &doBicubic);
+ paint.getFilterQuality(), viewMatrix, srcToDstMatrix,
+ fContext->priv().options().fSharpenMipmappedTextures, &doBicubic);
const GrSamplerState::Filter* filterMode = doBicubic ? nullptr : &fm;
GrTextureProducer::FilterConstraint constraintMode;
@@ -280,302 +280,58 @@
// If we have to outset for AA then we will generate texture coords outside the src rect. The
// same happens for any mask filter that extends the bounds rendered in the dst.
// This is conservative as a mask filter does not have to expand the bounds rendered.
- bool coordsAllInsideSrcRect = aaFlags == GrQuadAAFlags::kNone && !mf;
+ bool coordsAllInsideSrcRect = !paint.isAntiAlias() && !mf;
// Check for optimization to drop the src rect constraint when on bilerp.
if (filterMode && GrSamplerState::Filter::kBilerp == *filterMode &&
GrTextureAdjuster::kYes_FilterConstraint == constraintMode && coordsAllInsideSrcRect) {
SkMatrix combinedMatrix;
- combinedMatrix.setConcat(ctm, srcToDst);
- if (can_ignore_bilerp_constraint(*producer, src, combinedMatrix, rtc->fsaaType())) {
+ combinedMatrix.setConcat(viewMatrix, srcToDstMatrix);
+ if (can_ignore_bilerp_constraint(*producer, clippedSrcRect, combinedMatrix,
+ fRenderTargetContext->fsaaType())) {
constraintMode = GrTextureAdjuster::kNo_FilterConstraint;
}
}
- SkMatrix textureMatrix;
+ const SkMatrix* textureMatrix;
+ SkMatrix tempMatrix;
if (canUseTextureCoordsAsLocalCoords) {
- textureMatrix = SkMatrix::I();
+ textureMatrix = &SkMatrix::I();
} else {
- if (!srcToDst.invert(&textureMatrix)) {
+ if (!srcToDstMatrix.invert(&tempMatrix)) {
return;
}
+ textureMatrix = &tempMatrix;
}
- auto fp = producer->createFragmentProcessor(textureMatrix, src, constraintMode,
+ auto fp = producer->createFragmentProcessor(*textureMatrix, clippedSrcRect, constraintMode,
coordsAllInsideSrcRect, filterMode);
fp = GrColorSpaceXformEffect::Make(std::move(fp), producer->colorSpace(), producer->alphaType(),
- rtc->colorSpaceInfo().colorSpace());
+ fRenderTargetContext->colorSpaceInfo().colorSpace());
if (!fp) {
return;
}
GrPaint grPaint;
- if (!SkPaintToGrPaintWithTexture(context, rtc->colorSpaceInfo(), paint, ctm,
- std::move(fp), producer->isAlphaOnly(), &grPaint)) {
+ if (!SkPaintToGrPaintWithTexture(fContext.get(), fRenderTargetContext->colorSpaceInfo(), paint,
+ viewMatrix, std::move(fp), producer->isAlphaOnly(),
+ &grPaint)) {
+ return;
+ }
+ GrAA aa = GrAA(paint.isAntiAlias());
+ if (canUseTextureCoordsAsLocalCoords) {
+ fRenderTargetContext->fillRectToRect(this->clip(), std::move(grPaint), aa, viewMatrix,
+ clippedDstRect, clippedSrcRect);
return;
}
if (!mf) {
- // Can draw the image directly (any mask filter on the paint was converted to an FP already)
- if (dstClip) {
- SkPoint srcClipPoints[4];
- SkPoint* srcClip = nullptr;
- if (canUseTextureCoordsAsLocalCoords) {
- // Calculate texture coordinates that match the dst clip
- GrMapRectPoints(dst, src, dstClip, srcClipPoints, 4);
- srcClip = srcClipPoints;
- }
- rtc->fillQuadWithEdgeAA(clip, std::move(grPaint), aa, aaFlags, ctm, dstClip, srcClip);
- } else {
- // Provide explicit texture coords when possible, otherwise rely on texture matrix
- rtc->fillRectWithEdgeAA(clip, std::move(grPaint), aa, aaFlags, ctm, dst,
- canUseTextureCoordsAsLocalCoords ? &src : nullptr);
- }
- } else {
- // Must draw the mask filter as a GrShape. For now, this loses the per-edge AA information
- // since it always draws with AA, but that is should not be noticeable since the mask filter
- // is probably a blur.
- GrShape shape;
- if (dstClip) {
- // Represent it as an SkPath formed from the dstClip
- SkPath path;
- path.addPoly(dstClip, 4, true);
- shape = GrShape(path);
- } else {
- shape = GrShape(dst);
- }
-
- GrBlurUtils::drawShapeWithMaskFilter(
- context, rtc, clip, shape, std::move(grPaint), ctm, mf);
- }
-}
-
-} // anonymous namespace
-
-//////////////////////////////////////////////////////////////////////////////
-
-void SkGpuDevice::drawImageQuad(const SkImage* image, const SkRect* srcRect, const SkRect* dstRect,
- const SkPoint dstClip[4], GrAA aa, GrQuadAAFlags aaFlags,
- const SkPaint& paint, SkCanvas::SrcRectConstraint constraint) {
- SkRect src;
- SkRect dst;
- SkMatrix srcToDst;
- ImageDrawMode mode = optimize_sample_area(SkISize::Make(image->width(), image->height()),
- srcRect, dstRect, dstClip, &src, &dst, &srcToDst);
- if (mode == ImageDrawMode::kSkip) {
+ fRenderTargetContext->drawRect(this->clip(), std::move(grPaint), aa, viewMatrix,
+ clippedDstRect);
return;
}
- if (src.contains(image->bounds())) {
- constraint = SkCanvas::kFast_SrcRectConstraint;
- }
- // Depending on the nature of image, it can flow through more or less optimal pipelines
- bool useDecal = mode == ImageDrawMode::kDecal;
- bool attemptDrawTexture = !useDecal; // rtc->drawTexture() only clamps
+ GrShape shape(clippedDstRect, GrStyle::SimpleFill());
- // YUVA images can be stored in multiple images with different plane resolutions, so this
- // uses an effect to combine them dynamically on the GPU. This is done before requesting a
- // pinned texture proxy because YUV images force-flatten to RGBA in that scenario.
- if (as_IB(image)->isYUVA()) {
- SK_HISTOGRAM_BOOLEAN("DrawTiled", false);
- LogDrawScaleFactor(this->ctm(), srcToDst, paint.getFilterQuality());
-
- GrYUVAImageTextureMaker maker(fContext.get(), image, useDecal);
- draw_texture_producer(fContext.get(), fRenderTargetContext.get(), this->clip(), this->ctm(),
- paint, &maker, src, dst, dstClip, srcToDst, aa, aaFlags, constraint,
- /* attempt draw texture */ false);
- return;
- }
-
- // Pinned texture proxies can be rendered directly as textures, or with relatively simple
- // adjustments applied to the image content (scaling, mipmaps, color space, etc.)
- uint32_t pinnedUniqueID;
- if (sk_sp<GrTextureProxy> proxy = as_IB(image)->refPinnedTextureProxy(&pinnedUniqueID)) {
- SK_HISTOGRAM_BOOLEAN("DrawTiled", false);
- LogDrawScaleFactor(this->ctm(), srcToDst, paint.getFilterQuality());
-
- SkAlphaType alphaType = image->alphaType();
- SkColorSpace* colorSpace = as_IB(image)->colorSpace();
-
- if (attemptDrawTexture && can_use_draw_texture(paint)) {
- draw_texture(fRenderTargetContext.get(), this->clip(), this->ctm(), paint, src, dst,
- dstClip, aa, aaFlags, constraint, std::move(proxy), alphaType, colorSpace);
- return;
- }
-
- GrTextureAdjuster adjuster(fContext.get(), std::move(proxy), alphaType, pinnedUniqueID,
- colorSpace, useDecal);
- draw_texture_producer(fContext.get(), fRenderTargetContext.get(), this->clip(), this->ctm(),
- paint, &adjuster, src, dst, dstClip, srcToDst, aa, aaFlags,
- constraint, /* attempt draw_texture */ false);
- return;
- }
-
- // Next up, try tiling the image
- // TODO (michaelludwig): Implement this with per-edge AA flags to handle seaming properly
- // instead of going through drawBitmapRect (which will be removed from SkDevice in the future)
- SkBitmap bm;
- if (this->shouldTileImage(image, &src, constraint, paint.getFilterQuality(), this->ctm(),
- srcToDst)) {
- // only support tiling as bitmap at the moment, so force raster-version
- if (!as_IB(image)->getROPixels(&bm)) {
- return;
- }
- this->drawBitmapRect(bm, &src, dst, paint, constraint);
- return;
- }
-
- // This is the funnel for all non-tiled bitmap/image draw calls. Log a histogram entry.
- SK_HISTOGRAM_BOOLEAN("DrawTiled", false);
- LogDrawScaleFactor(this->ctm(), srcToDst, paint.getFilterQuality());
-
- // Lazily generated images must get drawn as a texture producer that handles the final
- // texture creation.
- if (image->isLazyGenerated()) {
- GrImageTextureMaker maker(fContext.get(), image, SkImage::kAllow_CachingHint, useDecal);
- draw_texture_producer(fContext.get(), fRenderTargetContext.get(), this->clip(), this->ctm(),
- paint, &maker, src, dst, dstClip, srcToDst, aa, aaFlags, constraint,
- attemptDrawTexture);
- return;
- }
- if (as_IB(image)->getROPixels(&bm)) {
- GrBitmapTextureMaker maker(fContext.get(), bm, useDecal);
- draw_texture_producer(fContext.get(), fRenderTargetContext.get(), this->clip(), this->ctm(),
- paint, &maker, src, dst, dstClip, srcToDst, aa, aaFlags, constraint,
- attemptDrawTexture);
- }
-
- // Otherwise don't know how to draw it
-}
-
-// For ease-of-use, the temporary API treats null dstClipCounts as if it were the proper sized
-// array, filled with all 0s (so dstClips can be null too)
-void SkGpuDevice::tmp_drawImageSetV2(const SkCanvas::ImageSetEntry set[], int dstClipCounts[],
- int count, const SkPoint dstClips[], const SkPaint& paint,
- SkCanvas::SrcRectConstraint constraint) {
- SkASSERT(count > 0);
-
- if (!can_use_draw_texture(paint)) {
- // Send every entry through drawImageQuad() to handle the more complicated paint
- int dstClipIndex = 0;
- for (int i = 0; i < count; ++i) {
- // Only no clip or quad clip are supported
- SkASSERT(!dstClipCounts || dstClipCounts[i] == 0 || dstClipCounts[i] == 4);
- // Always send GrAA::kYes to preserve seaming across tiling in MSAA
- this->drawImageQuad(set[i].fImage.get(), &set[i].fSrcRect, &set[i].fDstRect,
- (dstClipCounts && dstClipCounts[i] > 0) ? dstClips + dstClipIndex : nullptr,
- GrAA::kYes, SkToGrQuadAAFlags(set[i].fAAFlags), paint, constraint);
- if (dstClipCounts) {
- dstClipIndex += dstClipCounts[i];
- }
- }
- return;
- }
-
- GrSamplerState::Filter filter = kNone_SkFilterQuality == paint.getFilterQuality() ?
- GrSamplerState::Filter::kNearest : GrSamplerState::Filter::kBilerp;
- SkBlendMode mode = paint.getBlendMode();
-
- SkAutoTArray<GrRenderTargetContext::TextureSetEntry> textures(count);
- // We accumulate compatible proxies until we find an an incompatible one or reach the end and
- // issue the accumulated 'n' draws starting at 'base'.
- int base = 0, n = 0;
- auto draw = [&] {
- if (n > 0) {
- auto textureXform = GrColorSpaceXform::Make(
- set[base].fImage->colorSpace(), set[base].fImage->alphaType(),
- fRenderTargetContext->colorSpaceInfo().colorSpace(), kPremul_SkAlphaType);
- fRenderTargetContext->drawTextureSet(this->clip(), textures.get() + base, n,
- filter, mode, GrAA::kYes, this->ctm(),
- std::move(textureXform));
- }
- };
- int dstClipIndex = 0;
- for (int i = 0; i < count; ++i) {
- // Manage the dst clip pointer tracking before any continues are used so we don't lose
- // our place in the dstClips array.
- int clipCount = (dstClipCounts ? dstClipCounts[i] : 0);
- SkASSERT(clipCount == 0 || (dstClipCounts[i] == 4 && dstClips));
- const SkPoint* clip = clipCount > 0 ? dstClips + dstClipIndex : nullptr;
- if (dstClipCounts) {
- dstClipIndex += dstClipCounts[i];
- }
- // The default SkBaseDevice implementation is based on drawImageRect which does not allow
- // non-sorted src rects. TODO: Decide this is OK or make sure we handle it.
- if (!set[i].fSrcRect.isSorted()) {
- draw();
- base = i + 1;
- n = 0;
- continue;
- }
-
- uint32_t uniqueID;
- textures[i].fProxy = as_IB(set[i].fImage.get())->refPinnedTextureProxy(&uniqueID);
- if (!textures[i].fProxy) {
- // FIXME(michaelludwig) - If asTextureProxyRef fails, does going through drawImageQuad
- // make sense? Does that catch the lazy-image cases then?
- // FIXME(michaelludwig) - Both refPinnedTextureProxy and asTextureProxyRef for YUVA
- // images force flatten the planes. It would be nice to detect a YUVA image entry and
- // send it to drawImageQuad (which uses a special effect for YUV)
- textures[i].fProxy =
- as_IB(set[i].fImage.get())
- ->asTextureProxyRef(fContext.get(), GrSamplerState::ClampBilerp(),
- nullptr);
- // If we failed to make a proxy then flush the accumulated set and reset for the next
- // image.
- if (!textures[i].fProxy) {
- draw();
- base = i + 1;
- n = 0;
- continue;
- }
- }
- textures[i].fSrcRect = set[i].fSrcRect;
- textures[i].fDstRect = set[i].fDstRect;
- textures[i].fDstClipQuad = clip;
- textures[i].fAlpha = set[i].fAlpha * paint.getAlphaf();
- textures[i].fAAFlags = SkToGrQuadAAFlags(set[i].fAAFlags);
-
- if (n > 0 &&
- (!GrTextureProxy::ProxiesAreCompatibleAsDynamicState(textures[i].fProxy.get(),
- textures[base].fProxy.get()) ||
- set[i].fImage->alphaType() != set[base].fImage->alphaType() ||
- !SkColorSpace::Equals(set[i].fImage->colorSpace(), set[base].fImage->colorSpace()))) {
- draw();
- base = i;
- n = 1;
- } else {
- ++n;
- }
- }
- draw();
-}
-
-// TODO (michaelludwig) - to be removed when drawBitmapRect doesn't need it anymore
-void SkGpuDevice::drawTextureProducer(GrTextureProducer* producer,
- const SkRect* srcRect,
- const SkRect* dstRect,
- SkCanvas::SrcRectConstraint constraint,
- const SkMatrix& viewMatrix,
- const SkPaint& paint,
- bool attemptDrawTexture) {
- // The texture refactor split the old logic of drawTextureProducer into the beginning of
- // drawImageQuad() and into the static draw_texture_producer. Replicate necessary logic that
- // drawImageQuad() handles.
- SkRect src;
- SkRect dst;
- SkMatrix srcToDst;
- ImageDrawMode mode = optimize_sample_area(SkISize::Make(producer->width(), producer->height()),
- srcRect, dstRect, nullptr, &src, &dst, &srcToDst);
- if (mode == ImageDrawMode::kSkip) {
- return;
- }
- // There's no dstClip to worry about and the producer is already made so we wouldn't be able
- // to tell it to use decals if we had to
- SkASSERT(mode != ImageDrawMode::kDecal);
-
- draw_texture_producer(fContext.get(), fRenderTargetContext.get(), this->clip(), viewMatrix,
- paint, producer, src, dst, /* clip */ nullptr, srcToDst,
- GrAA(paint.isAntiAlias()),
- paint.isAntiAlias() ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone,
- constraint, attemptDrawTexture);
+ GrBlurUtils::drawShapeWithMaskFilter(this->context(), fRenderTargetContext.get(), this->clip(),
+ shape, std::move(grPaint), viewMatrix, mf);
}
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 5fe5d41..eb9ccee 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -322,11 +322,11 @@
}
// Use dstRect unless dstClip is provided, which is assumed to be a quad
- auto quad = set[p].fDstClipQuad == nullptr ?
+ auto quad = set[p].fDstClip == nullptr ?
GrPerspQuad::MakeFromRect(set[p].fDstRect, viewMatrix) :
- GrPerspQuad::MakeFromSkQuad(set[p].fDstClipQuad, viewMatrix);
+ GrPerspQuad::MakeFromSkQuad(set[p].fDstClip, viewMatrix);
GrQuadType quadType = baseQuadType;
- if (set[p].fDstClipQuad && baseQuadType != GrQuadType::kPerspective) {
+ if (set[p].fDstClip && baseQuadType != GrQuadType::kPerspective) {
quadType = GrQuadType::kStandard;
}
@@ -348,11 +348,11 @@
float alpha = SkTPin(set[p].fAlpha, 0.f, 1.f);
SkPMColor4f color{alpha, alpha, alpha, alpha};
int srcQuadIndex = -1;
- if (set[p].fDstClipQuad) {
+ if (set[p].fDstClip) {
// Derive new source coordinates that match dstClip's relative locations in dstRect,
// but with respect to srcRect
SkPoint srcQuad[4];
- GrMapRectPoints(set[p].fDstRect, set[p].fSrcRect, set[p].fDstClipQuad, srcQuad, 4);
+ GrMapRectPoints(set[p].fDstRect, set[p].fSrcRect, set[p].fDstClip, srcQuad, 4);
fSrcQuads.push_back(GrPerspQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()),
GrQuadType::kStandard);
srcQuadIndex = fSrcQuads.count() - 1;