added optimizations to speed up skinning
Docs-Preview: https://skia.org/?cl=145148
Bug: skia:
Change-Id: If27722105a1e8999f6440b6fd4044cc1f327827e
Reviewed-on: https://skia-review.googlesource.com/145148
Commit-Queue: Ruiqi Mao <ruiqimao@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/core/SkDraw_vertices.cpp b/src/core/SkDraw_vertices.cpp
index 4d1ccea..b9320d4 100644
--- a/src/core/SkDraw_vertices.cpp
+++ b/src/core/SkDraw_vertices.cpp
@@ -167,7 +167,8 @@
const SkColor colors[], const SkVertices::BoneIndices boneIndices[],
const SkVertices::BoneWeights boneWeights[], SkBlendMode bmode,
const uint16_t indices[], int indexCount,
- const SkPaint& paint, const SkMatrix* bones, int boneCount) const {
+ const SkPaint& paint, const SkVertices::Bone bones[],
+ int boneCount) const {
SkASSERT(0 == vertexCount || vertices);
// abort early if there is nothing to draw
@@ -207,11 +208,9 @@
}
constexpr size_t kDefVertexCount = 16;
- constexpr size_t kDefBoneCount = 8;
constexpr size_t kOuterSize = sizeof(SkTriColorShader) +
sizeof(SkComposeShader) +
- (2 * sizeof(SkPoint) + sizeof(SkPM4f)) * kDefVertexCount +
- sizeof(SkMatrix) * kDefBoneCount;
+ (2 * sizeof(SkPoint) + sizeof(SkPM4f)) * kDefVertexCount;
SkSTArenaAlloc<kOuterSize> outerAlloc;
// deform vertices using the skeleton if it is passed in
@@ -219,28 +218,21 @@
// allocate space for the deformed vertices
SkPoint* deformed = outerAlloc.makeArray<SkPoint>(vertexCount);
- // get the bone matrices
- SkMatrix* transformedBones = outerAlloc.makeArray<SkMatrix>(boneCount);
-
- // transform the bone matrices by the world transform
- transformedBones[0] = bones[0];
- for (int i = 1; i < boneCount; i ++) {
- transformedBones[i] = SkMatrix::Concat(bones[i], bones[0]);
- }
-
// deform the vertices
if (boneIndices && boneWeights) {
for (int i = 0; i < vertexCount; i ++) {
const SkVertices::BoneIndices& indices = boneIndices[i];
const SkVertices::BoneWeights& weights = boneWeights[i];
+ // apply the world transform
+ SkPoint worldPoint = bones[0].mapPoint(vertices[i]);
+
// apply bone deformations
- SkPoint result = SkPoint::Make(0.0f, 0.0f);
- SkPoint transformed;
+ deformed[i] = SkPoint::Make(0.0f, 0.0f);
for (uint32_t j = 0; j < 4; j ++) {
// get the attachment data
- uint32_t index = indices.indices[j];
- float weight = weights.weights[j];
+ uint32_t index = indices[j];
+ float weight = weights[j];
// skip the bone if there is no weight
if (weight == 0.0f) {
@@ -248,19 +240,14 @@
}
SkASSERT(index != 0);
- // transformed = M * v
- transformedBones[index].mapPoints(&transformed, &vertices[i], 1);
-
- // result += transformed * w
- result += transformed * weight;
+ // deformed += M * v * w
+ deformed[i] += bones[index].mapPoint(worldPoint) * weight;
}
-
- // set the deformed point
- deformed[i] = result;
}
} else {
// no bones, so only apply world transform
- const SkMatrix& worldTransform = bones[0];
+ SkMatrix worldTransform = SkMatrix::I();
+ worldTransform.setAffine(bones[0].values);
worldTransform.mapPoints(deformed, vertices, vertexCount);
}