added caching of SkVertices

SkVertices can now be "volatile", meaning they should not be cached.
SkVertices is volatile by default if the argument is not given.

Pulled from reverted CL: https://skia-review.googlesource.com/c/skia/+/138596

Docs-Preview: https://skia.org/?cl=139545
Bug: skia:
Change-Id: I92cf832efe1c0aaa8f432eedde2678582dd2454e
Reviewed-on: https://skia-review.googlesource.com/139545
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Ruiqi Mao <ruiqimao@google.com>
This commit is contained in:
Ruiqi Mao 2018-07-09 14:16:56 -04:00 committed by Skia Commit-Bot
parent c3833b4c15
commit 9a6e42ff18
9 changed files with 266 additions and 67 deletions

View File

@ -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 ##

View File

@ -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

View File

@ -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.
};

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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();