diff options
author | joshualitt <joshualitt@chromium.org> | 2014-10-07 12:16:35 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-07 12:16:36 -0700 |
commit | fe1233c3f12f81bb675718516bbb32f72af726ec (patch) | |
tree | b39450a8713c745152561c4497ef65ce7349364a /src/gpu/gl/GrGLProgram.cpp | |
parent | 9323b8b8e16df4adcd63ee8496a6382e8df535c9 (diff) |
Cleanup of shader building system
this is a huge refactor and cleanup of the gl shader building system in
Skia. The entire shader building pipeline is now part of
GrGLProgramCreator, which takes a gp, and some fps, and creates a
program. I added some subclasses of GrGLProgram to handle the
eccentricities of Nvpr/Nvpres. Outside of the builders folder
and GrGLPrograms, this change is basically just a rename
solo gp
BUG=skia:
Review URL: https://codereview.chromium.org/611653002
Diffstat (limited to 'src/gpu/gl/GrGLProgram.cpp')
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 276 |
1 files changed, 225 insertions, 51 deletions
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 480e1b7735..a464a8bbde 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -7,8 +7,6 @@ #include "GrGLProgram.h" -#include "builders/GrGLFullProgramBuilder.h" -#include "builders/GrGLFragmentOnlyProgramBuilder.h" #include "GrAllocator.h" #include "GrProcessor.h" #include "GrCoordTransform.h" @@ -23,45 +21,58 @@ #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X) #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X) -GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu, - const GrOptDrawState& optState, - const GrGLProgramDesc& desc, - const GrGeometryStage* geometryProcessor, - const GrFragmentStage* colorStages[], - const GrFragmentStage* coverageStages[]) { - SkAutoTDelete<GrGLProgramBuilder> builder; - if (desc.getHeader().fUseFragShaderOnly) { - SkASSERT(gpu->glCaps().pathRenderingSupport()); - SkASSERT(gpu->glPathRendering()->texturingMode() == - GrGLPathRendering::FixedFunction_TexturingMode); - SkASSERT(NULL == geometryProcessor); - builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, optState, desc))); +/** + * Retrieves the final matrix that a transform needs to apply to its source coords. + */ +static SkMatrix get_transform_matrix(const GrProcessorStage& processorStage, + bool useExplicitLocalCoords, + int transformIdx) { + const GrCoordTransform& coordTransform = + processorStage.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() : processorStage.getCoordChangeMatrix(); + combined.setConcat(coordTransform.getMatrix(), ccm); } else { - builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, optState, desc))); + combined = coordTransform.getMatrix(); } - if (builder->genProgram(geometryProcessor, colorStages, coverageStages)) { - SkASSERT(0 != builder->getProgramID()); - return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder)); + if (coordTransform.reverseY()) { + // combined.postScale(1,-1); + // combined.postTranslate(0,1); + combined.set(SkMatrix::kMSkewY, + combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]); + combined.set(SkMatrix::kMScaleY, + combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]); + combined.set(SkMatrix::kMTransY, + combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]); } - return NULL; + return combined; } +/////////////////////////////////////////////////////////////////////////////////////////////////// + GrGLProgram::GrGLProgram(GrGpuGL* gpu, const GrGLProgramDesc& desc, - const GrGLProgramBuilder& builder) + const BuiltinUniformHandles& builtinUniforms, + GrGLuint programID, + const UniformInfoArray& uniforms, + GrGLInstalledProcessors* geometryProcessor, + GrGLInstalledProcessors* colorProcessors, + GrGLInstalledProcessors* coverageProcessors) : fColor(GrColor_ILLEGAL) , fCoverage(GrColor_ILLEGAL) , fDstCopyTexUnit(-1) - , fBuiltinUniformHandles(builder.getBuiltinUniformHandles()) - , fGeometryProcessor(SkSafeRef(builder.getGeometryProcessor())) - , fColorEffects(SkRef(builder.getColorEffects())) - , fCoverageEffects(SkRef(builder.getCoverageEffects())) - , fProgramID(builder.getProgramID()) - , fHasVertexShader(builder.hasVertexShader()) - , fTexCoordSetCnt(builder.getTexCoordSetCount()) + , fBuiltinUniformHandles(builtinUniforms) + , fProgramID(programID) + , fGeometryProcessor(SkSafeRef(geometryProcessor)) + , fColorEffects(SkRef(colorProcessors)) + , fCoverageEffects(SkRef(coverageProcessors)) , fDesc(desc) , fGpu(gpu) - , fProgramDataManager(gpu, this, builder) { + , fProgramDataManager(gpu, uniforms) { this->initSamplerUniforms(); } @@ -83,12 +94,42 @@ void GrGLProgram::initSamplerUniforms() { fDstCopyTexUnit = texUnitIdx++; } if (fGeometryProcessor.get()) { - fGeometryProcessor->initSamplers(fProgramDataManager, &texUnitIdx); + this->initSamplers(fGeometryProcessor.get(), &texUnitIdx); + } + this->initSamplers(fColorEffects.get(), &texUnitIdx); + this->initSamplers(fCoverageEffects.get(), &texUnitIdx); +} + +void GrGLProgram::initSamplers(GrGLInstalledProcessors* ip, int* texUnitIdx) { + int numEffects = ip->fGLProcessors.count(); + SkASSERT(numEffects == ip->fSamplers.count()); + for (int e = 0; e < numEffects; ++e) { + SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = ip->fSamplers[e]; + int numSamplers = samplers.count(); + for (int s = 0; s < numSamplers; ++s) { + SkASSERT(samplers[s].fUniform.isValid()); + fProgramDataManager.setSampler(samplers[s].fUniform, *texUnitIdx); + samplers[s].fTextureUnit = (*texUnitIdx)++; + } + } +} + +void GrGLProgram::bindTextures(const GrGLInstalledProcessors* ip, + const GrProcessor& processor, + int effectIdx) { + const SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = ip->fSamplers[effectIdx]; + int numSamplers = samplers.count(); + SkASSERT(numSamplers == processor.numTextures()); + for (int s = 0; s < numSamplers; ++s) { + SkASSERT(samplers[s].fTextureUnit >= 0); + const GrTextureAccess& textureAccess = processor.textureAccess(s); + fGpu->bindTexture(samplers[s].fTextureUnit, + textureAccess.getParams(), + static_cast<GrGLTexture*>(textureAccess.getTexture())); } - fColorEffects->initSamplers(fProgramDataManager, &texUnitIdx); - fCoverageEffects->initSamplers(fProgramDataManager, &texUnitIdx); } + /////////////////////////////////////////////////////////////////////////////// void GrGLProgram::setData(const GrOptDrawState& optState, @@ -126,21 +167,39 @@ void GrGLProgram::setData(const GrOptDrawState& optState, SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid()); } + // we set the textures, and uniforms for installed processors in a generic way, but subclasses + // of GLProgram determine how to set coord transforms if (fGeometryProcessor.get()) { SkASSERT(geometryProcessor); - fGeometryProcessor->setData(fGpu, drawType, fProgramDataManager, geometryProcessor); + this->setData<GrGeometryStage>(&geometryProcessor, fGeometryProcessor.get()); } - fColorEffects->setData(fGpu, drawType, fProgramDataManager, colorStages); - fCoverageEffects->setData(fGpu, drawType, fProgramDataManager, coverageStages); + this->setData<GrFragmentStage>(colorStages, fColorEffects.get()); + this->setData<GrFragmentStage>(coverageStages, fCoverageEffects.get()); + + // Some of GrGLProgram subclasses need to update state here + this->didSetData(drawType); +} - // 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 - // settings in that case. - if (!fHasVertexShader) { - fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt); +void GrGLProgram::setTransformData(const GrProcessorStage& processor, + int effectIdx, + GrGLInstalledProcessors* ip) { + SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = ip->fTransforms[effectIdx]; + int numTransforms = transforms.count(); + 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->fHasExplicitLocalCoords, t); + if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) { + fProgramDataManager.setSkMatrix(transforms[t].fHandle.convertToUniformHandle(), matrix); + transforms[t].fCurrentValue = matrix; + } } } +void GrGLProgram::didSetData(GrGpu::DrawType drawType) { + SkASSERT(!GrGpu::IsPathRenderingDrawType(drawType)); +} + void GrGLProgram::setColor(const GrOptDrawState& optState, GrColor color, SharedGLState* sharedState) { @@ -220,22 +279,25 @@ void GrGLProgram::setCoverage(const GrOptDrawState& optState, void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, const GrOptDrawState& optState) { - const GrRenderTarget* rt = optState.getRenderTarget(); - SkISize size; - size.set(rt->width(), rt->height()); - // Load the RT height uniform if it is needed to y-flip gl_FragCoord. if (fBuiltinUniformHandles.fRTHeightUni.isValid() && - fMatrixState.fRenderTargetSize.fHeight != size.fHeight) { + fMatrixState.fRenderTargetSize.fHeight != optState.getRenderTarget()->width()) { fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, - SkIntToScalar(size.fHeight)); + SkIntToScalar(optState.getRenderTarget()->height())); } - if (GrGpu::IsPathRenderingDrawType(drawType)) { - fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin()); - } else if (fMatrixState.fRenderTargetOrigin != rt->origin() || - fMatrixState.fRenderTargetSize != size || - !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) { + // call subclasses to set the actual view matrix + this->onSetMatrixAndRenderTargetHeight(drawType, optState); +} + +void GrGLProgram::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, + const GrOptDrawState& optState) { + const GrRenderTarget* rt = optState.getRenderTarget(); + SkISize size; + size.set(rt->width(), rt->height()); + if (fMatrixState.fRenderTargetOrigin != rt->origin() || + fMatrixState.fRenderTargetSize != size || + !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) { SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid()); fMatrixState.fViewMatrix = optState.getViewMatrix(); @@ -251,3 +313,115 @@ void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec); } } + +///////////////////////////////////////////////////////////////////////////////////////// + +GrGLNvprProgramBase::GrGLNvprProgramBase(GrGpuGL* gpu, + const GrGLProgramDesc& desc, + const BuiltinUniformHandles& builtinUniforms, + GrGLuint programID, + const UniformInfoArray& uniforms, + GrGLInstalledProcessors* colorProcessors, + GrGLInstalledProcessors* coverageProcessors) + : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL, colorProcessors, + coverageProcessors) { +} + +void GrGLNvprProgramBase::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, + const GrOptDrawState& optState) { + SkASSERT(GrGpu::IsPathRenderingDrawType(drawType)); + const GrRenderTarget* rt = optState.getRenderTarget(); + SkISize size; + size.set(rt->width(), rt->height()); + fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin()); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +GrGLNvprProgram::GrGLNvprProgram(GrGpuGL* gpu, + const GrGLProgramDesc& desc, + const BuiltinUniformHandles& builtinUniforms, + GrGLuint programID, + const UniformInfoArray& uniforms, + GrGLInstalledProcessors* colorProcessors, + GrGLInstalledProcessors* coverageProcessors, + const SeparableVaryingInfoArray& separableVaryings) + : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, colorProcessors, + coverageProcessors) { + int count = separableVaryings.count(); + fVaryings.push_back_n(count); + for (int i = 0; i < count; i++) { + Varying& varying = fVaryings[i]; + const SeparableVaryingInfo& builderVarying = separableVaryings[i]; + SkASSERT(GrGLShaderVar::kNonArray == builderVarying.fVariable.getArrayCount()); + SkDEBUGCODE( + varying.fType = builderVarying.fVariable.getType(); + ); + varying.fLocation = builderVarying.fLocation; + } +} + +void GrGLNvprProgram::didSetData(GrGpu::DrawType drawType) { + SkASSERT(GrGpu::IsPathRenderingDrawType(drawType)); +} + +void GrGLNvprProgram::setTransformData(const GrProcessorStage& processor, + int effectIdx, + GrGLInstalledProcessors* ip) { + SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = ip->fTransforms[effectIdx]; + int numTransforms = transforms.count(); + SkASSERT(numTransforms == processor.getProcessor()->numTransforms()); + for (int t = 0; t < numTransforms; ++t) { + SkASSERT(transforms[t].fHandle.isValid()); + const SkMatrix& transform = get_transform_matrix(processor, ip->fHasExplicitLocalCoords, t); + if (transforms[t].fCurrentValue.cheapEqualTo(transform)) { + continue; + } + transforms[t].fCurrentValue = transform; + const Varying& fragmentInput = fVaryings[transforms[t].fHandle.handle()]; + SkASSERT(transforms[t].fType == kVec2f_GrSLType || transforms[t].fType == kVec3f_GrSLType); + unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3; + fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgramID, + fragmentInput.fLocation, + GR_GL_OBJECT_LINEAR, + components, + transform); + } +} + +////////////////////////////////////////////////////////////////////////////////////// + +GrGLLegacyNvprProgram::GrGLLegacyNvprProgram(GrGpuGL* gpu, + const GrGLProgramDesc& desc, + const BuiltinUniformHandles& builtinUniforms, + GrGLuint programID, + const UniformInfoArray& uniforms, + GrGLInstalledProcessors* colorProcessors, + GrGLInstalledProcessors* coverageProcessors, + int texCoordSetCnt) + : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, colorProcessors, + coverageProcessors) + , fTexCoordSetCnt(texCoordSetCnt) { +} + +void GrGLLegacyNvprProgram::didSetData(GrGpu::DrawType drawType) { + SkASSERT(GrGpu::IsPathRenderingDrawType(drawType)); + fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt); +} + +void GrGLLegacyNvprProgram::setTransformData(const GrProcessorStage& processorStage, + int effectIdx, + GrGLInstalledProcessors* ip) { + // We've hidden the texcoord index in the first entry of the transforms array for each effect + int texCoordIndex = ip->fTransforms[effectIdx][0].fHandle.handle(); + int numTransforms = processorStage.getProcessor()->numTransforms(); + for (int t = 0; t < numTransforms; ++t) { + const SkMatrix& transform = get_transform_matrix(processorStage, false, t); + GrGLPathRendering::PathTexGenComponents components = + GrGLPathRendering::kST_PathTexGenComponents; + if (processorStage.isPerspectiveCoordTransform(t, false)) { + components = GrGLPathRendering::kSTR_PathTexGenComponents; + } + fGpu->glPathRendering()->enablePathTexGen(texCoordIndex++, components, transform); + } +} |