aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2017-02-06 09:41:10 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-02-06 17:52:22 +0000
commit199fb875c5e63c13233209e89b943c7ac7ab6665 (patch)
treecdcf5bf1edd44036fa7e7900e65339f0e04cb4a0 /src/gpu
parentabc88d26365efa14b58d26ca3b8fbfb58a7dcbad (diff)
Add refcnt'ed immutable vertices class for SkCanvas::drawVertices.
Change-Id: I44a62f5efc674d0adbbf4a33690c3ded9fab3803 Reviewed-on: https://skia-review.googlesource.com/8040 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src/gpu')
-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
7 files changed, 318 insertions, 171 deletions
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;