diff options
Diffstat (limited to 'src/core/SkDraw_vertices.cpp')
-rw-r--r-- | src/core/SkDraw_vertices.cpp | 88 |
1 files changed, 73 insertions, 15 deletions
diff --git a/src/core/SkDraw_vertices.cpp b/src/core/SkDraw_vertices.cpp index de6eaea5b6..f918269992 100644 --- a/src/core/SkDraw_vertices.cpp +++ b/src/core/SkDraw_vertices.cpp @@ -161,15 +161,16 @@ static bool compute_is_opaque(const SkColor colors[], int count) { return SkColorGetA(c) == 0xFF; } -void SkDraw::drawVertices(SkVertices::VertexMode vmode, int count, +void SkDraw::drawVertices(SkVertices::VertexMode vmode, int vertexCount, const SkPoint vertices[], const SkPoint textures[], - const SkColor colors[], SkBlendMode bmode, + const SkColor colors[], const SkVertices::BoneIndices boneIndices[], + const SkVertices::BoneWeights boneWeights[], SkBlendMode bmode, const uint16_t indices[], int indexCount, - const SkPaint& paint) const { - SkASSERT(0 == count || vertices); + const SkPaint& paint, const SkMatrix* bones, int boneCount) const { + SkASSERT(0 == vertexCount || vertices); // abort early if there is nothing to draw - if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) { + if (vertexCount < 3 || (indices && indexCount < 3) || fRC->isEmpty()) { return; } SkMatrix ctmInv; @@ -204,25 +205,81 @@ void SkDraw::drawVertices(SkVertices::VertexMode vmode, int count, shader = nullptr; } - constexpr size_t defCount = 16; - constexpr size_t outerSize = sizeof(SkTriColorShader) + + constexpr size_t kDefVertexCount = 16; + constexpr size_t kDefBoneCount = 8; + constexpr size_t kOuterSize = sizeof(SkTriColorShader) + sizeof(SkComposeShader) + - (sizeof(SkPoint) + sizeof(SkPM4f)) * defCount; - SkSTArenaAlloc<outerSize> outerAlloc; + (2 * sizeof(SkPoint) + sizeof(SkPM4f)) * kDefVertexCount + + sizeof(SkMatrix) * kDefBoneCount; + SkSTArenaAlloc<kOuterSize> outerAlloc; + + // deform vertices using the skeleton if it is passed in + if (bones && boneCount) { + // 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 bone deformations + SkPoint result = SkPoint::Make(0.0f, 0.0f); + SkPoint transformed; + for (uint32_t j = 0; j < 4; j ++) { + // get the attachment data + uint32_t index = indices.indices[j]; + float weight = weights.weights[j]; + + // skip the bone if there is no weight + if (weight == 0.0f) { + continue; + } + SkASSERT(index != 0); + + // transformed = M * v + transformedBones[index].mapPoints(&transformed, &vertices[i], 1); + + // result += transformed * w + result += transformed * weight; + } + + // set the deformed point + deformed[i] = result; + } + } else { + // no bones, so only apply world transform + const SkMatrix& worldTransform = bones[0]; + worldTransform.mapPoints(deformed, vertices, vertexCount); + } + + // change the vertices to point to deformed + vertices = deformed; + } - SkPoint* devVerts = outerAlloc.makeArray<SkPoint>(count); - fMatrix->mapPoints(devVerts, vertices, count); + SkPoint* devVerts = outerAlloc.makeArray<SkPoint>(vertexCount); + fMatrix->mapPoints(devVerts, vertices, vertexCount); { SkRect bounds; // this also sets bounds to empty if we see a non-finite value - bounds.set(devVerts, count); + bounds.set(devVerts, vertexCount); if (bounds.isEmpty()) { return; } } - VertState state(count, indices, indexCount); + VertState state(vertexCount, indices, indexCount); VertState::Proc vertProc = state.chooseProc(vmode); if (colors || textures) { @@ -230,10 +287,11 @@ void SkDraw::drawVertices(SkVertices::VertexMode vmode, int count, Matrix43* matrix43 = nullptr; if (colors) { - dstColors = convert_colors(colors, count, fDst.colorSpace(), &outerAlloc); + dstColors = convert_colors(colors, vertexCount, fDst.colorSpace(), &outerAlloc); SkTriColorShader* triShader = outerAlloc.make<SkTriColorShader>( - compute_is_opaque(colors, count)); + compute_is_opaque(colors, + vertexCount)); matrix43 = triShader->getMatrix43(); if (shader) { shader = outerAlloc.make<SkComposeShader>(sk_ref_sp(triShader), sk_ref_sp(shader), |