diff options
author | Brian Salomon <bsalomon@google.com> | 2017-02-06 09:41:10 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-02-06 17:52:22 +0000 |
commit | 199fb875c5e63c13233209e89b943c7ac7ab6665 (patch) | |
tree | cdcf5bf1edd44036fa7e7900e65339f0e04cb4a0 /src/gpu | |
parent | abc88d26365efa14b58d26ca3b8fbfb58a7dcbad (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.cpp | 26 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetOpList.cpp | 4 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 94 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.h | 2 | ||||
-rw-r--r-- | src/gpu/SkGrPriv.h | 16 | ||||
-rw-r--r-- | src/gpu/ops/GrDrawVerticesOp.cpp | 258 | ||||
-rw-r--r-- | src/gpu/ops/GrDrawVerticesOp.h | 89 |
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; |