aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrDefaultGeoProcFactory.cpp
diff options
context:
space:
mode:
authorGravatar Ruiqi Mao <ruiqimao@google.com>2018-07-10 17:21:07 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-07-11 13:46:08 +0000
commit4ec72f7cc745bbd98a0ae0d160e774ce8ad1a1ff (patch)
tree14da5c61f858276bcf67c12f6abd31d2e01b1e97 /src/gpu/GrDefaultGeoProcFactory.cpp
parent2229b76258f70b1be76b8fdd1cfc868bd507bbd0 (diff)
added skeletal animation support to GPU backend
Pulled from reverted CL: https://skia-review.googlesource.com/c/skia/+/139282 Bug: skia: Change-Id: Iad8e834aa5bbd085b2dee679cb343c5736c57907 Reviewed-on: https://skia-review.googlesource.com/140383 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Ruiqi Mao <ruiqimao@google.com>
Diffstat (limited to 'src/gpu/GrDefaultGeoProcFactory.cpp')
-rw-r--r--src/gpu/GrDefaultGeoProcFactory.cpp127
1 files changed, 117 insertions, 10 deletions
diff --git a/src/gpu/GrDefaultGeoProcFactory.cpp b/src/gpu/GrDefaultGeoProcFactory.cpp
index e2bf87b277..b1c423aef7 100644
--- a/src/gpu/GrDefaultGeoProcFactory.cpp
+++ b/src/gpu/GrDefaultGeoProcFactory.cpp
@@ -27,8 +27,12 @@ enum GPFlag {
kColorAttributeIsSkColor_GPFlag = 0x2,
kLocalCoordAttribute_GPFlag = 0x4,
kCoverageAttribute_GPFlag = 0x8,
+ kBonesAttribute_GPFlag = 0x10,
};
+static constexpr int kMaxBones = 100; // Due to GPU memory limitations, only up to 100 bone
+ // matrices are accepted.
+
class DefaultGeoProc : public GrGeometryProcessor {
public:
static sk_sp<GrGeometryProcessor> Make(uint32_t gpTypeFlags,
@@ -37,10 +41,12 @@ public:
const SkMatrix& viewMatrix,
const SkMatrix& localMatrix,
bool localCoordsWillBeRead,
- uint8_t coverage) {
+ uint8_t coverage,
+ const float* bones,
+ int boneCount) {
return sk_sp<GrGeometryProcessor>(new DefaultGeoProc(
gpTypeFlags, color, std::move(colorSpaceXform), viewMatrix, localMatrix, coverage,
- localCoordsWillBeRead));
+ localCoordsWillBeRead, bones, boneCount));
}
const char* name() const override { return "DefaultGeometryProcessor"; }
@@ -52,6 +58,9 @@ public:
bool localCoordsWillBeRead() const { return fLocalCoordsWillBeRead; }
uint8_t coverage() const { return fCoverage; }
bool hasVertexCoverage() const { return fInCoverage.isInitialized(); }
+ const float* bones() const { return fBones; }
+ int boneCount() const { return fBoneCount; }
+ bool hasBones() const { return SkToBool(fBones); }
class GLSLProcessor : public GrGLSLGeometryProcessor {
public:
@@ -99,11 +108,37 @@ public:
&fColorUniform);
}
+ // Setup bone transforms
+ const char* transformedPositionName = gp.fInPosition.name();
+ if (gp.hasBones()) {
+ const char* vertBonesUniformName;
+ fBonesUniform = uniformHandler->addUniformArray(kVertex_GrShaderFlag,
+ kFloat3x3_GrSLType,
+ "Bones",
+ kMaxBones,
+ &vertBonesUniformName);
+ vertBuilder->codeAppendf(
+ "float2 transformedPosition = (%s[0] * float3(%s, 1)).xy;"
+ "float3x3 influence = float3x3(0);"
+ "for (int i = 0; i < 4; i++) {"
+ " int index = %s[i];"
+ " float weight = %s[i];"
+ " influence += %s[index] * weight;"
+ "}"
+ "transformedPosition = (influence * float3(transformedPosition, 1)).xy;",
+ vertBonesUniformName,
+ gp.fInPosition.name(),
+ gp.fInBoneIndices.name(),
+ gp.fInBoneWeights.name(),
+ vertBonesUniformName);
+ transformedPositionName = "transformedPosition";
+ }
+
// Setup position
this->writeOutputPosition(vertBuilder,
uniformHandler,
gpArgs,
- gp.fInPosition.name(),
+ transformedPositionName,
gp.viewMatrix(),
&fViewMatrixUniform);
@@ -147,8 +182,8 @@ public:
GrProcessorKeyBuilder* b) {
const DefaultGeoProc& def = gp.cast<DefaultGeoProc>();
uint32_t key = def.fFlags;
- key |= (def.coverage() == 0xff) ? 0x10 : 0;
- key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x20 : 0x0;
+ key |= (def.coverage() == 0xff) ? 0x20 : 0;
+ key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x40 : 0x0;
key |= ComputePosKey(def.viewMatrix()) << 20;
b->add32(key);
b->add32(GrColorSpaceXform::XformKey(def.fColorSpaceXform.get()));
@@ -180,6 +215,10 @@ public:
this->setTransformDataHelper(dgp.fLocalMatrix, pdman, &transformIter);
fColorSpaceHelper.setData(pdman, dgp.fColorSpaceXform.get());
+
+ if (dgp.hasBones()) {
+ pdman.setMatrix3fv(fBonesUniform, dgp.boneCount(), dgp.bones());
+ }
}
private:
@@ -189,6 +228,7 @@ public:
UniformHandle fViewMatrixUniform;
UniformHandle fColorUniform;
UniformHandle fCoverageUniform;
+ UniformHandle fBonesUniform;
GrGLSLColorSpaceXformHelper fColorSpaceHelper;
typedef GrGLSLGeometryProcessor INHERITED;
@@ -209,7 +249,9 @@ private:
const SkMatrix& viewMatrix,
const SkMatrix& localMatrix,
uint8_t coverage,
- bool localCoordsWillBeRead)
+ bool localCoordsWillBeRead,
+ const float* bones,
+ int boneCount)
: INHERITED(kDefaultGeoProc_ClassID)
, fColor(color)
, fViewMatrix(viewMatrix)
@@ -217,7 +259,9 @@ private:
, fCoverage(coverage)
, fFlags(gpTypeFlags)
, fLocalCoordsWillBeRead(localCoordsWillBeRead)
- , fColorSpaceXform(std::move(colorSpaceXform)) {
+ , fColorSpaceXform(std::move(colorSpaceXform))
+ , fBones(bones)
+ , fBoneCount(boneCount) {
fInPosition = {"inPosition", kFloat2_GrVertexAttribType};
int cnt = 1;
if (fFlags & kColorAttribute_GPFlag) {
@@ -232,17 +276,32 @@ private:
fInCoverage = {"inCoverage", kHalf_GrVertexAttribType};
++cnt;
}
+ if (fFlags & kBonesAttribute_GPFlag) {
+ SkASSERT(bones && (boneCount > 0));
+ fInBoneIndices = {"inBoneIndices", kInt4_GrVertexAttribType};
+ ++cnt;
+ fInBoneWeights = {"inBoneWeights", kFloat4_GrVertexAttribType};
+ ++cnt;
+ }
this->setVertexAttributeCnt(cnt);
}
const Attribute& onVertexAttribute(int i) const override {
- return IthInitializedAttribute(i, fInPosition, fInColor, fInLocalCoords, fInCoverage);
+ return IthInitializedAttribute(i,
+ fInPosition,
+ fInColor,
+ fInLocalCoords,
+ fInCoverage,
+ fInBoneIndices,
+ fInBoneWeights);
}
Attribute fInPosition;
Attribute fInColor;
Attribute fInLocalCoords;
Attribute fInCoverage;
+ Attribute fInBoneIndices;
+ Attribute fInBoneWeights;
GrColor fColor;
SkMatrix fViewMatrix;
SkMatrix fLocalMatrix;
@@ -250,6 +309,8 @@ private:
uint32_t fFlags;
bool fLocalCoordsWillBeRead;
sk_sp<GrColorSpaceXform> fColorSpaceXform;
+ const float* fBones;
+ int fBoneCount;
GR_DECLARE_GEOMETRY_PROCESSOR_TEST
@@ -259,6 +320,15 @@ private:
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DefaultGeoProc);
#if GR_TEST_UTILS
+static constexpr int kNumFloatsPerSkMatrix = 9;
+static constexpr int kTestBoneCount = 4;
+static constexpr float kTestBones[kTestBoneCount * kNumFloatsPerSkMatrix] = {
+ 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+};
+
sk_sp<GrGeometryProcessor> DefaultGeoProc::TestCreate(GrProcessorTestData* d) {
uint32_t flags = 0;
if (d->fRandom->nextBool()) {
@@ -273,6 +343,9 @@ sk_sp<GrGeometryProcessor> DefaultGeoProc::TestCreate(GrProcessorTestData* d) {
if (d->fRandom->nextBool()) {
flags |= kLocalCoordAttribute_GPFlag;
}
+ if (d->fRandom->nextBool()) {
+ flags |= kBonesAttribute_GPFlag;
+ }
return DefaultGeoProc::Make(flags,
GrRandomColor(d->fRandom),
@@ -280,7 +353,9 @@ sk_sp<GrGeometryProcessor> DefaultGeoProc::TestCreate(GrProcessorTestData* d) {
GrTest::TestMatrix(d->fRandom),
GrTest::TestMatrix(d->fRandom),
d->fRandom->nextBool(),
- GrRandomCoverage(d->fRandom));
+ GrRandomCoverage(d->fRandom),
+ kTestBones,
+ kTestBoneCount);
}
#endif
@@ -307,7 +382,9 @@ sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::Make(const Color& color,
viewMatrix,
localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(),
localCoordsWillBeRead,
- inCoverage);
+ inCoverage,
+ nullptr,
+ 0);
}
sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeForDeviceSpace(
@@ -330,3 +407,33 @@ sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeForDeviceSpace(
LocalCoords inverted(LocalCoords::kUsePosition_Type, &invert);
return Make(color, coverage, inverted, SkMatrix::I());
}
+
+sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeWithBones(const Color& color,
+ const Coverage& coverage,
+ const LocalCoords& localCoords,
+ const Bones& bones,
+ const SkMatrix& viewMatrix) {
+ uint32_t flags = 0;
+ if (Color::kPremulGrColorAttribute_Type == color.fType) {
+ flags |= kColorAttribute_GPFlag;
+ } else if (Color::kUnpremulSkColorAttribute_Type == color.fType) {
+ flags |= kColorAttribute_GPFlag | kColorAttributeIsSkColor_GPFlag;
+ }
+ flags |= coverage.fType == Coverage::kAttribute_Type ? kCoverageAttribute_GPFlag : 0;
+ flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoordAttribute_GPFlag : 0;
+ flags |= kBonesAttribute_GPFlag;
+
+ uint8_t inCoverage = coverage.fCoverage;
+ bool localCoordsWillBeRead = localCoords.fType != LocalCoords::kUnused_Type;
+
+ GrColor inColor = color.fColor;
+ return DefaultGeoProc::Make(flags,
+ inColor,
+ color.fColorSpaceXform,
+ viewMatrix,
+ localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(),
+ localCoordsWillBeRead,
+ inCoverage,
+ bones.fBones,
+ bones.fBoneCount);
+}