diff options
Diffstat (limited to 'src/gpu/GrDefaultGeoProcFactory.cpp')
-rw-r--r-- | src/gpu/GrDefaultGeoProcFactory.cpp | 127 |
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); +} |