aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/vertices.cpp146
-rw-r--r--gn/core.gni1
-rw-r--r--include/core/SkCanvas.h30
-rwxr-xr-xinclude/core/SkVertices.h141
-rw-r--r--include/gpu/GrRenderTargetContext.h15
-rw-r--r--include/utils/SkDumpCanvas.h5
-rw-r--r--include/utils/SkLuaCanvas.h4
-rw-r--r--include/utils/SkNoDrawCanvas.h5
-rw-r--r--src/core/SkCanvas.cpp33
-rw-r--r--src/core/SkDevice.cpp21
-rw-r--r--src/core/SkDevice.h2
-rw-r--r--src/core/SkPictureRecord.h5
-rw-r--r--src/gpu/GrRenderTargetContext.cpp26
-rw-r--r--src/gpu/GrRenderTargetOpList.cpp4
-rw-r--r--src/gpu/SkGpuDevice.cpp94
-rw-r--r--src/gpu/SkGpuDevice.h2
-rw-r--r--src/gpu/SkGrPriv.h16
-rw-r--r--src/gpu/ops/GrDrawVerticesOp.cpp258
-rw-r--r--src/gpu/ops/GrDrawVerticesOp.h89
-rw-r--r--tools/debugger/SkDebugCanvas.h5
20 files changed, 664 insertions, 238 deletions
diff --git a/gm/vertices.cpp b/gm/vertices.cpp
index 8cfb164c5e..5fdce92a8e 100644
--- a/gm/vertices.cpp
+++ b/gm/vertices.cpp
@@ -10,6 +10,7 @@
#include "SkColorFilter.h"
#include "SkGradientShader.h"
#include "SkRandom.h"
+#include "SkVertices.h"
static constexpr SkScalar kShaderSize = 40;
static sk_sp<SkShader> make_shader1() {
@@ -39,6 +40,7 @@ static constexpr uint16_t kMeshFan[] = {
0, 1, 2, 5, 8, 7, 6, 3, 0
};
+static const int kMeshIndexCnt = (int)SK_ARRAY_COUNT(kMeshFan);
static const int kMeshVertexCnt = 9;
static void fill_mesh(SkPoint pts[kMeshVertexCnt], SkPoint texs[kMeshVertexCnt],
@@ -76,9 +78,11 @@ class VerticesGM : public skiagm::GM {
sk_sp<SkShader> fShader1;
sk_sp<SkShader> fShader2;
sk_sp<SkColorFilter> fColorFilter;
+ sk_sp<SkVertices> fVertices;
+ bool fUseObject;
public:
- VerticesGM() {}
+ VerticesGM(bool useObject) : fUseObject(useObject) {}
protected:
@@ -87,10 +91,27 @@ protected:
fShader1 = make_shader1();
fShader2 = make_shader2();
fColorFilter = make_color_filter();
+ if (fUseObject) {
+ std::unique_ptr<SkPoint[]> points(new SkPoint[kMeshVertexCnt]);
+ std::unique_ptr<SkPoint[]> texs(new SkPoint[kMeshVertexCnt]);
+ std::unique_ptr<SkColor[]> colors(new SkColor[kMeshVertexCnt]);
+ std::unique_ptr<uint16_t[]> indices(new uint16_t[kMeshIndexCnt]);
+ memcpy(points.get(), fPts, sizeof(SkPoint) * kMeshVertexCnt);
+ memcpy(colors.get(), fColors, sizeof(SkColor) * kMeshVertexCnt);
+ memcpy(texs.get(), fTexs, sizeof(SkPoint) * kMeshVertexCnt);
+ memcpy(indices.get(), kMeshFan, sizeof(uint16_t) * kMeshIndexCnt);
+ fVertices = SkVertices::MakeIndexed(SkCanvas::kTriangleFan_VertexMode,
+ std::move(points),
+ std::move(colors), std::move(texs), kMeshVertexCnt,
+ std::move(indices), kMeshIndexCnt);
+ }
}
SkString onShortName() override {
SkString name("vertices");
+ if (fUseObject) {
+ name.append("_object");
+ }
return name;
}
@@ -99,39 +120,6 @@ protected:
}
void onDraw(SkCanvas* canvas) override {
- const struct {
- const SkColor* fColors;
- const SkPoint* fTexs;
- const sk_sp<SkShader>& fShader;
- const sk_sp<SkColorFilter>& fColorFilter;
- uint8_t fAlpha;
- } rec[] = {
- { fColors, nullptr, fShader1, nullptr , 0xFF },
- { nullptr, fTexs , fShader1, nullptr , 0xFF },
- { fColors, fTexs , fShader1, nullptr , 0xFF },
- { fColors, nullptr, fShader2, nullptr , 0xFF },
- { nullptr, fTexs , fShader2, nullptr , 0xFF },
- { fColors, fTexs , fShader2, nullptr , 0xFF },
- { fColors, nullptr, fShader1, fColorFilter, 0xFF },
- { nullptr, fTexs , fShader1, fColorFilter, 0xFF },
- { fColors, fTexs , fShader1, fColorFilter, 0xFF },
- { fColors, nullptr, fShader2, fColorFilter, 0xFF },
- { nullptr, fTexs , fShader2, fColorFilter, 0xFF },
- { fColors, fTexs , fShader2, fColorFilter, 0xFF },
- { fColors, nullptr, fShader1, nullptr , 0x80 },
- { nullptr, fTexs , fShader1, nullptr , 0x80 },
- { fColors, fTexs , fShader1, nullptr , 0x80 },
- { fColors, nullptr, fShader2, nullptr , 0x80 },
- { nullptr, fTexs , fShader2, nullptr , 0x80 },
- { fColors, fTexs , fShader2, nullptr , 0x80 },
- { fColors, nullptr, fShader1, fColorFilter, 0x80 },
- { nullptr, fTexs , fShader1, fColorFilter, 0x80 },
- { fColors, fTexs , fShader1, fColorFilter, 0x80 },
- { fColors, nullptr, fShader2, fColorFilter, 0x80 },
- { nullptr, fTexs , fShader2, fColorFilter, 0x80 },
- { fColors, fTexs , fShader2, fColorFilter, 0x80 },
- };
-
const SkBlendMode modes[] = {
SkBlendMode::kClear,
SkBlendMode::kSrc,
@@ -168,18 +156,38 @@ protected:
canvas->translate(4, 4);
int x = 0;
- for (size_t j = 0; j < SK_ARRAY_COUNT(modes); ++j) {
+ for (auto mode : modes) {
canvas->save();
- for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
- paint.setShader(rec[i].fShader);
- paint.setColorFilter(rec[i].fColorFilter);
- paint.setAlpha(rec[i].fAlpha);
- //if (2 == x)
- canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode, kMeshVertexCnt, fPts,
- rec[i].fTexs, rec[i].fColors, modes[j], kMeshFan,
- SK_ARRAY_COUNT(kMeshFan), paint);
- canvas->translate(40, 0);
- ++x;
+ for (uint8_t alpha : {0xFF, 0x80}) {
+ for (const auto& cf : {sk_sp<SkColorFilter>(nullptr), fColorFilter}) {
+ for (const auto& shader : {fShader1, fShader2}) {
+ static constexpr struct {
+ bool fHasColors;
+ bool fHasTexs;
+ } kAttrs[] = {{true, false}, {false, true}, {true, true}};
+ for (auto attrs : kAttrs) {
+ paint.setShader(shader);
+ paint.setColorFilter(cf);
+ paint.setAlpha(alpha);
+ if (fUseObject) {
+ uint32_t flags = 0;
+ flags |=
+ attrs.fHasColors ? 0 : SkCanvas::kIgnoreColors_VerticesFlag;
+ flags |= attrs.fHasTexs ? 0
+ : SkCanvas::kIgnoreTexCoords_VerticesFlag;
+ canvas->drawVertices(fVertices, mode, paint, flags);
+ } else {
+ const SkColor* colors = attrs.fHasColors ? fColors : nullptr;
+ const SkPoint* texs = attrs.fHasTexs ? fTexs : nullptr;
+ canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode,
+ kMeshVertexCnt, fPts, texs, colors, mode,
+ kMeshFan, kMeshIndexCnt, paint);
+ }
+ canvas->translate(40, 0);
+ ++x;
+ }
+ }
+ }
}
canvas->restore();
canvas->translate(0, 40);
@@ -192,14 +200,15 @@ private:
/////////////////////////////////////////////////////////////////////////////////////
-DEF_GM(return new VerticesGM();)
+DEF_GM(return new VerticesGM(true);)
+DEF_GM(return new VerticesGM(false);)
+
+static void draw_batching(SkCanvas* canvas, bool useObject) {
+ std::unique_ptr<SkPoint[]> pts(new SkPoint[kMeshVertexCnt]);
+ std::unique_ptr<SkPoint[]> texs(new SkPoint[kMeshVertexCnt]);
+ std::unique_ptr<SkColor[]> colors(new SkColor[kMeshVertexCnt]);
+ fill_mesh(pts.get(), texs.get(), colors.get());
-// This test exists to exercise batching in the gpu backend.
-DEF_SIMPLE_GM(vertices_batching, canvas, 50, 500) {
- SkPoint pts[kMeshVertexCnt];
- SkPoint texs[kMeshVertexCnt];
- SkColor colors[kMeshVertexCnt];
- fill_mesh(pts, texs, colors);
SkTDArray<SkMatrix> matrices;
matrices.push()->reset();
matrices.push()->setTranslate(0, 40);
@@ -211,13 +220,23 @@ DEF_SIMPLE_GM(vertices_batching, canvas, 50, 500) {
auto shader = make_shader1();
// Triangle fans can't batch so we convert to regular triangles,
- static constexpr int kNumTris = SK_ARRAY_COUNT(kMeshFan) - 2;
- uint16_t indices[3 * kNumTris];
+ static constexpr int kNumTris = kMeshIndexCnt - 2;
+ std::unique_ptr<uint16_t[]> indices(new uint16_t[3 * kNumTris]);
for (size_t i = 0; i < kNumTris; ++i) {
indices[3 * i] = kMeshFan[0];
indices[3 * i + 1] = kMeshFan[i + 1];
indices[3 * i + 2] = kMeshFan[i + 2];
}
+
+ sk_sp<SkVertices> vertices;
+ if (useObject) {
+ vertices =
+ SkVertices::MakeIndexed(SkCanvas::kTriangles_VertexMode, std::move(pts),
+ std::move(colors),
+ std::move(texs), kMeshVertexCnt, std::move(indices),
+ 3 * kNumTris);
+ }
+ canvas->save();
canvas->translate(10, 10);
for (bool useShader : {false, true}) {
for (bool useTex : {false, true}) {
@@ -225,13 +244,26 @@ DEF_SIMPLE_GM(vertices_batching, canvas, 50, 500) {
canvas->save();
canvas->concat(m);
SkPaint paint;
- const SkPoint* t = useTex ? texs : nullptr;
paint.setShader(useShader ? shader : nullptr);
- canvas->drawVertices(SkCanvas::kTriangles_VertexMode, kMeshVertexCnt, pts, t,
- colors, indices, SK_ARRAY_COUNT(indices), paint);
+ if (useObject) {
+ uint32_t flags = useTex ? 0 : SkCanvas::kIgnoreTexCoords_VerticesFlag;
+ canvas->drawVertices(vertices, SkBlendMode::kModulate, paint, flags);
+ } else {
+ const SkPoint* t = useTex ? texs.get() : nullptr;
+ canvas->drawVertices(SkCanvas::kTriangles_VertexMode, kMeshVertexCnt, pts.get(),
+ t, colors.get(), indices.get(), kNumTris * 3, paint);
+ }
canvas->restore();
}
canvas->translate(0, 120);
}
}
+ canvas->restore();
+}
+
+// This test exists to exercise batching in the gpu backend.
+DEF_SIMPLE_GM(vertices_batching, canvas, 100, 500) {
+ draw_batching(canvas, false);
+ canvas->translate(50, 0);
+ draw_batching(canvas, true);
}
diff --git a/gn/core.gni b/gn/core.gni
index b10b628be0..12089371ee 100644
--- a/gn/core.gni
+++ b/gn/core.gni
@@ -442,6 +442,7 @@ skia_core_sources = [
"$_include/core/SkTypeface.h",
"$_include/core/SkTypes.h",
"$_include/core/SkUnPreMultiply.h",
+ "$_include/core/SkVertices.h",
"$_include/core/SkWriter32.h",
# private
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index b2bc9ed3f4..d58b7ea515 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -42,6 +42,7 @@ struct SkRSXform;
class SkSurface;
class SkSurface_Base;
class SkTextBlob;
+class SkVertices;
/** \class SkCanvas
@@ -1152,9 +1153,9 @@ public:
in _texture_ space (not uv space) for each vertex.
@param colors May be null. If not null, specifies a color for each
vertex, to be interpolated across the triangle.
- @param mode Used if both texs and colors are present. In this
- case the colors are combined with the texture using mode,
- before being drawn using the paint.
+ @param mode Used if both texs and colors are present and paint has a
+ shader. In this case the colors are combined with the texture
+ using mode, before being drawn using the paint.
@param indices If not null, array of indices to reference into the
vertex (texs, colors) array.
@param indexCount number of entries in the indices array (if not null)
@@ -1172,6 +1173,23 @@ public:
this->drawVertices(vmode, vertexCount, vertices, texs, colors, SkBlendMode::kModulate,
indices, indexCount, paint);
}
+ enum VerticesFlags {
+ /** Ignore the vertices' colors and instead use the paint color. */
+ kIgnoreColors_VerticesFlag = 0x1,
+ /** Ignore the vertices' tex coords (and any shader on the paint). */
+ kIgnoreTexCoords_VerticesFlag = 0x2
+ };
+ /** Draw vertices from an immutable SkVertices object.
+
+ @param vertices The mesh to draw.
+ @param mode Used if both texs and colors are present and paint has a
+ shader. In this case the colors are combined with the texture
+ using mode, before being drawn using the paint.
+ @param paint Specifies the shader/texture if present.
+ @param flags Allows the caller to ignore colors or texs on vertices.
+ */
+ void drawVertices(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint,
+ uint32_t flags = 0);
/**
Draw a cubic coons patch
@@ -1424,6 +1442,12 @@ protected:
virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
const SkPoint texs[], const SkColor colors[], SkBlendMode,
const uint16_t indices[], int indexCount, const SkPaint&);
+ virtual void onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode mode,
+ const SkPaint& paint, uint32_t flags);
+ // Subclasses can use this put the vertices object call on the regular draw vertices code path.
+ // This is temporary until we teach recording and other SkCanvas classes about SkVertices.
+ void onDrawVerticesObjectFallback(sk_sp<SkVertices> vertices, SkBlendMode mode,
+ const SkPaint& paint, uint32_t flags);
virtual void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
int count, SkBlendMode, const SkRect* cull, const SkPaint*);
diff --git a/include/core/SkVertices.h b/include/core/SkVertices.h
new file mode 100755
index 0000000000..9b94372d7c
--- /dev/null
+++ b/include/core/SkVertices.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkVertices_DEFINED
+#define SkVertices_DEFINED
+
+#include "SkCanvas.h"
+#include "SkColor.h"
+#include "SkPoint.h"
+#include "SkRect.h"
+#include "SkRefCnt.h"
+
+/**
+ * An immutable set of vertex data that can be used with SkCanvas::drawVertices. Clients are
+ * encouraged to provide a bounds on the vertex positions if they can compute one more cheaply than
+ * looping over the positions.
+ */
+class SkVertices : public SkNVRefCnt<SkVertices> {
+public:
+ static sk_sp<SkVertices> Make(SkCanvas::VertexMode mode,
+ std::unique_ptr<const SkPoint[]> positions,
+ std::unique_ptr<const SkColor[]> colors, /* optional */
+ std::unique_ptr<const SkPoint[]> texs, /* optional */
+ int vertexCnt) {
+ if (!positions || vertexCnt <= 0) {
+ return nullptr;
+ }
+ return sk_sp<SkVertices>(new SkVertices(mode, std::move(positions), std::move(colors),
+ std::move(texs), vertexCnt, nullptr, 0, nullptr));
+ }
+
+ static sk_sp<SkVertices> Make(SkCanvas::VertexMode mode,
+ std::unique_ptr<const SkPoint[]> positions,
+ std::unique_ptr<const SkColor[]> colors, /* optional */
+ std::unique_ptr<const SkPoint[]> texs, /* optional */
+ int vertexCnt,
+ const SkRect& bounds) {
+ if (!positions || vertexCnt <= 0) {
+ return nullptr;
+ }
+ return sk_sp<SkVertices>(new SkVertices(mode, std::move(positions), std::move(colors),
+ std::move(texs), vertexCnt, nullptr, 0, &bounds));
+ }
+
+ static sk_sp<SkVertices> MakeIndexed(SkCanvas::VertexMode mode,
+ std::unique_ptr<const SkPoint[]> positions,
+ std::unique_ptr<const SkColor[]> colors, /* optional */
+ std::unique_ptr<const SkPoint[]> texs, /* optional */
+ int vertexCnt,
+ std::unique_ptr<const uint16_t[]> indices,
+ int indexCnt) {
+ if (!positions || !indices || vertexCnt <= 0 || indexCnt <= 0) {
+ return nullptr;
+ }
+ return sk_sp<SkVertices>(new SkVertices(mode, std::move(positions), std::move(colors),
+ std::move(texs), vertexCnt, std::move(indices),
+ indexCnt, nullptr));
+ }
+
+ static sk_sp<SkVertices> MakeIndexed(SkCanvas::VertexMode mode,
+ std::unique_ptr<const SkPoint[]> positions,
+ std::unique_ptr<const SkColor[]> colors, /* optional */
+ std::unique_ptr<const SkPoint[]> texs, /* optional */
+ int vertexCnt,
+ std::unique_ptr<const uint16_t[]> indices,
+ int indexCnt,
+ const SkRect& bounds) {
+ if (!positions || !indices || vertexCnt <= 0 || indexCnt <= 0) {
+ return nullptr;
+ }
+ return sk_sp<SkVertices>(new SkVertices(mode, std::move(positions), std::move(colors),
+ std::move(texs), vertexCnt, std::move(indices),
+ indexCnt, &bounds));
+ }
+
+ SkCanvas::VertexMode mode() const { return fMode; }
+
+ int vertexCount() const { return fVertexCnt; }
+ bool hasColors() const { return SkToBool(fColors); }
+ bool hasTexCoords() const { return SkToBool(fTexs); }
+ const SkPoint* positions() const { return fPositions.get(); }
+ const SkPoint* texCoords() const { return fTexs.get(); }
+ const SkColor* colors() const { return fColors.get(); }
+
+ bool isIndexed() const { return SkToBool(fIndexCnt); }
+ int indexCount() const { return fIndexCnt; }
+ const uint16_t* indices() const { return fIndices.get(); }
+
+ size_t size() const {
+ return fVertexCnt * (sizeof(SkPoint) * (this->hasTexCoords() ? 2 : 1) + sizeof(SkColor)) +
+ fIndexCnt * sizeof(uint16_t);
+ }
+
+ const SkRect& bounds() const { return fBounds; }
+
+private:
+ SkVertices(SkCanvas::VertexMode mode, std::unique_ptr<const SkPoint[]> positions,
+ std::unique_ptr<const SkColor[]> colors, std::unique_ptr<const SkPoint[]> texs,
+ int vertexCnt, std::unique_ptr<const uint16_t[]> indices, int indexCnt,
+ const SkRect* bounds)
+ : fMode(mode)
+ , fVertexCnt(vertexCnt)
+ , fIndexCnt(indexCnt)
+ , fPositions(std::move(positions))
+ , fColors(std::move(colors))
+ , fTexs(std::move(texs))
+ , fIndices(std::move(indices)) {
+ SkASSERT(SkToBool(fPositions) && SkToBool(fVertexCnt));
+ SkASSERT(SkToBool(fIndices) == SkToBool(fIndexCnt));
+ if (bounds) {
+#ifdef SK_DEBUG
+ fBounds.setBounds(fPositions.get(), fVertexCnt);
+ SkASSERT(bounds->fLeft <= fBounds.fLeft && bounds->fRight >= fBounds.fRight &&
+ bounds->fTop <= fBounds.fTop && bounds->fBottom >= fBounds.fBottom);
+#endif
+ fBounds = *bounds;
+ } else {
+ fBounds.setBounds(fPositions.get(), fVertexCnt);
+ }
+#ifdef SK_DEBUG
+ for (int i = 0; i < fIndexCnt; ++i) {
+ SkASSERT(fIndices[i] < fVertexCnt);
+ }
+#endif
+ }
+
+ SkCanvas::VertexMode fMode;
+ int fVertexCnt;
+ int fIndexCnt;
+ std::unique_ptr<const SkPoint[]> fPositions;
+ std::unique_ptr<const SkColor[]> fColors;
+ std::unique_ptr<const SkPoint[]> fTexs;
+ std::unique_ptr<const uint16_t[]> fIndices;
+ SkRect fBounds;
+};
+
+#endif
diff --git a/include/gpu/GrRenderTargetContext.h b/include/gpu/GrRenderTargetContext.h
index 403de56f34..11b1c531e0 100644
--- a/include/gpu/GrRenderTargetContext.h
+++ b/include/gpu/GrRenderTargetContext.h
@@ -42,6 +42,7 @@ class SkRegion;
class SkRRect;
struct SkRSXform;
class SkTextBlob;
+class SkVertices;
/**
* A helper object to orchestrate commands (draws, etc...) for GrSurfaces that are GrRenderTargets.
@@ -230,6 +231,20 @@ public:
ColorArrayType = ColorArrayType::kPremulGrColor);
/**
+ * Draws vertices with a paint.
+ *
+ * @param paint describes how to color pixels.
+ * @param viewMatrix transformation matrix
+ * @param veritces specifies the mesh to draw.
+ * @param flags A bitfield of options specified by SkCanvas::VerticesFlags.
+ */
+ void drawVertices(const GrClip&,
+ GrPaint&& paint,
+ const SkMatrix& viewMatrix,
+ sk_sp<SkVertices> vertices,
+ uint32_t flags);
+
+ /**
* Draws textured sprites from an atlas with a paint. This currently does not support AA for the
* sprite rectangle edges.
*
diff --git a/include/utils/SkDumpCanvas.h b/include/utils/SkDumpCanvas.h
index c8f977ec10..79a49bcd3b 100644
--- a/include/utils/SkDumpCanvas.h
+++ b/include/utils/SkDumpCanvas.h
@@ -9,6 +9,7 @@
#define SkDumpCanvas_DEFINED
#include "SkCanvas.h"
+#include "SkVertices.h"
/** This class overrides all the draw methods on SkCanvas, and formats them
as text, and then sends that to a Dumper helper object.
@@ -116,6 +117,10 @@ protected:
const SkColor colors[], SkBlendMode,
const uint16_t indices[], int indexCount,
const SkPaint&) override;
+ void onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint,
+ uint32_t flags) override {
+ this->onDrawVerticesObjectFallback(std::move(vertices), mode, paint, flags);
+ }
void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
diff --git a/include/utils/SkLuaCanvas.h b/include/utils/SkLuaCanvas.h
index 357ddc81da..805c2e14b6 100644
--- a/include/utils/SkLuaCanvas.h
+++ b/include/utils/SkLuaCanvas.h
@@ -62,6 +62,10 @@ protected:
const SkColor colors[], SkBlendMode,
const uint16_t indices[], int indexCount,
const SkPaint&) override;
+ void onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint,
+ uint32_t flags) override {
+ this->onDrawVerticesObjectFallback(std::move(vertices), mode, paint, flags);
+ }
void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
diff --git a/include/utils/SkNoDrawCanvas.h b/include/utils/SkNoDrawCanvas.h
index 316a1c0e02..14b85549f4 100644
--- a/include/utils/SkNoDrawCanvas.h
+++ b/include/utils/SkNoDrawCanvas.h
@@ -9,6 +9,7 @@
#define SkNoDrawCanvas_DEFINED
#include "SkCanvas.h"
+#include "SkVertices.h"
struct SkIRect;
@@ -67,6 +68,10 @@ protected:
const SkPaint*) override {}
void onDrawVertices(VertexMode, int, const SkPoint[], const SkPoint[], const SkColor[],
SkBlendMode, const uint16_t[], int, const SkPaint&) override {}
+ void onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint,
+ uint32_t flags) override {
+ this->onDrawVerticesObjectFallback(std::move(vertices), mode, paint, flags);
+ }
void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
int, SkBlendMode, const SkRect*, const SkPaint*) override {}
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 41c5116718..eb81bd7951 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -49,6 +49,7 @@
#endif
#include "SkClipOpPriv.h"
+#include "SkVertices.h"
#define RETURN_ON_NULL(ptr) do { if (nullptr == (ptr)) return; } while (0)
@@ -1857,8 +1858,14 @@ void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], con
void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
const SkPoint texs[], const SkColor colors[], SkBlendMode bmode,
const uint16_t indices[], int indexCount, const SkPaint& paint) {
- this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, bmode,
- indices, indexCount, paint);
+ this->onDrawVertices(vmode, vertexCount, std::move(vertices), texs, colors, bmode, indices,
+ indexCount, paint);
+}
+
+void SkCanvas::drawVertices(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint,
+ uint32_t flags) {
+ RETURN_ON_NULL(vertices);
+ this->onDrawVerticesObject(std::move(vertices), mode, paint, flags);
}
void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
@@ -2815,6 +2822,28 @@ void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
LOOPER_END
}
+void SkCanvas::onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode bmode,
+ const SkPaint& paint, uint32_t flags) {
+ TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
+ LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
+
+ while (iter.next()) {
+ // In the common case of one iteration we could std::move vertices here.
+ iter.fDevice->drawVerticesObject(iter, vertices, bmode, looper.paint(), flags);
+ }
+
+ LOOPER_END
+}
+
+void SkCanvas::onDrawVerticesObjectFallback(sk_sp<SkVertices> vertices, SkBlendMode mode,
+ const SkPaint& paint, uint32_t flags) {
+ const SkPoint* texs =
+ (flags & SkCanvas::kIgnoreTexCoords_VerticesFlag) ? nullptr : vertices->texCoords();
+ const SkColor* colors = (flags & kIgnoreColors_VerticesFlag) ? nullptr : vertices->colors();
+ this->onDrawVertices(vertices->mode(), vertices->vertexCount(), vertices->positions(), texs,
+ colors, mode, vertices->indices(), vertices->indexCount(), paint);
+}
+
void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
const SkPoint texCoords[4], SkBlendMode bmode,
const SkPaint& paint) {
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 8042c16f2c..07b9c23373 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -5,26 +5,27 @@
* found in the LICENSE file.
*/
-#include "SkColorFilter.h"
#include "SkDevice.h"
+#include "SkColorFilter.h"
#include "SkDraw.h"
#include "SkDrawFilter.h"
-#include "SkImage_Base.h"
#include "SkImageCacherator.h"
#include "SkImageFilter.h"
#include "SkImageFilterCache.h"
#include "SkImagePriv.h"
+#include "SkImage_Base.h"
#include "SkLatticeIter.h"
#include "SkPatchUtils.h"
-#include "SkPathPriv.h"
#include "SkPathMeasure.h"
-#include "SkRasterClip.h"
+#include "SkPathPriv.h"
#include "SkRSXform.h"
+#include "SkRasterClip.h"
#include "SkShader.h"
#include "SkSpecialImage.h"
+#include "SkTLazy.h"
#include "SkTextBlobRunIterator.h"
#include "SkTextToPathIter.h"
-#include "SkTLazy.h"
+#include "SkVertices.h"
SkBaseDevice::SkBaseDevice(const SkImageInfo& info, const SkSurfaceProps& surfaceProps)
: fInfo(info)
@@ -309,6 +310,16 @@ void SkBaseDevice::drawAtlas(const SkDraw& draw, const SkImage* atlas, const SkR
}
}
+void SkBaseDevice::drawVerticesObject(const SkDraw& draw, sk_sp<SkVertices> vertices,
+ SkBlendMode mode, const SkPaint& paint, uint32_t flags) {
+ const SkPoint* texs =
+ (flags & SkCanvas::kIgnoreTexCoords_VerticesFlag) ? nullptr : vertices->texCoords();
+ const SkColor* colors =
+ (flags & SkCanvas::kIgnoreColors_VerticesFlag) ? nullptr : vertices->colors();
+ this->drawVertices(draw, vertices->mode(), vertices->vertexCount(), vertices->positions(), texs,
+ colors, mode, vertices->indices(), vertices->indexCount(), paint);
+}
+
///////////////////////////////////////////////////////////////////////////////////////////////////
void SkBaseDevice::drawSpecial(const SkDraw&, SkSpecialImage*, int x, int y, const SkPaint&) {}
diff --git a/src/core/SkDevice.h b/src/core/SkDevice.h
index ab0fdbd734..92396725a4 100644
--- a/src/core/SkDevice.h
+++ b/src/core/SkDevice.h
@@ -198,6 +198,8 @@ protected:
const SkColor colors[], SkBlendMode,
const uint16_t indices[], int indexCount,
const SkPaint& paint) = 0;
+ virtual void drawVerticesObject(const SkDraw&, sk_sp<SkVertices>, SkBlendMode, const SkPaint&,
+ uint32_t flags);
// default implementation unrolls the blob runs.
virtual void drawTextBlob(const SkDraw&, const SkTextBlob*, SkScalar x, SkScalar y,
const SkPaint& paint, SkDrawFilter* drawFilter);
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 9339d12ba5..587233c298 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -15,6 +15,7 @@
#include "SkTArray.h"
#include "SkTDArray.h"
#include "SkTHash.h"
+#include "SkVertices.h"
#include "SkWriter32.h"
// These macros help with packing and unpacking a single byte value and
@@ -203,6 +204,10 @@ protected:
const SkColor colors[], SkBlendMode,
const uint16_t indices[], int indexCount,
const SkPaint&) override;
+ void onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint,
+ uint32_t flags) override {
+ this->onDrawVerticesObjectFallback(std::move(vertices), mode, paint, flags);
+ }
void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index c0b25dedcf..8e90b04ee5 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -898,12 +898,34 @@ void GrRenderTargetContext::drawVertices(const GrClip& clip,
return;
}
- viewMatrix.mapRect(&bounds);
-
std::unique_ptr<GrDrawOp> op = GrDrawVerticesOp::Make(
paint.getColor(), primitiveType, viewMatrix, positions, vertexCount, indices,
indexCount, colors, texCoords, bounds, colorArrayType);
+ if (!op) {
+ return;
+ }
+ GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
+ this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+}
+void GrRenderTargetContext::drawVertices(const GrClip& clip,
+ GrPaint&& paint,
+ const SkMatrix& viewMatrix,
+ sk_sp<SkVertices> vertices,
+ uint32_t flags) {
+ ASSERT_SINGLE_OWNER
+ RETURN_IF_ABANDONED
+ SkDEBUGCODE(this->validate();)
+ GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawVertices");
+
+ AutoCheckFlush acf(this->drawingManager());
+
+ SkASSERT(vertices);
+ std::unique_ptr<GrDrawOp> op =
+ GrDrawVerticesOp::Make(paint.getColor(), std::move(vertices), viewMatrix, flags);
+ if (!op) {
+ return;
+ }
GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
}
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index 1c0243ba14..69ba279434 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -466,7 +466,7 @@ GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr<GrOp> op,
// 2) intersect with something
// 3) find a 'blocker'
GR_AUDIT_TRAIL_ADD_OP(fAuditTrail, op.get(), renderTargetID);
- GrOP_INFO("Re-Recording (%s, B%u)\n"
+ GrOP_INFO("Recording (%s, B%u)\n"
"\tBounds LRTB (%f, %f, %f, %f)\n",
op->name(),
op->uniqueID(),
@@ -492,6 +492,8 @@ GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr<GrOp> op,
if (candidate.fOp->combineIfPossible(op.get(), *this->caps())) {
GrOP_INFO("\t\tCombining with (%s, B%u)\n", candidate.fOp->name(),
candidate.fOp->uniqueID());
+ GrOP_INFO("\t\t\tCombined op info:\n");
+ GrOP_INFO(SkTabString(candidate.fOp->dumpInfo(), 4).c_str());
GR_AUDIT_TRAIL_OPS_RESULT_COMBINED(fAuditTrail, candidate.fOp.get(), op.get());
join(&fRecordedOps.fromBack(i).fClippedBounds,
fRecordedOps.fromBack(i).fClippedBounds, clippedBounds);
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index b658def522..4068c2b102 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -14,10 +14,10 @@
#include "GrImageTextureMaker.h"
#include "GrRenderTargetContextPriv.h"
#include "GrStyle.h"
+#include "GrSurfaceContextPriv.h"
#include "GrTextureAdjuster.h"
#include "GrTextureProxy.h"
#include "GrTracing.h"
-
#include "SkCanvasPriv.h"
#include "SkDraw.h"
#include "SkGlyphCache.h"
@@ -44,6 +44,7 @@
#include "SkTLazy.h"
#include "SkUtils.h"
#include "SkVertState.h"
+#include "SkVertices.h"
#include "SkWritePixelsRec.h"
#include "effects/GrBicubicEffect.h"
#include "effects/GrSimpleTextureEffect.h"
@@ -1568,14 +1569,30 @@ void SkGpuDevice::drawBitmapLattice(const SkDraw& draw, const SkBitmap& bitmap,
this->drawProducerLattice(draw, &maker, lattice, dst, paint);
}
-///////////////////////////////////////////////////////////////////////////////
-
-// must be in SkCanvas::VertexMode order
-static const GrPrimitiveType gVertexMode2PrimitiveType[] = {
- kTriangles_GrPrimitiveType,
- kTriangleStrip_GrPrimitiveType,
- kTriangleFan_GrPrimitiveType,
-};
+bool init_vertices_paint(const SkPaint& skPaint, const SkMatrix& matrix, SkBlendMode bmode,
+ bool hasTexs, bool hasColors, GrRenderTargetContext* rtc,
+ GrPaint* grPaint) {
+ GrContext* context = rtc->surfPriv().getContext();
+ if (hasTexs && skPaint.getShader()) {
+ if (hasColors) {
+ // When there are texs and colors the shader and colors are combined using bmode.
+ return SkPaintToGrPaintWithXfermode(context, rtc, skPaint, matrix, bmode, false,
+ grPaint);
+ } else {
+ // We have a shader, but no colors to blend it against.
+ return SkPaintToGrPaint(context, rtc, skPaint, matrix, grPaint);
+ }
+ } else {
+ if (hasColors) {
+ // We have colors, but either have no shader or no texture coords (which implies that
+ // we should ignore the shader).
+ return SkPaintToGrPaintWithPrimitiveColor(context, rtc, skPaint, grPaint);
+ } else {
+ // No colors and no shaders. Just draw with the paint color.
+ return (!SkPaintToGrPaintNoShader(context, rtc, skPaint, grPaint));
+ }
+ }
+}
void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
int vertexCount, const SkPoint vertices[],
@@ -1645,40 +1662,13 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
return;
}
- GrPrimitiveType primType = gVertexMode2PrimitiveType[vmode];
+ GrPrimitiveType primType = SkVertexModeToGrPrimitiveType(vmode);
GrPaint grPaint;
- if (texs && paint.getShader()) {
- if (colors) {
- // When there are texs and colors the shader and colors are combined using bmode.
- if (!SkPaintToGrPaintWithXfermode(this->context(), fRenderTargetContext.get(), paint,
- *draw.fMatrix, bmode, false, &grPaint)) {
- return;
- }
- } else {
- // We have a shader, but no colors to blend it against.
- if (!SkPaintToGrPaint(this->context(), fRenderTargetContext.get(), paint, *draw.fMatrix,
- &grPaint)) {
- return;
- }
- }
- } else {
- if (colors) {
- // We have colors, but either have no shader or no texture coords (which implies that
- // we should ignore the shader).
- if (!SkPaintToGrPaintWithPrimitiveColor(this->context(), fRenderTargetContext.get(),
- paint, &grPaint)) {
- return;
- }
- } else {
- // No colors and no shaders. Just draw with the paint color.
- if (!SkPaintToGrPaintNoShader(this->context(), fRenderTargetContext.get(), paint,
- &grPaint)) {
- return;
- }
- }
+ if (!init_vertices_paint(paint, *draw.fMatrix, bmode, SkToBool(texs), SkToBool(colors),
+ fRenderTargetContext.get(), &grPaint)) {
+ return;
}
-
fRenderTargetContext->drawVertices(fClip,
std::move(grPaint),
*draw.fMatrix,
@@ -1692,6 +1682,30 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
GrRenderTargetContext::ColorArrayType::kSkColor);
}
+void SkGpuDevice::drawVerticesObject(const SkDraw& draw, sk_sp<SkVertices> vertices,
+ SkBlendMode mode, const SkPaint& paint, uint32_t flags) {
+ ASSERT_SINGLE_OWNER
+ CHECK_SHOULD_DRAW(draw);
+ GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawVerticesObject", fContext.get());
+
+ SkASSERT(vertices);
+ GrPaint grPaint;
+ bool hasColors = vertices->hasColors() && !(SkCanvas::kIgnoreColors_VerticesFlag & flags);
+ bool hasTexs = vertices->hasTexCoords() & !(SkCanvas::kIgnoreTexCoords_VerticesFlag & flags);
+ if (!hasTexs && !hasColors) {
+ // The dreaded wireframe mode. Fallback to drawVertices and go so slooooooow.
+ this->drawVertices(draw, vertices->mode(), vertices->vertexCount(), vertices->positions(),
+ nullptr, nullptr, mode, vertices->indices(), vertices->indexCount(),
+ paint);
+ }
+ if (!init_vertices_paint(paint, *draw.fMatrix, mode, hasTexs, hasColors,
+ fRenderTargetContext.get(), &grPaint)) {
+ return;
+ }
+ fRenderTargetContext->drawVertices(fClip, std::move(grPaint), *draw.fMatrix,
+ std::move(vertices), flags);
+}
+
///////////////////////////////////////////////////////////////////////////////
void SkGpuDevice::drawAtlas(const SkDraw& draw, const SkImage* atlas, const SkRSXform xform[],
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index 29452146d1..846a7e5798 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -93,6 +93,8 @@ public:
void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount, const SkPoint verts[],
const SkPoint texs[], const SkColor colors[], SkBlendMode,
const uint16_t indices[], int indexCount, const SkPaint&) override;
+ void drawVerticesObject(const SkDraw&, sk_sp<SkVertices>, SkBlendMode, const SkPaint&,
+ uint32_t flags) override;
void drawAtlas(const SkDraw&, const SkImage* atlas, const SkRSXform[], const SkRect[],
const SkColor[], int count, SkBlendMode, const SkPaint&) override;
void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, const SkPaint&) override;
diff --git a/src/gpu/SkGrPriv.h b/src/gpu/SkGrPriv.h
index 9e2aad0ccd..5437d4a07c 100644
--- a/src/gpu/SkGrPriv.h
+++ b/src/gpu/SkGrPriv.h
@@ -10,6 +10,7 @@
#include "GrBlend.h"
#include "GrTypes.h"
+#include "SkCanvas.h"
#include "SkImageInfo.h"
#include "SkMatrix.h"
#include "SkPM4f.h"
@@ -103,6 +104,21 @@ bool SkPaintToGrPaintWithTexture(GrContext* context,
//////////////////////////////////////////////////////////////////////////////
+static inline GrPrimitiveType SkVertexModeToGrPrimitiveType(const SkCanvas::VertexMode mode) {
+ switch (mode) {
+ case SkCanvas::kTriangles_VertexMode:
+ return kTriangles_GrPrimitiveType;
+ case SkCanvas::kTriangleStrip_VertexMode:
+ return kTriangleStrip_GrPrimitiveType;
+ case SkCanvas::kTriangleFan_VertexMode:
+ return kTriangleFan_GrPrimitiveType;
+ }
+ SkFAIL("Invalid mode");
+ return kPoints_GrPrimitiveType;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
static inline SkPM4f GrColor4fToSkPM4f(const GrColor4f& c) {
SkPM4f pm4f;
pm4f.fVec[SkPM4f::R] = c.fRGBA[0];
diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp
index 43093cee5b..7420a5275a 100644
--- a/src/gpu/ops/GrDrawVerticesOp.cpp
+++ b/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -6,87 +6,99 @@
*/
#include "GrDrawVerticesOp.h"
-
#include "GrDefaultGeoProcFactory.h"
-#include "GrInvariantOutput.h"
#include "GrOpFlushState.h"
+#include "SkGrPriv.h"
-static sk_sp<GrGeometryProcessor> make_gp(bool clientProvidedLocalCoords,
- bool pipelineReadsLocalCoords,
- GrRenderTargetContext::ColorArrayType colorArrayType,
- bool multipleViewMatrices,
- const SkMatrix& viewMatrixIfCommon,
- bool* hasLocalCoordAttribute) {
- using namespace GrDefaultGeoProcFactory;
- LocalCoords::Type localCoordsType;
- if (pipelineReadsLocalCoords) {
- if (clientProvidedLocalCoords || multipleViewMatrices) {
- *hasLocalCoordAttribute = true;
- localCoordsType = LocalCoords::kHasExplicit_Type;
- } else {
- *hasLocalCoordAttribute = false;
- localCoordsType = LocalCoords::kUsePosition_Type;
- }
+std::unique_ptr<GrDrawOp> GrDrawVerticesOp::Make(
+ GrColor color, GrPrimitiveType primitiveType, const SkMatrix& viewMatrix,
+ const SkPoint* positions, int vertexCount, const uint16_t* indices, int indexCount,
+ const uint32_t* colors, const SkPoint* localCoords, const SkRect& bounds,
+ GrRenderTargetContext::ColorArrayType colorArrayType) {
+ SkASSERT(positions);
+ std::unique_ptr<SkPoint[]> pos(new SkPoint[vertexCount]);
+ memcpy(pos.get(), positions, sizeof(SkPoint) * vertexCount);
+ std::unique_ptr<SkColor[]> col;
+ if (colors) {
+ col.reset(new SkColor[vertexCount]);
+ memcpy(col.get(), colors, sizeof(SkColor) * vertexCount);
} else {
- localCoordsType = LocalCoords::kUnused_Type;
- *hasLocalCoordAttribute = false;
+ // When we tessellate we will fill a color array with the GrColor value passed above as
+ // 'color'.
+ colorArrayType = GrRenderTargetContext::ColorArrayType::kPremulGrColor;
+ }
+ std::unique_ptr<SkPoint[]> lc;
+ if (localCoords) {
+ lc.reset(new SkPoint[vertexCount]);
+ memcpy(lc.get(), localCoords, sizeof(SkPoint) * vertexCount);
}
+ std::unique_ptr<uint16_t[]> idx;
+ if (indexCount) {
+ idx.reset(new uint16_t[indexCount]);
+ memcpy(idx.get(), indices, sizeof(uint16_t) * indexCount);
+ }
+ static constexpr SkCanvas::VertexMode kIgnoredMode = SkCanvas::kTriangles_VertexMode;
+ sk_sp<SkVertices> vertices;
+ if (indices) {
+ vertices = SkVertices::MakeIndexed(kIgnoredMode, std::move(pos), std::move(col),
+ std::move(lc),
+ vertexCount, std::move(idx), indexCount, bounds);
+ } else {
+ vertices = SkVertices::Make(kIgnoredMode, std::move(pos), std::move(col), std::move(lc),
+ vertexCount, bounds);
+ }
+ if (!vertices) {
+ return nullptr;
+ }
+ return std::unique_ptr<GrDrawOp>(new GrDrawVerticesOp(std::move(vertices), primitiveType, color,
+ colorArrayType, viewMatrix));
+}
- Color::Type colorType =
- (colorArrayType == GrRenderTargetContext::ColorArrayType::kPremulGrColor)
- ? Color::kPremulGrColorAttribute_Type
- : Color::kUnpremulSkColorAttribute_Type;
- const SkMatrix& vm = multipleViewMatrices ? SkMatrix::I() : viewMatrixIfCommon;
- return GrDefaultGeoProcFactory::Make(colorType, Coverage::kSolid_Type, localCoordsType, vm);
+std::unique_ptr<GrDrawOp> GrDrawVerticesOp::Make(GrColor color, sk_sp<SkVertices> vertices,
+ const SkMatrix& viewMatrix, uint32_t flags) {
+ SkASSERT(vertices);
+ GrPrimitiveType primType = SkVertexModeToGrPrimitiveType(vertices->mode());
+ return std::unique_ptr<GrDrawOp>(new GrDrawVerticesOp(
+ std::move(vertices), primType, color, GrRenderTargetContext::ColorArrayType::kSkColor,
+ viewMatrix, flags));
}
-GrDrawVerticesOp::GrDrawVerticesOp(GrColor color, GrPrimitiveType primitiveType,
- const SkMatrix& viewMatrix, const SkPoint* positions,
- int vertexCount, const uint16_t* indices, int indexCount,
- const uint32_t* colors, const SkPoint* localCoords,
- const SkRect& bounds,
- GrRenderTargetContext::ColorArrayType colorArrayType)
- : INHERITED(ClassID()) {
- SkASSERT(positions);
+GrDrawVerticesOp::GrDrawVerticesOp(sk_sp<SkVertices> vertices, GrPrimitiveType primitiveType,
+ GrColor color,
+ GrRenderTargetContext::ColorArrayType colorArrayType,
+ const SkMatrix& viewMatrix, uint32_t flags)
+ : INHERITED(ClassID()), fColorArrayType(colorArrayType) {
+ SkASSERT(vertices);
+
+ fVertexCount = vertices->vertexCount();
+ fIndexCount = vertices->indexCount();
+ fPrimitiveType = primitiveType;
Mesh& mesh = fMeshes.push_back();
mesh.fColor = color;
mesh.fViewMatrix = viewMatrix;
+ mesh.fVertices = std::move(vertices);
+ mesh.fFlags = flags;
- mesh.fPositions.append(vertexCount, positions);
- if (indices) {
- mesh.fIndices.append(indexCount, indices);
+ fFlags = 0;
+ if (mesh.hasPerVertexColors()) {
+ fFlags |= kRequiresPerVertexColors_Flag;
}
-
- if (colors) {
- fVariableColor = true;
- mesh.fColors.append(vertexCount, colors);
- fColorArrayType = colorArrayType;
- } else {
- fVariableColor = false;
- // When we tessellate we will fill a color array with the GrColor value passed above as
- // 'color'.
- fColorArrayType = GrRenderTargetContext::ColorArrayType::kPremulGrColor;
+ if (mesh.hasExplicitLocalCoords()) {
+ fFlags |= kAnyMeshHasExplicitLocalCoords;
}
- if (localCoords) {
- mesh.fLocalCoords.append(vertexCount, localCoords);
- }
- fVertexCount = vertexCount;
- fIndexCount = indexCount;
- fPrimitiveType = primitiveType;
-
IsZeroArea zeroArea;
if (GrIsPrimTypeLines(primitiveType) || kPoints_GrPrimitiveType == primitiveType) {
zeroArea = IsZeroArea::kYes;
} else {
zeroArea = IsZeroArea::kNo;
}
- this->setBounds(bounds, HasAABloat::kNo, zeroArea);
+ this->setTransformedBounds(mesh.fVertices->bounds(), viewMatrix, HasAABloat::kNo, zeroArea);
}
void GrDrawVerticesOp::getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const {
- if (fVariableColor) {
+ if (this->requiresPerVertexColors()) {
input->pipelineColorInput()->setUnknownFourComponents();
} else {
input->pipelineColorInput()->setKnownFourComponents(fMeshes[0].fColor);
@@ -99,25 +111,58 @@ void GrDrawVerticesOp::applyPipelineOptimizations(const GrPipelineOptimizations&
GrColor overrideColor;
if (optimizations.getOverrideColorIfSet(&overrideColor)) {
fMeshes[0].fColor = overrideColor;
- fMeshes[0].fColors.reset();
- fVariableColor = false;
+ fMeshes[0].fFlags |= SkCanvas::kIgnoreColors_VerticesFlag;
+ fFlags &= ~kRequiresPerVertexColors_Flag;
fColorArrayType = GrRenderTargetContext::ColorArrayType::kPremulGrColor;
}
- if (!(fPipelineNeedsLocalCoords = optimizations.readsLocalCoords())) {
- fMeshes[0].fLocalCoords.reset();
+ if (optimizations.readsLocalCoords()) {
+ fFlags |= kPipelineRequiresLocalCoords_Flag;
+ } else {
+ fFlags |= SkCanvas::kIgnoreTexCoords_VerticesFlag;
+ fFlags &= ~kAnyMeshHasExplicitLocalCoords;
}
}
+sk_sp<GrGeometryProcessor> GrDrawVerticesOp::makeGP(bool* hasColorAttribute,
+ bool* hasLocalCoordAttribute) const {
+ using namespace GrDefaultGeoProcFactory;
+ LocalCoords::Type localCoordsType;
+ if (this->pipelineRequiresLocalCoords()) {
+ // If we have multiple view matrices we will transform the positions into device space. We
+ // must then also provide untransformed positions as local coords.
+ if (this->anyMeshHasExplicitLocalCoords() || this->hasMultipleViewMatrices()) {
+ *hasLocalCoordAttribute = true;
+ localCoordsType = LocalCoords::kHasExplicit_Type;
+ } else {
+ *hasLocalCoordAttribute = false;
+ localCoordsType = LocalCoords::kUsePosition_Type;
+ }
+ } else {
+ localCoordsType = LocalCoords::kUnused_Type;
+ *hasLocalCoordAttribute = false;
+ }
+
+ Color color(fMeshes[0].fColor);
+ if (this->requiresPerVertexColors()) {
+ color.fType = (fColorArrayType == GrRenderTargetContext::ColorArrayType::kPremulGrColor)
+ ? Color::kPremulGrColorAttribute_Type
+ : Color::kUnpremulSkColorAttribute_Type;
+ *hasColorAttribute = true;
+ } else {
+ *hasColorAttribute = false;
+ };
+ const SkMatrix& vm = this->hasMultipleViewMatrices() ? SkMatrix::I() : fMeshes[0].fViewMatrix;
+ return GrDefaultGeoProcFactory::Make(color, Coverage::kSolid_Type, localCoordsType, vm);
+}
+
void GrDrawVerticesOp::onPrepareDraws(Target* target) const {
- bool clientLocalCoords = !fMeshes[0].fLocalCoords.isEmpty();
- bool hasLocalCoordAttribute;
- sk_sp<GrGeometryProcessor> gp =
- make_gp(clientLocalCoords, fPipelineNeedsLocalCoords, fColorArrayType,
- fMultipleViewMatrices, fMeshes[0].fViewMatrix, &hasLocalCoordAttribute);
+ bool hasColorAttribute;
+ bool hasLocalCoordsAttribute;
+ sk_sp<GrGeometryProcessor> gp = this->makeGP(&hasColorAttribute, &hasLocalCoordsAttribute);
size_t vertexStride = gp->getVertexStride();
- SkASSERT(vertexStride ==
- sizeof(SkPoint) + (hasLocalCoordAttribute ? sizeof(SkPoint) : 0) + sizeof(uint32_t));
+ SkASSERT(vertexStride == sizeof(SkPoint) + (hasColorAttribute ? sizeof(uint32_t) : 0) +
+ (hasLocalCoordsAttribute ? sizeof(SkPoint) : 0));
int instanceCount = fMeshes.count();
@@ -135,7 +180,7 @@ void GrDrawVerticesOp::onPrepareDraws(Target* target) const {
int firstIndex = 0;
uint16_t* indices = nullptr;
- if (!fMeshes[0].fIndices.isEmpty()) {
+ if (this->isIndexed()) {
indices = target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex);
if (!indices) {
@@ -148,34 +193,39 @@ void GrDrawVerticesOp::onPrepareDraws(Target* target) const {
int vertexOffset = 0;
for (int i = 0; i < instanceCount; i++) {
const Mesh& mesh = fMeshes[i];
- // Currently we require all meshes to either have explicit local coords or not, though it
- // wouldn't be hard to allow them to mix.
- SkASSERT(clientLocalCoords == !mesh.fLocalCoords.isEmpty());
if (indices) {
- for (int j = 0; j < mesh.fIndices.count(); ++j, ++indexOffset) {
- *(indices + indexOffset) = mesh.fIndices[j] + vertexOffset;
+ int indexCount = mesh.fVertices->indexCount();
+ for (int j = 0; j < indexCount; ++j, ++indexOffset) {
+ *(indices + indexOffset) = mesh.fVertices->indices()[j] + vertexOffset;
}
}
static constexpr size_t kColorOffset = sizeof(SkPoint);
- static constexpr size_t kLocalCoordOffset = kColorOffset + sizeof(uint32_t);
-
- for (int j = 0; j < mesh.fPositions.count(); ++j) {
- if (fMultipleViewMatrices) {
- mesh.fViewMatrix.mapPoints(((SkPoint*)verts), &mesh.fPositions[j], 1);
+ size_t localCoordOffset =
+ hasColorAttribute ? kColorOffset + sizeof(uint32_t) : kColorOffset;
+
+ int vertexCount = mesh.fVertices->vertexCount();
+ const SkPoint* positions = mesh.fVertices->positions();
+ const SkColor* colors = mesh.fVertices->colors();
+ const SkPoint* localCoords = mesh.fVertices->texCoords();
+ for (int j = 0; j < vertexCount; ++j) {
+ if (this->hasMultipleViewMatrices()) {
+ mesh.fViewMatrix.mapPoints(((SkPoint*)verts), &positions[j], 1);
} else {
- *((SkPoint*)verts) = mesh.fPositions[j];
+ *((SkPoint*)verts) = positions[j];
}
- if (mesh.fColors.isEmpty()) {
- *(uint32_t*)((intptr_t)verts + kColorOffset) = mesh.fColor;
- } else {
- *(uint32_t*)((intptr_t)verts + kColorOffset) = mesh.fColors[j];
+ if (hasColorAttribute) {
+ if (mesh.hasPerVertexColors()) {
+ *(uint32_t*)((intptr_t)verts + kColorOffset) = colors[j];
+ } else {
+ *(uint32_t*)((intptr_t)verts + kColorOffset) = mesh.fColor;
+ }
}
- if (hasLocalCoordAttribute) {
- if (clientLocalCoords) {
- *(SkPoint*)((intptr_t)verts + kLocalCoordOffset) = mesh.fLocalCoords[j];
+ if (hasLocalCoordsAttribute) {
+ if (mesh.hasExplicitLocalCoords()) {
+ *(SkPoint*)((intptr_t)verts + localCoordOffset) = localCoords[j];
} else {
- *(SkPoint*)((intptr_t)verts + kLocalCoordOffset) = mesh.fPositions[j];
+ *(SkPoint*)((intptr_t)verts + localCoordOffset) = positions[j];
}
}
verts = (void*)((intptr_t)verts + vertexStride);
@@ -206,14 +256,7 @@ bool GrDrawVerticesOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
return false;
}
-
- if (fMeshes[0].fIndices.isEmpty() != that->fMeshes[0].fIndices.isEmpty()) {
- return false;
- }
-
- // This could be relaxed by using positions for the one that doesn't already have explicit
- // local coordindates.
- if (fMeshes[0].fLocalCoords.isEmpty() != that->fMeshes[0].fLocalCoords.isEmpty()) {
+ if (fMeshes[0].fVertices->isIndexed() != that->fMeshes[0].fVertices->isIndexed()) {
return false;
}
@@ -221,22 +264,21 @@ bool GrDrawVerticesOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
return false;
}
- if (fIndexCount + that->fIndexCount > SK_MaxU16) {
+ if (fVertexCount + that->fVertexCount > SK_MaxU16) {
return false;
}
- if (!fVariableColor) {
- if (that->fVariableColor || that->fMeshes[0].fColor != fMeshes[0].fColor) {
- fVariableColor = true;
- }
- }
+ // If either op required explicit local coords or per-vertex colors the combined mesh does. Same
+ // with multiple view matrices.
+ fFlags |= that->fFlags;
+ if (!this->requiresPerVertexColors() && this->fMeshes[0].fColor != that->fMeshes[0].fColor) {
+ fFlags |= kRequiresPerVertexColors_Flag;
+ }
// Check whether we are about to acquire a mesh with a different view matrix.
- if (!fMultipleViewMatrices) {
- if (that->fMultipleViewMatrices ||
- !fMeshes[0].fViewMatrix.cheapEqualTo(that->fMeshes[0].fViewMatrix)) {
- fMultipleViewMatrices = true;
- }
+ if (!this->hasMultipleViewMatrices() &&
+ !this->fMeshes[0].fViewMatrix.cheapEqualTo(that->fMeshes[0].fViewMatrix)) {
+ fFlags |= kHasMultipleViewMatrices_Flag;
}
fMeshes.push_back_n(that->fMeshes.count(), that->fMeshes.begin());
@@ -348,11 +390,9 @@ DRAW_OP_TEST_DEFINE(VerticesOp) {
SkDEBUGCODE(bool result =) bounds.setBoundsCheck(positions.begin(), vertexCount);
SkASSERT(result);
- viewMatrix.mapRect(&bounds);
-
GrColor color = GrRandomColor(random);
return GrDrawVerticesOp::Make(color, type, viewMatrix, positions.begin(), vertexCount,
- indices.begin(), hasIndices ? vertexCount : 0, colors.begin(),
+ indices.begin(), hasIndices ? indices.count() : 0, colors.begin(),
texCoords.begin(), bounds, colorArrayType);
}
diff --git a/src/gpu/ops/GrDrawVerticesOp.h b/src/gpu/ops/GrDrawVerticesOp.h
index a2560af774..1cd3334396 100644
--- a/src/gpu/ops/GrDrawVerticesOp.h
+++ b/src/gpu/ops/GrDrawVerticesOp.h
@@ -15,46 +15,62 @@
#include "SkMatrix.h"
#include "SkRect.h"
#include "SkTDArray.h"
+#include "SkVertices.h"
class GrOpFlushState;
+class SkVertices;
struct GrInitInvariantOutput;
class GrDrawVerticesOp final : public GrMeshDrawOp {
public:
DEFINE_OP_CLASS_ID
+ /**
+ * The 'color' param is used if the 'colors' array is null. 'bounds' is the bounds of the
+ * 'positions' array (in local space prior to application of 'viewMatrix'). If 'indices' is null
+ * then 'indexCnt' must be zero and vice versa. In this case the vertices are indexed as 0, 1,
+ * ..., 'vertexCount' - 1. 'localCoords' are optional and if null the vertex positions are used
+ * as local coords. 'colorArrayType' specifies whether the colors are premul GrColors or
+ * unpremul SkColors.
+ */
static std::unique_ptr<GrDrawOp> Make(GrColor color, GrPrimitiveType primitiveType,
const SkMatrix& viewMatrix, const SkPoint* positions,
int vertexCount, const uint16_t* indices, int indexCount,
const uint32_t* colors, const SkPoint* localCoords,
const SkRect& bounds,
- GrRenderTargetContext::ColorArrayType colorArrayType) {
- return std::unique_ptr<GrDrawOp>(new GrDrawVerticesOp(
- color, primitiveType, viewMatrix, positions, vertexCount, indices, indexCount,
- colors, localCoords, bounds, colorArrayType));
- }
+ GrRenderTargetContext::ColorArrayType colorArrayType);
+
+ /**
+ * Draw a SkVertices. The GrColor param is used if the vertices lack per-vertex color or 'flags'
+ * indicates that the per-vertex color should be ignored. The 'flags' options are those
+ * specified by SkCanvas::VerticesFlags. If the vertices lack local coords or 'flags' indicates
+ * that they should be ignored then the vertex positions are used as local coords.
+ */
+ static std::unique_ptr<GrDrawOp> Make(GrColor color, sk_sp<SkVertices>,
+ const SkMatrix& viewMatrix, uint32_t flags);
const char* name() const override { return "DrawVerticesOp"; }
SkString dumpInfo() const override {
SkString string;
- string.appendf("PrimType: %d, VarColor: %d, VCount: %d, ICount: %d\n", fPrimitiveType,
- fVariableColor, fVertexCount, fIndexCount);
+ string.appendf("PrimType: %d, MeshCount %d, VCount: %d, ICount: %d\n", fPrimitiveType,
+ fMeshes.count(), fVertexCount, fIndexCount);
string.append(DumpPipelineInfo(*this->pipeline()));
string.append(INHERITED::dumpInfo());
return string;
}
private:
- GrDrawVerticesOp(GrColor color, GrPrimitiveType primitiveType, const SkMatrix& viewMatrix,
- const SkPoint* positions, int vertexCount, const uint16_t* indices,
- int indexCount, const uint32_t* colors, const SkPoint* localCoords,
- const SkRect& bounds, GrRenderTargetContext::ColorArrayType colorArrayType);
+ GrDrawVerticesOp(sk_sp<SkVertices>, GrPrimitiveType, GrColor,
+ GrRenderTargetContext::ColorArrayType, const SkMatrix& viewMatrix,
+ uint32_t flags = 0);
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override;
void applyPipelineOptimizations(const GrPipelineOptimizations&) override;
void onPrepareDraws(Target*) const override;
+ sk_sp<GrGeometryProcessor> makeGP(bool* hasColorAttribute, bool* hasLocalCoordAttribute) const;
+
GrPrimitiveType primitiveType() const { return fPrimitiveType; }
bool combinablePrimitive() const {
return kTriangles_GrPrimitiveType == fPrimitiveType ||
@@ -65,20 +81,55 @@ private:
bool onCombineIfPossible(GrOp* t, const GrCaps&) override;
struct Mesh {
- GrColor fColor; // Only used if there are no per-vertex colors
- SkTDArray<SkPoint> fPositions;
- SkTDArray<uint16_t> fIndices;
- SkTDArray<uint32_t> fColors;
- SkTDArray<SkPoint> fLocalCoords;
+ GrColor fColor; // Used if this->hasPerVertexColors() is false.
+ sk_sp<SkVertices> fVertices;
SkMatrix fViewMatrix;
+ uint32_t fFlags;
+
+ bool hasExplicitLocalCoords() const {
+ return fVertices->hasTexCoords() && !(SkCanvas::kIgnoreTexCoords_VerticesFlag & fFlags);
+ }
+
+ bool hasPerVertexColors() const {
+ return fVertices->hasColors() && !(SkCanvas::kIgnoreColors_VerticesFlag & fFlags);
+ }
+ };
+
+ bool isIndexed() const {
+ // Consistency enforced in onCombineIfPossible.
+ return fMeshes[0].fVertices->isIndexed();
+ }
+
+ bool requiresPerVertexColors() const {
+ return SkToBool(kRequiresPerVertexColors_Flag & fFlags);
+ }
+
+ bool anyMeshHasExplicitLocalCoords() const {
+ return SkToBool(kAnyMeshHasExplicitLocalCoords & fFlags);
+ }
+
+ bool pipelineRequiresLocalCoords() const {
+ return SkToBool(kPipelineRequiresLocalCoords_Flag & fFlags);
+ }
+
+ bool hasMultipleViewMatrices() const {
+ return SkToBool(kHasMultipleViewMatrices_Flag & fFlags);
+ }
+
+ enum Flags {
+ kRequiresPerVertexColors_Flag = 0x1,
+ kAnyMeshHasExplicitLocalCoords = 0x2,
+ kPipelineRequiresLocalCoords_Flag = 0x4,
+ kHasMultipleViewMatrices_Flag = 0x8
+
};
+ // GrPrimitiveType is more expressive than fVertices.mode() so it is used instead and we ignore
+ // the SkVertices mode (though fPrimitiveType may have been inferred from it).
GrPrimitiveType fPrimitiveType;
- bool fVariableColor;
+ uint32_t fFlags;
int fVertexCount;
int fIndexCount;
- bool fMultipleViewMatrices = false;
- bool fPipelineNeedsLocalCoords;
GrRenderTargetContext::ColorArrayType fColorArrayType;
SkSTArray<1, Mesh, true> fMeshes;
diff --git a/tools/debugger/SkDebugCanvas.h b/tools/debugger/SkDebugCanvas.h
index 57bf99874a..d25fe40274 100644
--- a/tools/debugger/SkDebugCanvas.h
+++ b/tools/debugger/SkDebugCanvas.h
@@ -16,6 +16,7 @@
#include "SkPicture.h"
#include "SkString.h"
#include "SkTArray.h"
+#include "SkVertices.h"
#include "UrlDataManager.h"
class GrAuditTrail;
@@ -229,6 +230,10 @@ protected:
const SkColor colors[], SkBlendMode,
const uint16_t indices[], int indexCount,
const SkPaint&) override;
+ void onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint,
+ uint32_t flags) override {
+ this->onDrawVerticesObjectFallback(std::move(vertices), mode, paint, flags);
+ }
void onDrawPath(const SkPath&, const SkPaint&) override;
void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;
void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,