A simple change to move a bunch of stuff out of Gr*Geometry.h

BUG=skia:

Review URL: https://codereview.chromium.org/920863002
This commit is contained in:
joshualitt 2015-02-12 14:20:52 -08:00 committed by Commit bot
parent b0fb935bd5
commit 8072caa803
18 changed files with 1087 additions and 965 deletions

View File

@ -111,6 +111,8 @@
'<(skia_src_path)/gpu/GrPaint.cpp',
'<(skia_src_path)/gpu/GrPath.cpp',
'<(skia_src_path)/gpu/GrPath.h',
'<(skia_src_path)/gpu/GrPathProcessor.cpp',
'<(skia_src_path)/gpu/GrPathProcessor.h',
'<(skia_src_path)/gpu/GrPathRange.cpp',
'<(skia_src_path)/gpu/GrPathRange.h',
'<(skia_src_path)/gpu/GrPathRendererChain.cpp',
@ -126,6 +128,8 @@
'<(skia_src_path)/gpu/GrPipeline.h',
'<(skia_src_path)/gpu/GrPipelineBuilder.cpp',
'<(skia_src_path)/gpu/GrPipelineBuilder.h',
'<(skia_src_path)/gpu/GrPrimitiveProcessor.cpp',
'<(skia_src_path)/gpu/GrPrimitiveProcessor.h',
'<(skia_src_path)/gpu/GrProgramDesc.h',
'<(skia_src_path)/gpu/GrProgramElement.cpp',
'<(skia_src_path)/gpu/GrProcessor.cpp',
@ -231,6 +235,7 @@
'<(skia_src_path)/gpu/gl/GrGLCreateNativeInterface_none.cpp',
'<(skia_src_path)/gpu/gl/GrGLDefaultInterface_none.cpp',
'<(skia_src_path)/gpu/gl/GrGLDefines.h',
'<(skia_src_path)/gpu/gl/GrGLGeometryProcessor.cpp',
'<(skia_src_path)/gpu/gl/GrGLGeometryProcessor.h',
'<(skia_src_path)/gpu/gl/GrGLGpu.cpp',
'<(skia_src_path)/gpu/gl/GrGLGpu.h',
@ -246,10 +251,14 @@
'<(skia_src_path)/gpu/gl/GrGLNoOpInterface.h',
'<(skia_src_path)/gpu/gl/GrGLPath.cpp',
'<(skia_src_path)/gpu/gl/GrGLPath.h',
'<(skia_src_path)/gpu/gl/GrGLPathProcessor.cpp',
'<(skia_src_path)/gpu/gl/GrGLPathProcessor.h',
'<(skia_src_path)/gpu/gl/GrGLPathRange.cpp',
'<(skia_src_path)/gpu/gl/GrGLPathRange.h',
'<(skia_src_path)/gpu/gl/GrGLPathRendering.cpp',
'<(skia_src_path)/gpu/gl/GrGLPathRendering.h',
'<(skia_src_path)/gpu/gl/GrGLPrimitiveProcessor.cpp',
'<(skia_src_path)/gpu/gl/GrGLPrimitiveProcessor.h',
'<(skia_src_path)/gpu/gl/GrGLProcessor.h',
'<(skia_src_path)/gpu/gl/GrGLProgram.cpp',
'<(skia_src_path)/gpu/gl/GrGLProgram.h',

View File

@ -11,6 +11,8 @@
#include "GrClipData.h"
#include "GrClipMaskManager.h"
#include "GrContext.h"
#include "GrPathProcessor.h"
#include "GrPrimitiveProcessor.h"
#include "GrIndexBuffer.h"
#include "GrPathRendering.h"
#include "GrPipelineBuilder.h"

View File

@ -7,70 +7,7 @@
#include "GrGeometryProcessor.h"
#include "GrCoordTransform.h"
#include "GrInvariantOutput.h"
#include "gl/GrGLGeometryProcessor.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
/**
* The key for an individual coord transform is made up of a matrix type, a precision, and a bit
* that indicates the source of the input coords.
*/
enum {
kMatrixTypeKeyBits = 1,
kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
kPrecisionBits = 2,
kPrecisionShift = kMatrixTypeKeyBits,
kPositionCoords_Flag = (1 << (kPrecisionShift + kPrecisionBits)),
kDeviceCoords_Flag = kPositionCoords_Flag + kPositionCoords_Flag,
kTransformKeyBits = kMatrixTypeKeyBits + kPrecisionBits + 2,
};
GR_STATIC_ASSERT(kHigh_GrSLPrecision < (1 << kPrecisionBits));
/**
* We specialize the vertex code for each of these matrix types.
*/
enum MatrixType {
kNoPersp_MatrixType = 0,
kGeneral_MatrixType = 1,
};
uint32_t
GrPrimitiveProcessor::getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords) const {
uint32_t totalKey = 0;
for (int t = 0; t < coords.count(); ++t) {
uint32_t key = 0;
const GrCoordTransform* coordTransform = coords[t];
if (coordTransform->getMatrix().hasPerspective()) {
key |= kGeneral_MatrixType;
} else {
key |= kNoPersp_MatrixType;
}
if (kLocal_GrCoordSet == coordTransform->sourceCoords() &&
!this->hasExplicitLocalCoords()) {
key |= kPositionCoords_Flag;
} else if (kDevice_GrCoordSet == coordTransform->sourceCoords()) {
key |= kDeviceCoords_Flag;
}
GR_STATIC_ASSERT(kGrSLPrecisionCount <= (1 << kPrecisionBits));
key |= (coordTransform->precision() << kPrecisionShift);
key <<= kTransformKeyBits * t;
SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
totalKey |= key;
}
return totalKey;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void GrGeometryProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const {
if (fHasVertexColor) {
@ -89,483 +26,4 @@ void GrGeometryProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out)
this->onGetInvariantOutputCoverage(out);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "gl/builders/GrGLProgramBuilder.h"
SkMatrix GrGLPrimitiveProcessor::GetTransformMatrix(const SkMatrix& localMatrix,
const GrCoordTransform& coordTransform) {
SkMatrix combined;
// We only apply the localmatrix to localcoords
if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
combined.setConcat(coordTransform.getMatrix(), localMatrix);
} 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;
}
void
GrGLPrimitiveProcessor::setupColorPassThrough(GrGLGPBuilder* pb,
GrGPInput inputType,
const char* outputName,
const GrGeometryProcessor::Attribute* colorAttr,
UniformHandle* colorUniform) {
GrGLGPFragmentBuilder* fs = pb->getFragmentShaderBuilder();
if (kUniform_GrGPInput == inputType) {
SkASSERT(colorUniform);
const char* stagedLocalVarName;
*colorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType,
kDefault_GrSLPrecision,
"Color",
&stagedLocalVarName);
fs->codeAppendf("%s = %s;", outputName, stagedLocalVarName);
} else if (kAttribute_GrGPInput == inputType) {
SkASSERT(colorAttr);
pb->addPassThroughAttribute(colorAttr, outputName);
} else if (kAllOnes_GrGPInput == inputType) {
fs->codeAppendf("%s = vec4(1);", outputName);
}
}
void GrGLPrimitiveProcessor::addUniformViewMatrix(GrGLGPBuilder* pb) {
fViewMatrixUniform = pb->addUniform(GrGLProgramBuilder::kVertex_Visibility,
kMat33f_GrSLType, kDefault_GrSLPrecision,
"uViewM",
&fViewMatrixName);
}
void GrGLPrimitiveProcessor::setUniformViewMatrix(const GrGLProgramDataManager& pdman,
const SkMatrix& viewMatrix) {
if (!fViewMatrix.cheapEqualTo(viewMatrix)) {
SkASSERT(fViewMatrixUniform.isValid());
fViewMatrix = viewMatrix;
GrGLfloat viewMatrix[3 * 3];
GrGLGetMatrix<3>(viewMatrix, fViewMatrix);
pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void GrGLGeometryProcessor::emitCode(EmitArgs& args) {
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
GrGPArgs gpArgs;
this->onEmitCode(args, &gpArgs);
vsBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar);
}
void GrGLGeometryProcessor::emitTransforms(GrGLGPBuilder* pb,
const GrShaderVar& posVar,
const char* localCoords,
const SkMatrix& localMatrix,
const TransformsIn& tin,
TransformsOut* tout) {
GrGLVertexBuilder* vb = pb->getVertexShaderBuilder();
tout->push_back_n(tin.count());
fInstalledTransforms.push_back_n(tin.count());
for (int i = 0; i < tin.count(); i++) {
const ProcCoords& coordTransforms = tin[i];
fInstalledTransforms[i].push_back_n(coordTransforms.count());
for (int t = 0; t < coordTransforms.count(); t++) {
SkString strUniName("StageMatrix");
strUniName.appendf("_%i_%i", i, t);
GrSLType varyingType;
GrCoordSet coordType = coordTransforms[t]->sourceCoords();
uint32_t type = coordTransforms[t]->getMatrix().getType();
if (kLocal_GrCoordSet == coordType) {
type |= localMatrix.getType();
}
varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType :
kVec2f_GrSLType;
GrSLPrecision precision = coordTransforms[t]->precision();
const char* uniName;
fInstalledTransforms[i][t].fHandle =
pb->addUniform(GrGLProgramBuilder::kVertex_Visibility,
kMat33f_GrSLType, precision,
strUniName.c_str(),
&uniName).toShaderBuilderIndex();
SkString strVaryingName("MatrixCoord");
strVaryingName.appendf("_%i_%i", i, t);
GrGLVertToFrag v(varyingType);
pb->addVarying(strVaryingName.c_str(), &v, precision);
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords,
(SkString(v.fsIn()), varyingType));
// varying = matrix * coords (logically)
if (kDevice_GrCoordSet == coordType) {
if (kVec2f_GrSLType == varyingType) {
if (kVec2f_GrSLType == posVar.getType()) {
vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
v.vsOut(), uniName, posVar.c_str());
} else {
// The brackets here are just to scope the temp variable
vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVar.c_str());
vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z); }", v.vsOut());
}
} else {
if (kVec2f_GrSLType == posVar.getType()) {
vb->codeAppendf("%s = %s * vec3(%s, 1);",
v.vsOut(), uniName, posVar.c_str());
} else {
vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, posVar.c_str());
}
}
} else {
if (kVec2f_GrSLType == varyingType) {
vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
} else {
vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName, localCoords);
}
}
}
}
}
void
GrGLGeometryProcessor::setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) {
SkSTArray<2, Transform, true>& procTransforms = fInstalledTransforms[index];
int numTransforms = transforms.count();
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(procTransforms[t].fHandle.isValid());
const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *transforms[t]);
if (!procTransforms[t].fCurrentValue.cheapEqualTo(transform)) {
pdman.setSkMatrix(procTransforms[t].fHandle.convertToUniformHandle(), transform);
procTransforms[t].fCurrentValue = transform;
}
}
}
void GrGLGeometryProcessor::SetupPosition(GrGLVertexBuilder* vsBuilder,
GrGPArgs* gpArgs,
const char* posName,
const SkMatrix& mat,
const char* matName) {
if (mat.isIdentity()) {
gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
vsBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
} else if (!mat.hasPerspective()) {
gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
vsBuilder->codeAppendf("vec2 %s = vec2(%s * vec3(%s, 1));",
gpArgs->fPositionVar.c_str(), matName, posName);
} else {
gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3");
vsBuilder->codeAppendf("vec3 %s = %s * vec3(%s, 1);",
gpArgs->fPositionVar.c_str(), matName, posName);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "gl/GrGLGpu.h"
#include "gl/GrGLPathRendering.h"
struct PathBatchTracker {
GrGPInput fInputColorType;
GrGPInput fInputCoverageType;
GrColor fColor;
bool fUsesLocalCoords;
};
GrGLPathProcessor::GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&)
: fColor(GrColor_ILLEGAL) {}
void GrGLPathProcessor::emitCode(EmitArgs& args) {
GrGLGPBuilder* pb = args.fPB;
GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder();
const PathBatchTracker& local = args.fBT.cast<PathBatchTracker>();
// emit transforms
this->emitTransforms(args.fPB, args.fTransformsIn, args.fTransformsOut);
// Setup uniform color
if (kUniform_GrGPInput == local.fInputColorType) {
const char* stagedLocalVarName;
fColorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType,
kDefault_GrSLPrecision,
"Color",
&stagedLocalVarName);
fs->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
}
// setup constant solid coverage
if (kAllOnes_GrGPInput == local.fInputCoverageType) {
fs->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
}
}
void GrGLPathProcessor::GenKey(const GrPathProcessor&,
const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
const PathBatchTracker& local = bt.cast<PathBatchTracker>();
b->add32(local.fInputColorType | local.fInputCoverageType << 16);
}
void GrGLPathProcessor::setData(const GrGLProgramDataManager& pdman,
const GrPrimitiveProcessor& primProc,
const GrBatchTracker& bt) {
const PathBatchTracker& local = bt.cast<PathBatchTracker>();
if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
GrGLfloat c[4];
GrColorToRGBAFloat(local.fColor, c);
pdman.set4fv(fColorUniform, 1, c);
fColor = local.fColor;
}
}
class GrGLLegacyPathProcessor : public GrGLPathProcessor {
public:
GrGLLegacyPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracker& bt,
int maxTexCoords)
: INHERITED(pathProc, bt)
, fTexCoordSetCnt(0) {
SkDEBUGCODE(fMaxTexCoords = maxTexCoords;)
}
int addTexCoordSets(int count) {
int firstFreeCoordSet = fTexCoordSetCnt;
fTexCoordSetCnt += count;
SkASSERT(fMaxTexCoords >= fTexCoordSetCnt);
return firstFreeCoordSet;
}
void emitTransforms(GrGLGPBuilder*, const TransformsIn& tin, TransformsOut* tout) SK_OVERRIDE {
tout->push_back_n(tin.count());
fInstalledTransforms.push_back_n(tin.count());
for (int i = 0; i < tin.count(); i++) {
const ProcCoords& coordTransforms = tin[i];
int texCoordIndex = this->addTexCoordSets(coordTransforms.count());
// Use the first uniform location as the texcoord index.
fInstalledTransforms[i].push_back_n(1);
fInstalledTransforms[i][0].fHandle = ShaderVarHandle(texCoordIndex);
SkString name;
for (int t = 0; t < coordTransforms.count(); ++t) {
GrSLType type = coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
kVec2f_GrSLType;
name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords, (name, type));
}
}
}
void setTransformData(const GrPrimitiveProcessor& primProc,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms,
GrGLPathRendering* glpr,
GrGLuint) SK_OVERRIDE {
// We've hidden the texcoord index in the first entry of the transforms array for each
// effect
int texCoordIndex = fInstalledTransforms[index][0].fHandle.handle();
for (int t = 0; t < transforms.count(); ++t) {
const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *transforms[t]);
GrGLPathRendering::PathTexGenComponents components =
GrGLPathRendering::kST_PathTexGenComponents;
if (transform.hasPerspective()) {
components = GrGLPathRendering::kSTR_PathTexGenComponents;
}
glpr->enablePathTexGen(texCoordIndex++, components, transform);
}
}
void didSetData(GrGLPathRendering* glpr) SK_OVERRIDE {
glpr->flushPathTexGenSettings(fTexCoordSetCnt);
}
private:
SkDEBUGCODE(int fMaxTexCoords;)
int fTexCoordSetCnt;
typedef GrGLPathProcessor INHERITED;
};
class GrGLNormalPathProcessor : public GrGLPathProcessor {
public:
GrGLNormalPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracker& bt)
: INHERITED(pathProc, bt) {}
void emitTransforms(GrGLGPBuilder* pb, const TransformsIn& tin,
TransformsOut* tout) SK_OVERRIDE {
tout->push_back_n(tin.count());
fInstalledTransforms.push_back_n(tin.count());
for (int i = 0; i < tin.count(); i++) {
const ProcCoords& coordTransforms = tin[i];
fInstalledTransforms[i].push_back_n(coordTransforms.count());
for (int t = 0; t < coordTransforms.count(); t++) {
GrSLType varyingType =
coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
kVec2f_GrSLType;
SkString strVaryingName("MatrixCoord");
strVaryingName.appendf("_%i_%i", i, t);
GrGLVertToFrag v(varyingType);
pb->addVarying(strVaryingName.c_str(), &v);
SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back();
varyingInfo.fVariable = pb->getFragmentShaderBuilder()->fInputs.back();
varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1;
varyingInfo.fType = varyingType;
fInstalledTransforms[i][t].fHandle = ShaderVarHandle(varyingInfo.fLocation);
fInstalledTransforms[i][t].fType = varyingType;
SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords,
(SkString(v.fsIn()), varyingType));
}
}
}
void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {
int count = fSeparableVaryingInfos.count();
for (int i = 0; i < count; ++i) {
GrGLint location;
GR_GL_CALL_RET(gpu->glInterface(),
location,
GetProgramResourceLocation(programId,
GR_GL_FRAGMENT_INPUT,
fSeparableVaryingInfos[i].fVariable.c_str()));
fSeparableVaryingInfos[i].fLocation = location;
}
}
void setTransformData(const GrPrimitiveProcessor& primProc,
int index,
const SkTArray<const GrCoordTransform*, true>& coordTransforms,
GrGLPathRendering* glpr,
GrGLuint programID) SK_OVERRIDE {
SkSTArray<2, Transform, true>& transforms = fInstalledTransforms[index];
int numTransforms = transforms.count();
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(transforms[t].fHandle.isValid());
const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(),
*coordTransforms[t]);
if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
continue;
}
transforms[t].fCurrentValue = transform;
const SeparableVaryingInfo& fragmentInput =
fSeparableVaryingInfos[transforms[t].fHandle.handle()];
SkASSERT(transforms[t].fType == kVec2f_GrSLType ||
transforms[t].fType == kVec3f_GrSLType);
unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
glpr->setProgramPathFragmentInputTransform(programID,
fragmentInput.fLocation,
GR_GL_OBJECT_LINEAR,
components,
transform);
}
}
private:
struct SeparableVaryingInfo {
GrSLType fType;
GrGLShaderVar fVariable;
GrGLint fLocation;
};
typedef SkSTArray<8, SeparableVaryingInfo, true> SeparableVaryingInfoArray;
SeparableVaryingInfoArray fSeparableVaryingInfos;
typedef GrGLPathProcessor INHERITED;
};
GrPathProcessor::GrPathProcessor(GrColor color,
const SkMatrix& viewMatrix,
const SkMatrix& localMatrix)
: INHERITED(viewMatrix, localMatrix, true)
, fColor(color) {
this->initClassID<GrPathProcessor>();
}
void GrPathProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const {
out->setKnownFourComponents(fColor);
}
void GrPathProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out) const {
out->setKnownSingleComponent(0xff);
}
void GrPathProcessor::initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const {
PathBatchTracker* local = bt->cast<PathBatchTracker>();
if (init.fColorIgnored) {
local->fInputColorType = kIgnored_GrGPInput;
local->fColor = GrColor_ILLEGAL;
} else {
local->fInputColorType = kUniform_GrGPInput;
local->fColor = GrColor_ILLEGAL == init.fOverrideColor ? this->color() :
init.fOverrideColor;
}
local->fInputCoverageType = init.fCoverageIgnored ? kIgnored_GrGPInput : kAllOnes_GrGPInput;
local->fUsesLocalCoords = init.fUsesLocalCoords;
}
bool GrPathProcessor::canMakeEqual(const GrBatchTracker& m,
const GrPrimitiveProcessor& that,
const GrBatchTracker& t) const {
if (this->classID() != that.classID() || !this->hasSameTextureAccesses(that)) {
return false;
}
if (!this->viewMatrix().cheapEqualTo(that.viewMatrix())) {
return false;
}
const PathBatchTracker& mine = m.cast<PathBatchTracker>();
const PathBatchTracker& theirs = t.cast<PathBatchTracker>();
return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
that, theirs.fUsesLocalCoords) &&
CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor) &&
CanCombineOutput(mine.fInputCoverageType, 0xff,
theirs.fInputCoverageType, 0xff);
}
void GrPathProcessor::getGLProcessorKey(const GrBatchTracker& bt,
const GrGLCaps& caps,
GrProcessorKeyBuilder* b) const {
GrGLPathProcessor::GenKey(*this, bt, caps, b);
}
GrGLPrimitiveProcessor* GrPathProcessor::createGLInstance(const GrBatchTracker& bt,
const GrGLCaps& caps) const {
SkASSERT(caps.nvprSupport() != GrGLCaps::kNone_NvprSupport);
if (caps.nvprSupport() == GrGLCaps::kLegacy_NvprSupport) {
return SkNEW_ARGS(GrGLLegacyPathProcessor, (*this, bt,
caps.maxFixedFunctionTextureCoords()));
} else {
return SkNEW_ARGS(GrGLNormalPathProcessor, (*this, bt));
}
}

View File

@ -8,224 +8,7 @@
#ifndef GrGeometryProcessor_DEFINED
#define GrGeometryProcessor_DEFINED
#include "GrColor.h"
#include "GrProcessor.h"
#include "GrShaderVar.h"
/*
* The GrPrimitiveProcessor represents some kind of geometric primitive. This includes the shape
* of the primitive and the inherent color of the primitive. The GrPrimitiveProcessor is
* responsible for providing a color and coverage input into the Ganesh rendering pipeline. Through
* optimization, Ganesh may decide a different color, no color, and / or no coverage are required
* from the GrPrimitiveProcessor, so the GrPrimitiveProcessor must be able to support this
* functionality. We also use the GrPrimitiveProcessor to make batching decisions.
*
* There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the
* GrPrimitiveProcessor. These loops run on the CPU and compute any invariant components which
* might be useful for correctness / optimization decisions. The GrPrimitiveProcessor seeds these
* loops, one with initial color and one with initial coverage, in its
* onComputeInvariantColor / Coverage calls. These seed values are processed by the subsequent
* stages of the rendering pipeline and the output is then fed back into the GrPrimitiveProcessor in
* the initBatchTracker call, where the GrPrimitiveProcessor can then initialize the GrBatchTracker
* struct with the appropriate values.
*
* We are evolving this system to move towards generating geometric meshes and their associated
* vertex data after we have batched and reordered draws. This system, known as 'deferred geometry'
* will allow the GrPrimitiveProcessor much greater control over how data is transmitted to shaders.
*
* In a deferred geometry world, the GrPrimitiveProcessor can always 'batch' To do this, each
* primitive type is associated with one GrPrimitiveProcessor, who has complete control of how
* it draws. Each primitive draw will bundle all required data to perform the draw, and these
* bundles of data will be owned by an instance of the associated GrPrimitiveProcessor. Bundles
* can be updated alongside the GrBatchTracker struct itself, ultimately allowing the
* GrPrimitiveProcessor complete control of how it gets data into the fragment shader as long as
* it emits the appropriate color, or none at all, as directed.
*/
/*
* A struct for tracking batching decisions. While this lives on GrOptState, it is managed
* entirely by the derived classes of the GP.
* // TODO this was an early attempt at handling out of order batching. It should be
* used carefully as it is being replaced by GrBatch
*/
class GrBatchTracker {
public:
template <typename T> const T& cast() const {
SkASSERT(sizeof(T) <= kMaxSize);
return *reinterpret_cast<const T*>(fData.get());
}
template <typename T> T* cast() {
SkASSERT(sizeof(T) <= kMaxSize);
return reinterpret_cast<T*>(fData.get());
}
static const size_t kMaxSize = 32;
private:
SkAlignedSStorage<kMaxSize> fData;
};
class GrIndexBufferAllocPool;
class GrGLCaps;
class GrGLPrimitiveProcessor;
class GrVertexBufferAllocPool;
struct GrInitInvariantOutput;
/*
* This struct allows the GrPipeline to communicate information about the pipeline. Most of this
* is overrides, but some of it is general information. Logically it should live in GrPipeline.h,
* but this is problematic due to circular dependencies.
*/
struct GrPipelineInfo {
bool fColorIgnored;
bool fCoverageIgnored;
GrColor fOverrideColor;
bool fUsesLocalCoords;
};
/*
* This enum is shared by GrPrimitiveProcessors and GrGLPrimitiveProcessors to coordinate shaders
* with vertex attributes / uniforms.
*/
enum GrGPInput {
kAllOnes_GrGPInput,
kAttribute_GrGPInput,
kUniform_GrGPInput,
kIgnored_GrGPInput,
};
/*
* GrPrimitiveProcessor defines an interface which all subclasses must implement. All
* GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage
* pipelines, and they must provide some notion of equality
*/
class GrPrimitiveProcessor : public GrProcessor {
public:
// TODO let the PrimProc itself set this in its setData call, this should really live on the
// bundle of primitive data
const SkMatrix& viewMatrix() const { return fViewMatrix; }
const SkMatrix& localMatrix() const { return fLocalMatrix; }
virtual void initBatchTracker(GrBatchTracker*, const GrPipelineInfo&) const = 0;
virtual bool canMakeEqual(const GrBatchTracker& mine,
const GrPrimitiveProcessor& that,
const GrBatchTracker& theirs) const = 0;
virtual void getInvariantOutputColor(GrInitInvariantOutput* out) const = 0;
virtual void getInvariantOutputCoverage(GrInitInvariantOutput* out) const = 0;
// Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but
// we put these calls on the base class to prevent having to cast
virtual bool willUseGeoShader() const = 0;
/*
* This is a safeguard to prevent GrPrimitiveProcessor's from going beyond platform specific
* attribute limits. This number can almost certainly be raised if required.
*/
static const int kMaxVertexAttribs = 6;
struct Attribute {
Attribute()
: fName(NULL)
, fType(kFloat_GrVertexAttribType)
, fOffset(0) {}
Attribute(const char* name, GrVertexAttribType type)
: fName(name)
, fType(type)
, fOffset(SkAlign4(GrVertexAttribTypeSize(type))) {}
const char* fName;
GrVertexAttribType fType;
size_t fOffset;
};
int numAttribs() const { return fNumAttribs; }
const Attribute& getAttrib(int index) const {
SkASSERT(index < fNumAttribs);
return fAttribs[index];
}
// Returns the vertex stride of the GP. A common use case is to request geometry from a
// drawtarget based off of the stride, and to populate this memory using an implicit array of
// structs. In this case, it is best to assert the vertexstride == sizeof(VertexStruct).
size_t getVertexStride() const { return fVertexStride; }
/**
* Gets a transformKey from an array of coord transforms
*/
uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>&) const;
/**
* Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
* processor's GL backend implementation.
*/
virtual void getGLProcessorKey(const GrBatchTracker& bt,
const GrGLCaps& caps,
GrProcessorKeyBuilder* b) const = 0;
/** Returns a new instance of the appropriate *GL* implementation class
for the given GrProcessor; caller is responsible for deleting
the object. */
virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt,
const GrGLCaps& caps) const = 0;
bool isPathRendering() const { return fIsPathRendering; }
protected:
GrPrimitiveProcessor(const SkMatrix& viewMatrix, const SkMatrix& localMatrix,
bool isPathRendering)
: fNumAttribs(0)
, fVertexStride(0)
, fViewMatrix(viewMatrix)
, fLocalMatrix(localMatrix)
, fIsPathRendering(isPathRendering) {}
/*
* CanCombineOutput will return true if two draws are 'batchable' from a color perspective.
* TODO remove this when GPs can upgrade to attribute color
*/
static bool CanCombineOutput(GrGPInput left, GrColor lColor, GrGPInput right, GrColor rColor) {
if (left != right) {
return false;
}
if (kUniform_GrGPInput == left && lColor != rColor) {
return false;
}
return true;
}
static bool CanCombineLocalMatrices(const GrPrimitiveProcessor& left,
bool leftUsesLocalCoords,
const GrPrimitiveProcessor& right,
bool rightUsesLocalCoords) {
if (leftUsesLocalCoords != rightUsesLocalCoords) {
return false;
}
if (leftUsesLocalCoords && !left.localMatrix().cheapEqualTo(right.localMatrix())) {
return false;
}
return true;
}
Attribute fAttribs[kMaxVertexAttribs];
int fNumAttribs;
size_t fVertexStride;
private:
virtual bool hasExplicitLocalCoords() const = 0;
const SkMatrix fViewMatrix;
SkMatrix fLocalMatrix;
bool fIsPathRendering;
typedef GrProcessor INHERITED;
};
#include "GrPrimitiveProcessor.h"
/**
* A GrGeometryProcessor is a flexible method for rendering a primitive. The GrGeometryProcessor
@ -370,49 +153,4 @@ private:
typedef GrPrimitiveProcessor INHERITED;
};
/*
* The path equivalent of the GP. For now this just manages color. In the long term we plan on
* extending this class to handle all nvpr uniform / varying / program work.
*/
class GrPathProcessor : public GrPrimitiveProcessor {
public:
static GrPathProcessor* Create(GrColor color,
const SkMatrix& viewMatrix = SkMatrix::I(),
const SkMatrix& localMatrix = SkMatrix::I()) {
return SkNEW_ARGS(GrPathProcessor, (color, viewMatrix, localMatrix));
}
void initBatchTracker(GrBatchTracker*, const GrPipelineInfo&) const SK_OVERRIDE;
bool canMakeEqual(const GrBatchTracker& mine,
const GrPrimitiveProcessor& that,
const GrBatchTracker& theirs) const SK_OVERRIDE;
const char* name() const SK_OVERRIDE { return "PathProcessor"; }
GrColor color() const { return fColor; }
void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE;
void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE;
bool willUseGeoShader() const SK_OVERRIDE { return false; }
virtual void getGLProcessorKey(const GrBatchTracker& bt,
const GrGLCaps& caps,
GrProcessorKeyBuilder* b) const SK_OVERRIDE;
virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt,
const GrGLCaps& caps) const SK_OVERRIDE;
protected:
GrPathProcessor(GrColor color, const SkMatrix& viewMatrix, const SkMatrix& localMatrix);
private:
bool hasExplicitLocalCoords() const SK_OVERRIDE { return false; }
GrColor fColor;
typedef GrPrimitiveProcessor INHERITED;
};
#endif

View File

@ -0,0 +1,73 @@
#include "GrPathProcessor.h"
#include "gl/GrGLPathProcessor.h"
#include "gl/GrGLGpu.h"
GrPathProcessor::GrPathProcessor(GrColor color,
const SkMatrix& viewMatrix,
const SkMatrix& localMatrix)
: INHERITED(viewMatrix, localMatrix, true)
, fColor(color) {
this->initClassID<GrPathProcessor>();
}
void GrPathProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const {
out->setKnownFourComponents(fColor);
}
void GrPathProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out) const {
out->setKnownSingleComponent(0xff);
}
void GrPathProcessor::initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const {
PathBatchTracker* local = bt->cast<PathBatchTracker>();
if (init.fColorIgnored) {
local->fInputColorType = kIgnored_GrGPInput;
local->fColor = GrColor_ILLEGAL;
} else {
local->fInputColorType = kUniform_GrGPInput;
local->fColor = GrColor_ILLEGAL == init.fOverrideColor ? this->color() :
init.fOverrideColor;
}
local->fInputCoverageType = init.fCoverageIgnored ? kIgnored_GrGPInput : kAllOnes_GrGPInput;
local->fUsesLocalCoords = init.fUsesLocalCoords;
}
bool GrPathProcessor::canMakeEqual(const GrBatchTracker& m,
const GrPrimitiveProcessor& that,
const GrBatchTracker& t) const {
if (this->classID() != that.classID() || !this->hasSameTextureAccesses(that)) {
return false;
}
if (!this->viewMatrix().cheapEqualTo(that.viewMatrix())) {
return false;
}
const PathBatchTracker& mine = m.cast<PathBatchTracker>();
const PathBatchTracker& theirs = t.cast<PathBatchTracker>();
return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
that, theirs.fUsesLocalCoords) &&
CanCombineOutput(mine.fInputColorType, mine.fColor,
theirs.fInputColorType, theirs.fColor) &&
CanCombineOutput(mine.fInputCoverageType, 0xff,
theirs.fInputCoverageType, 0xff);
}
void GrPathProcessor::getGLProcessorKey(const GrBatchTracker& bt,
const GrGLCaps& caps,
GrProcessorKeyBuilder* b) const {
GrGLPathProcessor::GenKey(*this, bt, caps, b);
}
GrGLPrimitiveProcessor* GrPathProcessor::createGLInstance(const GrBatchTracker& bt,
const GrGLCaps& caps) const {
SkASSERT(caps.nvprSupport() != GrGLCaps::kNone_NvprSupport);
if (caps.nvprSupport() == GrGLCaps::kLegacy_NvprSupport) {
return SkNEW_ARGS(GrGLLegacyPathProcessor, (*this, bt,
caps.maxFixedFunctionTextureCoords()));
} else {
return SkNEW_ARGS(GrGLNormalPathProcessor, (*this, bt));
}
}

65
src/gpu/GrPathProcessor.h Normal file
View File

@ -0,0 +1,65 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrPathProcessor_DEFINED
#define GrPathProcessor_DEFINED
#include "GrPrimitiveProcessor.h"
struct PathBatchTracker {
GrGPInput fInputColorType;
GrGPInput fInputCoverageType;
GrColor fColor;
bool fUsesLocalCoords;
};
/*
* The path equivalent of the GP. For now this just manages color. In the long term we plan on
* extending this class to handle all nvpr uniform / varying / program work.
*/
class GrPathProcessor : public GrPrimitiveProcessor {
public:
static GrPathProcessor* Create(GrColor color,
const SkMatrix& viewMatrix = SkMatrix::I(),
const SkMatrix& localMatrix = SkMatrix::I()) {
return SkNEW_ARGS(GrPathProcessor, (color, viewMatrix, localMatrix));
}
void initBatchTracker(GrBatchTracker*, const GrPipelineInfo&) const SK_OVERRIDE;
bool canMakeEqual(const GrBatchTracker& mine,
const GrPrimitiveProcessor& that,
const GrBatchTracker& theirs) const SK_OVERRIDE;
const char* name() const SK_OVERRIDE { return "PathProcessor"; }
GrColor color() const { return fColor; }
void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE;
void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE;
bool willUseGeoShader() const SK_OVERRIDE { return false; }
virtual void getGLProcessorKey(const GrBatchTracker& bt,
const GrGLCaps& caps,
GrProcessorKeyBuilder* b) const SK_OVERRIDE;
virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt,
const GrGLCaps& caps) const SK_OVERRIDE;
protected:
GrPathProcessor(GrColor color, const SkMatrix& viewMatrix, const SkMatrix& localMatrix);
private:
bool hasExplicitLocalCoords() const SK_OVERRIDE { return false; }
GrColor fColor;
typedef GrPrimitiveProcessor INHERITED;
};
#endif

View File

@ -11,7 +11,6 @@
#include "GrBatch.h"
#include "GrBlend.h"
#include "GrDrawTargetCaps.h"
#include "GrGeometryProcessor.h"
#include "GrGpuResourceRef.h"
#include "GrFragmentStage.h"
#include "GrProcOptInfo.h"

View File

@ -0,0 +1,67 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrPrimitiveProcessor.h"
#include "GrCoordTransform.h"
/**
* The key for an individual coord transform is made up of a matrix type, a precision, and a bit
* that indicates the source of the input coords.
*/
enum {
kMatrixTypeKeyBits = 1,
kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
kPrecisionBits = 2,
kPrecisionShift = kMatrixTypeKeyBits,
kPositionCoords_Flag = (1 << (kPrecisionShift + kPrecisionBits)),
kDeviceCoords_Flag = kPositionCoords_Flag + kPositionCoords_Flag,
kTransformKeyBits = kMatrixTypeKeyBits + kPrecisionBits + 2,
};
GR_STATIC_ASSERT(kHigh_GrSLPrecision < (1 << kPrecisionBits));
/**
* We specialize the vertex code for each of these matrix types.
*/
enum MatrixType {
kNoPersp_MatrixType = 0,
kGeneral_MatrixType = 1,
};
uint32_t
GrPrimitiveProcessor::getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords) const {
uint32_t totalKey = 0;
for (int t = 0; t < coords.count(); ++t) {
uint32_t key = 0;
const GrCoordTransform* coordTransform = coords[t];
if (coordTransform->getMatrix().hasPerspective()) {
key |= kGeneral_MatrixType;
} else {
key |= kNoPersp_MatrixType;
}
if (kLocal_GrCoordSet == coordTransform->sourceCoords() &&
!this->hasExplicitLocalCoords()) {
key |= kPositionCoords_Flag;
} else if (kDevice_GrCoordSet == coordTransform->sourceCoords()) {
key |= kDeviceCoords_Flag;
}
GR_STATIC_ASSERT(kGrSLPrecisionCount <= (1 << kPrecisionBits));
key |= (coordTransform->precision() << kPrecisionShift);
key <<= kTransformKeyBits * t;
SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
totalKey |= key;
}
return totalKey;
}

View File

@ -0,0 +1,230 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrPrimitiveProcessor_DEFINED
#define GrPrimitiveProcessor_DEFINED
#include "GrColor.h"
#include "GrProcessor.h"
#include "GrShaderVar.h"
/*
* The GrPrimitiveProcessor represents some kind of geometric primitive. This includes the shape
* of the primitive and the inherent color of the primitive. The GrPrimitiveProcessor is
* responsible for providing a color and coverage input into the Ganesh rendering pipeline. Through
* optimization, Ganesh may decide a different color, no color, and / or no coverage are required
* from the GrPrimitiveProcessor, so the GrPrimitiveProcessor must be able to support this
* functionality. We also use the GrPrimitiveProcessor to make batching decisions.
*
* There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the
* GrPrimitiveProcessor. These loops run on the CPU and compute any invariant components which
* might be useful for correctness / optimization decisions. The GrPrimitiveProcessor seeds these
* loops, one with initial color and one with initial coverage, in its
* onComputeInvariantColor / Coverage calls. These seed values are processed by the subsequent
* stages of the rendering pipeline and the output is then fed back into the GrPrimitiveProcessor in
* the initBatchTracker call, where the GrPrimitiveProcessor can then initialize the GrBatchTracker
* struct with the appropriate values.
*
* We are evolving this system to move towards generating geometric meshes and their associated
* vertex data after we have batched and reordered draws. This system, known as 'deferred geometry'
* will allow the GrPrimitiveProcessor much greater control over how data is transmitted to shaders.
*
* In a deferred geometry world, the GrPrimitiveProcessor can always 'batch' To do this, each
* primitive type is associated with one GrPrimitiveProcessor, who has complete control of how
* it draws. Each primitive draw will bundle all required data to perform the draw, and these
* bundles of data will be owned by an instance of the associated GrPrimitiveProcessor. Bundles
* can be updated alongside the GrBatchTracker struct itself, ultimately allowing the
* GrPrimitiveProcessor complete control of how it gets data into the fragment shader as long as
* it emits the appropriate color, or none at all, as directed.
*/
/*
* A struct for tracking batching decisions. While this lives on GrOptState, it is managed
* entirely by the derived classes of the GP.
* // TODO this was an early attempt at handling out of order batching. It should be
* used carefully as it is being replaced by GrBatch
*/
class GrBatchTracker {
public:
template <typename T> const T& cast() const {
SkASSERT(sizeof(T) <= kMaxSize);
return *reinterpret_cast<const T*>(fData.get());
}
template <typename T> T* cast() {
SkASSERT(sizeof(T) <= kMaxSize);
return reinterpret_cast<T*>(fData.get());
}
static const size_t kMaxSize = 32;
private:
SkAlignedSStorage<kMaxSize> fData;
};
class GrIndexBufferAllocPool;
class GrGLCaps;
class GrGLPrimitiveProcessor;
class GrVertexBufferAllocPool;
struct GrInitInvariantOutput;
/*
* This struct allows the GrPipeline to communicate information about the pipeline. Most of this
* is overrides, but some of it is general information. Logically it should live in GrPipeline.h,
* but this is problematic due to circular dependencies.
*/
struct GrPipelineInfo {
bool fColorIgnored;
bool fCoverageIgnored;
GrColor fOverrideColor;
bool fUsesLocalCoords;
};
/*
* This enum is shared by GrPrimitiveProcessors and GrGLPrimitiveProcessors to coordinate shaders
* with vertex attributes / uniforms.
*/
enum GrGPInput {
kAllOnes_GrGPInput,
kAttribute_GrGPInput,
kUniform_GrGPInput,
kIgnored_GrGPInput,
};
/*
* GrPrimitiveProcessor defines an interface which all subclasses must implement. All
* GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage
* pipelines, and they must provide some notion of equality
*/
class GrPrimitiveProcessor : public GrProcessor {
public:
// TODO let the PrimProc itself set this in its setData call, this should really live on the
// bundle of primitive data
const SkMatrix& viewMatrix() const { return fViewMatrix; }
const SkMatrix& localMatrix() const { return fLocalMatrix; }
virtual void initBatchTracker(GrBatchTracker*, const GrPipelineInfo&) const = 0;
virtual bool canMakeEqual(const GrBatchTracker& mine,
const GrPrimitiveProcessor& that,
const GrBatchTracker& theirs) const = 0;
virtual void getInvariantOutputColor(GrInitInvariantOutput* out) const = 0;
virtual void getInvariantOutputCoverage(GrInitInvariantOutput* out) const = 0;
// Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but
// we put these calls on the base class to prevent having to cast
virtual bool willUseGeoShader() const = 0;
/*
* This is a safeguard to prevent GrPrimitiveProcessor's from going beyond platform specific
* attribute limits. This number can almost certainly be raised if required.
*/
static const int kMaxVertexAttribs = 6;
struct Attribute {
Attribute()
: fName(NULL)
, fType(kFloat_GrVertexAttribType)
, fOffset(0) {}
Attribute(const char* name, GrVertexAttribType type)
: fName(name)
, fType(type)
, fOffset(SkAlign4(GrVertexAttribTypeSize(type))) {}
const char* fName;
GrVertexAttribType fType;
size_t fOffset;
};
int numAttribs() const { return fNumAttribs; }
const Attribute& getAttrib(int index) const {
SkASSERT(index < fNumAttribs);
return fAttribs[index];
}
// Returns the vertex stride of the GP. A common use case is to request geometry from a
// drawtarget based off of the stride, and to populate this memory using an implicit array of
// structs. In this case, it is best to assert the vertexstride == sizeof(VertexStruct).
size_t getVertexStride() const { return fVertexStride; }
/**
* Gets a transformKey from an array of coord transforms
*/
uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>&) const;
/**
* Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
* processor's GL backend implementation.
*/
virtual void getGLProcessorKey(const GrBatchTracker& bt,
const GrGLCaps& caps,
GrProcessorKeyBuilder* b) const = 0;
/** Returns a new instance of the appropriate *GL* implementation class
for the given GrProcessor; caller is responsible for deleting
the object. */
virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt,
const GrGLCaps& caps) const = 0;
bool isPathRendering() const { return fIsPathRendering; }
protected:
GrPrimitiveProcessor(const SkMatrix& viewMatrix, const SkMatrix& localMatrix,
bool isPathRendering)
: fNumAttribs(0)
, fVertexStride(0)
, fViewMatrix(viewMatrix)
, fLocalMatrix(localMatrix)
, fIsPathRendering(isPathRendering) {}
/*
* CanCombineOutput will return true if two draws are 'batchable' from a color perspective.
* TODO remove this when GPs can upgrade to attribute color
*/
static bool CanCombineOutput(GrGPInput left, GrColor lColor, GrGPInput right, GrColor rColor) {
if (left != right) {
return false;
}
if (kUniform_GrGPInput == left && lColor != rColor) {
return false;
}
return true;
}
static bool CanCombineLocalMatrices(const GrPrimitiveProcessor& left,
bool leftUsesLocalCoords,
const GrPrimitiveProcessor& right,
bool rightUsesLocalCoords) {
if (leftUsesLocalCoords != rightUsesLocalCoords) {
return false;
}
if (leftUsesLocalCoords && !left.localMatrix().cheapEqualTo(right.localMatrix())) {
return false;
}
return true;
}
Attribute fAttribs[kMaxVertexAttribs];
int fNumAttribs;
size_t fVertexStride;
private:
virtual bool hasExplicitLocalCoords() const = 0;
const SkMatrix fViewMatrix;
SkMatrix fLocalMatrix;
bool fIsPathRendering;
typedef GrProcessor INHERITED;
};
#endif

View File

@ -0,0 +1,129 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGLGeometryProcessor.h"
#include "builders/GrGLProgramBuilder.h"
void GrGLGeometryProcessor::emitCode(EmitArgs& args) {
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
GrGPArgs gpArgs;
this->onEmitCode(args, &gpArgs);
vsBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar);
}
void GrGLGeometryProcessor::emitTransforms(GrGLGPBuilder* pb,
const GrShaderVar& posVar,
const char* localCoords,
const SkMatrix& localMatrix,
const TransformsIn& tin,
TransformsOut* tout) {
GrGLVertexBuilder* vb = pb->getVertexShaderBuilder();
tout->push_back_n(tin.count());
fInstalledTransforms.push_back_n(tin.count());
for (int i = 0; i < tin.count(); i++) {
const ProcCoords& coordTransforms = tin[i];
fInstalledTransforms[i].push_back_n(coordTransforms.count());
for (int t = 0; t < coordTransforms.count(); t++) {
SkString strUniName("StageMatrix");
strUniName.appendf("_%i_%i", i, t);
GrSLType varyingType;
GrCoordSet coordType = coordTransforms[t]->sourceCoords();
uint32_t type = coordTransforms[t]->getMatrix().getType();
if (kLocal_GrCoordSet == coordType) {
type |= localMatrix.getType();
}
varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType :
kVec2f_GrSLType;
GrSLPrecision precision = coordTransforms[t]->precision();
const char* uniName;
fInstalledTransforms[i][t].fHandle =
pb->addUniform(GrGLProgramBuilder::kVertex_Visibility,
kMat33f_GrSLType, precision,
strUniName.c_str(),
&uniName).toShaderBuilderIndex();
SkString strVaryingName("MatrixCoord");
strVaryingName.appendf("_%i_%i", i, t);
GrGLVertToFrag v(varyingType);
pb->addVarying(strVaryingName.c_str(), &v, precision);
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords,
(SkString(v.fsIn()), varyingType));
// varying = matrix * coords (logically)
if (kDevice_GrCoordSet == coordType) {
if (kVec2f_GrSLType == varyingType) {
if (kVec2f_GrSLType == posVar.getType()) {
vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
v.vsOut(), uniName, posVar.c_str());
} else {
// The brackets here are just to scope the temp variable
vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVar.c_str());
vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z); }", v.vsOut());
}
} else {
if (kVec2f_GrSLType == posVar.getType()) {
vb->codeAppendf("%s = %s * vec3(%s, 1);",
v.vsOut(), uniName, posVar.c_str());
} else {
vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, posVar.c_str());
}
}
} else {
if (kVec2f_GrSLType == varyingType) {
vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
} else {
vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName, localCoords);
}
}
}
}
}
void
GrGLGeometryProcessor::setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) {
SkSTArray<2, Transform, true>& procTransforms = fInstalledTransforms[index];
int numTransforms = transforms.count();
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(procTransforms[t].fHandle.isValid());
const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *transforms[t]);
if (!procTransforms[t].fCurrentValue.cheapEqualTo(transform)) {
pdman.setSkMatrix(procTransforms[t].fHandle.convertToUniformHandle(), transform);
procTransforms[t].fCurrentValue = transform;
}
}
}
void GrGLGeometryProcessor::SetupPosition(GrGLVertexBuilder* vsBuilder,
GrGPArgs* gpArgs,
const char* posName,
const SkMatrix& mat,
const char* matName) {
if (mat.isIdentity()) {
gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
vsBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
} else if (!mat.hasPerspective()) {
gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
vsBuilder->codeAppendf("vec2 %s = vec2(%s * vec3(%s, 1));",
gpArgs->fPositionVar.c_str(), matName, posName);
} else {
gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3");
vsBuilder->codeAppendf("vec3 %s = %s * vec3(%s, 1);",
gpArgs->fPositionVar.c_str(), matName, posName);
}
}

View File

@ -8,126 +8,10 @@
#ifndef GrGLGeometryProcessor_DEFINED
#define GrGLGeometryProcessor_DEFINED
#include "GrGLProcessor.h"
#include "GrGLPrimitiveProcessor.h"
class GrBatchTracker;
class GrFragmentProcessor;
class GrGLGPBuilder;
class GrGLPrimitiveProcessor {
public:
GrGLPrimitiveProcessor() : fViewMatrixName(NULL) { fViewMatrix = SkMatrix::InvalidMatrix(); }
virtual ~GrGLPrimitiveProcessor() {}
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray;
typedef SkSTArray<2, const GrCoordTransform*, true> ProcCoords;
typedef SkSTArray<8, ProcCoords> TransformsIn;
typedef SkSTArray<8, GrGLProcessor::TransformedCoordsArray> TransformsOut;
struct EmitArgs {
EmitArgs(GrGLGPBuilder* pb,
const GrPrimitiveProcessor& gp,
const GrBatchTracker& bt,
const char* outputColor,
const char* outputCoverage,
const TextureSamplerArray& samplers,
const TransformsIn& transformsIn,
TransformsOut* transformsOut)
: fPB(pb)
, fGP(gp)
, fBT(bt)
, fOutputColor(outputColor)
, fOutputCoverage(outputCoverage)
, fSamplers(samplers)
, fTransformsIn(transformsIn)
, fTransformsOut(transformsOut) {}
GrGLGPBuilder* fPB;
const GrPrimitiveProcessor& fGP;
const GrBatchTracker& fBT;
const char* fOutputColor;
const char* fOutputCoverage;
const TextureSamplerArray& fSamplers;
const TransformsIn& fTransformsIn;
TransformsOut* fTransformsOut;
};
/**
* This is similar to emitCode() in the base class, except it takes a full shader builder.
* This allows the effect subclass to emit vertex code.
*/
virtual void emitCode(EmitArgs&) = 0;
/** A GrGLPrimitiveProcessor instance can be reused with any GrGLPrimitiveProcessor that
produces the same stage key; this function reads data from a GrGLPrimitiveProcessor and
uploads any uniform variables required by the shaders created in emitCode(). The
GrPrimitiveProcessor parameter is guaranteed to be of the same type that created this
GrGLPrimitiveProcessor and to have an identical processor key as the one that created this
GrGLPrimitiveProcessor. */
virtual void setData(const GrGLProgramDataManager&,
const GrPrimitiveProcessor&,
const GrBatchTracker&) = 0;
static SkMatrix GetTransformMatrix(const SkMatrix& localMatrix, const GrCoordTransform&);
protected:
/** a helper which can setup vertex, constant, or uniform color depending on inputType.
* This function will only do the minimum required to emit the correct shader code. If
* inputType == attribute, then colorAttr must not be NULL. Likewise, if inputType == Uniform
* then colorUniform must not be NULL.
*/
void setupColorPassThrough(GrGLGPBuilder* pb,
GrGPInput inputType,
const char* inputName,
const GrGeometryProcessor::Attribute* colorAttr,
UniformHandle* colorUniform);
const char* uViewM() const { return fViewMatrixName; }
/** a helper function to setup the uniform handle for the uniform view matrix */
void addUniformViewMatrix(GrGLGPBuilder*);
/** a helper function to upload a uniform viewmatrix.
* TODO we can remove this function when we have deferred geometry in place
*/
void setUniformViewMatrix(const GrGLProgramDataManager&,
const SkMatrix& viewMatrix);
class ShaderVarHandle {
public:
bool isValid() const { return fHandle > -1; }
ShaderVarHandle() : fHandle(-1) {}
ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
int handle() const { SkASSERT(this->isValid()); return fHandle; }
UniformHandle convertToUniformHandle() {
SkASSERT(this->isValid());
return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
}
private:
int fHandle;
};
struct Transform {
Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
ShaderVarHandle fHandle;
SkMatrix fCurrentValue;
GrSLType fType;
};
SkSTArray<8, SkSTArray<2, Transform, true> > fInstalledTransforms;
private:
UniformHandle fViewMatrixUniform;
SkMatrix fViewMatrix;
const char* fViewMatrixName;
};
class GrGLPathRendering;
class GrGLVertexBuilder;
/**
* If a GL effect needs a GrGLFullShaderBuilder* object to emit vertex code, then it must inherit
* from this class. Since paths don't have vertices, this class is only meant to be used internally
@ -189,40 +73,4 @@ private:
typedef GrGLPrimitiveProcessor INHERITED;
};
class GrGLGpu;
class GrGLPathProcessor : public GrGLPrimitiveProcessor {
public:
GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&);
static void GenKey(const GrPathProcessor&,
const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b);
void emitCode(EmitArgs&) SK_OVERRIDE;
virtual void emitTransforms(GrGLGPBuilder*, const TransformsIn&, TransformsOut*) = 0;
virtual void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {}
void setData(const GrGLProgramDataManager&,
const GrPrimitiveProcessor&,
const GrBatchTracker&) SK_OVERRIDE;
virtual void setTransformData(const GrPrimitiveProcessor&,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms,
GrGLPathRendering*,
GrGLuint programID) = 0;
virtual void didSetData(GrGLPathRendering*) {}
private:
UniformHandle fColorUniform;
GrColor fColor;
typedef GrGLPrimitiveProcessor INHERITED;
};
#endif

View File

@ -0,0 +1,183 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGLPathProcessor.h"
#include "GrPathProcessor.h"
#include "GrGLGpu.h"
#include "GrGLPathRendering.h"
GrGLPathProcessor::GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&)
: fColor(GrColor_ILLEGAL) {}
void GrGLPathProcessor::emitCode(EmitArgs& args) {
GrGLGPBuilder* pb = args.fPB;
GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder();
const PathBatchTracker& local = args.fBT.cast<PathBatchTracker>();
// emit transforms
this->emitTransforms(args.fPB, args.fTransformsIn, args.fTransformsOut);
// Setup uniform color
if (kUniform_GrGPInput == local.fInputColorType) {
const char* stagedLocalVarName;
fColorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType,
kDefault_GrSLPrecision,
"Color",
&stagedLocalVarName);
fs->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
}
// setup constant solid coverage
if (kAllOnes_GrGPInput == local.fInputCoverageType) {
fs->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
}
}
void GrGLPathProcessor::GenKey(const GrPathProcessor&,
const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
const PathBatchTracker& local = bt.cast<PathBatchTracker>();
b->add32(local.fInputColorType | local.fInputCoverageType << 16);
}
void GrGLPathProcessor::setData(const GrGLProgramDataManager& pdman,
const GrPrimitiveProcessor& primProc,
const GrBatchTracker& bt) {
const PathBatchTracker& local = bt.cast<PathBatchTracker>();
if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
GrGLfloat c[4];
GrColorToRGBAFloat(local.fColor, c);
pdman.set4fv(fColorUniform, 1, c);
fColor = local.fColor;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void GrGLLegacyPathProcessor::emitTransforms(GrGLGPBuilder*, const TransformsIn& tin,
TransformsOut* tout) {
tout->push_back_n(tin.count());
fInstalledTransforms.push_back_n(tin.count());
for (int i = 0; i < tin.count(); i++) {
const ProcCoords& coordTransforms = tin[i];
int texCoordIndex = this->addTexCoordSets(coordTransforms.count());
// Use the first uniform location as the texcoord index.
fInstalledTransforms[i].push_back_n(1);
fInstalledTransforms[i][0].fHandle = ShaderVarHandle(texCoordIndex);
SkString name;
for (int t = 0; t < coordTransforms.count(); ++t) {
GrSLType type = coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
kVec2f_GrSLType;
name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords, (name, type));
}
}
}
void GrGLLegacyPathProcessor::setTransformData(
const GrPrimitiveProcessor& primProc,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms,
GrGLPathRendering* glpr,
GrGLuint) {
// We've hidden the texcoord index in the first entry of the transforms array for each
// effect
int texCoordIndex = fInstalledTransforms[index][0].fHandle.handle();
for (int t = 0; t < transforms.count(); ++t) {
const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *transforms[t]);
GrGLPathRendering::PathTexGenComponents components =
GrGLPathRendering::kST_PathTexGenComponents;
if (transform.hasPerspective()) {
components = GrGLPathRendering::kSTR_PathTexGenComponents;
}
glpr->enablePathTexGen(texCoordIndex++, components, transform);
}
}
void GrGLLegacyPathProcessor::didSetData(GrGLPathRendering* glpr) {
glpr->flushPathTexGenSettings(fTexCoordSetCnt);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void GrGLNormalPathProcessor::emitTransforms(GrGLGPBuilder* pb, const TransformsIn& tin,
TransformsOut* tout) {
tout->push_back_n(tin.count());
fInstalledTransforms.push_back_n(tin.count());
for (int i = 0; i < tin.count(); i++) {
const ProcCoords& coordTransforms = tin[i];
fInstalledTransforms[i].push_back_n(coordTransforms.count());
for (int t = 0; t < coordTransforms.count(); t++) {
GrSLType varyingType =
coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
kVec2f_GrSLType;
SkString strVaryingName("MatrixCoord");
strVaryingName.appendf("_%i_%i", i, t);
GrGLVertToFrag v(varyingType);
pb->addVarying(strVaryingName.c_str(), &v);
SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back();
varyingInfo.fVariable = pb->getFragmentShaderBuilder()->fInputs.back();
varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1;
varyingInfo.fType = varyingType;
fInstalledTransforms[i][t].fHandle = ShaderVarHandle(varyingInfo.fLocation);
fInstalledTransforms[i][t].fType = varyingType;
SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords,
(SkString(v.fsIn()), varyingType));
}
}
}
void GrGLNormalPathProcessor::resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {
int count = fSeparableVaryingInfos.count();
for (int i = 0; i < count; ++i) {
GrGLint location;
GR_GL_CALL_RET(gpu->glInterface(),
location,
GetProgramResourceLocation(programId,
GR_GL_FRAGMENT_INPUT,
fSeparableVaryingInfos[i].fVariable.c_str()));
fSeparableVaryingInfos[i].fLocation = location;
}
}
void GrGLNormalPathProcessor::setTransformData(
const GrPrimitiveProcessor& primProc,
int index,
const SkTArray<const GrCoordTransform*, true>& coordTransforms,
GrGLPathRendering* glpr,
GrGLuint programID) {
SkSTArray<2, Transform, true>& transforms = fInstalledTransforms[index];
int numTransforms = transforms.count();
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(transforms[t].fHandle.isValid());
const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(),
*coordTransforms[t]);
if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
continue;
}
transforms[t].fCurrentValue = transform;
const SeparableVaryingInfo& fragmentInput =
fSeparableVaryingInfos[transforms[t].fHandle.handle()];
SkASSERT(transforms[t].fType == kVec2f_GrSLType ||
transforms[t].fType == kVec3f_GrSLType);
unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
glpr->setProgramPathFragmentInputTransform(programID,
fragmentInput.fLocation,
GR_GL_OBJECT_LINEAR,
components,
transform);
}
}

View File

@ -0,0 +1,113 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLPathProcessor_DEFINED
#define GrGLPathProcessor_DEFINED
#include "GrGLPrimitiveProcessor.h"
class GrPathProcessor;
class GrGLPathRendering;
class GrGLGpu;
class GrGLPathProcessor : public GrGLPrimitiveProcessor {
public:
GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&);
static void GenKey(const GrPathProcessor&,
const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b);
void emitCode(EmitArgs&) SK_OVERRIDE;
virtual void emitTransforms(GrGLGPBuilder*, const TransformsIn&, TransformsOut*) = 0;
virtual void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {}
void setData(const GrGLProgramDataManager&,
const GrPrimitiveProcessor&,
const GrBatchTracker&) SK_OVERRIDE;
virtual void setTransformData(const GrPrimitiveProcessor&,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms,
GrGLPathRendering*,
GrGLuint programID) = 0;
virtual void didSetData(GrGLPathRendering*) {}
private:
UniformHandle fColorUniform;
GrColor fColor;
typedef GrGLPrimitiveProcessor INHERITED;
};
class GrGLLegacyPathProcessor : public GrGLPathProcessor {
public:
GrGLLegacyPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracker& bt,
int maxTexCoords)
: INHERITED(pathProc, bt)
, fTexCoordSetCnt(0) {
SkDEBUGCODE(fMaxTexCoords = maxTexCoords;)
}
int addTexCoordSets(int count) {
int firstFreeCoordSet = fTexCoordSetCnt;
fTexCoordSetCnt += count;
SkASSERT(fMaxTexCoords >= fTexCoordSetCnt);
return firstFreeCoordSet;
}
void emitTransforms(GrGLGPBuilder*, const TransformsIn& tin, TransformsOut* tout) SK_OVERRIDE;
void setTransformData(const GrPrimitiveProcessor& primProc,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms,
GrGLPathRendering* glpr,
GrGLuint) SK_OVERRIDE;
void didSetData(GrGLPathRendering* glpr) SK_OVERRIDE;
private:
SkDEBUGCODE(int fMaxTexCoords;)
int fTexCoordSetCnt;
typedef GrGLPathProcessor INHERITED;
};
class GrGLNormalPathProcessor : public GrGLPathProcessor {
public:
GrGLNormalPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracker& bt)
: INHERITED(pathProc, bt) {}
void emitTransforms(GrGLGPBuilder* pb, const TransformsIn& tin,TransformsOut* tout) SK_OVERRIDE;
void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId);
void setTransformData(const GrPrimitiveProcessor& primProc,
int index,
const SkTArray<const GrCoordTransform*, true>& coordTransforms,
GrGLPathRendering* glpr,
GrGLuint programID) SK_OVERRIDE;
private:
struct SeparableVaryingInfo {
GrSLType fType;
GrGLShaderVar fVariable;
GrGLint fLocation;
};
typedef SkSTArray<8, SeparableVaryingInfo, true> SeparableVaryingInfoArray;
SeparableVaryingInfoArray fSeparableVaryingInfos;
typedef GrGLPathProcessor INHERITED;
};
#endif

View File

@ -0,0 +1,75 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGLPrimitiveProcessor.h"
#include "builders/GrGLProgramBuilder.h"
SkMatrix GrGLPrimitiveProcessor::GetTransformMatrix(const SkMatrix& localMatrix,
const GrCoordTransform& coordTransform) {
SkMatrix combined;
// We only apply the localmatrix to localcoords
if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
combined.setConcat(coordTransform.getMatrix(), localMatrix);
} 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;
}
void
GrGLPrimitiveProcessor::setupColorPassThrough(GrGLGPBuilder* pb,
GrGPInput inputType,
const char* outputName,
const GrGeometryProcessor::Attribute* colorAttr,
UniformHandle* colorUniform) {
GrGLGPFragmentBuilder* fs = pb->getFragmentShaderBuilder();
if (kUniform_GrGPInput == inputType) {
SkASSERT(colorUniform);
const char* stagedLocalVarName;
*colorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType,
kDefault_GrSLPrecision,
"Color",
&stagedLocalVarName);
fs->codeAppendf("%s = %s;", outputName, stagedLocalVarName);
} else if (kAttribute_GrGPInput == inputType) {
SkASSERT(colorAttr);
pb->addPassThroughAttribute(colorAttr, outputName);
} else if (kAllOnes_GrGPInput == inputType) {
fs->codeAppendf("%s = vec4(1);", outputName);
}
}
void GrGLPrimitiveProcessor::addUniformViewMatrix(GrGLGPBuilder* pb) {
fViewMatrixUniform = pb->addUniform(GrGLProgramBuilder::kVertex_Visibility,
kMat33f_GrSLType, kDefault_GrSLPrecision,
"uViewM",
&fViewMatrixName);
}
void GrGLPrimitiveProcessor::setUniformViewMatrix(const GrGLProgramDataManager& pdman,
const SkMatrix& viewMatrix) {
if (!fViewMatrix.cheapEqualTo(viewMatrix)) {
SkASSERT(fViewMatrixUniform.isValid());
fViewMatrix = viewMatrix;
GrGLfloat viewMatrix[3 * 3];
GrGLGetMatrix<3>(viewMatrix, fViewMatrix);
pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
}
}

View File

@ -0,0 +1,130 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLPrimitiveProcessor_DEFINED
#define GrGLPrimitiveProcessor_DEFINED
#include "GrPrimitiveProcessor.h"
#include "GrGLProcessor.h"
class GrBatchTracker;
class GrPrimitiveProcessor;
class GrGLGPBuilder;
class GrGLPrimitiveProcessor {
public:
GrGLPrimitiveProcessor() : fViewMatrixName(NULL) { fViewMatrix = SkMatrix::InvalidMatrix(); }
virtual ~GrGLPrimitiveProcessor() {}
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray;
typedef SkSTArray<2, const GrCoordTransform*, true> ProcCoords;
typedef SkSTArray<8, ProcCoords> TransformsIn;
typedef SkSTArray<8, GrGLProcessor::TransformedCoordsArray> TransformsOut;
struct EmitArgs {
EmitArgs(GrGLGPBuilder* pb,
const GrPrimitiveProcessor& gp,
const GrBatchTracker& bt,
const char* outputColor,
const char* outputCoverage,
const TextureSamplerArray& samplers,
const TransformsIn& transformsIn,
TransformsOut* transformsOut)
: fPB(pb)
, fGP(gp)
, fBT(bt)
, fOutputColor(outputColor)
, fOutputCoverage(outputCoverage)
, fSamplers(samplers)
, fTransformsIn(transformsIn)
, fTransformsOut(transformsOut) {}
GrGLGPBuilder* fPB;
const GrPrimitiveProcessor& fGP;
const GrBatchTracker& fBT;
const char* fOutputColor;
const char* fOutputCoverage;
const TextureSamplerArray& fSamplers;
const TransformsIn& fTransformsIn;
TransformsOut* fTransformsOut;
};
/**
* This is similar to emitCode() in the base class, except it takes a full shader builder.
* This allows the effect subclass to emit vertex code.
*/
virtual void emitCode(EmitArgs&) = 0;
/** A GrGLPrimitiveProcessor instance can be reused with any GrGLPrimitiveProcessor that
produces the same stage key; this function reads data from a GrGLPrimitiveProcessor and
uploads any uniform variables required by the shaders created in emitCode(). The
GrPrimitiveProcessor parameter is guaranteed to be of the same type that created this
GrGLPrimitiveProcessor and to have an identical processor key as the one that created this
GrGLPrimitiveProcessor. */
virtual void setData(const GrGLProgramDataManager&,
const GrPrimitiveProcessor&,
const GrBatchTracker&) = 0;
static SkMatrix GetTransformMatrix(const SkMatrix& localMatrix, const GrCoordTransform&);
protected:
/** a helper which can setup vertex, constant, or uniform color depending on inputType.
* This function will only do the minimum required to emit the correct shader code. If
* inputType == attribute, then colorAttr must not be NULL. Likewise, if inputType == Uniform
* then colorUniform must not be NULL.
*/
void setupColorPassThrough(GrGLGPBuilder* pb,
GrGPInput inputType,
const char* inputName,
const GrPrimitiveProcessor::Attribute* colorAttr,
UniformHandle* colorUniform);
const char* uViewM() const { return fViewMatrixName; }
/** a helper function to setup the uniform handle for the uniform view matrix */
void addUniformViewMatrix(GrGLGPBuilder*);
/** a helper function to upload a uniform viewmatrix.
* TODO we can remove this function when we have deferred geometry in place
*/
void setUniformViewMatrix(const GrGLProgramDataManager&,
const SkMatrix& viewMatrix);
class ShaderVarHandle {
public:
bool isValid() const { return fHandle > -1; }
ShaderVarHandle() : fHandle(-1) {}
ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
int handle() const { SkASSERT(this->isValid()); return fHandle; }
UniformHandle convertToUniformHandle() {
SkASSERT(this->isValid());
return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
}
private:
int fHandle;
};
struct Transform {
Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
ShaderVarHandle fHandle;
SkMatrix fCurrentValue;
GrSLType fType;
};
SkSTArray<8, SkSTArray<2, Transform, true> > fInstalledTransforms;
private:
UniformHandle fViewMatrixUniform;
SkMatrix fViewMatrix;
const char* fViewMatrixName;
};
#endif

View File

@ -11,12 +11,12 @@
#include "GrProcessor.h"
#include "GrCoordTransform.h"
#include "GrGLGeometryProcessor.h"
#include "GrGLProcessor.h"
#include "GrGLXferProcessor.h"
#include "GrGLGpu.h"
#include "GrGLPathProcessor.h"
#include "GrGLPathRendering.h"
#include "GrGLShaderVar.h"
#include "GrGLSL.h"
#include "GrGLXferProcessor.h"
#include "GrPipeline.h"
#include "GrXferProcessor.h"
#include "SkXfermode.h"

View File

@ -6,11 +6,14 @@
*/
#include "GrGLProgramBuilder.h"
#include "gl/GrGLGeometryProcessor.h"
#include "gl/GrGLGpu.h"
#include "gl/GrGLPathProcessor.h"
#include "gl/GrGLProgram.h"
#include "gl/GrGLSLPrettyPrint.h"
#include "gl/GrGLUniformHandle.h"
#include "../GrGLXferProcessor.h"
#include "../GrGLGpu.h"
#include "gl/GrGLXferProcessor.h"
#include "GrCoordTransform.h"
#include "GrGLProgramBuilder.h"
#include "GrTexture.h"

View File

@ -13,7 +13,7 @@
#include "GrGLVertexShaderBuilder.h"
#include "../GrGLProgramDataManager.h"
#include "../GrGLUniformHandle.h"
#include "../GrGLGeometryProcessor.h"
#include "../GrGLPrimitiveProcessor.h"
#include "../GrGLXferProcessor.h"
#include "../../GrPendingFragmentStage.h"
#include "../../GrPipeline.h"