Revert "Replaced all calls to fragmentPosition() with sk_FragCoord"
This reverts commit de4d301881
.
Reason for revert: several Chrome rendering bugs on Mac
BUG=skia:
Change-Id: I492082b0b7e7c902ede4b598c5809f604d210ce1
Reviewed-on: https://skia-review.googlesource.com/7887
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
ebfbba9bbd
commit
cae3a4c8ab
@ -105,7 +105,8 @@ public:
|
||||
*/
|
||||
enum RequiredFeatures {
|
||||
kNone_RequiredFeatures = 0,
|
||||
kSampleLocations_RequiredFeature = 1 << 0
|
||||
kFragmentPosition_RequiredFeature = 1 << 0,
|
||||
kSampleLocations_RequiredFeature = 1 << 1
|
||||
};
|
||||
|
||||
GR_DECL_BITFIELD_OPS_FRIENDS(RequiredFeatures);
|
||||
@ -147,6 +148,7 @@ protected:
|
||||
* must call these methods from its constructor. Otherwise, requests to use these features will
|
||||
* be denied.
|
||||
*/
|
||||
void setWillReadFragmentPosition() { fRequiredFeatures |= kFragmentPosition_RequiredFeature; }
|
||||
void setWillUseSampleLocations() { fRequiredFeatures |= kSampleLocations_RequiredFeature; }
|
||||
|
||||
void combineRequiredFeatures(const GrProcessor& other) {
|
||||
|
@ -47,6 +47,7 @@ void GrCircleBlurFragmentProcessor::GLSLProcessor::emitCode(EmitArgs& args) {
|
||||
&dataName);
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const char *fragmentPos = fragBuilder->fragmentPosition();
|
||||
|
||||
if (args.fInputColor) {
|
||||
fragBuilder->codeAppendf("vec4 src=%s;", args.fInputColor);
|
||||
@ -56,9 +57,9 @@ void GrCircleBlurFragmentProcessor::GLSLProcessor::emitCode(EmitArgs& args) {
|
||||
|
||||
// We just want to compute "(length(vec) - %s.z + 0.5) * %s.w" but need to rearrange
|
||||
// for precision.
|
||||
fragBuilder->codeAppendf("vec2 vec = vec2( (sk_FragCoord.x - %s.x) * %s.w, "
|
||||
"(sk_FragCoord.y - %s.y) * %s.w );",
|
||||
dataName, dataName, dataName, dataName);
|
||||
fragBuilder->codeAppendf("vec2 vec = vec2( (%s.x - %s.x) * %s.w , (%s.y - %s.y) * %s.w );",
|
||||
fragmentPos, dataName, dataName,
|
||||
fragmentPos, dataName, dataName);
|
||||
fragBuilder->codeAppendf("float dist = length(vec) + (0.5 - %s.z) * %s.w;",
|
||||
dataName, dataName);
|
||||
|
||||
@ -95,6 +96,7 @@ GrCircleBlurFragmentProcessor::GrCircleBlurFragmentProcessor(const SkRect& circl
|
||||
, fBlurProfileSampler(blurProfile, GrSamplerParams::kBilerp_FilterMode) {
|
||||
this->initClassID<GrCircleBlurFragmentProcessor>();
|
||||
this->addTextureSampler(&fBlurProfileSampler);
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
GrGLSLFragmentProcessor* GrCircleBlurFragmentProcessor::onCreateGLSLInstance() const {
|
||||
|
@ -904,6 +904,7 @@ void GrGLRectBlurEffect::emitCode(EmitArgs& args) {
|
||||
&profileSizeName);
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const char *fragmentPos = fragBuilder->fragmentPosition();
|
||||
|
||||
if (args.fInputColor) {
|
||||
fragBuilder->codeAppendf("vec4 src=%s;", args.fInputColor);
|
||||
@ -911,8 +912,8 @@ void GrGLRectBlurEffect::emitCode(EmitArgs& args) {
|
||||
fragBuilder->codeAppendf("vec4 src=vec4(1);");
|
||||
}
|
||||
|
||||
fragBuilder->codeAppendf("%s vec2 translatedPos = sk_FragCoord.xy - %s.xy;",
|
||||
precisionString.c_str(), rectName);
|
||||
fragBuilder->codeAppendf("%s vec2 translatedPos = %s.xy - %s.xy;", precisionString.c_str(),
|
||||
fragmentPos, rectName);
|
||||
fragBuilder->codeAppendf("%s float width = %s.z - %s.x;", precisionString.c_str(), rectName,
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("%s float height = %s.w - %s.y;", precisionString.c_str(), rectName,
|
||||
@ -983,6 +984,7 @@ GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture* b
|
||||
, fPrecision(precision) {
|
||||
this->initClassID<GrRectBlurEffect>();
|
||||
this->addTextureSampler(&fBlurProfileSampler);
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
void GrRectBlurEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
@ -1216,6 +1218,7 @@ GrRRectBlurEffect::GrRRectBlurEffect(float sigma, const SkRRect& rrect, GrTextur
|
||||
, fNinePatchSampler(ninePatchTexture) {
|
||||
this->initClassID<GrRRectBlurEffect>();
|
||||
this->addTextureSampler(&fNinePatchSampler);
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
bool GrRRectBlurEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
@ -1283,11 +1286,12 @@ void GrGLRRectBlurEffect::emitCode(EmitArgs& args) {
|
||||
&blurRadiusName);
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const char* fragmentPos = fragBuilder->fragmentPosition();
|
||||
|
||||
// warp the fragment position to the appropriate part of the 9patch blur texture
|
||||
|
||||
fragBuilder->codeAppendf("vec2 rectCenter = (%s.xy + %s.zw)/2.0;", rectName, rectName);
|
||||
fragBuilder->codeAppendf("vec2 translatedFragPos = sk_FragCoord.xy - %s.xy;", rectName);
|
||||
fragBuilder->codeAppendf("vec2 translatedFragPos = %s.xy - %s.xy;", fragmentPos, rectName);
|
||||
fragBuilder->codeAppendf("float threshold = %s + 2.0*%s;", cornerRadiusName, blurRadiusName);
|
||||
fragBuilder->codeAppendf("vec2 middle = %s.zw - %s.xy - 2.0*threshold;", rectName, rectName);
|
||||
|
||||
|
@ -770,6 +770,8 @@ public:
|
||||
virtual bool isEqual(const SkImageFilterLight& other) const {
|
||||
return fColor == other.fColor;
|
||||
}
|
||||
// Called to know whether the generated GrGLLight will require access to the fragment position.
|
||||
virtual bool requiresFragmentPosition() const = 0;
|
||||
virtual SkImageFilterLight* transform(const SkMatrix& matrix) const = 0;
|
||||
|
||||
// Defined below SkLight's subclasses.
|
||||
@ -818,6 +820,7 @@ public:
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
bool requiresFragmentPosition() const override { return false; }
|
||||
|
||||
bool isEqual(const SkImageFilterLight& other) const override {
|
||||
if (other.type() != kDistant_LightType) {
|
||||
@ -876,6 +879,7 @@ public:
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
bool requiresFragmentPosition() const override { return true; }
|
||||
bool isEqual(const SkImageFilterLight& other) const override {
|
||||
if (other.type() != kPoint_LightType) {
|
||||
return false;
|
||||
@ -989,6 +993,7 @@ public:
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
bool requiresFragmentPosition() const override { return true; }
|
||||
LightType type() const override { return kSpot_LightType; }
|
||||
const SkPoint3& location() const { return fLocation; }
|
||||
const SkPoint3& target() const { return fTarget; }
|
||||
@ -1710,6 +1715,9 @@ GrLightingEffect::GrLightingEffect(GrTexture* texture,
|
||||
, fBoundaryMode(boundaryMode)
|
||||
, fDomain(create_domain(texture, srcBounds, GrTextureDomain::kDecal_Mode)) {
|
||||
fLight->ref();
|
||||
if (light->requiresFragmentPosition()) {
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
}
|
||||
|
||||
GrLightingEffect::~GrLightingEffect() {
|
||||
@ -2094,8 +2102,8 @@ void GrGLPointLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
|
||||
fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec3f_GrSLType, kDefault_GrSLPrecision,
|
||||
"LightLocation", &loc);
|
||||
fragBuilder->codeAppendf("normalize(%s - vec3(sk_FragCoord.xy, %s))",
|
||||
loc, z);
|
||||
fragBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))",
|
||||
loc, fragBuilder->fragmentPosition(), z);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -2121,8 +2129,8 @@ void GrGLSpotLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
|
||||
kVec3f_GrSLType, kDefault_GrSLPrecision,
|
||||
"LightLocation", &location);
|
||||
|
||||
fragBuilder->codeAppendf("normalize(%s - vec3(sk_FragCoord.xy, %s))",
|
||||
location, z);
|
||||
fragBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))",
|
||||
location, fragBuilder->fragmentPosition(), z);
|
||||
}
|
||||
|
||||
void GrGLSpotLight::emitLightColor(GrGLSLUniformHandler* uniformHandler,
|
||||
|
@ -209,6 +209,7 @@ public:
|
||||
RRectsGaussianEdgeFP(const SkRRect& first, const SkRRect& second, SkScalar radius)
|
||||
: INHERITED(kNone_OptimizationFlags), fFirst(first), fSecond(second), fRadius(radius) {
|
||||
this->initClassID<RRectsGaussianEdgeFP>();
|
||||
this->setWillReadFragmentPosition();
|
||||
|
||||
fFirstMode = ComputeMode(fFirst);
|
||||
fSecondMode = ComputeMode(fSecond);
|
||||
@ -232,8 +233,8 @@ public:
|
||||
|
||||
// Positive distance is towards the center of the circle.
|
||||
// Map all the cases to the lower right quadrant.
|
||||
fragBuilder->codeAppendf("vec2 delta = abs(sk_FragCoord.xy - %s.%s);",
|
||||
posName, indices);
|
||||
fragBuilder->codeAppendf("vec2 delta = abs(%s.xy - %s.%s);",
|
||||
fragBuilder->fragmentPosition(), posName, indices);
|
||||
|
||||
switch (mode) {
|
||||
case kCircle_Mode:
|
||||
|
@ -195,10 +195,15 @@ bool GrProgramDesc::Build(GrProgramDesc* desc,
|
||||
// make sure any padding in the header is zeroed.
|
||||
memset(header, 0, kHeaderSize);
|
||||
|
||||
header->fSurfaceOriginKey = 0;
|
||||
|
||||
GrRenderTarget* rt = pipeline.getRenderTarget();
|
||||
|
||||
if (requiredFeatures & (GrProcessor::kFragmentPosition_RequiredFeature |
|
||||
GrProcessor::kSampleLocations_RequiredFeature)) {
|
||||
header->fSurfaceOriginKey = GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(rt->origin());
|
||||
} else {
|
||||
header->fSurfaceOriginKey = 0;
|
||||
}
|
||||
|
||||
if (requiredFeatures & GrProcessor::kSampleLocations_RequiredFeature) {
|
||||
SkASSERT(pipeline.isHWAntialiasState());
|
||||
header->fSamplePatternKey =
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "GrTypesPriv.h"
|
||||
#include "SkOpts.h"
|
||||
#include "SkTArray.h"
|
||||
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
|
||||
class GrShaderCaps;
|
||||
class GrPipeline;
|
||||
@ -81,11 +80,6 @@ public:
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
void setSurfaceOriginKey(int key) {
|
||||
KeyHeader* header = this->atOffset<KeyHeader, kHeaderOffset>();
|
||||
header->fSurfaceOriginKey = key;
|
||||
}
|
||||
|
||||
static bool Less(const GrProgramDesc& a, const GrProgramDesc& b) {
|
||||
SkASSERT(SkIsAlign4(a.keyLength()));
|
||||
int l = a.keyLength() >> 2;
|
||||
|
@ -27,6 +27,7 @@ GrXferProcessor::GrXferProcessor(const DstTexture* dstTexture,
|
||||
fDstTexture.reset(dstTexture->texture());
|
||||
fDstTextureOffset = dstTexture->offset();
|
||||
this->addTextureSampler(&fDstTexture);
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ private:
|
||||
AARectEffect(GrPrimitiveEdgeType edgeType, const SkRect& rect)
|
||||
: INHERITED(kModulatesInput_OptimizationFlag), fRect(rect), fEdgeType(edgeType) {
|
||||
this->initClassID<AARectEffect>();
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
||||
@ -114,27 +115,24 @@ void GLAARectEffect::emitCode(EmitArgs& args) {
|
||||
&rectName);
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const char* fragmentPos = fragBuilder->fragmentPosition();
|
||||
if (GrProcessorEdgeTypeIsAA(aare.getEdgeType())) {
|
||||
// The amount of coverage removed in x and y by the edges is computed as a pair of negative
|
||||
// numbers, xSub and ySub.
|
||||
fragBuilder->codeAppend("\t\tfloat xSub, ySub;\n");
|
||||
fragBuilder->codeAppendf("\t\txSub = min(sk_FragCoord.x - %s.x, 0.0);\n", rectName);
|
||||
fragBuilder->codeAppendf("\t\txSub += min(%s.z - sk_FragCoord.x, 0.0);\n", rectName);
|
||||
fragBuilder->codeAppendf("\t\tySub = min(sk_FragCoord.y - %s.y, 0.0);\n", rectName);
|
||||
fragBuilder->codeAppendf("\t\tySub += min(%s.w - sk_FragCoord.y, 0.0);\n", rectName);
|
||||
fragBuilder->codeAppendf("\t\txSub = min(%s.x - %s.x, 0.0);\n", fragmentPos, rectName);
|
||||
fragBuilder->codeAppendf("\t\txSub += min(%s.z - %s.x, 0.0);\n", rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("\t\tySub = min(%s.y - %s.y, 0.0);\n", fragmentPos, rectName);
|
||||
fragBuilder->codeAppendf("\t\tySub += min(%s.w - %s.y, 0.0);\n", rectName, fragmentPos);
|
||||
// Now compute coverage in x and y and multiply them to get the fraction of the pixel
|
||||
// covered.
|
||||
fragBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
|
||||
} else {
|
||||
fragBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n");
|
||||
fragBuilder->codeAppendf("\t\talpha *= (sk_FragCoord.x - %s.x) > -0.5 ? 1.0 : 0.0;\n",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("\t\talpha *= (%s.z - sk_FragCoord.x) > -0.5 ? 1.0 : 0.0;\n",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("\t\talpha *= (sk_FragCoord.y - %s.y) > -0.5 ? 1.0 : 0.0;\n",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("\t\talpha *= (%s.w - sk_FragCoord.y) > -0.5 ? 1.0 : 0.0;\n",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
|
||||
fragBuilder->codeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
|
||||
fragBuilder->codeAppendf("\t\talpha *= (%s.w - %s.y) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
|
||||
}
|
||||
|
||||
if (GrProcessorEdgeTypeIsInverseFill(aare.getEdgeType())) {
|
||||
@ -203,10 +201,10 @@ void GrGLConvexPolyEffect::emitCode(EmitArgs& args) {
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
fragBuilder->codeAppend("\t\tfloat alpha = 1.0;\n");
|
||||
fragBuilder->codeAppend("\t\tfloat edge;\n");
|
||||
const char* fragmentPos = fragBuilder->fragmentPosition();
|
||||
for (int i = 0; i < cpe.getEdgeCount(); ++i) {
|
||||
fragBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(sk_FragCoord.x, sk_FragCoord.y, "
|
||||
"1));\n",
|
||||
edgeArrayName, i);
|
||||
fragBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n",
|
||||
edgeArrayName, i, fragmentPos, fragmentPos);
|
||||
if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) {
|
||||
fragBuilder->codeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n");
|
||||
} else {
|
||||
@ -351,6 +349,7 @@ GrConvexPolyEffect::GrConvexPolyEffect(GrPrimitiveEdgeType edgeType, int n, cons
|
||||
for (int i = 0; i < n; ++i) {
|
||||
fEdges[3 * i + 2] += SK_ScalarHalf;
|
||||
}
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
bool GrConvexPolyEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
|
@ -26,7 +26,10 @@ public:
|
||||
const char* name() const override { return "Dither"; }
|
||||
|
||||
private:
|
||||
DitherEffect() : INHERITED(kNone_OptimizationFlags) { this->initClassID<DitherEffect>(); }
|
||||
DitherEffect() : INHERITED(kNone_OptimizationFlags) {
|
||||
this->initClassID<DitherEffect>();
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
||||
|
||||
@ -78,8 +81,8 @@ void GLDitherEffect::emitCode(EmitArgs& args) {
|
||||
// For each channel c, add the random offset to the pixel to either bump
|
||||
// it up or let it remain constant during quantization.
|
||||
fragBuilder->codeAppendf("\t\tfloat r = "
|
||||
"fract(sin(dot(sk_FragCoord.xy, vec2(12.9898,78.233))) * "
|
||||
"43758.5453);\n");
|
||||
"fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n",
|
||||
fragBuilder->fragmentPosition());
|
||||
fragBuilder->codeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n",
|
||||
args.fOutputColor, GrGLSLExpr4(args.fInputColor).c_str());
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ void CircleEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
|
||||
CircleEffect::CircleEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar r)
|
||||
: INHERITED(kModulatesInput_OptimizationFlag), fCenter(c), fRadius(r), fEdgeType(edgeType) {
|
||||
this->initClassID<CircleEffect>();
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
bool CircleEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
@ -123,6 +124,7 @@ void GLCircleEffect::emitCode(EmitArgs& args) {
|
||||
&circleName);
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const char* fragmentPos = fragBuilder->fragmentPosition();
|
||||
|
||||
SkASSERT(kHairlineAA_GrProcessorEdgeType != ce.getEdgeType());
|
||||
// TODO: Right now the distance to circle caclulation is performed in a space normalized to the
|
||||
@ -130,13 +132,11 @@ void GLCircleEffect::emitCode(EmitArgs& args) {
|
||||
// mediump. It'd be nice to only to this on mediump devices but we currently don't have the
|
||||
// caps here.
|
||||
if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) {
|
||||
fragBuilder->codeAppendf("float d = (length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * "
|
||||
"%s.z;",
|
||||
circleName, circleName, circleName);
|
||||
fragBuilder->codeAppendf("float d = (length((%s.xy - %s.xy) * %s.w) - 1.0) * %s.z;",
|
||||
circleName, fragmentPos, circleName, circleName);
|
||||
} else {
|
||||
fragBuilder->codeAppendf("float d = (1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * "
|
||||
"%s.z;",
|
||||
circleName, circleName, circleName);
|
||||
fragBuilder->codeAppendf("float d = (1.0 - length((%s.xy - %s.xy) * %s.w)) * %s.z;",
|
||||
circleName, fragmentPos, circleName, circleName);
|
||||
}
|
||||
if (GrProcessorEdgeTypeIsAA(ce.getEdgeType())) {
|
||||
fragBuilder->codeAppend("d = clamp(d, 0.0, 1.0);");
|
||||
@ -237,6 +237,7 @@ EllipseEffect::EllipseEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkS
|
||||
, fRadii(SkVector::Make(rx, ry))
|
||||
, fEdgeType(edgeType) {
|
||||
this->initClassID<EllipseEffect>();
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
bool EllipseEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
@ -308,9 +309,10 @@ void GLEllipseEffect::emitCode(EmitArgs& args) {
|
||||
}
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const char* fragmentPos = fragBuilder->fragmentPosition();
|
||||
|
||||
// d is the offset to the ellipse center
|
||||
fragBuilder->codeAppendf("vec2 d = sk_FragCoord.xy - %s.xy;", ellipseName);
|
||||
fragBuilder->codeAppendf("vec2 d = %s.xy - %s.xy;", fragmentPos, ellipseName);
|
||||
if (scaleName) {
|
||||
fragBuilder->codeAppendf("d *= %s.y;", scaleName);
|
||||
}
|
||||
|
@ -100,6 +100,7 @@ CircularRRectEffect::CircularRRectEffect(GrPrimitiveEdgeType edgeType, uint32_t
|
||||
, fEdgeType(edgeType)
|
||||
, fCircularCornerFlags(circularCornerFlags) {
|
||||
this->initClassID<CircularRRectEffect>();
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
bool CircularRRectEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
@ -180,6 +181,7 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) {
|
||||
}
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const char* fragmentPos = fragBuilder->fragmentPosition();
|
||||
// At each quarter-circle corner we compute a vector that is the offset of the fragment position
|
||||
// from the circle center. The vector is pinned in x and y to be in the quarter-plane relevant
|
||||
// to that corner. This means that points near the interior near the rrect top edge will have
|
||||
@ -197,86 +199,84 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) {
|
||||
// alphas together.
|
||||
switch (crre.getCircularCornerFlags()) {
|
||||
case CircularRRectEffect::kAll_CornerFlags:
|
||||
fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("vec2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName);
|
||||
fragBuilder->codeAppend("vec2 dxy = max(max(dxy0, dxy1), 0.0);");
|
||||
fragBuilder->codeAppendf("float alpha = %s;", clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kTopLeft_CornerFlag:
|
||||
fragBuilder->codeAppendf("vec2 dxy = max(%s.xy - sk_FragCoord.xy, 0.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("vec2 dxy = max(%s.xy - %s.xy, 0.0);",
|
||||
rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);",
|
||||
rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);",
|
||||
rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("float alpha = bottomAlpha * rightAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kTopRight_CornerFlag:
|
||||
fragBuilder->codeAppendf("vec2 dxy = max(vec2(sk_FragCoord.x - %s.z, "
|
||||
"%s.y - sk_FragCoord.y), 0.0);",
|
||||
rectName, rectName);
|
||||
fragBuilder->codeAppendf("float leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("vec2 dxy = max(vec2(%s.x - %s.z, %s.y - %s.y), 0.0);",
|
||||
fragmentPos, rectName, rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("float leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);",
|
||||
fragmentPos, rectName);
|
||||
fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);",
|
||||
rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("float alpha = bottomAlpha * leftAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kBottomRight_CornerFlag:
|
||||
fragBuilder->codeAppendf("vec2 dxy = max(sk_FragCoord.xy - %s.zw, 0.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("float leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("float topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("vec2 dxy = max(%s.xy - %s.zw, 0.0);",
|
||||
fragmentPos, rectName);
|
||||
fragBuilder->codeAppendf("float leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);",
|
||||
fragmentPos, rectName);
|
||||
fragBuilder->codeAppendf("float topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);",
|
||||
fragmentPos, rectName);
|
||||
fragBuilder->codeAppendf("float alpha = topAlpha * leftAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kBottomLeft_CornerFlag:
|
||||
fragBuilder->codeAppendf("vec2 dxy = max(vec2(%s.x - sk_FragCoord.x, sk_FragCoord.y - "
|
||||
"%s.w), 0.0);",
|
||||
rectName, rectName);
|
||||
fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("float topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("vec2 dxy = max(vec2(%s.x - %s.x, %s.y - %s.w), 0.0);",
|
||||
rectName, fragmentPos, fragmentPos, rectName);
|
||||
fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);",
|
||||
rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("float topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);",
|
||||
fragmentPos, rectName);
|
||||
fragBuilder->codeAppendf("float alpha = topAlpha * rightAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kLeft_CornerFlags:
|
||||
fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("float dy1 = sk_FragCoord.y - %s.w;", rectName);
|
||||
fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("float dy1 = %s.y - %s.w;", fragmentPos, rectName);
|
||||
fragBuilder->codeAppend("vec2 dxy = max(vec2(dxy0.x, max(dxy0.y, dy1)), 0.0);");
|
||||
fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("float rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);",
|
||||
rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("float alpha = rightAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kTop_CornerFlags:
|
||||
fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("float dx1 = sk_FragCoord.x - %s.z;", rectName);
|
||||
fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("float dx1 = %s.x - %s.z;", fragmentPos, rectName);
|
||||
fragBuilder->codeAppend("vec2 dxy = max(vec2(max(dxy0.x, dx1), dxy0.y), 0.0);");
|
||||
fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("float bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);",
|
||||
rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("float alpha = bottomAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kRight_CornerFlags:
|
||||
fragBuilder->codeAppendf("float dy0 = %s.y - sk_FragCoord.y;", rectName);
|
||||
fragBuilder->codeAppendf("vec2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppendf("float dy0 = %s.y - %s.y;", rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName);
|
||||
fragBuilder->codeAppend("vec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1.y)), 0.0);");
|
||||
fragBuilder->codeAppendf("float leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("float leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);",
|
||||
fragmentPos, rectName);
|
||||
fragBuilder->codeAppendf("float alpha = leftAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
case CircularRRectEffect::kBottom_CornerFlags:
|
||||
fragBuilder->codeAppendf("float dx0 = %s.x - sk_FragCoord.x;", rectName);
|
||||
fragBuilder->codeAppendf("vec2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppendf("float dx0 = %s.x - %s.x;", rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName);
|
||||
fragBuilder->codeAppend("vec2 dxy = max(vec2(max(dx0, dxy1.x), dxy1.y), 0.0);");
|
||||
fragBuilder->codeAppendf("float topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);",
|
||||
rectName);
|
||||
fragBuilder->codeAppendf("float topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);",
|
||||
fragmentPos, rectName);
|
||||
fragBuilder->codeAppendf("float alpha = topAlpha * %s;",
|
||||
clampedCircleDistance.c_str());
|
||||
break;
|
||||
@ -436,6 +436,7 @@ void EllipticalRRectEffect::onComputeInvariantOutput(GrInvariantOutput* inout) c
|
||||
EllipticalRRectEffect::EllipticalRRectEffect(GrPrimitiveEdgeType edgeType, const SkRRect& rrect)
|
||||
: INHERITED(kModulatesInput_OptimizationFlag), fRRect(rrect), fEdgeType(edgeType) {
|
||||
this->initClassID<EllipticalRRectEffect>();
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
bool EllipticalRRectEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
@ -519,6 +520,7 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
|
||||
&rectName);
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const char* fragmentPos = fragBuilder->fragmentPosition();
|
||||
// At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos
|
||||
// to the ellipse center. The vector is pinned in x and y to be in the quarter-plane relevant
|
||||
// to that corner. This means that points near the interior near the rrect top edge will have
|
||||
@ -531,8 +533,8 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
|
||||
// The code below is a simplified version of the above that performs maxs on the vector
|
||||
// components before computing distances and alpha values so that only one distance computation
|
||||
// need be computed to determine the min alpha.
|
||||
fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
|
||||
fragBuilder->codeAppendf("vec2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
|
||||
fragBuilder->codeAppendf("vec2 dxy0 = %s.xy - %s.xy;", rectName, fragmentPos);
|
||||
fragBuilder->codeAppendf("vec2 dxy1 = %s.xy - %s.zw;", fragmentPos, rectName);
|
||||
|
||||
// If we're on a device with a "real" mediump then we'll do the distance computation in a space
|
||||
// that is normalized by the largest radius. The scale uniform will be scale, 1/scale. The
|
||||
|
@ -419,6 +419,7 @@ GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentPro
|
||||
fDeviceSpaceOffset.fX = deviceSpaceOffset.fX - subset.fLeft;
|
||||
fDeviceSpaceOffset.fY = deviceSpaceOffset.fY - subset.fTop;
|
||||
this->initClassID<GrDeviceSpaceTextureDecalFragmentProcessor>();
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
sk_sp<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::Make(
|
||||
@ -443,6 +444,7 @@ GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentPro
|
||||
fDeviceSpaceOffset.fX = deviceSpaceOffset.fX - subset.fLeft;
|
||||
fDeviceSpaceOffset.fY = deviceSpaceOffset.fY - subset.fTop;
|
||||
this->initClassID<GrDeviceSpaceTextureDecalFragmentProcessor>();
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
GrGLSLFragmentProcessor* GrDeviceSpaceTextureDecalFragmentProcessor::onCreateGLSLInstance() const {
|
||||
@ -457,7 +459,8 @@ GrGLSLFragmentProcessor* GrDeviceSpaceTextureDecalFragmentProcessor::onCreateGLS
|
||||
kDefault_GrSLPrecision,
|
||||
"scaleAndTranslate",
|
||||
&scaleAndTranslateName);
|
||||
args.fFragBuilder->codeAppendf("vec2 coords = sk_FragCoord.xy * %s.xy + %s.zw;",
|
||||
args.fFragBuilder->codeAppendf("vec2 coords = %s.xy * %s.xy + %s.zw;",
|
||||
args.fFragBuilder->fragmentPosition(),
|
||||
scaleAndTranslateName, scaleAndTranslateName);
|
||||
fGLDomain.sampleTexture(args.fFragBuilder,
|
||||
args.fUniformHandler,
|
||||
|
@ -80,19 +80,12 @@ GrGLProgram* GrGLGpu::ProgramCache::refProgram(const GrGLGpu* gpu,
|
||||
}
|
||||
desc.finalize();
|
||||
std::unique_ptr<Entry>* entry = fMap.find(desc);
|
||||
if (!entry) {
|
||||
// Didn't find an origin-independent version, check with the specific origin
|
||||
GrSurfaceOrigin origin = pipeline.getRenderTarget()->origin();
|
||||
desc.setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(origin));
|
||||
desc.finalize();
|
||||
entry = fMap.find(desc);
|
||||
}
|
||||
if (!entry) {
|
||||
// We have a cache miss
|
||||
#ifdef PROGRAM_CACHE_STATS
|
||||
++fCacheMisses;
|
||||
#endif
|
||||
GrGLProgram* program = GrGLProgramBuilder::CreateProgram(pipeline, primProc, &desc, fGpu);
|
||||
GrGLProgram* program = GrGLProgramBuilder::CreateProgram(pipeline, primProc, desc, fGpu);
|
||||
if (nullptr == program) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrPipeline& pipeline,
|
||||
const GrPrimitiveProcessor& primProc,
|
||||
GrProgramDesc* desc,
|
||||
const GrProgramDesc& desc,
|
||||
GrGLGpu* gpu) {
|
||||
GrAutoLocaleSetter als("C");
|
||||
|
||||
@ -56,7 +56,7 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrPipeline& pipeline,
|
||||
GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu,
|
||||
const GrPipeline& pipeline,
|
||||
const GrPrimitiveProcessor& primProc,
|
||||
GrProgramDesc* desc)
|
||||
const GrProgramDesc& desc)
|
||||
: INHERITED(pipeline, primProc, desc)
|
||||
, fGpu(gpu)
|
||||
, fVaryingHandler(this)
|
||||
@ -89,13 +89,6 @@ bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader,
|
||||
}
|
||||
|
||||
*shaderIds->append() = shaderId;
|
||||
if (!outInputs->fFlipY) {
|
||||
GrProgramDesc* d = this->desc();
|
||||
// the program doesn't care about the surface origin, set the key to zero to indicate that
|
||||
// it doesn't matter
|
||||
d->setSurfaceOriginKey(0);
|
||||
d->finalize();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -251,7 +244,7 @@ void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
|
||||
|
||||
GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
|
||||
return new GrGLProgram(fGpu,
|
||||
*this->desc(),
|
||||
this->desc(),
|
||||
fUniformHandles,
|
||||
programID,
|
||||
fUniformHandler.fUniforms,
|
||||
|
@ -29,14 +29,11 @@ public:
|
||||
* The program implements what is specified in the stages given as input.
|
||||
* After successful generation, the builder result objects are available
|
||||
* to be used.
|
||||
* This function may modify the GrProgramDesc by setting the surface origin
|
||||
* key to 0 (unspecified) if it turns out the program does not care about
|
||||
* the surface origin.
|
||||
* @return true if generation was successful.
|
||||
*/
|
||||
static GrGLProgram* CreateProgram(const GrPipeline&,
|
||||
const GrPrimitiveProcessor&,
|
||||
GrProgramDesc*,
|
||||
const GrProgramDesc&,
|
||||
GrGLGpu*);
|
||||
|
||||
const GrCaps* caps() const override;
|
||||
@ -45,7 +42,7 @@ public:
|
||||
|
||||
private:
|
||||
GrGLProgramBuilder(GrGLGpu*, const GrPipeline&, const GrPrimitiveProcessor&,
|
||||
GrProgramDesc*);
|
||||
const GrProgramDesc&);
|
||||
|
||||
bool compileAndAttachShaders(GrGLSLShaderBuilder& shader,
|
||||
GrGLuint programId,
|
||||
|
@ -130,6 +130,11 @@ SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords)
|
||||
return coords2D;
|
||||
}
|
||||
|
||||
const char* GrGLSLFragmentShaderBuilder::fragmentPosition() {
|
||||
SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kFragmentPosition_RequiredFeature;)
|
||||
return "sk_FragCoord";
|
||||
}
|
||||
|
||||
const char* GrGLSLFragmentShaderBuilder::distanceVectorName() const {
|
||||
return "fsDistanceVector";
|
||||
}
|
||||
|
@ -47,6 +47,11 @@ public:
|
||||
*/
|
||||
virtual SkString ensureCoords2D(const GrShaderVar&) = 0;
|
||||
|
||||
|
||||
/** 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). */
|
||||
virtual const char* fragmentPosition() = 0;
|
||||
|
||||
// TODO: remove this method.
|
||||
void declAppendf(const char* fmt, ...);
|
||||
|
||||
@ -162,6 +167,7 @@ public:
|
||||
// Shared GrGLSLFragmentBuilder interface.
|
||||
bool enableFeature(GLSLFeature) override;
|
||||
virtual SkString ensureCoords2D(const GrShaderVar&) override;
|
||||
const char* fragmentPosition() override;
|
||||
const char* distanceVectorName() const override;
|
||||
|
||||
// GrGLSLFPFragmentBuilder interface.
|
||||
|
@ -20,7 +20,7 @@ const int GrGLSLProgramBuilder::kVarsPerBlock = 8;
|
||||
|
||||
GrGLSLProgramBuilder::GrGLSLProgramBuilder(const GrPipeline& pipeline,
|
||||
const GrPrimitiveProcessor& primProc,
|
||||
GrProgramDesc* desc)
|
||||
const GrProgramDesc& desc)
|
||||
: fVS(this)
|
||||
, fGS(this)
|
||||
, fFS(this)
|
||||
@ -348,7 +348,7 @@ void GrGLSLProgramBuilder::emitImageStorage(const GrProcessor::ImageStorageAcces
|
||||
void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) {
|
||||
// Swizzle the fragment shader outputs if necessary.
|
||||
GrSwizzle swizzle;
|
||||
swizzle.setFromKey(this->desc()->header().fOutputSwizzle);
|
||||
swizzle.setFromKey(this->desc().header().fOutputSwizzle);
|
||||
if (swizzle != GrSwizzle::RGBA()) {
|
||||
fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(),
|
||||
fFS.getPrimaryColorOutputName(),
|
||||
|
@ -40,8 +40,8 @@ public:
|
||||
|
||||
const GrPrimitiveProcessor& primitiveProcessor() const { return fPrimProc; }
|
||||
const GrPipeline& pipeline() const { return fPipeline; }
|
||||
GrProgramDesc* desc() { return fDesc; }
|
||||
const GrProgramDesc::KeyHeader& header() const { return fDesc->header(); }
|
||||
const GrProgramDesc& desc() const { return fDesc; }
|
||||
const GrProgramDesc::KeyHeader& header() const { return fDesc.header(); }
|
||||
|
||||
void appendUniformDecls(GrShaderFlags visibility, SkString*) const;
|
||||
|
||||
@ -99,7 +99,7 @@ public:
|
||||
|
||||
const GrPipeline& fPipeline;
|
||||
const GrPrimitiveProcessor& fPrimProc;
|
||||
GrProgramDesc* fDesc;
|
||||
const GrProgramDesc& fDesc;
|
||||
|
||||
BuiltinUniformHandles fUniformHandles;
|
||||
|
||||
@ -110,7 +110,7 @@ public:
|
||||
protected:
|
||||
explicit GrGLSLProgramBuilder(const GrPipeline&,
|
||||
const GrPrimitiveProcessor&,
|
||||
GrProgramDesc*);
|
||||
const GrProgramDesc&);
|
||||
|
||||
void addFeature(GrShaderFlags shaders, uint32_t featureBit, const char* extensionName);
|
||||
|
||||
|
@ -22,7 +22,7 @@ void GrGLSLVertexBuilder::transformToNormalizedDeviceSpace(const GrShaderVar& po
|
||||
fProgramBuilder->addRTAdjustmentUniform(kHigh_GrSLPrecision,
|
||||
fProgramBuilder->rtAdjustment(),
|
||||
&fRtAdjustName);
|
||||
if (this->getProgramBuilder()->desc()->header().fSnapVerticesToPixelCenters) {
|
||||
if (this->getProgramBuilder()->desc().header().fSnapVerticesToPixelCenters) {
|
||||
if (kVec3f_GrSLType == posVar.getType()) {
|
||||
const char* p = posVar.c_str();
|
||||
this->codeAppendf("{vec2 _posTmp = vec2(%s.x/%s.z, %s.y/%s.z);", p, p, p, p);
|
||||
@ -47,7 +47,7 @@ void GrGLSLVertexBuilder::transformToNormalizedDeviceSpace(const GrShaderVar& po
|
||||
}
|
||||
// We could have the GrGeometryProcessor do this, but its just easier to have it performed
|
||||
// here. If we ever need to set variable pointsize, then we can reinvestigate.
|
||||
if (this->getProgramBuilder()->desc()->header().fHasPointSize) {
|
||||
if (this->getProgramBuilder()->desc().header().fHasPointSize) {
|
||||
this->codeAppend("gl_PointSize = 1.0;");
|
||||
}
|
||||
}
|
||||
|
@ -49,10 +49,11 @@ void GrGLSLXferProcessor::emitCode(const EmitArgs& args) {
|
||||
kDefault_GrSLPrecision,
|
||||
"DstTextureCoordScale",
|
||||
&dstCoordScaleName);
|
||||
const char* fragPos = fragBuilder->fragmentPosition();
|
||||
|
||||
fragBuilder->codeAppend("// Read color from copy of the destination.\n");
|
||||
fragBuilder->codeAppendf("vec2 _dstTexCoord = (sk_FragCoord.xy - %s) * %s;",
|
||||
dstTopLeftName, dstCoordScaleName);
|
||||
fragBuilder->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
|
||||
fragPos, dstTopLeftName, dstCoordScaleName);
|
||||
|
||||
if (!topDown) {
|
||||
fragBuilder->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
|
||||
|
@ -64,6 +64,9 @@ public:
|
||||
|
||||
bool installPipeline(const GrPipeline::CreateArgs&);
|
||||
|
||||
// TODO no GrPrimitiveProcessors yet read fragment position
|
||||
bool willReadFragmentPosition() const { return false; }
|
||||
|
||||
protected:
|
||||
static SkString DumpPipelineInfo(const GrPipeline& pipeline) {
|
||||
SkString string;
|
||||
|
@ -344,7 +344,8 @@ public:
|
||||
// gl_FragCoord. The oriented box positioning of the subsamples is of course not
|
||||
// optimal, but it greatly simplifies the math and this simplification is necessary for
|
||||
// performance reasons.
|
||||
fsBuilder->codeAppendf("highp vec2 firstSample = sk_FragCoord.xy - vec2(0.25);");
|
||||
fsBuilder->codeAppendf("highp vec2 firstSample = %s.xy - vec2(0.25);",
|
||||
fsBuilder->fragmentPosition());
|
||||
fsBuilder->codeAppendf("highp vec2 delta1 = %s;", delta1.fsIn());
|
||||
fsBuilder->codeAppendf("highp vec2 delta2 = %s;", delta2.fsIn());
|
||||
fsBuilder->codeAppendf("highp vec2 delta3 = %s;", delta3.fsIn());
|
||||
@ -422,6 +423,7 @@ private:
|
||||
kHigh_GrSLPrecision);
|
||||
fInWindings = &this->addVertexAttrib("inWindings", kInt_GrVertexAttribType,
|
||||
kLow_GrSLPrecision);
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
const Attribute* fInPosition;
|
||||
@ -540,7 +542,8 @@ public:
|
||||
fsBuilder->codeAppend("highp vec2 uvIncY = uvdX * 0.1 + uvdY * 0.55;");
|
||||
fsBuilder->codeAppendf("highp vec2 uv = %s.xy - uvdX * 0.35 - uvdY * 0.25;",
|
||||
uv.fsIn());
|
||||
fsBuilder->codeAppendf("highp vec2 firstSample = sk_FragCoord.xy - vec2(0.25);");
|
||||
fsBuilder->codeAppendf("highp vec2 firstSample = %s.xy - vec2(0.25);",
|
||||
fsBuilder->fragmentPosition());
|
||||
fsBuilder->codeAppendf("highp float d = dot(%s, (firstSample - %s).yx) * 2.0;",
|
||||
delta.fsIn(), ep1.fsIn());
|
||||
fsBuilder->codeAppendf("pls.windings[0] += %s(d, uv) ? %s : 0;", inQuadName.c_str(),
|
||||
@ -601,6 +604,7 @@ private:
|
||||
kHigh_GrSLPrecision);
|
||||
fInWindings = &this->addVertexAttrib("inWindings", kInt_GrVertexAttribType,
|
||||
kLow_GrSLPrecision);
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
|
||||
const Attribute* fInPosition;
|
||||
|
@ -19,7 +19,7 @@ GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState(
|
||||
const GrStencilSettings& stencil,
|
||||
const GrPrimitiveProcessor& primProc,
|
||||
GrPrimitiveType primitiveType,
|
||||
GrVkPipelineState::Desc* desc,
|
||||
const GrVkPipelineState::Desc& desc,
|
||||
const GrVkRenderPass& renderPass) {
|
||||
// create a builder. This will be handed off to effects so they can use it to add
|
||||
// uniforms, varyings, textures, etc
|
||||
@ -39,7 +39,7 @@ GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState(
|
||||
GrVkPipelineStateBuilder::GrVkPipelineStateBuilder(GrVkGpu* gpu,
|
||||
const GrPipeline& pipeline,
|
||||
const GrPrimitiveProcessor& primProc,
|
||||
GrProgramDesc* desc)
|
||||
const GrProgramDesc& desc)
|
||||
: INHERITED(pipeline, primProc, desc)
|
||||
, fGpu(gpu)
|
||||
, fVaryingHandler(this)
|
||||
@ -62,8 +62,7 @@ bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage,
|
||||
const GrGLSLShaderBuilder& builder,
|
||||
VkShaderModule* shaderModule,
|
||||
VkPipelineShaderStageCreateInfo* stageInfo,
|
||||
const SkSL::Program::Settings& settings,
|
||||
GrVkPipelineState::Desc* desc) {
|
||||
const SkSL::Program::Settings& settings) {
|
||||
SkString shaderString;
|
||||
for (int i = 0; i < builder.fCompilerStrings.count(); ++i) {
|
||||
if (builder.fCompilerStrings[i]) {
|
||||
@ -81,19 +80,13 @@ bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage,
|
||||
if (inputs.fRTHeight) {
|
||||
this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
|
||||
}
|
||||
if (!inputs.fFlipY) {
|
||||
// the program doesn't care about the surface origin, set the key to zero to indicate that
|
||||
// it doesn't matter
|
||||
desc->setSurfaceOriginKey(0);
|
||||
desc->finalize();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil,
|
||||
GrPrimitiveType primitiveType,
|
||||
const GrVkRenderPass& renderPass,
|
||||
GrVkPipelineState::Desc* desc) {
|
||||
const GrVkPipelineState::Desc& desc) {
|
||||
VkDescriptorSetLayout dsLayout[2];
|
||||
VkPipelineLayout pipelineLayout;
|
||||
VkShaderModule vertShaderModule;
|
||||
@ -140,8 +133,7 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s
|
||||
fVS,
|
||||
&vertShaderModule,
|
||||
&shaderStageInfo[0],
|
||||
settings,
|
||||
desc));
|
||||
settings));
|
||||
|
||||
// TODO: geometry shader support.
|
||||
SkASSERT(!this->primitiveProcessor().willUseGeoShader());
|
||||
@ -150,8 +142,7 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s
|
||||
fFS,
|
||||
&fragShaderModule,
|
||||
&shaderStageInfo[1],
|
||||
settings,
|
||||
desc));
|
||||
settings));
|
||||
|
||||
GrVkPipeline* pipeline = resourceProvider.createPipeline(fPipeline,
|
||||
stencil,
|
||||
@ -174,7 +165,7 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s
|
||||
}
|
||||
|
||||
return new GrVkPipelineState(fGpu,
|
||||
*desc,
|
||||
desc,
|
||||
pipeline,
|
||||
pipelineLayout,
|
||||
samplerDSHandle,
|
||||
|
@ -28,8 +28,6 @@ public:
|
||||
*
|
||||
* The GrVkPipelineState implements what is specified in the GrPipeline and GrPrimitiveProcessor
|
||||
* as input. After successful generation, the builder result objects are available to be used.
|
||||
* This function may modify the program key by setting the surface origin key to 0 (unspecified)
|
||||
* if it turns out the program does not care about the surface origin.
|
||||
* @return true if generation was successful.
|
||||
*/
|
||||
static GrVkPipelineState* CreatePipelineState(GrVkGpu*,
|
||||
@ -37,7 +35,7 @@ public:
|
||||
const GrStencilSettings&,
|
||||
const GrPrimitiveProcessor&,
|
||||
GrPrimitiveType,
|
||||
GrVkPipelineState::Desc*,
|
||||
const GrVkPipelineState::Desc&,
|
||||
const GrVkRenderPass& renderPass);
|
||||
|
||||
const GrCaps* caps() const override;
|
||||
@ -51,19 +49,18 @@ private:
|
||||
GrVkPipelineStateBuilder(GrVkGpu*,
|
||||
const GrPipeline&,
|
||||
const GrPrimitiveProcessor&,
|
||||
GrProgramDesc*);
|
||||
const GrProgramDesc&);
|
||||
|
||||
GrVkPipelineState* finalize(const GrStencilSettings&,
|
||||
GrPrimitiveType primitiveType,
|
||||
const GrVkRenderPass& renderPass,
|
||||
GrVkPipelineState::Desc*);
|
||||
const GrVkPipelineState::Desc&);
|
||||
|
||||
bool createVkShaderModule(VkShaderStageFlagBits stage,
|
||||
const GrGLSLShaderBuilder& builder,
|
||||
VkShaderModule* shaderModule,
|
||||
VkPipelineShaderStageCreateInfo* stageInfo,
|
||||
const SkSL::Program::Settings& settings,
|
||||
GrVkPipelineState::Desc* desc);
|
||||
const SkSL::Program::Settings& settings);
|
||||
|
||||
GrGLSLUniformHandler* uniformHandler() override { return &fUniformHandler; }
|
||||
const GrGLSLUniformHandler* uniformHandler() const override { return &fUniformHandler; }
|
||||
|
@ -100,13 +100,6 @@ sk_sp<GrVkPipelineState> GrVkResourceProvider::PipelineStateCache::refPipelineSt
|
||||
desc.finalize();
|
||||
|
||||
std::unique_ptr<Entry>* entry = fMap.find(desc);
|
||||
if (!entry) {
|
||||
// Didn't find an origin-independent version, check with the specific origin
|
||||
GrSurfaceOrigin origin = pipeline.getRenderTarget()->origin();
|
||||
desc.setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(origin));
|
||||
desc.finalize();
|
||||
entry = fMap.find(desc);
|
||||
}
|
||||
if (!entry) {
|
||||
#ifdef GR_PIPELINE_STATE_CACHE_STATS
|
||||
++fCacheMisses;
|
||||
@ -117,7 +110,7 @@ sk_sp<GrVkPipelineState> GrVkResourceProvider::PipelineStateCache::refPipelineSt
|
||||
stencil,
|
||||
primProc,
|
||||
primitiveType,
|
||||
&desc,
|
||||
desc,
|
||||
renderPass));
|
||||
if (nullptr == pipelineState) {
|
||||
return nullptr;
|
||||
|
@ -33,10 +33,8 @@ following differences between SkSL and GLSL:
|
||||
'do_something_else();', depending on whether that cap is enabled or not.
|
||||
* no #version statement is required, and will be ignored if present
|
||||
* the output color is sk_FragColor (do not declare it)
|
||||
* the fragment coordinate is sk_FragCoord, and is always relative to the upper
|
||||
left.
|
||||
* lowp, mediump, and highp are always permitted (but will only be respected if
|
||||
you run on a device which supports them)
|
||||
you run on a GLES device)
|
||||
* you do not need to include ".0" to make a number a float (meaning that
|
||||
"vec2(x, y) * 4" is perfectly legal in SkSL, unlike GLSL where it would often
|
||||
have to be expressed "vec2(x, y) * 4.0". There is no performance penalty for
|
||||
|
@ -624,14 +624,11 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier&
|
||||
f->fFunctions));
|
||||
}
|
||||
case Symbol::kVariable_Kind: {
|
||||
const Variable* var = (const Variable*) result;
|
||||
if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) {
|
||||
fInputs.fFlipY = true;
|
||||
if (fSettings->fFlipY &&
|
||||
(!fSettings->fCaps ||
|
||||
!fSettings->fCaps->fragCoordConventionsExtensionString())) {
|
||||
fInputs.fRTHeight = true;
|
||||
}
|
||||
Variable* var = (Variable*) result;
|
||||
if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN &&
|
||||
fSettings->fFlipY &&
|
||||
(!fSettings->fCaps || !fSettings->fCaps->fragCoordConventionsExtensionString())) {
|
||||
fInputs.fRTHeight = true;
|
||||
}
|
||||
// default to kRead_RefKind; this will be corrected later if the variable is written to
|
||||
return std::unique_ptr<VariableReference>(new VariableReference(
|
||||
|
@ -27,8 +27,6 @@ namespace SkSL {
|
||||
struct Program {
|
||||
struct Settings {
|
||||
const GrShaderCaps* fCaps = nullptr;
|
||||
// if false, sk_FragCoord is exactly the same as gl_FragCoord. If true, the y coordinate
|
||||
// must be flipped.
|
||||
bool fFlipY = false;
|
||||
};
|
||||
|
||||
@ -36,17 +34,12 @@ struct Program {
|
||||
// if true, this program requires the render target height uniform to be defined
|
||||
bool fRTHeight;
|
||||
|
||||
// if true, this program must be recompiled if the flipY setting changes. If false, the
|
||||
// program will compile to the same code regardless of the flipY setting.
|
||||
bool fFlipY;
|
||||
|
||||
void reset() {
|
||||
fRTHeight = false;
|
||||
fFlipY = false;
|
||||
}
|
||||
|
||||
bool isEmpty() {
|
||||
return !fRTHeight && !fFlipY;
|
||||
return !fRTHeight;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -31,6 +31,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageStorageLoad, reporter, ctxInfo) {
|
||||
: INHERITED(kNone_OptimizationFlags)
|
||||
, fImageStorageAccess(std::move(texture), kRead_GrIOType, mm, restrict) {
|
||||
this->initClassID<TestFP>();
|
||||
this->setWillReadFragmentPosition();
|
||||
this->addImageStorageAccess(&fImageStorageAccess);
|
||||
}
|
||||
|
||||
@ -50,7 +51,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageStorageLoad, reporter, ctxInfo) {
|
||||
const TestFP& tfp = args.fFp.cast<TestFP>();
|
||||
GrGLSLFPFragmentBuilder* fb = args.fFragBuilder;
|
||||
SkString imageLoadStr;
|
||||
fb->codeAppend("highp vec2 coord = sk_FragCoord.xy;");
|
||||
fb->codeAppendf("highp vec2 coord = %s.xy;",
|
||||
args.fFragBuilder->fragmentPosition());
|
||||
fb->appendImageStorageLoad(&imageLoadStr, args.fImageStorages[0],
|
||||
"ivec2(coord)");
|
||||
if (GrPixelConfigIsSint(tfp.fImageStorageAccess.texture()->config())) {
|
||||
|
@ -418,13 +418,4 @@ DEF_TEST(SkSLDivByZero, r) {
|
||||
"error: 1: division by zero\n1 error\n");
|
||||
}
|
||||
|
||||
DEF_TEST(SkSLUnsupportedGLSLIdentifiers, r) {
|
||||
test_failure(r,
|
||||
"void main() { float x = gl_FragCoord.x; };",
|
||||
"error: 1: unknown identifier 'gl_FragCoord'\n1 error\n");
|
||||
test_failure(r,
|
||||
"void main() { float r = gl_FragColor.r; };",
|
||||
"error: 1: unknown identifier 'gl_FragColor'\n1 error\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user