Use vertexless shaders when NVpr is available

Adds support for vertexless shaders and enables them when
NV_path_rendering is available. This takes a
GrGLFragmentOnlyShaderBuilder class, a GrGLTexGenEffectArray class,
support for setting TexGen and the projection matrix in GrGpuGL, and
code for setting the GL fixed function state where necessary.

R=bsalomon@google.com, kkinnunen@nvidia.com

Author: cdalton@nvidia.com

Review URL: https://codereview.chromium.org/25846002

git-svn-id: http://skia.googlecode.com/svn/trunk@11620 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2013-10-04 20:02:53 +00:00
Родитель d35736d2d2
Коммит 6b30e45740
11 изменённых файлов: 775 добавлений и 277 удалений

Просмотреть файл

@ -39,7 +39,9 @@ GrGLProgram::GrGLProgram(GrGpuGL* gpu,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[])
: fGpu(gpu)
, fUniformManager(gpu) {
, fUniformManager(gpu)
, fHasVertexShader(false)
, fNumTexCoordSets(0) {
fDesc = desc;
fProgramID = 0;
@ -48,7 +50,21 @@ GrGLProgram::GrGLProgram(GrGpuGL* gpu,
fColor = GrColor_ILLEGAL;
fColorFilterColor = GrColor_ILLEGAL;
this->genProgram(colorStages, coverageStages);
if (fDesc.getHeader().fHasVertexCode ||
!fGpu->glCaps().fixedFunctionSupport() ||
!fGpu->glCaps().pathStencilingSupport()) {
GrGLFullShaderBuilder fullBuilder(fGpu, fUniformManager, fDesc);
if (this->genProgram(&fullBuilder, colorStages, coverageStages)) {
fUniformHandles.fViewMatrixUni = fullBuilder.getViewMatrixUniform();
fHasVertexShader = true;
}
} else {
GrGLFragmentOnlyShaderBuilder fragmentOnlyBuilder(fGpu, fUniformManager, fDesc);
if (this->genProgram(&fragmentOnlyBuilder, colorStages, coverageStages)) {
fNumTexCoordSets = fragmentOnlyBuilder.getNumTexCoordSets();
}
}
}
GrGLProgram::~GrGLProgram() {
@ -205,18 +221,16 @@ void expand_known_value4f(SkString* string, GrSLConstantVec vec) {
}
bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[]) {
SkASSERT(0 == fProgramID);
const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
GrGLFullShaderBuilder builder(fGpu, fUniformManager, fDesc);
fUniformHandles.fViewMatrixUni = builder.getViewMatrixUniform();
// incoming color to current stage being processed.
SkString inColor = builder.getInputColor();
GrSLConstantVec knownColorValue = builder.getKnownColorValue();
SkString inColor = builder->getInputColor();
GrSLConstantVec knownColorValue = builder->getKnownColorValue();
// Get the coeffs for the Mode-based color filter, determine if color is needed.
SkXfermode::Coeff colorCoeff;
@ -229,20 +243,20 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor);
fColorEffects.reset(
builder.createAndEmitEffects(colorStages,
fDesc.effectKeys(),
needColor ? fDesc.numColorEffects() : 0,
&inColor,
&knownColorValue));
builder->createAndEmitEffects(colorStages,
fDesc.effectKeys(),
needColor ? fDesc.numColorEffects() : 0,
&inColor,
&knownColorValue));
// Insert the color filter. This will soon be replaced by a color effect.
if (SkXfermode::kDst_Mode != header.fColorFilterXfermode) {
const char* colorFilterColorUniName = NULL;
fUniformHandles.fColorFilterUni = builder.addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "FilterColor",
&colorFilterColorUniName);
fUniformHandles.fColorFilterUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "FilterColor",
&colorFilterColorUniName);
builder.fsCodeAppend("\tvec4 filteredColor;\n");
builder->fsCodeAppend("\tvec4 filteredColor;\n");
const char* color;
// add_color_filter requires a real input string.
if (knownColorValue == kOnes_GrSLConstantVec) {
@ -252,36 +266,36 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
} else {
color = inColor.c_str();
}
add_color_filter(&builder, "filteredColor", filterColorCoeff,
add_color_filter(builder, "filteredColor", filterColorCoeff,
colorCoeff, colorFilterColorUniName, color);
inColor = "filteredColor";
}
///////////////////////////////////////////////////////////////////////////
// compute the partial coverage
SkString inCoverage = builder.getInputCoverage();
GrSLConstantVec knownCoverageValue = builder.getKnownCoverageValue();
SkString inCoverage = builder->getInputCoverage();
GrSLConstantVec knownCoverageValue = builder->getKnownCoverageValue();
fCoverageEffects.reset(
builder.createAndEmitEffects(coverageStages,
fDesc.getEffectKeys() + fDesc.numColorEffects(),
fDesc.numCoverageEffects(),
&inCoverage,
&knownCoverageValue));
builder->createAndEmitEffects(coverageStages,
fDesc.getEffectKeys() + fDesc.numColorEffects(),
fDesc.numCoverageEffects(),
&inCoverage,
&knownCoverageValue));
// discard if coverage is zero
if (header.fDiscardIfZeroCoverage && kOnes_GrSLConstantVec != knownCoverageValue) {
if (kZeros_GrSLConstantVec == knownCoverageValue) {
// This is unfortunate.
builder.fsCodeAppend("\tdiscard;\n");
builder->fsCodeAppend("\tdiscard;\n");
} else {
builder.fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n",
inCoverage.c_str());
builder->fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n",
inCoverage.c_str());
}
}
if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
const char* secondaryOutputName = builder.enableSecondaryOutput();
const char* secondaryOutputName = builder->enableSecondaryOutput();
// default coeff to ones for kCoverage_DualSrcOutput
SkString coeff;
@ -317,7 +331,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
knownCoeffValue,
knownCoverageValue,
false);
builder.fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, modulate.c_str());
builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, modulate.c_str());
}
///////////////////////////////////////////////////////////////////////////
@ -343,7 +357,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
SkString dstContribution;
GrSLConstantVec knownDstContributionValue = GrGLSLModulatef<4>(&dstContribution,
dstCoeff.c_str(),
builder.dstColor(),
builder->dstColor(),
knownDstCoeffValue,
kNone_GrSLConstantVec,
true);
@ -358,18 +372,18 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
} else {
expand_known_value4f(&fragColor, knownFragColorValue);
}
builder.fsCodeAppendf("\t%s = %s;\n", builder.getColorOutputName(), fragColor.c_str());
builder->fsCodeAppendf("\t%s = %s;\n", builder->getColorOutputName(), fragColor.c_str());
if (!builder.finish(&fProgramID)) {
if (!builder->finish(&fProgramID)) {
return false;
}
fUniformHandles.fRTHeightUni = builder.getRTHeightUniform();
fUniformHandles.fDstCopyTopLeftUni = builder.getDstCopyTopLeftUniform();
fUniformHandles.fDstCopyScaleUni = builder.getDstCopyScaleUniform();
fUniformHandles.fColorUni = builder.getColorUniform();
fUniformHandles.fCoverageUni = builder.getCoverageUniform();
fUniformHandles.fDstCopySamplerUni = builder.getDstCopySamplerUniform();
fUniformHandles.fRTHeightUni = builder->getRTHeightUniform();
fUniformHandles.fDstCopyTopLeftUni = builder->getDstCopyTopLeftUniform();
fUniformHandles.fDstCopyScaleUni = builder->getDstCopyScaleUniform();
fUniformHandles.fColorUni = builder->getColorUniform();
fUniformHandles.fCoverageUni = builder->getCoverageUniform();
fUniformHandles.fDstCopySamplerUni = builder->getDstCopySamplerUniform();
// This must be called after we set fDstCopySamplerUni above.
this->initSamplerUniforms();
@ -445,6 +459,10 @@ void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
fColorEffects->setData(fGpu, fUniformManager, colorStages);
fCoverageEffects->setData(fGpu, fUniformManager, coverageStages);
if (!fHasVertexShader) {
fGpu->disableUnusedTexGen(fNumTexCoordSets);
}
}
void GrGLProgram::setColor(const GrDrawState& drawState,
@ -537,9 +555,13 @@ void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight));
}
if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
!fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix()) ||
fMatrixState.fRenderTargetSize != size) {
if (!fHasVertexShader) {
SkASSERT(!fUniformHandles.fViewMatrixUni.isValid());
fGpu->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
} else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
fMatrixState.fRenderTargetSize != size ||
!fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) {
SkASSERT(fUniformHandles.fViewMatrixUni.isValid());
fMatrixState.fViewMatrix = drawState.getViewMatrix();
fMatrixState.fRenderTargetSize = size;

Просмотреть файл

@ -62,6 +62,8 @@ public:
*/
GrGLuint programID() const { return fProgramID; }
bool hasVertexShader() const { return fHasVertexShader; }
/**
* Some GL state that is relevant to programs is not stored per-program. In particular color
* and coverage attributes can be global state. This struct is read and updated by
@ -160,7 +162,9 @@ private:
* This is the heavy initialization routine for building a GLProgram. colorStages and
* coverageStages correspond to the output of GrGLProgramDesc::Build().
*/
bool genProgram(const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[]);
bool genProgram(GrGLShaderBuilder* builder,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[]);
// Sets the texture units for samplers
void initSamplerUniforms();
@ -195,6 +199,9 @@ private:
GrGLUniformManager fUniformManager;
UniformHandles fUniformHandles;
bool fHasVertexShader;
int fNumTexCoordSets;
typedef SkRefCnt INHERITED;
};

Просмотреть файл

@ -233,6 +233,7 @@ private:
friend class GrGLProgram;
friend class GrGLShaderBuilder;
friend class GrGLFullShaderBuilder;
friend class GrGLFragmentOnlyShaderBuilder;
};
#endif

Просмотреть файл

@ -37,7 +37,6 @@ enum {
kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
kTransformKeyBits = kMatrixTypeKeyBits + 1,
kTransformKeyMask = (1 << kTransformKeyBits) - 1,
};
namespace {
@ -69,8 +68,78 @@ inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
return false;
}
/**
* Retrieves the matrix type from transformKey for the transform at transformIdx.
*/
MatrixType get_matrix_type(EffectKey transformKey, int transformIdx) {
return static_cast<MatrixType>(
(transformKey >> (kTransformKeyBits * transformIdx)) & kMatrixTypeKeyMask);
}
/**
* Retrieves the source coords from transformKey for the transform at transformIdx. It may not be
* the same coordinate set as the original GrCoordTransform if the position and local coords are
* identical for this program.
*/
GrCoordSet get_source_coords(EffectKey transformKey, int transformIdx) {
return (transformKey >> (kTransformKeyBits * transformIdx)) & kPositionCoords_Flag ?
kPosition_GrCoordSet :
kLocal_GrCoordSet;
}
/**
* Retrieves the final translation that a transform needs to apply to its source coords (and
* verifies that a translation is all it needs).
*/
void get_transform_translation(const GrDrawEffect& drawEffect,
int transformIdx,
GrGLfloat* tx,
GrGLfloat* ty) {
const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(transformIdx);
SkASSERT(!coordTransform.reverseY());
const SkMatrix& matrix = coordTransform.getMatrix();
if (kLocal_GrCoordSet == coordTransform.sourceCoords() &&
!drawEffect.programHasExplicitLocalCoords()) {
const SkMatrix& coordChangeMatrix = drawEffect.getCoordChangeMatrix();
SkASSERT(SkMatrix::kTranslate_Mask == (matrix.getType() | coordChangeMatrix.getType()));
*tx = SkScalarToFloat(matrix[SkMatrix::kMTransX] + coordChangeMatrix[SkMatrix::kMTransX]);
*ty = SkScalarToFloat(matrix[SkMatrix::kMTransY] + coordChangeMatrix[SkMatrix::kMTransY]);
} else {
SkASSERT(SkMatrix::kTranslate_Mask == matrix.getType());
*tx = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
*ty = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
}
}
/**
* Retrieves the final matrix that a transform needs to apply to its source coords.
*/
SkMatrix get_transform_matrix(const GrDrawEffect& drawEffect, int transformIdx) {
const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(transformIdx);
SkMatrix combined;
if (kLocal_GrCoordSet == coordTransform.sourceCoords() &&
!drawEffect.programHasExplicitLocalCoords()) {
combined.setConcat(coordTransform.getMatrix(), drawEffect.getCoordChangeMatrix());
} else {
combined = coordTransform.getMatrix();
}
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 combined;
}
}
////////////////////////////////////////////////////////////////////////////////
EffectKey GrGLProgramEffects::GenAttribKey(const GrDrawEffect& drawEffect) {
EffectKey key = 0;
int numAttributes = drawEffect.getVertexAttribIndexCount();
@ -144,6 +213,23 @@ GrGLProgramEffects::~GrGLProgramEffects() {
}
}
void GrGLProgramEffects::emitSamplers(GrGLShaderBuilder* builder,
const GrEffectRef& effect,
TextureSamplerArray* outSamplers) {
SkTArray<Sampler, true>& samplers = fSamplers.push_back();
int numTextures = effect->numTextures();
samplers.push_back_n(numTextures);
SkString name;
for (int t = 0; t < numTextures; ++t) {
name.printf("Sampler%d", t);
samplers[t].fUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kSampler2D_GrSLType,
name.c_str());
SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler,
(samplers[t].fUniform, effect->textureAccess(t)));
}
}
void GrGLProgramEffects::initSamplers(const GrGLUniformManager& uniformManager, int* texUnitIdx) {
int numEffects = fGLEffects.count();
SkASSERT(numEffects == fSamplers.count());
@ -158,77 +244,6 @@ void GrGLProgramEffects::initSamplers(const GrGLUniformManager& uniformManager,
}
}
void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
const GrGLUniformManager& uniformManager,
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(uniformManager, drawEffect);
this->setTransformData(uniformManager, drawEffect, e);
this->bindTextures(gpu, *drawEffect.effect(), e);
}
}
void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& uniformManager,
const GrDrawEffect& drawEffect,
int effectIdx) {
SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
int numTransforms = transforms.count();
SkASSERT(numTransforms == (*drawEffect.effect())->numTransforms());
for (int t = 0; t < numTransforms; ++t) {
const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(t);
const SkMatrix& matrix = coordTransform.getMatrix();
const SkMatrix& coordChangeMatrix = kLocal_GrCoordSet == coordTransform.sourceCoords() ?
drawEffect.getCoordChangeMatrix() :
SkMatrix::I();
SkASSERT(transforms[t].fHandle.isValid() != (kVoid_GrSLType == transforms[t].fType));
switch (transforms[t].fType) {
case kVoid_GrSLType:
SkASSERT(matrix.isIdentity());
SkASSERT(coordChangeMatrix.isIdentity());
SkASSERT(!coordTransform.reverseY());
return;
case kVec2f_GrSLType: {
SkASSERT(SkMatrix::kTranslate_Mask == (matrix.getType() | coordChangeMatrix.getType()));
SkASSERT(!coordTransform.reverseY());
SkScalar tx = matrix[SkMatrix::kMTransX] + (coordChangeMatrix)[SkMatrix::kMTransX];
SkScalar ty = matrix[SkMatrix::kMTransY] + (coordChangeMatrix)[SkMatrix::kMTransY];
if (transforms[t].fCurrentValue.get(SkMatrix::kMTransX) != tx ||
transforms[t].fCurrentValue.get(SkMatrix::kMTransY) != ty) {
uniformManager.set2f(transforms[t].fHandle, tx, ty);
transforms[t].fCurrentValue.set(SkMatrix::kMTransX, tx);
transforms[t].fCurrentValue.set(SkMatrix::kMTransY, ty);
}
break;
}
case kMat33f_GrSLType: {
SkMatrix combined;
combined.setConcat(matrix, coordChangeMatrix);
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]);
}
if (!transforms[t].fCurrentValue.cheapEqualTo(combined)) {
uniformManager.setSkMatrix(transforms[t].fHandle, combined);
transforms[t].fCurrentValue = combined;
}
break;
}
default:
GrCrash("Unexpected uniform type.");
}
}
}
void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffectRef& effect, int effectIdx) {
const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx];
int numSamplers = samplers.count();
@ -244,75 +259,67 @@ void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffectRef& effect, i
////////////////////////////////////////////////////////////////////////////////
GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder* builder,
int reserveCount)
: fBuilder(builder)
, fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
(reserveCount, fBuilder->hasExplicitLocalCoords()))) {
}
void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
EffectKey key,
const char* outColor,
const char* inColor,
int stageIndex) {
SkASSERT(NULL != fProgramEffects.get());
GrDrawEffect drawEffect(stage, fProgramEffects->fHasExplicitLocalCoords);
void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder,
const GrEffectStage& stage,
EffectKey key,
const char* outColor,
const char* inColor,
int stageIndex) {
GrDrawEffect drawEffect(stage, fHasExplicitLocalCoords);
const GrEffectRef& effect = *stage.getEffect();
SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
SkSTArray<4, TextureSampler> samplers(effect->numTextures());
this->emitAttributes(stage);
this->emitTransforms(effect, key, &coords);
INHERITED::emitSamplers(fBuilder, fProgramEffects.get(), effect, &samplers);
this->emitAttributes(builder, stage);
this->emitTransforms(builder, effect, key, &coords);
this->emitSamplers(builder, effect, &samplers);
GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
fProgramEffects->fGLEffects.push_back(glEffect);
fGLEffects.push_back(glEffect);
// Enclose custom code in a block to avoid namespace conflicts
SkString openBrace;
openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
fBuilder->vsCodeAppend(openBrace.c_str());
fBuilder->fsCodeAppend(openBrace.c_str());
builder->vsCodeAppend(openBrace.c_str());
builder->fsCodeAppend(openBrace.c_str());
if (glEffect->isVertexEffect()) {
GrGLVertexEffect* vertexEffect = static_cast<GrGLVertexEffect*>(glEffect);
vertexEffect->emitCode(fBuilder, drawEffect, key, outColor, inColor, coords, samplers);
vertexEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
} else {
glEffect->emitCode(fBuilder, drawEffect, key, outColor, inColor, coords, samplers);
glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
}
fBuilder->vsCodeAppend("\t}\n");
fBuilder->fsCodeAppend("\t}\n");
builder->vsCodeAppend("\t}\n");
builder->fsCodeAppend("\t}\n");
}
void GrGLVertexProgramEffectsBuilder::emitAttributes(const GrEffectStage& stage) {
void GrGLVertexProgramEffects::emitAttributes(GrGLFullShaderBuilder* builder,
const GrEffectStage& stage) {
int numAttributes = stage.getVertexAttribIndexCount();
const int* attributeIndices = stage.getVertexAttribIndices();
for (int a = 0; a < numAttributes; ++a) {
// TODO: Make addAttribute mangle the name.
SkString attributeName("aAttr");
attributeName.appendS32(attributeIndices[a]);
fBuilder->addEffectAttribute(attributeIndices[a],
(*stage.getEffect())->vertexAttribType(a),
attributeName);
builder->addEffectAttribute(attributeIndices[a],
(*stage.getEffect())->vertexAttribType(a),
attributeName);
}
}
void GrGLVertexProgramEffectsBuilder::emitTransforms(const GrEffectRef& effect,
EffectKey effectKey,
TransformedCoordsArray* outCoords) {
typedef GrGLVertexProgramEffects::Transform Transform;
SkTArray<Transform, true>& transforms = fProgramEffects->fTransforms.push_back();
void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder,
const GrEffectRef& effect,
EffectKey effectKey,
TransformedCoordsArray* outCoords) {
SkTArray<Transform, true>& transforms = fTransforms.push_back();
EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey);
int numTransforms = effect->numTransforms();
transforms.push_back_n(numTransforms);
for (int t = 0; t < numTransforms; t++) {
EffectKey key = (totalKey >> (kTransformKeyBits * t)) & kTransformKeyMask;
GrSLType varyingType = kVoid_GrSLType;
const char* uniName;
switch (key & kMatrixTypeKeyMask) {
switch (get_matrix_type(totalKey, t)) {
case kIdentity_MatrixType:
transforms[t].fType = kVoid_GrSLType;
uniName = NULL;
@ -343,10 +350,10 @@ void GrGLVertexProgramEffectsBuilder::emitTransforms(const GrEffectRef& effect,
suffixedUniName.appendf("_%i", t);
uniName = suffixedUniName.c_str();
}
transforms[t].fHandle = fBuilder->addUniform(GrGLShaderBuilder::kVertex_Visibility,
transforms[t].fType,
uniName,
&uniName);
transforms[t].fHandle = builder->addUniform(GrGLShaderBuilder::kVertex_Visibility,
transforms[t].fType,
uniName,
&uniName);
}
const char* varyingName = "MatrixCoord";
@ -358,55 +365,222 @@ void GrGLVertexProgramEffectsBuilder::emitTransforms(const GrEffectRef& effect,
}
const char* vsVaryingName;
const char* fsVaryingName;
fBuilder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
const GrGLShaderVar& coords = (kPositionCoords_Flag & key) ?
fBuilder->positionAttribute() :
fBuilder->localCoordsAttribute();
const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ?
builder->positionAttribute() :
builder->localCoordsAttribute();
// varying = matrix * coords (logically)
switch (transforms[t].fType) {
case kVoid_GrSLType:
SkASSERT(kVec2f_GrSLType == varyingType);
fBuilder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords.c_str());
builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords.c_str());
break;
case kVec2f_GrSLType:
SkASSERT(kVec2f_GrSLType == varyingType);
fBuilder->vsCodeAppendf("\t%s = %s + %s;\n",
vsVaryingName, uniName, coords.c_str());
builder->vsCodeAppendf("\t%s = %s + %s;\n",
vsVaryingName, uniName, coords.c_str());
break;
case kMat33f_GrSLType: {
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
if (kVec2f_GrSLType == varyingType) {
fBuilder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
vsVaryingName, uniName, coords.c_str());
builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
vsVaryingName, uniName, coords.c_str());
} else {
fBuilder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n",
vsVaryingName, uniName, coords.c_str());
builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n",
vsVaryingName, uniName, coords.c_str());
}
break;
}
default:
GrCrash("Unexpected uniform type.");
}
SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (fsVaryingName, varyingType));
SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords,
(SkString(fsVaryingName), varyingType));
}
}
void GrGLProgramEffectsBuilder::emitSamplers(GrGLShaderBuilder* builder,
GrGLProgramEffects* programEffects,
const GrEffectRef& effect,
TextureSamplerArray* outSamplers) {
typedef GrGLProgramEffects::Sampler Sampler;
SkTArray<Sampler, true>& samplers = programEffects->fSamplers.push_back();
int numTextures = effect->numTextures();
samplers.push_back_n(numTextures);
SkString name;
for (int t = 0; t < numTextures; ++t) {
name.printf("Sampler%d", t);
samplers[t].fUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kSampler2D_GrSLType,
name.c_str());
SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler,
(samplers[t].fUniform, effect->textureAccess(t)));
void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
const GrGLUniformManager& uniformManager,
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(uniformManager, drawEffect);
this->setTransformData(uniformManager, drawEffect, e);
this->bindTextures(gpu, *drawEffect.effect(), e);
}
}
void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& uniformManager,
const GrDrawEffect& drawEffect,
int effectIdx) {
SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
int numTransforms = transforms.count();
SkASSERT(numTransforms == (*drawEffect.effect())->numTransforms());
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(transforms[t].fHandle.isValid() != (kVoid_GrSLType == transforms[t].fType));
switch (transforms[t].fType) {
case kVoid_GrSLType:
SkASSERT(get_transform_matrix(drawEffect, t).isIdentity());
return;
case kVec2f_GrSLType: {
GrGLfloat tx, ty;
get_transform_translation(drawEffect, t, &tx, &ty);
if (transforms[t].fCurrentValue.get(SkMatrix::kMTransX) != tx ||
transforms[t].fCurrentValue.get(SkMatrix::kMTransY) != ty) {
uniformManager.set2f(transforms[t].fHandle, tx, ty);
transforms[t].fCurrentValue.set(SkMatrix::kMTransX, tx);
transforms[t].fCurrentValue.set(SkMatrix::kMTransY, ty);
}
break;
}
case kMat33f_GrSLType: {
const SkMatrix& matrix = get_transform_matrix(drawEffect, t);
if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
uniformManager.setSkMatrix(transforms[t].fHandle, matrix);
transforms[t].fCurrentValue = matrix;
}
break;
}
default:
GrCrash("Unexpected uniform type.");
}
}
}
GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder* builder,
int reserveCount)
: fBuilder(builder)
, fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
(reserveCount, fBuilder->hasExplicitLocalCoords()))) {
}
void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
GrGLProgramEffects::EffectKey key,
const char* outColor,
const char* inColor,
int stageIndex) {
SkASSERT(NULL != fProgramEffects.get());
fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
}
////////////////////////////////////////////////////////////////////////////////
void GrGLTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* builder,
const GrEffectStage& stage,
EffectKey key,
const char* outColor,
const char* inColor,
int stageIndex) {
GrDrawEffect drawEffect(stage, false);
const GrEffectRef& effect = *stage.getEffect();
SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
SkSTArray<4, TextureSampler> samplers(effect->numTextures());
SkASSERT(0 == stage.getVertexAttribIndexCount());
this->setupTexGen(builder, effect, key, &coords);
this->emitSamplers(builder, effect, &samplers);
GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
fGLEffects.push_back(glEffect);
// Enclose custom code in a block to avoid namespace conflicts
SkString openBrace;
openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
builder->fsCodeAppend(openBrace.c_str());
SkASSERT(!glEffect->isVertexEffect());
glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
builder->fsCodeAppend("\t}\n");
}
void GrGLTexGenProgramEffects::setupTexGen(GrGLFragmentOnlyShaderBuilder* builder,
const GrEffectRef& effect,
EffectKey effectKey,
TransformedCoordsArray* outCoords) {
int numTransforms = effect->numTransforms();
EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey);
int texCoordIndex = builder->addTexCoordSets(numTransforms);
SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
SkString name;
for (int t = 0; t < numTransforms; ++t) {
GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ?
kVec3f_GrSLType :
kVec2f_GrSLType;
name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type));
}
}
void GrGLTexGenProgramEffects::setData(GrGpuGL* gpu,
const GrGLUniformManager& uniformManager,
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(uniformManager, drawEffect);
this->setTexGenState(gpu, drawEffect, e);
this->bindTextures(gpu, *drawEffect.effect(), e);
}
}
void GrGLTexGenProgramEffects::setTexGenState(GrGpuGL* gpu,
const GrDrawEffect& drawEffect,
int effectIdx) {
EffectKey totalKey = fTransforms[effectIdx].fTransformKey;
int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
int numTransforms = (*drawEffect.effect())->numTransforms();
for (int t = 0; t < numTransforms; ++t) {
switch (get_matrix_type(totalKey, t)) {
case kIdentity_MatrixType: {
SkASSERT(get_transform_matrix(drawEffect, t).isIdentity());
GrGLfloat identity[] = {1, 0, 0,
0, 1, 0};
gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, identity);
break;
}
case kTrans_MatrixType: {
GrGLfloat tx, ty;
get_transform_translation(drawEffect, t, &tx, &ty);
GrGLfloat translate[] = {1, 0, tx,
0, 1, ty};
gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, translate);
break;
}
case kNoPersp_MatrixType: {
const SkMatrix& transform = get_transform_matrix(drawEffect, t);
gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, transform);
break;
}
case kGeneral_MatrixType: {
const SkMatrix& transform = get_transform_matrix(drawEffect, t);
gpu->enableTexGen(texCoordIndex++, GrGpuGL::kSTR_TexGenComponents, transform);
break;
}
default:
GrCrash("Unexpected matrixs type.");
}
}
}
GrGLTexGenProgramEffectsBuilder::GrGLTexGenProgramEffectsBuilder(
GrGLFragmentOnlyShaderBuilder* builder,
int reserveCount)
: fBuilder(builder)
, fProgramEffects(SkNEW_ARGS(GrGLTexGenProgramEffects, (reserveCount))) {
}
void GrGLTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
GrGLProgramEffects::EffectKey key,
const char* outColor,
const char* inColor,
int stageIndex) {
SkASSERT(NULL != fProgramEffects.get());
fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
}

Просмотреть файл

@ -14,10 +14,10 @@
#include "GrGLUniformManager.h"
class GrEffectStage;
class GrGLProgramEffectsBuilder;
class GrGLVertexProgramEffectsBuilder;
class GrGLShaderBuilder;
class GrGLFullShaderBuilder;
class GrGLFragmentOnlyShaderBuilder;
/**
* This class encapsulates an array of GrGLEffects and their supporting data (coord transforms
@ -56,7 +56,7 @@ public:
*/
class TransformedCoords {
public:
TransformedCoords(const char* name, GrSLType type)
TransformedCoords(const SkString& name, GrSLType type)
: fName(name), fType(type) {
}
@ -97,13 +97,18 @@ public:
typedef SkTArray<TextureSampler> TextureSamplerArray;
protected:
friend class GrGLProgramEffectsBuilder;
GrGLProgramEffects(int reserveCount)
: fGLEffects(reserveCount)
, fSamplers(reserveCount) {
}
/**
* Helper for emitEffect() in a subclasses. Emits uniforms for an effect's texture accesses and
* appends the necessary data to the TextureSamplerArray* object so effects can add texture
* lookups to their code. This method is only meant to be called during the construction phase.
*/
void emitSamplers(GrGLShaderBuilder*, const GrEffectRef&, TextureSamplerArray*);
/**
* Helper for setData(). Binds all the textures for an effect.
*/
@ -119,6 +124,23 @@ protected:
SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
};
/**
* This is an abstract base class for constructing different types of GrGLProgramEffects objects.
*/
class GrGLProgramEffectsBuilder {
public:
/**
* Emits the effect's shader code, and stores the necessary uniforms internally.
*/
virtual void emitEffect(const GrEffectStage&,
GrGLProgramEffects::EffectKey,
const char* outColor,
const char* inColor,
int stageIndex) = 0;
};
////////////////////////////////////////////////////////////////////////////////
/**
* This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader.
*/
@ -137,6 +159,34 @@ private:
, fHasExplicitLocalCoords(explicitLocalCoords) {
}
/**
* Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called
* during the construction phase.
*/
void emitEffect(GrGLFullShaderBuilder*,
const GrEffectStage&,
GrGLProgramEffects::EffectKey,
const char* outColor,
const char* inColor,
int stageIndex);
/**
* Helper for emitEffect(). Emits any attributes an effect may have.
*/
void emitAttributes(GrGLFullShaderBuilder*, const GrEffectStage&);
/**
* Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
* Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
* vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
* of the varyings in the VS and FS as well their types are appended to the
* TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
*/
void emitTransforms(GrGLFullShaderBuilder*,
const GrEffectRef&,
EffectKey,
TransformedCoordsArray*);
/**
* Helper for setData(). Sets all the transform matrices for an effect.
*/
@ -155,35 +205,8 @@ private:
typedef GrGLProgramEffects INHERITED;
};
////////////////////////////////////////////////////////////////////////////////
/**
* This is an abstract base class for constructing different types of GrGLProgramEffects objects.
*/
class GrGLProgramEffectsBuilder {
public:
/**
* Emits the effect's shader code, and stores the necessary uniforms internally.
*/
virtual void emitEffect(const GrEffectStage&,
GrGLProgramEffects::EffectKey,
const char* outColor,
const char* inColor,
int stageIndex) = 0;
protected:
/**
* Helper for emitEffect(). Emits uniforms for an effect's texture accesses and appends the
* necessary data to the TextureSamplerArray* object so effects can add texture lookups.
*/
static void emitSamplers(GrGLShaderBuilder*,
GrGLProgramEffects*,
const GrEffectRef&,
GrGLProgramEffects::TextureSamplerArray*);
};
/**
* This class is used to construct a GrGLVertexProgramEffects object.
* This class is used to construct a GrGLVertexProgramEffects* object.
*/
class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
public:
@ -202,26 +225,97 @@ public:
GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
private:
/**
* Helper for emitEffect(). Emits any attributes an effect might have.
*/
void emitAttributes(const GrEffectStage&);
/**
* Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
* Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
* vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
* of the varyings in the VS and FS as well their types are appended to the
* TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
*/
void emitTransforms(const GrEffectRef&,
GrGLProgramEffects::EffectKey,
GrGLProgramEffects::TransformedCoordsArray*);
GrGLFullShaderBuilder* fBuilder;
SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
typedef GrGLProgramEffectsBuilder INHERITED;
};
////////////////////////////////////////////////////////////////////////////////
/**
* This is a GrGLProgramEffects implementation that does coord transforms with the the built-in GL
* TexGen functionality.
*/
class GrGLTexGenProgramEffects : public GrGLProgramEffects {
public:
virtual void setData(GrGpuGL*,
const GrGLUniformManager&,
const GrEffectStage* effectStages[]) SK_OVERRIDE;
private:
friend class GrGLTexGenProgramEffectsBuilder;
GrGLTexGenProgramEffects(int reserveCount)
: INHERITED(reserveCount)
, fTransforms(reserveCount) {
}
/**
* Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called
* during the construction phase.
*/
void emitEffect(GrGLFragmentOnlyShaderBuilder*,
const GrEffectStage&,
GrGLProgramEffects::EffectKey,
const char* outColor,
const char* inColor,
int stageIndex);
/**
* Helper for emitEffect(). Allocates texture units from the builder for each transform in an
* effect. The transforms all use adjacent texture units. They either use two or three of the
* coordinates at a given texture unit, depending on if they need perspective interpolation.
* The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
* types are appended to the TransformedCoordsArray* object, which is in turn passed to the
* effect's emitCode() function.
*/
void setupTexGen(GrGLFragmentOnlyShaderBuilder*,
const GrEffectRef&,
EffectKey,
TransformedCoordsArray*);
/**
* Helper for setData(). Sets the TexGen state for each transform in an effect.
*/
void setTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx);
struct Transforms {
Transforms(EffectKey transformKey, int texCoordIndex)
: fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {}
EffectKey fTransformKey;
int fTexCoordIndex;
};
SkTArray<Transforms> fTransforms;
typedef GrGLProgramEffects INHERITED;
};
/**
* This class is used to construct a GrGLTexGenProgramEffects* object.
*/
class GrGLTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
public:
GrGLTexGenProgramEffectsBuilder(GrGLFragmentOnlyShaderBuilder*, int reserveCount);
virtual void emitEffect(const GrEffectStage&,
GrGLProgramEffects::EffectKey,
const char* outColor,
const char* inColor,
int stageIndex) SK_OVERRIDE;
/**
* Finalizes the building process and returns the effect array. After this call, the builder
* becomes invalid.
*/
GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
private:
GrGLFragmentOnlyShaderBuilder* fBuilder;
SkAutoTDelete<GrGLTexGenProgramEffects> fProgramEffects;
typedef GrGLProgramEffectsBuilder INHERITED;
};
#endif

Просмотреть файл

@ -441,7 +441,6 @@ const char* GrGLShaderBuilder::fragmentPosition() {
}
}
void GrGLShaderBuilder::fsEmitFunction(GrSLType returnType,
const char* name,
int argCnt,
@ -920,3 +919,35 @@ void GrGLFullShaderBuilder::bindProgramLocations(GrGLuint programId) const {
GL_CALL(BindAttribLocation(programId, attrib->fIndex, attrib->fName.c_str()));
}
}
////////////////////////////////////////////////////////////////////////////////
GrGLFragmentOnlyShaderBuilder::GrGLFragmentOnlyShaderBuilder(GrGpuGL* gpu,
GrGLUniformManager& uniformManager,
const GrGLProgramDesc& desc)
: INHERITED(gpu, uniformManager, desc)
, fNumTexCoordSets(0) {
SkASSERT(!desc.getHeader().fHasVertexCode);
SkASSERT(gpu->glCaps().fixedFunctionSupport());
SkASSERT(gpu->glCaps().pathStencilingSupport());
SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
}
GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects(
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
SkString* inOutFSColor,
GrSLConstantVec* fsInOutColorKnownValue) {
GrGLTexGenProgramEffectsBuilder texGenEffectsBuilder(this, effectCnt);
this->INHERITED::createAndEmitEffects(&texGenEffectsBuilder,
effectStages,
effectKeys,
effectCnt,
inOutFSColor,
fsInOutColorKnownValue);
return texGenEffectsBuilder.finish();
}

Просмотреть файл

@ -450,4 +450,26 @@ private:
typedef GrGLShaderBuilder INHERITED;
};
////////////////////////////////////////////////////////////////////////////////
class GrGLFragmentOnlyShaderBuilder : public GrGLShaderBuilder {
public:
GrGLFragmentOnlyShaderBuilder(GrGpuGL*, GrGLUniformManager&, const GrGLProgramDesc&);
int getNumTexCoordSets() const { return fNumTexCoordSets; }
int addTexCoordSets(int count) { return (fNumTexCoordSets += count) - count; }
virtual GrGLProgramEffects* createAndEmitEffects(
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
SkString* inOutFSColor,
GrSLConstantVec* fsInOutColorKnownValue) SK_OVERRIDE;
private:
int fNumTexCoordSets;
typedef GrGLShaderBuilder INHERITED;
};
#endif

Просмотреть файл

@ -124,6 +124,7 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context)
fCaps.reset(SkRef(ctx.info().caps()));
fHWBoundTextures.reset(ctx.info().caps()->maxFragmentTextureUnits());
fHWTexGenSettings.reset(ctx.info().caps()->maxFixedFunctionTextureCoords());
fillInConfigRenderableTable();
@ -377,7 +378,13 @@ void GrGpuGL::onResetContext(uint32_t resetBits) {
GL_CALL(Disable(GR_GL_TEXTURE_GEN_T));
GL_CALL(Disable(GR_GL_TEXTURE_GEN_Q));
GL_CALL(Disable(GR_GL_TEXTURE_GEN_R));
if (this->caps()->pathStencilingSupport()) {
GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
}
fHWTexGenSettings[i].fMode = GR_GL_NONE;
fHWTexGenSettings[i].fNumComponents = 0;
}
fHWActiveTexGenSets = 0;
}
// we assume these values
@ -2114,6 +2121,124 @@ void GrGpuGL::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTextur
texture->setCachedTexParams(newTexParams, this->getResetTimestamp());
}
void GrGpuGL::setProjectionMatrix(const SkMatrix& matrix,
const SkISize& renderTargetSize,
GrSurfaceOrigin renderTargetOrigin) {
SkASSERT(this->glCaps().fixedFunctionSupport());
if (renderTargetOrigin == fHWProjectionMatrixState.fRenderTargetOrigin &&
renderTargetSize == fHWProjectionMatrixState.fRenderTargetSize &&
matrix.cheapEqualTo(fHWProjectionMatrixState.fViewMatrix)) {
return;
}
fHWProjectionMatrixState.fViewMatrix = matrix;
fHWProjectionMatrixState.fRenderTargetSize = renderTargetSize;
fHWProjectionMatrixState.fRenderTargetOrigin = renderTargetOrigin;
GrGLfloat glMatrix[4 * 4];
fHWProjectionMatrixState.getGLMatrix<4>(glMatrix);
GL_CALL(MatrixMode(GR_GL_PROJECTION));
GL_CALL(LoadMatrixf(glMatrix));
}
void GrGpuGL::enableTexGen(int unitIdx,
TexGenComponents components,
const GrGLfloat* coefficients) {
SkASSERT(this->glCaps().fixedFunctionSupport());
SkASSERT(this->caps()->pathStencilingSupport());
SkASSERT(components >= kS_TexGenComponents && components <= kSTR_TexGenComponents);
if (GR_GL_OBJECT_LINEAR == fHWTexGenSettings[unitIdx].fMode &&
components == fHWTexGenSettings[unitIdx].fNumComponents &&
!memcmp(coefficients, fHWTexGenSettings[unitIdx].fCoefficients,
3 * components * sizeof(GrGLfloat))) {
return;
}
this->setTextureUnit(unitIdx);
if (GR_GL_OBJECT_LINEAR != fHWTexGenSettings[unitIdx].fMode) {
for (int i = 0; i < 4; i++) {
GL_CALL(TexGeni(GR_GL_S + i, GR_GL_TEXTURE_GEN_MODE, GR_GL_OBJECT_LINEAR));
}
fHWTexGenSettings[unitIdx].fMode = GR_GL_OBJECT_LINEAR;
}
for (int i = fHWTexGenSettings[unitIdx].fNumComponents; i < components; i++) {
GL_CALL(Enable(GR_GL_TEXTURE_GEN_S + i));
}
for (int i = components; i < fHWTexGenSettings[unitIdx].fNumComponents; i++) {
GL_CALL(Disable(GR_GL_TEXTURE_GEN_S + i));
}
fHWTexGenSettings[unitIdx].fNumComponents = components;
for (int i = 0; i < components; i++) {
GrGLfloat plane[] = {coefficients[0 + 3 * i],
coefficients[1 + 3 * i],
0,
coefficients[2 + 3 * i]};
GL_CALL(TexGenfv(GR_GL_S + i, GR_GL_OBJECT_PLANE, plane));
}
GL_CALL(PathTexGen(GR_GL_TEXTURE0 + unitIdx,
GR_GL_OBJECT_LINEAR,
components,
coefficients));
memcpy(fHWTexGenSettings[unitIdx].fCoefficients, coefficients,
3 * components * sizeof(GrGLfloat));
fHWActiveTexGenSets = SkTMax(fHWActiveTexGenSets, unitIdx);
}
void GrGpuGL::enableTexGen(int unitIdx, TexGenComponents components, const SkMatrix& matrix) {
GrGLfloat coefficients[3 * 3];
SkASSERT(this->glCaps().fixedFunctionSupport());
SkASSERT(components >= kS_TexGenComponents && components <= kSTR_TexGenComponents);
coefficients[0] = SkScalarToFloat(matrix[SkMatrix::kMScaleX]);
coefficients[1] = SkScalarToFloat(matrix[SkMatrix::kMSkewX]);
coefficients[2] = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
if (components >= kST_TexGenComponents) {
coefficients[3] = SkScalarToFloat(matrix[SkMatrix::kMSkewY]);
coefficients[4] = SkScalarToFloat(matrix[SkMatrix::kMScaleY]);
coefficients[5] = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
}
if (components >= kSTR_TexGenComponents) {
coefficients[6] = SkScalarToFloat(matrix[SkMatrix::kMPersp0]);
coefficients[7] = SkScalarToFloat(matrix[SkMatrix::kMPersp1]);
coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]);
}
enableTexGen(unitIdx, components, coefficients);
}
void GrGpuGL::disableUnusedTexGen(int numUsedTexCoordSets) {
SkASSERT(this->glCaps().fixedFunctionSupport());
for (int i = numUsedTexCoordSets; i < fHWActiveTexGenSets; i++) {
if (0 == fHWTexGenSettings[i].fNumComponents) {
continue;
}
this->setTextureUnit(i);
for (int j = 0; j < fHWTexGenSettings[i].fNumComponents; j++) {
GL_CALL(Disable(GR_GL_TEXTURE_GEN_S + j));
}
GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
fHWTexGenSettings[i].fNumComponents = 0;
}
fHWActiveTexGenSets = SkTMin(fHWActiveTexGenSets, numUsedTexCoordSets);
}
void GrGpuGL::flushMiscFixedFunctionState() {
const GrDrawState& drawState = this->getDrawState();

Просмотреть файл

@ -37,8 +37,19 @@ public:
GrGLVersion glVersion() const { return fGLContext.info().version(); }
GrGLSLGeneration glslGeneration() const { return fGLContext.info().glslGeneration(); }
// Used by GrGLProgram to bind necessary textures for GrGLEffects.
// Used by GrGLProgram and GrGLTexGenProgramEffects to configure OpenGL state.
void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture);
void setProjectionMatrix(const SkMatrix& matrix,
const SkISize& renderTargetSize,
GrSurfaceOrigin renderTargetOrigin);
enum TexGenComponents {
kS_TexGenComponents = 1,
kST_TexGenComponents = 2,
kSTR_TexGenComponents = 3
};
void enableTexGen(int unitIdx, TexGenComponents, const GrGLfloat* coefficients);
void enableTexGen(int unitIdx, TexGenComponents, const SkMatrix& matrix);
void disableUnusedTexGen(int numUsedTexCoordSets);
bool programUnitTest(int maxStages);
@ -213,9 +224,6 @@ private:
#endif
};
// sets the matrix for path stenciling (uses the GL fixed pipe matrices)
void flushPathStencilMatrix();
// flushes dithering, color-mask, and face culling stat
void flushMiscFixedFunctionState();
@ -432,6 +440,14 @@ private:
TriState fHWDitherEnabled;
GrRenderTarget* fHWBoundRenderTarget;
SkTArray<GrTexture*, true> fHWBoundTextures;
struct TexGenData {
GrGLenum fMode;
GrGLint fNumComponents;
GrGLfloat fCoefficients[3 * 3];
};
int fHWActiveTexGenSets;
SkTArray<TexGenData, true> fHWTexGenSettings;
///@}
// we record what stencil format worked last time to hopefully exit early

Просмотреть файл

@ -210,28 +210,6 @@ void GrGpuGL::abandonResources(){
#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
void GrGpuGL::flushPathStencilMatrix() {
const SkMatrix& viewMatrix = this->getDrawState().getViewMatrix();
const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
SkISize size;
size.set(rt->width(), rt->height());
const SkMatrix& vm = this->getDrawState().getViewMatrix();
if (fHWProjectionMatrixState.fRenderTargetOrigin != rt->origin() ||
!fHWProjectionMatrixState.fViewMatrix.cheapEqualTo(viewMatrix) ||
fHWProjectionMatrixState.fRenderTargetSize!= size) {
fHWProjectionMatrixState.fViewMatrix = vm;
fHWProjectionMatrixState.fRenderTargetSize = size;
fHWProjectionMatrixState.fRenderTargetOrigin = rt->origin();
GrGLfloat projectionMatrix[4 * 4];
fHWProjectionMatrixState.getGLMatrix<4>(projectionMatrix);
GL_CALL(MatrixMode(GR_GL_PROJECTION));
GL_CALL(LoadMatrixf(projectionMatrix));
}
}
bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) {
const GrDrawState& drawState = this->getDrawState();
@ -239,7 +217,10 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
SkASSERT(NULL != drawState.getRenderTarget());
if (kStencilPath_DrawType == type) {
this->flushPathStencilMatrix();
const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
SkISize size;
size.set(rt->width(), rt->height());
this->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
} else {
this->flushMiscFixedFunctionState();
@ -360,24 +341,40 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
GrGLAttribArrayState* attribState =
fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf);
uint32_t usedAttribArraysMask = 0;
const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs();
int vertexAttribCount = this->getDrawState().getVertexAttribCount();
for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount;
++vertexAttribIndex, ++vertexAttrib) {
if (!fCurrentProgram->hasVertexShader()) {
int posIdx = this->getDrawState().positionAttributeIndex();
const GrVertexAttrib* vertexArray = this->getDrawState().getVertexAttribs() + posIdx;
GrVertexAttribType vertexArrayType = vertexArray->fType;
SkASSERT(!GrGLAttribTypeToLayout(vertexArrayType).fNormalized);
SkASSERT(GrGLAttribTypeToLayout(vertexArrayType).fCount == 2);
attribState->setFixedFunctionVertexArray(this,
vbuf,
2,
GrGLAttribTypeToLayout(vertexArrayType).fType,
stride,
reinterpret_cast<GrGLvoid*>(
vertexOffsetInBytes + vertexArray->fOffset));
attribState->disableUnusedArrays(this, 0, true);
} else {
uint32_t usedAttribArraysMask = 0;
const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs();
int vertexAttribCount = this->getDrawState().getVertexAttribCount();
for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount;
++vertexAttribIndex, ++vertexAttrib) {
usedAttribArraysMask |= (1 << vertexAttribIndex);
GrVertexAttribType attribType = vertexAttrib->fType;
attribState->set(this,
vertexAttribIndex,
vbuf,
GrGLAttribTypeToLayout(attribType).fCount,
GrGLAttribTypeToLayout(attribType).fType,
GrGLAttribTypeToLayout(attribType).fNormalized,
stride,
reinterpret_cast<GrGLvoid*>(
vertexOffsetInBytes + vertexAttrib->fOffset));
usedAttribArraysMask |= (1 << vertexAttribIndex);
GrVertexAttribType attribType = vertexAttrib->fType;
attribState->set(this,
vertexAttribIndex,
vbuf,
GrGLAttribTypeToLayout(attribType).fCount,
GrGLAttribTypeToLayout(attribType).fType,
GrGLAttribTypeToLayout(attribType).fNormalized,
stride,
reinterpret_cast<GrGLvoid*>(
vertexOffsetInBytes + vertexAttrib->fOffset));
}
attribState->disableUnusedArrays(this, usedAttribArraysMask, false);
}
attribState->disableUnusedArrays(this, usedAttribArraysMask, false);
}

Просмотреть файл

@ -78,6 +78,7 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
bool dstRead = false;
bool fragPos = false;
bool vertexCode = false;
int numStages = numColorStages + numCoverageStages;
for (int s = 0; s < numStages; ++s) {
const GrBackendEffectFactory& factory = (*stages[s]->getEffect())->getFactory();
@ -89,6 +90,9 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
if ((*stages[s]->getEffect())->willReadFragmentPosition()) {
fragPos = true;
}
if ((*stages[s]->getEffect())->hasVertexCode()) {
vertexCode = true;
}
}
if (dstRead) {
@ -103,6 +107,11 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
header->fFragPosKey = 0;
}
header->fHasVertexCode = vertexCode ||
useLocalCoords ||
kAttribute_ColorInput == header->fColorInput ||
kAttribute_ColorInput == header->fCoverageInput;
CoverageOutput coverageOutput;
bool illegalCoverageOutput;
do {