Automatically handle converting gl_FragCoord to Skia's y-down device coords.
NOTE: THIS WILL LIKELY REQUIRE GM REBASELINING. R=robertphillips@google.com,senorblanco@chromium.org Review URL: https://codereview.appspot.com/6744061 git-svn-id: http://skia.googlecode.com/svn/trunk@6030 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
c2e8cef479
commit
4fe9b1b740
@ -42,14 +42,7 @@ void setUniformPoint3(const GrGLUniformManager& uman, UniformHandle uni, const S
|
||||
}
|
||||
|
||||
void setUniformNormal3(const GrGLUniformManager& uman, UniformHandle uni, const SkPoint3& point) {
|
||||
setUniformPoint3(uman, uni, SkPoint3(point.fX, -point.fY, point.fZ));
|
||||
}
|
||||
|
||||
void setUniformPoint3FlipY(const GrGLUniformManager& uman,
|
||||
UniformHandle uni,
|
||||
const SkPoint3& point,
|
||||
int height) {
|
||||
setUniformPoint3(uman, uni, SkPoint3(point.fX, height-point.fY, point.fZ));
|
||||
setUniformPoint3(uman, uni, SkPoint3(point.fX, point.fY, point.fZ));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -376,7 +369,7 @@ public:
|
||||
virtual void setupVariables(GrGLShaderBuilder* builder);
|
||||
virtual void emitVS(SkString* out) const {}
|
||||
virtual void emitFuncs(GrGLShaderBuilder* builder) {}
|
||||
virtual void emitSurfaceToLight(const GrGLShaderBuilder*,
|
||||
virtual void emitSurfaceToLight(GrGLShaderBuilder*,
|
||||
SkString* out,
|
||||
const char* z) const = 0;
|
||||
virtual void emitLightColor(GrGLShaderBuilder*,
|
||||
@ -397,7 +390,7 @@ public:
|
||||
virtual ~GrGLDistantLight() {}
|
||||
virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
|
||||
virtual void setData(const GrGLUniformManager&, const GrRenderTarget* rt, const SkLight* light) const SK_OVERRIDE;
|
||||
virtual void emitSurfaceToLight(const GrGLShaderBuilder*,
|
||||
virtual void emitSurfaceToLight(GrGLShaderBuilder*,
|
||||
SkString* out,
|
||||
const char* z) const SK_OVERRIDE;
|
||||
private:
|
||||
@ -413,7 +406,7 @@ public:
|
||||
virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
|
||||
virtual void setData(const GrGLUniformManager&, const GrRenderTarget* rt, const SkLight* light) const SK_OVERRIDE;
|
||||
virtual void emitVS(SkString* out) const SK_OVERRIDE;
|
||||
virtual void emitSurfaceToLight(const GrGLShaderBuilder*,
|
||||
virtual void emitSurfaceToLight(GrGLShaderBuilder*,
|
||||
SkString* out,
|
||||
const char* z) const SK_OVERRIDE;
|
||||
private:
|
||||
@ -431,7 +424,7 @@ public:
|
||||
virtual void setData(const GrGLUniformManager&, const GrRenderTarget* rt, const SkLight* light) const SK_OVERRIDE;
|
||||
virtual void emitVS(SkString* out) const SK_OVERRIDE;
|
||||
virtual void emitFuncs(GrGLShaderBuilder* builder);
|
||||
virtual void emitSurfaceToLight(const GrGLShaderBuilder* builder,
|
||||
virtual void emitSurfaceToLight(GrGLShaderBuilder* builder,
|
||||
SkString* out,
|
||||
const char* z) const SK_OVERRIDE;
|
||||
virtual void emitLightColor(GrGLShaderBuilder*,
|
||||
@ -1133,7 +1126,7 @@ void GrGLLightingEffect::emitFS(GrGLShaderBuilder* builder,
|
||||
"pointToNormal",
|
||||
SK_ARRAY_COUNT(gPointToNormalArgs),
|
||||
gPointToNormalArgs,
|
||||
"\treturn normalize(vec3(-x * scale, -y * scale, 1));\n",
|
||||
"\treturn normalize(vec3(-x * scale, y * scale, 1));\n",
|
||||
&pointToNormalName);
|
||||
|
||||
static const GrGLShaderVar gInteriorNormalArgs[] = {
|
||||
@ -1364,7 +1357,7 @@ void GrGLDistantLight::setData(const GrGLUniformManager& uman,
|
||||
setUniformNormal3(uman, fDirectionUni, distantLight->direction());
|
||||
}
|
||||
|
||||
void GrGLDistantLight::emitSurfaceToLight(const GrGLShaderBuilder* builder,
|
||||
void GrGLDistantLight::emitSurfaceToLight(GrGLShaderBuilder* builder,
|
||||
SkString* out,
|
||||
const char* z) const {
|
||||
const char* dir = builder->getUniformCStr(fDirectionUni);
|
||||
@ -1385,17 +1378,17 @@ void GrGLPointLight::setData(const GrGLUniformManager& uman,
|
||||
INHERITED::setData(uman, rt, light);
|
||||
SkASSERT(light->type() == SkLight::kPoint_LightType);
|
||||
const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
|
||||
setUniformPoint3FlipY(uman, fLocationUni, pointLight->location(), rt->height());
|
||||
setUniformPoint3(uman, fLocationUni, pointLight->location());
|
||||
}
|
||||
|
||||
void GrGLPointLight::emitVS(SkString* out) const {
|
||||
}
|
||||
|
||||
void GrGLPointLight::emitSurfaceToLight(const GrGLShaderBuilder* builder,
|
||||
void GrGLPointLight::emitSurfaceToLight(GrGLShaderBuilder* builder,
|
||||
SkString* out,
|
||||
const char* z) const {
|
||||
const char* loc = builder->getUniformCStr(fLocationUni);
|
||||
out->appendf("normalize(%s - vec3(gl_FragCoord.xy, %s))", loc, z);
|
||||
out->appendf("normalize(%s - vec3(%s.xy, %s))", loc, builder->fragmentPosition(), z);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -1422,7 +1415,7 @@ void GrGLSpotLight::setData(const GrGLUniformManager& uman,
|
||||
INHERITED::setData(uman, rt, light);
|
||||
SkASSERT(light->type() == SkLight::kSpot_LightType);
|
||||
const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
|
||||
setUniformPoint3FlipY(uman, fLocationUni, spotLight->location(), rt->height());
|
||||
setUniformPoint3(uman, fLocationUni, spotLight->location());
|
||||
uman.set1f(fExponentUni, spotLight->specularExponent());
|
||||
uman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
|
||||
uman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
|
||||
@ -1463,11 +1456,11 @@ void GrGLSpotLight::emitFuncs(GrGLShaderBuilder* builder) {
|
||||
&fLightColorFunc);
|
||||
}
|
||||
|
||||
void GrGLSpotLight::emitSurfaceToLight(const GrGLShaderBuilder* builder,
|
||||
void GrGLSpotLight::emitSurfaceToLight(GrGLShaderBuilder* builder,
|
||||
SkString* out,
|
||||
const char* z) const {
|
||||
const char* location= builder->getUniformCStr(fLocationUni);
|
||||
out->appendf("normalize(%s - vec3(gl_FragCoord.xy, %s))", location, z);
|
||||
out->appendf("normalize(%s - vec3(%s.xy, %s))", location, builder->fragmentPosition(), z);
|
||||
}
|
||||
|
||||
void GrGLSpotLight::emitLightColor(GrGLShaderBuilder* builder,
|
||||
|
@ -458,16 +458,7 @@ void add_line(const SkPoint p[2],
|
||||
if (orthVec.setLength(SK_Scalar1)) {
|
||||
orthVec.setOrthog(orthVec);
|
||||
|
||||
// the values we pass down to the frag shader
|
||||
// have to be in y-points-up space;
|
||||
SkVector normal;
|
||||
normal.fX = orthVec.fX;
|
||||
normal.fY = -orthVec.fY;
|
||||
SkPoint aYDown;
|
||||
aYDown.fX = a.fX;
|
||||
aYDown.fY = rtHeight - a.fY;
|
||||
|
||||
SkScalar lineC = -(aYDown.dot(normal));
|
||||
SkScalar lineC = -(a.dot(orthVec));
|
||||
for (int i = 0; i < kVertsPerLineSeg; ++i) {
|
||||
(*vert)[i].fPos = (i < 2) ? a : b;
|
||||
if (0 == i || 3 == i) {
|
||||
@ -475,8 +466,8 @@ void add_line(const SkPoint p[2],
|
||||
} else {
|
||||
(*vert)[i].fPos += orthVec;
|
||||
}
|
||||
(*vert)[i].fLine.fA = normal.fX;
|
||||
(*vert)[i].fLine.fB = normal.fY;
|
||||
(*vert)[i].fLine.fA = orthVec.fX;
|
||||
(*vert)[i].fLine.fB = orthVec.fY;
|
||||
(*vert)[i].fLine.fC = lineC;
|
||||
}
|
||||
if (NULL != toSrc) {
|
||||
|
@ -1061,9 +1061,7 @@ void GrContext::drawOval(const GrPaint& paint,
|
||||
verts[3].fPos = SkPoint::Make(R, B);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
// this goes to fragment shader, it should be in y-points-up space.
|
||||
verts[i].fCenter = SkPoint::Make(center.fX, rt->height() - center.fY);
|
||||
|
||||
verts[i].fCenter = center;
|
||||
verts[i].fOuterRadius = outerRadius;
|
||||
verts[i].fInnerRadius = innerRadius;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ void GrGLCaps::reset() {
|
||||
fTextureRedSupport = false;
|
||||
fImagingSupport = false;
|
||||
fTwoFormatLimit = false;
|
||||
fFragCoordsConventionSupport = false;
|
||||
}
|
||||
|
||||
GrGLCaps::GrGLCaps(const GrGLCaps& caps) {
|
||||
@ -65,6 +66,7 @@ GrGLCaps& GrGLCaps::operator = (const GrGLCaps& caps) {
|
||||
fTextureRedSupport = caps.fTextureRedSupport;
|
||||
fImagingSupport = caps.fImagingSupport;
|
||||
fTwoFormatLimit = caps.fTwoFormatLimit;
|
||||
fFragCoordsConventionSupport = caps.fFragCoordsConventionSupport;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -158,6 +160,9 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo) {
|
||||
// can change based on which render target is bound
|
||||
fTwoFormatLimit = kES2_GrGLBinding == binding;
|
||||
|
||||
fFragCoordsConventionSupport = ctxInfo.glslGeneration() >= k150_GrGLSLGeneration ||
|
||||
ctxInfo.hasExtension("GL_ARB_fragment_coord_conventions");
|
||||
|
||||
this->initFSAASupport(ctxInfo);
|
||||
this->initStencilFormats(ctxInfo);
|
||||
}
|
||||
|
@ -216,6 +216,9 @@ public:
|
||||
/// Is GL_ARB_IMAGING supported
|
||||
bool imagingSupport() const { return fImagingSupport; }
|
||||
|
||||
/// Is GL_ARB_fragment_coord_conventions supported?
|
||||
bool fragCoordConventionsSupport() const { return fFragCoordsConventionSupport; }
|
||||
|
||||
// Does ReadPixels support the provided format/type combo?
|
||||
bool readPixelsSupported(const GrGLInterface* intf,
|
||||
GrGLenum format,
|
||||
@ -293,6 +296,7 @@ private:
|
||||
bool fTextureRedSupport : 1;
|
||||
bool fImagingSupport : 1;
|
||||
bool fTwoFormatLimit : 1;
|
||||
bool fFragCoordsConventionSupport : 1;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -77,6 +77,7 @@ GrGLProgram::GrGLProgram(const GrGLContextInfo& gl,
|
||||
fViewportSize.set(-1, -1);
|
||||
fColor = GrColor_ILLEGAL;
|
||||
fColorFilterColor = GrColor_ILLEGAL;
|
||||
fRTHeight = -1;
|
||||
|
||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||
fProgramStage[s] = NULL;
|
||||
@ -234,56 +235,57 @@ static void addColorFilter(SkString* fsCode, const char * outputVar,
|
||||
}
|
||||
|
||||
bool GrGLProgram::genEdgeCoverage(SkString* coverageVar,
|
||||
GrGLShaderBuilder* segments) const {
|
||||
GrGLShaderBuilder* builder) const {
|
||||
if (fDesc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit) {
|
||||
const char *vsName, *fsName;
|
||||
segments->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName);
|
||||
segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
|
||||
GrGLShaderVar::kAttribute_TypeModifier, EDGE_ATTR_NAME);
|
||||
segments->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
|
||||
builder->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName);
|
||||
builder->fVSAttrs.push_back().set(kVec4f_GrSLType,
|
||||
GrGLShaderVar::kAttribute_TypeModifier,
|
||||
EDGE_ATTR_NAME);
|
||||
builder->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
|
||||
switch (fDesc.fVertexEdgeType) {
|
||||
case GrDrawState::kHairLine_EdgeType:
|
||||
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");
|
||||
builder->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(%s.xy,1), %s.xyz));\n", builder->fragmentPosition(), fsName);
|
||||
builder->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
|
||||
break;
|
||||
case GrDrawState::kQuad_EdgeType:
|
||||
segments->fFSCode.append("\tfloat edgeAlpha;\n");
|
||||
builder->fFSCode.append("\tfloat edgeAlpha;\n");
|
||||
// keep the derivative instructions outside the conditional
|
||||
segments->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
|
||||
segments->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
|
||||
segments->fFSCode.appendf("\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName);
|
||||
builder->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
|
||||
builder->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
|
||||
builder->fFSCode.appendf("\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName);
|
||||
// today we know z and w are in device space. We could use derivatives
|
||||
segments->fFSCode.appendf("\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName);
|
||||
segments->fFSCode.append ("\t} else {\n");
|
||||
segments->fFSCode.appendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
|
||||
"\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n",
|
||||
fsName, fsName);
|
||||
segments->fFSCode.appendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
|
||||
segments->fFSCode.append("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n"
|
||||
"\t}\n");
|
||||
builder->fFSCode.appendf("\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName);
|
||||
builder->fFSCode.append ("\t} else {\n");
|
||||
builder->fFSCode.appendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
|
||||
"\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n",
|
||||
fsName, fsName);
|
||||
builder->fFSCode.appendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
|
||||
builder->fFSCode.append("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n"
|
||||
"\t}\n");
|
||||
if (kES2_GrGLBinding == fContextInfo.binding()) {
|
||||
segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
|
||||
builder->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
|
||||
}
|
||||
break;
|
||||
case GrDrawState::kHairQuad_EdgeType:
|
||||
segments->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
|
||||
segments->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
|
||||
segments->fFSCode.appendf("\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
|
||||
"\t 2.0*%s.x*duvdy.x - duvdy.y);\n",
|
||||
fsName, fsName);
|
||||
segments->fFSCode.appendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
|
||||
segments->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
|
||||
segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
|
||||
builder->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
|
||||
builder->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
|
||||
builder->fFSCode.appendf("\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
|
||||
"\t 2.0*%s.x*duvdy.x - duvdy.y);\n",
|
||||
fsName, fsName);
|
||||
builder->fFSCode.appendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
|
||||
builder->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
|
||||
builder->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
|
||||
if (kES2_GrGLBinding == fContextInfo.binding()) {
|
||||
segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
|
||||
builder->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
|
||||
}
|
||||
break;
|
||||
case GrDrawState::kCircle_EdgeType:
|
||||
segments->fFSCode.append("\tfloat edgeAlpha;\n");
|
||||
segments->fFSCode.appendf("\tfloat d = distance(gl_FragCoord.xy, %s.xy);\n", fsName);
|
||||
segments->fFSCode.appendf("\tfloat outerAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName);
|
||||
segments->fFSCode.appendf("\tfloat innerAlpha = %s.w == 0.0 ? 1.0 : smoothstep(%s.w - 0.5, %s.w + 0.5, d);\n", fsName, fsName, fsName);
|
||||
segments->fFSCode.append("\tedgeAlpha = outerAlpha * innerAlpha;\n");
|
||||
builder->fFSCode.append("\tfloat edgeAlpha;\n");
|
||||
builder->fFSCode.appendf("\tfloat d = distance(%s.xy, %s.xy);\n", builder->fragmentPosition(), fsName);
|
||||
builder->fFSCode.appendf("\tfloat outerAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName);
|
||||
builder->fFSCode.appendf("\tfloat innerAlpha = %s.w == 0.0 ? 1.0 : smoothstep(%s.w - 0.5, %s.w + 0.5, d);\n", fsName, fsName, fsName);
|
||||
builder->fFSCode.append("\tedgeAlpha = outerAlpha * innerAlpha;\n");
|
||||
break;
|
||||
default:
|
||||
GrCrash("Unknown Edge Type!");
|
||||
@ -807,6 +809,7 @@ bool GrGLProgram::genProgram(const GrCustomStage** customStages) {
|
||||
|
||||
builder.finished(fProgramID);
|
||||
this->initSamplerUniforms();
|
||||
fUniforms.fRTHeight = builder.getRTHeightUniform();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -964,7 +967,13 @@ GrGLProgramStage* GrGLProgram::GenStageCode(const GrCustomStage* stage,
|
||||
return glStage;
|
||||
}
|
||||
|
||||
void GrGLProgram::setData(const GrDrawState& drawState) const {
|
||||
void GrGLProgram::setData(const GrDrawState& drawState) {
|
||||
int rtHeight = drawState.getRenderTarget()->height();
|
||||
if (GrGLUniformManager::kInvalidUniformHandle != fUniforms.fRTHeight &&
|
||||
rtHeight != fRTHeight) {
|
||||
fUniformManager.set1f(fUniforms.fRTHeight, GrIntToScalar(rtHeight));
|
||||
fRTHeight = rtHeight;
|
||||
}
|
||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||
if (NULL != fProgramStage[s]) {
|
||||
const GrSamplerState& sampler = drawState.getSampler(s);
|
||||
|
@ -72,7 +72,7 @@ public:
|
||||
* This function uploads uniforms and calls each GrCustomStage's setData. It is called before a
|
||||
* draw occurs using the program after the program has already been bound.
|
||||
*/
|
||||
void setData(const GrDrawState& drawState) const;
|
||||
void setData(const GrDrawState& drawState);
|
||||
|
||||
// Parameters that affect code generation
|
||||
// These structs should be kept compact; they are the input to an
|
||||
@ -221,12 +221,16 @@ private:
|
||||
UniformHandle fColorUni;
|
||||
UniformHandle fCoverageUni;
|
||||
UniformHandle fColorFilterUni;
|
||||
// We use the render target height to provide a y-down frag coord when specifying
|
||||
// origin_upper_left is not supported.
|
||||
UniformHandle fRTHeight;
|
||||
StageUniforms fStages[GrDrawState::kNumStages];
|
||||
Uniforms() {
|
||||
fViewMatrixUni = GrGLUniformManager::kInvalidUniformHandle;
|
||||
fColorUni = GrGLUniformManager::kInvalidUniformHandle;
|
||||
fCoverageUni = GrGLUniformManager::kInvalidUniformHandle;
|
||||
fColorFilterUni = GrGLUniformManager::kInvalidUniformHandle;
|
||||
fRTHeight = GrGLUniformManager::kInvalidUniformHandle;
|
||||
}
|
||||
};
|
||||
|
||||
@ -246,6 +250,7 @@ private:
|
||||
GrColor fColor;
|
||||
GrColor fCoverage;
|
||||
GrColor fColorFilterColor;
|
||||
int fRTHeight;
|
||||
/// When it is sent to GL, the texture matrix will be flipped if the texture orientation
|
||||
/// (below) requires.
|
||||
GrMatrix fTextureMatrices[GrDrawState::kNumStages];
|
||||
|
@ -93,13 +93,15 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctx, GrGLUniformMana
|
||||
, fContext(ctx)
|
||||
, fUniformManager(uniformManager)
|
||||
, fCurrentStage(kNonStageIdx)
|
||||
, fSetupFragPosition(false)
|
||||
, fRTHeightUniform(GrGLUniformManager::kInvalidUniformHandle)
|
||||
, fTexCoordVaryingType(kVoid_GrSLType) {
|
||||
}
|
||||
|
||||
void GrGLShaderBuilder::setupTextureAccess(const char* varyingFSName, GrSLType varyingType) {
|
||||
// FIXME: We don't know how the custom stage will manipulate the coords. So we give up on using
|
||||
// projective texturing and always give the stage 2D coords. This will be fixed when custom
|
||||
// stages are repsonsible for setting up their own tex coords / tex matrices.
|
||||
// stages are responsible for setting up their own tex coords / tex matrices.
|
||||
switch (varyingType) {
|
||||
case kVec2f_GrSLType:
|
||||
fDefaultTexCoordsName = varyingFSName;
|
||||
@ -283,6 +285,39 @@ void GrGLShaderBuilder::addVarying(GrSLType type,
|
||||
}
|
||||
}
|
||||
|
||||
const char* GrGLShaderBuilder::fragmentPosition() {
|
||||
if (fContext.caps().fragCoordConventionsSupport()) {
|
||||
if (!fSetupFragPosition) {
|
||||
this->fFSHeader.append("layout(origin_upper_left) in vec4 gl_FragCoord;\n");
|
||||
fSetupFragPosition = true;
|
||||
}
|
||||
return "gl_FragCoord";
|
||||
} else {
|
||||
static const char* kCoordName = "fragCoordYDown";
|
||||
if (!fSetupFragPosition) {
|
||||
GrAssert(GrGLUniformManager::kInvalidUniformHandle == fRTHeightUniform);
|
||||
const char* rtHeightName;
|
||||
|
||||
// temporarily change the stage index because we're inserting a uniform whose name
|
||||
// shouldn't be mangled to be stage-specific.
|
||||
int oldStageIdx = fCurrentStage;
|
||||
fCurrentStage = kNonStageIdx;
|
||||
fRTHeightUniform = this->addUniform(kFragment_ShaderType,
|
||||
kFloat_GrSLType,
|
||||
"RTHeight",
|
||||
&rtHeightName);
|
||||
fCurrentStage = oldStageIdx;
|
||||
|
||||
this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n",
|
||||
kCoordName, rtHeightName);
|
||||
fSetupFragPosition = true;
|
||||
}
|
||||
GrAssert(GrGLUniformManager::kInvalidUniformHandle != fRTHeightUniform);
|
||||
return kCoordName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GrGLShaderBuilder::emitFunction(ShaderType shader,
|
||||
GrSLType returnType,
|
||||
const char* name,
|
||||
@ -381,6 +416,7 @@ void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
|
||||
append_default_precision_qualifier(kDefaultFragmentPrecision,
|
||||
fContext.binding(),
|
||||
shaderStr);
|
||||
shaderStr->append(fFSHeader);
|
||||
this->appendUniformDecls(kFragment_ShaderType, shaderStr);
|
||||
this->appendDecls(fFSInputs, shaderStr);
|
||||
// We shouldn't have declared outputs on 1.10
|
||||
|
@ -129,7 +129,7 @@ public:
|
||||
the generated shader code. This potentially allows greater reuse of cached shaders. */
|
||||
static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
|
||||
|
||||
/** Add a uniform variable to the current program, that has visibilty in one or more shaders.
|
||||
/** Add a uniform variable to the current program, that has visibility in one or more shaders.
|
||||
visibility is a bitfield of ShaderType values indicating from which shaders the uniform
|
||||
should be accessible. At least one bit must be set. Geometry shader uniforms are not
|
||||
supported at this time. The actual uniform name will be mangled. If outName is not NULL then
|
||||
@ -151,7 +151,7 @@ public:
|
||||
const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle) const;
|
||||
|
||||
/**
|
||||
* Shorcut for getUniformVariable(u).c_str()
|
||||
* Shortcut for getUniformVariable(u).c_str()
|
||||
*/
|
||||
const char* getUniformCStr(GrGLUniformManager::UniformHandle u) const {
|
||||
return this->getUniformVariable(u).c_str();
|
||||
@ -165,6 +165,10 @@ public:
|
||||
const char** vsOutName = NULL,
|
||||
const char** fsInName = NULL);
|
||||
|
||||
/** Returns a variable name that represents the position of the fragment in the FS. The position
|
||||
is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
|
||||
const char* fragmentPosition();
|
||||
|
||||
/** Called after building is complete to get the final shader string. */
|
||||
void getShader(ShaderType, SkString*) const;
|
||||
|
||||
@ -180,6 +184,8 @@ public:
|
||||
void setCurrentStage(int stage) { fCurrentStage = stage; }
|
||||
void setNonStage() { fCurrentStage = kNonStageIdx; }
|
||||
|
||||
GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
|
||||
|
||||
private:
|
||||
|
||||
typedef GrTAllocator<GrGLShaderVar> VarArray;
|
||||
@ -211,10 +217,14 @@ private:
|
||||
kNonStageIdx = -1,
|
||||
};
|
||||
|
||||
const GrGLContextInfo& fContext;
|
||||
GrGLUniformManager& fUniformManager;
|
||||
int fCurrentStage;
|
||||
SkString fFSFunctions;
|
||||
const GrGLContextInfo& fContext;
|
||||
GrGLUniformManager& fUniformManager;
|
||||
int fCurrentStage;
|
||||
SkString fFSFunctions;
|
||||
SkString fFSHeader;
|
||||
|
||||
bool fSetupFragPosition;
|
||||
GrGLUniformManager::UniformHandle fRTHeightUniform;
|
||||
|
||||
/// Per-stage settings - only valid while we're inside GrGLProgram::genStageCode().
|
||||
//@{
|
||||
|
Loading…
Reference in New Issue
Block a user