diff options
author | joshualitt <joshualitt@chromium.org> | 2014-12-03 06:24:10 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-12-03 06:24:10 -0800 |
commit | 2dd1ae016d7f297b433c3ea3a771ef8e01657c1f (patch) | |
tree | 96aa03d4b4b1802490cb5b769627b75f3de4a470 | |
parent | 960fb50a1a7ac76fd51e22983812f26bfffa6d1e (diff) |
First step to moving vertex attributes to the geometryProcessor
BUG=skia:
Review URL: https://codereview.chromium.org/761563002
41 files changed, 858 insertions, 1323 deletions
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt index eec9c974fc..9337e7563b 100644 --- a/expectations/gm/ignored-tests.txt +++ b/expectations/gm/ignored-tests.txt @@ -66,3 +66,6 @@ drawbitmapmatrix #junov skbug.com/3176 pictureimagefilter + +#joshualitt +bezier_cubic_effects diff --git a/gm/beziereffects.cpp b/gm/beziereffects.cpp index 3de47d3be2..f875607792 100644 --- a/gm/beziereffects.cpp +++ b/gm/beziereffects.cpp @@ -21,15 +21,6 @@ #include "effects/GrBezierEffect.h" -// Position & KLM line eq values. These are the vertex attributes for Bezier curves. The last value -// of the Vec4f is ignored. -namespace { -extern const GrVertexAttrib kAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding} -}; -} - static inline SkScalar eval_line(const SkPoint& p, const SkScalar lineEq[3], SkScalar sign) { return sign * (lineEq[0] * p.fX + lineEq[1] * p.fY + lineEq[2]); } @@ -159,9 +150,9 @@ protected: SkASSERT(tt.target()); GrDrawState ds; - ds.setVertexAttribs<kAttribs>(2, sizeof(Vertex)); - GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, ds.getVertexStride(), 0); + GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, gp->getVertexStride(), 0); + SkASSERT(gp->getVertexStride() == sizeof(Vertex)); Vertex* verts = reinterpret_cast<Vertex*>(geo.vertices()); verts[0].fPosition.setRectFan(bounds.fLeft, bounds.fTop, @@ -316,9 +307,9 @@ protected: SkASSERT(tt.target()); GrDrawState ds; - ds.setVertexAttribs<kAttribs>(2, sizeof(Vertex)); - GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, ds.getVertexStride(), 0); + GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, gp->getVertexStride(), 0); + SkASSERT(gp->getVertexStride() == sizeof(Vertex)); Vertex* verts = reinterpret_cast<Vertex*>(geo.vertices()); verts[0].fPosition.setRectFan(bounds.fLeft, bounds.fTop, @@ -504,9 +495,9 @@ protected: SkASSERT(tt.target()); GrDrawState ds; - ds.setVertexAttribs<kAttribs>(2, sizeof(Vertex)); - GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, ds.getVertexStride(), 0); + GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, gp->getVertexStride(), 0); + SkASSERT(gp->getVertexStride() == sizeof(Vertex)); Vertex* verts = reinterpret_cast<Vertex*>(geo.vertices()); verts[0].fPosition.setRectFan(bounds.fLeft, bounds.fTop, diff --git a/gm/convexpolyeffect.cpp b/gm/convexpolyeffect.cpp index 8ee4a5db6f..1e5c6017ca 100644 --- a/gm/convexpolyeffect.cpp +++ b/gm/convexpolyeffect.cpp @@ -133,13 +133,15 @@ protected: } GrDrawState ds; - ds.setGeometryProcessor(GrDefaultGeoProcFactory::Create(false))->unref(); + const GrGeometryProcessor* gp = GrDefaultGeoProcFactory::Create(); + ds.setGeometryProcessor(gp)->unref(); ds.addCoverageProcessor(fp); ds.setIdentityViewMatrix(); ds.setRenderTarget(rt); ds.setColor(0xff000000); - GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, ds.getVertexStride(), 0); + GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, gp->getVertexStride(), 0); + SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices()); SkRect bounds = p.getBounds(); @@ -189,13 +191,15 @@ protected: } GrDrawState ds; - ds.setGeometryProcessor(GrDefaultGeoProcFactory::Create(false))->unref(); + const GrGeometryProcessor* gp = GrDefaultGeoProcFactory::Create(); + ds.setGeometryProcessor(gp)->unref(); ds.addCoverageProcessor(fp); ds.setIdentityViewMatrix(); ds.setRenderTarget(rt); ds.setColor(0xff000000); - GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, ds.getVertexStride(), 0); + GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, gp->getVertexStride(), 0); + SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices()); SkRect bounds = rect; diff --git a/include/gpu/GrTypesPriv.h b/include/gpu/GrTypesPriv.h index 75c987f148..0ff4e5709e 100644 --- a/include/gpu/GrTypesPriv.h +++ b/include/gpu/GrTypesPriv.h @@ -120,58 +120,24 @@ static inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) { } /** - * Semantic bindings for vertex attributes. kEffect means that the attribute is input to a - * GrProcessor. Each binding other than kEffect may not appear more than once in the current set of - * attributes. kPosition must be appear for exactly one attribute. + * converts a GrVertexAttribType to a GrSLType */ -enum GrVertexAttribBinding { - kPosition_GrVertexAttribBinding, // required, must have vector count of 2 - kLocalCoord_GrVertexAttribBinding, // must have vector count of 2 - kColor_GrVertexAttribBinding, // must have vector count of 4 - kCoverage_GrVertexAttribBinding, // must have a single byte - - kLastFixedFunction_GrVertexAttribBinding = kCoverage_GrVertexAttribBinding, - - kGeometryProcessor_GrVertexAttribBinding, // vector length must agree with - // GrProcessor::vertexAttribType() for each effect input to - // which the attribute is mapped by GrDrawState::setEffect() - kLast_GrVertexAttribBinding = kGeometryProcessor_GrVertexAttribBinding -}; - -static const int kGrVertexAttribBindingCnt = kLast_GrVertexAttribBinding + 1; -static const int kGrFixedFunctionVertexAttribBindingCnt = - kLastFixedFunction_GrVertexAttribBinding + 1; - -static inline int GrFixedFunctionVertexAttribVectorCount(GrVertexAttribBinding binding) { - SkASSERT(binding >= 0 && binding < kGrFixedFunctionVertexAttribBindingCnt); - static const int kVecCounts[] = { 2, 2, 4, 1 }; - - return kVecCounts[binding]; - - GR_STATIC_ASSERT(0 == kPosition_GrVertexAttribBinding); - GR_STATIC_ASSERT(1 == kLocalCoord_GrVertexAttribBinding); - GR_STATIC_ASSERT(2 == kColor_GrVertexAttribBinding); - GR_STATIC_ASSERT(3 == kCoverage_GrVertexAttribBinding); - GR_STATIC_ASSERT(kGrFixedFunctionVertexAttribBindingCnt == SK_ARRAY_COUNT(kVecCounts)); -} - -struct GrVertexAttrib { - inline void set(GrVertexAttribType type, size_t offset, GrVertexAttribBinding binding) { - fType = type; - fOffset = offset; - fBinding = binding; +static inline GrSLType GrVertexAttribTypeToSLType(GrVertexAttribType type) { + switch (type) { + default: + SkFAIL("Unsupported type conversion"); + case kUByte_GrVertexAttribType: + case kFloat_GrVertexAttribType: + return kFloat_GrSLType; + case kVec2f_GrVertexAttribType: + return kVec2f_GrSLType; + case kVec3f_GrVertexAttribType: + return kVec3f_GrSLType; + case kVec4ub_GrVertexAttribType: + case kVec4f_GrVertexAttribType: + return kVec4f_GrSLType; } - bool operator==(const GrVertexAttrib& other) const { - return fType == other.fType && fOffset == other.fOffset && fBinding == other.fBinding; - }; - bool operator!=(const GrVertexAttrib& other) const { return !(*this == other); } - - GrVertexAttribType fType; - size_t fOffset; - GrVertexAttribBinding fBinding; -}; - -template <int N> class GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {}; +} ////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp index 934eb04ed8..b5ad44adc0 100644 --- a/src/gpu/GrAAConvexPathRenderer.cpp +++ b/src/gpu/GrAAConvexPathRenderer.cpp @@ -518,7 +518,8 @@ public: static const char* Name() { return "QuadEdge"; } - const GrShaderVar& inQuadEdge() const { return fInQuadEdge; } + const GrAttribute* inPosition() const { return fInPosition; } + const GrAttribute* inQuadEdge() const { return fInQuadEdge; } virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE { return GrTBackendGeometryProcessorFactory<QuadEdgeEffect>::getInstance(); @@ -530,8 +531,20 @@ public: : INHERITED (factory) {} virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { + const QuadEdgeEffect& qe = args.fGP.cast<QuadEdgeEffect>(); + GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); + GrGLVertToFrag v(kVec4f_GrSLType); args.fPB->addVarying("QuadEdge", &v); + vsBuilder->codeAppendf("%s = %s;", v.vsOut(), qe.inQuadEdge()->fName); + + // setup coord outputs + vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), qe.inPosition()->fName); + vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), qe.inPosition()->fName); + + // setup position varying + vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), + vsBuilder->uViewM(), qe.inPosition()->fName); GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); @@ -555,17 +568,7 @@ public: fsBuilder->codeAppendf("edgeAlpha = " "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);}"); - - fsBuilder->codeAppendf("%s = %s;", args.fOutput, - (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("edgeAlpha")).c_str()); - - const GrShaderVar& inQuadEdge = args.fGP.cast<QuadEdgeEffect>().inQuadEdge(); - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); - vsBuilder->codeAppendf("\t%s = %s;\n", v.vsOut(), inQuadEdge.c_str()); - - // setup position varying - vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), - vsBuilder->uViewM(), vsBuilder->inPosition()); + fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage); } static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {} @@ -577,10 +580,9 @@ public: }; private: - QuadEdgeEffect() - : fInQuadEdge(this->addVertexAttrib(GrShaderVar("inQuadEdge", - kVec4f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { + QuadEdgeEffect() { + fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType)); + fInQuadEdge = &this->addVertexAttrib(GrAttribute("inQuadEdge", kVec4f_GrVertexAttribType)); } virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { @@ -591,7 +593,8 @@ private: inout->mulByUnknownAlpha(); } - const GrShaderVar& fInQuadEdge; + const GrAttribute* fInPosition; + const GrAttribute* fInQuadEdge; GR_DECLARE_GEOMETRY_PROCESSOR_TEST; @@ -619,16 +622,6 @@ bool GrAAConvexPathRenderer::canDrawPath(const GrDrawTarget* target, stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex()); } -namespace { - -// position + edge -extern const GrVertexAttrib gPathAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding} -}; - -}; - bool GrAAConvexPathRenderer::onDrawPath(GrDrawTarget* target, GrDrawState* drawState, const SkPath& origPath, @@ -678,12 +671,11 @@ bool GrAAConvexPathRenderer::onDrawPath(GrDrawTarget* target, // Our computed verts should all be within one pixel of the segment control points. devBounds.outset(SK_Scalar1, SK_Scalar1); - drawState->setVertexAttribs<gPathAttribs>(SK_ARRAY_COUNT(gPathAttribs), sizeof(QuadVertex)); - GrGeometryProcessor* quadProcessor = QuadEdgeEffect::Create(); drawState->setGeometryProcessor(quadProcessor)->unref(); - GrDrawTarget::AutoReleaseGeometry arg(target, vCount, drawState->getVertexStride(), iCount); + GrDrawTarget::AutoReleaseGeometry arg(target, vCount, quadProcessor->getVertexStride(), iCount); + SkASSERT(quadProcessor->getVertexStride() == sizeof(QuadVertex)); if (!arg.succeeded()) { return false; } diff --git a/src/gpu/GrAADistanceFieldPathRenderer.cpp b/src/gpu/GrAADistanceFieldPathRenderer.cpp index 5e0410fd75..6ac504a948 100755 --- a/src/gpu/GrAADistanceFieldPathRenderer.cpp +++ b/src/gpu/GrAADistanceFieldPathRenderer.cpp @@ -103,13 +103,6 @@ GrAADistanceFieldPathRenderer::onGetStencilSupport(const GrDrawTarget*, //////////////////////////////////////////////////////////////////////////////// -// position + texture coord -extern const GrVertexAttrib gSDFPathVertexAttribs[] = { - { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, - { kVec2f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding } -}; -static const size_t kSDFPathVASize = 2 * sizeof(SkPoint); - bool GrAADistanceFieldPathRenderer::onDrawPath(GrDrawTarget* target, GrDrawState* drawState, const SkPath& path, @@ -322,12 +315,25 @@ bool GrAADistanceFieldPathRenderer::internalDrawPath(GrDrawTarget* target, GrDrawTarget::DrawToken drawToken = target->getCurrentDrawToken(); pathData->fPlot->setDrawToken(drawToken); - // make me some vertices - drawState->setVertexAttribs<gSDFPathVertexAttribs>(SK_ARRAY_COUNT(gSDFPathVertexAttribs), - kSDFPathVASize); + // set up any flags + uint32_t flags = 0; + const SkMatrix& vm = drawState->getViewMatrix(); + flags |= vm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0; + + GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode); + if (flags != fEffectFlags) { + fCachedGeometryProcessor.reset(GrDistanceFieldNoGammaTextureEffect::Create(texture, + params, + flags)); + fEffectFlags = flags; + } + drawState->setGeometryProcessor(fCachedGeometryProcessor.get()); + void* vertices = NULL; - bool success = target->reserveVertexAndIndexSpace(4, drawState->getVertexStride(), 0, &vertices, - NULL); + bool success = target->reserveVertexAndIndexSpace(4, + fCachedGeometryProcessor->getVertexStride(), + 0, &vertices, NULL); + SkASSERT(fCachedGeometryProcessor->getVertexStride() == 2 * sizeof(SkPoint)); GrAlwaysAssert(success); SkScalar dx = pathData->fBounds.fLeft; @@ -361,20 +367,6 @@ bool GrAADistanceFieldPathRenderer::internalDrawPath(GrDrawTarget* target, SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty + th)), vertSize); - // set up any flags - uint32_t flags = 0; - const SkMatrix& vm = drawState->getViewMatrix(); - flags |= vm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0; - - GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode); - if (flags != fEffectFlags) { - fCachedGeometryProcessor.reset(GrDistanceFieldNoGammaTextureEffect::Create(texture, - params, - flags)); - fEffectFlags = flags; - } - drawState->setGeometryProcessor(fCachedGeometryProcessor.get()); - vm.mapRect(&r); target->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 4, 6, &r); diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp index 0d16cf8ea2..7168c83884 100644 --- a/src/gpu/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/GrAAHairLinePathRenderer.cpp @@ -642,14 +642,6 @@ void add_line(const SkPoint p[2], /////////////////////////////////////////////////////////////////////////////// -namespace { -// position + edge -extern const GrVertexAttrib gHairlineBezierAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding} -}; -}; - bool GrAAHairLinePathRenderer::createLineGeom(GrDrawTarget* target, GrDrawState* drawState, GrDrawTarget::AutoReleaseGeometry* arg, @@ -661,10 +653,9 @@ bool GrAAHairLinePathRenderer::createLineGeom(GrDrawTarget* target, int vertCnt = kLineSegNumVertices * lineCnt; - GrDefaultGeoProcFactory::SetAttribs(drawState, GrDefaultGeoProcFactory::kPosition_GPType | - GrDefaultGeoProcFactory::kCoverage_GPType); - - if (!arg->set(target, vertCnt, drawState->getVertexStride(), 0)) { + size_t vstride = drawState->getGeometryProcessor()->getVertexStride(); + SkASSERT(vstride == sizeof(LineVertex)); + if (!arg->set(target, vertCnt, vstride, 0)) { return false; } @@ -701,15 +692,13 @@ bool GrAAHairLinePathRenderer::createBezierGeom(GrDrawTarget* target, const PtArray& conics, int conicCnt, const IntArray& qSubdivs, - const FloatArray& cWeights) { + const FloatArray& cWeights, + size_t vertexStride) { const SkMatrix& viewM = drawState->getViewMatrix(); int vertCnt = kQuadNumVertices * quadCnt + kQuadNumVertices * conicCnt; - int vAttribCnt = SK_ARRAY_COUNT(gHairlineBezierAttribs); - drawState->setVertexAttribs<gHairlineBezierAttribs>(vAttribCnt, sizeof(BezierVertex)); - - if (!arg->set(target, vertCnt, drawState->getVertexStride(), 0)) { + if (!arg->set(target, vertCnt, vertexStride, 0)) { return false; } @@ -846,6 +835,11 @@ bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, GrDrawTarget::AutoReleaseGeometry arg; SkRect devBounds; + uint32_t gpFlags = GrDefaultGeoProcFactory::kPosition_GPType | + GrDefaultGeoProcFactory::kCoverage_GPType; + GrDrawState::AutoRestoreEffects are(drawState); + drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(gpFlags))->unref(); + if (!this->createLineGeom(target, drawState, &arg, @@ -868,8 +862,6 @@ bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, kLineSegNumVertices * lineCnt)); { - GrDrawState::AutoRestoreEffects are(drawState); - drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(false))->unref(); target->setIndexSourceToBuffer(fLinesIndexBuffer); int lines = 0; while (lines < lineCnt) { @@ -901,7 +893,8 @@ bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, conics, conicCnt, qSubdivs, - cWeights)) { + cWeights, + sizeof(BezierVertex))) { return false; } @@ -923,6 +916,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, SkASSERT(hairQuadProcessor); GrDrawState::AutoRestoreEffects are(drawState); target->setIndexSourceToBuffer(fQuadsIndexBuffer); + drawState->setGeometryProcessor(hairQuadProcessor)->unref(); int quads = 0; while (quads < quadCnt) { @@ -943,6 +937,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, GrGeometryProcessor* hairConicProcessor = GrConicEffect::Create( kHairlineAA_GrProcessorEdgeType, *target->caps()); SkASSERT(hairConicProcessor); + drawState->setGeometryProcessor(hairConicProcessor)->unref(); int conics = 0; while (conics < conicCnt) { diff --git a/src/gpu/GrAAHairLinePathRenderer.h b/src/gpu/GrAAHairLinePathRenderer.h index c5f64f5e8f..2f44860c6c 100644 --- a/src/gpu/GrAAHairLinePathRenderer.h +++ b/src/gpu/GrAAHairLinePathRenderer.h @@ -57,7 +57,8 @@ private: const PtArray& conics, int conicCnt, const IntArray& qSubdivs, - const FloatArray& cWeights); + const FloatArray& cWeights, + size_t vertexStride); const GrIndexBuffer* fLinesIndexBuffer; const GrIndexBuffer* fQuadsIndexBuffer; diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp index edb59d04d8..95fe8c9b7f 100644 --- a/src/gpu/GrAARectRenderer.cpp +++ b/src/gpu/GrAARectRenderer.cpp @@ -27,18 +27,17 @@ enum CoverageAttribType { } static CoverageAttribType set_rect_attribs(GrDrawState* drawState) { + uint32_t flags = GrDefaultGeoProcFactory::kColor_GPType; if (drawState->canTweakAlphaForCoverage()) { - drawState->setGeometryProcessor( - GrDefaultGeoProcFactory::CreateAndSetAttribs( - drawState, - GrDefaultGeoProcFactory::kColor_GPType))->unref(); + drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(flags))->unref(); + SkASSERT(drawState->getGeometryProcessor()->getVertexStride() == + sizeof(GrDefaultGeoProcFactory::PositionColorAttr)); return kUseColor_CoverageAttribType; } else { - drawState->setGeometryProcessor( - GrDefaultGeoProcFactory::CreateAndSetAttribs( - drawState, - GrDefaultGeoProcFactory::kColor_GPType | - GrDefaultGeoProcFactory::kCoverage_GPType))->unref(); + flags |= GrDefaultGeoProcFactory::kCoverage_GPType; + drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(flags))->unref(); + SkASSERT(drawState->getGeometryProcessor()->getVertexStride() == + sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr)); return kUseCoverage_CoverageAttribType; } } @@ -190,7 +189,8 @@ void GrAARectRenderer::geometryFillAARect(GrDrawTarget* target, drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true); } - GrDrawTarget::AutoReleaseGeometry geo(target, 8, drawState->getVertexStride(), 0); + size_t vstride = drawState->getGeometryProcessor()->getVertexStride(); + GrDrawTarget::AutoReleaseGeometry geo(target, 8, vstride, 0); if (!geo.succeeded()) { SkDebugf("Failed to get space for vertices!\n"); return; @@ -209,7 +209,6 @@ void GrAARectRenderer::geometryFillAARect(GrDrawTarget* target, } intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); - size_t vstride = drawState->getVertexStride(); SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vstride); @@ -395,7 +394,8 @@ void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target, int outerVertexNum = miterStroke ? 4 : 8; int totalVertexNum = (outerVertexNum + innerVertexNum) * 2; - GrDrawTarget::AutoReleaseGeometry geo(target, totalVertexNum, drawState->getVertexStride(), 0); + size_t vstride = drawState->getGeometryProcessor()->getVertexStride(); + GrDrawTarget::AutoReleaseGeometry geo(target, totalVertexNum, vstride, 0); if (!geo.succeeded()) { SkDebugf("Failed to get space for vertices!\n"); return; @@ -407,7 +407,6 @@ void GrAARectRenderer::geometryStrokeAARect(GrDrawTarget* target, } intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); - size_t vstride = drawState->getVertexStride(); // We create vertices for four nested rectangles. There are two ramps from 0 to full // coverage, one on the exterior of the stroke and the other on the interior. diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp index 2ff410e5cf..3b0bddb8e7 100755 --- a/src/gpu/GrBitmapTextContext.cpp +++ b/src/gpu/GrBitmapTextContext.cpp @@ -35,24 +35,11 @@ SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, "Dump the contents of the font cache before every purge."); namespace { -// position + texture coord -extern const GrVertexAttrib gLCDVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec2f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding} -}; - static const size_t kLCDTextVASize = 2 * sizeof(SkPoint); // position + local coord static const size_t kColorTextVASize = 2 * sizeof(SkPoint); -// position + color + texture coord -extern const GrVertexAttrib gGrayVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding}, - {kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kGeometryProcessor_GrVertexAttribBinding} -}; - static const size_t kGrayTextVASize = 2 * sizeof(SkPoint) + sizeof(GrColor); static const int kVerticesPerGlyph = 4; @@ -354,19 +341,6 @@ static size_t get_vertex_stride(GrMaskFormat maskFormat) { } } -static void set_vertex_attributes(GrDrawState* drawState, GrMaskFormat maskFormat) { - if (kA8_GrMaskFormat == maskFormat) { - drawState->setVertexAttribs<gGrayVertexAttribs>( - SK_ARRAY_COUNT(gGrayVertexAttribs), kGrayTextVASize); - } else if (kARGB_GrMaskFormat == maskFormat) { - GrDefaultGeoProcFactory::SetAttribs(drawState, - GrDefaultGeoProcFactory::kLocalCoord_GPType); - } else { - drawState->setVertexAttribs<gLCDVertexAttribs>( - SK_ARRAY_COUNT(gLCDVertexAttribs), kLCDTextVASize); - } -} - static void* alloc_vertices(GrDrawTarget* drawTarget, int numVertices, GrMaskFormat maskFormat) { @@ -552,16 +526,15 @@ void GrBitmapTextContext::flush() { GrDrawState drawState; drawState.setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget()); - set_vertex_attributes(&drawState, fCurrMaskFormat); - // setup our sampler state for our text texture/atlas SkASSERT(SkIsAlign4(fCurrVertex)); SkASSERT(fCurrTexture); - GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode); // This effect could be stored with one of the cache objects (atlas?) + GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode); if (kARGB_GrMaskFormat == fCurrMaskFormat) { - drawState.setGeometryProcessor(GrDefaultGeoProcFactory::Create(true))->unref(); + uint32_t flags = GrDefaultGeoProcFactory::kLocalCoord_GPType; + drawState.setGeometryProcessor(GrDefaultGeoProcFactory::Create(flags))->unref(); GrFragmentProcessor* fragProcessor = GrSimpleTextureEffect::Create(fCurrTexture, SkMatrix::I(), params); @@ -569,11 +542,12 @@ void GrBitmapTextContext::flush() { } else { uint32_t textureUniqueID = fCurrTexture->getUniqueID(); if (textureUniqueID != fEffectTextureUniqueID) { + bool hasColor = kA8_GrMaskFormat == fCurrMaskFormat; fCachedGeometryProcessor.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture, - params)); + params, + hasColor)); fEffectTextureUniqueID = textureUniqueID; } - drawState.setGeometryProcessor(fCachedGeometryProcessor.get()); } diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 852afe01ba..e947a16dd6 100755 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -313,13 +313,13 @@ GrTexture* GrContext::createResizedTexture(const GrSurfaceDesc& desc, GrTextureParams::kNone_FilterMode); drawState.addColorTextureProcessor(clampedTexture, SkMatrix::I(), params); - drawState.setGeometryProcessor( - GrDefaultGeoProcFactory::CreateAndSetAttribs( - &drawState, - GrDefaultGeoProcFactory::kPosition_GPType | - GrDefaultGeoProcFactory::kLocalCoord_GPType))->unref(); + uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType | + GrDefaultGeoProcFactory::kLocalCoord_GPType; + const GrGeometryProcessor* gp = GrDefaultGeoProcFactory::Create(flags); + drawState.setGeometryProcessor(gp)->unref(); - GrDrawTarget::AutoReleaseGeometry arg(fDrawBuffer, 4, drawState.getVertexStride(), 0); + GrDrawTarget::AutoReleaseGeometry arg(fDrawBuffer, 4, gp->getVertexStride(), 0); + SkASSERT(gp->getVertexStride() == 2 * sizeof(SkPoint)); if (arg.succeeded()) { SkPoint* verts = (SkPoint*) arg.vertices(); @@ -753,12 +753,13 @@ void GrContext::drawRect(const GrPaint& paint, // unitSquareVertexBuffer() static const int worstCaseVertCount = 10; - drawState.setDefaultVertexAttribs(); - drawState.setGeometryProcessor(GrDefaultGeoProcFactory::Create(false))->unref(); + const GrGeometryProcessor* gp = GrDefaultGeoProcFactory::Create(); + drawState.setGeometryProcessor(gp)->unref(); GrDrawTarget::AutoReleaseGeometry geo(target, worstCaseVertCount, - drawState.getVertexStride(), + gp->getVertexStride(), 0); + SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); if (!geo.succeeded()) { SkDebugf("Failed to get space for vertices!\n"); @@ -828,8 +829,7 @@ static void set_vertex_attributes(GrDrawState* drawState, *colorOffset = sizeof(SkPoint); flags |= GrDefaultGeoProcFactory::kColor_GPType; } - drawState->setGeometryProcessor(GrDefaultGeoProcFactory::CreateAndSetAttribs(drawState, - flags))->unref(); + drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(flags))->unref(); } void GrContext::drawVertices(const GrPaint& paint, @@ -854,7 +854,9 @@ void GrContext::drawVertices(const GrPaint& paint, int colorOffset = -1, texOffset = -1; set_vertex_attributes(&drawState, texCoords, colors, &colorOffset, &texOffset); - size_t vertexStride = drawState.getVertexStride(); + size_t vertexStride = drawState.getGeometryProcessor()->getVertexStride(); + SkASSERT(vertexStride == sizeof(SkPoint) + (SkToBool(texCoords) ? sizeof(SkPoint) : 0) + + (SkToBool(colors) ? sizeof(GrColor) : 0)); if (!geo.set(target, vertexCount, vertexStride, indexCount)) { SkDebugf("Failed to get space for vertices!\n"); return; @@ -1546,9 +1548,6 @@ GrDrawTarget* GrContext::prepareToDraw(GrDrawState* ds, SkDebugf("Partial pixel coverage will be incorrectly blended.\n"); } #endif - // Clear any vertex attributes configured for the previous use of the - // GrDrawState which can effect which blend optimizations are in effect. - ds->setDefaultVertexAttribs(); } else { ds->reset(fViewMatrix); ds->setRenderTarget(fRenderTarget.get()); diff --git a/src/gpu/GrDefaultGeoProcFactory.cpp b/src/gpu/GrDefaultGeoProcFactory.cpp index 332e73324c..ab28a579e7 100644 --- a/src/gpu/GrDefaultGeoProcFactory.cpp +++ b/src/gpu/GrDefaultGeoProcFactory.cpp @@ -7,22 +7,59 @@ #include "GrDefaultGeoProcFactory.h" -#include "gl/builders/GrGLProgramBuilder.h" -#include "gl/GrGLGeometryProcessor.h" #include "GrDrawState.h" #include "GrInvariantOutput.h" #include "GrTBackendProcessorFactory.h" +#include "gl/GrGLGeometryProcessor.h" +#include "gl/builders/GrGLProgramBuilder.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. */ +typedef GrDefaultGeoProcFactory Flag; + class DefaultGeoProc : public GrGeometryProcessor { public: - static GrGeometryProcessor* Create(bool hasCoverage) { - GR_CREATE_STATIC_PROCESSOR(gDefaultGeoProc, DefaultGeoProc, (hasCoverage)); - return SkRef(gDefaultGeoProc); + static GrGeometryProcessor* Create(uint32_t gpTypeFlags) { + switch (gpTypeFlags) { + case Flag::kColor_GPType | Flag::kCoverage_GPType | Flag::kLocalCoord_GPType: { + GR_CREATE_STATIC_PROCESSOR(gDefaultGeoProcColLocCov, DefaultGeoProc, (gpTypeFlags)); + return SkRef(gDefaultGeoProcColLocCov); + } + case Flag::kColor_GPType | Flag::kLocalCoord_GPType: { + GR_CREATE_STATIC_PROCESSOR(gDefaultGeoProcColLoc, DefaultGeoProc, (gpTypeFlags)); + return SkRef(gDefaultGeoProcColLoc); + } + case Flag::kColor_GPType | Flag::kCoverage_GPType: { + GR_CREATE_STATIC_PROCESSOR(gDefaultGeoProcColCov, DefaultGeoProc, (gpTypeFlags)); + return SkRef(gDefaultGeoProcColCov); + } + case Flag::kColor_GPType: { + GR_CREATE_STATIC_PROCESSOR(gDefaultGeoProcCol, DefaultGeoProc, (gpTypeFlags)); + return SkRef(gDefaultGeoProcCol); + } + case Flag::kLocalCoord_GPType | Flag::kCoverage_GPType: { + GR_CREATE_STATIC_PROCESSOR(gDefaultGeoProcLocCov, DefaultGeoProc, (gpTypeFlags)); + return SkRef(gDefaultGeoProcLocCov); + } + case Flag::kLocalCoord_GPType: { + GR_CREATE_STATIC_PROCESSOR(gDefaultGeoProcLoc, DefaultGeoProc, (gpTypeFlags)); + return SkRef(gDefaultGeoProcLoc); + } + case Flag::kCoverage_GPType: { + GR_CREATE_STATIC_PROCESSOR(gDefaultGeoProcCov, DefaultGeoProc, (gpTypeFlags)); + return SkRef(gDefaultGeoProcCov); + } + case Flag::kPosition_GPType: { + GR_CREATE_STATIC_PROCESSOR(gDefaultGeoProc, DefaultGeoProc, (gpTypeFlags)); + return SkRef(gDefaultGeoProc); + } + default: + SkFAIL("Incomplete Switch"); + return NULL; + } } static const char* Name() { return "DefaultGeometryProcessor"; } @@ -31,24 +68,51 @@ public: return GrTBackendGeometryProcessorFactory<DefaultGeoProc>::getInstance(); } + const GrAttribute* inPosition() const { return fInPosition; } + const GrAttribute* inColor() const { return fInColor; } + const GrAttribute* inLocalCoords() const { return fInLocalCoords; } + const GrAttribute* inCoverage() const { return fInCoverage; } + class GLProcessor : public GrGLGeometryProcessor { public: GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&) : INHERITED (factory) {} virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { + const DefaultGeoProc& gp = args.fGP.cast<DefaultGeoProc>(); GrGLVertexBuilder* vs = args.fPB->getVertexShaderBuilder(); + vs->codeAppendf("%s = %s;", vs->positionCoords(), gp.inPosition()->fName); + + // Setup pass through color + if (gp.inColor()) { + args.fPB->addPassThroughAttribute(gp.inColor(), args.fOutputColor); + } + + // Setup local coords if needed + if (gp.inLocalCoords()) { + vs->codeAppendf("%s = %s;", vs->localCoords(), gp.inLocalCoords()->fName); + } else { + vs->codeAppendf("%s = %s;", vs->localCoords(), gp.inPosition()->fName); + } + // setup position varying vs->codeAppendf("%s = %s * vec3(%s, 1);", vs->glPosition(), vs->uViewM(), - vs->inPosition()); + gp.inPosition()->fName); - // output coverage in FS(pass through) + // Setup coverage as pass through GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder(); - fs->codeAppendf("%s = %s;", args.fOutput, GrGLSLExpr4(args.fInput).c_str()); + fs->codeAppendf("float alpha = 1.0;"); + if (gp.inCoverage()) { + args.fPB->addPassThroughAttribute(gp.inCoverage(), "alpha"); + } + fs->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage); } - static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {} + static inline void GenKey(const GrProcessor& gp, const GrGLCaps&, GrProcessorKeyBuilder* b) { + const DefaultGeoProc& def = gp.cast<DefaultGeoProc>(); + b->add32(def.fFlags); + } virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE {} @@ -57,23 +121,52 @@ public: }; private: - DefaultGeoProc(bool hasCoverageAttribute) : fHasCoverageAttribute(hasCoverageAttribute) {} + DefaultGeoProc(uint32_t gpTypeFlags) + : fInPosition(NULL) + , fInColor(NULL) + , fInLocalCoords(NULL) + , fInCoverage(NULL) + , fFlags(gpTypeFlags) { + bool hasColor = SkToBool(gpTypeFlags & GrDefaultGeoProcFactory::kColor_GPType); + bool hasLocalCoord = SkToBool(gpTypeFlags & GrDefaultGeoProcFactory::kLocalCoord_GPType); + bool hasCoverage = SkToBool(gpTypeFlags & GrDefaultGeoProcFactory::kCoverage_GPType); + fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType)); + if (hasColor) { + fInColor = &this->addVertexAttrib(GrAttribute("inColor", kVec4ub_GrVertexAttribType)); + this->setHasVertexColor(); + } + if (hasLocalCoord) { + fInLocalCoords = &this->addVertexAttrib(GrAttribute("inLocalCoord", + kVec2f_GrVertexAttribType)); + this->setHasLocalCoords(); + } + if (hasCoverage) { + fInCoverage = &this->addVertexAttrib(GrAttribute("inCoverage", + kFloat_GrVertexAttribType)); + this->setHasVertexCoverage(); + } + } virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { - return true; + const DefaultGeoProc& gp = other.cast<DefaultGeoProc>(); + return gp.fFlags == this->fFlags; } virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE { - if (fHasCoverageAttribute) { + if (fInCoverage) { inout->mulByUnknownAlpha(); } else { inout->mulByKnownAlpha(255); } } - GR_DECLARE_GEOMETRY_PROCESSOR_TEST; + const GrAttribute* fInPosition; + const GrAttribute* fInColor; + const GrAttribute* fInLocalCoords; + const GrAttribute* fInCoverage; + uint32_t fFlags; - bool fHasCoverageAttribute; + GR_DECLARE_GEOMETRY_PROCESSOR_TEST; typedef GrFragmentProcessor INHERITED; }; @@ -84,112 +177,20 @@ 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; + uint32_t flags = 0; + if (random->nextBool()) { + flags |= GrDefaultGeoProcFactory::kColor_GPType; } -} - -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<kDefaultPosColLocalCoordGeoProc>(count, size); - } else { - ds->setVertexAttribs<kDefaultPosColLocalCoordGeoProc>(count, size); - - } - } else { - if (hasCoverage) { - size += get_size(kCoverage_GPType); - count++; - ds->setVertexAttribs<kDefaultPosColorGeoProc>(count, size); - } else { - ds->setVertexAttribs<kDefaultPosColorGeoProc>(count, size); - } - } - } else if (hasLocalCoord) { - size += get_size(kLocalCoord_GPType); - count++; - if (hasCoverage) { - size += get_size(kCoverage_GPType); - count++; - ds->setVertexAttribs<kDefaultPosLocalCoordGeoProc>(count, size); - } else { - ds->setVertexAttribs<kDefaultPosLocalCoordGeoProc>(count, size); - } - } else if (hasCoverage) { - size += get_size(kCoverage_GPType); - count++; - ds->setVertexAttribs<kDefaultPositionGeoProc>(count, size); - } else { - // Just position - ds->setVertexAttribs<kDefaultPositionGeoProc>(count, size); + if (random->nextBool()) { + flags |= GrDefaultGeoProcFactory::kCoverage_GPType; + } + if (random->nextBool()) { + flags |= GrDefaultGeoProcFactory::kLocalCoord_GPType; } -} - -const GrGeometryProcessor* -GrDefaultGeoProcFactory::CreateAndSetAttribs(GrDrawState* ds, uint32_t gpTypeFlags) { - SetAttribs(ds, gpTypeFlags); - bool hasCoverage = SkToBool(gpTypeFlags & kCoverage_GPType); - return DefaultGeoProc::Create(hasCoverage); + return DefaultGeoProc::Create(flags); } -const GrGeometryProcessor* GrDefaultGeoProcFactory::Create(bool hasAttributeCoverage) { - return DefaultGeoProc::Create(hasAttributeCoverage); +const GrGeometryProcessor* GrDefaultGeoProcFactory::Create(uint32_t gpTypeFlags) { + return DefaultGeoProc::Create(gpTypeFlags); } diff --git a/src/gpu/GrDefaultGeoProcFactory.h b/src/gpu/GrDefaultGeoProcFactory.h index 99d85b64d6..a39c76da19 100644 --- a/src/gpu/GrDefaultGeoProcFactory.h +++ b/src/gpu/GrDefaultGeoProcFactory.h @@ -17,8 +17,6 @@ class GrDrawState; * view matrix and wire through color, coverage, UV coords if requested. Right now this is only * used in the creation of optimized draw states because adding default GPs to the drawstate can * interfere with batching due to updating the drawstate. - * TODO When we track geometry state separately from the draw state, we should be able use a default - * GP with every draw call */ class GrDefaultGeoProcFactory { public: @@ -82,9 +80,7 @@ public: * * You must unref the return from Create. */ - static void SetAttribs(GrDrawState*, uint32_t GPTypeFlags = 0); - static const GrGeometryProcessor* CreateAndSetAttribs(GrDrawState*, uint32_t GPTypeFlags = 0); - static const GrGeometryProcessor* Create(bool hasAttributeCoverage); + static const GrGeometryProcessor* Create(uint32_t gpTypeFlags = 0); }; #endif diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp index 3b31e876a2..4d9026f086 100644 --- a/src/gpu/GrDefaultPathRenderer.cpp +++ b/src/gpu/GrDefaultPathRenderer.cpp @@ -233,10 +233,12 @@ bool GrDefaultPathRenderer::createGeom(GrDrawTarget* target, } } - drawState->setDefaultVertexAttribs(); - if (!arg->set(target, maxPts, drawState->getVertexStride(), maxIdxs)) { + // TODO this is really wierd, I just need default vertex stride, can I think of a better way? + SkAutoTUnref<const GrGeometryProcessor> gp(GrDefaultGeoProcFactory::Create()); + if (!arg->set(target, maxPts, gp->getVertexStride(), maxIdxs)) { return false; } + SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); uint16_t* idxBase = reinterpret_cast<uint16_t*>(arg->indices()); uint16_t* idx = idxBase; @@ -497,7 +499,7 @@ bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target, drawState->enableState(GrDrawState::kNoColorWrites_StateBit); } GrDrawState::AutoRestoreEffects are(drawState); - drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(false))->unref(); + drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create())->unref(); if (indexCnt) { target->drawIndexed(drawState, primType, diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp index a012bc28b7..99aed573b6 100755 --- a/src/gpu/GrDistanceFieldTextContext.cpp +++ b/src/gpu/GrDistanceFieldTextContext.cpp @@ -38,27 +38,11 @@ static const int kMediumDFFontSize = 78; static const int kMediumDFFontLimit = 78; static const int kLargeDFFontSize = 192; -namespace { -// position + texture coord -extern const GrVertexAttrib gTextVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec2f_GrVertexAttribType, sizeof(SkPoint) , kGeometryProcessor_GrVertexAttribBinding} -}; - static const size_t kTextVASize = 2 * sizeof(SkPoint); - -// position + color + texture coord -extern const GrVertexAttrib gTextVertexWithColorAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding}, - {kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kGeometryProcessor_GrVertexAttribBinding} -}; - static const size_t kTextVAColorSize = 2 * sizeof(SkPoint) + sizeof(GrColor); static const int kVerticesPerGlyph = 4; static const int kIndicesPerGlyph = 6; -}; GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context, const SkDeviceProperties& properties, @@ -432,6 +416,7 @@ void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo colorNoPreMul, flags)); } else { + flags |= kColorAttr_DistanceFieldEffectFlag; #ifdef SK_GAMMA_APPLY_TO_A8 U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.gamma(), filteredColor); @@ -618,18 +603,6 @@ HAS_ATLAS: return true; } -// We use color vertices if we aren't drawing LCD text -static void set_vertex_attributes(GrDrawState* drawState, bool useColorVerts) { - // set up attributes - if (useColorVerts) { - drawState->setVertexAttribs<gTextVertexWithColorAttribs>( - SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize); - } else { - drawState->setVertexAttribs<gTextVertexAttribs>( - SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize); - } -} - void GrDistanceFieldTextContext::flush() { if (NULL == fDrawTarget) { return; @@ -638,8 +611,6 @@ void GrDistanceFieldTextContext::flush() { if (fCurrVertex > 0) { GrDrawState drawState; drawState.setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTarget()); - bool useColorVerts = !fUseLCDText; - set_vertex_attributes(&drawState, useColorVerts); // setup our sampler state for our text texture/atlas SkASSERT(SkIsAlign4(fCurrVertex)); diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp index 7538cdb340..ff58c4899a 100644 --- a/src/gpu/GrDrawState.cpp +++ b/src/gpu/GrDrawState.cpp @@ -28,9 +28,6 @@ bool GrDrawState::isEqual(const GrDrawState& that) const { this->fDstBlend != that.fDstBlend || this->fBlendConstant != that.fBlendConstant || this->fFlagBits != that.fFlagBits || - this->fVACount != that.fVACount || - this->fVAStride != that.fVAStride || - memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) || this->fStencilSettings != that.fStencilSettings || this->fDrawFace != that.fDrawFace) { return false; @@ -65,10 +62,6 @@ bool GrDrawState::isEqual(const GrDrawState& that) const { } } - SkASSERT(0 == memcmp(this->fFixedFunctionVertexAttribIndices, - that.fFixedFunctionVertexAttribIndices, - sizeof(this->fFixedFunctionVertexAttribIndices))); - return true; } @@ -95,9 +88,6 @@ GrDrawState& GrDrawState::operator=(const GrDrawState& that) { fDstBlend = that.fDstBlend; fBlendConstant = that.fBlendConstant; fFlagBits = that.fFlagBits; - fVACount = that.fVACount; - fVAPtr = that.fVAPtr; - fVAStride = that.fVAStride; fStencilSettings = that.fStencilSettings; fCoverage = that.fCoverage; fDrawFace = that.fDrawFace; @@ -115,10 +105,6 @@ GrDrawState& GrDrawState::operator=(const GrDrawState& that) { if (fCoverageProcInfoValid) { fCoverageProcInfo = that.fCoverageProcInfo; } - - memcpy(fFixedFunctionVertexAttribIndices, - that.fFixedFunctionVertexAttribIndices, - sizeof(fFixedFunctionVertexAttribIndices)); return *this; } @@ -130,9 +116,6 @@ void GrDrawState::onReset(const SkMatrix* initialViewMatrix) { fColorStages.reset(); fCoverageStages.reset(); - - this->setDefaultVertexAttribs(); - fColor = 0xffffffff; if (NULL == initialViewMatrix) { fViewMatrix.reset(); @@ -212,126 +195,6 @@ void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRende //////////////////////////////////////////////////////////////////////////////// -bool GrDrawState::validateVertexAttribs() const { - // check consistency of effects and attributes - GrSLType slTypes[kMaxVertexAttribCnt]; - for (int i = 0; i < kMaxVertexAttribCnt; ++i) { - slTypes[i] = static_cast<GrSLType>(-1); - } - - if (this->hasGeometryProcessor()) { - const GrGeometryProcessor* gp = this->getGeometryProcessor(); - // make sure that any attribute indices have the correct binding type, that the attrib - // type and effect's shader lang type are compatible, and that attributes shared by - // multiple effects use the same shader lang type. - const GrGeometryProcessor::VertexAttribArray& s = gp->getVertexAttribs(); - - int effectIndex = 0; - for (int index = 0; index < fVACount; index++) { - if (kGeometryProcessor_GrVertexAttribBinding != fVAPtr[index].fBinding) { - // we only care about effect bindings - continue; - } - SkASSERT(effectIndex < s.count()); - GrSLType effectSLType = s[effectIndex].getType(); - GrVertexAttribType attribType = fVAPtr[index].fType; - int slVecCount = GrSLTypeVectorCount(effectSLType); - int attribVecCount = GrVertexAttribTypeVectorCount(attribType); - if (slVecCount != attribVecCount || - (static_cast<GrSLType>(-1) != slTypes[index] && slTypes[index] != effectSLType)) { - return false; - } - slTypes[index] = effectSLType; - effectIndex++; - } - // Make sure all attributes are consumed and we were able to find everything - SkASSERT(s.count() == effectIndex); - } - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// - -static void validate_vertex_attribs(const GrVertexAttrib* attribs, int count, size_t stride) { - // this works as long as we're 4 byte-aligned -#ifdef SK_DEBUG - uint32_t overlapCheck = 0; - SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt); - for (int index = 0; index < count; ++index) { - size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType); - size_t attribOffset = attribs[index].fOffset; - SkASSERT(attribOffset + attribSize <= stride); - size_t dwordCount = attribSize >> 2; - uint32_t mask = (1 << dwordCount)-1; - size_t offsetShift = attribOffset >> 2; - SkASSERT(!(overlapCheck & (mask << offsetShift))); - overlapCheck |= (mask << offsetShift); - } -#endif -} - -//////////////////////////////////////////////////////////////////////////////// - -void GrDrawState::internalSetVertexAttribs(const GrVertexAttrib* attribs, int count, - size_t stride) { - SkASSERT(count <= kMaxVertexAttribCnt); - - fVAPtr = attribs; - fVACount = count; - fVAStride = stride; - validate_vertex_attribs(fVAPtr, fVACount, fVAStride); - - // Set all the indices to -1 - memset(fFixedFunctionVertexAttribIndices, - 0xff, - sizeof(fFixedFunctionVertexAttribIndices)); -#ifdef SK_DEBUG - uint32_t overlapCheck = 0; -#endif - for (int i = 0; i < count; ++i) { - if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) { - // The fixed function attribs can only be specified once - SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]); - SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) == - GrVertexAttribTypeVectorCount(attribs[i].fType)); - fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i; - } -#ifdef SK_DEBUG - size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2; - uint32_t mask = (1 << dwordCount)-1; - size_t offsetShift = attribs[i].fOffset >> 2; - SkASSERT(!(overlapCheck & (mask << offsetShift))); - overlapCheck |= (mask << offsetShift); -#endif - } - fColorProcInfoValid = false; - fCoverageProcInfoValid = false; - // Positions must be specified. - SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]); -} - -//////////////////////////////////////////////////////////////////////////////// - -void GrDrawState::setDefaultVertexAttribs() { - static const GrVertexAttrib kPositionAttrib = - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}; - - fVAPtr = &kPositionAttrib; - fVACount = 1; - fVAStride = GrVertexAttribTypeSize(kVec2f_GrVertexAttribType); - - // set all the fixed function indices to -1 except position. - memset(fFixedFunctionVertexAttribIndices, - 0xff, - sizeof(fFixedFunctionVertexAttribIndices)); - fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0; - fColorProcInfoValid = false; - fCoverageProcInfoValid = false; -} - -//////////////////////////////////////////////////////////////////////////////// - bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const { if (caps.dualSourceBlendingSupport()) { return true; @@ -361,17 +224,6 @@ bool GrDrawState::hasSolidCoverage() const { return fCoverageProcInfo.isSolidWhite(); } -////////////////////////////////////////////////////////////////////////////// - -GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawState) { - SkASSERT(drawState); - fDrawState = drawState; - fVAPtr = drawState->fVAPtr; - fVACount = drawState->fVACount; - fVAStride = drawState->fVAStride; - fDrawState->setDefaultVertexAttribs(); -} - //////////////////////////////////////////////////////////////////////////////s bool GrDrawState::willEffectReadDstColor() const { diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index a049f1d807..a236d1a559 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -70,74 +70,17 @@ public: /// @name Vertex Attributes //// - enum { - kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4, - }; - - const GrVertexAttrib* getVertexAttribs() const { return fVAPtr; } - int getVertexAttribCount() const { return fVACount; } - - size_t getVertexStride() const { return fVAStride; } - + // TODO when we move this info off of GrGeometryProcessor, delete these bool hasLocalCoordAttribute() const { - return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding]; + return this->hasGeometryProcessor() && this->getGeometryProcessor()->hasLocalCoords(); } bool hasColorVertexAttribute() const { - return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding]; + return this->hasGeometryProcessor() && this->getGeometryProcessor()->hasVertexColor(); } bool hasCoverageVertexAttribute() const { - return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding]; + return this->hasGeometryProcessor() && this->getGeometryProcessor()->hasVertexCoverage(); } - const int* getFixedFunctionVertexAttribIndices() const { - return fFixedFunctionVertexAttribIndices; - } - - bool validateVertexAttribs() const; - - /** - * The format of vertices is represented as an array of GrVertexAttribs, with each representing - * the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in - * GrTypesPriv.h). - * - * The mapping of attributes with kEffect bindings to GrProcessor inputs is specified when - * setEffect is called. - */ - - /** - * Sets vertex attributes for next draw. The object driving the templatization - * should be a global GrVertexAttrib array that is never changed. - * - * @param count the number of attributes being set, limited to kMaxVertexAttribCnt. - * @param stride the number of bytes between successive vertex data. - */ - template <const GrVertexAttrib A[]> void setVertexAttribs(int count, size_t stride) { - this->internalSetVertexAttribs(A, count, stride); - } - - /** - * Sets default vertex attributes for next draw. The default is a single attribute: - * {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType} - */ - void setDefaultVertexAttribs(); - - /** - * Helper to save/restore vertex attribs - */ - class AutoVertexAttribRestore { - public: - AutoVertexAttribRestore(GrDrawState* drawState); - - ~AutoVertexAttribRestore() { fDrawState->internalSetVertexAttribs(fVAPtr, fVACount, - fVAStride); } - - private: - GrDrawState* fDrawState; - const GrVertexAttrib* fVAPtr; - int fVACount; - size_t fVAStride; - }; - /// @} /** @@ -765,8 +708,6 @@ private: // This is used to assert that this condition holds. SkDEBUGCODE(int fBlockEffectRemovalCnt;) - void internalSetVertexAttribs(const GrVertexAttrib attribs[], int count, size_t stride); - typedef SkSTArray<4, GrFragmentStage> FragmentStageArray; SkAutoTUnref<GrRenderTarget> fRenderTarget; @@ -774,9 +715,6 @@ private: SkMatrix fViewMatrix; GrColor fBlendConstant; uint32_t fFlagBits; - const GrVertexAttrib* fVAPtr; - int fVACount; - size_t fVAStride; GrStencilSettings fStencilSettings; uint8_t fCoverage; DrawFace fDrawFace; @@ -787,10 +725,6 @@ private: FragmentStageArray fCoverageStages; uint32_t fHints; - // This is simply a different representation of info in fVertexAttribs and thus does - // not need to be compared in op==. - int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt]; - mutable GrProcOptInfo fColorProcInfo; mutable GrProcOptInfo fCoverageProcInfo; mutable bool fColorProcInfoValid; diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index c385f27100..7728ea5497 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -375,7 +375,6 @@ bool GrDrawTarget::checkDraw(const GrDrawState& drawState, } } - SkASSERT(drawState.validateVertexAttribs()); #endif if (NULL == drawState.getRenderTarget()) { return false; @@ -472,7 +471,7 @@ void GrDrawTarget::drawIndexed(GrDrawState* ds, if (!this->setupDstReadIfNecessary(ds, &dstCopy, devBounds)) { return; } - this->setDrawBuffers(&info, ds->getVertexStride()); + this->setDrawBuffers(&info, ds->getGeometryProcessor()->getVertexStride()); this->onDraw(*ds, info, scissorState, dstCopy.texture() ? &dstCopy : NULL); } @@ -515,7 +514,7 @@ void GrDrawTarget::drawNonIndexed(GrDrawState* ds, return; } - this->setDrawBuffers(&info, ds->getVertexStride()); + this->setDrawBuffers(&info, ds->getGeometryProcessor()->getVertexStride()); this->onDraw(*ds, info, scissorState, dstCopy.texture() ? &dstCopy : NULL); } @@ -779,7 +778,7 @@ void GrDrawTarget::drawIndexedInstances(GrDrawState* ds, info.fStartIndex, info.fVertexCount, info.fIndexCount)) { - this->setDrawBuffers(&info, ds->getVertexStride()); + this->setDrawBuffers(&info, ds->getGeometryProcessor()->getVertexStride()); this->onDraw(*ds, info, scissorState, dstCopy.texture() ? &dstCopy : NULL); } info.fStartVertex += info.fVertexCount; diff --git a/src/gpu/GrGeometryProcessor.h b/src/gpu/GrGeometryProcessor.h index 6d27f0b4f1..17344d2bb4 100644 --- a/src/gpu/GrGeometryProcessor.h +++ b/src/gpu/GrGeometryProcessor.h @@ -13,7 +13,7 @@ #include "GrShaderVar.h" /** - * A GrGeomteryProcessor is used to perform computation in the vertex shader and + * A GrGeometryProcessor is used to perform computation in the vertex shader and * add support for custom vertex attributes. A GrGemeotryProcessor is typically * tied to the code that does a specific type of high-level primitive rendering * (e.g. anti-aliased circle rendering). The GrGeometryProcessor used for a draw is @@ -25,19 +25,38 @@ class GrGeometryProcessor : public GrProcessor { public: GrGeometryProcessor() - : fWillUseGeoShader(false) {} + : fVertexStride(0) + , fWillUseGeoShader(false) + , fHasVertexColor(false) + , fHasVertexCoverage(false) + , fHasLocalCoords(false) {} virtual const GrBackendGeometryProcessorFactory& getFactory() const = 0; /* - * This only has a max because GLProgramsTest needs to generate test arrays, and these have to - * be static - * TODO make this truly dynamic + * This is a safeguard to prevent GPs from going beyond platform specific attribute limits. + * This number can almost certainly be raised if required. */ - static const int kMaxVertexAttribs = 2; - typedef SkTArray<GrShaderVar, true> VertexAttribArray; + static const int kMaxVertexAttribs = 6; - const VertexAttribArray& getVertexAttribs() const { return fVertexAttribs; } + struct GrAttribute { + GrAttribute(const char* name, GrVertexAttribType type) + : fName(name) + , fType(type) + , fOffset(SkAlign4(GrVertexAttribTypeSize(type))) {} + const char* fName; + GrVertexAttribType fType; + size_t fOffset; + }; + + typedef SkTArray<GrAttribute, true> VertexAttribArray; + + const VertexAttribArray& getAttribs() const { return fAttribs; } + + // Returns the vertex stride of the GP. A common use case is to request geometry from a + // drawtarget based off of the stride, and to populate this memory using an implicit array of + // structs. In this case, it is best to assert the vertexstride == sizeof(VertexStruct). + size_t getVertexStride() const { return fVertexStride; } bool willUseGeoShader() const { return fWillUseGeoShader; } @@ -54,24 +73,40 @@ public: return this->onIsEqual(that); } + // TODO this is a total hack until the gp can own whether or not it uses uniform + // color / coverage + bool hasVertexColor() const { return fHasVertexColor; } + bool hasVertexCoverage() const { return fHasVertexCoverage; } + bool hasLocalCoords() const { return fHasLocalCoords; } + protected: /** - * Subclasses call this from their constructor to register vertex attributes (at most - * kMaxVertexAttribs). This must only be called from the constructor because GrProcessors are - * immutable. + * Subclasses call this from their constructor to register vertex attributes. Attributes + * will be padded to the nearest 4 bytes for performance reasons. + * TODO After deferred geometry, we should do all of this inline in GenerateGeometry alongside + * the struct used to actually populate the attributes */ - const GrShaderVar& addVertexAttrib(const GrShaderVar& var) { - SkASSERT(fVertexAttribs.count() < kMaxVertexAttribs); - return fVertexAttribs.push_back(var); + const GrAttribute& addVertexAttrib(const GrAttribute& attribute) { + fVertexStride += attribute.fOffset; + return fAttribs.push_back(attribute); } void setWillUseGeoShader() { fWillUseGeoShader = true; } + // TODO hack see above + void setHasVertexColor() { fHasVertexColor = true; } + void setHasVertexCoverage() { fHasVertexCoverage = true; } + void setHasLocalCoords() { fHasLocalCoords = true; } + private: virtual bool onIsEqual(const GrGeometryProcessor&) const = 0; - SkSTArray<kMaxVertexAttribs, GrShaderVar, true> fVertexAttribs; + SkSTArray<kMaxVertexAttribs, GrAttribute, true> fAttribs; + size_t fVertexStride; bool fWillUseGeoShader; + bool fHasVertexColor; + bool fHasVertexCoverage; + bool fHasLocalCoords; typedef GrProcessor INHERITED; }; diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp index 6b98e13439..5533174853 100644 --- a/src/gpu/GrInOrderDrawBuffer.cpp +++ b/src/gpu/GrInOrderDrawBuffer.cpp @@ -66,8 +66,7 @@ static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, G uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType | GrDefaultGeoProcFactory::kColor_GPType; flags |= hasLocalCoords ? GrDefaultGeoProcFactory::kLocalCoord_GPType : 0; - drawState->setGeometryProcessor(GrDefaultGeoProcFactory::CreateAndSetAttribs(drawState, - flags))->unref(); + drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(flags))->unref(); if (0xFF == GrColorUnpackA(color)) { drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true); } @@ -119,7 +118,10 @@ void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds, GrColor color = ds->getColor(); set_vertex_attributes(ds, SkToBool(localRect), color); - AutoReleaseGeometry geo(this, 4, ds->getVertexStride(), 0); + size_t vstride = ds->getGeometryProcessor()->getVertexStride(); + SkASSERT(vstride == sizeof(SkPoint) + sizeof(GrColor) + (SkToBool(localRect) ? sizeof(SkPoint) : + 0)); + AutoReleaseGeometry geo(this, 4, vstride, 0); if (!geo.succeeded()) { SkDebugf("Failed to get space for vertices!\n"); return; @@ -136,8 +138,6 @@ void GrInOrderDrawBuffer::onDrawRect(GrDrawState* ds, return; } - size_t vstride = ds->getVertexStride(); - geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride); matrix.mapPointsWithStride(geo.positions(), vstride, 4); diff --git a/src/gpu/GrOptDrawState.cpp b/src/gpu/GrOptDrawState.cpp index a494b171de..41a34c4ed2 100644 --- a/src/gpu/GrOptDrawState.cpp +++ b/src/gpu/GrOptDrawState.cpp @@ -7,7 +7,6 @@ #include "GrOptDrawState.h" -#include "GrDefaultGeoProcFactory.h" #include "GrDrawState.h" #include "GrDrawTargetCaps.h" #include "GrGpu.h" @@ -30,9 +29,6 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, // Set the fields that don't default init and return. The lack of a render target will // indicate that this can be skipped. fFlags = 0; - fVAPtr = NULL; - fVACount = 0; - fVAStride = 0; fDrawFace = GrDrawState::kInvalid_DrawFace; fSrcBlend = kZero_GrBlendCoeff; fDstBlend = kZero_GrBlendCoeff; @@ -46,9 +42,6 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, fScissorState = scissorState; fViewMatrix = drawState.getViewMatrix(); fBlendConstant = drawState.getBlendConstant(); - fVAPtr = drawState.getVertexAttribs(); - fVACount = drawState.getVertexAttribCount(); - fVAStride = drawState.getVertexStride(); fStencilSettings = drawState.getStencil(); fDrawFace = drawState.getDrawFace(); fSrcBlend = optSrcCoeff; @@ -72,18 +65,21 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, fFlags |= kDither_Flag; } - memcpy(descInfo.fFixedFunctionVertexAttribIndices, - drawState.getFixedFunctionVertexAttribIndices(), - sizeof(descInfo.fFixedFunctionVertexAttribIndices)); + descInfo.fHasVertexColor = drawState.hasGeometryProcessor() && + drawState.getGeometryProcessor()->hasVertexColor(); - uint8_t fixedFunctionVAToRemove = 0; + descInfo.fHasVertexCoverage = drawState.hasGeometryProcessor() && + drawState.getGeometryProcessor()->hasVertexCoverage(); + + bool hasLocalCoords = drawState.hasGeometryProcessor() && + drawState.getGeometryProcessor()->hasLocalCoords(); const GrProcOptInfo& colorPOI = drawState.colorProcInfo(); int firstColorStageIdx = colorPOI.firstEffectiveStageIndex(); descInfo.fInputColorIsUsed = colorPOI.inputColorIsUsed(); fColor = colorPOI.inputColorToEffectiveStage(); if (colorPOI.removeVertexAttrib()) { - fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding; + descInfo.fHasVertexColor = false; } // TODO: Once we can handle single or four channel input into coverage stages then we can use @@ -93,12 +89,10 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, fCoverage = drawState.getCoverage(); this->adjustProgramForBlendOpt(drawState, blendOpt, &descInfo, &firstColorStageIdx, - &firstCoverageStageIdx, &fixedFunctionVAToRemove); - // Should not be setting any more FFVA to be removed at this point - if (0 != fixedFunctionVAToRemove) { - this->removeFixedFunctionVertexAttribs(fixedFunctionVAToRemove, &descInfo); - } - this->getStageStats(drawState, firstColorStageIdx, firstCoverageStageIdx, &descInfo); + &firstCoverageStageIdx); + + this->getStageStats(drawState, firstColorStageIdx, firstCoverageStageIdx, hasLocalCoords, + &descInfo); // Copy GeometryProcesssor from DS or ODS SkASSERT(GrGpu::IsPathRenderingDrawType(drawType) || @@ -107,18 +101,16 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, fGeometryProcessor.reset(drawState.getGeometryProcessor()); // Copy Stages from DS to ODS - bool explicitLocalCoords = descInfo.hasLocalCoordAttribute(); - for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) { SkNEW_APPEND_TO_TARRAY(&fFragmentStages, GrPendingFragmentStage, - (drawState.fColorStages[i], explicitLocalCoords)); + (drawState.fColorStages[i], hasLocalCoords)); } fNumColorStages = fFragmentStages.count(); for (int i = firstCoverageStageIdx; i < drawState.numCoverageStages(); ++i) { SkNEW_APPEND_TO_TARRAY(&fFragmentStages, GrPendingFragmentStage, - (drawState.fCoverageStages[i], explicitLocalCoords)); + (drawState.fCoverageStages[i], hasLocalCoords)); } this->setOutputStateInfo(drawState, blendOpt, *gpu->caps(), &descInfo); @@ -166,8 +158,7 @@ void GrOptDrawState::adjustProgramForBlendOpt(const GrDrawState& ds, GrDrawState::BlendOpt blendOpt, GrProgramDesc::DescInfo* descInfo, int* firstColorStageIdx, - int* firstCoverageStageIdx, - uint8_t* fixedFunctionVAToRemove) { + int* firstCoverageStageIdx) { switch (blendOpt) { case GrDrawState::kNone_BlendOpt: case GrDrawState::kSkipDraw_BlendOpt: @@ -177,7 +168,7 @@ void GrOptDrawState::adjustProgramForBlendOpt(const GrDrawState& ds, fColor = 0xffffffff; descInfo->fInputColorIsUsed = true; *firstColorStageIdx = ds.numColorStages(); - *fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding; + descInfo->fHasVertexColor = false; break; case GrDrawState::kEmitTransBlack_BlendOpt: fColor = 0; @@ -186,48 +177,12 @@ void GrOptDrawState::adjustProgramForBlendOpt(const GrDrawState& ds, descInfo->fInputCoverageIsUsed = true; *firstColorStageIdx = ds.numColorStages(); *firstCoverageStageIdx = ds.numCoverageStages(); - *fixedFunctionVAToRemove |= (0x1 << kColor_GrVertexAttribBinding | - 0x1 << kCoverage_GrVertexAttribBinding); + descInfo->fHasVertexColor = false; + descInfo->fHasVertexCoverage = false; break; } } -void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag, - GrProgramDesc::DescInfo* descInfo) { - int numToRemove = 0; - uint8_t maskCheck = 0x1; - // Count the number of vertex attributes that we will actually remove - for (int i = 0; i < kGrFixedFunctionVertexAttribBindingCnt; ++i) { - if ((maskCheck & removeVAFlag) && -1 != descInfo->fFixedFunctionVertexAttribIndices[i]) { - ++numToRemove; - } - maskCheck <<= 1; - } - - fOptVA.reset(fVACount - numToRemove); - - GrVertexAttrib* dst = fOptVA.get(); - const GrVertexAttrib* src = fVAPtr; - - for (int i = 0, newIdx = 0; i < fVACount; ++i, ++src) { - const GrVertexAttrib& currAttrib = *src; - if (currAttrib.fBinding < kGrFixedFunctionVertexAttribBindingCnt) { - uint8_t maskCheck = 0x1 << currAttrib.fBinding; - if (maskCheck & removeVAFlag) { - SkASSERT(-1 != descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding]); - descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1; - continue; - } - descInfo->fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx; - } - memcpy(dst, src, sizeof(GrVertexAttrib)); - ++newIdx; - ++dst; - } - fVACount -= numToRemove; - fVAPtr = fOptVA.get(); -} - static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) { if (stage.getProcessor()->willReadDstColor()) { *readsDst = true; @@ -238,10 +193,11 @@ static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* } void GrOptDrawState::getStageStats(const GrDrawState& ds, int firstColorStageIdx, - int firstCoverageStageIdx, GrProgramDesc::DescInfo* descInfo) { + int firstCoverageStageIdx, bool hasLocalCoords, + GrProgramDesc::DescInfo* descInfo) { // We will need a local coord attrib if there is one currently set on the optState and we are // actually generating some effect code - descInfo->fRequiresLocalCoordAttrib = descInfo->hasLocalCoordAttribute() && + descInfo->fRequiresLocalCoordAttrib = hasLocalCoords && ds.numTotalStages() - firstColorStageIdx - firstCoverageStageIdx > 0; descInfo->fReadsDst = false; @@ -267,8 +223,8 @@ bool GrOptDrawState::operator== (const GrOptDrawState& that) const { if (this->fDesc != that.fDesc) { return false; } - bool usingVertexColors = that.fDesc.header().fColorAttributeIndex != -1; - if (!usingVertexColors && this->fColor != that.fColor) { + bool hasVertexColors = this->fDesc.header().fColorInput == GrProgramDesc::kAttribute_ColorInput; + if (!hasVertexColors && this->fColor != that.fColor) { return false; } @@ -279,17 +235,15 @@ bool GrOptDrawState::operator== (const GrOptDrawState& that) const { this->fDstBlend != that.fDstBlend || this->fBlendConstant != that.fBlendConstant || this->fFlags != that.fFlags || - this->fVACount != that.fVACount || - this->fVAStride != that.fVAStride || - memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) || this->fStencilSettings != that.fStencilSettings || this->fDrawFace != that.fDrawFace || this->fDstCopy.texture() != that.fDstCopy.texture()) { return false; } - bool usingVertexCoverage = this->fDesc.header().fCoverageAttributeIndex != -1; - if (!usingVertexCoverage && this->fCoverage != that.fCoverage) { + bool hasVertexCoverage = + this->fDesc.header().fCoverageInput == GrProgramDesc::kAttribute_ColorInput; + if (!hasVertexCoverage && this->fCoverage != that.fCoverage) { return false; } diff --git a/src/gpu/GrOptDrawState.h b/src/gpu/GrOptDrawState.h index bf4f78e5ef..542172fd64 100644 --- a/src/gpu/GrOptDrawState.h +++ b/src/gpu/GrOptDrawState.h @@ -36,19 +36,6 @@ public: bool operator== (const GrOptDrawState& that) const; bool operator!= (const GrOptDrawState& that) const { return !(*this == that); } - /////////////////////////////////////////////////////////////////////////// - /// @name Vertex Attributes - //// - - enum { - kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4, - }; - - const GrVertexAttrib* getVertexAttribs() const { return fVAPtr; } - int getVertexAttribCount() const { return fVACount; } - - size_t getVertexStride() const { return fVAStride; } - /// @} /////////////////////////////////////////////////////////////////////////// @@ -213,26 +200,18 @@ private: int* firstCoverageStageIdx); /** - * This function takes in a flag and removes the corresponding fixed function vertex attributes. - * The flags are in the same order as GrVertexAttribBinding array. If bit i of removeVAFlags is - * set, then vertex attributes with binding (GrVertexAttribute)i will be removed. - */ - void removeFixedFunctionVertexAttribs(uint8_t removeVAFlags, GrProgramDesc::DescInfo*); - - /** * Alter the program desc and inputs (attribs and processors) based on the blend optimization. */ void adjustProgramForBlendOpt(const GrDrawState& ds, GrDrawState::BlendOpt, GrProgramDesc::DescInfo*, - int* firstColorStageIdx, int* firstCoverageStageIdx, - uint8_t* fixedFunctionVAToRemove); + int* firstColorStageIdx, int* firstCoverageStageIdx); /** * Loop over the effect stages to determine various info like what data they will read and what * shaders they require. */ void getStageStats(const GrDrawState& ds, int firstColorStageIdx, int firstCoverageStageIdx, - GrProgramDesc::DescInfo*); + bool hasLocalCoords, GrProgramDesc::DescInfo*); /** * Calculates the primary and secondary output types of the shader. For certain output types @@ -256,9 +235,6 @@ private: GrColor fColor; SkMatrix fViewMatrix; GrColor fBlendConstant; - const GrVertexAttrib* fVAPtr; - int fVACount; - size_t fVAStride; GrStencilSettings fStencilSettings; uint8_t fCoverage; GrDrawState::DrawFace fDrawFace; @@ -272,8 +248,6 @@ private: // This function is equivalent to the offset into fFragmentStages where coverage stages begin. int fNumColorStages; - SkAutoSTArray<4, GrVertexAttrib> fOptVA; - GrProgramDesc fDesc; typedef SkRefCnt INHERITED; diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp index 42844ee9ea..a9dda840aa 100644 --- a/src/gpu/GrOvalRenderer.cpp +++ b/src/gpu/GrOvalRenderer.cpp @@ -76,7 +76,8 @@ public: } } - const GrShaderVar& inCircleEdge() const { return fInCircleEdge; } + const GrAttribute* inPosition() const { return fInPosition; } + const GrAttribute* inCircleEdge() const { return fInCircleEdge; } virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE { return GrTBackendGeometryProcessorFactory<CircleEdgeEffect>::getInstance(); @@ -94,28 +95,31 @@ public: : INHERITED (factory) {} virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { - const CircleEdgeEffect& circleEffect = args.fGP.cast<CircleEdgeEffect>(); + const CircleEdgeEffect& ce = args.fGP.cast<CircleEdgeEffect>(); + GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); + GrGLVertToFrag v(kVec4f_GrSLType); args.fPB->addVarying("CircleEdge", &v); + vsBuilder->codeAppendf("%s = %s;", v.vsOut(), ce.inCircleEdge()->fName); - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();; - vsBuilder->codeAppendf("%s = %s;", v.vsOut(), circleEffect.inCircleEdge().c_str()); + // setup coord outputs + vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), ce.inPosition()->fName); + vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), ce.inPosition()->fName); // setup position varying vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), - vsBuilder->uViewM(), vsBuilder->inPosition()); + vsBuilder->uViewM(), ce.inPosition()->fName); GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); fsBuilder->codeAppendf("float d = length(%s.xy);", v.fsIn()); fsBuilder->codeAppendf("float edgeAlpha = clamp(%s.z - d, 0.0, 1.0);", v.fsIn()); - if (circleEffect.isStroked()) { + if (ce.isStroked()) { fsBuilder->codeAppendf("float innerAlpha = clamp(d - %s.w, 0.0, 1.0);", v.fsIn()); fsBuilder->codeAppend("edgeAlpha *= innerAlpha;"); } - fsBuilder->codeAppendf("%s = %s;\n", args.fOutput, - (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("edgeAlpha")).c_str()); + fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage); } static void GenKey(const GrProcessor& processor, const GrGLCaps&, @@ -132,11 +136,10 @@ public: private: - CircleEdgeEffect(bool stroke) - : fInCircleEdge(this->addVertexAttrib( - GrShaderVar("inCircleEdge", - kVec4f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { + CircleEdgeEffect(bool stroke) { + fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType)); + fInCircleEdge = &this->addVertexAttrib(GrAttribute("inCircleEdge", + kVec4f_GrVertexAttribType)); fStroke = stroke; } @@ -149,7 +152,8 @@ private: inout->mulByUnknownAlpha(); } - const GrShaderVar& fInCircleEdge; + const GrAttribute* fInPosition; + const GrAttribute* fInCircleEdge; bool fStroke; GR_DECLARE_GEOMETRY_PROCESSOR_TEST; @@ -199,8 +203,10 @@ public: static const char* Name() { return "EllipseEdge"; } - const GrShaderVar& inEllipseOffset() const { return fInEllipseOffset; } - const GrShaderVar& inEllipseRadii() const { return fInEllipseRadii; } + + const GrAttribute* inPosition() const { return fInPosition; } + const GrAttribute* inEllipseOffset() const { return fInEllipseOffset; } + const GrAttribute* inEllipseRadii() const { return fInEllipseRadii; } inline bool isStroked() const { return fStroke; } @@ -210,23 +216,27 @@ public: : INHERITED (factory) {} virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { - const EllipseEdgeEffect& ellipseEffect = args.fGP.cast<EllipseEdgeEffect>(); + const EllipseEdgeEffect& ee = args.fGP.cast<EllipseEdgeEffect>(); + + GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); GrGLVertToFrag ellipseOffsets(kVec2f_GrSLType); args.fPB->addVarying("EllipseOffsets", &ellipseOffsets); - - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); vsBuilder->codeAppendf("%s = %s;", ellipseOffsets.vsOut(), - ellipseEffect.inEllipseOffset().c_str()); + ee.inEllipseOffset()->fName); GrGLVertToFrag ellipseRadii(kVec4f_GrSLType); args.fPB->addVarying("EllipseRadii", &ellipseRadii); vsBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), - ellipseEffect.inEllipseRadii().c_str()); + ee.inEllipseRadii()->fName); + + // setup coord outputs + vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), ee.inPosition()->fName); + vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), ee.inPosition()->fName); // setup position varying vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), - vsBuilder->uViewM(), vsBuilder->inPosition()); + vsBuilder->uViewM(), ee.inPosition()->fName); // for outer curve GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); @@ -242,7 +252,7 @@ public: fsBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);"); // for inner curve - if (ellipseEffect.isStroked()) { + if (ee.isStroked()) { fsBuilder->codeAppendf("scaledOffset = %s*%s.zw;", ellipseOffsets.fsIn(), ellipseRadii.fsIn()); fsBuilder->codeAppend("test = dot(scaledOffset, scaledOffset) - 1.0;"); @@ -252,8 +262,7 @@ public: fsBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);"); } - fsBuilder->codeAppendf("%s = %s;", args.fOutput, - (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("edgeAlpha")).c_str()); + fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage); } static void GenKey(const GrProcessor& processor, const GrGLCaps&, @@ -270,15 +279,12 @@ public: }; private: - EllipseEdgeEffect(bool stroke) - : fInEllipseOffset(this->addVertexAttrib( - GrShaderVar("inEllipseOffset", - kVec2f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) - , fInEllipseRadii(this->addVertexAttrib( - GrShaderVar("inEllipseRadii", - kVec4f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { + EllipseEdgeEffect(bool stroke) { + fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType)); + fInEllipseOffset = &this->addVertexAttrib(GrAttribute("inEllipseOffset", + kVec2f_GrVertexAttribType)); + fInEllipseRadii = &this->addVertexAttrib(GrAttribute("inEllipseRadii", + kVec4f_GrVertexAttribType)); fStroke = stroke; } @@ -291,8 +297,9 @@ private: inout->mulByUnknownAlpha(); } - const GrShaderVar& fInEllipseOffset; - const GrShaderVar& fInEllipseRadii; + const GrAttribute* fInPosition; + const GrAttribute* fInEllipseOffset; + const GrAttribute* fInEllipseRadii; bool fStroke; GR_DECLARE_GEOMETRY_PROCESSOR_TEST; @@ -349,8 +356,9 @@ public: static const char* Name() { return "DIEllipseEdge"; } - const GrShaderVar& inEllipseOffsets0() const { return fInEllipseOffsets0; } - const GrShaderVar& inEllipseOffsets1() const { return fInEllipseOffsets1; } + const GrAttribute* inPosition() const { return fInPosition; } + const GrAttribute* inEllipseOffsets0() const { return fInEllipseOffsets0; } + const GrAttribute* inEllipseOffsets1() const { return fInEllipseOffsets1; } inline Mode getMode() const { return fMode; } @@ -360,23 +368,27 @@ public: : INHERITED (factory) {} virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { - const DIEllipseEdgeEffect& ellipseEffect = args.fGP.cast<DIEllipseEdgeEffect>(); + const DIEllipseEdgeEffect& ee = args.fGP.cast<DIEllipseEdgeEffect>(); + + GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); GrGLVertToFrag offsets0(kVec2f_GrSLType); args.fPB->addVarying("EllipseOffsets0", &offsets0); - - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); vsBuilder->codeAppendf("%s = %s;", offsets0.vsOut(), - ellipseEffect.inEllipseOffsets0().c_str()); + ee.inEllipseOffsets0()->fName); GrGLVertToFrag offsets1(kVec2f_GrSLType); args.fPB->addVarying("EllipseOffsets1", &offsets1); vsBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), - ellipseEffect.inEllipseOffsets1().c_str()); + ee.inEllipseOffsets1()->fName); + + // setup coord outputs + vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), ee.inPosition()->fName); + vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), ee.inPosition()->fName); // setup position varying vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), - vsBuilder->uViewM(), vsBuilder->inPosition()); + vsBuilder->uViewM(), ee.inPosition()->fName); GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); SkAssertResult(fsBuilder->enableFeature( @@ -394,7 +406,7 @@ public: // avoid calling inversesqrt on zero. fsBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); fsBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); - if (kHairline == ellipseEffect.getMode()) { + if (kHairline == ee.getMode()) { // can probably do this with one step fsBuilder->codeAppend("float edgeAlpha = clamp(1.0-test*invlen, 0.0, 1.0);"); fsBuilder->codeAppend("edgeAlpha *= clamp(1.0+test*invlen, 0.0, 1.0);"); @@ -403,7 +415,7 @@ public: } // for inner curve - if (kStroke == ellipseEffect.getMode()) { + if (kStroke == ee.getMode()) { fsBuilder->codeAppendf("scaledOffset = %s.xy;", offsets1.fsIn()); fsBuilder->codeAppend("test = dot(scaledOffset, scaledOffset) - 1.0;"); fsBuilder->codeAppendf("duvdx = dFdx(%s);", offsets1.fsIn()); @@ -416,8 +428,7 @@ public: fsBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);"); } - fsBuilder->codeAppendf("%s = %s;", args.fOutput, - (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("edgeAlpha")).c_str()); + fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage); } static void GenKey(const GrProcessor& processor, const GrGLCaps&, @@ -435,15 +446,12 @@ public: }; private: - DIEllipseEdgeEffect(Mode mode) - : fInEllipseOffsets0(this->addVertexAttrib( - GrShaderVar("inEllipseOffsets0", - kVec2f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) - , fInEllipseOffsets1(this->addVertexAttrib( - GrShaderVar("inEllipseOffsets1", - kVec2f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { + DIEllipseEdgeEffect(Mode mode) { + fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType)); + fInEllipseOffsets0 = &this->addVertexAttrib(GrAttribute("inEllipseOffsets0", + kVec2f_GrVertexAttribType)); + fInEllipseOffsets1 = &this->addVertexAttrib(GrAttribute("inEllipseOffsets1", + kVec2f_GrVertexAttribType)); fMode = mode; } @@ -456,8 +464,9 @@ private: inout->mulByUnknownAlpha(); } - const GrShaderVar& fInEllipseOffsets0; - const GrShaderVar& fInEllipseOffsets1; + const GrAttribute* fInPosition; + const GrAttribute* fInEllipseOffsets0; + const GrAttribute* fInEllipseOffsets1; Mode fMode; GR_DECLARE_GEOMETRY_PROCESSOR_TEST; @@ -517,12 +526,6 @@ bool GrOvalRenderer::drawOval(GrDrawTarget* target, /////////////////////////////////////////////////////////////////////////////// -// position + edge -extern const GrVertexAttrib gCircleVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding} -}; - void GrOvalRenderer::drawCircle(GrDrawTarget* target, GrDrawState* drawState, const GrContext* context, @@ -541,17 +544,6 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target, return; } - drawState->setVertexAttribs<gCircleVertexAttribs>(SK_ARRAY_COUNT(gCircleVertexAttribs), - sizeof(CircleVertex)); - - GrDrawTarget::AutoReleaseGeometry geo(target, 4, drawState->getVertexStride(), 0); - if (!geo.succeeded()) { - SkDebugf("Failed to get space for vertices!\n"); - return; - } - - CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); - SkStrokeRec::Style style = stroke.getStyle(); bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style; @@ -576,6 +568,15 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target, GrGeometryProcessor* gp = CircleEdgeEffect::Create(isStrokeOnly && innerRadius > 0); drawState->setGeometryProcessor(gp)->unref(); + GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); + SkASSERT(gp->getVertexStride() == sizeof(CircleVertex)); + if (!geo.succeeded()) { + SkDebugf("Failed to get space for vertices!\n"); + return; + } + + CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); + // The radii are outset for two reasons. First, it allows the shader to simply perform // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the // verts of the bounding box that is rendered and the outset ensures the box will cover all @@ -617,20 +618,6 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target, /////////////////////////////////////////////////////////////////////////////// -// position + offset + 1/radii -extern const GrVertexAttrib gEllipseVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec2f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding}, - {kVec4f_GrVertexAttribType, 2*sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding} -}; - -// position + offsets -extern const GrVertexAttrib gDIEllipseVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec2f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding}, - {kVec2f_GrVertexAttribType, 2*sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding}, -}; - bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, GrDrawState* drawState, const GrContext* context, @@ -704,10 +691,13 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, return false; } - drawState->setVertexAttribs<gEllipseVertexAttribs>(SK_ARRAY_COUNT(gEllipseVertexAttribs), - sizeof(EllipseVertex)); + GrGeometryProcessor* gp = EllipseEdgeEffect::Create(isStrokeOnly && + innerXRadius > 0 && innerYRadius > 0); - GrDrawTarget::AutoReleaseGeometry geo(target, 4, drawState->getVertexStride(), 0); + drawState->setGeometryProcessor(gp)->unref(); + + GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); + SkASSERT(gp->getVertexStride() == sizeof(EllipseVertex)); if (!geo.succeeded()) { SkDebugf("Failed to get space for vertices!\n"); return false; @@ -715,11 +705,6 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); - GrGeometryProcessor* gp = EllipseEdgeEffect::Create(isStrokeOnly && - innerXRadius > 0 && innerYRadius > 0); - - drawState->setGeometryProcessor(gp)->unref(); - // Compute the reciprocals of the radii here to save time in the shader SkScalar xRadRecip = SkScalarInvert(xRadius); SkScalar yRadRecip = SkScalarInvert(yRadius); @@ -824,10 +809,12 @@ bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, SkScalar innerRatioX = SkScalarDiv(xRadius, innerXRadius); SkScalar innerRatioY = SkScalarDiv(yRadius, innerYRadius); - drawState->setVertexAttribs<gDIEllipseVertexAttribs>(SK_ARRAY_COUNT(gDIEllipseVertexAttribs), - sizeof(DIEllipseVertex)); + GrGeometryProcessor* gp = DIEllipseEdgeEffect::Create(mode); + + drawState->setGeometryProcessor(gp)->unref(); - GrDrawTarget::AutoReleaseGeometry geo(target, 4, drawState->getVertexStride(), 0); + GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); + SkASSERT(gp->getVertexStride() == sizeof(DIEllipseVertex)); if (!geo.succeeded()) { SkDebugf("Failed to get space for vertices!\n"); return false; @@ -835,10 +822,6 @@ bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(geo.vertices()); - GrGeometryProcessor* gp = DIEllipseEdgeEffect::Create(mode); - - drawState->setGeometryProcessor(gp)->unref(); - // This expands the outer rect so that after CTM we end up with a half-pixel border SkScalar a = vm[SkMatrix::kMScaleX]; SkScalar b = vm[SkMatrix::kMSkewX]; @@ -1072,16 +1055,6 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, // if the corners are circles, use the circle renderer if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius) { - drawState->setVertexAttribs<gCircleVertexAttribs>(SK_ARRAY_COUNT(gCircleVertexAttribs), - sizeof(CircleVertex)); - - GrDrawTarget::AutoReleaseGeometry geo(target, 16, drawState->getVertexStride(), 0); - if (!geo.succeeded()) { - SkDebugf("Failed to get space for vertices!\n"); - return false; - } - CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); - SkScalar innerRadius = 0.0f; SkScalar outerRadius = xRadius; SkScalar halfWidth = 0; @@ -1104,6 +1077,14 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, GrGeometryProcessor* effect = CircleEdgeEffect::Create(isStrokeOnly); drawState->setGeometryProcessor(effect)->unref(); + GrDrawTarget::AutoReleaseGeometry geo(target, 16, effect->getVertexStride(), 0); + SkASSERT(effect->getVertexStride() == sizeof(CircleVertex)); + if (!geo.succeeded()) { + SkDebugf("Failed to get space for vertices!\n"); + return false; + } + CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); + // The radii are outset for two reasons. First, it allows the shader to simply perform // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the // verts of the bounding box that is rendered and the outset ensures the box will cover all @@ -1161,9 +1142,6 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, // otherwise we use the ellipse renderer } else { - drawState->setVertexAttribs<gEllipseVertexAttribs>(SK_ARRAY_COUNT(gEllipseVertexAttribs), - sizeof(EllipseVertex)); - SkScalar innerXRadius = 0.0f; SkScalar innerYRadius = 0.0f; if (hasStroke) { @@ -1198,15 +1176,17 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); - GrDrawTarget::AutoReleaseGeometry geo(target, 16, drawState->getVertexStride(), 0); + GrGeometryProcessor* effect = EllipseEdgeEffect::Create(isStrokeOnly); + drawState->setGeometryProcessor(effect)->unref(); + + GrDrawTarget::AutoReleaseGeometry geo(target, 16, effect->getVertexStride(), 0); + SkASSERT(effect->getVertexStride() == sizeof(EllipseVertex)); if (!geo.succeeded()) { SkDebugf("Failed to get space for vertices!\n"); return false; } - EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); - GrGeometryProcessor* effect = EllipseEdgeEffect::Create(isStrokeOnly); - drawState->setGeometryProcessor(effect)->unref(); + EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); // Compute the reciprocals of the radii here to save time in the shader SkScalar xRadRecip = SkScalarInvert(xRadius); diff --git a/src/gpu/GrProgramDesc.h b/src/gpu/GrProgramDesc.h index 788842d7be..655254f892 100644 --- a/src/gpu/GrProgramDesc.h +++ b/src/gpu/GrProgramDesc.h @@ -111,11 +111,6 @@ public: PrimaryOutputType fPrimaryOutputType : 8; SecondaryOutputType fSecondaryOutputType : 8; - int8_t fPositionAttributeIndex; - int8_t fLocalCoordAttributeIndex; - int8_t fColorAttributeIndex; - int8_t fCoverageAttributeIndex; - SkBool8 fHasGeometryProcessor; int8_t fColorEffectCnt; int8_t fCoverageEffectCnt; @@ -141,29 +136,10 @@ public: // A struct to communicate descriptor information to the program descriptor builder struct DescInfo { - int positionAttributeIndex() const { - return fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]; - } - int localCoordAttributeIndex() const { - return fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding]; - } - int colorVertexAttributeIndex() const { - return fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding]; - } - int coverageVertexAttributeIndex() const { - return fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding]; - } - bool hasLocalCoordAttribute() const { - return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding]; - } - bool hasColorVertexAttribute() const { - return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding]; - } - bool hasCoverageVertexAttribute() const { - return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding]; - } - - int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt]; + // TODO when GPs control uniform / attribute handling of color / coverage, then we can + // clean this up + bool fHasVertexColor; + bool fHasVertexCoverage; // These flags are needed to protect the code from creating an unused uniform color/coverage // which will cause shader compiler errors. diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp index 26049b398b..f38a136992 100644 --- a/src/gpu/effects/GrBezierEffect.cpp +++ b/src/gpu/effects/GrBezierEffect.cpp @@ -37,16 +37,20 @@ GrGLConicEffect::GrGLConicEffect(const GrBackendProcessorFactory& factory, } void GrGLConicEffect::emitCode(const EmitArgs& args) { + GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); + const GrConicEffect& gp = args.fGP.cast<GrConicEffect>(); + GrGLVertToFrag v(kVec4f_GrSLType); args.fPB->addVarying("ConicCoeffs", &v); + vsBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs()->fName); - const GrShaderVar& inConicCoeffs = args.fGP.cast<GrConicEffect>().inConicCoeffs(); - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); - vsBuilder->codeAppendf("%s = %s;", v.vsOut(), inConicCoeffs.c_str()); + // setup coord outputs + vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), gp.inPosition()->fName); + vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), gp.inPosition()->fName); // setup position varying vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), vsBuilder->uViewM(), - vsBuilder->inPosition()); + gp.inPosition()->fName); GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); fsBuilder->codeAppend("float edgeAlpha;"); @@ -105,8 +109,7 @@ void GrGLConicEffect::emitCode(const EmitArgs& args) { SkFAIL("Shouldn't get here"); } - fsBuilder->codeAppendf("%s = %s;", args.fOutput, - (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("edgeAlpha")).c_str()); + fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage); } void GrGLConicEffect::GenKey(const GrProcessor& processor, const GrGLCaps&, @@ -125,10 +128,10 @@ const GrBackendGeometryProcessorFactory& GrConicEffect::getFactory() const { } GrConicEffect::GrConicEffect(GrPrimitiveEdgeType edgeType) - : fEdgeType(edgeType) - , fInConicCoeffs(this->addVertexAttrib(GrShaderVar("inConicCoeffs", - kVec4f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { + : fEdgeType(edgeType) { + fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType)); + fInConicCoeffs = &this->addVertexAttrib(GrAttribute("inConicCoeffs", + kVec4f_GrVertexAttribType)); } bool GrConicEffect::onIsEqual(const GrGeometryProcessor& other) const { @@ -181,16 +184,20 @@ GrGLQuadEffect::GrGLQuadEffect(const GrBackendProcessorFactory& factory, } void GrGLQuadEffect::emitCode(const EmitArgs& args) { + GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); + const GrQuadEffect& gp = args.fGP.cast<GrQuadEffect>(); + GrGLVertToFrag v(kVec4f_GrSLType); args.fPB->addVarying("HairQuadEdge", &v); + vsBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge()->fName); - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); - const GrShaderVar& inHairQuadEdge = args.fGP.cast<GrQuadEffect>().inHairQuadEdge(); - vsBuilder->codeAppendf("%s = %s;", v.vsOut(), inHairQuadEdge.c_str()); + // setup coord outputs + vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), gp.inPosition()->fName); + vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), gp.inPosition()->fName); // setup position varying vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), vsBuilder->uViewM(), - vsBuilder->inPosition()); + gp.inPosition()->fName); GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); fsBuilder->codeAppendf("float edgeAlpha;"); @@ -235,8 +242,7 @@ void GrGLQuadEffect::emitCode(const EmitArgs& args) { SkFAIL("Shouldn't get here"); } - fsBuilder->codeAppendf("%s = %s;", args.fOutput, - (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("edgeAlpha")).c_str()); + fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage); } void GrGLQuadEffect::GenKey(const GrProcessor& processor, const GrGLCaps&, @@ -255,10 +261,10 @@ const GrBackendGeometryProcessorFactory& GrQuadEffect::getFactory() const { } GrQuadEffect::GrQuadEffect(GrPrimitiveEdgeType edgeType) - : fEdgeType(edgeType) - , fInHairQuadEdge(this->addVertexAttrib(GrShaderVar("inCubicCoeffs", - kVec4f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { + : fEdgeType(edgeType) { + fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType)); + fInHairQuadEdge = &this->addVertexAttrib(GrAttribute("inHairQuadEdge", + kVec4f_GrVertexAttribType)); } bool GrQuadEffect::onIsEqual(const GrGeometryProcessor& other) const { @@ -311,16 +317,20 @@ GrGLCubicEffect::GrGLCubicEffect(const GrBackendProcessorFactory& factory, } void GrGLCubicEffect::emitCode(const EmitArgs& args) { + GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); + const GrCubicEffect& gp = args.fGP.cast<GrCubicEffect>(); + GrGLVertToFrag v(kVec4f_GrSLType); - args.fPB->addVarying("CubicCoeffs", &v, GrGLShaderVar::kHigh_Precision); + args.fPB->addVarying("CubicCoeffs", &v); + vsBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inCubicCoeffs()->fName); - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); - const GrShaderVar& inCubicCoeffs = args.fGP.cast<GrCubicEffect>().inCubicCoeffs(); - vsBuilder->codeAppendf("%s = %s;", v.vsOut(), inCubicCoeffs.c_str()); + // setup coord outputs + vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), gp.inPosition()->fName); + vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), gp.inPosition()->fName); // setup position varying vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), vsBuilder->uViewM(), - vsBuilder->inPosition()); + gp.inPosition()->fName); GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); @@ -405,8 +415,8 @@ void GrGLCubicEffect::emitCode(const EmitArgs& args) { SkFAIL("Shouldn't get here"); } - fsBuilder->codeAppendf("%s = %s;", args.fOutput, - (GrGLSLExpr4(args.fInput) * GrGLSLExpr1(edgeAlpha.c_str())).c_str()); + + fsBuilder->codeAppendf("%s = vec4(%s);", args.fOutputCoverage, edgeAlpha.c_str()); } void GrGLCubicEffect::GenKey(const GrProcessor& processor, const GrGLCaps&, @@ -425,10 +435,10 @@ const GrBackendGeometryProcessorFactory& GrCubicEffect::getFactory() const { } GrCubicEffect::GrCubicEffect(GrPrimitiveEdgeType edgeType) - : fEdgeType(edgeType) - , fInCubicCoeffs(this->addVertexAttrib(GrShaderVar("inCubicCoeffs", - kVec4f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { + : fEdgeType(edgeType) { + fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType)); + fInCubicCoeffs = &this->addVertexAttrib(GrAttribute("inCubicCoeffs", + kVec4f_GrVertexAttribType)); } bool GrCubicEffect::onIsEqual(const GrGeometryProcessor& other) const { diff --git a/src/gpu/effects/GrBezierEffect.h b/src/gpu/effects/GrBezierEffect.h index 9b71f7d395..27f2fa1aa2 100644 --- a/src/gpu/effects/GrBezierEffect.h +++ b/src/gpu/effects/GrBezierEffect.h @@ -88,7 +88,8 @@ public: static const char* Name() { return "Conic"; } - inline const GrShaderVar& inConicCoeffs() const { return fInConicCoeffs; } + inline const GrAttribute* inPosition() const { return fInPosition; } + inline const GrAttribute* inConicCoeffs() const { return fInConicCoeffs; } inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); } inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); } inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } @@ -107,7 +108,8 @@ private: } GrPrimitiveEdgeType fEdgeType; - const GrShaderVar& fInConicCoeffs; + const GrAttribute* fInPosition; + const GrAttribute* fInConicCoeffs; GR_DECLARE_GEOMETRY_PROCESSOR_TEST; @@ -157,7 +159,8 @@ public: static const char* Name() { return "Quad"; } - inline const GrShaderVar& inHairQuadEdge() const { return fInHairQuadEdge; } + inline const GrAttribute* inPosition() const { return fInPosition; } + inline const GrAttribute* inHairQuadEdge() const { return fInHairQuadEdge; } inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); } inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); } inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } @@ -176,7 +179,8 @@ private: } GrPrimitiveEdgeType fEdgeType; - const GrShaderVar& fInHairQuadEdge; + const GrAttribute* fInPosition; + const GrAttribute* fInHairQuadEdge; GR_DECLARE_GEOMETRY_PROCESSOR_TEST; @@ -228,7 +232,8 @@ public: static const char* Name() { return "Cubic"; } - inline const GrShaderVar& inCubicCoeffs() const { return fInCubicCoeffs; } + inline const GrAttribute* inPosition() const { return fInPosition; } + inline const GrAttribute* inCubicCoeffs() const { return fInCubicCoeffs; } inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); } inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); } inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } @@ -247,7 +252,8 @@ private: } GrPrimitiveEdgeType fEdgeType; - const GrShaderVar& fInCubicCoeffs; + const GrAttribute* fInPosition; + const GrAttribute* fInCubicCoeffs; GR_DECLARE_GEOMETRY_PROCESSOR_TEST; diff --git a/src/gpu/effects/GrCustomCoordsTextureEffect.cpp b/src/gpu/effects/GrCustomCoordsTextureEffect.cpp index f61a37bb6f..45c3008889 100644 --- a/src/gpu/effects/GrCustomCoordsTextureEffect.cpp +++ b/src/gpu/effects/GrCustomCoordsTextureEffect.cpp @@ -21,33 +21,44 @@ public: : INHERITED (factory) {} virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { - const GrCustomCoordsTextureEffect& customCoordsTextureEffect = + const GrCustomCoordsTextureEffect& cte = args.fGP.cast<GrCustomCoordsTextureEffect>(); - SkASSERT(1 == customCoordsTextureEffect.getVertexAttribs().count()); + + GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); GrGLVertToFrag v(kVec2f_GrSLType); args.fPB->addVarying("TextureCoords", &v); + vsBuilder->codeAppendf("%s = %s;", v.vsOut(), cte.inTextureCoords()->fName); - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); - const GrShaderVar& inTextureCoords = customCoordsTextureEffect.inTextureCoords(); - vsBuilder->codeAppendf("%s = %s;", v.vsOut(), inTextureCoords.c_str()); + if (cte.inColor()) { + args.fPB->addPassThroughAttribute(cte.inColor(), args.fOutputColor); + } + + // setup output coords + vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), cte.inPosition()->fName); + vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), cte.inPosition()->fName); // setup position varying vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), - vsBuilder->uViewM(), vsBuilder->inPosition()); + vsBuilder->uViewM(), cte.inPosition()->fName); GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); - fsBuilder->codeAppendf("%s = ", args.fOutput); - fsBuilder->appendTextureLookupAndModulate(args.fInput, - args.fSamplers[0], - v.fsIn(), - kVec2f_GrSLType); + fsBuilder->codeAppendf("%s = ", args.fOutputCoverage); + fsBuilder->appendTextureLookup(args.fSamplers[0], v.fsIn(), kVec2f_GrSLType); fsBuilder->codeAppend(";"); } virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE {} + static inline void GenKey(const GrProcessor& proc, const GrGLCaps&, + GrProcessorKeyBuilder* b) { + const GrCustomCoordsTextureEffect& gp = proc.cast<GrCustomCoordsTextureEffect>(); + + b->add32(SkToBool(gp.inColor())); + } + + private: typedef GrGLGeometryProcessor INHERITED; }; @@ -55,16 +66,22 @@ private: /////////////////////////////////////////////////////////////////////////////// GrCustomCoordsTextureEffect::GrCustomCoordsTextureEffect(GrTexture* texture, - const GrTextureParams& params) - : fTextureAccess(texture, params) - , fInTextureCoords(this->addVertexAttrib(GrShaderVar("inTextureCoords", - kVec2f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { + const GrTextureParams& params, + bool hasColor) + : fTextureAccess(texture, params), fInColor(NULL) { + fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType)); + if (hasColor) { + fInColor = &this->addVertexAttrib(GrAttribute("inColor", kVec4ub_GrVertexAttribType)); + this->setHasVertexColor(); + } + fInTextureCoords = &this->addVertexAttrib(GrAttribute("inTextureCoords", + kVec2f_GrVertexAttribType)); this->addTextureAccess(&fTextureAccess); } bool GrCustomCoordsTextureEffect::onIsEqual(const GrGeometryProcessor& other) const { - return true; + const GrCustomCoordsTextureEffect& gp = other.cast<GrCustomCoordsTextureEffect>(); + return SkToBool(this->inColor()) == SkToBool(gp.inColor()); } void GrCustomCoordsTextureEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { @@ -103,5 +120,5 @@ GrGeometryProcessor* GrCustomCoordsTextureEffect::TestCreate(SkRandom* random, GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode : GrTextureParams::kNone_FilterMode); - return GrCustomCoordsTextureEffect::Create(textures[texIdx], params); + return GrCustomCoordsTextureEffect::Create(textures[texIdx], params, random->nextBool()); } diff --git a/src/gpu/effects/GrCustomCoordsTextureEffect.h b/src/gpu/effects/GrCustomCoordsTextureEffect.h index 103e20916c..89fc9355f6 100644 --- a/src/gpu/effects/GrCustomCoordsTextureEffect.h +++ b/src/gpu/effects/GrCustomCoordsTextureEffect.h @@ -21,29 +21,33 @@ class GrInvariantOutput; */ class GrCustomCoordsTextureEffect : public GrGeometryProcessor { public: - static GrGeometryProcessor* Create(GrTexture* tex, const GrTextureParams& p) { - return SkNEW_ARGS(GrCustomCoordsTextureEffect, (tex, p)); + static GrGeometryProcessor* Create(GrTexture* tex, const GrTextureParams& p, bool hasColor) { + return SkNEW_ARGS(GrCustomCoordsTextureEffect, (tex, p, hasColor)); } virtual ~GrCustomCoordsTextureEffect() {} static const char* Name() { return "Texture"; } - const GrShaderVar& inTextureCoords() const { return fInTextureCoords; } + const GrAttribute* inPosition() const { return fInPosition; } + const GrAttribute* inColor() const { return fInColor; } + const GrAttribute* inTextureCoords() const { return fInTextureCoords; } typedef GrGLCustomCoordsTextureEffect GLProcessor; virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE; private: - GrCustomCoordsTextureEffect(GrTexture* texture, const GrTextureParams& params); + GrCustomCoordsTextureEffect(GrTexture* texture, const GrTextureParams& params, bool hasColor); virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE; virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE; GrTextureAccess fTextureAccess; - const GrShaderVar& fInTextureCoords; + const GrAttribute* fInPosition; + const GrAttribute* fInColor; + const GrAttribute* fInTextureCoords; GR_DECLARE_GEOMETRY_PROCESSOR_TEST; diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp index 71d92cbb84..95760e62e5 100644 --- a/src/gpu/effects/GrDashingEffect.cpp +++ b/src/gpu/effects/GrDashingEffect.cpp @@ -65,18 +65,12 @@ static bool can_fast_path_dash(const SkPoint pts[2], const GrStrokeInfo& strokeI } namespace { - struct DashLineVertex { SkPoint fPos; SkPoint fDashPos; }; - -extern const GrVertexAttrib gDashLineVertexAttribs[] = { - { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, - { kVec2f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding }, }; -}; static void calc_dash_scaling(SkScalar* parallelScale, SkScalar* perpScale, const SkMatrix& viewMatrix, const SkPoint pts[2]) { SkVector vecSrc = pts[1] - pts[0]; @@ -341,6 +335,8 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, GrDrawState } devIntervals[0] = lineLength; } + + const GrGeometryProcessor* gp; bool fullDash = devIntervals[1] > 0.f || useAA; if (fullDash) { SkPathEffect::DashInfo devInfo; @@ -352,20 +348,14 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, GrDrawState bool isRoundCap = SkPaint::kRound_Cap == cap; GrDashingEffect::DashCap capType = isRoundCap ? GrDashingEffect::kRound_DashCap : GrDashingEffect::kNonRound_DashCap; - drawState->setGeometryProcessor( - GrDashingEffect::Create(edgeType, devInfo, strokeWidth, capType))->unref(); - - // Set up the vertex data for the line and start/end dashes - drawState->setVertexAttribs<gDashLineVertexAttribs>(SK_ARRAY_COUNT(gDashLineVertexAttribs), - sizeof(DashLineVertex)); + gp = GrDashingEffect::Create(edgeType, devInfo, strokeWidth, capType); } else { // Set up the vertex data for the line and start/end dashes - drawState->setGeometryProcessor( - GrDefaultGeoProcFactory::CreateAndSetAttribs( - drawState, - GrDefaultGeoProcFactory::kPosition_GPType))->unref(); + gp = GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPosition_GPType); } + drawState->setGeometryProcessor(gp)->unref(); + int totalRectCnt = 0; totalRectCnt += !lineDone ? 1 : 0; @@ -374,7 +364,7 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, GrDrawState GrDrawTarget::AutoReleaseGeometry geo(target, totalRectCnt * 4, - drawState->getVertexStride(), 0); + gp->getVertexStride(), 0); if (!geo.succeeded()) { SkDebugf("Failed to get space for vertices!\n"); return false; @@ -401,10 +391,12 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, GrDrawState bounds.outset(bloatX + strokeAdj, bloatY + halfSrcStroke); if (fullDash) { DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertices()); + SkASSERT(gp->getVertexStride() == sizeof(DashLineVertex)); setup_dashed_rect(bounds, verts, curVIdx, combinedMatrix, startOffset, devBloat, lineLength, halfDevStroke); } else { SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices()); + SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); setup_dashed_rect_pos(bounds, curVIdx, combinedMatrix, verts); } curVIdx += 4; @@ -415,10 +407,12 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, GrDrawState startRect.outset(bloatX, bloatY); if (fullDash) { DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertices()); + SkASSERT(gp->getVertexStride() == sizeof(DashLineVertex)); setup_dashed_rect(startRect, verts, curVIdx, combinedMatrix, startOffset, devBloat, devIntervals[0], halfDevStroke); } else { SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices()); + SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); setup_dashed_rect_pos(startRect, curVIdx, combinedMatrix, verts); } @@ -430,10 +424,12 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, GrDrawState endRect.outset(bloatX, bloatY); if (fullDash) { DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertices()); + SkASSERT(gp->getVertexStride() == sizeof(DashLineVertex)); setup_dashed_rect(endRect, verts, curVIdx, combinedMatrix, startOffset, devBloat, devIntervals[0], halfDevStroke); } else { SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices()); + SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); setup_dashed_rect_pos(endRect, curVIdx, combinedMatrix, verts); } @@ -469,7 +465,9 @@ public: static const char* Name() { return "DashingCircleEffect"; } - const GrShaderVar& inCoord() const { return fInCoord; } + const GrAttribute* inPosition() const { return fInPosition; } + + const GrAttribute* inCoord() const { return fInCoord; } GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } @@ -490,8 +488,9 @@ private: virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE; - GrPrimitiveEdgeType fEdgeType; - const GrShaderVar& fInCoord; + GrPrimitiveEdgeType fEdgeType; + const GrAttribute* fInPosition; + const GrAttribute* fInCoord; SkScalar fIntervalLength; SkScalar fRadius; SkScalar fCenterX; @@ -539,15 +538,19 @@ void GLDashingCircleEffect::emitCode(const EmitArgs& args) { "params", ¶mName); + GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); + GrGLVertToFrag v(kVec2f_GrSLType); args.fPB->addVarying("Coord", &v); + vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dce.inCoord()->fName); - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); - vsBuilder->codeAppendf("\t%s = %s;\n", v.vsOut(), dce.inCoord().c_str()); + // setup coord outputs + vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), dce.inPosition()->fName); + vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), dce.inPosition()->fName); // setup position varying vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), vsBuilder->uViewM(), - vsBuilder->inPosition()); + dce.inPosition()->fName); // transforms all points so that we can compare them to our test circle GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); @@ -564,8 +567,7 @@ void GLDashingCircleEffect::emitCode(const EmitArgs& args) { fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n"); fsBuilder->codeAppendf("\t\talpha *= dist < %s.x + 0.5 ? 1.0 : 0.0;\n", paramName); } - fsBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutput, - (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("alpha")).c_str()); + fsBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage); } void GLDashingCircleEffect::setData(const GrGLProgramDataManager& pdman @@ -611,10 +613,9 @@ const GrBackendGeometryProcessorFactory& DashingCircleEffect::getFactory() const DashingCircleEffect::DashingCircleEffect(GrPrimitiveEdgeType edgeType, const DashInfo& info, SkScalar radius) - : fEdgeType(edgeType) - , fInCoord(this->addVertexAttrib(GrShaderVar("inCoord", - kVec2f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { + : fEdgeType(edgeType) { + fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType)); + fInCoord = &this->addVertexAttrib(GrAttribute("inCoord", kVec2f_GrVertexAttribType)); SkScalar onLen = info.fIntervals[0]; SkScalar offLen = info.fIntervals[1]; fIntervalLength = onLen + offLen; @@ -675,7 +676,9 @@ public: static const char* Name() { return "DashingEffect"; } - const GrShaderVar& inCoord() const { return fInCoord; } + const GrAttribute* inPosition() const { return fInPosition; } + + const GrAttribute* inCoord() const { return fInCoord; } GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } @@ -694,8 +697,9 @@ private: virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE; - GrPrimitiveEdgeType fEdgeType; - const GrShaderVar& fInCoord; + GrPrimitiveEdgeType fEdgeType; + const GrAttribute* fInPosition; + const GrAttribute* fInCoord; SkRect fRect; SkScalar fIntervalLength; @@ -747,14 +751,20 @@ void GLDashingLineEffect::emitCode(const EmitArgs& args) { "interval", &intervalName); + + GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); + GrGLVertToFrag v(kVec2f_GrSLType); args.fPB->addVarying("Coord", &v); - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); - vsBuilder->codeAppendf("\t%s = %s;\n", v.vsOut(), de.inCoord().c_str()); + vsBuilder->codeAppendf("%s = %s;", v.vsOut(), de.inCoord()->fName); + + // setup coord outputs + vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), de.inPosition()->fName); + vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), de.inPosition()->fName); // setup position varying vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), vsBuilder->uViewM(), - vsBuilder->inPosition()); + de.inPosition()->fName); // transforms all points so that we can compare them to our test rect GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); @@ -778,8 +788,7 @@ void GLDashingLineEffect::emitCode(const EmitArgs& args) { fsBuilder->codeAppendf("\t\talpha *= (fragPosShifted.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName); fsBuilder->codeAppendf("\t\talpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;\n", rectName); } - fsBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutput, - (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("alpha")).c_str()); + fsBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage); } void GLDashingLineEffect::setData(const GrGLProgramDataManager& pdman, @@ -826,10 +835,9 @@ const GrBackendGeometryProcessorFactory& DashingLineEffect::getFactory() const { DashingLineEffect::DashingLineEffect(GrPrimitiveEdgeType edgeType, const DashInfo& info, SkScalar strokeWidth) - : fEdgeType(edgeType) - , fInCoord(this->addVertexAttrib(GrShaderVar("inCoord", - kVec2f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { + : fEdgeType(edgeType) { + fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType)); + fInCoord = &this->addVertexAttrib(GrAttribute("inCoord", kVec2f_GrVertexAttribType)); SkScalar onLen = info.fIntervals[0]; SkScalar offLen = info.fIntervals[1]; SkScalar halfOffLen = SkScalarHalf(offLen); diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp index bc4146d891..5e1bc9968c 100755 --- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp +++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp @@ -34,21 +34,30 @@ public: virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { const GrDistanceFieldTextureEffect& dfTexEffect = args.fGP.cast<GrDistanceFieldTextureEffect>(); - SkASSERT(1 == dfTexEffect.getVertexAttribs().count()); GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); SkAssertResult(fsBuilder->enableFeature( GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); + GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); GrGLVertToFrag v(kVec2f_GrSLType); args.fPB->addVarying("TextureCoords", &v); + vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName); - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); - vsBuilder->codeAppendf("\t%s = %s;\n", v.vsOut(), dfTexEffect.inTextureCoords().c_str()); + // setup color attribute + if(dfTexEffect.inColor()) { + args.fPB->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor); + } // setup position varying vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), - vsBuilder->uViewM(), vsBuilder->inPosition()); + vsBuilder->uViewM(), dfTexEffect.inPosition()->fName); + + // setup output coords + vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), + dfTexEffect.inPosition()->fName); + vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), + dfTexEffect.inPosition()->fName); const char* textureSizeUniName = NULL; fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility, @@ -111,8 +120,7 @@ public: fsBuilder->codeAppend("\tval = gammaColor.r;\n"); #endif - fsBuilder->codeAppendf("\t%s = %s;\n", args.fOutput, - (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("val")).c_str()); + fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage); } virtual void setData(const GrGLProgramDataManager& pdman, @@ -171,10 +179,15 @@ GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrTexture* texture, , fLuminance(luminance) #endif , fFlags(flags & kNonLCD_DistanceFieldEffectMask) - , fInTextureCoords(this->addVertexAttrib(GrShaderVar("inTextureCoords", - kVec2f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { + , fInColor(NULL) { SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask)); + fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType)); + if (flags & kColorAttr_DistanceFieldEffectFlag) { + fInColor = &this->addVertexAttrib(GrAttribute("inColor", kVec4ub_GrVertexAttribType)); + this->setHasVertexColor(); + } + fInTextureCoords = &this->addVertexAttrib(GrAttribute("inTextureCoords", + kVec2f_GrVertexAttribType)); this->addTextureAccess(&fTextureAccess); #ifdef SK_GAMMA_APPLY_TO_A8 this->addTextureAccess(&fGammaTextureAccess); @@ -249,21 +262,31 @@ public: virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { const GrDistanceFieldNoGammaTextureEffect& dfTexEffect = args.fGP.cast<GrDistanceFieldNoGammaTextureEffect>(); - SkASSERT(1 == dfTexEffect.getVertexAttribs().count()); GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); SkAssertResult(fsBuilder->enableFeature( GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); + GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); GrGLVertToFrag v(kVec2f_GrSLType); args.fPB->addVarying("TextureCoords", &v); - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); - vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords().c_str()); + // setup color attribute + if(dfTexEffect.inColor()) { + args.fPB->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor); + } + + vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName); + + // setup coord outputs + vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), + dfTexEffect.inPosition()->fName); + vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), + dfTexEffect.inPosition()->fName); // setup position varying vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), - vsBuilder->uViewM(), vsBuilder->inPosition()); + vsBuilder->uViewM(), dfTexEffect.inPosition()->fName); const char* textureSizeUniName = NULL; fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility, @@ -311,8 +334,7 @@ public: } fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);"); - fsBuilder->codeAppendf("%s = %s;", args.fOutput, - (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("val")).c_str()); + fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage); } virtual void setData(const GrGLProgramDataManager& pdman, @@ -351,10 +373,15 @@ GrDistanceFieldNoGammaTextureEffect::GrDistanceFieldNoGammaTextureEffect(GrTextu uint32_t flags) : fTextureAccess(texture, params) , fFlags(flags & kNonLCD_DistanceFieldEffectMask) - , fInTextureCoords(this->addVertexAttrib(GrShaderVar("inTextureCoords", - kVec2f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { + , fInColor(NULL) { SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask)); + fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType)); + if (flags & kColorAttr_DistanceFieldEffectFlag) { + fInColor = &this->addVertexAttrib(GrAttribute("inColor", kVec4ub_GrVertexAttribType)); + this->setHasVertexColor(); + } + fInTextureCoords = &this->addVertexAttrib(GrAttribute("inTextureCoords", + kVec2f_GrVertexAttribType)); this->addTextureAccess(&fTextureAccess); } @@ -411,17 +438,21 @@ public: virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { const GrDistanceFieldLCDTextureEffect& dfTexEffect = args.fGP.cast<GrDistanceFieldLCDTextureEffect>(); - SkASSERT(1 == dfTexEffect.getVertexAttribs().count()); + GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); GrGLVertToFrag v(kVec2f_GrSLType); args.fPB->addVarying("TextureCoords", &v); + vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName); - GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); - vsBuilder->codeAppendf("\t%s = %s;\n", v.vsOut(), dfTexEffect.inTextureCoords().c_str()); + // setup coord outputs + vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), + dfTexEffect.inPosition()->fName); + vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), + dfTexEffect.inPosition()->fName); // setup position varying vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(), - vsBuilder->uViewM(), vsBuilder->inPosition()); + vsBuilder->uViewM(), dfTexEffect.inPosition()->fName); const char* textureSizeUniName = NULL; // width, height, 1/(3*width) @@ -528,8 +559,7 @@ public: fsBuilder->codeAppend(";\n"); fsBuilder->codeAppend("\tval.z = gammaColor.r;\n"); - fsBuilder->codeAppendf("\t%s = %s;\n", args.fOutput, - (GrGLSLExpr4(args.fInput) * GrGLSLExpr4("val")).c_str()); + fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage); } virtual void setData(const GrGLProgramDataManager& pdman, @@ -591,12 +621,11 @@ GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect( : fTextureAccess(texture, params) , fGammaTextureAccess(gamma, gParams) , fTextColor(textColor) - , fFlags(flags & kLCD_DistanceFieldEffectMask) - , fInTextureCoords(this->addVertexAttrib(GrShaderVar("inTextureCoords", - kVec2f_GrSLType, - GrShaderVar::kAttribute_TypeModifier))) { + , fFlags(flags & kLCD_DistanceFieldEffectMask){ SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag)); - + fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType)); + fInTextureCoords = &this->addVertexAttrib(GrAttribute("inTextureCoords", + kVec2f_GrVertexAttribType)); this->addTextureAccess(&fTextureAccess); this->addTextureAccess(&fGammaTextureAccess); } diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.h b/src/gpu/effects/GrDistanceFieldTextureEffect.h index bcc40889fd..a074d69f63 100644 --- a/src/gpu/effects/GrDistanceFieldTextureEffect.h +++ b/src/gpu/effects/GrDistanceFieldTextureEffect.h @@ -22,13 +22,15 @@ enum GrDistanceFieldEffectFlags { kUseLCD_DistanceFieldEffectFlag = 0x04, // use lcd text kBGR_DistanceFieldEffectFlag = 0x08, // lcd display has bgr order kPortrait_DistanceFieldEffectFlag = 0x10, // lcd display is in portrait mode (not used yet) + kColorAttr_DistanceFieldEffectFlag = 0x20, // color vertex attribute kInvalid_DistanceFieldEffectFlag = 0x80, // invalid state (for initialization) kUniformScale_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag | kRectToRect_DistanceFieldEffectFlag, // The subset of the flags relevant to GrDistanceFieldTextureEffect - kNonLCD_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag, + kNonLCD_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag | + kColorAttr_DistanceFieldEffectFlag, // The subset of the flags relevant to GrDistanceFieldLCDTextureEffect kLCD_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag | kRectToRect_DistanceFieldEffectFlag | @@ -62,7 +64,9 @@ public: static const char* Name() { return "DistanceFieldTexture"; } - const GrShaderVar& inTextureCoords() const { return fInTextureCoords; } + const GrAttribute* inPosition() const { return fInPosition; } + const GrAttribute* inColor() const { return fInColor; } + const GrAttribute* inTextureCoords() const { return fInTextureCoords; } #ifdef SK_GAMMA_APPLY_TO_A8 float getLuminance() const { return fLuminance; } #endif @@ -89,7 +93,9 @@ private: float fLuminance; #endif uint32_t fFlags; - const GrShaderVar& fInTextureCoords; + const GrAttribute* fInPosition; + const GrAttribute* fInColor; + const GrAttribute* fInTextureCoords; GR_DECLARE_GEOMETRY_PROCESSOR_TEST; @@ -114,7 +120,9 @@ public: static const char* Name() { return "DistanceFieldTexture"; } - const GrShaderVar& inTextureCoords() const { return fInTextureCoords; } + const GrAttribute* inPosition() const { return fInPosition; } + const GrAttribute* inColor() const { return fInColor; } + const GrAttribute* inTextureCoords() const { return fInTextureCoords; } uint32_t getFlags() const { return fFlags; } typedef GrGLDistanceFieldNoGammaTextureEffect GLProcessor; @@ -131,7 +139,9 @@ private: GrTextureAccess fTextureAccess; uint32_t fFlags; - const GrShaderVar& fInTextureCoords; + const GrAttribute* fInPosition; + const GrAttribute* fInColor; + const GrAttribute* fInTextureCoords; GR_DECLARE_GEOMETRY_PROCESSOR_TEST; @@ -157,7 +167,8 @@ public: static const char* Name() { return "DistanceFieldLCDTexture"; } - const GrShaderVar& inTextureCoords() const { return fInTextureCoords; } + const GrAttribute* inPosition() const { return fInPosition; } + const GrAttribute* inTextureCoords() const { return fInTextureCoords; } GrColor getTextColor() const { return fTextColor; } uint32_t getFlags() const { return fFlags; } @@ -179,7 +190,8 @@ private: GrTextureAccess fGammaTextureAccess; GrColor fTextColor; uint32_t fFlags; - const GrShaderVar& fInTextureCoords; + const GrAttribute* fInPosition; + const GrAttribute* fInTextureCoords; GR_DECLARE_GEOMETRY_PROCESSOR_TEST; diff --git a/src/gpu/gl/GrGLGeometryProcessor.h b/src/gpu/gl/GrGLGeometryProcessor.h index 06b4aa9d47..c3bee95266 100644 --- a/src/gpu/gl/GrGLGeometryProcessor.h +++ b/src/gpu/gl/GrGLGeometryProcessor.h @@ -25,14 +25,18 @@ public: struct EmitArgs { EmitArgs(GrGLGPBuilder* pb, const GrGeometryProcessor& gp, - const char* output, - const char* input, + const char* outputColor, + const char* outputCoverage, const TextureSamplerArray& samplers) - : fPB(pb), fGP(gp), fOutput(output), fInput(input), fSamplers(samplers) {} + : fPB(pb) + , fGP(gp) + , fOutputColor(outputColor) + , fOutputCoverage(outputCoverage) + , fSamplers(samplers) {} GrGLGPBuilder* fPB; const GrGeometryProcessor& fGP; - const char* fOutput; - const char* fInput; + const char* fOutputColor; + const char* fOutputCoverage; const TextureSamplerArray& fSamplers; }; /** diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 3249793d62..63cb9da20b 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -25,16 +25,13 @@ /** * Retrieves the final matrix that a transform needs to apply to its source coords. */ -static SkMatrix get_transform_matrix(const GrPendingFragmentStage& stage, - bool useExplicitLocalCoords, - int transformIdx) { +static SkMatrix get_transform_matrix(const GrPendingFragmentStage& stage, int transformIdx) { const GrCoordTransform& coordTransform = stage.getProcessor()->coordTransform(transformIdx); SkMatrix combined; if (kLocal_GrCoordSet == coordTransform.sourceCoords()) { // If we have explicit local coords then we shouldn't need a coord change. - const SkMatrix& ccm = - useExplicitLocalCoords ? SkMatrix::I() : stage.getCoordChangeMatrix(); + const SkMatrix& ccm = stage.getCoordChangeMatrix(); combined.setConcat(coordTransform.getMatrix(), ccm); } else { combined = coordTransform.getMatrix(); @@ -187,7 +184,7 @@ void GrGLProgram::setTransformData(const GrPendingFragmentStage& processor, SkASSERT(numTransforms == processor.getProcessor()->numTransforms()); for (int t = 0; t < numTransforms; ++t) { SkASSERT(transforms[t].fHandle.isValid()); - const SkMatrix& matrix = get_transform_matrix(processor, ip->fLocalCoordAttrib, t); + const SkMatrix& matrix = get_transform_matrix(processor, t); if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) { fProgramDataManager.setSkMatrix(transforms[t].fHandle.convertToUniformHandle(), matrix); transforms[t].fCurrentValue = matrix; @@ -335,7 +332,7 @@ void GrGLNvprProgram::setTransformData(const GrPendingFragmentStage& proc, SkASSERT(numTransforms == proc.getProcessor()->numTransforms()); for (int t = 0; t < numTransforms; ++t) { SkASSERT(transforms[t].fHandle.isValid()); - const SkMatrix& transform = get_transform_matrix(proc, false, t); + const SkMatrix& transform = get_transform_matrix(proc, t); if (transforms[t].fCurrentValue.cheapEqualTo(transform)) { continue; } @@ -376,7 +373,7 @@ GrGLLegacyNvprProgram::setTransformData(const GrPendingFragmentStage& proc, int texCoordIndex = ip->fTransforms[0].fHandle.handle(); int numTransforms = proc.getProcessor()->numTransforms(); for (int t = 0; t < numTransforms; ++t) { - const SkMatrix& transform = get_transform_matrix(proc, false, t); + const SkMatrix& transform = get_transform_matrix(proc, t); GrGLPathRendering::PathTexGenComponents components = GrGLPathRendering::kST_PathTexGenComponents; if (proc.isPerspectiveCoordTransform(t)) { diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp index 6a2d388692..74f669f2e3 100644 --- a/src/gpu/gl/GrGLProgramDesc.cpp +++ b/src/gpu/gl/GrGLProgramDesc.cpp @@ -63,9 +63,9 @@ static bool swizzle_requires_alpha_remapping(const GrGLCaps& caps, static uint32_t gen_attrib_key(const GrGeometryProcessor& proc) { uint32_t key = 0; - const GrGeometryProcessor::VertexAttribArray& vars = proc.getVertexAttribs(); + const GrGeometryProcessor::VertexAttribArray& vars = proc.getAttribs(); int numAttributes = vars.count(); - SkASSERT(numAttributes <= 2); + SkASSERT(numAttributes <= GrGeometryProcessor::kMaxVertexAttribs); for (int a = 0; a < numAttributes; ++a) { uint32_t value = 1 << a; key |= value; @@ -206,11 +206,7 @@ bool GrGLProgramDescBuilder::Build(const GrOptDrawState& optState, header->fUseNvpr = false; } - bool hasUniformColor = inputColorIsUsed && - (isPathRendering || !descInfo.hasColorVertexAttribute()); - - bool hasUniformCoverage = inputCoverageIsUsed && - (isPathRendering || !descInfo.hasCoverageVertexAttribute()); + bool hasUniformColor = inputColorIsUsed && (isPathRendering || !descInfo.fHasVertexColor); if (!inputColorIsUsed) { header->fColorInput = GrProgramDesc::kAllOnes_ColorInput; @@ -221,12 +217,13 @@ bool GrGLProgramDescBuilder::Build(const GrOptDrawState& optState, SkASSERT(!header->fUseNvpr); } - bool covIsSolidWhite = !descInfo.hasCoverageVertexAttribute() && - 0xffffffff == optState.getCoverageColor(); + bool hasVertexCoverage = !isPathRendering && descInfo.fHasVertexCoverage; + + bool covIsSolidWhite = !hasVertexCoverage && 0xffffffff == optState.getCoverageColor(); if (covIsSolidWhite || !inputCoverageIsUsed) { header->fCoverageInput = GrProgramDesc::kAllOnes_ColorInput; - } else if (hasUniformCoverage) { + } else if (!hasVertexCoverage) { header->fCoverageInput = GrProgramDesc::kUniform_ColorInput; } else { header->fCoverageInput = GrProgramDesc::kAttribute_ColorInput; @@ -255,31 +252,6 @@ bool GrGLProgramDescBuilder::Build(const GrOptDrawState& optState, header->fFragPosKey = 0; } - // Record attribute indices - header->fPositionAttributeIndex = descInfo.positionAttributeIndex(); - header->fLocalCoordAttributeIndex = descInfo.localCoordAttributeIndex(); - - // For constant color and coverage we need an attribute with an index beyond those already set - int availableAttributeIndex = optState.getVertexAttribCount(); - if (descInfo.hasColorVertexAttribute()) { - header->fColorAttributeIndex = descInfo.colorVertexAttributeIndex(); - } else if (GrProgramDesc::kAttribute_ColorInput == header->fColorInput) { - SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); - header->fColorAttributeIndex = availableAttributeIndex; - availableAttributeIndex++; - } else { - header->fColorAttributeIndex = -1; - } - - if (descInfo.hasCoverageVertexAttribute()) { - header->fCoverageAttributeIndex = descInfo.coverageVertexAttributeIndex(); - } else if (GrProgramDesc::kAttribute_ColorInput == header->fCoverageInput) { - SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); - header->fCoverageAttributeIndex = availableAttributeIndex; - } else { - header->fCoverageAttributeIndex = -1; - } - header->fPrimaryOutputType = descInfo.fPrimaryOutputType; header->fSecondaryOutputType = descInfo.fSecondaryOutputType; diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 32da5d7798..df35d2c78c 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -146,7 +146,7 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context) fProgramCache = SkNEW_ARGS(ProgramCache, (this)); - SkASSERT(this->glCaps().maxVertexAttributes() >= GrDrawState::kMaxVertexAttribCnt); + SkASSERT(this->glCaps().maxVertexAttributes() >= GrGeometryProcessor::kMaxVertexAttribs); fLastSuccessfulStencilFmtIdx = 0; fHWProgramID = 0; diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index e2c59b927f..cb8810cc79 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -250,16 +250,11 @@ bool GrGpuGL::flushGraphicsState(const GrOptDrawState& optState, DrawType type) void GrGpuGL::setupGeometry(const GrOptDrawState& optState, const GrDrawTarget::DrawInfo& info, size_t* indexOffsetInBytes) { - GrGLsizei stride = static_cast<GrGLsizei>(optState.getVertexStride()); - - size_t vertexOffsetInBytes = stride * info.startVertex(); - GrGLVertexBuffer* vbuf; vbuf = (GrGLVertexBuffer*) info.vertexBuffer(); SkASSERT(vbuf); SkASSERT(!vbuf->isMapped()); - vertexOffsetInBytes += vbuf->baseOffset(); GrGLIndexBuffer* ibuf = NULL; if (info.isIndexed()) { @@ -276,23 +271,31 @@ void GrGpuGL::setupGeometry(const GrOptDrawState& optState, fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf); if (fCurrentProgram->hasVertexShader()) { - int vertexAttribCount = optState.getVertexAttribCount(); + const GrGeometryProcessor* gp = optState.getGeometryProcessor(); + + GrGLsizei stride = static_cast<GrGLsizei>(gp->getVertexStride()); + + size_t vertexOffsetInBytes = stride * info.startVertex(); + + vertexOffsetInBytes += vbuf->baseOffset(); + + const SkTArray<GrGeometryProcessor::GrAttribute, true>& attribs = gp->getAttribs(); + int vaCount = attribs.count(); uint32_t usedAttribArraysMask = 0; - const GrVertexAttrib* vertexAttrib = optState.getVertexAttribs(); + size_t offset = 0; - for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount; - ++vertexAttribIndex, ++vertexAttrib) { - usedAttribArraysMask |= (1 << vertexAttribIndex); - GrVertexAttribType attribType = vertexAttrib->fType; + for (int attribIndex = 0; attribIndex < vaCount; attribIndex++) { + usedAttribArraysMask |= (1 << attribIndex); + GrVertexAttribType attribType = attribs[attribIndex].fType; attribState->set(this, - vertexAttribIndex, + attribIndex, vbuf, GrGLAttribTypeToLayout(attribType).fCount, GrGLAttribTypeToLayout(attribType).fType, GrGLAttribTypeToLayout(attribType).fNormalized, stride, - reinterpret_cast<GrGLvoid*>( - vertexOffsetInBytes + vertexAttrib->fOffset)); + reinterpret_cast<GrGLvoid*>(vertexOffsetInBytes + offset)); + offset += attribs[attribIndex].fOffset; } attribState->disableUnusedArrays(this, usedAttribArraysMask); } diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp index 16cc5d4964..64150a4fda 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -52,37 +52,15 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, GrGLSLExpr1 inputCoverage; pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage); - // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES), then we may have - // to setup a few more things like builtin vertex attributes - bool hasVertexShader = !(header.fUseNvpr && - gpu->glPathRendering()->texturingMode() == - GrGLPathRendering::FixedFunction_TexturingMode); - - if (hasVertexShader) { - pb->fVS.setupUniformViewMatrix(); - pb->fVS.setupPositionAndLocalCoords(); - - if (header.fEmitsPointSize) { - pb->fVS.codeAppend("gl_PointSize = 1.0;"); - } - if (GrProgramDesc::kAttribute_ColorInput == header.fColorInput) { - pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor); - } - if (GrProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { - pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage); - } - } - // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can // remove this cast to a vec4. - GrGLSLExpr4 inputCoverageVec4 = GrGLSLExpr4::VectorCast(inputCoverage); + GrGLSLExpr4 inputCoverageVec4; + if (inputCoverage.isValid()) { + inputCoverageVec4 = GrGLSLExpr4::VectorCast(inputCoverage); + } pb->emitAndInstallProcs(&inputColor, &inputCoverageVec4); - if (hasVertexShader) { - pb->fVS.transformToNormalizedDeviceSpace(); - } - // write the secondary color output if necessary if (GrProgramDesc::kNone_SecondaryOutputType != header.fSecondaryOutputType) { pb->fFS.enableSecondaryOutput(inputColor, inputCoverageVec4); @@ -145,6 +123,15 @@ void GrGLProgramBuilder::addVarying(const char* name, } } +void GrGLProgramBuilder::addPassThroughAttribute(const GrGeometryProcessor::GrAttribute* input, + const char* output) { + GrSLType type = GrVertexAttribTypeToSLType(input->fType); + GrGLVertToFrag v(type); + this->addVarying(input->fName, &v); + fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName); + fFS.codeAppendf("%s = %s;", output, v.fsIn()); +} + void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) { if ('\0' == prefix) { *out = name; @@ -242,50 +229,84 @@ void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* input } } -void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, - GrGLSLExpr4* inputCoverage) { - fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs)); - int numProcs = fOptState.numFragmentStages(); - this->emitAndInstallFragProcs(0, fOptState.numColorStages(), inputColor); +void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) { if (fOptState.hasGeometryProcessor()) { + fVS.setupUniformViewMatrix(); + + const GrProgramDesc::KeyHeader& header = this->header(); + if (header.fEmitsPointSize) { + fVS.codeAppend("gl_PointSize = 1.0;"); + } + + // Setup position + // TODO it'd be possible to remove these from the vertexshader builder and have them + // be outputs from the emit call. We don't do this because emitargs is constant. It would + // be easy to change this though + fVS.codeAppendf("vec3 %s;", fVS.glPosition()); + fVS.codeAppendf("vec2 %s;", fVS.positionCoords()); + fVS.codeAppendf("vec2 %s;", fVS.localCoords()); + const GrGeometryProcessor& gp = *fOptState.getGeometryProcessor(); fVS.emitAttributes(gp); - GrGLSLExpr4 output; - this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, *inputCoverage, &output); - *inputCoverage = output; + GrGLSLExpr4 outputColor; + GrGLSLExpr4 outputCoverage; + this->emitAndInstallProc(gp, &outputColor, &outputCoverage); + + // We may override color and coverage here if we have unform color or coverage. This is + // obviously not ideal. + // TODO lets the GP itself do the override + if (GrProgramDesc::kAttribute_ColorInput == header.fColorInput) { + *inputColor = outputColor; + } + if (GrProgramDesc::kUniform_ColorInput != header.fCoverageInput) { + *inputCoverage = outputCoverage; + } } + + fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs)); + int numProcs = fOptState.numFragmentStages(); + this->emitAndInstallFragProcs(0, fOptState.numColorStages(), inputColor); this->emitAndInstallFragProcs(fOptState.numColorStages(), numProcs, inputCoverage); + + if (fOptState.hasGeometryProcessor()) { + fVS.transformToNormalizedDeviceSpace(); + } } -void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut) { +void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, + int numProcs, + GrGLSLExpr4* inOut) { for (int e = procOffset; e < numProcs; ++e) { GrGLSLExpr4 output; const GrPendingFragmentStage& stage = fOptState.getFragmentStage(e); - this->emitAndInstallProc<GrPendingFragmentStage>(stage, e, *inOut, &output); + this->emitAndInstallProc(stage, e, *inOut, &output); *inOut = output; } } +void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) { + // create var to hold stage result. If we already have a valid output name, just use that + // otherwise create a new mangled one. This name is only valid if we are reordering stages + // and have to tell stage exactly where to put its output. + SkString outName; + if (output->isValid()) { + outName = output->c_str(); + } else { + this->nameVariable(&outName, '\0', baseName); + } + fFS.codeAppendf("vec4 %s;", outName.c_str()); + *output = outName; +} + // TODO Processors cannot output zeros because an empty string is all 1s // the fix is to allow effects to take the GrGLSLExpr4 directly -template <class Proc> -void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc, +void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& proc, int index, const GrGLSLExpr4& input, GrGLSLExpr4* output) { // Program builders have a bit of state we need to clear with each effect AutoStageAdvance adv(this); - - // create var to hold stage result. If we already have a valid output name, just use that - // otherwise create a new mangled one. - SkString outColorName; - if (output->isValid()) { - outColorName = output->c_str(); - } else { - this->nameVariable(&outColorName, '\0', "output"); - } - fFS.codeAppendf("vec4 %s;", outColorName.c_str()); - *output = outColorName; + this->nameExpression(output, "output"); // Enclose custom code in a block to avoid namespace conflicts SkString openBrace; @@ -297,10 +318,28 @@ void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc, fFS.codeAppend("}"); } +void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& proc, + GrGLSLExpr4* outputColor, + GrGLSLExpr4* outputCoverage) { + // Program builders have a bit of state we need to clear with each effect + AutoStageAdvance adv(this); + this->nameExpression(outputColor, "outputColor"); + this->nameExpression(outputCoverage, "outputCoverage"); + + // Enclose custom code in a block to avoid namespace conflicts + SkString openBrace; + openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); + fFS.codeAppend(openBrace.c_str()); + + this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str()); + + fFS.codeAppend("}"); +} + void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs, const char* outColor, const char* inColor) { - GrGLInstalledFragProc* ifp = SkNEW_ARGS(GrGLInstalledFragProc, (fVS.hasLocalCoords())); + GrGLInstalledFragProc* ifp = SkNEW(GrGLInstalledFragProc); const GrFragmentProcessor& fp = *fs.getProcessor(); ifp->fGLProc.reset(fp.getFactory().createGLInstance(fp)); @@ -321,8 +360,8 @@ void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs, } void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp, - const char* outCoverage, - const char* inCoverage) { + const char* outColor, + const char* outCoverage) { SkASSERT(!fGeometryProcessor); fGeometryProcessor = SkNEW(GrGLInstalledGeoProc); @@ -331,7 +370,7 @@ void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp, SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures()); this->emitSamplers(gp, &samplers, fGeometryProcessor); - GrGLGeometryProcessor::EmitArgs args(this, gp, outCoverage, inCoverage, samplers); + GrGLGeometryProcessor::EmitArgs args(this, gp, outColor, outCoverage, samplers); fGeometryProcessor->fGLProc->emitCode(args); // We have to check that effects and the code they emit are consistent, ie if an effect @@ -377,9 +416,10 @@ void GrGLProgramBuilder::emitTransforms(const GrPendingFragmentStage& stage, suffixedVaryingName.appendf("_%i", t); varyingName = suffixedVaryingName.c_str(); } - const char* coords = kPosition_GrCoordSet == processor->coordTransform(t).sourceCoords() ? - fVS.positionAttribute().c_str() : - fVS.localCoordsAttribute().c_str(); + + bool useLocalCoords = kLocal_GrCoordSet == processor->coordTransform(t).sourceCoords(); + const char* coords = useLocalCoords ? fVS.localCoords() : fVS.positionCoords(); + GrGLVertToFrag v(varyingType); this->addCoordVarying(varyingName, &v, uniName, coords); @@ -419,6 +459,7 @@ GrGLProgram* GrGLProgramBuilder::finalize() { this->cleanupProgram(programID, shadersToDelete); return NULL; } + if (!(GrGLProgramDescBuilder::GetHeader(fDesc).fUseNvpr && fGpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode)) { @@ -426,7 +467,11 @@ GrGLProgram* GrGLProgramBuilder::finalize() { this->cleanupProgram(programID, shadersToDelete); return NULL; } - fVS.bindVertexAttributes(programID); + + // Non fixed function NVPR actually requires a vertex shader to compile + if (fOptState.hasGeometryProcessor()) { + fVS.bindVertexAttributes(programID); + } } bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; if (usingBindUniform) { diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h index 7a4646d03f..76f7ae97c3 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.h +++ b/src/gpu/gl/builders/GrGLProgramBuilder.h @@ -126,10 +126,25 @@ struct GrGLGeoToFrag : public GrGLVarying { /* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */ class GrGLGPBuilder : public virtual GrGLUniformBuilder { public: + /* + * addVarying allows fine grained control for setting up varyings between stages. If you just + * need to take an attribute and pass it through to an output value in a fragment shader, use + * addPassThroughAttribute. + * TODO convert most uses of addVarying to addPassThroughAttribute + */ virtual void addVarying(const char* name, GrGLVarying*, GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) = 0; + /* + * This call can be used by GP to pass an attribute through all shaders directly to 'output' in + * the fragment shader. Though this call effects both the vertex shader and fragment shader, + * it expects 'output' to be defined in the fragment shader before this call is made. + * TODO it might be nicer behavior to have a flag to declare output inside this call + */ + virtual void addPassThroughAttribute(const GrGeometryProcessor::GrAttribute*, + const char* output) = 0; + // TODO rename getFragmentBuilder virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0; virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0; @@ -205,6 +220,10 @@ public: GrGLVarying*, GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) SK_OVERRIDE; + virtual void addPassThroughAttribute(const GrGeometryProcessor::GrAttribute*, + const char* output) SK_OVERRIDE; + + // Handles for program uniforms (other than per-effect uniforms) struct BuiltinUniformHandles { UniformHandle fViewMatrixUni; @@ -242,22 +261,29 @@ protected: // generating stage code. void nameVariable(SkString* out, char prefix, const char* name); void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr1* inputCoverage); + // Generates a possibly mangled name for a stage variable and writes it to the fragment shader. + // If GrGLSLExpr4 has a valid name then it will use that instead + void nameExpression(GrGLSLExpr4*, const char* baseName); void emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage); void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut); - template <class Proc> - void emitAndInstallProc(const Proc&, + void emitAndInstallProc(const GrPendingFragmentStage&, int index, const GrGLSLExpr4& input, GrGLSLExpr4* output); + void emitAndInstallProc(const GrGeometryProcessor&, + GrGLSLExpr4* outputColor, + GrGLSLExpr4* outputCoverage); + // these emit functions help to keep the createAndEmitProcessors template general void emitAndInstallProc(const GrPendingFragmentStage&, const char* outColor, const char* inColor); void emitAndInstallProc(const GrGeometryProcessor&, - const char* outCoverage, - const char* inCoverage); + const char* outColor, + const char* outCoverage); + void verify(const GrGeometryProcessor&); void verify(const GrFragmentProcessor&); void emitSamplers(const GrProcessor&, @@ -372,7 +398,7 @@ struct GrGLInstalledGeoProc : public GrGLInstalledProc { }; struct GrGLInstalledFragProc : public GrGLInstalledProc { - GrGLInstalledFragProc(bool useLocalCoords) : fGLProc(NULL), fLocalCoordAttrib(useLocalCoords) {} + GrGLInstalledFragProc() : fGLProc(NULL) {} class ShaderVarHandle { public: bool isValid() const { return fHandle > -1; } @@ -397,7 +423,6 @@ struct GrGLInstalledFragProc : public GrGLInstalledProc { SkAutoTDelete<GrGLFragmentProcessor> fGLProc; SkSTArray<2, Transform, true> fTransforms; - bool fLocalCoordAttrib; }; struct GrGLInstalledFragProcs : public SkRefCnt { diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp index 7af5ce9843..63cd352dd2 100644 --- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.cpp @@ -13,15 +13,9 @@ #define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X) #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(), R, X) -static const char* color_attribute_name() { return "inColor"; } -static const char* coverage_attribute_name() { return "inCoverage"; } - GrGLVertexBuilder::GrGLVertexBuilder(GrGLProgramBuilder* program) : INHERITED(program) - , fPositionVar(NULL) - , fLocalCoordsVar(NULL) - , fRtAdjustName(NULL) - , fEffectAttribOffset(0) { + , fRtAdjustName(NULL) { } void GrGLVertexBuilder::addVarying(const char* name, GrGLVarying* v) { @@ -39,58 +33,13 @@ void GrGLVertexBuilder::setupUniformViewMatrix() { this->uViewM()); } -void GrGLVertexBuilder::setupPositionAndLocalCoords() { - // Setup position - this->codeAppendf("vec3 %s;", this->glPosition()); - - // setup position and local coords attribute - fPositionVar = &fInputs.push_back(); - fPositionVar->set(kVec2f_GrSLType, - GrGLShaderVar::kAttribute_TypeModifier, - this->inPosition()); - if (-1 != fProgramBuilder->header().fLocalCoordAttributeIndex) { - fLocalCoordsVar = &fInputs.push_back(); - fLocalCoordsVar->set(kVec2f_GrSLType, - GrGLShaderVar::kAttribute_TypeModifier, - "inLocalCoords"); - } else { - fLocalCoordsVar = fPositionVar; - } - fEffectAttribOffset = fInputs.count(); -} - -void GrGLVertexBuilder::setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr1* out) { - GrGLVertToFrag v(kFloat_GrSLType); - fProgramBuilder->addVarying(inName, &v); - SkString name(inName); - name.prepend("in"); - this->addAttribute(GrShaderVar(name.c_str(), - kFloat_GrSLType, - GrShaderVar::kAttribute_TypeModifier)); - this->codeAppendf("%s = %s;", v.vsOut(), name.c_str()); - *out = v.fsIn(); - fEffectAttribOffset++; -} - -void GrGLVertexBuilder::setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr4* out) { - GrGLVertToFrag v(kVec4f_GrSLType); - fProgramBuilder->addVarying(inName, &v); - SkString name(inName); - name.prepend("in"); - this->addAttribute(GrShaderVar(name.c_str(), - kVec4f_GrSLType, - GrShaderVar::kAttribute_TypeModifier)); - this->codeAppendf("%s = %s;", v.vsOut(), name.c_str()); - *out = v.fsIn(); - fEffectAttribOffset++; -} - void GrGLVertexBuilder::emitAttributes(const GrGeometryProcessor& gp) { - const GrGeometryProcessor::VertexAttribArray& vars = gp.getVertexAttribs(); - int numAttributes = vars.count(); - for (int a = 0; a < numAttributes; ++a) { - this->addAttribute(vars[a]); + const GrGeometryProcessor::VertexAttribArray& v = gp.getAttribs(); + int vaCount = v.count(); + for (int i = 0; i < vaCount; i++) { + this->addAttribute(&v[i]); } + return; } void GrGLVertexBuilder::transformToNormalizedDeviceSpace() { @@ -124,49 +73,14 @@ void GrGLVertexBuilder::transformToNormalizedDeviceSpace() { } void GrGLVertexBuilder::bindVertexAttributes(GrGLuint programID) { - // Bind the attrib locations to same values for all shaders - const GrProgramDesc::KeyHeader& header = fProgramBuilder->header(); - SkASSERT(-1 != header.fPositionAttributeIndex); - GL_CALL(BindAttribLocation(programID, - header.fPositionAttributeIndex, - fPositionVar->c_str())); - if (-1 != header.fLocalCoordAttributeIndex) { - GL_CALL(BindAttribLocation(programID, - header.fLocalCoordAttributeIndex, - fLocalCoordsVar->c_str())); - } - if (-1 != header.fColorAttributeIndex) { - GL_CALL(BindAttribLocation(programID, - header.fColorAttributeIndex, - color_attribute_name())); - } - if (-1 != header.fCoverageAttributeIndex) { - GL_CALL(BindAttribLocation(programID, - header.fCoverageAttributeIndex, - coverage_attribute_name())); - } - - const GrOptDrawState& optState = fProgramBuilder->optState(); - const GrVertexAttrib* vaPtr = optState.getVertexAttribs(); - const int vaCount = optState.getVertexAttribCount(); + const GrGeometryProcessor* gp = fProgramBuilder->fOptState.getGeometryProcessor(); - // We start binding attributes after builtins - int i = fEffectAttribOffset; - for (int index = 0; index < vaCount; index++) { - if (kGeometryProcessor_GrVertexAttribBinding != vaPtr[index].fBinding) { - continue; - } - SkASSERT(index != header.fPositionAttributeIndex && - index != header.fLocalCoordAttributeIndex && - index != header.fColorAttributeIndex && - index != header.fCoverageAttributeIndex); - // We should never find another effect attribute if we have bound everything - SkASSERT(i < fInputs.count()); - GL_CALL(BindAttribLocation(programID, index, fInputs[i].c_str())); - i++; + const GrGeometryProcessor::VertexAttribArray& v = gp->getAttribs(); + int vaCount = v.count(); + for (int i = 0; i < vaCount; i++) { + GL_CALL(BindAttribLocation(programID, i, v[i].fName)); } - // Make sure we bound everything - SkASSERT(fInputs.count() == i); + return; } bool GrGLVertexBuilder::compileAndAttachShaders(GrGLuint programId, diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.h b/src/gpu/gl/builders/GrGLVertexShaderBuilder.h index 7d6d95e508..dbff24fe83 100644 --- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.h +++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.h @@ -16,29 +16,20 @@ class GrGLVertexBuilder : public GrGLShaderBuilder { public: GrGLVertexBuilder(GrGLProgramBuilder* program); - /** - * Are explicit local coordinates provided as input to the vertex shader. - */ - bool hasLocalCoords() const { return (fLocalCoordsVar != fPositionVar); } - - /** Returns a vertex attribute that represents the local coords in the VS. This may be the same - as positionAttribute() or it may not be. It depends upon whether the rendering code - specified explicit local coords or not in the GrDrawState. */ - const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; } - - /** Returns a vertex attribute that represents the vertex position in the VS. This is the - pre-matrix position and is commonly used by effects to compute texture coords via a matrix. - */ - const GrGLShaderVar& positionAttribute() const { return *fPositionVar; } - /** returns the expected position output */ const char* glPosition() const { return "pos3"; } + const char* positionCoords() const { return "position"; } + const char* localCoords() const { return "localCoords"; } /** returns the expected uviewM matrix */ // TODO all of this fixed function stuff can live on the GP/PP const char* uViewM() const { return "uViewM"; } - const char* inPosition() const { return "inPosition"; } + void addAttribute(const GrGeometryProcessor::GrAttribute* attr) { + this->addAttribute(GrShaderVar(attr->fName, + GrVertexAttribTypeToSLType(attr->fType), + GrShaderVar::kAttribute_TypeModifier)); + } private: /* @@ -52,27 +43,14 @@ private: void transformToNormalizedDeviceSpace(); //TODO GP itself should setup the uniform view matrix void setupUniformViewMatrix(); - void setupPositionAndLocalCoords(); - void setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr1* out); - void setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr4* out); void emitAttributes(const GrGeometryProcessor& gp); void bindVertexAttributes(GrGLuint programID); bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const; // an internal call which checks for uniquness of a var before adding it to the list of inputs bool addAttribute(const GrShaderVar& var); - struct AttributePair { - void set(int index, const SkString& name) { - fIndex = index; fName = name; - } - int fIndex; - SkString fName; - }; - GrGLShaderVar* fPositionVar; - GrGLShaderVar* fLocalCoordsVar; - const char* fRtAdjustName; - int fEffectAttribOffset; + const char* fRtAdjustName; friend class GrGLProgramBuilder; diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index f03f3014aa..aa8359d5e5 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -118,50 +118,6 @@ static GrRenderTarget* random_render_target(GrContext* context, return SkRef(texture->asRenderTarget()); } -// TODO clean this up, we have to do this to test geometry processors but there has got to be -// a better way. In the mean time, we actually fill out these generic vertex attribs below with -// the correct vertex attribs from the GP. We have to ensure, however, we don't try to add more -// than two attributes. In addition, we 'pad' the below array with GPs up to 6 entries, 4 fixed -// function vertex attributes and 2 GP custom attributes. -GrVertexAttrib kGenericVertexAttribs[] = { - { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, - { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding }, - { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding }, - { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding }, - { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding }, - { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding } -}; - -/* - * convert sl type to vertexattrib type, not a complete implementation, only use for debugging - */ -static GrVertexAttribType convert_sltype_to_attribtype(GrSLType type) { - switch (type) { - case kFloat_GrSLType: - return kFloat_GrVertexAttribType; - case kVec2f_GrSLType: - return kVec2f_GrVertexAttribType; - case kVec3f_GrSLType: - return kVec3f_GrVertexAttribType; - case kVec4f_GrSLType: - return kVec4f_GrVertexAttribType; - default: - SkFAIL("Type isn't convertible"); - return kFloat_GrVertexAttribType; - } -} -// end test hack - -static void setup_random_ff_attribute(GrVertexAttribBinding binding, GrVertexAttribType type, - SkRandom* random, int* attribIndex, int* runningStride) { - if (random->nextBool()) { - kGenericVertexAttribs[*attribIndex].fType = type; - kGenericVertexAttribs[*attribIndex].fOffset = *runningStride; - kGenericVertexAttribs[*attribIndex].fBinding = binding; - *runningStride += GrVertexAttribTypeSize(kGenericVertexAttribs[(*attribIndex)++].fType); - } -} - static void set_random_gp(GrContext* context, const GrDrawTargetCaps& caps, GrDrawState* ds, @@ -174,41 +130,6 @@ static void set_random_gp(GrContext* context, dummyTextures)); SkASSERT(gp); - // we have to set dummy vertex attributes, first we setup the fixed function attributes - // always leave the position attribute untouched in the array - int attribIndex = 1; - int runningStride = GrVertexAttribTypeSize(kGenericVertexAttribs[0].fType); - - // local coords - setup_random_ff_attribute(kLocalCoord_GrVertexAttribBinding, kVec2f_GrVertexAttribType, - random, &attribIndex, &runningStride); - - // color - setup_random_ff_attribute(kColor_GrVertexAttribBinding, kVec4f_GrVertexAttribType, - random, &attribIndex, &runningStride); - - // coverage - setup_random_ff_attribute(kCoverage_GrVertexAttribBinding, kUByte_GrVertexAttribType, - random, &attribIndex, &runningStride); - - // Update the geometry processor attributes - const GrGeometryProcessor::VertexAttribArray& v = gp->getVertexAttribs(); - int numGPAttribs = v.count(); - SkASSERT(numGPAttribs <= GrGeometryProcessor::kMaxVertexAttribs && - GrGeometryProcessor::kMaxVertexAttribs == 2); - - // we actually can't overflow if kMaxVertexAttribs == 2, but GCC 4.8 wants more proof - int maxIndex = SK_ARRAY_COUNT(kGenericVertexAttribs); - for (int i = 0; i < numGPAttribs && i + attribIndex < maxIndex; i++) { - kGenericVertexAttribs[i + attribIndex].fType = - convert_sltype_to_attribtype(v[i].getType()); - kGenericVertexAttribs[i + attribIndex].fOffset = runningStride; - kGenericVertexAttribs[i + attribIndex].fBinding = kGeometryProcessor_GrVertexAttribBinding; - runningStride += GrVertexAttribTypeSize(kGenericVertexAttribs[i + attribIndex].fType); - } - - // update the vertex attributes with the ds - ds->setVertexAttribs<kGenericVertexAttribs>(attribIndex + numGPAttribs, runningStride); ds->setGeometryProcessor(gp); } |