Use unnormalized coords all the way through with GL_TEXTURE_RECTANGLE textures.
We used to unnormalize them in the shader via SkSL.
This allows us to support GL_TEXTURE_RECTANGLE without having textureSize()
available in GLSL.
Change-Id: Ibe63a302228811933ef000251db4cad9aaf4f2ea
Reviewed-on: https://skia-review.googlesource.com/c/174068
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrCoordTransform.h b/src/gpu/GrCoordTransform.h
index 43405f2..aee2253 100644
--- a/src/gpu/GrCoordTransform.h
+++ b/src/gpu/GrCoordTransform.h
@@ -36,7 +36,7 @@
GrCoordTransform(GrTextureProxy* proxy) {
SkASSERT(proxy);
SkDEBUGCODE(fInProcessor = false);
- this->reset(SkMatrix::I(), proxy, true);
+ this->reset(SkMatrix::I(), proxy);
}
/**
@@ -46,7 +46,7 @@
GrCoordTransform(const SkMatrix& m, GrTextureProxy* proxy) {
SkASSERT(proxy);
SkDEBUGCODE(fInProcessor = false);
- this->reset(m, proxy, true);
+ this->reset(m, proxy);
}
/**
@@ -57,24 +57,6 @@
this->reset(m);
}
- void reset(const SkMatrix& m, GrTextureProxy* proxy, bool normalize) {
- SkASSERT(proxy);
- SkASSERT(!fInProcessor);
-
- fMatrix = m;
- fProxy = proxy;
- fNormalize = normalize;
- fReverseY = kBottomLeft_GrSurfaceOrigin == proxy->origin();
- }
-
- void reset(const SkMatrix& m) {
- SkASSERT(!fInProcessor);
- fMatrix = m;
- fProxy = nullptr;
- fNormalize = false;
- fReverseY = false;
- }
-
GrCoordTransform& operator= (const GrCoordTransform& that) {
SkASSERT(!fInProcessor);
fMatrix = that.fMatrix;
@@ -119,6 +101,15 @@
GrTexture* peekTexture() const { return fProxy->peekTexture(); }
private:
+ void reset(const SkMatrix& m, GrTextureProxy* proxy = nullptr) {
+ SkASSERT(!fInProcessor);
+
+ fMatrix = m;
+ fProxy = proxy;
+ fNormalize = proxy && proxy->textureType() != GrTextureType::kRectangle;
+ fReverseY = proxy && kBottomLeft_GrSurfaceOrigin == proxy->origin();
+ }
+
// The textures' effect is to optionally normalize the final matrix, so a blind
// equality check could be misleading
bool operator==(const GrCoordTransform& that) const;
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index d8df5ac..28a47cd 100644
--- a/src/gpu/effects/GrTextureDomain.cpp
+++ b/src/gpu/effects/GrTextureDomain.cpp
@@ -165,8 +165,15 @@
GrTexture* tex = proxy->peekTexture();
SkASSERT(fHasMode && textureDomain.mode() == fMode);
if (kIgnore_Mode != textureDomain.mode()) {
- SkScalar wInv = SK_Scalar1 / tex->width();
- SkScalar hInv = SK_Scalar1 / tex->height();
+ SkScalar wInv, hInv, h;
+ if (proxy->textureType() == GrTextureType::kRectangle) {
+ wInv = hInv = 1.f;
+ h = tex->height();
+ } else {
+ wInv = SK_Scalar1 / tex->width();
+ hInv = SK_Scalar1 / tex->height();
+ h = 1.f;
+ }
float values[kPrevDomainCount] = {
SkScalarToFloat(textureDomain.domain().fLeft * wInv),
@@ -175,15 +182,23 @@
SkScalarToFloat(textureDomain.domain().fBottom * hInv)
};
- SkASSERT(values[0] >= 0.0f && values[0] <= 1.0f);
- SkASSERT(values[1] >= 0.0f && values[1] <= 1.0f);
- SkASSERT(values[2] >= 0.0f && values[2] <= 1.0f);
- SkASSERT(values[3] >= 0.0f && values[3] <= 1.0f);
+ if (proxy->textureType() == GrTextureType::kRectangle) {
+ SkASSERT(values[0] >= 0.0f && values[0] <= proxy->height());
+ SkASSERT(values[1] >= 0.0f && values[1] <= proxy->height());
+ SkASSERT(values[2] >= 0.0f && values[2] <= proxy->height());
+ SkASSERT(values[3] >= 0.0f && values[3] <= proxy->height());
+ } else {
+ SkASSERT(values[0] >= 0.0f && values[0] <= 1.0f);
+ SkASSERT(values[1] >= 0.0f && values[1] <= 1.0f);
+ SkASSERT(values[2] >= 0.0f && values[2] <= 1.0f);
+ SkASSERT(values[3] >= 0.0f && values[3] <= 1.0f);
+ }
// vertical flip if necessary
if (kBottomLeft_GrSurfaceOrigin == proxy->origin()) {
- values[1] = 1.0f - values[1];
- values[3] = 1.0f - values[3];
+ values[1] = h - values[1];
+ values[3] = h - values[3];
+
// The top and bottom were just flipped, so correct the ordering
// of elements so that values = (l, t, r, b).
using std::swap;
diff --git a/src/gpu/effects/GrYUVtoRGBEffect.h b/src/gpu/effects/GrYUVtoRGBEffect.h
index 6cdcce9..3d94402 100644
--- a/src/gpu/effects/GrYUVtoRGBEffect.h
+++ b/src/gpu/effects/GrYUVtoRGBEffect.h
@@ -42,7 +42,8 @@
fSamplers[i].reset(std::move(proxies[i]),
GrSamplerState(GrSamplerState::WrapMode::kClamp, filterModes[i]));
fSamplerTransforms[i] = SkMatrix::MakeScale(scales[i].width(), scales[i].height());
- fSamplerCoordTransforms[i].reset(fSamplerTransforms[i], fSamplers[i].proxy(), true);
+ fSamplerCoordTransforms[i] =
+ GrCoordTransform(fSamplerTransforms[i], fSamplers[i].proxy());
}
this->setTextureSamplerCnt(numPlanes);
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 73e1f9d..9f26a7c 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -227,11 +227,7 @@
if (kGL_GrGLStandard == standard) {
if (version >= GR_GL_VER(3, 1) || ctxInfo.hasExtension("GL_ARB_texture_rectangle") ||
ctxInfo.hasExtension("GL_ANGLE_texture_rectangle")) {
- // We also require textureSize() support for rectangle 2D samplers which was added in
- // GLSL 1.40.
- if (ctxInfo.glslGeneration() >= k140_GrGLSLGeneration) {
- fRectangleTextureSupport = true;
- }
+ fRectangleTextureSupport = true;
}
} else {
// Command buffer exposes this in GL ES context for Chromium reasons,
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index df10ffd..63bf032 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3739,11 +3739,13 @@
sy0 = sh - sy0;
sy1 = sh - sy1;
}
- // src rect edges in normalized texture space (0 to 1)
- sx0 /= sw;
- sx1 /= sw;
- sy0 /= sh;
- sy1 /= sh;
+ if (srcTex->texturePriv().textureType() != GrTextureType::kRectangle) {
+ // src rect edges in normalized texture space (0 to 1)
+ sx0 /= sw;
+ sx1 /= sw;
+ sy0 /= sh;
+ sy1 /= sh;
+ }
GL_CALL(Uniform4f(fCopyPrograms[progIdx].fPosXformUniform, dx1 - dx0, dy1 - dy0, dx0, dy0));
GL_CALL(Uniform4f(fCopyPrograms[progIdx].fTexCoordXformUniform,
diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
index fb6e7f2..8e6099e 100644
--- a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
@@ -24,14 +24,26 @@
}
if (coordTransform.reverseY()) {
- // combined.postScale(1,-1);
- // combined.postTranslate(0,1);
- combined.set(SkMatrix::kMSkewY,
- combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
- combined.set(SkMatrix::kMScaleY,
- combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
- combined.set(SkMatrix::kMTransY,
- combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
+ if (coordTransform.normalize()) {
+ // combined.postScale(1,-1);
+ // combined.postTranslate(0,1);
+ combined.set(SkMatrix::kMSkewY,
+ combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
+ combined.set(SkMatrix::kMScaleY,
+ combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
+ combined.set(SkMatrix::kMTransY,
+ combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
+ } else {
+ // combined.postScale(1, -1);
+ // combined.postTranslate(0,1);
+ SkScalar h = coordTransform.peekTexture()->height();
+ combined.set(SkMatrix::kMSkewY,
+ h * combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
+ combined.set(SkMatrix::kMScaleY,
+ h * combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
+ combined.set(SkMatrix::kMTransY,
+ h * combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
+ }
}
return combined;
}
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 255f937..7ef5896 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -54,9 +54,11 @@
SkScalarFraction(qt) != SkScalarFraction(srcRect.fTop);
}
-static SkRect compute_domain(Domain domain, GrSamplerState::Filter filter,
- GrSurfaceOrigin origin, const SkRect& srcRect, float iw, float ih) {
- static constexpr SkRect kLargeRect = {-2, -2, 2, 2};
+// if normalizing the domain then pass 1/width, 1/height, 1 for iw, ih, h. Otherwise pass
+// 1, 1, and height.
+static SkRect compute_domain(Domain domain, GrSamplerState::Filter filter, GrSurfaceOrigin origin,
+ const SkRect& srcRect, float iw, float ih, float h) {
+ static constexpr SkRect kLargeRect = {-100000, -100000, 1000000, 1000000};
if (domain == Domain::kNo) {
// Either the quad has no domain constraint and is batched with a domain constrained op
// (in which case we want a domain that doesn't restrict normalized tex coords), or the
@@ -75,7 +77,7 @@
ltrb *= Sk4f(iw, ih, iw, ih);
if (origin == kBottomLeft_GrSurfaceOrigin) {
static const Sk4f kMul = {1.f, -1.f, 1.f, -1.f};
- static const Sk4f kAdd = {0.f, 1.f, 0.f, 1.f};
+ static const Sk4f kAdd = {0.f, h, 0.f, h};
ltrb = SkNx_shuffle<0, 3, 2, 1>(kMul * ltrb + kAdd);
}
@@ -84,8 +86,10 @@
return domainRect;
}
-static GrPerspQuad compute_src_quad(GrSurfaceOrigin origin, const SkRect& srcRect,
- float iw, float ih) {
+// If normalizing the src quad then pass 1/width, 1/height, 1 for iw, ih, h. Otherwise pass
+// 1, 1, and height.
+static GrPerspQuad compute_src_quad(GrSurfaceOrigin origin, const SkRect& srcRect, float iw,
+ float ih, float h) {
// Convert the pixel-space src rectangle into normalized texture coordinates
SkRect texRect = {
iw * srcRect.fLeft,
@@ -94,8 +98,8 @@
ih * srcRect.fBottom
};
if (origin == kBottomLeft_GrSurfaceOrigin) {
- texRect.fTop = 1.f - texRect.fTop;
- texRect.fBottom = 1.f - texRect.fBottom;
+ texRect.fTop = h - texRect.fTop;
+ texRect.fBottom = h - texRect.fBottom;
}
return GrPerspQuad(texRect, SkMatrix::I());
}
@@ -305,13 +309,21 @@
TRACE_EVENT0("skia", TRACE_FUNC);
auto origin = proxy->origin();
const auto* texture = proxy->peekTexture();
- float iw = 1.f / texture->width();
- float ih = 1.f / texture->height();
+ float iw, ih, h;
+ if (proxy->textureType() == GrTextureType::kRectangle) {
+ iw = ih = 1.f;
+ h = texture->height();
+ } else {
+ iw = 1.f / texture->width();
+ ih = 1.f / texture->height();
+ h = 1.f;
+ }
for (int i = start; i < start + cnt; ++i) {
const auto q = fQuads[i];
- GrPerspQuad srcQuad = compute_src_quad(origin, q.srcRect(), iw, ih);
- SkRect domain = compute_domain(q.domain(), this->filter(), origin, q.srcRect(), iw, ih);
+ GrPerspQuad srcQuad = compute_src_quad(origin, q.srcRect(), iw, ih, h);
+ SkRect domain =
+ compute_domain(q.domain(), this->filter(), origin, q.srcRect(), iw, ih, h);
v = GrQuadPerEdgeAA::Tessellate(v, spec, q.quad(), q.color(), srcQuad, domain,
q.aaFlags());
}
diff --git a/src/shaders/SkPerlinNoiseShader.cpp b/src/shaders/SkPerlinNoiseShader.cpp
index b0e3b58..b0d464b 100644
--- a/src/shaders/SkPerlinNoiseShader.cpp
+++ b/src/shaders/SkPerlinNoiseShader.cpp
@@ -768,7 +768,7 @@
, fNoiseSampler(std::move(noiseProxy))
, fPaintingData(std::move(paintingData)) {
this->setTextureSamplerCnt(2);
- fCoordTransform.reset(matrix);
+ fCoordTransform = GrCoordTransform(matrix);
this->addCoordTransform(&fCoordTransform);
}
@@ -1191,7 +1191,7 @@
, fGradientSampler(std::move(gradientProxy))
, fPaintingData(std::move(paintingData)) {
this->setTextureSamplerCnt(2);
- fCoordTransform.reset(matrix);
+ fCoordTransform = GrCoordTransform(matrix);
this->addCoordTransform(&fCoordTransform);
}
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 3374630..6f9fcd9 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -1549,37 +1549,6 @@
std::move(ifFalse)));
}
-// scales the texture coordinates by the texture size for sampling rectangle textures.
-// For float2coordinates, implements the transformation:
-// texture(sampler, coord) -> texture(sampler, textureSize(sampler) * coord)
-// For float3coordinates, implements the transformation:
-// texture(sampler, coord) -> texture(sampler, float3textureSize(sampler), 1.0) * coord))
-void IRGenerator::fixRectSampling(std::vector<std::unique_ptr<Expression>>& arguments) {
- SkASSERT(arguments.size() == 2);
- SkASSERT(arguments[0]->fType == *fContext.fSampler2DRect_Type);
- SkASSERT(arguments[0]->fKind == Expression::kVariableReference_Kind);
- const Variable& sampler = ((VariableReference&) *arguments[0]).fVariable;
- const Symbol* textureSizeSymbol = (*fSymbolTable)["textureSize"];
- SkASSERT(textureSizeSymbol->fKind == Symbol::kFunctionDeclaration_Kind);
- const FunctionDeclaration& textureSize = (FunctionDeclaration&) *textureSizeSymbol;
- std::vector<std::unique_ptr<Expression>> sizeArguments;
- sizeArguments.emplace_back(new VariableReference(-1, sampler));
- std::unique_ptr<Expression> float2ize = call(-1, textureSize, std::move(sizeArguments));
- const Type& type = arguments[1]->fType;
- std::unique_ptr<Expression> scale;
- if (type == *fContext.fFloat2_Type) {
- scale = std::move(float2ize);
- } else {
- SkASSERT(type == *fContext.fFloat3_Type);
- std::vector<std::unique_ptr<Expression>> float3rguments;
- float3rguments.push_back(std::move(float2ize));
- float3rguments.emplace_back(new FloatLiteral(fContext, -1, 1.0));
- scale.reset(new Constructor(-1, *fContext.fFloat3_Type, std::move(float3rguments)));
- }
- arguments[1].reset(new BinaryExpression(-1, std::move(scale), Token::STAR,
- std::move(arguments[1]), type));
-}
-
std::unique_ptr<Expression> IRGenerator::call(int offset,
const FunctionDeclaration& function,
std::vector<std::unique_ptr<Expression>> arguments) {
@@ -1620,10 +1589,6 @@
VariableReference::kPointer_RefKind);
}
}
- if (function.fBuiltin && function.fName == "texture" &&
- arguments[0]->fType == *fContext.fSampler2DRect_Type) {
- this->fixRectSampling(arguments);
- }
return std::unique_ptr<FunctionCall>(new FunctionCall(offset, *returnType, function,
std::move(arguments)));
}
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index f456915..0effeb4 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -167,7 +167,6 @@
// returns a statement which converts sk_Position from device to normalized coordinates
std::unique_ptr<Statement> getNormalizeSkPositionCode();
- void fixRectSampling(std::vector<std::unique_ptr<Expression>>& arguments);
void checkValid(const Expression& expr);
void setRefKind(const Expression& expr, VariableReference::RefKind kind);
void getConstantInt(const Expression& value, int64_t* out);