aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--docs/SkCanvas_Reference.bmh2
-rw-r--r--include/core/SkCanvas.h4
-rw-r--r--include/core/SkVertices.h30
-rw-r--r--site/user/api/SkCanvas_Reference.md2
-rw-r--r--src/core/SkCanvas.cpp2
-rw-r--r--src/core/SkVertices.cpp26
-rw-r--r--src/gpu/ops/GrDrawVerticesOp.cpp194
-rw-r--r--src/gpu/ops/GrDrawVerticesOp.h33
-rw-r--r--tools/viewer/NIMASlide.cpp38
9 files changed, 265 insertions, 66 deletions
diff --git a/docs/SkCanvas_Reference.bmh b/docs/SkCanvas_Reference.bmh
index cfeef6331b..bfd3e9d7d1 100644
--- a/docs/SkCanvas_Reference.bmh
+++ b/docs/SkCanvas_Reference.bmh
@@ -5772,6 +5772,7 @@ contains Shader, Blend_Mode mode combines Vertices_Colors with Shader.
The first element of bones should be an object to world space transformation matrix that
will be applied before performing mesh deformations. If no such transformation is needed,
it should be the identity matrix.
+boneCount must be at most 100, and thus the size of bones should be at most 100.
#Param vertices triangle mesh to draw ##
#Param bones bone matrix data ##
@@ -5821,6 +5822,7 @@ contains Shader, Blend_Mode mode combines Vertices_Colors with Shader.
The first element of bones should be an object to world space transformation matrix that
will be applied before performing mesh deformations. If no such transformation is needed,
it should be the identity matrix.
+boneCount must be at most 100, and thus the size of bones should be at most 100.
#Param vertices triangle mesh to draw ##
#Param bones bone matrix data ##
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index 90e51e9b0e..abac335a0c 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -6,7 +6,7 @@
*/
/* Generated by tools/bookmaker from include/core/SkCanvas.h and docs/SkCanvas_Reference.bmh
- on 2018-07-02 10:27:08. Additional documentation and examples can be found at:
+ on 2018-07-03 11:34:22. Additional documentation and examples can be found at:
https://skia.org/user/api/SkCanvas_Reference
You may edit either file directly. Structural changes to public interfaces require
@@ -2156,6 +2156,7 @@ public:
The first element of bones should be an object to world space transformation matrix that
will be applied before performing mesh deformations. If no such transformation is needed,
it should be the identity matrix.
+ boneCount must be at most 100, and thus the size of bones should be at most 100.
@param vertices triangle mesh to draw
@param bones bone matrix data
@@ -2173,6 +2174,7 @@ public:
The first element of bones should be an object to world space transformation matrix that
will be applied before performing mesh deformations. If no such transformation is needed,
it should be the identity matrix.
+ boneCount must be at most 100, and thus the size of bones should be at most 100.
@param vertices triangle mesh to draw
@param bones bone matrix data
diff --git a/include/core/SkVertices.h b/include/core/SkVertices.h
index 6c4fb390d0..9c1300b0a5 100644
--- a/include/core/SkVertices.h
+++ b/include/core/SkVertices.h
@@ -55,14 +55,16 @@ public:
const BoneIndices boneIndices[],
const BoneWeights boneWeights[],
int indexCount,
- const uint16_t indices[]);
+ const uint16_t indices[],
+ bool isVolatile = true);
static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
const SkPoint positions[],
const SkPoint texs[],
const SkColor colors[],
const BoneIndices boneIndices[],
- const BoneWeights boneWeights[]) {
+ const BoneWeights boneWeights[],
+ bool isVolatile = true) {
return MakeCopy(mode,
vertexCount,
positions,
@@ -71,7 +73,8 @@ public:
boneIndices,
boneWeights,
0,
- nullptr);
+ nullptr,
+ isVolatile);
}
static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
@@ -79,7 +82,8 @@ public:
const SkPoint texs[],
const SkColor colors[],
int indexCount,
- const uint16_t indices[]) {
+ const uint16_t indices[],
+ bool isVolatile = true) {
return MakeCopy(mode,
vertexCount,
positions,
@@ -88,14 +92,16 @@ public:
nullptr,
nullptr,
indexCount,
- indices);
+ indices,
+ isVolatile);
}
static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
const SkPoint positions[],
const SkPoint texs[],
- const SkColor colors[]) {
- return MakeCopy(mode, vertexCount, positions, texs, colors, nullptr, nullptr);
+ const SkColor colors[],
+ bool isVolatile = true) {
+ return MakeCopy(mode, vertexCount, positions, texs, colors, nullptr, nullptr, isVolatile);
}
struct Sizes;
@@ -104,6 +110,7 @@ public:
kHasTexCoords_BuilderFlag = 1 << 0,
kHasColors_BuilderFlag = 1 << 1,
kHasBones_BuilderFlag = 1 << 2,
+ kIsNonVolatile_BuilderFlag = 1 << 3,
};
class Builder {
public:
@@ -114,6 +121,7 @@ public:
// if the builder is invalid, these will return 0
int vertexCount() const;
int indexCount() const;
+ bool isVolatile() const;
SkPoint* positions();
SkPoint* texCoords(); // returns null if there are no texCoords
SkColor* colors(); // returns null if there are no colors
@@ -125,9 +133,9 @@ public:
sk_sp<SkVertices> detach();
private:
- Builder(VertexMode mode, int vertexCount, int indexCount, const Sizes&);
+ Builder(VertexMode mode, int vertexCount, int indexCount, bool isVolatile, const Sizes&);
- void init(VertexMode mode, int vertexCount, int indexCount, const Sizes&);
+ void init(VertexMode mode, int vertexCount, int indexCount, bool isVolatile, const Sizes&);
// holds a partially complete object. only completed in detach()
sk_sp<SkVertices> fVertices;
@@ -158,6 +166,8 @@ public:
int indexCount() const { return fIndexCnt; }
const uint16_t* indices() const { return fIndices; }
+ bool isVolatile() const { return fIsVolatile; }
+
// returns approximate byte size of the vertices object
size_t approximateSize() const;
@@ -199,6 +209,8 @@ private:
int fVertexCnt;
int fIndexCnt;
+ bool fIsVolatile;
+
VertexMode fMode;
// below here is where the actual array data is stored.
};
diff --git a/site/user/api/SkCanvas_Reference.md b/site/user/api/SkCanvas_Reference.md
index df15f490f0..73dfc5d3bf 100644
--- a/site/user/api/SkCanvas_Reference.md
+++ b/site/user/api/SkCanvas_Reference.md
@@ -6537,6 +6537,7 @@ contains <a href='undocumented#Shader'>Shader</a>, <a href='SkBlendMode_Referenc
The first element of <a href='#SkCanvas_drawVertices_3_bones'>bones</a> should be an object to world space transformation matrix that
will be applied before performing mesh deformations. If no such transformation is needed,
it should be the identity matrix.
+<a href='#SkCanvas_drawVertices_3_boneCount'>boneCount</a> must be at most 100, and thus the size of <a href='#SkCanvas_drawVertices_3_bones'>bones</a> should be at most 100.
### Parameters
@@ -6581,6 +6582,7 @@ contains <a href='undocumented#Shader'>Shader</a>, <a href='SkBlendMode_Referenc
The first element of <a href='#SkCanvas_drawVertices_4_bones'>bones</a> should be an object to world space transformation matrix that
will be applied before performing mesh deformations. If no such transformation is needed,
it should be the identity matrix.
+<a href='#SkCanvas_drawVertices_4_boneCount'>boneCount</a> must be at most 100, and thus the size of <a href='#SkCanvas_drawVertices_4_bones'>bones</a> should be at most 100.
### Parameters
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 8314f803f0..45bbc64308 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1715,6 +1715,7 @@ void SkCanvas::drawVertices(const sk_sp<SkVertices>& vertices, const SkMatrix* b
SkBlendMode mode, const SkPaint& paint) {
TRACE_EVENT0("skia", TRACE_FUNC);
RETURN_ON_NULL(vertices);
+ SkASSERT(boneCount <= 100);
this->onDrawVerticesObject(vertices.get(), bones, boneCount, mode, paint);
}
@@ -1722,6 +1723,7 @@ void SkCanvas::drawVertices(const SkVertices* vertices, const SkMatrix* bones, i
SkBlendMode mode, const SkPaint& paint) {
TRACE_EVENT0("skia", TRACE_FUNC);
RETURN_ON_NULL(vertices);
+ SkASSERT(boneCount <= 100);
this->onDrawVerticesObject(vertices, bones, boneCount, mode, paint);
}
diff --git a/src/core/SkVertices.cpp b/src/core/SkVertices.cpp
index 04db0d35fb..97a136c548 100644
--- a/src/core/SkVertices.cpp
+++ b/src/core/SkVertices.cpp
@@ -95,16 +95,17 @@ SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount,
bool hasTexs = SkToBool(builderFlags & SkVertices::kHasTexCoords_BuilderFlag);
bool hasColors = SkToBool(builderFlags & SkVertices::kHasColors_BuilderFlag);
bool hasBones = SkToBool(builderFlags & SkVertices::kHasBones_BuilderFlag);
- this->init(mode, vertexCount, indexCount,
+ bool isVolatile = !SkToBool(builderFlags & SkVertices::kIsNonVolatile_BuilderFlag);
+ this->init(mode, vertexCount, indexCount, isVolatile,
SkVertices::Sizes(mode, vertexCount, indexCount, hasTexs, hasColors, hasBones));
}
-SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount,
+SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount, bool isVolatile,
const SkVertices::Sizes& sizes) {
- this->init(mode, vertexCount, indexCount, sizes);
+ this->init(mode, vertexCount, indexCount, isVolatile, sizes);
}
-void SkVertices::Builder::init(VertexMode mode, int vertexCount, int indexCount,
+void SkVertices::Builder::init(VertexMode mode, int vertexCount, int indexCount, bool isVolatile,
const SkVertices::Sizes& sizes) {
if (!sizes.isValid()) {
return; // fVertices will already be null
@@ -128,6 +129,7 @@ void SkVertices::Builder::init(VertexMode mode, int vertexCount, int indexCount,
fVertices->fIndices = sizes.fISize ? (uint16_t*)ptr : nullptr;
fVertices->fVertexCnt = vertexCount;
fVertices->fIndexCnt = indexCount;
+ fVertices->fIsVolatile = isVolatile;
fVertices->fMode = mode;
// We defer assigning fBounds and fUniqueID until detach() is called
@@ -171,6 +173,10 @@ int SkVertices::Builder::indexCount() const {
return fVertices ? fVertices->indexCount() : 0;
}
+bool SkVertices::Builder::isVolatile() const {
+ return fVertices ? fVertices->isVolatile() : true;
+}
+
SkPoint* SkVertices::Builder::positions() {
return fVertices ? const_cast<SkPoint*>(fVertices->positions()) : nullptr;
}
@@ -208,7 +214,8 @@ sk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount,
const SkColor colors[],
const BoneIndices boneIndices[],
const BoneWeights boneWeights[],
- int indexCount, const uint16_t indices[]) {
+ int indexCount, const uint16_t indices[],
+ bool isVolatile) {
SkASSERT((!boneIndices && !boneWeights) || (boneIndices && boneWeights));
Sizes sizes(mode,
vertexCount,
@@ -220,7 +227,7 @@ sk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount,
return nullptr;
}
- Builder builder(mode, vertexCount, indexCount, sizes);
+ Builder builder(mode, vertexCount, indexCount, isVolatile, sizes);
SkASSERT(builder.isValid());
sk_careful_memcpy(builder.positions(), pos, sizes.fVSize);
@@ -255,6 +262,7 @@ size_t SkVertices::approximateSize() const {
#define kHasTexs_Mask 0x100
#define kHasColors_Mask 0x200
#define kHasBones_Mask 0x400
+#define kIsNonVolatile_Mask 0x800
#define kHeaderSize (3 * sizeof(uint32_t))
sk_sp<SkData> SkVertices::encode() const {
@@ -270,6 +278,9 @@ sk_sp<SkData> SkVertices::encode() const {
if (this->hasBones()) {
packed |= kHasBones_Mask;
}
+ if (!this->isVolatile()) {
+ packed |= kIsNonVolatile_Mask;
+ }
Sizes sizes(fMode,
fVertexCnt,
@@ -318,6 +329,7 @@ sk_sp<SkVertices> SkVertices::Decode(const void* data, size_t length) {
const bool hasTexs = SkToBool(packed & kHasTexs_Mask);
const bool hasColors = SkToBool(packed & kHasColors_Mask);
const bool hasBones = SkToBool(packed & kHasBones_Mask);
+ const bool isVolatile = !SkToBool(packed & kIsNonVolatile_Mask);
Sizes sizes(mode, vertexCount, indexCount, hasTexs, hasColors, hasBones);
if (!sizes.isValid()) {
return nullptr;
@@ -327,7 +339,7 @@ sk_sp<SkVertices> SkVertices::Decode(const void* data, size_t length) {
return nullptr;
}
- Builder builder(mode, vertexCount, indexCount, sizes);
+ Builder builder(mode, vertexCount, indexCount, isVolatile, sizes);
reader.read(builder.positions(), sizes.fVSize);
reader.read(builder.texCoords(), sizes.fTSize);
diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp
index ad5aba2b2c..7cfb3a2efa 100644
--- a/src/gpu/ops/GrDrawVerticesOp.cpp
+++ b/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -10,6 +10,7 @@
#include "GrDefaultGeoProcFactory.h"
#include "GrOpFlushState.h"
#include "SkGr.h"
+#include "SkRectPriv.h"
std::unique_ptr<GrDrawOp> GrDrawVerticesOp::Make(GrContext* context,
GrPaint&& paint,
@@ -53,7 +54,7 @@ GrDrawVerticesOp::GrDrawVerticesOp(const Helper::MakeArgs& helperArgs, GrColor c
fFlags |= kRequiresPerVertexColors_Flag;
}
if (mesh.hasExplicitLocalCoords()) {
- fFlags |= kAnyMeshHasExplicitLocalCoords;
+ fFlags |= kAnyMeshHasExplicitLocalCoords_Flag;
}
IsZeroArea zeroArea;
@@ -62,7 +63,11 @@ GrDrawVerticesOp::GrDrawVerticesOp(const Helper::MakeArgs& helperArgs, GrColor c
} else {
zeroArea = IsZeroArea::kNo;
}
- this->setTransformedBounds(mesh.fVertices->bounds(), viewMatrix, HasAABloat::kNo, zeroArea);
+
+ this->setTransformedBounds(mesh.fVertices->bounds(),
+ mesh.fViewMatrix,
+ HasAABloat::kNo,
+ zeroArea);
}
SkString GrDrawVerticesOp::dumpInfo() const {
@@ -96,7 +101,7 @@ GrDrawOp::RequiresDstTexture GrDrawVerticesOp::finalize(const GrCaps& caps,
}
if (!fHelper.usesLocalCoords()) {
fMeshes[0].fIgnoreTexCoords = true;
- fFlags &= ~kAnyMeshHasExplicitLocalCoords;
+ fFlags &= ~kAnyMeshHasExplicitLocalCoords_Flag;
}
return result;
}
@@ -132,26 +137,39 @@ sk_sp<GrGeometryProcessor> GrDrawVerticesOp::makeGP(bool* hasColorAttribute,
} else {
*hasColorAttribute = false;
};
+
const SkMatrix& vm = this->hasMultipleViewMatrices() ? SkMatrix::I() : fMeshes[0].fViewMatrix;
- return GrDefaultGeoProcFactory::Make(color, Coverage::kSolid_Type, localCoordsType, vm);
+
+ return GrDefaultGeoProcFactory::Make(color,
+ Coverage::kSolid_Type,
+ localCoordsType,
+ vm);
}
void GrDrawVerticesOp::onPrepareDraws(Target* target) {
+ if (fMeshes[0].fVertices->isVolatile()) {
+ this->drawVolatile(target);
+ } else {
+ this->drawNonVolatile(target);
+ }
+}
+
+void GrDrawVerticesOp::drawVolatile(Target* target) {
bool hasColorAttribute;
bool hasLocalCoordsAttribute;
- sk_sp<GrGeometryProcessor> gp = this->makeGP(&hasColorAttribute, &hasLocalCoordsAttribute);
+ sk_sp<GrGeometryProcessor> gp = this->makeGP(&hasColorAttribute,
+ &hasLocalCoordsAttribute);
- size_t vertexStride = sizeof(SkPoint) + (hasColorAttribute ? sizeof(uint32_t) : 0) +
+ // Calculate the stride.
+ size_t vertexStride = sizeof(SkPoint) +
+ (hasColorAttribute ? sizeof(uint32_t) : 0) +
(hasLocalCoordsAttribute ? sizeof(SkPoint) : 0);
SkASSERT(vertexStride == gp->debugOnly_vertexStride());
- int instanceCount = fMeshes.count();
-
- const GrBuffer* vertexBuffer;
- int firstVertex;
-
+ // Allocate buffers.
+ const GrBuffer* vertexBuffer = nullptr;
+ int firstVertex = 0;
void* verts = target->makeVertexSpace(vertexStride, fVertexCount, &vertexBuffer, &firstVertex);
-
if (!verts) {
SkDebugf("Could not allocate vertices\n");
return;
@@ -159,29 +177,139 @@ void GrDrawVerticesOp::onPrepareDraws(Target* target) {
const GrBuffer* indexBuffer = nullptr;
int firstIndex = 0;
-
uint16_t* indices = nullptr;
if (this->isIndexed()) {
indices = target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex);
+ if (!indices) {
+ SkDebugf("Could not allocate indices\n");
+ return;
+ }
+ }
+
+ // Fill the buffers.
+ this->fillBuffers(hasColorAttribute,
+ hasLocalCoordsAttribute,
+ vertexStride,
+ verts,
+ indices);
+
+ // Draw the vertices.
+ this->drawVertices(target, gp.get(), vertexBuffer, firstVertex, indexBuffer, firstIndex);
+}
+
+void GrDrawVerticesOp::drawNonVolatile(Target* target) {
+ static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
+ bool hasColorAttribute;
+ bool hasLocalCoordsAttribute;
+ sk_sp<GrGeometryProcessor> gp = this->makeGP(&hasColorAttribute,
+ &hasLocalCoordsAttribute);
+
+ SkASSERT(fMeshes.count() == 1); // Non-volatile meshes should never combine.
+
+ // Get the resource provider.
+ GrResourceProvider* rp = target->resourceProvider();
+
+ // Generate keys for the buffers.
+ GrUniqueKey vertexKey, indexKey;
+ GrUniqueKey::Builder vertexKeyBuilder(&vertexKey, kDomain, 2);
+ GrUniqueKey::Builder indexKeyBuilder(&indexKey, kDomain, 2);
+ vertexKeyBuilder[0] = indexKeyBuilder[0] = fMeshes[0].fVertices->uniqueID();
+ vertexKeyBuilder[1] = 0;
+ indexKeyBuilder[1] = 1;
+ vertexKeyBuilder.finish();
+ indexKeyBuilder.finish();
+
+ // Try to grab data from the cache.
+ sk_sp<GrBuffer> vertexBuffer = rp->findByUniqueKey<GrBuffer>(vertexKey);
+ sk_sp<GrBuffer> indexBuffer = this->isIndexed() ?
+ rp->findByUniqueKey<GrBuffer>(indexKey) :
+ nullptr;
+
+ // Draw using the cached buffers if possible.
+ if (vertexBuffer && (!this->isIndexed() || indexBuffer)) {
+ this->drawVertices(target, gp.get(), vertexBuffer.get(), 0, indexBuffer.get(), 0);
+ return;
+ }
+
+ // Calculate the stride.
+ size_t vertexStride = sizeof(SkPoint) +
+ (hasColorAttribute ? sizeof(uint32_t) : 0) +
+ (hasLocalCoordsAttribute ? sizeof(SkPoint) : 0);
+ SkASSERT(vertexStride == gp->debugOnly_vertexStride());
+
+ // Allocate vertex buffer.
+ vertexBuffer.reset(rp->createBuffer(fVertexCount * vertexStride,
+ kVertex_GrBufferType,
+ kStatic_GrAccessPattern,
+ 0));
+ void* verts = vertexBuffer ? vertexBuffer->map() : nullptr;
+ if (!verts) {
+ SkDebugf("Could not allocate vertices\n");
+ return;
+ }
+
+ // Allocate index buffer.
+ uint16_t* indices = nullptr;
+ if (this->isIndexed()) {
+ indexBuffer.reset(rp->createBuffer(fIndexCount * sizeof(uint16_t),
+ kIndex_GrBufferType,
+ kStatic_GrAccessPattern,
+ 0));
+ indices = indexBuffer ? static_cast<uint16_t*>(indexBuffer->map()) : nullptr;
if (!indices) {
SkDebugf("Could not allocate indices\n");
return;
}
}
+ // Fill the buffers.
+ this->fillBuffers(hasColorAttribute,
+ hasLocalCoordsAttribute,
+ vertexStride,
+ verts,
+ indices);
+
+ // Unmap the buffers.
+ vertexBuffer->unmap();
+ if (indexBuffer) {
+ indexBuffer->unmap();
+ }
+
+ // Cache the buffers.
+ rp->assignUniqueKeyToResource(vertexKey, vertexBuffer.get());
+ rp->assignUniqueKeyToResource(indexKey, indexBuffer.get());
+
+ // Draw the vertices.
+ this->drawVertices(target, gp.get(), vertexBuffer.get(), 0, indexBuffer.get(), 0);
+}
+
+void GrDrawVerticesOp::fillBuffers(bool hasColorAttribute,
+ bool hasLocalCoordsAttribute,
+ size_t vertexStride,
+ void* verts,
+ uint16_t* indices) const {
+ int instanceCount = fMeshes.count();
+
+ // Copy data into the buffers.
int vertexOffset = 0;
// We have a fast case below for uploading the vertex data when the matrix is translate
- // only and there are colors but not local coords.
+ // only and there are colors but not local coords. Fast case does not apply when there are bone
+ // transformations.
bool fastAttrs = hasColorAttribute && !hasLocalCoordsAttribute;
for (int i = 0; i < instanceCount; i++) {
+ // Get each mesh.
const Mesh& mesh = fMeshes[i];
+
+ // Copy data into the index buffer.
if (indices) {
int indexCount = mesh.fVertices->indexCount();
for (int j = 0; j < indexCount; ++j) {
*indices++ = mesh.fVertices->indices()[j] + vertexOffset;
}
}
+
+ // Copy data into the vertex buffer.
int vertexCount = mesh.fVertices->vertexCount();
const SkPoint* positions = mesh.fVertices->positions();
const SkColor* colors = mesh.fVertices->colors();
@@ -190,6 +318,7 @@ void GrDrawVerticesOp::onPrepareDraws(Target* target) {
mesh.fViewMatrix.getType() <= SkMatrix::kTranslate_Mask) &&
mesh.hasPerVertexColors();
if (fastAttrs && fastMesh) {
+ // Fast case.
struct V {
SkPoint fPos;
uint32_t fColor;
@@ -207,9 +336,13 @@ void GrDrawVerticesOp::onPrepareDraws(Target* target) {
}
verts = v + vertexCount;
} else {
+ // Normal case.
static constexpr size_t kColorOffset = sizeof(SkPoint);
- size_t localCoordOffset =
- hasColorAttribute ? kColorOffset + sizeof(uint32_t) : kColorOffset;
+ size_t offset = kColorOffset;
+ if (hasColorAttribute) {
+ offset += sizeof(uint32_t);
+ }
+ size_t localCoordOffset = offset;
for (int j = 0; j < vertexCount; ++j) {
if (this->hasMultipleViewMatrices()) {
@@ -236,17 +369,25 @@ void GrDrawVerticesOp::onPrepareDraws(Target* target) {
}
vertexOffset += vertexCount;
}
+}
+void GrDrawVerticesOp::drawVertices(Target* target,
+ GrGeometryProcessor* gp,
+ const GrBuffer* vertexBuffer,
+ int firstVertex,
+ const GrBuffer* indexBuffer,
+ int firstIndex) {
GrMesh mesh(this->primitiveType());
- if (!indices) {
- mesh.setNonIndexedNonInstanced(fVertexCount);
- } else {
- mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertexCount - 1,
+ if (this->isIndexed()) {
+ mesh.setIndexed(indexBuffer, fIndexCount,
+ firstIndex, 0, fVertexCount - 1,
GrPrimitiveRestart::kNo);
+ } else {
+ mesh.setNonIndexedNonInstanced(fVertexCount);
}
mesh.setVertexData(vertexBuffer, firstVertex);
auto pipe = fHelper.makePipeline(target);
- target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
+ target->draw(gp, pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
bool GrDrawVerticesOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
@@ -256,6 +397,13 @@ bool GrDrawVerticesOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
return false;
}
+ // Non-volatile meshes cannot batch, because if a non-volatile mesh batches with another mesh,
+ // then on the next frame, if that non-volatile mesh is drawn, it will draw the other mesh
+ // that was saved in its vertex buffer, which is not necessarily there anymore.
+ if (!this->fMeshes[0].fVertices->isVolatile() || !that->fMeshes[0].fVertices->isVolatile()) {
+ return false;
+ }
+
if (!this->combinablePrimitive() || this->primitiveType() != that->primitiveType()) {
return false;
}
@@ -410,8 +558,8 @@ GR_DRAW_OP_TEST_DEFINE(GrDrawVerticesOp) {
if (GrFSAAType::kUnifiedMSAA == fsaaType && random->nextBool()) {
aaType = GrAAType::kMSAA;
}
- return GrDrawVerticesOp::Make(context, std::move(paint), std::move(vertices), viewMatrix,
- aaType, std::move(colorSpaceXform), &type);
+ return GrDrawVerticesOp::Make(context, std::move(paint), std::move(vertices),
+ viewMatrix, aaType, std::move(colorSpaceXform), &type);
}
#endif
diff --git a/src/gpu/ops/GrDrawVerticesOp.h b/src/gpu/ops/GrDrawVerticesOp.h
index 6d35c0d0e9..3a6eca0a0d 100644
--- a/src/gpu/ops/GrDrawVerticesOp.h
+++ b/src/gpu/ops/GrDrawVerticesOp.h
@@ -43,9 +43,8 @@ public:
sk_sp<GrColorSpaceXform>,
GrPrimitiveType* overridePrimType = nullptr);
- GrDrawVerticesOp(const Helper::MakeArgs& helperArgs, GrColor, sk_sp<SkVertices>,
- GrPrimitiveType, GrAAType, sk_sp<GrColorSpaceXform>,
- const SkMatrix& viewMatrix);
+ GrDrawVerticesOp(const Helper::MakeArgs&, GrColor, sk_sp<SkVertices>, GrPrimitiveType, GrAAType,
+ sk_sp<GrColorSpaceXform>, const SkMatrix& viewMatrix);
const char* name() const override { return "DrawVerticesOp"; }
@@ -68,7 +67,24 @@ private:
void onPrepareDraws(Target*) override;
- sk_sp<GrGeometryProcessor> makeGP(bool* hasColorAttribute, bool* hasLocalCoordAttribute) const;
+ void drawVolatile(Target*);
+ void drawNonVolatile(Target*);
+
+ void fillBuffers(bool hasColorAttribute,
+ bool hasLocalCoordsAttribute,
+ size_t vertexStride,
+ void* verts,
+ uint16_t* indices) const;
+
+ void drawVertices(Target*,
+ GrGeometryProcessor*,
+ const GrBuffer* vertexBuffer,
+ int firstVertex,
+ const GrBuffer* indexBuffer,
+ int firstIndex);
+
+ sk_sp<GrGeometryProcessor> makeGP(bool* hasColorAttribute,
+ bool* hasLocalCoordAttribute) const;
GrPrimitiveType primitiveType() const { return fPrimitiveType; }
bool combinablePrimitive() const {
@@ -105,7 +121,7 @@ private:
}
bool anyMeshHasExplicitLocalCoords() const {
- return SkToBool(kAnyMeshHasExplicitLocalCoords & fFlags);
+ return SkToBool(kAnyMeshHasExplicitLocalCoords_Flag & fFlags);
}
bool hasMultipleViewMatrices() const {
@@ -113,10 +129,9 @@ private:
}
enum Flags {
- kRequiresPerVertexColors_Flag = 0x1,
- kAnyMeshHasExplicitLocalCoords = 0x2,
- kHasMultipleViewMatrices_Flag = 0x4
-
+ kRequiresPerVertexColors_Flag = 0x1,
+ kAnyMeshHasExplicitLocalCoords_Flag = 0x2,
+ kHasMultipleViewMatrices_Flag = 0x4,
};
Helper fHelper;
diff --git a/tools/viewer/NIMASlide.cpp b/tools/viewer/NIMASlide.cpp
index c13ff2f11d..25d023f67b 100644
--- a/tools/viewer/NIMASlide.cpp
+++ b/tools/viewer/NIMASlide.cpp
@@ -62,7 +62,7 @@ public:
this->updateBones();
// Update the vertices object.
- this->updateVerticesObject(false);
+ this->updateVerticesObject(false, false);
}
void renderBackend(SkCanvas* canvas) {
@@ -70,16 +70,13 @@ public:
if (fRenderMode != kBackend_RenderMode) {
fRenderMode = kBackend_RenderMode;
this->updateVertices();
- this->updateVerticesObject(false);
+ this->updateVerticesObject(false, false);
}
- canvas->save();
-
// Update the vertex data.
- if (fActorImage->doesAnimationVertexDeform() && fActorImage->isVertexDeformDirty()) {
+ if (fActorImage->doesAnimationVertexDeform()) {
this->updateVertices();
- this->updateVerticesObject(false);
- fActorImage->isVertexDeformDirty(false);
+ this->updateVerticesObject(false, true);
}
// Update the bones.
@@ -87,8 +84,6 @@ public:
// Draw the vertices object.
this->drawVerticesObject(canvas, true);
-
- canvas->restore();
}
void renderImmediate(SkCanvas* canvas) {
@@ -96,7 +91,7 @@ public:
if (fRenderMode != kImmediate_RenderMode) {
fRenderMode = kImmediate_RenderMode;
this->updateVertices();
- this->updateVerticesObject(true);
+ this->updateVerticesObject(true, true);
}
// Update the vertex data.
@@ -106,7 +101,7 @@ public:
}
// Update the vertices object.
- this->updateVerticesObject(true);
+ this->updateVerticesObject(true, true);
// Draw the vertices object.
this->drawVerticesObject(canvas, false);
@@ -198,7 +193,7 @@ private:
nima_to_skmatrix(fActorImage->worldTransform().values(), fBones[0]);
}
- void updateVerticesObject(bool applyDeforms) {
+ void updateVerticesObject(bool applyDeforms, bool isVolatile) {
std::vector<SkPoint>* positions = &fPositions;
// Apply deforms if requested.
@@ -229,7 +224,8 @@ private:
fBoneIdx.data(),
fBoneWgt.data(),
fIndices.size(),
- fIndices.data());
+ fIndices.data(),
+ isVolatile);
}
void drawVerticesObject(SkCanvas* canvas, bool useBones) const {
@@ -421,11 +417,19 @@ NIMASlide::~NIMASlide() {}
void NIMASlide::draw(SkCanvas* canvas) {
canvas->save();
- canvas->translate(500, 500);
- canvas->scale(1, -1);
+ for (int i = 0; i < 10; i ++) {
+ for (int j = 0; j < 10; j ++) {
+ canvas->save();
- // Render the actor.
- fActor->render(canvas, fRenderMode);
+ canvas->translate(1250 - 250 * i, 1250 - 250 * j);
+ canvas->scale(0.5, -0.5);
+
+ // Render the actor.
+ fActor->render(canvas, fRenderMode);
+
+ canvas->restore();
+ }
+ }
canvas->restore();