/* * Copyright 2014 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "GrDefaultGeoProcFactory.h" #include "gl/builders/GrGLProgramBuilder.h" #include "gl/GrGLGeometryProcessor.h" #include "GrDrawState.h" #include "GrInvariantOutput.h" #include "GrTBackendProcessorFactory.h" /* * The default Geometry Processor simply takes position and multiplies it by the uniform view * matrix. It also leaves coverage untouched. Behind the scenes, we may add per vertex color or * local coords. */ class DefaultGeoProc : public GrGeometryProcessor { public: static GrGeometryProcessor* Create(bool hasCoverage) { GR_CREATE_STATIC_PROCESSOR(gDefaultGeoProc, DefaultGeoProc, (hasCoverage)); return SkRef(gDefaultGeoProc); } static const char* Name() { return "DefaultGeometryProcessor"; } virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE { return GrTBackendGeometryProcessorFactory::getInstance(); } class GLProcessor : public GrGLGeometryProcessor { public: GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&) : INHERITED (factory) {} virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { GrGLVertexBuilder* vs = args.fPB->getVertexShaderBuilder(); // setup position varying vs->codeAppendf("%s = %s * vec3(%s, 1);", vs->glPosition(), vs->uViewM(), vs->inPosition()); // output coverage in FS(pass through) GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder(); fs->codeAppendf("%s = %s;", args.fOutput, GrGLSLExpr4(args.fInput).c_str()); } static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {} virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE {} private: typedef GrGLGeometryProcessor INHERITED; }; private: DefaultGeoProc(bool hasCoverageAttribute) : fHasCoverageAttribute(hasCoverageAttribute) {} virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { return true; } virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE { if (fHasCoverageAttribute) { inout->mulByUnknownAlpha(); } else { inout->mulByKnownAlpha(255); } } GR_DECLARE_GEOMETRY_PROCESSOR_TEST; bool fHasCoverageAttribute; typedef GrFragmentProcessor INHERITED; }; GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DefaultGeoProc); GrGeometryProcessor* DefaultGeoProc::TestCreate(SkRandom* random, GrContext*, const GrDrawTargetCaps& caps, GrTexture*[]) { return DefaultGeoProc::Create(random->nextBool()); } // We use these arrays to customize our default GP. We only need 4 because we omit coverage if // coverage is not requested in the flags to the create function. GrVertexAttrib kDefaultPositionGeoProc[] = { { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, { kFloat_GrVertexAttribType, sizeof(SkPoint), kCoverage_GrVertexAttribBinding }, }; GrVertexAttrib kDefaultPosColorGeoProc[] = { { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, { kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding }, { kFloat_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kCoverage_GrVertexAttribBinding }, }; GrVertexAttrib kDefaultPosLocalCoordGeoProc[] = { { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, { kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding }, { kFloat_GrVertexAttribType, 2 * sizeof(SkPoint), kCoverage_GrVertexAttribBinding }, }; GrVertexAttrib kDefaultPosColLocalCoordGeoProc[] = { { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, { kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding }, { kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kLocalCoord_GrVertexAttribBinding }, { kFloat_GrVertexAttribType, 2 * sizeof(SkPoint) + sizeof(GrColor), kCoverage_GrVertexAttribBinding }, }; static size_t get_size(GrDefaultGeoProcFactory::GPType flag) { switch (flag) { case GrDefaultGeoProcFactory::kPosition_GPType: return GrVertexAttribTypeSize(kVec2f_GrVertexAttribType); case GrDefaultGeoProcFactory::kColor_GPType: return GrVertexAttribTypeSize(kVec4ub_GrVertexAttribType); case GrDefaultGeoProcFactory::kLocalCoord_GPType: return GrVertexAttribTypeSize(kVec2f_GrVertexAttribType); case GrDefaultGeoProcFactory::kCoverage_GPType: return GrVertexAttribTypeSize(kFloat_GrVertexAttribType); default: SkFAIL("Should never get here"); return 0; } } void GrDefaultGeoProcFactory::SetAttribs(GrDrawState* ds, uint32_t gpTypeFlags) { SkASSERT(ds); // always atleast position in the GP size_t size = get_size(kPosition_GPType); int count = 1; bool hasColor = SkToBool(gpTypeFlags & kColor_GPType); bool hasLocalCoord = SkToBool(gpTypeFlags & kLocalCoord_GPType); bool hasCoverage = SkToBool(gpTypeFlags & kCoverage_GPType); if (hasColor) { size += get_size(kColor_GPType); count++; if (hasLocalCoord) { size += get_size(kLocalCoord_GPType); count++; if (hasCoverage) { size += get_size(kCoverage_GPType); count++; ds->setVertexAttribs(count, size); } else { ds->setVertexAttribs(count, size); } } else { if (hasCoverage) { size += get_size(kCoverage_GPType); count++; ds->setVertexAttribs(count, size); } else { ds->setVertexAttribs(count, size); } } } else if (hasLocalCoord) { size += get_size(kLocalCoord_GPType); count++; if (hasCoverage) { size += get_size(kCoverage_GPType); count++; ds->setVertexAttribs(count, size); } else { ds->setVertexAttribs(count, size); } } else if (hasCoverage) { size += get_size(kCoverage_GPType); count++; ds->setVertexAttribs(count, size); } else { // Just position ds->setVertexAttribs(count, size); } } const GrGeometryProcessor* GrDefaultGeoProcFactory::CreateAndSetAttribs(GrDrawState* ds, uint32_t gpTypeFlags) { SetAttribs(ds, gpTypeFlags); bool hasCoverage = SkToBool(gpTypeFlags & kCoverage_GPType); return DefaultGeoProc::Create(hasCoverage); } const GrGeometryProcessor* GrDefaultGeoProcFactory::Create(bool hasAttributeCoverage) { return DefaultGeoProc::Create(hasAttributeCoverage); }