Don't call bindTexture from GrGLProgram

Updates GrGLProgram to tell the gpu object which textures it wants
bound, instead of calling bindTexture directly. This begins to break
its dependence on the specific GrGLGpu object.

BUG=skia:

Review URL: https://codereview.chromium.org/1192463003
This commit is contained in:
cdalton 2015-06-18 11:54:30 -07:00 committed by Commit bot
parent 241b56db1d
commit 4271765d11
5 changed files with 72 additions and 86 deletions

View File

@ -1492,7 +1492,14 @@ bool GrGLGpu::flushGLState(const DrawArgs& args) {
this->flushBlend(blendInfo);
}
program->setData(*args.fPrimitiveProcessor, pipeline, *args.fBatchTracker);
SkSTArray<8, const GrTextureAccess*> textureAccesses;
program->setData(*args.fPrimitiveProcessor, pipeline, *args.fBatchTracker, &textureAccesses);
int numTextureAccesses = textureAccesses.count();
for (int i = 0; i < numTextureAccesses; i++) {
this->bindTexture(i, textureAccesses[i]->getParams(),
static_cast<GrGLTexture*>(textureAccesses[i]->getTexture()));
}
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget());
this->flushStencil(pipeline.getStencil());

View File

@ -34,7 +34,8 @@ GrGLProgram::GrGLProgram(GrGLGpu* gpu,
const UniformInfoArray& uniforms,
GrGLInstalledGeoProc* geometryProcessor,
GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors)
GrGLInstalledFragProcs* fragmentProcessors,
SkTArray<UniformHandle>* passSamplerUniforms)
: fColor(GrColor_ILLEGAL)
, fCoverage(0)
, fDstTextureUnit(-1)
@ -46,7 +47,12 @@ GrGLProgram::GrGLProgram(GrGLGpu* gpu,
, fDesc(desc)
, fGpu(gpu)
, fProgramDataManager(gpu, uniforms) {
this->initSamplerUniforms();
fSamplerUniforms.swap(passSamplerUniforms);
// Assign texture units to sampler uniforms one time up front.
GL_CALL(UseProgram(fProgramID));
for (int i = 0; i < fSamplerUniforms.count(); i++) {
fProgramDataManager.setSampler(fSamplerUniforms[i], i);
}
}
GrGLProgram::~GrGLProgram() {
@ -59,68 +65,46 @@ void GrGLProgram::abandon() {
fProgramID = 0;
}
void GrGLProgram::initSamplerUniforms() {
GL_CALL(UseProgram(fProgramID));
GrGLint texUnitIdx = 0;
this->initSamplers(fGeometryProcessor.get(), &texUnitIdx);
if (fXferProcessor.get()) {
this->initSamplers(fXferProcessor.get(), &texUnitIdx);
}
int numProcs = fFragmentProcessors->fProcs.count();
for (int i = 0; i < numProcs; i++) {
this->initSamplers(fFragmentProcessors->fProcs[i], &texUnitIdx);
}
}
template <class Proc>
void GrGLProgram::initSamplers(Proc* ip, int* texUnitIdx) {
SkTArray<typename Proc::Sampler, true>& samplers = ip->fSamplers;
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)++;
}
}
template <class Proc>
void GrGLProgram::bindTextures(const Proc* ip, const GrProcessor& processor) {
const SkTArray<typename Proc::Sampler, true>& samplers = ip->fSamplers;
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()));
}
}
///////////////////////////////////////////////////////////////////////////////
void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline,
const GrBatchTracker& batchTracker) {
template <class Proc>
static void append_texture_bindings(const Proc* ip,
const GrProcessor& processor,
SkTArray<const GrTextureAccess*>* textureBindings) {
if (int numTextures = processor.numTextures()) {
SkASSERT(textureBindings->count() == ip->fSamplersIdx);
const GrTextureAccess** bindings = textureBindings->push_back_n(numTextures);
int i = 0;
do {
bindings[i] = &processor.textureAccess(i);
} while (++i < numTextures);
}
}
void GrGLProgram::setData(const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline,
const GrBatchTracker& batchTracker,
SkTArray<const GrTextureAccess*>* textureBindings) {
this->setRenderTargetState(primProc, pipeline);
// we set the textures, and uniforms for installed processors in a generic way, but subclasses
// of GLProgram determine how to set coord transforms
fGeometryProcessor->fGLProc->setData(fProgramDataManager, primProc, batchTracker);
this->bindTextures(fGeometryProcessor.get(), primProc);
append_texture_bindings(fGeometryProcessor.get(), primProc, textureBindings);
this->setFragmentData(primProc, pipeline, textureBindings);
const GrXferProcessor& xp = *pipeline.getXferProcessor();
fXferProcessor->fGLProc->setData(fProgramDataManager, xp);
this->bindTextures(fXferProcessor.get(), xp);
this->setFragmentData(primProc, pipeline);
append_texture_bindings(fXferProcessor.get(), xp, textureBindings);
// Some of GrGLProgram subclasses need to update state here
this->didSetData();
}
void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline) {
const GrPipeline& pipeline,
SkTArray<const GrTextureAccess*>* textureBindings) {
int numProcessors = fFragmentProcessors->fProcs.count();
for (int e = 0; e < numProcessors; ++e) {
const GrPendingFragmentStage& stage = pipeline.getFragmentStage(e);
@ -130,7 +114,7 @@ void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc,
stage,
e,
fFragmentProcessors->fProcs[e]);
this->bindTextures(fFragmentProcessors->fProcs[e], processor);
append_texture_bindings(fFragmentProcessors->fProcs[e], processor, textureBindings);
}
}
void GrGLProgram::setTransformData(const GrPrimitiveProcessor& primProc,
@ -181,9 +165,10 @@ GrGLNvprProgram::GrGLNvprProgram(GrGLGpu* gpu,
const UniformInfoArray& uniforms,
GrGLInstalledGeoProc* primProc,
GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors)
GrGLInstalledFragProcs* fragmentProcessors,
SkTArray<UniformHandle>* passSamplerUniforms)
: INHERITED(gpu, desc, builtinUniforms, programID, uniforms, primProc,
xferProcessor, fragmentProcessors) {
xferProcessor, fragmentProcessors, passSamplerUniforms) {
}
void GrGLNvprProgram::didSetData() {
GrGLPathProcessor* pathProc =

View File

@ -90,12 +90,13 @@ public:
};
/**
* This function uploads uniforms and calls each GrGLProcessor's setData. It is called before a
* draw occurs using the program after the program has already been bound. It also uses the
* GrGLGpu object to bind the textures required by the GrGLProcessors. The color and coverage
* stages come from GrGLProgramDesc::Build().
* This function uploads uniforms, calls each GrGLProcessor's setData, and retrieves the
* textures that need to be bound on each unit. It is the caller's responsibility to ensure
* the program is bound before calling, and to bind the outgoing textures to their respective
* units upon return. (Each index in the array corresponds to its matching GL texture unit.)
*/
void setData(const GrPrimitiveProcessor&, const GrPipeline&, const GrBatchTracker&);
void setData(const GrPrimitiveProcessor&, const GrPipeline&, const GrBatchTracker&,
SkTArray<const GrTextureAccess*>* textureBindings);
protected:
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
@ -108,21 +109,16 @@ protected:
const UniformInfoArray&,
GrGLInstalledGeoProc* geometryProcessor,
GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors);
// Sets the texture units for samplers.
void initSamplerUniforms();
template <class Proc>
void initSamplers(Proc*, int* texUnitIdx);
GrGLInstalledFragProcs* fragmentProcessors,
SkTArray<UniformHandle>* passSamplerUniforms);
// A templated helper to loop over effects, set the transforms(via subclass) and bind textures
void setFragmentData(const GrPrimitiveProcessor&, const GrPipeline&);
void setFragmentData(const GrPrimitiveProcessor&, const GrPipeline&,
SkTArray<const GrTextureAccess*>* textureBindings);
virtual void setTransformData(const GrPrimitiveProcessor&,
const GrPendingFragmentStage&,
int index,
GrGLInstalledFragProc*);
template <class Proc>
void bindTextures(const Proc*, const GrProcessor&);
/*
* Legacy NVPR needs a hook here to flush path tex gen settings.
@ -150,6 +146,7 @@ protected:
GrProgramDesc fDesc;
GrGLGpu* fGpu;
GrGLProgramDataManager fProgramDataManager;
SkTArray<UniformHandle> fSamplerUniforms;
friend class GrGLProgramBuilder;
@ -172,7 +169,8 @@ protected:
const UniformInfoArray&,
GrGLInstalledGeoProc*,
GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors);
GrGLInstalledFragProcs* fragmentProcessors,
SkTArray<UniformHandle>* passSamplerUniforms);
private:
void didSetData() override;

View File

@ -38,9 +38,8 @@ public:
static_cast<GrGLPathProcessor*>(fGeometryProcessor->fGLProc.get());
pathProc->resolveSeparableVaryings(fGpu, programID);
return SkNEW_ARGS(GrGLNvprProgram, (fGpu, this->desc(), fUniformHandles, programID,
fUniforms,
fGeometryProcessor,
fXferProcessor, fFragmentProcessors.get()));
fUniforms, fGeometryProcessor, fXferProcessor,
fFragmentProcessors.get(), &fSamplerUniforms));
}
private:
@ -98,7 +97,8 @@ GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args)
, fXferProcessor(NULL)
, fArgs(args)
, fGpu(gpu)
, fUniforms(kVarsPerBlock) {
, fUniforms(kVarsPerBlock)
, fSamplerUniforms(4) {
}
void GrGLProgramBuilder::addVarying(const char* name,
@ -381,16 +381,17 @@ template <class Proc>
void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
GrGLProcessor::TextureSamplerArray* outSamplers,
GrGLInstalledProc<Proc>* ip) {
SkDEBUGCODE(ip->fSamplersIdx = fSamplerUniforms.count();)
int numTextures = processor.numTextures();
ip->fSamplers.push_back_n(numTextures);
UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextures);
SkString name;
for (int t = 0; t < numTextures; ++t) {
name.printf("Sampler%d", t);
ip->fSamplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kSampler2D_GrSLType, kDefault_GrSLPrecision,
name.c_str());
localSamplerUniforms[t] = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kSampler2D_GrSLType, kDefault_GrSLPrecision,
name.c_str());
SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
(ip->fSamplers[t].fUniform, processor.textureAccess(t)));
(localSamplerUniforms[t], processor.textureAccess(t)));
}
}
@ -498,7 +499,8 @@ void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
return SkNEW_ARGS(GrGLProgram, (fGpu, this->desc(), fUniformHandles, programID, fUniforms,
fGeometryProcessor, fXferProcessor, fFragmentProcessors.get()));
fGeometryProcessor, fXferProcessor, fFragmentProcessors.get(),
&fSamplerUniforms));
}
///////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -188,15 +188,8 @@ public:
*/
template <class Proc>
struct GrGLInstalledProc {
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
struct Sampler {
SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
UniformHandle fUniform;
int fTextureUnit;
};
SkSTArray<4, Sampler, true> fSamplers;
SkAutoTDelete<Proc> fGLProc;
SkDEBUGCODE(int fSamplersIdx;)
SkAutoTDelete<Proc> fGLProc;
};
typedef GrGLInstalledProc<GrGLPrimitiveProcessor> GrGLInstalledGeoProc;
@ -390,6 +383,7 @@ protected:
UniformInfoArray fUniforms;
GrGLPrimitiveProcessor::TransformsIn fCoordTransforms;
GrGLPrimitiveProcessor::TransformsOut fOutCoords;
SkTArray<UniformHandle> fSamplerUniforms;
friend class GrGLShaderBuilder;
friend class GrGLVertexBuilder;