зеркало из https://github.com/mozilla/moz-skia.git
Remove GrGLProgram::CachedData, make GrGLProgram represent the program
Review URL: http://codereview.appspot.com/6409043/ git-svn-id: http://skia.googlecode.com/svn/trunk@4627 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
a2333d9703
Коммит
9ba4fa6f0f
|
@ -13,30 +13,40 @@
|
||||||
#include "GrTypes.h"
|
#include "GrTypes.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash function class that can take a data chunk of any predetermined
|
* Hash function class that can take a data chunk of any predetermined length. The hash function
|
||||||
* length. The hash function used is the One-at-a-Time Hash
|
* used is the One-at-a-Time Hash (http://burtleburtle.net/bob/hash/doobs.html).
|
||||||
* (http://burtleburtle.net/bob/hash/doobs.html).
|
*
|
||||||
|
* Keys are computed from Entry objects. Entry must be fully ordered by a member:
|
||||||
|
* int compare(const GrTBinHashKey<Entry, ..>& k);
|
||||||
|
* which returns negative if the Entry < k, 0 if it equals k, and positive if k < the Entry.
|
||||||
|
* Additionally, Entry must be flattenable into the key using setKeyData.
|
||||||
|
*
|
||||||
|
* This class satisfies the requirements to be a key for a GrTHashTable.
|
||||||
*/
|
*/
|
||||||
template<typename Entry, size_t KeySize>
|
template<typename Entry, size_t KeySize>
|
||||||
class GrBinHashKey {
|
class GrTBinHashKey {
|
||||||
public:
|
public:
|
||||||
GrBinHashKey()
|
GrTBinHashKey() {
|
||||||
: fHash(0)
|
this->reset();
|
||||||
#if GR_DEBUG
|
}
|
||||||
, fIsValid(false)
|
|
||||||
#endif
|
|
||||||
{}
|
|
||||||
|
|
||||||
GrBinHashKey(const GrBinHashKey<Entry, KeySize>& other) {
|
GrTBinHashKey(const GrTBinHashKey<Entry, KeySize>& other) {
|
||||||
*this = other;
|
*this = other;
|
||||||
}
|
}
|
||||||
GrBinHashKey<Entry, KeySize>& operator=(const GrBinHashKey<Entry,
|
|
||||||
KeySize>& other) {
|
GrTBinHashKey<Entry, KeySize>& operator=(const GrTBinHashKey<Entry, KeySize>& other) {
|
||||||
memcpy(this, &other, sizeof(*this));
|
memcpy(this, &other, sizeof(*this));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~GrBinHashKey() {
|
~GrTBinHashKey() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
fHash = 0;
|
||||||
|
#if GR_DEBUG
|
||||||
|
fIsValid = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void setKeyData(const uint32_t* SK_RESTRICT data) {
|
void setKeyData(const uint32_t* SK_RESTRICT data) {
|
||||||
|
@ -60,19 +70,17 @@ public:
|
||||||
fHash = hash;
|
fHash = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
int compare(const GrBinHashKey<Entry, KeySize>& key) const {
|
int compare(const GrTBinHashKey<Entry, KeySize>& key) const {
|
||||||
GrAssert(fIsValid && key.fIsValid);
|
GrAssert(fIsValid && key.fIsValid);
|
||||||
return memcmp(fData, key.fData, KeySize);
|
return memcmp(fData, key.fData, KeySize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool EQ(const Entry& entry, const GrTBinHashKey<Entry, KeySize>& key) {
|
||||||
EQ(const Entry& entry, const GrBinHashKey<Entry, KeySize>& key) {
|
|
||||||
GrAssert(key.fIsValid);
|
GrAssert(key.fIsValid);
|
||||||
return 0 == entry.compare(key);
|
return 0 == entry.compare(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool LT(const Entry& entry, const GrTBinHashKey<Entry, KeySize>& key) {
|
||||||
LT(const Entry& entry, const GrBinHashKey<Entry, KeySize>& key) {
|
|
||||||
GrAssert(key.fIsValid);
|
GrAssert(key.fIsValid);
|
||||||
return entry.compare(key) < 0;
|
return entry.compare(key) < 0;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +92,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t fHash;
|
uint32_t fHash;
|
||||||
uint8_t fData[KeySize]; //Buffer for key storage
|
uint8_t fData[KeySize]; // Buffer for key storage
|
||||||
|
|
||||||
#if GR_DEBUG
|
#if GR_DEBUG
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include "SkTrace.h"
|
#include "SkTrace.h"
|
||||||
#include "SkXfermode.h"
|
#include "SkXfermode.h"
|
||||||
|
|
||||||
|
SK_DEFINE_INST_COUNT(GrGLProgram)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -28,7 +30,7 @@ enum {
|
||||||
|
|
||||||
#define PRINT_SHADERS 0
|
#define PRINT_SHADERS 0
|
||||||
|
|
||||||
typedef GrGLProgram::ProgramDesc::StageDesc StageDesc;
|
typedef GrGLProgram::Desc::StageDesc StageDesc;
|
||||||
|
|
||||||
#define VIEW_MATRIX_NAME "uViewM"
|
#define VIEW_MATRIX_NAME "uViewM"
|
||||||
|
|
||||||
|
@ -95,18 +97,21 @@ GrGLProgram::GrGLProgram() {
|
||||||
}
|
}
|
||||||
|
|
||||||
GrGLProgram::~GrGLProgram() {
|
GrGLProgram::~GrGLProgram() {
|
||||||
|
for (int i = 0; i < GrDrawState::kNumStages; ++i) {
|
||||||
|
delete fProgramStage[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
|
void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
|
||||||
GrBlendCoeff* dstCoeff) const {
|
GrBlendCoeff* dstCoeff) const {
|
||||||
switch (fProgramDesc.fDualSrcOutput) {
|
switch (fDesc.fDualSrcOutput) {
|
||||||
case ProgramDesc::kNone_DualSrcOutput:
|
case Desc::kNone_DualSrcOutput:
|
||||||
break;
|
break;
|
||||||
// the prog will write a coverage value to the secondary
|
// the prog will write a coverage value to the secondary
|
||||||
// output and the dst is blended by one minus that value.
|
// output and the dst is blended by one minus that value.
|
||||||
case ProgramDesc::kCoverage_DualSrcOutput:
|
case Desc::kCoverage_DualSrcOutput:
|
||||||
case ProgramDesc::kCoverageISA_DualSrcOutput:
|
case Desc::kCoverageISA_DualSrcOutput:
|
||||||
case ProgramDesc::kCoverageISC_DualSrcOutput:
|
case Desc::kCoverageISC_DualSrcOutput:
|
||||||
*dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
|
*dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -281,17 +286,15 @@ static void addColorMatrix(SkString* fsCode, const char * outputVar,
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl,
|
void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl,
|
||||||
GrVertexLayout layout,
|
|
||||||
CachedData* programData,
|
|
||||||
SkString* coverageVar,
|
SkString* coverageVar,
|
||||||
GrGLShaderBuilder* segments) const {
|
GrGLShaderBuilder* segments) const {
|
||||||
if (layout & GrDrawTarget::kEdge_VertexLayoutBit) {
|
if (fDesc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit) {
|
||||||
const char *vsName, *fsName;
|
const char *vsName, *fsName;
|
||||||
segments->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName);
|
segments->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName);
|
||||||
segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
|
segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
|
||||||
GrGLShaderVar::kAttribute_TypeModifier, EDGE_ATTR_NAME);
|
GrGLShaderVar::kAttribute_TypeModifier, EDGE_ATTR_NAME);
|
||||||
segments->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
|
segments->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
|
||||||
switch (fProgramDesc.fVertexEdgeType) {
|
switch (fDesc.fVertexEdgeType) {
|
||||||
case GrDrawState::kHairLine_EdgeType:
|
case GrDrawState::kHairLine_EdgeType:
|
||||||
segments->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), %s.xyz));\n", fsName);
|
segments->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), %s.xyz));\n", fsName);
|
||||||
segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
|
segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
|
||||||
|
@ -345,32 +348,27 @@ void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
void GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) {
|
||||||
|
switch (fDesc.fColorInput) {
|
||||||
void genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput,
|
case GrGLProgram::Desc::kAttribute_ColorInput: {
|
||||||
GrGLProgram::CachedData* programData,
|
builder->fVSAttrs.push_back().set(kVec4f_GrSLType,
|
||||||
GrGLShaderBuilder* segments,
|
|
||||||
SkString* inColor) {
|
|
||||||
switch (colorInput) {
|
|
||||||
case GrGLProgram::ProgramDesc::kAttribute_ColorInput: {
|
|
||||||
segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
|
|
||||||
GrGLShaderVar::kAttribute_TypeModifier,
|
GrGLShaderVar::kAttribute_TypeModifier,
|
||||||
COL_ATTR_NAME);
|
COL_ATTR_NAME);
|
||||||
const char *vsName, *fsName;
|
const char *vsName, *fsName;
|
||||||
segments->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
|
builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
|
||||||
segments->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
|
builder->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
|
||||||
*inColor = fsName;
|
*inColor = fsName;
|
||||||
} break;
|
} break;
|
||||||
case GrGLProgram::ProgramDesc::kUniform_ColorInput:
|
case GrGLProgram::Desc::kUniform_ColorInput:
|
||||||
segments->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
||||||
kVec4f_GrSLType, COL_UNI_NAME);
|
kVec4f_GrSLType, COL_UNI_NAME);
|
||||||
programData->fUniLocations.fColorUni = kUseUniform;
|
fUniLocations.fColorUni = kUseUniform;
|
||||||
*inColor = COL_UNI_NAME;
|
*inColor = COL_UNI_NAME;
|
||||||
break;
|
break;
|
||||||
case GrGLProgram::ProgramDesc::kTransBlack_ColorInput:
|
case GrGLProgram::Desc::kTransBlack_ColorInput:
|
||||||
GrAssert(!"needComputedColor should be false.");
|
GrAssert(!"needComputedColor should be false.");
|
||||||
break;
|
break;
|
||||||
case GrGLProgram::ProgramDesc::kSolidWhite_ColorInput:
|
case GrGLProgram::Desc::kSolidWhite_ColorInput:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GrCrash("Unknown color type.");
|
GrCrash("Unknown color type.");
|
||||||
|
@ -378,8 +376,22 @@ void genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void genAttributeCoverage(GrGLShaderBuilder* segments,
|
void GrGLProgram::genUniformCoverage(GrGLShaderBuilder* builder, SkString* inOutCoverage) {
|
||||||
SkString* inOutCoverage) {
|
builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
||||||
|
kVec4f_GrSLType, COV_UNI_NAME);
|
||||||
|
fUniLocations.fCoverageUni = kUseUniform;
|
||||||
|
if (inOutCoverage->size()) {
|
||||||
|
builder->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n",
|
||||||
|
COV_UNI_NAME, inOutCoverage->c_str());
|
||||||
|
*inOutCoverage = "uniCoverage";
|
||||||
|
} else {
|
||||||
|
*inOutCoverage = COV_UNI_NAME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void gen_attribute_coverage(GrGLShaderBuilder* segments,
|
||||||
|
SkString* inOutCoverage) {
|
||||||
segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
|
segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
|
||||||
GrGLShaderVar::kAttribute_TypeModifier,
|
GrGLShaderVar::kAttribute_TypeModifier,
|
||||||
COV_ATTR_NAME);
|
COV_ATTR_NAME);
|
||||||
|
@ -394,35 +406,19 @@ void genAttributeCoverage(GrGLShaderBuilder* segments,
|
||||||
*inOutCoverage = fsName;
|
*inOutCoverage = fsName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void genUniformCoverage(GrGLShaderBuilder* segments,
|
|
||||||
GrGLProgram::CachedData* programData,
|
|
||||||
SkString* inOutCoverage) {
|
|
||||||
segments->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
|
||||||
kVec4f_GrSLType, COV_UNI_NAME);
|
|
||||||
programData->fUniLocations.fCoverageUni = kUseUniform;
|
|
||||||
if (inOutCoverage->size()) {
|
|
||||||
segments->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n",
|
|
||||||
COV_UNI_NAME, inOutCoverage->c_str());
|
|
||||||
*inOutCoverage = "uniCoverage";
|
|
||||||
} else {
|
|
||||||
*inOutCoverage = COV_UNI_NAME;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGLProgram::genGeometryShader(const GrGLContextInfo& gl,
|
void GrGLProgram::genGeometryShader(const GrGLContextInfo& gl,
|
||||||
GrGLShaderBuilder* segments) const {
|
GrGLShaderBuilder* segments) const {
|
||||||
#if GR_GL_EXPERIMENTAL_GS
|
#if GR_GL_EXPERIMENTAL_GS
|
||||||
if (fProgramDesc.fExperimentalGS) {
|
if (fDesc.fExperimentalGS) {
|
||||||
GrAssert(gl.glslGeneration() >= k150_GrGLSLGeneration);
|
GrAssert(gl.glslGeneration() >= k150_GrGLSLGeneration);
|
||||||
segments->fGSHeader.append("layout(triangles) in;\n"
|
segments->fGSHeader.append("layout(triangles) in;\n"
|
||||||
"layout(triangle_strip, max_vertices = 6) out;\n");
|
"layout(triangle_strip, max_vertices = 6) out;\n");
|
||||||
segments->fGSCode.append("void main() {\n"
|
segments->fGSCode.append("void main() {\n"
|
||||||
"\tfor (int i = 0; i < 3; ++i) {\n"
|
"\tfor (int i = 0; i < 3; ++i) {\n"
|
||||||
"\t\tgl_Position = gl_in[i].gl_Position;\n");
|
"\t\tgl_Position = gl_in[i].gl_Position;\n");
|
||||||
if (this->fProgramDesc.fEmitsPointSize) {
|
if (fDesc.fEmitsPointSize) {
|
||||||
segments->fGSCode.append("\t\tgl_PointSize = 1.0;\n");
|
segments->fGSCode.append("\t\tgl_PointSize = 1.0;\n");
|
||||||
}
|
}
|
||||||
GrAssert(segments->fGSInputs.count() == segments->fGSOutputs.count());
|
GrAssert(segments->fGSInputs.count() == segments->fGSOutputs.count());
|
||||||
|
@ -444,7 +440,7 @@ const char* GrGLProgram::adjustInColor(const SkString& inColor) const {
|
||||||
if (inColor.size()) {
|
if (inColor.size()) {
|
||||||
return inColor.c_str();
|
return inColor.c_str();
|
||||||
} else {
|
} else {
|
||||||
if (ProgramDesc::kSolidWhite_ColorInput == fProgramDesc.fColorInput) {
|
if (Desc::kSolidWhite_ColorInput == fDesc.fColorInput) {
|
||||||
return all_ones_vec(4);
|
return all_ones_vec(4);
|
||||||
} else {
|
} else {
|
||||||
return all_zeros_vec(4);
|
return all_zeros_vec(4);
|
||||||
|
@ -452,14 +448,6 @@ const char* GrGLProgram::adjustInColor(const SkString& inColor) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this destructor is in the header file, we must include GrGLProgramStage
|
|
||||||
// instead of just forward-declaring it.
|
|
||||||
GrGLProgram::CachedData::~CachedData() {
|
|
||||||
for (int i = 0; i < GrDrawState::kNumStages; ++i) {
|
|
||||||
delete fCustomStage[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
#define GL_CALL(X) GR_GL_CALL(gl.interface(), X)
|
#define GL_CALL(X) GR_GL_CALL(gl.interface(), X)
|
||||||
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gl.interface(), R, X)
|
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gl.interface(), R, X)
|
||||||
|
@ -524,10 +512,11 @@ GrGLuint compile_shader(const GrGLContextInfo& gl, GrGLenum type, const SkString
|
||||||
return compile_shader(gl, type, 1, &str, &length);
|
return compile_shader(gl, type, 1, &str, &length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compiles all the shaders from builder and stores the shader IDs in programData.
|
}
|
||||||
bool compile_shaders(const GrGLContextInfo& gl,
|
|
||||||
const GrGLShaderBuilder& builder,
|
// compiles all the shaders from builder and stores the shader IDs
|
||||||
GrGLProgram::CachedData* programData) {
|
bool GrGLProgram::compileShaders(const GrGLContextInfo& gl,
|
||||||
|
const GrGLShaderBuilder& builder) {
|
||||||
|
|
||||||
SkString shader;
|
SkString shader;
|
||||||
|
|
||||||
|
@ -536,7 +525,7 @@ bool compile_shaders(const GrGLContextInfo& gl,
|
||||||
GrPrintf(shader.c_str());
|
GrPrintf(shader.c_str());
|
||||||
GrPrintf("\n");
|
GrPrintf("\n");
|
||||||
#endif
|
#endif
|
||||||
if (!(programData->fVShaderID = compile_shader(gl, GR_GL_VERTEX_SHADER, shader))) {
|
if (!(fVShaderID = compile_shader(gl, GR_GL_VERTEX_SHADER, shader))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,11 +535,11 @@ bool compile_shaders(const GrGLContextInfo& gl,
|
||||||
GrPrintf(shader.c_str());
|
GrPrintf(shader.c_str());
|
||||||
GrPrintf("\n");
|
GrPrintf("\n");
|
||||||
#endif
|
#endif
|
||||||
if (!(programData->fGShaderID = compile_shader(gl, GR_GL_GEOMETRY_SHADER, shader))) {
|
if (!(fGShaderID = compile_shader(gl, GR_GL_GEOMETRY_SHADER, shader))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
programData->fGShaderID = 0;
|
fGShaderID = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader);
|
builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader);
|
||||||
|
@ -558,34 +547,34 @@ bool compile_shaders(const GrGLContextInfo& gl,
|
||||||
GrPrintf(shader.c_str());
|
GrPrintf(shader.c_str());
|
||||||
GrPrintf("\n");
|
GrPrintf("\n");
|
||||||
#endif
|
#endif
|
||||||
if (!(programData->fFShaderID = compile_shader(gl, GR_GL_FRAGMENT_SHADER, shader))) {
|
if (!(fFShaderID = compile_shader(gl, GR_GL_FRAGMENT_SHADER, shader))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
GrCustomStage** customStages,
|
const Desc& desc,
|
||||||
GrGLProgram::CachedData* programData) const {
|
GrCustomStage** customStages) {
|
||||||
|
fDesc = desc;
|
||||||
GrGLShaderBuilder builder(gl);
|
GrGLShaderBuilder builder(gl);
|
||||||
const uint32_t& layout = fProgramDesc.fVertexLayout;
|
const uint32_t& layout = fDesc.fVertexLayout;
|
||||||
|
|
||||||
programData->fUniLocations.reset();
|
fUniLocations.reset();
|
||||||
|
|
||||||
#if GR_GL_EXPERIMENTAL_GS
|
#if GR_GL_EXPERIMENTAL_GS
|
||||||
builder.fUsesGS = fProgramDesc.fExperimentalGS;
|
builder.fUsesGS = fDesc.fExperimentalGS;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SkXfermode::Coeff colorCoeff, uniformCoeff;
|
SkXfermode::Coeff colorCoeff, uniformCoeff;
|
||||||
bool applyColorMatrix = SkToBool(fProgramDesc.fColorMatrixEnabled);
|
bool applyColorMatrix = SkToBool(fDesc.fColorMatrixEnabled);
|
||||||
// The rest of transfer mode color filters have not been implemented
|
// The rest of transfer mode color filters have not been implemented
|
||||||
if (fProgramDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) {
|
if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) {
|
||||||
GR_DEBUGCODE(bool success =)
|
GR_DEBUGCODE(bool success =)
|
||||||
SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode>
|
SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode>
|
||||||
(fProgramDesc.fColorFilterXfermode),
|
(fDesc.fColorFilterXfermode),
|
||||||
&uniformCoeff, &colorCoeff);
|
&uniformCoeff, &colorCoeff);
|
||||||
GR_DEBUGASSERT(success);
|
GR_DEBUGASSERT(success);
|
||||||
} else {
|
} else {
|
||||||
|
@ -596,7 +585,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
// no need to do the color filter / matrix at all if coverage is 0. The
|
// no need to do the color filter / matrix at all if coverage is 0. The
|
||||||
// output color is scaled by the coverage. All the dual source outputs are
|
// output color is scaled by the coverage. All the dual source outputs are
|
||||||
// scaled by the coverage as well.
|
// scaled by the coverage as well.
|
||||||
if (ProgramDesc::kTransBlack_ColorInput == fProgramDesc.fCoverageInput) {
|
if (Desc::kTransBlack_ColorInput == fDesc.fCoverageInput) {
|
||||||
colorCoeff = SkXfermode::kZero_Coeff;
|
colorCoeff = SkXfermode::kZero_Coeff;
|
||||||
uniformCoeff = SkXfermode::kZero_Coeff;
|
uniformCoeff = SkXfermode::kZero_Coeff;
|
||||||
applyColorMatrix = false;
|
applyColorMatrix = false;
|
||||||
|
@ -605,7 +594,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
// If we know the final color is going to be all zeros then we can
|
// If we know the final color is going to be all zeros then we can
|
||||||
// simplify the color filter coeffecients. needComputedColor will then
|
// simplify the color filter coeffecients. needComputedColor will then
|
||||||
// come out false below.
|
// come out false below.
|
||||||
if (ProgramDesc::kTransBlack_ColorInput == fProgramDesc.fColorInput) {
|
if (Desc::kTransBlack_ColorInput == fDesc.fColorInput) {
|
||||||
colorCoeff = SkXfermode::kZero_Coeff;
|
colorCoeff = SkXfermode::kZero_Coeff;
|
||||||
if (SkXfermode::kDC_Coeff == uniformCoeff ||
|
if (SkXfermode::kDC_Coeff == uniformCoeff ||
|
||||||
SkXfermode::kDA_Coeff == uniformCoeff) {
|
SkXfermode::kDA_Coeff == uniformCoeff) {
|
||||||
|
@ -637,7 +626,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
|
|
||||||
builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType,
|
builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType,
|
||||||
kMat33f_GrSLType, VIEW_MATRIX_NAME);
|
kMat33f_GrSLType, VIEW_MATRIX_NAME);
|
||||||
programData->fUniLocations.fViewMatrixUni = kUseUniform;
|
fUniLocations.fViewMatrixUni = kUseUniform;
|
||||||
|
|
||||||
builder.fVSAttrs.push_back().set(kVec2f_GrSLType,
|
builder.fVSAttrs.push_back().set(kVec2f_GrSLType,
|
||||||
GrGLShaderVar::kAttribute_TypeModifier,
|
GrGLShaderVar::kAttribute_TypeModifier,
|
||||||
|
@ -651,12 +640,11 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
SkString inColor;
|
SkString inColor;
|
||||||
|
|
||||||
if (needComputedColor) {
|
if (needComputedColor) {
|
||||||
genInputColor((ProgramDesc::ColorInput) fProgramDesc.fColorInput,
|
this->genInputColor(&builder, &inColor);
|
||||||
programData, &builder, &inColor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we output point size in the GS if present
|
// we output point size in the GS if present
|
||||||
if (fProgramDesc.fEmitsPointSize && !builder.fUsesGS){
|
if (fDesc.fEmitsPointSize && !builder.fUsesGS){
|
||||||
builder.fVSCode.append("\tgl_PointSize = 1.0;\n");
|
builder.fVSCode.append("\tgl_PointSize = 1.0;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,7 +667,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
// uses of programData, but it's safest to do so below when we're *sure*
|
// uses of programData, but it's safest to do so below when we're *sure*
|
||||||
// we need them.
|
// we need them.
|
||||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||||
programData->fCustomStage[s] = NULL;
|
fProgramStage[s] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -689,8 +677,8 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
// of each to the next and generating code for each stage.
|
// of each to the next and generating code for each stage.
|
||||||
if (needComputedColor) {
|
if (needComputedColor) {
|
||||||
SkString outColor;
|
SkString outColor;
|
||||||
for (int s = 0; s < fProgramDesc.fFirstCoverageStage; ++s) {
|
for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) {
|
||||||
if (fProgramDesc.fStages[s].isEnabled()) {
|
if (fDesc.fStages[s].isEnabled()) {
|
||||||
// create var to hold stage result
|
// create var to hold stage result
|
||||||
outColor = "color";
|
outColor = "color";
|
||||||
outColor.appendS32(s);
|
outColor.appendS32(s);
|
||||||
|
@ -708,20 +696,15 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL != customStages[s]) {
|
if (NULL != customStages[s]) {
|
||||||
const GrProgramStageFactory& factory =
|
const GrProgramStageFactory& factory = customStages[s]->getFactory();
|
||||||
customStages[s]->getFactory();
|
fProgramStage[s] = factory.createGLInstance(*customStages[s]);
|
||||||
programData->fCustomStage[s] =
|
|
||||||
factory.createGLInstance(*customStages[s]);
|
|
||||||
}
|
}
|
||||||
this->genStageCode(gl,
|
this->genStageCode(gl,
|
||||||
s,
|
s,
|
||||||
fProgramDesc.fStages[s],
|
|
||||||
inColor.size() ? inColor.c_str() : NULL,
|
inColor.size() ? inColor.c_str() : NULL,
|
||||||
outColor.c_str(),
|
outColor.c_str(),
|
||||||
inCoords,
|
inCoords,
|
||||||
&builder,
|
&builder);
|
||||||
&programData->fUniLocations.fStages[s],
|
|
||||||
programData->fCustomStage[s]);
|
|
||||||
inColor = outColor;
|
inColor = outColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -730,7 +713,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
// if have all ones or zeros for the "dst" input to the color filter then we
|
// if have all ones or zeros for the "dst" input to the color filter then we
|
||||||
// may be able to make additional optimizations.
|
// may be able to make additional optimizations.
|
||||||
if (needColorFilterUniform && needComputedColor && !inColor.size()) {
|
if (needColorFilterUniform && needComputedColor && !inColor.size()) {
|
||||||
GrAssert(ProgramDesc::kSolidWhite_ColorInput == fProgramDesc.fColorInput);
|
GrAssert(Desc::kSolidWhite_ColorInput == fDesc.fColorInput);
|
||||||
bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff ||
|
bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff ||
|
||||||
SkXfermode::kIDA_Coeff == uniformCoeff;
|
SkXfermode::kIDA_Coeff == uniformCoeff;
|
||||||
if (uniformCoeffIsZero) {
|
if (uniformCoeffIsZero) {
|
||||||
|
@ -743,7 +726,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
if (needColorFilterUniform) {
|
if (needColorFilterUniform) {
|
||||||
builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
||||||
kVec4f_GrSLType, COL_FILTER_UNI_NAME);
|
kVec4f_GrSLType, COL_FILTER_UNI_NAME);
|
||||||
programData->fUniLocations.fColorFilterUni = kUseUniform;
|
fUniLocations.fColorFilterUni = kUseUniform;
|
||||||
}
|
}
|
||||||
bool wroteFragColorZero = false;
|
bool wroteFragColorZero = false;
|
||||||
if (SkXfermode::kZero_Coeff == uniformCoeff &&
|
if (SkXfermode::kZero_Coeff == uniformCoeff &&
|
||||||
|
@ -753,7 +736,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
colorOutput.getName().c_str(),
|
colorOutput.getName().c_str(),
|
||||||
all_zeros_vec(4));
|
all_zeros_vec(4));
|
||||||
wroteFragColorZero = true;
|
wroteFragColorZero = true;
|
||||||
} else if (SkXfermode::kDst_Mode != fProgramDesc.fColorFilterXfermode) {
|
} else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) {
|
||||||
builder.fFSCode.append("\tvec4 filteredColor;\n");
|
builder.fFSCode.append("\tvec4 filteredColor;\n");
|
||||||
const char* color = adjustInColor(inColor);
|
const char* color = adjustInColor(inColor);
|
||||||
addColorFilter(&builder.fFSCode, "filteredColor", uniformCoeff,
|
addColorFilter(&builder.fFSCode, "filteredColor", uniformCoeff,
|
||||||
|
@ -765,8 +748,8 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
kMat44f_GrSLType, COL_MATRIX_UNI_NAME);
|
kMat44f_GrSLType, COL_MATRIX_UNI_NAME);
|
||||||
builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
||||||
kVec4f_GrSLType, COL_MATRIX_VEC_UNI_NAME);
|
kVec4f_GrSLType, COL_MATRIX_VEC_UNI_NAME);
|
||||||
programData->fUniLocations.fColorMatrixUni = kUseUniform;
|
fUniLocations.fColorMatrixUni = kUseUniform;
|
||||||
programData->fUniLocations.fColorMatrixVecUni = kUseUniform;
|
fUniLocations.fColorMatrixVecUni = kUseUniform;
|
||||||
builder.fFSCode.append("\tvec4 matrixedColor;\n");
|
builder.fFSCode.append("\tvec4 matrixedColor;\n");
|
||||||
const char* color = adjustInColor(inColor);
|
const char* color = adjustInColor(inColor);
|
||||||
addColorMatrix(&builder.fFSCode, "matrixedColor", color);
|
addColorMatrix(&builder.fFSCode, "matrixedColor", color);
|
||||||
|
@ -777,34 +760,32 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
// compute the partial coverage (coverage stages and edge aa)
|
// compute the partial coverage (coverage stages and edge aa)
|
||||||
|
|
||||||
SkString inCoverage;
|
SkString inCoverage;
|
||||||
bool coverageIsZero = ProgramDesc::kTransBlack_ColorInput ==
|
bool coverageIsZero = Desc::kTransBlack_ColorInput == fDesc.fCoverageInput;
|
||||||
fProgramDesc.fCoverageInput;
|
|
||||||
// we don't need to compute coverage at all if we know the final shader
|
// we don't need to compute coverage at all if we know the final shader
|
||||||
// output will be zero and we don't have a dual src blend output.
|
// output will be zero and we don't have a dual src blend output.
|
||||||
if (!wroteFragColorZero ||
|
if (!wroteFragColorZero || Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
|
||||||
ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
|
|
||||||
|
|
||||||
if (!coverageIsZero) {
|
if (!coverageIsZero) {
|
||||||
this->genEdgeCoverage(gl, layout, programData, &inCoverage, &builder);
|
this->genEdgeCoverage(gl, &inCoverage, &builder);
|
||||||
|
|
||||||
switch (fProgramDesc.fCoverageInput) {
|
switch (fDesc.fCoverageInput) {
|
||||||
case ProgramDesc::kSolidWhite_ColorInput:
|
case Desc::kSolidWhite_ColorInput:
|
||||||
// empty string implies solid white
|
// empty string implies solid white
|
||||||
break;
|
break;
|
||||||
case ProgramDesc::kAttribute_ColorInput:
|
case Desc::kAttribute_ColorInput:
|
||||||
genAttributeCoverage(&builder, &inCoverage);
|
gen_attribute_coverage(&builder, &inCoverage);
|
||||||
break;
|
break;
|
||||||
case ProgramDesc::kUniform_ColorInput:
|
case Desc::kUniform_ColorInput:
|
||||||
genUniformCoverage(&builder, programData, &inCoverage);
|
this->genUniformCoverage(&builder, &inCoverage);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GrCrash("Unexpected input coverage.");
|
GrCrash("Unexpected input coverage.");
|
||||||
}
|
}
|
||||||
|
|
||||||
SkString outCoverage;
|
SkString outCoverage;
|
||||||
const int& startStage = fProgramDesc.fFirstCoverageStage;
|
const int& startStage = fDesc.fFirstCoverageStage;
|
||||||
for (int s = startStage; s < GrDrawState::kNumStages; ++s) {
|
for (int s = startStage; s < GrDrawState::kNumStages; ++s) {
|
||||||
if (fProgramDesc.fStages[s].isEnabled()) {
|
if (fDesc.fStages[s].isEnabled()) {
|
||||||
// create var to hold stage output
|
// create var to hold stage output
|
||||||
outCoverage = "coverage";
|
outCoverage = "coverage";
|
||||||
outCoverage.appendS32(s);
|
outCoverage.appendS32(s);
|
||||||
|
@ -825,37 +806,31 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL != customStages[s]) {
|
if (NULL != customStages[s]) {
|
||||||
const GrProgramStageFactory& factory =
|
const GrProgramStageFactory& factory = customStages[s]->getFactory();
|
||||||
customStages[s]->getFactory();
|
fProgramStage[s] = factory.createGLInstance(*customStages[s]);
|
||||||
programData->fCustomStage[s] =
|
|
||||||
factory.createGLInstance(*customStages[s]);
|
|
||||||
}
|
}
|
||||||
this->genStageCode(gl, s,
|
this->genStageCode(gl,
|
||||||
fProgramDesc.fStages[s],
|
s,
|
||||||
inCoverage.size() ? inCoverage.c_str() : NULL,
|
inCoverage.size() ? inCoverage.c_str() : NULL,
|
||||||
outCoverage.c_str(),
|
outCoverage.c_str(),
|
||||||
inCoords,
|
inCoords,
|
||||||
&builder,
|
&builder);
|
||||||
&programData->fUniLocations.fStages[s],
|
|
||||||
programData->fCustomStage[s]);
|
|
||||||
inCoverage = outCoverage;
|
inCoverage = outCoverage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
|
if (Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
|
||||||
builder.fFSOutputs.push_back().set(kVec4f_GrSLType,
|
builder.fFSOutputs.push_back().set(kVec4f_GrSLType,
|
||||||
GrGLShaderVar::kOut_TypeModifier,
|
GrGLShaderVar::kOut_TypeModifier,
|
||||||
dual_source_output_name());
|
dual_source_output_name());
|
||||||
bool outputIsZero = coverageIsZero;
|
bool outputIsZero = coverageIsZero;
|
||||||
SkString coeff;
|
SkString coeff;
|
||||||
if (!outputIsZero &&
|
if (!outputIsZero &&
|
||||||
ProgramDesc::kCoverage_DualSrcOutput !=
|
Desc::kCoverage_DualSrcOutput != fDesc.fDualSrcOutput && !wroteFragColorZero) {
|
||||||
fProgramDesc.fDualSrcOutput && !wroteFragColorZero) {
|
|
||||||
if (!inColor.size()) {
|
if (!inColor.size()) {
|
||||||
outputIsZero = true;
|
outputIsZero = true;
|
||||||
} else {
|
} else {
|
||||||
if (fProgramDesc.fDualSrcOutput ==
|
if (Desc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) {
|
||||||
ProgramDesc::kCoverageISA_DualSrcOutput) {
|
|
||||||
coeff.printf("(1 - %s.a)", inColor.c_str());
|
coeff.printf("(1 - %s.a)", inColor.c_str());
|
||||||
} else {
|
} else {
|
||||||
coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str());
|
coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str());
|
||||||
|
@ -890,16 +865,14 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
inCoverage.c_str(),
|
inCoverage.c_str(),
|
||||||
&builder.fFSCode);
|
&builder.fFSCode);
|
||||||
}
|
}
|
||||||
if (ProgramDesc::kUnpremultiplied_RoundDown_OutputConfig ==
|
if (Desc::kUnpremultiplied_RoundDown_OutputConfig == fDesc.fOutputConfig) {
|
||||||
fProgramDesc.fOutputConfig) {
|
|
||||||
builder.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n",
|
builder.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n",
|
||||||
colorOutput.getName().c_str(),
|
colorOutput.getName().c_str(),
|
||||||
colorOutput.getName().c_str(),
|
colorOutput.getName().c_str(),
|
||||||
colorOutput.getName().c_str(),
|
colorOutput.getName().c_str(),
|
||||||
colorOutput.getName().c_str(),
|
colorOutput.getName().c_str(),
|
||||||
colorOutput.getName().c_str());
|
colorOutput.getName().c_str());
|
||||||
} else if (ProgramDesc::kUnpremultiplied_RoundUp_OutputConfig ==
|
} else if (Desc::kUnpremultiplied_RoundUp_OutputConfig == fDesc.fOutputConfig) {
|
||||||
fProgramDesc.fOutputConfig) {
|
|
||||||
builder.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n",
|
builder.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n",
|
||||||
colorOutput.getName().c_str(),
|
colorOutput.getName().c_str(),
|
||||||
colorOutput.getName().c_str(),
|
colorOutput.getName().c_str(),
|
||||||
|
@ -921,132 +894,124 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// compile and setup attribs and unis
|
// compile and setup attribs and unis
|
||||||
|
|
||||||
if (!compile_shaders(gl, builder, programData)) {
|
if (!this->compileShaders(gl, builder)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->bindOutputsAttribsAndLinkProgram(gl, texCoordAttrs,
|
if (!this->bindOutputsAttribsAndLinkProgram(gl,
|
||||||
|
texCoordAttrs,
|
||||||
isColorDeclared,
|
isColorDeclared,
|
||||||
dualSourceOutputWritten,
|
dualSourceOutputWritten)) {
|
||||||
programData)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->getUniformLocationsAndInitCache(builder, gl, programData);
|
this->getUniformLocationsAndInitCache(gl, builder);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLContextInfo& gl,
|
bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLContextInfo& gl,
|
||||||
SkString texCoordAttrNames[],
|
SkString texCoordAttrNames[],
|
||||||
bool bindColorOut,
|
bool bindColorOut,
|
||||||
bool bindDualSrcOut,
|
bool bindDualSrcOut) {
|
||||||
CachedData* programData) const {
|
GL_CALL_RET(fProgramID, CreateProgram());
|
||||||
GL_CALL_RET(programData->fProgramID, CreateProgram());
|
if (!fProgramID) {
|
||||||
if (!programData->fProgramID) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const GrGLint& progID = programData->fProgramID;
|
|
||||||
|
|
||||||
GL_CALL(AttachShader(progID, programData->fVShaderID));
|
GL_CALL(AttachShader(fProgramID, fVShaderID));
|
||||||
if (programData->fGShaderID) {
|
if (fGShaderID) {
|
||||||
GL_CALL(AttachShader(progID, programData->fGShaderID));
|
GL_CALL(AttachShader(fProgramID, fGShaderID));
|
||||||
}
|
}
|
||||||
GL_CALL(AttachShader(progID, programData->fFShaderID));
|
GL_CALL(AttachShader(fProgramID, fFShaderID));
|
||||||
|
|
||||||
if (bindColorOut) {
|
if (bindColorOut) {
|
||||||
GL_CALL(BindFragDataLocation(programData->fProgramID,
|
GL_CALL(BindFragDataLocation(fProgramID, 0, declared_color_output_name()));
|
||||||
0, declared_color_output_name()));
|
|
||||||
}
|
}
|
||||||
if (bindDualSrcOut) {
|
if (bindDualSrcOut) {
|
||||||
GL_CALL(BindFragDataLocationIndexed(programData->fProgramID,
|
GL_CALL(BindFragDataLocationIndexed(fProgramID, 0, 1, dual_source_output_name()));
|
||||||
0, 1, dual_source_output_name()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind the attrib locations to same values for all shaders
|
// Bind the attrib locations to same values for all shaders
|
||||||
GL_CALL(BindAttribLocation(progID, PositionAttributeIdx(), POS_ATTR_NAME));
|
GL_CALL(BindAttribLocation(fProgramID, PositionAttributeIdx(), POS_ATTR_NAME));
|
||||||
for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
|
for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
|
||||||
if (texCoordAttrNames[t].size()) {
|
if (texCoordAttrNames[t].size()) {
|
||||||
GL_CALL(BindAttribLocation(progID,
|
GL_CALL(BindAttribLocation(fProgramID,
|
||||||
TexCoordAttributeIdx(t),
|
TexCoordAttributeIdx(t),
|
||||||
texCoordAttrNames[t].c_str()));
|
texCoordAttrNames[t].c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_CALL(BindAttribLocation(progID, ColorAttributeIdx(), COL_ATTR_NAME));
|
GL_CALL(BindAttribLocation(fProgramID, ColorAttributeIdx(), COL_ATTR_NAME));
|
||||||
GL_CALL(BindAttribLocation(progID, CoverageAttributeIdx(), COV_ATTR_NAME));
|
GL_CALL(BindAttribLocation(fProgramID, CoverageAttributeIdx(), COV_ATTR_NAME));
|
||||||
GL_CALL(BindAttribLocation(progID, EdgeAttributeIdx(), EDGE_ATTR_NAME));
|
GL_CALL(BindAttribLocation(fProgramID, EdgeAttributeIdx(), EDGE_ATTR_NAME));
|
||||||
|
|
||||||
GL_CALL(LinkProgram(progID));
|
GL_CALL(LinkProgram(fProgramID));
|
||||||
|
|
||||||
GrGLint linked = GR_GL_INIT_ZERO;
|
GrGLint linked = GR_GL_INIT_ZERO;
|
||||||
GL_CALL(GetProgramiv(progID, GR_GL_LINK_STATUS, &linked));
|
GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked));
|
||||||
if (!linked) {
|
if (!linked) {
|
||||||
GrGLint infoLen = GR_GL_INIT_ZERO;
|
GrGLint infoLen = GR_GL_INIT_ZERO;
|
||||||
GL_CALL(GetProgramiv(progID, GR_GL_INFO_LOG_LENGTH, &infoLen));
|
GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
|
||||||
SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
|
SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
|
||||||
if (infoLen > 0) {
|
if (infoLen > 0) {
|
||||||
// retrieve length even though we don't need it to workaround
|
// retrieve length even though we don't need it to workaround
|
||||||
// bug in chrome cmd buffer param validation.
|
// bug in chrome cmd buffer param validation.
|
||||||
GrGLsizei length = GR_GL_INIT_ZERO;
|
GrGLsizei length = GR_GL_INIT_ZERO;
|
||||||
GL_CALL(GetProgramInfoLog(progID,
|
GL_CALL(GetProgramInfoLog(fProgramID,
|
||||||
infoLen+1,
|
infoLen+1,
|
||||||
&length,
|
&length,
|
||||||
(char*)log.get()));
|
(char*)log.get()));
|
||||||
GrPrintf((char*)log.get());
|
GrPrintf((char*)log.get());
|
||||||
}
|
}
|
||||||
GrAssert(!"Error linking program");
|
GrAssert(!"Error linking program");
|
||||||
GL_CALL(DeleteProgram(progID));
|
GL_CALL(DeleteProgram(fProgramID));
|
||||||
programData->fProgramID = 0;
|
fProgramID = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& builder,
|
void GrGLProgram::getUniformLocationsAndInitCache(const GrGLContextInfo& gl,
|
||||||
const GrGLContextInfo& gl,
|
const GrGLShaderBuilder& builder) {
|
||||||
CachedData* programData) const {
|
|
||||||
const GrGLint& progID = programData->fProgramID;
|
|
||||||
|
|
||||||
if (kUseUniform == programData->fUniLocations.fViewMatrixUni) {
|
if (kUseUniform == fUniLocations.fViewMatrixUni) {
|
||||||
GL_CALL_RET(programData->fUniLocations.fViewMatrixUni,
|
GL_CALL_RET(fUniLocations.fViewMatrixUni, GetUniformLocation(fProgramID, VIEW_MATRIX_NAME));
|
||||||
GetUniformLocation(progID, VIEW_MATRIX_NAME));
|
GrAssert(kUnusedUniform != fUniLocations.fViewMatrixUni);
|
||||||
GrAssert(kUnusedUniform != programData->fUniLocations.fViewMatrixUni);
|
|
||||||
}
|
}
|
||||||
if (kUseUniform == programData->fUniLocations.fColorUni) {
|
if (kUseUniform == fUniLocations.fColorUni) {
|
||||||
GL_CALL_RET(programData->fUniLocations.fColorUni,
|
GL_CALL_RET(fUniLocations.fColorUni, GetUniformLocation(fProgramID, COL_UNI_NAME));
|
||||||
GetUniformLocation(progID, COL_UNI_NAME));
|
GrAssert(kUnusedUniform != fUniLocations.fColorUni);
|
||||||
GrAssert(kUnusedUniform != programData->fUniLocations.fColorUni);
|
|
||||||
}
|
}
|
||||||
if (kUseUniform == programData->fUniLocations.fColorFilterUni) {
|
if (kUseUniform == fUniLocations.fColorFilterUni) {
|
||||||
GL_CALL_RET(programData->fUniLocations.fColorFilterUni,
|
GL_CALL_RET(fUniLocations.fColorFilterUni,
|
||||||
GetUniformLocation(progID, COL_FILTER_UNI_NAME));
|
GetUniformLocation(fProgramID, COL_FILTER_UNI_NAME));
|
||||||
GrAssert(kUnusedUniform != programData->fUniLocations.fColorFilterUni);
|
GrAssert(kUnusedUniform != fUniLocations.fColorFilterUni);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kUseUniform == programData->fUniLocations.fColorMatrixUni) {
|
if (kUseUniform == fUniLocations.fColorMatrixUni) {
|
||||||
GL_CALL_RET(programData->fUniLocations.fColorMatrixUni,
|
GL_CALL_RET(fUniLocations.fColorMatrixUni,
|
||||||
GetUniformLocation(progID, COL_MATRIX_UNI_NAME));
|
GetUniformLocation(fProgramID, COL_MATRIX_UNI_NAME));
|
||||||
|
GrAssert(kUnusedUniform != fUniLocations.fColorMatrixUni);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kUseUniform == programData->fUniLocations.fColorMatrixVecUni) {
|
if (kUseUniform == fUniLocations.fColorMatrixVecUni) {
|
||||||
GL_CALL_RET(programData->fUniLocations.fColorMatrixVecUni,
|
GL_CALL_RET(fUniLocations.fColorMatrixVecUni,
|
||||||
GetUniformLocation(progID, COL_MATRIX_VEC_UNI_NAME));
|
GetUniformLocation(fProgramID, COL_MATRIX_VEC_UNI_NAME));
|
||||||
|
GrAssert(kUnusedUniform != fUniLocations.fColorMatrixVecUni);
|
||||||
}
|
}
|
||||||
if (kUseUniform == programData->fUniLocations.fCoverageUni) {
|
if (kUseUniform == fUniLocations.fCoverageUni) {
|
||||||
GL_CALL_RET(programData->fUniLocations.fCoverageUni,
|
GrAssert(kUnusedUniform != fUniLocations.fCoverageUni);
|
||||||
GetUniformLocation(progID, COV_UNI_NAME));
|
|
||||||
GrAssert(kUnusedUniform != programData->fUniLocations.fCoverageUni);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||||
StageUniLocations& locations = programData->fUniLocations.fStages[s];
|
StageUniLocations& locations = fUniLocations.fStages[s];
|
||||||
if (fProgramDesc.fStages[s].isEnabled()) {
|
if (fDesc.fStages[s].isEnabled()) {
|
||||||
if (kUseUniform == locations.fTextureMatrixUni) {
|
if (kUseUniform == locations.fTextureMatrixUni) {
|
||||||
SkString texMName;
|
SkString texMName;
|
||||||
tex_matrix_name(s, &texMName);
|
tex_matrix_name(s, &texMName);
|
||||||
GL_CALL_RET(locations.fTextureMatrixUni,
|
GL_CALL_RET(locations.fTextureMatrixUni,
|
||||||
GetUniformLocation(progID, texMName.c_str()));
|
GetUniformLocation(fProgramID, texMName.c_str()));
|
||||||
GrAssert(kUnusedUniform != locations.fTextureMatrixUni);
|
GrAssert(kUnusedUniform != locations.fTextureMatrixUni);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1054,7 +1019,7 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& build
|
||||||
SkString samplerName;
|
SkString samplerName;
|
||||||
sampler_name(s, &samplerName);
|
sampler_name(s, &samplerName);
|
||||||
GL_CALL_RET(locations.fSamplerUni,
|
GL_CALL_RET(locations.fSamplerUni,
|
||||||
GetUniformLocation(progID,samplerName.c_str()));
|
GetUniformLocation(fProgramID,samplerName.c_str()));
|
||||||
GrAssert(kUnusedUniform != locations.fSamplerUni);
|
GrAssert(kUnusedUniform != locations.fSamplerUni);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1062,33 +1027,32 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& build
|
||||||
SkString texDomName;
|
SkString texDomName;
|
||||||
tex_domain_name(s, &texDomName);
|
tex_domain_name(s, &texDomName);
|
||||||
GL_CALL_RET(locations.fTexDomUni,
|
GL_CALL_RET(locations.fTexDomUni,
|
||||||
GetUniformLocation(progID, texDomName.c_str()));
|
GetUniformLocation(fProgramID, texDomName.c_str()));
|
||||||
GrAssert(kUnusedUniform != locations.fTexDomUni);
|
GrAssert(kUnusedUniform != locations.fTexDomUni);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL != programData->fCustomStage[s]) {
|
if (NULL != fProgramStage[s]) {
|
||||||
programData->fCustomStage[s]->initUniforms(&builder, gl.interface(), progID);
|
fProgramStage[s]->initUniforms(&builder, gl.interface(), fProgramID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GL_CALL(UseProgram(progID));
|
GL_CALL(UseProgram(fProgramID));
|
||||||
|
|
||||||
// init sampler unis and set bogus values for state tracking
|
// init sampler unis and set bogus values for state tracking
|
||||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||||
if (kUnusedUniform != programData->fUniLocations.fStages[s].fSamplerUni) {
|
if (kUnusedUniform != fUniLocations.fStages[s].fSamplerUni) {
|
||||||
GL_CALL(Uniform1i(programData->fUniLocations.fStages[s].fSamplerUni, s));
|
GL_CALL(Uniform1i(fUniLocations.fStages[s].fSamplerUni, s));
|
||||||
}
|
}
|
||||||
programData->fTextureMatrices[s] = GrMatrix::InvalidMatrix();
|
fTextureMatrices[s] = GrMatrix::InvalidMatrix();
|
||||||
programData->fTextureDomain[s].setEmpty();
|
fTextureDomain[s].setEmpty();
|
||||||
// this is arbitrary, just initialize to something
|
// this is arbitrary, just initialize to something
|
||||||
programData->fTextureOrientation[s] =
|
fTextureOrientation[s] = GrGLTexture::kBottomUp_Orientation;
|
||||||
GrGLTexture::kBottomUp_Orientation;
|
|
||||||
// Must not reset fStageOverride[] here.
|
// Must not reset fStageOverride[] here.
|
||||||
}
|
}
|
||||||
programData->fViewMatrix = GrMatrix::InvalidMatrix();
|
fViewMatrix = GrMatrix::InvalidMatrix();
|
||||||
programData->fViewportSize.set(-1, -1);
|
fViewportSize.set(-1, -1);
|
||||||
programData->fColor = GrColor_ILLEGAL;
|
fColor = GrColor_ILLEGAL;
|
||||||
programData->fColorFilterColor = GrColor_ILLEGAL;
|
fColorFilterColor = GrColor_ILLEGAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1096,17 +1060,17 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& build
|
||||||
|
|
||||||
void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
|
void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
|
||||||
int stageNum,
|
int stageNum,
|
||||||
const GrGLProgram::StageDesc& desc,
|
|
||||||
const char* fsInColor, // NULL means no incoming color
|
const char* fsInColor, // NULL means no incoming color
|
||||||
const char* fsOutColor,
|
const char* fsOutColor,
|
||||||
const char* vsInCoord,
|
const char* vsInCoord,
|
||||||
GrGLShaderBuilder* segments,
|
GrGLShaderBuilder* segments) {
|
||||||
StageUniLocations* locations,
|
|
||||||
GrGLProgramStage* customStage) const {
|
|
||||||
|
|
||||||
GrAssert(stageNum >= 0 && stageNum <= GrDrawState::kNumStages);
|
GrAssert(stageNum >= 0 && stageNum <= GrDrawState::kNumStages);
|
||||||
GrAssert((desc.fInConfigFlags & StageDesc::kInConfigBitMask) ==
|
|
||||||
desc.fInConfigFlags);
|
const GrGLProgram::StageDesc& desc = fDesc.fStages[stageNum];
|
||||||
|
StageUniLocations& locations = fUniLocations.fStages[stageNum];
|
||||||
|
GrGLProgramStage* customStage = fProgramStage[stageNum];
|
||||||
|
|
||||||
|
GrAssert((desc.fInConfigFlags & StageDesc::kInConfigBitMask) == desc.fInConfigFlags);
|
||||||
|
|
||||||
/// Vertex Shader Stuff
|
/// Vertex Shader Stuff
|
||||||
|
|
||||||
|
@ -1124,7 +1088,7 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
|
||||||
const GrGLShaderVar& mat = segments->getUniformVariable(m);
|
const GrGLShaderVar& mat = segments->getUniformVariable(m);
|
||||||
// Can't use texMatName.c_str() because it's on the stack!
|
// Can't use texMatName.c_str() because it's on the stack!
|
||||||
matName = mat.getName().c_str();
|
matName = mat.getName().c_str();
|
||||||
locations->fTextureMatrixUni = kUseUniform;
|
locations.fTextureMatrixUni = kUseUniform;
|
||||||
|
|
||||||
if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
|
if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
|
||||||
segments->fVaryingDims = segments->fCoordDims;
|
segments->fVaryingDims = segments->fCoordDims;
|
||||||
|
@ -1143,14 +1107,14 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
|
||||||
sampler_name(stageNum, &samplerName);
|
sampler_name(stageNum, &samplerName);
|
||||||
segments->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
segments->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
||||||
kSampler2D_GrSLType, samplerName.c_str());
|
kSampler2D_GrSLType, samplerName.c_str());
|
||||||
locations->fSamplerUni = kUseUniform;
|
locations.fSamplerUni = kUseUniform;
|
||||||
|
|
||||||
const char *varyingVSName, *varyingFSName;
|
const char *varyingVSName, *varyingFSName;
|
||||||
segments->addVarying(GrSLFloatVectorType(segments->fVaryingDims),
|
segments->addVarying(GrSLFloatVectorType(segments->fVaryingDims),
|
||||||
"Stage",
|
"Stage",
|
||||||
stageNum,
|
stageNum,
|
||||||
&varyingVSName,
|
&varyingVSName,
|
||||||
&varyingFSName);
|
&varyingFSName);
|
||||||
|
|
||||||
if (!matName) {
|
if (!matName) {
|
||||||
GrAssert(segments->fVaryingDims == segments->fCoordDims);
|
GrAssert(segments->fVaryingDims == segments->fCoordDims);
|
||||||
|
@ -1203,7 +1167,7 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
|
||||||
texDomainName.c_str(),
|
texDomainName.c_str(),
|
||||||
texDomainName.c_str());
|
texDomainName.c_str());
|
||||||
segments->fSampleCoords = coordVar;
|
segments->fSampleCoords = coordVar;
|
||||||
locations->fTexDomUni = kUseUniform;
|
locations.fTexDomUni = kUseUniform;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: GrGLProgramStages are now responsible for fetching
|
// NOTE: GrGLProgramStages are now responsible for fetching
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include "GrGLContextInfo.h"
|
#include "GrGLContextInfo.h"
|
||||||
#include "GrGLSL.h"
|
#include "GrGLSL.h"
|
||||||
#include "GrGLTexture.h"
|
#include "GrGLTexture.h"
|
||||||
#include "GrGpu.h"
|
//#include "GrGpu.h"
|
||||||
|
|
||||||
#include "SkString.h"
|
#include "SkString.h"
|
||||||
#include "SkXfermode.h"
|
#include "SkXfermode.h"
|
||||||
|
@ -35,28 +35,29 @@ class GrGLShaderBuilder;
|
||||||
* Uniforms are program-local so we can't rely on fHWState to hold the
|
* Uniforms are program-local so we can't rely on fHWState to hold the
|
||||||
* previous uniform state after a program change.
|
* previous uniform state after a program change.
|
||||||
*/
|
*/
|
||||||
class GrGLProgram {
|
class GrGLProgram : public GrRefCnt {
|
||||||
public:
|
public:
|
||||||
|
SK_DECLARE_INST_COUNT(GrGLProgram)
|
||||||
|
|
||||||
class CachedData;
|
struct Desc;
|
||||||
|
|
||||||
GrGLProgram();
|
GrGLProgram();
|
||||||
~GrGLProgram();
|
virtual ~GrGLProgram();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the heavy initilization routine for building a GLProgram.
|
* This is the heavy initilization routine for building a GLProgram.
|
||||||
* The result of heavy init is not stored in datamembers of GrGLProgam,
|
|
||||||
* but in a separate cacheable container.
|
|
||||||
*/
|
*/
|
||||||
bool genProgram(const GrGLContextInfo& gl,
|
bool genProgram(const GrGLContextInfo& gl,
|
||||||
GrCustomStage** customStages,
|
const Desc& desc,
|
||||||
CachedData* programData) const;
|
GrCustomStage** customStages);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shader may modify the blend coeffecients. Params are in/out
|
* The shader may modify the blend coeffecients. Params are in/out
|
||||||
*/
|
*/
|
||||||
void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const;
|
void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const;
|
||||||
|
|
||||||
|
const Desc& getDesc() { return fDesc; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attribute indices. These should not overlap. Matrices consume 3 slots.
|
* Attribute indices. These should not overlap. Matrices consume 3 slots.
|
||||||
*/
|
*/
|
||||||
|
@ -75,16 +76,23 @@ public:
|
||||||
return 7 + GrDrawState::kMaxTexCoords + 3 * stage;
|
return 7 + GrDrawState::kMaxTexCoords + 3 * stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
enum {
|
||||||
|
kUnusedUniform = -1,
|
||||||
|
};
|
||||||
|
|
||||||
// Parameters that affect code generation
|
// Parameters that affect code generation
|
||||||
// These structs should be kept compact; they are the input to an
|
// These structs should be kept compact; they are the input to an
|
||||||
// expensive hash key generator.
|
// expensive hash key generator.
|
||||||
struct ProgramDesc {
|
struct Desc {
|
||||||
ProgramDesc() {
|
Desc() {
|
||||||
// since we use this as part of a key we can't have any unitialized
|
// since we use this as part of a key we can't have any unitialized
|
||||||
// padding
|
// padding
|
||||||
memset(this, 0, sizeof(ProgramDesc));
|
memset(this, 0, sizeof(Desc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns this as a uint32_t array to be used as a key in the program cache
|
||||||
|
const uint32_t* asKey() const {
|
||||||
|
return reinterpret_cast<const uint32_t*>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum OutputConfig {
|
enum OutputConfig {
|
||||||
|
@ -224,23 +232,46 @@ public:
|
||||||
|
|
||||||
uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode
|
uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode
|
||||||
int8_t fPadding[1];
|
int8_t fPadding[1];
|
||||||
|
};
|
||||||
} fProgramDesc;
|
GR_STATIC_ASSERT(!(sizeof(Desc) % 4));
|
||||||
GR_STATIC_ASSERT(!(sizeof(ProgramDesc) % 4));
|
|
||||||
|
|
||||||
// for code readability
|
// for code readability
|
||||||
typedef ProgramDesc::StageDesc StageDesc;
|
typedef Desc::StageDesc StageDesc;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void genInputColor(GrGLShaderBuilder* builder, SkString* inColor);
|
||||||
|
|
||||||
|
// Determines which uniforms will need to be bound.
|
||||||
|
void genStageCode(const GrGLContextInfo& gl,
|
||||||
|
int stageNum,
|
||||||
|
const char* fsInColor, // NULL means no incoming color
|
||||||
|
const char* fsOutColor,
|
||||||
|
const char* vsInCoord,
|
||||||
|
GrGLShaderBuilder* builder);
|
||||||
|
|
||||||
|
void genGeometryShader(const GrGLContextInfo& gl, GrGLShaderBuilder* segments) const;
|
||||||
|
|
||||||
|
void genUniformCoverage(GrGLShaderBuilder* segments, SkString* inOutCoverage);
|
||||||
|
|
||||||
|
// generates code to compute coverage based on edge AA.
|
||||||
|
void genEdgeCoverage(const GrGLContextInfo& gl,
|
||||||
|
SkString* coverageVar,
|
||||||
|
GrGLShaderBuilder* builder) const;
|
||||||
|
|
||||||
|
// Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program
|
||||||
|
bool bindOutputsAttribsAndLinkProgram(const GrGLContextInfo& gl,
|
||||||
|
SkString texCoordAttrNames[GrDrawState::kMaxTexCoords],
|
||||||
|
bool bindColorOut,
|
||||||
|
bool bindDualSrcOut);
|
||||||
|
|
||||||
|
// Binds uniforms; initializes cache to invalid values.
|
||||||
|
void getUniformLocationsAndInitCache(const GrGLContextInfo& gl,
|
||||||
|
const GrGLShaderBuilder& builder);
|
||||||
|
|
||||||
|
bool compileShaders(const GrGLContextInfo& gl, const GrGLShaderBuilder& builder);
|
||||||
|
|
||||||
const ProgramDesc& getDesc() { return fProgramDesc; }
|
|
||||||
const char* adjustInColor(const SkString& inColor) const;
|
const char* adjustInColor(const SkString& inColor) const;
|
||||||
|
|
||||||
public:
|
|
||||||
enum {
|
|
||||||
kUnusedUniform = -1,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct StageUniLocations {
|
struct StageUniLocations {
|
||||||
GrGLint fTextureMatrixUni;
|
GrGLint fTextureMatrixUni;
|
||||||
GrGLint fSamplerUni;
|
GrGLint fSamplerUni;
|
||||||
|
@ -273,104 +304,37 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CachedData : public ::GrNoncopyable {
|
// IDs
|
||||||
public:
|
GrGLuint fVShaderID;
|
||||||
CachedData() {
|
GrGLuint fGShaderID;
|
||||||
for (int i = 0; i < GrDrawState::kNumStages; ++i) {
|
GrGLuint fFShaderID;
|
||||||
fCustomStage[i] = NULL;
|
GrGLuint fProgramID;
|
||||||
}
|
// shader uniform locations (-1 if shader doesn't use them)
|
||||||
}
|
UniLocations fUniLocations;
|
||||||
|
|
||||||
~CachedData();
|
// The matrix sent to GL is determined by both the client's matrix and
|
||||||
|
// the size of the viewport.
|
||||||
|
GrMatrix fViewMatrix;
|
||||||
|
SkISize fViewportSize;
|
||||||
|
|
||||||
void copyAndTakeOwnership(CachedData& other) {
|
// these reflect the current values of uniforms
|
||||||
memcpy(this, &other, sizeof(*this));
|
// (GL uniform values travel with program)
|
||||||
for (int i = 0; i < GrDrawState::kNumStages; ++i) {
|
GrColor fColor;
|
||||||
other.fCustomStage[i] = NULL;
|
GrColor fCoverage;
|
||||||
}
|
GrColor fColorFilterColor;
|
||||||
}
|
GrMatrix fTextureMatrices[GrDrawState::kNumStages];
|
||||||
|
GrRect fTextureDomain[GrDrawState::kNumStages];
|
||||||
|
// The texture domain and texture matrix sent to GL depend upon the
|
||||||
|
// orientation.
|
||||||
|
GrGLTexture::Orientation fTextureOrientation[GrDrawState::kNumStages];
|
||||||
|
|
||||||
public:
|
GrGLProgramStage* fProgramStage[GrDrawState::kNumStages];
|
||||||
|
|
||||||
// IDs
|
Desc fDesc;
|
||||||
GrGLuint fVShaderID;
|
|
||||||
GrGLuint fGShaderID;
|
|
||||||
GrGLuint fFShaderID;
|
|
||||||
GrGLuint fProgramID;
|
|
||||||
// shader uniform locations (-1 if shader doesn't use them)
|
|
||||||
UniLocations fUniLocations;
|
|
||||||
|
|
||||||
// The matrix sent to GL is determined by both the client's matrix and
|
friend class GrGpuGL; // TODO: remove this by adding getters and moving functionality.
|
||||||
// the size of the viewport.
|
|
||||||
GrMatrix fViewMatrix;
|
|
||||||
SkISize fViewportSize;
|
|
||||||
|
|
||||||
// these reflect the current values of uniforms
|
typedef GrRefCnt INHERITED;
|
||||||
// (GL uniform values travel with program)
|
|
||||||
GrColor fColor;
|
|
||||||
GrColor fCoverage;
|
|
||||||
GrColor fColorFilterColor;
|
|
||||||
GrMatrix fTextureMatrices[GrDrawState::kNumStages];
|
|
||||||
GrRect fTextureDomain[GrDrawState::kNumStages];
|
|
||||||
// The texture domain and texture matrix sent to GL depend upon the
|
|
||||||
// orientation.
|
|
||||||
GrGLTexture::Orientation fTextureOrientation[GrDrawState::kNumStages];
|
|
||||||
|
|
||||||
GrGLProgramStage* fCustomStage[GrDrawState::kNumStages];
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum Constants {
|
|
||||||
kUniLocationPreAllocSize = 8
|
|
||||||
};
|
|
||||||
|
|
||||||
}; // CachedData
|
|
||||||
|
|
||||||
enum Constants {
|
|
||||||
kProgramKeySize = sizeof(ProgramDesc)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Provide an opaque ProgramDesc
|
|
||||||
const uint32_t* keyData() const{
|
|
||||||
return reinterpret_cast<const uint32_t*>(&fProgramDesc);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Determines which uniforms will need to be bound.
|
|
||||||
void genStageCode(const GrGLContextInfo& gl,
|
|
||||||
int stageNum,
|
|
||||||
const ProgramDesc::StageDesc& desc,
|
|
||||||
const char* fsInColor, // NULL means no incoming color
|
|
||||||
const char* fsOutColor,
|
|
||||||
const char* vsInCoord,
|
|
||||||
GrGLShaderBuilder* segments,
|
|
||||||
StageUniLocations* locations,
|
|
||||||
GrGLProgramStage* override) const;
|
|
||||||
|
|
||||||
void genGeometryShader(const GrGLContextInfo& gl,
|
|
||||||
GrGLShaderBuilder* segments) const;
|
|
||||||
|
|
||||||
// generates code to compute coverage based on edge AA.
|
|
||||||
void genEdgeCoverage(const GrGLContextInfo& gl,
|
|
||||||
GrVertexLayout layout,
|
|
||||||
CachedData* programData,
|
|
||||||
SkString* coverageVar,
|
|
||||||
GrGLShaderBuilder* segments) const;
|
|
||||||
|
|
||||||
// Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program
|
|
||||||
bool bindOutputsAttribsAndLinkProgram(
|
|
||||||
const GrGLContextInfo& gl,
|
|
||||||
SkString texCoordAttrNames[GrDrawState::kMaxTexCoords],
|
|
||||||
bool bindColorOut,
|
|
||||||
bool bindDualSrcOut,
|
|
||||||
CachedData* programData) const;
|
|
||||||
|
|
||||||
// Binds uniforms; initializes cache to invalid values.
|
|
||||||
void getUniformLocationsAndInitCache(const GrGLShaderBuilder& builder,
|
|
||||||
const GrGLContextInfo& gl,
|
|
||||||
CachedData* programData) const;
|
|
||||||
|
|
||||||
friend class GrGpuGL;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -175,7 +175,6 @@ GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) {
|
||||||
|
|
||||||
this->initCaps();
|
this->initCaps();
|
||||||
|
|
||||||
fProgramData = NULL;
|
|
||||||
fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContextInfo()));
|
fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContextInfo()));
|
||||||
|
|
||||||
fLastSuccessfulStencilFmtIdx = 0;
|
fLastSuccessfulStencilFmtIdx = 0;
|
||||||
|
@ -186,16 +185,14 @@ GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
GrGpuGL::~GrGpuGL() {
|
GrGpuGL::~GrGpuGL() {
|
||||||
if (fProgramData && 0 != fHWProgramID) {
|
if (0 != fHWProgramID) {
|
||||||
// detach the current program so there is no confusion on OpenGL's part
|
// detach the current program so there is no confusion on OpenGL's part
|
||||||
// that we want it to be deleted
|
// that we want it to be deleted
|
||||||
GrAssert(fHWProgramID == fProgramData->fProgramID);
|
GrAssert(fHWProgramID == fCurrentProgram->fProgramID);
|
||||||
GL_CALL(UseProgram(0));
|
GL_CALL(UseProgram(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
delete fProgramCache;
|
delete fProgramCache;
|
||||||
fProgramCache = NULL;
|
|
||||||
fProgramData = NULL;
|
|
||||||
|
|
||||||
// This must be called by before the GrDrawTarget destructor
|
// This must be called by before the GrDrawTarget destructor
|
||||||
this->releaseGeometry();
|
this->releaseGeometry();
|
||||||
|
|
|
@ -162,9 +162,8 @@ private:
|
||||||
static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
|
static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
|
||||||
|
|
||||||
// for readability of function impls
|
// for readability of function impls
|
||||||
typedef GrGLProgram::ProgramDesc ProgramDesc;
|
typedef GrGLProgram::Desc ProgramDesc;
|
||||||
typedef ProgramDesc::StageDesc StageDesc;
|
typedef ProgramDesc::StageDesc StageDesc;
|
||||||
typedef GrGLProgram::CachedData CachedData;
|
|
||||||
|
|
||||||
class ProgramCache : public ::GrNoncopyable {
|
class ProgramCache : public ::GrNoncopyable {
|
||||||
public:
|
public:
|
||||||
|
@ -172,31 +171,37 @@ private:
|
||||||
~ProgramCache();
|
~ProgramCache();
|
||||||
|
|
||||||
void abandon();
|
void abandon();
|
||||||
CachedData* getProgramData(const GrGLProgram& desc,
|
GrGLProgram* getProgram(const GrGLProgram::Desc& desc, GrCustomStage** stages);
|
||||||
GrCustomStage** stages);
|
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
kKeySize = GrGLProgram::kProgramKeySize,
|
kKeySize = sizeof(ProgramDesc),
|
||||||
// We may actually have kMaxEntries+1 shaders in the GL context
|
// We may actually have kMaxEntries+1 shaders in the GL context because we create a new
|
||||||
// because we create a new shader before evicting from the cache.
|
// shader before evicting from the cache.
|
||||||
kMaxEntries = 32
|
kMaxEntries = 32
|
||||||
};
|
};
|
||||||
|
|
||||||
class Entry;
|
class Entry;
|
||||||
typedef GrBinHashKey<Entry, kKeySize> ProgramHashKey;
|
// The value of the hash key is based on the ProgramDesc.
|
||||||
|
typedef GrTBinHashKey<Entry, kKeySize> ProgramHashKey;
|
||||||
|
|
||||||
class Entry : public ::GrNoncopyable {
|
class Entry : public ::GrNoncopyable {
|
||||||
public:
|
public:
|
||||||
Entry() {}
|
Entry() : fProgram(NULL), fLRUStamp(0) {}
|
||||||
void copyAndTakeOwnership(Entry& entry);
|
Entry& operator = (const Entry& entry) {
|
||||||
|
GrSafeRef(entry.fProgram.get());
|
||||||
|
fProgram.reset(entry.fProgram.get());
|
||||||
|
fKey = entry.fKey;
|
||||||
|
fLRUStamp = entry.fLRUStamp;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
int compare(const ProgramHashKey& key) const {
|
int compare(const ProgramHashKey& key) const {
|
||||||
return fKey.compare(key);
|
return fKey.compare(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CachedData fProgramData;
|
SkAutoTUnref<GrGLProgram> fProgram;
|
||||||
ProgramHashKey fKey;
|
ProgramHashKey fKey;
|
||||||
unsigned int fLRUStamp;
|
unsigned int fLRUStamp; // Move outside entry?
|
||||||
};
|
};
|
||||||
|
|
||||||
GrTHashTable<Entry, ProgramHashKey, 8> fHashCache;
|
GrTHashTable<Entry, ProgramHashKey, 8> fHashCache;
|
||||||
|
@ -243,13 +248,13 @@ private:
|
||||||
// flushing the scissor after that function is called.
|
// flushing the scissor after that function is called.
|
||||||
void flushScissor();
|
void flushScissor();
|
||||||
|
|
||||||
static void DeleteProgram(const GrGLInterface* gl,
|
static void DeleteProgram(const GrGLInterface* gl, GrGLProgram* programData);
|
||||||
CachedData* programData);
|
|
||||||
|
|
||||||
void buildProgram(bool isPoints,
|
void buildProgram(bool isPoints,
|
||||||
BlendOptFlags blendOpts,
|
BlendOptFlags blendOpts,
|
||||||
GrBlendCoeff dstCoeff,
|
GrBlendCoeff dstCoeff,
|
||||||
GrCustomStage** customStages);
|
GrCustomStage** customStages,
|
||||||
|
ProgramDesc* desc);
|
||||||
|
|
||||||
// Inits GrDrawTarget::Caps, sublcass may enable additional caps.
|
// Inits GrDrawTarget::Caps, sublcass may enable additional caps.
|
||||||
void initCaps();
|
void initCaps();
|
||||||
|
@ -304,8 +309,7 @@ private:
|
||||||
|
|
||||||
// GL program-related state
|
// GL program-related state
|
||||||
ProgramCache* fProgramCache;
|
ProgramCache* fProgramCache;
|
||||||
CachedData* fProgramData;
|
SkAutoTUnref<GrGLProgram> fCurrentProgram;
|
||||||
GrGLProgram fCurrentProgram;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
///@name Caching of GL State
|
///@name Caching of GL State
|
||||||
|
|
|
@ -14,12 +14,6 @@
|
||||||
#define SKIP_CACHE_CHECK true
|
#define SKIP_CACHE_CHECK true
|
||||||
#define GR_UINT32_MAX static_cast<uint32_t>(-1)
|
#define GR_UINT32_MAX static_cast<uint32_t>(-1)
|
||||||
|
|
||||||
void GrGpuGL::ProgramCache::Entry::copyAndTakeOwnership(Entry& entry) {
|
|
||||||
fProgramData.copyAndTakeOwnership(entry.fProgramData);
|
|
||||||
fKey = entry.fKey; // ownership transfer
|
|
||||||
fLRUStamp = entry.fLRUStamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
GrGpuGL::ProgramCache::ProgramCache(const GrGLContextInfo& gl)
|
GrGpuGL::ProgramCache::ProgramCache(const GrGLContextInfo& gl)
|
||||||
: fCount(0)
|
: fCount(0)
|
||||||
, fCurrLRUStamp(0)
|
, fCurrLRUStamp(0)
|
||||||
|
@ -28,8 +22,7 @@ GrGpuGL::ProgramCache::ProgramCache(const GrGLContextInfo& gl)
|
||||||
|
|
||||||
GrGpuGL::ProgramCache::~ProgramCache() {
|
GrGpuGL::ProgramCache::~ProgramCache() {
|
||||||
for (int i = 0; i < fCount; ++i) {
|
for (int i = 0; i < fCount; ++i) {
|
||||||
GrGpuGL::DeleteProgram(fGL.interface(),
|
GrGpuGL::DeleteProgram(fGL.interface(), fEntries[i].fProgram);
|
||||||
&fEntries[i].fProgramData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,15 +30,14 @@ void GrGpuGL::ProgramCache::abandon() {
|
||||||
fCount = 0;
|
fCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrGLProgram::CachedData* GrGpuGL::ProgramCache::getProgramData(
|
GrGLProgram* GrGpuGL::ProgramCache::getProgram(const ProgramDesc& desc, GrCustomStage** stages) {
|
||||||
const GrGLProgram& desc,
|
|
||||||
GrCustomStage** stages) {
|
|
||||||
Entry newEntry;
|
Entry newEntry;
|
||||||
newEntry.fKey.setKeyData(desc.keyData());
|
newEntry.fKey.setKeyData(desc.asKey());
|
||||||
|
|
||||||
Entry* entry = fHashCache.find(newEntry.fKey);
|
Entry* entry = fHashCache.find(newEntry.fKey);
|
||||||
if (NULL == entry) {
|
if (NULL == entry) {
|
||||||
if (!desc.genProgram(fGL, stages, &newEntry.fProgramData)) {
|
newEntry.fProgram.reset(SkNEW(GrGLProgram));
|
||||||
|
if (!newEntry.fProgram->genProgram(fGL, desc, stages)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (fCount < kMaxEntries) {
|
if (fCount < kMaxEntries) {
|
||||||
|
@ -60,10 +52,9 @@ GrGLProgram::CachedData* GrGpuGL::ProgramCache::getProgramData(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fHashCache.remove(entry->fKey, entry);
|
fHashCache.remove(entry->fKey, entry);
|
||||||
GrGpuGL::DeleteProgram(fGL.interface(),
|
GrGpuGL::DeleteProgram(fGL.interface(), entry->fProgram);
|
||||||
&entry->fProgramData);
|
|
||||||
}
|
}
|
||||||
entry->copyAndTakeOwnership(newEntry);
|
*entry = newEntry;
|
||||||
fHashCache.insert(entry->fKey, entry);
|
fHashCache.insert(entry->fKey, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,21 +66,20 @@ GrGLProgram::CachedData* GrGpuGL::ProgramCache::getProgramData(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++fCurrLRUStamp;
|
++fCurrLRUStamp;
|
||||||
return &entry->fProgramData;
|
return entry->fProgram;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGpuGL::DeleteProgram(const GrGLInterface* gl,
|
void GrGpuGL::DeleteProgram(const GrGLInterface* gl, GrGLProgram* program) {
|
||||||
CachedData* programData) {
|
GR_GL_CALL(gl, DeleteShader(program->fVShaderID));
|
||||||
GR_GL_CALL(gl, DeleteShader(programData->fVShaderID));
|
if (program->fGShaderID) {
|
||||||
if (programData->fGShaderID) {
|
GR_GL_CALL(gl, DeleteShader(program->fGShaderID));
|
||||||
GR_GL_CALL(gl, DeleteShader(programData->fGShaderID));
|
|
||||||
}
|
}
|
||||||
GR_GL_CALL(gl, DeleteShader(programData->fFShaderID));
|
GR_GL_CALL(gl, DeleteShader(program->fFShaderID));
|
||||||
GR_GL_CALL(gl, DeleteProgram(programData->fProgramID));
|
GR_GL_CALL(gl, DeleteProgram(program->fProgramID));
|
||||||
GR_DEBUGCODE(programData->fVShaderID = 0);
|
GR_DEBUGCODE(program->fVShaderID = 0);
|
||||||
GR_DEBUGCODE(programData->fGShaderID = 0);
|
GR_DEBUGCODE(program->fGShaderID = 0);
|
||||||
GR_DEBUGCODE(programData->fFShaderID = 0);
|
GR_DEBUGCODE(program->fFShaderID = 0);
|
||||||
GR_DEBUGCODE(programData->fProgramID = 0);
|
GR_DEBUGCODE(program->fProgramID = 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -150,8 +140,8 @@ void GrGpuGL::flushViewMatrix(DrawType type) {
|
||||||
fHWPathMatrixState.fViewMatrix = vm;
|
fHWPathMatrixState.fViewMatrix = vm;
|
||||||
fHWPathMatrixState.fRTSize = viewportSize;
|
fHWPathMatrixState.fRTSize = viewportSize;
|
||||||
}
|
}
|
||||||
} else if (!fProgramData->fViewMatrix.cheapEqualTo(vm) ||
|
} else if (!fCurrentProgram->fViewMatrix.cheapEqualTo(vm) ||
|
||||||
fProgramData->fViewportSize != viewportSize) {
|
fCurrentProgram->fViewportSize != viewportSize) {
|
||||||
GrMatrix m;
|
GrMatrix m;
|
||||||
m.setAll(
|
m.setAll(
|
||||||
GrIntToScalar(2) / viewportSize.fWidth, 0, -GR_Scalar1,
|
GrIntToScalar(2) / viewportSize.fWidth, 0, -GR_Scalar1,
|
||||||
|
@ -174,11 +164,11 @@ void GrGpuGL::flushViewMatrix(DrawType type) {
|
||||||
};
|
};
|
||||||
|
|
||||||
GrAssert(GrGLProgram::kUnusedUniform !=
|
GrAssert(GrGLProgram::kUnusedUniform !=
|
||||||
fProgramData->fUniLocations.fViewMatrixUni);
|
fCurrentProgram->fUniLocations.fViewMatrixUni);
|
||||||
GL_CALL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni,
|
GL_CALL(UniformMatrix3fv(fCurrentProgram->fUniLocations.fViewMatrixUni,
|
||||||
1, false, mt));
|
1, false, mt));
|
||||||
fProgramData->fViewMatrix = vm;
|
fCurrentProgram->fViewMatrix = vm;
|
||||||
fProgramData->fViewportSize = viewportSize;
|
fCurrentProgram->fViewportSize = viewportSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,13 +215,13 @@ void GrGpuGL::flushTextureMatrixAndDomain(int s) {
|
||||||
static_cast<const GrGLTexture*>(drawState.getTexture(s));
|
static_cast<const GrGLTexture*>(drawState.getTexture(s));
|
||||||
if (NULL != texture) {
|
if (NULL != texture) {
|
||||||
|
|
||||||
bool orientationChange = fProgramData->fTextureOrientation[s] !=
|
bool orientationChange = fCurrentProgram->fTextureOrientation[s] !=
|
||||||
texture->orientation();
|
texture->orientation();
|
||||||
|
|
||||||
const GrGLint& matrixUni =
|
const GrGLint& matrixUni =
|
||||||
fProgramData->fUniLocations.fStages[s].fTextureMatrixUni;
|
fCurrentProgram->fUniLocations.fStages[s].fTextureMatrixUni;
|
||||||
|
|
||||||
const GrMatrix& hwMatrix = fProgramData->fTextureMatrices[s];
|
const GrMatrix& hwMatrix = fCurrentProgram->fTextureMatrices[s];
|
||||||
const GrMatrix& samplerMatrix = drawState.getSampler(s).getMatrix();
|
const GrMatrix& samplerMatrix = drawState.getSampler(s).getMatrix();
|
||||||
|
|
||||||
if (GrGLProgram::kUnusedUniform != matrixUni &&
|
if (GrGLProgram::kUnusedUniform != matrixUni &&
|
||||||
|
@ -255,16 +245,15 @@ void GrGpuGL::flushTextureMatrixAndDomain(int s) {
|
||||||
};
|
};
|
||||||
|
|
||||||
GL_CALL(UniformMatrix3fv(matrixUni, 1, false, mt));
|
GL_CALL(UniformMatrix3fv(matrixUni, 1, false, mt));
|
||||||
fProgramData->fTextureMatrices[s] = samplerMatrix;
|
fCurrentProgram->fTextureMatrices[s] = samplerMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GrGLint& domUni =
|
const GrGLint& domUni = fCurrentProgram->fUniLocations.fStages[s].fTexDomUni;
|
||||||
fProgramData->fUniLocations.fStages[s].fTexDomUni;
|
|
||||||
const GrRect &texDom = drawState.getSampler(s).getTextureDomain();
|
const GrRect &texDom = drawState.getSampler(s).getTextureDomain();
|
||||||
if (GrGLProgram::kUnusedUniform != domUni &&
|
if (GrGLProgram::kUnusedUniform != domUni &&
|
||||||
(orientationChange ||fProgramData->fTextureDomain[s] != texDom)) {
|
(orientationChange ||fCurrentProgram->fTextureDomain[s] != texDom)) {
|
||||||
|
|
||||||
fProgramData->fTextureDomain[s] = texDom;
|
fCurrentProgram->fTextureDomain[s] = texDom;
|
||||||
|
|
||||||
float values[4] = {
|
float values[4] = {
|
||||||
GrScalarToFloat(texDom.left()),
|
GrScalarToFloat(texDom.left()),
|
||||||
|
@ -283,15 +272,14 @@ void GrGpuGL::flushTextureMatrixAndDomain(int s) {
|
||||||
}
|
}
|
||||||
GL_CALL(Uniform4fv(domUni, 1, values));
|
GL_CALL(Uniform4fv(domUni, 1, values));
|
||||||
}
|
}
|
||||||
fProgramData->fTextureOrientation[s] = texture->orientation();
|
fCurrentProgram->fTextureOrientation[s] = texture->orientation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GrGpuGL::flushColorMatrix() {
|
void GrGpuGL::flushColorMatrix() {
|
||||||
// const ProgramDesc& desc = fCurrentProgram.getDesc();
|
int matrixUni = fCurrentProgram->fUniLocations.fColorMatrixUni;
|
||||||
int matrixUni = fProgramData->fUniLocations.fColorMatrixUni;
|
int vecUni = fCurrentProgram->fUniLocations.fColorMatrixVecUni;
|
||||||
int vecUni = fProgramData->fUniLocations.fColorMatrixVecUni;
|
|
||||||
if (GrGLProgram::kUnusedUniform != matrixUni
|
if (GrGLProgram::kUnusedUniform != matrixUni
|
||||||
&& GrGLProgram::kUnusedUniform != vecUni) {
|
&& GrGLProgram::kUnusedUniform != vecUni) {
|
||||||
const float* m = this->getDrawState().getColorMatrix();
|
const float* m = this->getDrawState().getColorMatrix();
|
||||||
|
@ -320,7 +308,7 @@ static const float ONE_OVER_255 = 1.f / 255.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGpuGL::flushColor(GrColor color) {
|
void GrGpuGL::flushColor(GrColor color) {
|
||||||
const ProgramDesc& desc = fCurrentProgram.getDesc();
|
const ProgramDesc& desc = fCurrentProgram->getDesc();
|
||||||
const GrDrawState& drawState = this->getDrawState();
|
const GrDrawState& drawState = this->getDrawState();
|
||||||
|
|
||||||
if (this->getVertexLayout() & kColor_VertexLayoutBit) {
|
if (this->getVertexLayout() & kColor_VertexLayoutBit) {
|
||||||
|
@ -340,15 +328,14 @@ void GrGpuGL::flushColor(GrColor color) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ProgramDesc::kUniform_ColorInput:
|
case ProgramDesc::kUniform_ColorInput:
|
||||||
if (fProgramData->fColor != color) {
|
if (fCurrentProgram->fColor != color) {
|
||||||
// OpenGL ES doesn't support unsigned byte varieties of
|
// OpenGL ES doesn't support unsigned byte varieties of
|
||||||
// glUniform
|
// glUniform
|
||||||
float c[] = GR_COLOR_TO_VEC4(color);
|
float c[] = GR_COLOR_TO_VEC4(color);
|
||||||
GrAssert(GrGLProgram::kUnusedUniform !=
|
GrAssert(GrGLProgram::kUnusedUniform !=
|
||||||
fProgramData->fUniLocations.fColorUni);
|
fCurrentProgram->fUniLocations.fColorUni);
|
||||||
GL_CALL(Uniform4fv(fProgramData->fUniLocations.fColorUni,
|
GL_CALL(Uniform4fv(fCurrentProgram->fUniLocations.fColorUni, 1, c));
|
||||||
1, c));
|
fCurrentProgram->fColor = color;
|
||||||
fProgramData->fColor = color;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ProgramDesc::kSolidWhite_ColorInput:
|
case ProgramDesc::kSolidWhite_ColorInput:
|
||||||
|
@ -358,18 +345,18 @@ void GrGpuGL::flushColor(GrColor color) {
|
||||||
GrCrash("Unknown color type.");
|
GrCrash("Unknown color type.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fProgramData->fUniLocations.fColorFilterUni
|
if (fCurrentProgram->fUniLocations.fColorFilterUni
|
||||||
!= GrGLProgram::kUnusedUniform
|
!= GrGLProgram::kUnusedUniform
|
||||||
&& fProgramData->fColorFilterColor
|
&& fCurrentProgram->fColorFilterColor
|
||||||
!= drawState.getColorFilterColor()) {
|
!= drawState.getColorFilterColor()) {
|
||||||
float c[] = GR_COLOR_TO_VEC4(drawState.getColorFilterColor());
|
float c[] = GR_COLOR_TO_VEC4(drawState.getColorFilterColor());
|
||||||
GL_CALL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c));
|
GL_CALL(Uniform4fv(fCurrentProgram->fUniLocations.fColorFilterUni, 1, c));
|
||||||
fProgramData->fColorFilterColor = drawState.getColorFilterColor();
|
fCurrentProgram->fColorFilterColor = drawState.getColorFilterColor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGpuGL::flushCoverage(GrColor coverage) {
|
void GrGpuGL::flushCoverage(GrColor coverage) {
|
||||||
const ProgramDesc& desc = fCurrentProgram.getDesc();
|
const ProgramDesc& desc = fCurrentProgram->getDesc();
|
||||||
// const GrDrawState& drawState = this->getDrawState();
|
// const GrDrawState& drawState = this->getDrawState();
|
||||||
|
|
||||||
|
|
||||||
|
@ -390,15 +377,14 @@ void GrGpuGL::flushCoverage(GrColor coverage) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ProgramDesc::kUniform_ColorInput:
|
case ProgramDesc::kUniform_ColorInput:
|
||||||
if (fProgramData->fCoverage != coverage) {
|
if (fCurrentProgram->fCoverage != coverage) {
|
||||||
// OpenGL ES doesn't support unsigned byte varieties of
|
// OpenGL ES doesn't support unsigned byte varieties of
|
||||||
// glUniform
|
// glUniform
|
||||||
float c[] = GR_COLOR_TO_VEC4(coverage);
|
float c[] = GR_COLOR_TO_VEC4(coverage);
|
||||||
GrAssert(GrGLProgram::kUnusedUniform !=
|
GrAssert(GrGLProgram::kUnusedUniform !=
|
||||||
fProgramData->fUniLocations.fCoverageUni);
|
fCurrentProgram->fUniLocations.fCoverageUni);
|
||||||
GL_CALL(Uniform4fv(fProgramData->fUniLocations.fCoverageUni,
|
GL_CALL(Uniform4fv(fCurrentProgram->fUniLocations.fCoverageUni, 1, c));
|
||||||
1, c));
|
fCurrentProgram->fCoverage = coverage;
|
||||||
fProgramData->fCoverage = coverage;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ProgramDesc::kSolidWhite_ColorInput:
|
case ProgramDesc::kSolidWhite_ColorInput:
|
||||||
|
@ -428,20 +414,21 @@ bool GrGpuGL::flushGraphicsState(DrawType type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
GrCustomStage* customStages [GrDrawState::kNumStages];
|
GrCustomStage* customStages [GrDrawState::kNumStages];
|
||||||
this->buildProgram(kDrawPoints_DrawType == type,
|
GrGLProgram::Desc desc;
|
||||||
blendOpts, dstCoeff, customStages);
|
this->buildProgram(kDrawPoints_DrawType == type, blendOpts, dstCoeff, customStages, &desc);
|
||||||
fProgramData = fProgramCache->getProgramData(fCurrentProgram,
|
|
||||||
customStages);
|
fCurrentProgram.reset(fProgramCache->getProgram(desc, customStages));
|
||||||
if (NULL == fProgramData) {
|
if (NULL == fCurrentProgram.get()) {
|
||||||
GrAssert(!"Failed to create program!");
|
GrAssert(!"Failed to create program!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
fCurrentProgram.get()->ref();
|
||||||
|
|
||||||
if (fHWProgramID != fProgramData->fProgramID) {
|
if (fHWProgramID != fCurrentProgram->fProgramID) {
|
||||||
GL_CALL(UseProgram(fProgramData->fProgramID));
|
GL_CALL(UseProgram(fCurrentProgram->fProgramID));
|
||||||
fHWProgramID = fProgramData->fProgramID;
|
fHWProgramID = fCurrentProgram->fProgramID;
|
||||||
}
|
}
|
||||||
fCurrentProgram.overrideBlend(&srcCoeff, &dstCoeff);
|
fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
|
||||||
this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
|
this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
|
||||||
|
|
||||||
GrColor color;
|
GrColor color;
|
||||||
|
@ -472,16 +459,13 @@ bool GrGpuGL::flushGraphicsState(DrawType type) {
|
||||||
|
|
||||||
this->flushTextureMatrixAndDomain(s);
|
this->flushTextureMatrixAndDomain(s);
|
||||||
|
|
||||||
if (NULL != fProgramData->fCustomStage[s]) {
|
if (NULL != fCurrentProgram->fProgramStage[s]) {
|
||||||
const GrSamplerState& sampler =
|
const GrSamplerState& sampler = this->getDrawState().getSampler(s);
|
||||||
this->getDrawState().getSampler(s);
|
const GrGLTexture* texture = static_cast<const GrGLTexture*>(
|
||||||
const GrGLTexture* texture =
|
this->getDrawState().getTexture(s));
|
||||||
static_cast<const GrGLTexture*>(
|
fCurrentProgram->fProgramStage[s]->setData(this->glInterface(),
|
||||||
this->getDrawState().getTexture(s));
|
*sampler.getCustomStage(),
|
||||||
fProgramData->fCustomStage[s]->setData(
|
drawState.getRenderTarget(), s);
|
||||||
this->glInterface(),
|
|
||||||
*sampler.getCustomStage(),
|
|
||||||
drawState.getRenderTarget(), s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -658,7 +642,7 @@ void GrGpuGL::setupGeometry(int* startVertex,
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void setup_custom_stage(GrGLProgram::ProgramDesc::StageDesc* stage,
|
void setup_custom_stage(GrGLProgram::Desc::StageDesc* stage,
|
||||||
const GrSamplerState& sampler,
|
const GrSamplerState& sampler,
|
||||||
GrCustomStage** customStages,
|
GrCustomStage** customStages,
|
||||||
GrGLProgram* program, int index) {
|
GrGLProgram* program, int index) {
|
||||||
|
@ -678,8 +662,8 @@ void setup_custom_stage(GrGLProgram::ProgramDesc::StageDesc* stage,
|
||||||
void GrGpuGL::buildProgram(bool isPoints,
|
void GrGpuGL::buildProgram(bool isPoints,
|
||||||
BlendOptFlags blendOpts,
|
BlendOptFlags blendOpts,
|
||||||
GrBlendCoeff dstCoeff,
|
GrBlendCoeff dstCoeff,
|
||||||
GrCustomStage** customStages) {
|
GrCustomStage** customStages,
|
||||||
ProgramDesc& desc = fCurrentProgram.fProgramDesc;
|
ProgramDesc* desc) {
|
||||||
const GrDrawState& drawState = this->getDrawState();
|
const GrDrawState& drawState = this->getDrawState();
|
||||||
|
|
||||||
// This should already have been caught
|
// This should already have been caught
|
||||||
|
@ -696,31 +680,31 @@ void GrGpuGL::buildProgram(bool isPoints,
|
||||||
// to a canonical value to avoid duplicate programs with different keys.
|
// to a canonical value to avoid duplicate programs with different keys.
|
||||||
|
|
||||||
// Must initialize all fields or cache will have false negatives!
|
// Must initialize all fields or cache will have false negatives!
|
||||||
desc.fVertexLayout = this->getVertexLayout();
|
desc->fVertexLayout = this->getVertexLayout();
|
||||||
|
|
||||||
desc.fEmitsPointSize = isPoints;
|
desc->fEmitsPointSize = isPoints;
|
||||||
|
|
||||||
bool requiresAttributeColors =
|
bool requiresAttributeColors =
|
||||||
!skipColor && SkToBool(desc.fVertexLayout & kColor_VertexLayoutBit);
|
!skipColor && SkToBool(desc->fVertexLayout & kColor_VertexLayoutBit);
|
||||||
bool requiresAttributeCoverage =
|
bool requiresAttributeCoverage =
|
||||||
!skipCoverage && SkToBool(desc.fVertexLayout &
|
!skipCoverage && SkToBool(desc->fVertexLayout &
|
||||||
kCoverage_VertexLayoutBit);
|
kCoverage_VertexLayoutBit);
|
||||||
|
|
||||||
// fColorInput/fCoverageInput records how colors are specified for the.
|
// fColorInput/fCoverageInput records how colors are specified for the.
|
||||||
// program. So we strip the bits from the layout to avoid false negatives
|
// program. So we strip the bits from the layout to avoid false negatives
|
||||||
// when searching for an existing program in the cache.
|
// when searching for an existing program in the cache.
|
||||||
desc.fVertexLayout &= ~(kColor_VertexLayoutBit | kCoverage_VertexLayoutBit);
|
desc->fVertexLayout &= ~(kColor_VertexLayoutBit | kCoverage_VertexLayoutBit);
|
||||||
|
|
||||||
desc.fColorFilterXfermode = skipColor ?
|
desc->fColorFilterXfermode = skipColor ?
|
||||||
SkXfermode::kDst_Mode :
|
SkXfermode::kDst_Mode :
|
||||||
drawState.getColorFilterMode();
|
drawState.getColorFilterMode();
|
||||||
|
|
||||||
desc.fColorMatrixEnabled = drawState.isStateFlagEnabled(GrDrawState::kColorMatrix_StateBit);
|
desc->fColorMatrixEnabled = drawState.isStateFlagEnabled(GrDrawState::kColorMatrix_StateBit);
|
||||||
|
|
||||||
// no reason to do edge aa or look at per-vertex coverage if coverage is
|
// no reason to do edge aa or look at per-vertex coverage if coverage is
|
||||||
// ignored
|
// ignored
|
||||||
if (skipCoverage) {
|
if (skipCoverage) {
|
||||||
desc.fVertexLayout &= ~(kEdge_VertexLayoutBit |
|
desc->fVertexLayout &= ~(kEdge_VertexLayoutBit |
|
||||||
kCoverage_VertexLayoutBit);
|
kCoverage_VertexLayoutBit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -729,40 +713,40 @@ void GrGpuGL::buildProgram(bool isPoints,
|
||||||
(!requiresAttributeColors &&
|
(!requiresAttributeColors &&
|
||||||
0xffffffff == drawState.getColor());
|
0xffffffff == drawState.getColor());
|
||||||
if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) {
|
if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) {
|
||||||
desc.fColorInput = ProgramDesc::kTransBlack_ColorInput;
|
desc->fColorInput = ProgramDesc::kTransBlack_ColorInput;
|
||||||
} else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) {
|
} else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) {
|
||||||
desc.fColorInput = ProgramDesc::kSolidWhite_ColorInput;
|
desc->fColorInput = ProgramDesc::kSolidWhite_ColorInput;
|
||||||
} else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
|
} else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
|
||||||
desc.fColorInput = ProgramDesc::kUniform_ColorInput;
|
desc->fColorInput = ProgramDesc::kUniform_ColorInput;
|
||||||
} else {
|
} else {
|
||||||
desc.fColorInput = ProgramDesc::kAttribute_ColorInput;
|
desc->fColorInput = ProgramDesc::kAttribute_ColorInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool covIsSolidWhite = !requiresAttributeCoverage &&
|
bool covIsSolidWhite = !requiresAttributeCoverage &&
|
||||||
0xffffffff == drawState.getCoverage();
|
0xffffffff == drawState.getCoverage();
|
||||||
|
|
||||||
if (skipCoverage) {
|
if (skipCoverage) {
|
||||||
desc.fCoverageInput = ProgramDesc::kTransBlack_ColorInput;
|
desc->fCoverageInput = ProgramDesc::kTransBlack_ColorInput;
|
||||||
} else if (covIsSolidWhite) {
|
} else if (covIsSolidWhite) {
|
||||||
desc.fCoverageInput = ProgramDesc::kSolidWhite_ColorInput;
|
desc->fCoverageInput = ProgramDesc::kSolidWhite_ColorInput;
|
||||||
} else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
|
} else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
|
||||||
desc.fCoverageInput = ProgramDesc::kUniform_ColorInput;
|
desc->fCoverageInput = ProgramDesc::kUniform_ColorInput;
|
||||||
} else {
|
} else {
|
||||||
desc.fCoverageInput = ProgramDesc::kAttribute_ColorInput;
|
desc->fCoverageInput = ProgramDesc::kAttribute_ColorInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lastEnabledStage = -1;
|
int lastEnabledStage = -1;
|
||||||
|
|
||||||
if (!skipCoverage && (desc.fVertexLayout &
|
if (!skipCoverage && (desc->fVertexLayout &
|
||||||
GrDrawTarget::kEdge_VertexLayoutBit)) {
|
GrDrawTarget::kEdge_VertexLayoutBit)) {
|
||||||
desc.fVertexEdgeType = drawState.getVertexEdgeType();
|
desc->fVertexEdgeType = drawState.getVertexEdgeType();
|
||||||
} else {
|
} else {
|
||||||
// use canonical value when not set to avoid cache misses
|
// use canonical value when not set to avoid cache misses
|
||||||
desc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType;
|
desc->fVertexEdgeType = GrDrawState::kHairLine_EdgeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||||
StageDesc& stage = desc.fStages[s];
|
StageDesc& stage = desc->fStages[s];
|
||||||
|
|
||||||
stage.fOptFlags = 0;
|
stage.fOptFlags = 0;
|
||||||
stage.setEnabled(this->isStageEnabled(s));
|
stage.setEnabled(this->isStageEnabled(s));
|
||||||
|
@ -825,8 +809,7 @@ void GrGpuGL::buildProgram(bool isPoints,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_custom_stage(&stage, sampler, customStages,
|
setup_custom_stage(&stage, sampler, customStages, fCurrentProgram.get(), s);
|
||||||
&fCurrentProgram, s);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
stage.fOptFlags = 0;
|
stage.fOptFlags = 0;
|
||||||
|
@ -841,23 +824,23 @@ void GrGpuGL::buildProgram(bool isPoints,
|
||||||
// when rounding.
|
// when rounding.
|
||||||
GrAssert(4 == GrBytesPerPixel(drawState.getRenderTarget()->config()));
|
GrAssert(4 == GrBytesPerPixel(drawState.getRenderTarget()->config()));
|
||||||
if (kUpOnWrite_DownOnRead_UnpremulConversion == fUnpremulConversion) {
|
if (kUpOnWrite_DownOnRead_UnpremulConversion == fUnpremulConversion) {
|
||||||
desc.fOutputConfig =
|
desc->fOutputConfig =
|
||||||
ProgramDesc::kUnpremultiplied_RoundUp_OutputConfig;
|
ProgramDesc::kUnpremultiplied_RoundUp_OutputConfig;
|
||||||
} else {
|
} else {
|
||||||
desc.fOutputConfig =
|
desc->fOutputConfig =
|
||||||
ProgramDesc::kUnpremultiplied_RoundDown_OutputConfig;
|
ProgramDesc::kUnpremultiplied_RoundDown_OutputConfig;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
desc.fOutputConfig = ProgramDesc::kPremultiplied_OutputConfig;
|
desc->fOutputConfig = ProgramDesc::kPremultiplied_OutputConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput;
|
desc->fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput;
|
||||||
|
|
||||||
// currently the experimental GS will only work with triangle prims
|
// currently the experimental GS will only work with triangle prims
|
||||||
// (and it doesn't do anything other than pass through values from
|
// (and it doesn't do anything other than pass through values from
|
||||||
// the VS to the FS anyway).
|
// the VS to the FS anyway).
|
||||||
#if 0 && GR_GL_EXPERIMENTAL_GS
|
#if 0 && GR_GL_EXPERIMENTAL_GS
|
||||||
desc.fExperimentalGS = this->getCaps().fGeometryShaderSupport;
|
desc->fExperimentalGS = this->getCaps().fGeometryShaderSupport;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// we want to avoid generating programs with different "first cov stage"
|
// we want to avoid generating programs with different "first cov stage"
|
||||||
|
@ -866,7 +849,7 @@ void GrGpuGL::buildProgram(bool isPoints,
|
||||||
// coverage stages or the distinction between coverage and color is
|
// coverage stages or the distinction between coverage and color is
|
||||||
// immaterial.
|
// immaterial.
|
||||||
int firstCoverageStage = GrDrawState::kNumStages;
|
int firstCoverageStage = GrDrawState::kNumStages;
|
||||||
desc.fFirstCoverageStage = GrDrawState::kNumStages;
|
desc->fFirstCoverageStage = GrDrawState::kNumStages;
|
||||||
bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage;
|
bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage;
|
||||||
if (hasCoverage) {
|
if (hasCoverage) {
|
||||||
firstCoverageStage = drawState.getFirstCoverageStage();
|
firstCoverageStage = drawState.getFirstCoverageStage();
|
||||||
|
@ -876,13 +859,13 @@ void GrGpuGL::buildProgram(bool isPoints,
|
||||||
if (!hasCoverage) {
|
if (!hasCoverage) {
|
||||||
hasCoverage =
|
hasCoverage =
|
||||||
requiresAttributeCoverage ||
|
requiresAttributeCoverage ||
|
||||||
(desc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit);
|
(desc->fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasCoverage) {
|
if (hasCoverage) {
|
||||||
// color filter is applied between color/coverage computation
|
// color filter is applied between color/coverage computation
|
||||||
if (SkXfermode::kDst_Mode != desc.fColorFilterXfermode) {
|
if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) {
|
||||||
desc.fFirstCoverageStage = firstCoverageStage;
|
desc->fFirstCoverageStage = firstCoverageStage;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->getCaps().fDualSourceBlendingSupport &&
|
if (this->getCaps().fDualSourceBlendingSupport &&
|
||||||
|
@ -890,18 +873,18 @@ void GrGpuGL::buildProgram(bool isPoints,
|
||||||
kCoverageAsAlpha_BlendOptFlag))) {
|
kCoverageAsAlpha_BlendOptFlag))) {
|
||||||
if (kZero_GrBlendCoeff == dstCoeff) {
|
if (kZero_GrBlendCoeff == dstCoeff) {
|
||||||
// write the coverage value to second color
|
// write the coverage value to second color
|
||||||
desc.fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput;
|
desc->fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput;
|
||||||
desc.fFirstCoverageStage = firstCoverageStage;
|
desc->fFirstCoverageStage = firstCoverageStage;
|
||||||
} else if (kSA_GrBlendCoeff == dstCoeff) {
|
} else if (kSA_GrBlendCoeff == dstCoeff) {
|
||||||
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
|
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
|
||||||
// cover
|
// cover
|
||||||
desc.fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput;
|
desc->fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput;
|
||||||
desc.fFirstCoverageStage = firstCoverageStage;
|
desc->fFirstCoverageStage = firstCoverageStage;
|
||||||
} else if (kSC_GrBlendCoeff == dstCoeff) {
|
} else if (kSC_GrBlendCoeff == dstCoeff) {
|
||||||
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
|
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
|
||||||
// cover
|
// cover
|
||||||
desc.fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput;
|
desc->fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput;
|
||||||
desc.fFirstCoverageStage = firstCoverageStage;
|
desc->fFirstCoverageStage = firstCoverageStage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,8 +231,6 @@ bool GrGpuGL::programUnitTest() {
|
||||||
StageDesc::kSmearAlpha_InConfigFlag,
|
StageDesc::kSmearAlpha_InConfigFlag,
|
||||||
StageDesc::kSmearRed_InConfigFlag,
|
StageDesc::kSmearRed_InConfigFlag,
|
||||||
};
|
};
|
||||||
GrGLProgram program;
|
|
||||||
ProgramDesc& pdesc = program.fProgramDesc;
|
|
||||||
|
|
||||||
static const int NUM_TESTS = 512;
|
static const int NUM_TESTS = 512;
|
||||||
|
|
||||||
|
@ -247,6 +245,7 @@ bool GrGpuGL::programUnitTest() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ProgramDesc pdesc;
|
||||||
pdesc.fVertexLayout = 0;
|
pdesc.fVertexLayout = 0;
|
||||||
pdesc.fEmitsPointSize = random.nextF() > .5f;
|
pdesc.fEmitsPointSize = random.nextF() > .5f;
|
||||||
pdesc.fColorInput = random_int(&random, ProgramDesc::kColorInputCnt);
|
pdesc.fColorInput = random_int(&random, ProgramDesc::kColorInputCnt);
|
||||||
|
@ -317,14 +316,15 @@ bool GrGpuGL::programUnitTest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CachedData cachedData;
|
|
||||||
GR_STATIC_ASSERT(sizeof(customStages) ==
|
GR_STATIC_ASSERT(sizeof(customStages) ==
|
||||||
GrDrawState::kNumStages * sizeof(GrCustomStage*));
|
GrDrawState::kNumStages * sizeof(GrCustomStage*));
|
||||||
GrCustomStage** stages = reinterpret_cast<GrCustomStage**>(&customStages);
|
GrCustomStage** stages = reinterpret_cast<GrCustomStage**>(&customStages);
|
||||||
if (!program.genProgram(this->glContextInfo(), stages, &cachedData)) {
|
SkAutoTUnref<GrGLProgram> program(SkNEW(GrGLProgram));
|
||||||
|
|
||||||
|
if (!program->genProgram(this->glContextInfo(), pdesc, stages)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
DeleteProgram(this->glInterface(), &cachedData);
|
DeleteProgram(this->glInterface(), program);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,10 +87,10 @@ static void test_binHashKey()
|
||||||
kDataLenUsedForKey = 8
|
kDataLenUsedForKey = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
GrBinHashKey<BogusEntry, kDataLenUsedForKey> keyA;
|
GrTBinHashKey<BogusEntry, kDataLenUsedForKey> keyA;
|
||||||
keyA.setKeyData(testStringA);
|
keyA.setKeyData(testStringA);
|
||||||
// test copy constructor and comparison
|
// test copy constructor and comparison
|
||||||
GrBinHashKey<BogusEntry, kDataLenUsedForKey> keyA2(keyA);
|
GrTBinHashKey<BogusEntry, kDataLenUsedForKey> keyA2(keyA);
|
||||||
GrAssert(keyA.compare(keyA2) == 0);
|
GrAssert(keyA.compare(keyA2) == 0);
|
||||||
GrAssert(keyA.getHash() == keyA2.getHash());
|
GrAssert(keyA.getHash() == keyA2.getHash());
|
||||||
// test re-init
|
// test re-init
|
||||||
|
@ -98,7 +98,7 @@ static void test_binHashKey()
|
||||||
GrAssert(keyA.compare(keyA2) == 0);
|
GrAssert(keyA.compare(keyA2) == 0);
|
||||||
GrAssert(keyA.getHash() == keyA2.getHash());
|
GrAssert(keyA.getHash() == keyA2.getHash());
|
||||||
// test sorting
|
// test sorting
|
||||||
GrBinHashKey<BogusEntry, kDataLenUsedForKey> keyB;
|
GrTBinHashKey<BogusEntry, kDataLenUsedForKey> keyB;
|
||||||
keyB.setKeyData(testStringB);
|
keyB.setKeyData(testStringB);
|
||||||
GrAssert(keyA.compare(keyB) < 0);
|
GrAssert(keyA.compare(keyB) < 0);
|
||||||
GrAssert(keyA.getHash() != keyB.getHash());
|
GrAssert(keyA.getHash() != keyB.getHash());
|
||||||
|
|
Загрузка…
Ссылка в новой задаче