diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrGpu.h | 4 | ||||
-rw-r--r-- | src/gpu/effects/GrVertexEffect.h | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 3 | ||||
-rw-r--r-- | src/gpu/gl/GrGLDefines.h | 7 | ||||
-rw-r--r-- | src/gpu/gl/GrGLPathRendering.cpp | 30 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 26 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 5 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramDataManager.cpp | 30 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramDataManager.h | 55 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramDesc.cpp | 24 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramDesc.h | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramEffects.cpp | 71 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramEffects.h | 17 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.h | 7 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_program.cpp | 6 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLProgramBuilder.cpp | 29 | ||||
-rw-r--r-- | src/gpu/gl/builders/GrGLProgramBuilder.h | 26 |
17 files changed, 263 insertions, 83 deletions
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 353ec33437..e495de9afa 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -336,6 +336,10 @@ public: kDrawPaths_DrawType, }; + static bool IsPathRenderingDrawType(DrawType type) { + return kDrawPath_DrawType == type || kDrawPaths_DrawType == type; + } + protected: DrawType PrimTypeToDrawType(GrPrimitiveType type) { switch (type) { diff --git a/src/gpu/effects/GrVertexEffect.h b/src/gpu/effects/GrVertexEffect.h index 387ec7aee9..323c85e34e 100644 --- a/src/gpu/effects/GrVertexEffect.h +++ b/src/gpu/effects/GrVertexEffect.h @@ -17,7 +17,7 @@ */ class GrVertexEffect : public GrEffect { public: - GrVertexEffect() { fHasVertexCode = true; } + GrVertexEffect() { fRequiresVertexShader = true; } protected: /** diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index f12871192c..f9030d84d7 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -342,8 +342,7 @@ bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { ctxInfo.hasExtension("GL_ARB_program_interface_query")) && NULL != gli->fFunctions.fProgramPathFragmentInputGen)); } else { - // Note: path rendering is not yet implemented for GLES. - fPathRenderingSupport = ctxInfo.version() >= GR_GL_VER(3,1) && false; + fPathRenderingSupport = ctxInfo.version() >= GR_GL_VER(3,1); } } diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h index 06dd99dae1..048ad54df6 100644 --- a/src/gpu/gl/GrGLDefines.h +++ b/src/gpu/gl/GrGLDefines.h @@ -900,8 +900,13 @@ // shader stage of <program> (if a fragment stage exists). #define GR_GL_FRAGMENT_INPUT 0x936D +// NV_path_rendering extension to EXT_direct_state_access: +// [the matrix functions] must support the PATH_PROJECTION_NV and +// PATH_MODELVIEW_NV tokens for matrixMode. +#define GR_GL_PATH_PROJECTION 0x1701 +#define GR_GL_PATH_MODELVIEW 0x1700 + /* ARM specific define for MSAA support on framebuffer fetch */ #define GR_GL_FETCH_PER_SAMPLE_ARM 0x8F65 - #endif diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp index 135eb16866..337e83e811 100644 --- a/src/gpu/gl/GrGLPathRendering.cpp +++ b/src/gpu/gl/GrGLPathRendering.cpp @@ -54,8 +54,12 @@ GrGLPathRendering::GrGLPathRendering(GrGpuGL* gpu) NULL != glInterface->fFunctions.fStencilThenCoverFillPathInstanced && NULL != glInterface->fFunctions.fStencilThenCoverStrokePathInstanced; fCaps.fragmentInputGenSupport = + kGLES_GrGLStandard == glInterface->fStandard && NULL != glInterface->fFunctions.fProgramPathFragmentInputGen; - fHWPathTexGenSettings.reset(fGpu->glCaps().maxFixedFunctionTextureCoords()); + + if (!fCaps.fragmentInputGenSupport) { + fHWPathTexGenSettings.reset(fGpu->glCaps().maxFixedFunctionTextureCoords()); + } } GrGLPathRendering::~GrGLPathRendering() { @@ -68,14 +72,18 @@ void GrGLPathRendering::abandonGpuResources() { void GrGLPathRendering::resetContext() { fHWProjectionMatrixState.invalidate(); // we don't use the model view matrix. - GL_CALL(MatrixLoadIdentity(GR_GL_MODELVIEW)); - - for (int i = 0; i < fGpu->glCaps().maxFixedFunctionTextureCoords(); ++i) { - GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL)); - fHWPathTexGenSettings[i].fMode = GR_GL_NONE; - fHWPathTexGenSettings[i].fNumComponents = 0; + GrGLenum matrixMode = + fGpu->glStandard() == kGLES_GrGLStandard ? GR_GL_PATH_MODELVIEW : GR_GL_MODELVIEW; + GL_CALL(MatrixLoadIdentity(matrixMode)); + + if (!caps().fragmentInputGenSupport) { + for (int i = 0; i < fGpu->glCaps().maxFixedFunctionTextureCoords(); ++i) { + GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL)); + fHWPathTexGenSettings[i].fMode = GR_GL_NONE; + fHWPathTexGenSettings[i].fNumComponents = 0; + } + fHWActivePathTexGenSets = 0; } - fHWActivePathTexGenSets = 0; fHWPathStencilSettings.invalidate(); } @@ -105,7 +113,6 @@ void GrGLPathRendering::drawPath(const GrPath* path, SkPath::FillType fill) { GrGLuint id = static_cast<const GrGLPath*>(path)->pathID(); SkASSERT(NULL != fGpu->drawState()->getRenderTarget()); SkASSERT(NULL != fGpu->drawState()->getRenderTarget()->getStencilBuffer()); - SkASSERT(!fGpu->fCurrentProgram->hasVertexShader()); this->flushPathStencilSettings(fill); SkASSERT(!fHWPathStencilSettings.isTwoSided()); @@ -162,7 +169,6 @@ void GrGLPathRendering::drawPaths(const GrPathRange* pathRange, const uint32_t i SkASSERT(fGpu->caps()->pathRenderingSupport()); SkASSERT(NULL != fGpu->drawState()->getRenderTarget()); SkASSERT(NULL != fGpu->drawState()->getRenderTarget()->getStencilBuffer()); - SkASSERT(!fGpu->fCurrentProgram->hasVertexShader()); GrGLuint baseID = static_cast<const GrGLPathRange*>(pathRange)->basePathID(); @@ -347,7 +353,9 @@ void GrGLPathRendering::setProjectionMatrix(const SkMatrix& matrix, GrGLfloat glMatrix[4 * 4]; fHWProjectionMatrixState.getRTAdjustedGLMatrix<4>(glMatrix); - GL_CALL(MatrixLoadf(GR_GL_PROJECTION, glMatrix)); + GrGLenum matrixMode = + fGpu->glStandard() == kGLES_GrGLStandard ? GR_GL_PATH_PROJECTION : GR_GL_PROJECTION; + GL_CALL(MatrixLoadf(matrixMode, glMatrix)); } GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) { diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index d49d000fe3..11efda9214 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -13,6 +13,7 @@ #include "GrDrawEffect.h" #include "GrGLEffect.h" #include "GrGpuGL.h" +#include "GrGLPathRendering.h" #include "GrGLShaderVar.h" #include "GrGLSL.h" #include "SkXfermode.h" @@ -25,10 +26,12 @@ GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu, const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[]) { SkAutoTDelete<GrGLProgramBuilder> builder; - if (desc.getHeader().fHasVertexCode ||!gpu->shouldUseFixedFunctionTexturing()) { - builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, desc))); - } else { + if (!desc.getHeader().fRequiresVertexShader && + gpu->glCaps().pathRenderingSupport() && + gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode) { builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, desc))); + } else { + builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, desc))); } if (builder->genProgram(colorStages, coverageStages)) { SkASSERT(0 != builder->getProgramID()); @@ -100,7 +103,8 @@ void GrGLProgram::initSamplerUniforms() { /////////////////////////////////////////////////////////////////////////////// -void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts, +void GrGLProgram::setData(GrGpu::DrawType drawType, + GrDrawState::BlendOptFlags blendOpts, const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[], const GrDeviceCoordTexture* dstCopy, @@ -122,7 +126,7 @@ void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts, this->setColor(drawState, color, sharedState); this->setCoverage(drawState, coverage, sharedState); - this->setMatrixAndRenderTargetHeight(drawState); + this->setMatrixAndRenderTargetHeight(drawType, drawState); if (NULL != dstCopy) { if (fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid()) { @@ -145,9 +149,8 @@ void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts, SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid()); } - fColorEffects->setData(fGpu, fProgramDataManager, colorStages); - fCoverageEffects->setData(fGpu, fProgramDataManager, coverageStages); - + fColorEffects->setData(fGpu, drawType,fProgramDataManager, colorStages); + fCoverageEffects->setData(fGpu, drawType,fProgramDataManager, coverageStages); // PathTexGen state applies to the the fixed function vertex shader. For // custom shaders, it's ignored, so we don't need to change the texgen @@ -231,7 +234,8 @@ void GrGLProgram::setCoverage(const GrDrawState& drawState, } } -void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) { +void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, + const GrDrawState& drawState) { const GrRenderTarget* rt = drawState.getRenderTarget(); SkISize size; size.set(rt->width(), rt->height()); @@ -243,9 +247,7 @@ void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) { SkIntToScalar(size.fHeight)); } - if (!fHasVertexShader) { - SkASSERT(!fBuiltinUniformHandles.fViewMatrixUni.isValid()); - SkASSERT(!fBuiltinUniformHandles.fRTAdjustmentUni.isValid()); + if (GrGpu::IsPathRenderingDrawType(drawType)) { fGpu->glPathRendering()->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin()); } else if (fMatrixState.fRenderTargetOrigin != rt->origin() || fMatrixState.fRenderTargetSize != size || diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index 7af55f10ee..5b9deb9f91 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -156,7 +156,8 @@ public: * GrGpuGL object to bind the textures required by the GrGLEffects. The color and coverage * stages come from GrGLProgramDesc::Build(). */ - void setData(GrDrawState::BlendOptFlags, + void setData(GrGpu::DrawType, + GrDrawState::BlendOptFlags, const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[], const GrDeviceCoordTexture* dstCopy, // can be NULL @@ -181,7 +182,7 @@ private: void setCoverage(const GrDrawState&, GrColor coverage, SharedGLState*); // Helper for setData() that sets the view matrix and loads the render target height uniform - void setMatrixAndRenderTargetHeight(const GrDrawState&); + void setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, const GrDrawState&); // these reflect the current values of uniforms (GL uniform values travel with program) MatrixState fMatrixState; diff --git a/src/gpu/gl/GrGLProgramDataManager.cpp b/src/gpu/gl/GrGLProgramDataManager.cpp index eed9d1935d..c53abd79ab 100644 --- a/src/gpu/gl/GrGLProgramDataManager.cpp +++ b/src/gpu/gl/GrGLProgramDataManager.cpp @@ -6,6 +6,7 @@ */ #include "gl/builders/GrGLProgramBuilder.h" +#include "gl/GrGLPathRendering.h" #include "gl/GrGLProgram.h" #include "gl/GrGLUniformHandle.h" #include "gl/GrGpuGL.h" @@ -16,9 +17,10 @@ (1 == arrayCount && GrGLShaderVar::kNonArray == uni.fArrayCount)) GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu, - GrGLProgram*, + GrGLProgram* program, const GrGLProgramBuilder& builder) - : fGpu(gpu) { + : fGpu(gpu), + fProgram(program) { int count = builder.getUniformInfos().count(); fUniforms.push_back_n(count); for (int i = 0; i < count; i++) { @@ -43,6 +45,19 @@ GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu, uniform.fFSLocation = kUnusedUniform; } } + + count = builder.getSeparableVaryingInfos().count(); + fVaryings.push_back_n(count); + for (int i = 0; i < count; i++) { + Varying& varying = fVaryings[i]; + const GrGLProgramBuilder::SeparableVaryingInfo& builderVarying = + builder.getSeparableVaryingInfos()[i]; + SkASSERT(GrGLShaderVar::kNonArray == builderVarying.fVariable.getArrayCount()); + SkDEBUGCODE( + varying.fType = builderVarying.fVariable.getType(); + ); + varying.fLocation = builderVarying.fLocation; + } } void GrGLProgramDataManager::setSampler(UniformHandle u, GrGLint texUnit) const { @@ -261,3 +276,14 @@ void GrGLProgramDataManager::setSkMatrix(UniformHandle u, const SkMatrix& matrix }; this->setMatrix3f(u, mt); } + +void GrGLProgramDataManager::setProgramPathFragmentInputTransform(VaryingHandle i, + unsigned components, + const SkMatrix& matrix) const { + const Varying& fragmentInput = fVaryings[i.toProgramDataIndex()]; + fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgram->programID(), + fragmentInput.fLocation, + GR_GL_OBJECT_LINEAR, + components, + matrix); +} diff --git a/src/gpu/gl/GrGLProgramDataManager.h b/src/gpu/gl/GrGLProgramDataManager.h index 3082f6f02b..8a98a75cae 100644 --- a/src/gpu/gl/GrGLProgramDataManager.h +++ b/src/gpu/gl/GrGLProgramDataManager.h @@ -26,34 +26,51 @@ class GrGLProgramBuilder; class GrGLProgramDataManager : public SkRefCnt { public: // Opaque handle to a uniform - class UniformHandle { + class ShaderResourceHandle { public: - /** Creates a reference to an unifrom of a GrGLShaderBuilder. - * The ref can be used to set the uniform with corresponding the GrGLProgramDataManager.*/ - static UniformHandle CreateFromUniformIndex(int i); - bool isValid() const { return -1 != fValue; } - - bool operator==(const UniformHandle& other) const { return other.fValue == fValue; } - - UniformHandle() + ShaderResourceHandle() : fValue(-1) { } - - private: - UniformHandle(int value) + protected: + ShaderResourceHandle(int value) : fValue(value) { SkASSERT(isValid()); } + int fValue; + }; + class UniformHandle : public ShaderResourceHandle { + public: + /** Creates a reference to an unifrom of a GrGLShaderBuilder. + * The ref can be used to set the uniform with corresponding the GrGLProgramDataManager.*/ + static UniformHandle CreateFromUniformIndex(int i); + UniformHandle() { } + bool operator==(const UniformHandle& other) const { return other.fValue == fValue; } + private: + UniformHandle(int value) : ShaderResourceHandle(value) { } int toProgramDataIndex() const { SkASSERT(isValid()); return fValue; } int toShaderBuilderIndex() const { return toProgramDataIndex(); } - int fValue; friend class GrGLProgramDataManager; // For accessing toProgramDataIndex(). friend class GrGLProgramBuilder; // For accessing toShaderBuilderIndex(). }; + class VaryingHandle : public ShaderResourceHandle { + public: + /** Creates a reference to a varying in separable varyings of a GrGLShaderBuilder. + * The ref can be used to set the varying with the corresponding GrGLProgramDataManager.*/ + static VaryingHandle CreateFromSeparableVaryingIndex(int i) { + return VaryingHandle(i); + } + VaryingHandle() { } + bool operator==(const VaryingHandle& other) const { return other.fValue == fValue; } + private: + VaryingHandle(int value) : ShaderResourceHandle(value) { } + int toProgramDataIndex() const { SkASSERT(isValid()); return fValue; } + friend class GrGLProgramDataManager; // For accessing toProgramDataIndex(). + }; + GrGLProgramDataManager(GrGpuGL*, GrGLProgram*, const GrGLProgramBuilder&); /** Functions for uploading uniform values. The varities ending in v can be used to upload to an @@ -78,6 +95,10 @@ public: // convenience method for uploading a SkMatrix to a 3x3 matrix uniform void setSkMatrix(UniformHandle, const SkMatrix&) const; + void setProgramPathFragmentInputTransform(VaryingHandle i, + unsigned components, + const SkMatrix& matrix) const; + private: enum { kUnusedUniform = -1, @@ -91,9 +112,17 @@ private: int fArrayCount; ); }; + struct Varying { + GrGLint fLocation; + SkDEBUGCODE( + GrSLType fType; + ); + }; SkTArray<Uniform, true> fUniforms; + SkTArray<Varying, true> fVaryings; GrGpuGL* fGpu; + GrGLProgram* fProgram; typedef SkRefCnt INHERITED; }; diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp index 7cdbcd0efc..286924e1ef 100644 --- a/src/gpu/gl/GrGLProgramDesc.cpp +++ b/src/gpu/gl/GrGLProgramDesc.cpp @@ -21,7 +21,7 @@ bool GrGLProgramDesc::GetEffectKeyAndUpdateStats(const GrEffectStage& stage, uint16_t* effectKeySize, bool* setTrueIfReadsDst, bool* setTrueIfReadsPos, - bool* setTrueIfHasVertexCode) { + bool* setTrueIfRequiresVertexShader) { const GrBackendEffectFactory& factory = stage.getEffect()->getFactory(); GrDrawEffect drawEffect(stage, useExplicitLocalCoords); if (stage.getEffect()->willReadDstColor()) { @@ -30,8 +30,8 @@ bool GrGLProgramDesc::GetEffectKeyAndUpdateStats(const GrEffectStage& stage, if (stage.getEffect()->willReadFragmentPosition()) { *setTrueIfReadsPos = true; } - if (stage.getEffect()->hasVertexCode()) { - *setTrueIfHasVertexCode = true; + if (stage.getEffect()->requiresVertexShader()) { + *setTrueIfRequiresVertexShader = true; } factory.getGLEffectKey(drawEffect, caps, b); size_t size = b->size(); @@ -102,9 +102,10 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, bool readsDst = false; bool readFragPosition = false; - // We use vertexshader-less shader programs only when drawing paths. - bool hasVertexCode = !(GrGpu::kDrawPath_DrawType == drawType || - GrGpu::kDrawPaths_DrawType == drawType); + + // Provide option for shader programs without vertex shader only when drawing paths. + bool requiresVertexShader = !GrGpu::IsPathRenderingDrawType(drawType); + int numStages = 0; if (!skipColor) { numStages += drawState.numColorStages() - firstEffectiveColorStage; @@ -118,7 +119,6 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, desc->fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * numStages); int offsetAndSizeIndex = 0; - bool effectKeySuccess = true; if (!skipColor) { for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) { @@ -133,7 +133,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, drawState.getColorStage(s), gpu->glCaps(), requiresLocalCoordAttrib, &b, &effectKeySize, &readsDst, - &readFragPosition, &hasVertexCode); + &readFragPosition, &requiresVertexShader); effectKeySuccess |= (effectOffset <= SK_MaxU16); offsetAndSize[0] = SkToU16(effectOffset); @@ -154,7 +154,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, drawState.getCoverageStage(s), gpu->glCaps(), requiresLocalCoordAttrib, &b, &effectKeySize, &readsDst, - &readFragPosition, &hasVertexCode); + &readFragPosition, &requiresVertexShader); effectKeySuccess |= (effectOffset <= SK_MaxU16); offsetAndSize[0] = SkToU16(effectOffset); @@ -174,7 +174,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, // Because header is a pointer into the dynamic array, we can't push any new data into the key // below here. - header->fHasVertexCode = hasVertexCode || requiresLocalCoordAttrib; + header->fRequiresVertexShader = requiresVertexShader || requiresLocalCoordAttrib; header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType; // Currently the experimental GS will only work with triangle prims (and it doesn't do anything @@ -192,7 +192,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, header->fColorInput = kUniform_ColorInput; } else { header->fColorInput = kAttribute_ColorInput; - header->fHasVertexCode = true; + header->fRequiresVertexShader = true; } bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverageColor(); @@ -203,7 +203,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState, header->fCoverageInput = kUniform_ColorInput; } else { header->fCoverageInput = kAttribute_ColorInput; - header->fHasVertexCode = true; + header->fRequiresVertexShader = true; } if (readsDst) { diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h index e8925d0c5c..4796d5a4b3 100644 --- a/src/gpu/gl/GrGLProgramDesc.h +++ b/src/gpu/gl/GrGLProgramDesc.h @@ -147,7 +147,7 @@ private: ColorInput fCoverageInput : 8; CoverageOutput fCoverageOutput : 8; - SkBool8 fHasVertexCode; + SkBool8 fRequiresVertexShader; SkBool8 fEmitsPointSize; // To enable experimental geometry shader code (not for use in @@ -203,7 +203,7 @@ private: uint16_t* effectKeySize, bool* setTrueIfReadsDst, bool* setTrueIfReadsPos, - bool* setTrueIfHasVertexCode); + bool* setTrueIfRequiresVertexShader); void finalize(); diff --git a/src/gpu/gl/GrGLProgramEffects.cpp b/src/gpu/gl/GrGLProgramEffects.cpp index efb64fe640..8d97b42329 100644 --- a/src/gpu/gl/GrGLProgramEffects.cpp +++ b/src/gpu/gl/GrGLProgramEffects.cpp @@ -9,6 +9,8 @@ #include "GrGLProgramEffects.h" #include "GrDrawEffect.h" #include "gl/GrGLEffect.h" +#include "gl/GrGLPathRendering.h" +#include "gl/builders/GrGLProgramBuilder.h" #include "gl/GrGLVertexEffect.h" #include "gl/GrGpuGL.h" @@ -294,6 +296,16 @@ void GrGLVertexProgramEffects::emitTransforms(GrGLFullProgramBuilder* builder, uint32_t totalKey = GenTransformKey(drawEffect); int numTransforms = drawEffect.effect()->numTransforms(); transforms.push_back_n(numTransforms); + + SkTArray<PathTransform, true>* pathTransforms = NULL; + const GrGLCaps* glCaps = builder->ctxInfo().caps(); + if (glCaps->pathRenderingSupport() && + builder->gpu()->glPathRendering()->texturingMode() == + GrGLPathRendering::SeparableShaders_TexturingMode) { + pathTransforms = &fPathTransforms.push_back(); + pathTransforms->push_back_n(numTransforms); + } + for (int t = 0; t < numTransforms; t++) { GrSLType varyingType = kVoid_GrSLType; const char* uniName; @@ -330,7 +342,13 @@ void GrGLVertexProgramEffects::emitTransforms(GrGLFullProgramBuilder* builder, const char* vsVaryingName; const char* fsVaryingName; GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder(); - builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName); + if (pathTransforms) { + (*pathTransforms)[t].fHandle = + builder->addSeparableVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName); + (*pathTransforms)[t].fType = varyingType; + } else { + builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName); + } const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ? vsBuilder->positionAttribute() : @@ -350,20 +368,27 @@ void GrGLVertexProgramEffects::emitTransforms(GrGLFullProgramBuilder* builder, } void GrGLVertexProgramEffects::setData(GrGpuGL* gpu, - const GrGLProgramDataManager& programResourceManager, + GrGpu::DrawType drawType, + const GrGLProgramDataManager& programDataManager, const GrEffectStage* effectStages[]) { int numEffects = fGLEffects.count(); SkASSERT(numEffects == fTransforms.count()); SkASSERT(numEffects == fSamplers.count()); for (int e = 0; e < numEffects; ++e) { GrDrawEffect drawEffect(*effectStages[e], fHasExplicitLocalCoords); - fGLEffects[e]->setData(programResourceManager, drawEffect); - this->setTransformData(programResourceManager, drawEffect, e); + fGLEffects[e]->setData(programDataManager, drawEffect); + if (GrGpu::IsPathRenderingDrawType(drawType)) { + this->setPathTransformData(gpu, programDataManager, drawEffect, e); + } else { + this->setTransformData(gpu, programDataManager, drawEffect, e); + } + this->bindTextures(gpu, drawEffect.effect(), e); } } -void GrGLVertexProgramEffects::setTransformData(const GrGLProgramDataManager& programResourceManager, +void GrGLVertexProgramEffects::setTransformData(GrGpuGL* gpu, + const GrGLProgramDataManager& pdman, const GrDrawEffect& drawEffect, int effectIdx) { SkTArray<Transform, true>& transforms = fTransforms[effectIdx]; @@ -373,12 +398,39 @@ void GrGLVertexProgramEffects::setTransformData(const GrGLProgramDataManager& pr SkASSERT(transforms[t].fHandle.isValid()); const SkMatrix& matrix = get_transform_matrix(drawEffect, t); if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) { - programResourceManager.setSkMatrix(transforms[t].fHandle, matrix); + pdman.setSkMatrix(transforms[t].fHandle, matrix); transforms[t].fCurrentValue = matrix; } } } +void GrGLVertexProgramEffects::setPathTransformData(GrGpuGL* gpu, + const GrGLProgramDataManager& pdman, + const GrDrawEffect& drawEffect, + int effectIdx) { + SkTArray<PathTransform, true>& transforms = fPathTransforms[effectIdx]; + int numTransforms = transforms.count(); + SkASSERT(numTransforms == drawEffect.effect()->numTransforms()); + for (int t = 0; t < numTransforms; ++t) { + SkASSERT(transforms[t].fHandle.isValid()); + const SkMatrix& transform = get_transform_matrix(drawEffect, t); + if (transforms[t].fCurrentValue.cheapEqualTo(transform)) { + continue; + } + transforms[t].fCurrentValue = transform; + switch (transforms[t].fType) { + case kVec2f_GrSLType: + pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 2, transform); + break; + case kVec3f_GrSLType: + pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 3, transform); + break; + default: + SkFAIL("Unexpected matrix type."); + } + } +} + GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullProgramBuilder* builder, int reserveCount) : fBuilder(builder) @@ -445,14 +497,15 @@ void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyProgramBuilde } void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu, - const GrGLProgramDataManager& programResourceManager, - const GrEffectStage* effectStages[]) { + GrGpu::DrawType, + const GrGLProgramDataManager& pdman, + const GrEffectStage* effectStages[]) { int numEffects = fGLEffects.count(); SkASSERT(numEffects == fTransforms.count()); SkASSERT(numEffects == fSamplers.count()); for (int e = 0; e < numEffects; ++e) { GrDrawEffect drawEffect(*effectStages[e], false); - fGLEffects[e]->setData(programResourceManager, drawEffect); + fGLEffects[e]->setData(pdman, drawEffect); this->setPathTexGenState(gpu, drawEffect, e); this->bindTextures(gpu, drawEffect.effect(), e); } diff --git a/src/gpu/gl/GrGLProgramEffects.h b/src/gpu/gl/GrGLProgramEffects.h index e4d84a013b..0eaff53b76 100644 --- a/src/gpu/gl/GrGLProgramEffects.h +++ b/src/gpu/gl/GrGLProgramEffects.h @@ -10,6 +10,7 @@ #include "GrBackendEffectFactory.h" #include "GrGLProgramDataManager.h" +#include "GrGpu.h" #include "GrTexture.h" #include "GrTextureAccess.h" @@ -28,6 +29,7 @@ class GrGLFragmentOnlyProgramBuilder; class GrGLProgramEffects : public SkRefCnt { public: typedef GrGLProgramDataManager::UniformHandle UniformHandle; + typedef GrGLProgramDataManager::VaryingHandle VaryingHandle; /** * This class emits some of the code inserted into the shaders for an effect. The code it @@ -51,6 +53,7 @@ public: * Calls setData() on each effect, and sets their transformation matrices and texture bindings. */ virtual void setData(GrGpuGL*, + GrGpu::DrawType, const GrGLProgramDataManager&, const GrEffectStage* effectStages[]) = 0; @@ -165,6 +168,7 @@ public: class GrGLVertexProgramEffects : public GrGLProgramEffects { public: virtual void setData(GrGpuGL*, + GrGpu::DrawType, const GrGLProgramDataManager&, const GrEffectStage* effectStages[]) SK_OVERRIDE; @@ -205,7 +209,9 @@ private: /** * Helper for setData(). Sets all the transform matrices for an effect. */ - void setTransformData(const GrGLProgramDataManager&, const GrDrawEffect&, int effectIdx); + void setTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrDrawEffect&, int effectIdx); + void setPathTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrDrawEffect&, + int effectIdx); struct Transform { Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); } @@ -213,7 +219,15 @@ private: SkMatrix fCurrentValue; }; + struct PathTransform { + PathTransform() { fCurrentValue = SkMatrix::InvalidMatrix(); } + VaryingHandle fHandle; + SkMatrix fCurrentValue; + GrSLType fType; + }; + SkTArray<SkSTArray<2, Transform, true> > fTransforms; + SkTArray<SkTArray<PathTransform, true> > fPathTransforms; bool fHasExplicitLocalCoords; friend class GrGLVertexProgramEffectsBuilder; @@ -253,6 +267,7 @@ private: class GrGLPathTexGenProgramEffects : public GrGLProgramEffects { public: virtual void setData(GrGpuGL*, + GrGpu::DrawType, const GrGLProgramDataManager&, const GrEffectStage* effectStages[]) SK_OVERRIDE; diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index 110a6671ba..94fd307f6d 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -52,13 +52,6 @@ public: // state. void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture); - bool shouldUseFixedFunctionTexturing() const { - // At the moment non-fixed-function texturing is not implemented - // even though the GrGLPathRendering would support it. Thus just - // return the below. - return this->glCaps().pathRenderingSupport(); - } - bool programUnitTest(int maxStages); // GrGpu overrides diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index dac7443d17..b19676adb9 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -247,9 +247,6 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC return false; } - SkASSERT((kDrawPath_DrawType != type && kDrawPaths_DrawType != type) - || !fCurrentProgram->hasVertexShader()); - fCurrentProgram.get()->ref(); GrGLuint programID = fCurrentProgram->programID(); @@ -261,7 +258,8 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff); this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff); - fCurrentProgram->setData(blendOpts, + fCurrentProgram->setData(type, + blendOpts, colorStages.begin(), coverageStages.begin(), dstCopy, diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp index f4ee32b48d..41b84d806a 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -99,10 +99,13 @@ bool GrGLProgramBuilder::genProgram(const GrEffectStage* colorStages[], GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrGLProgramDesc& desc) - : fFragOnly(!desc.getHeader().fHasVertexCode && gpu->shouldUseFixedFunctionTexturing()) + : fFragOnly(!desc.getHeader().fRequiresVertexShader && + gpu->glCaps().pathRenderingSupport() && + gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode) , fTexCoordSetCnt(0) , fProgramID(0) , fFS(this, desc) + , fSeparableVaryingInfos(kVarsPerBlock) , fDesc(desc) , fGpu(gpu) , fUniforms(kVarsPerBlock) { @@ -304,6 +307,16 @@ void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) { fUniforms[i].fLocation = location; } } + + int count = fSeparableVaryingInfos.count(); + for (int i = 0; i < count; ++i) { + GrGLint location; + GL_CALL_RET(location, + GetProgramResourceLocation(programId, + GR_GL_FRAGMENT_INPUT, + fSeparableVaryingInfos[i].fVariable.c_str())); + fSeparableVaryingInfos[i].fLocation = location; + } } const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const { @@ -345,6 +358,18 @@ void GrGLFullProgramBuilder::addVarying(GrSLType type, fFS.addVarying(type, fsInputName->c_str(), fsInName); } +GrGLFullProgramBuilder::VaryingHandle +GrGLFullProgramBuilder::addSeparableVarying(GrSLType type, + const char* name, + const char** vsOutName, + const char** fsInName) { + addVarying(type, name, vsOutName, fsInName); + SeparableVaryingInfo& varying = fSeparableVaryingInfos.push_back(); + varying.fVariable = fFS.fInputs.back(); + return VaryingHandle::CreateFromSeparableVaryingIndex(fSeparableVaryingInfos.count() - 1); +} + + GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffects( const GrEffectStage* effectStages[], int effectCnt, @@ -381,7 +406,7 @@ void GrGLFullProgramBuilder::bindProgramLocations(GrGLuint programId) { GrGLFragmentOnlyProgramBuilder::GrGLFragmentOnlyProgramBuilder(GrGpuGL* gpu, const GrGLProgramDesc& desc) : INHERITED(gpu, desc) { - SkASSERT(!desc.getHeader().fHasVertexCode); + SkASSERT(!desc.getHeader().fRequiresVertexShader); SkASSERT(gpu->glCaps().pathRenderingSupport()); SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput); SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput); diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h index 09f7eba511..d1af63fc4e 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.h +++ b/src/gpu/gl/builders/GrGLProgramBuilder.h @@ -40,6 +40,7 @@ public: }; typedef GrGLProgramDataManager::UniformHandle UniformHandle; + typedef GrGLProgramDataManager::VaryingHandle VaryingHandle; // Handles for program uniforms (other than per-effect uniforms) struct BuiltinUniformHandles { @@ -69,6 +70,13 @@ public: // name strings. Otherwise, we'd have to hand out copies. typedef GrTAllocator<UniformInfo> UniformInfoArray; + struct SeparableVaryingInfo { + GrGLShaderVar fVariable; + GrGLint fLocation; + }; + + typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray; + /** Generates a shader program. * * The program implements what is specified in the stages given as input. @@ -91,6 +99,9 @@ public: bool hasVertexShader() const { SkASSERT(fProgramID); return !fFragOnly; } int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; } const UniformInfoArray& getUniformInfos() const { return fUniforms; } + const SeparableVaryingInfoArray& getSeparableVaryingInfos() const { + return fSeparableVaryingInfos; + } virtual ~GrGLProgramBuilder() {} @@ -126,13 +137,12 @@ public: const GrGLContextInfo& ctxInfo() const; GrGLFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; } + GrGpuGL* gpu() const { return fGpu; } protected: typedef GrTAllocator<GrGLShaderVar> VarArray; GrGLProgramBuilder(GrGpuGL*, const GrGLProgramDesc&); - GrGpuGL* gpu() const { return fGpu; } - const GrGLProgramDesc& desc() const { return fDesc; } // Helper for emitEffects(). @@ -162,6 +172,7 @@ protected: int fTexCoordSetCnt; GrGLuint fProgramID; GrGLFragmentShaderBuilder fFS; + SeparableVaryingInfoArray fSeparableVaryingInfos; private: class CodeStage : SkNoncopyable { public: @@ -271,6 +282,17 @@ public: const char** vsOutName = NULL, const char** fsInName = NULL); + /** Add a separable varying input variable to the current program. + * A separable varying (fragment shader input) is a varying that can be used also when vertex + * shaders are not used. With a vertex shader, the operation is same as with other + * varyings. Without a vertex shader, such as with NV_path_rendering, GL APIs are used to + * populate the variable. The APIs can refer to the variable through the returned handle. + */ + VaryingHandle addSeparableVarying(GrSLType type, + const char* name, + const char** vsOutName, + const char** fsInName); + GrGLVertexShaderBuilder* getVertexShaderBuilder() { return &fVS; } private: |