rectangle texture scaling is now handled in skslc

Bug: skia:
Change-Id: I658a95576143d69656cd63aec44ff65d430d332f
Reviewed-on: https://skia-review.googlesource.com/13813
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index d585e09..7665c2a 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -4005,20 +4005,17 @@
     GrGLfloat sx1 = (GrGLfloat)(srcRect.fLeft + w);
     GrGLfloat sy0 = (GrGLfloat)srcRect.fTop;
     GrGLfloat sy1 = (GrGLfloat)(srcRect.fTop + h);
+    int sw = src->width();
     int sh = src->height();
     if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
         sy0 = sh - sy0;
         sy1 = sh - sy1;
     }
-    // src rect edges in normalized texture space (0 to 1) unless we're using a RECTANGLE texture.
-    GrGLenum srcTarget = srcTex->target();
-    if (GR_GL_TEXTURE_RECTANGLE != srcTarget) {
-        int sw = src->width();
-        sx0 /= sw;
-        sx1 /= sw;
-        sy0 /= sh;
-        sy1 /= sh;
-    }
+    // 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/GrGLSLShaderBuilder.cpp b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
index 8658766..2c7e5e4 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
@@ -72,18 +72,7 @@
                                               const char* coordName,
                                               GrSLType varyingType) const {
     const GrShaderVar& sampler = fProgramBuilder->samplerVariable(samplerHandle);
-    GrSLType samplerType = sampler.getType();
-    if (samplerType == kTexture2DRectSampler_GrSLType) {
-        if (varyingType == kVec2f_GrSLType) {
-            out->appendf("texture(%s, textureSize(%s) * %s)",
-                         sampler.c_str(), sampler.c_str(), coordName);
-        } else {
-            out->appendf("texture(%s, vec3(textureSize(%s) * %s.xy, %s.z))",
-                         sampler.c_str(), sampler.c_str(), coordName, coordName);
-        }
-    } else {
-        out->appendf("texture(%s, %s)", sampler.c_str(), coordName);
-    }
+    out->appendf("texture(%s, %s)", sampler.c_str(), coordName);
     append_texture_swizzle(out, fProgramBuilder->samplerSwizzle(samplerHandle));
 }
 
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 9910513..975b05f 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -1112,6 +1112,37 @@
                                                              std::move(ifFalse)));
 }
 
+// scales the texture coordinates by the texture size for sampling rectangle textures.
+// For vec2 coordinates, implements the transformation:
+//     texture(sampler, coord) -> texture(sampler, textureSize(sampler) * coord)
+// For vec3 coordinates, implements the transformation:
+//     texture(sampler, coord) -> texture(sampler, vec3(textureSize(sampler), 1.0) * coord))
+void IRGenerator::fixRectSampling(std::vector<std::unique_ptr<Expression>>& arguments) {
+    ASSERT(arguments.size() == 2);
+    ASSERT(arguments[0]->fType == *fContext.fSampler2DRect_Type);
+    ASSERT(arguments[0]->fKind == Expression::kVariableReference_Kind);
+    const Variable& sampler = ((VariableReference&) *arguments[0]).fVariable;
+    const Symbol* textureSizeSymbol = (*fSymbolTable)["textureSize"];
+    ASSERT(textureSizeSymbol->fKind == Symbol::kFunctionDeclaration_Kind);
+    const FunctionDeclaration& textureSize = (FunctionDeclaration&) *textureSizeSymbol;
+    std::vector<std::unique_ptr<Expression>> sizeArguments;
+    sizeArguments.emplace_back(new VariableReference(Position(), sampler));
+    std::unique_ptr<Expression> vec2Size = call(Position(), textureSize, std::move(sizeArguments));
+    const Type& type = arguments[1]->fType;
+    std::unique_ptr<Expression> scale;
+    if (type == *fContext.fVec2_Type) {
+        scale = std::move(vec2Size);
+    } else {
+        ASSERT(type == *fContext.fVec3_Type);
+        std::vector<std::unique_ptr<Expression>> vec3Arguments;
+        vec3Arguments.push_back(std::move(vec2Size));
+        vec3Arguments.emplace_back(new FloatLiteral(fContext, Position(), 1.0));
+        scale.reset(new Constructor(Position(), *fContext.fVec3_Type, std::move(vec3Arguments)));
+    }
+    arguments[1].reset(new BinaryExpression(Position(), std::move(scale), Token::STAR,
+                                            std::move(arguments[1]), type));
+}
+
 std::unique_ptr<Expression> IRGenerator::call(Position position,
                                               const FunctionDeclaration& function,
                                               std::vector<std::unique_ptr<Expression>> arguments) {
@@ -1149,6 +1180,10 @@
             this->markWrittenTo(*arguments[i], true);
         }
     }
+    if (function.fBuiltin && function.fName == "texture" &&
+        arguments[0]->fType == *fContext.fSampler2DRect_Type) {
+        this->fixRectSampling(arguments);
+    }
     return std::unique_ptr<FunctionCall>(new FunctionCall(position, *returnType, function,
                                                           std::move(arguments)));
 }
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index b0a449a..d4a6846 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -164,6 +164,7 @@
     std::unique_ptr<Statement> convertVarDeclarationStatement(const ASTVarDeclarationStatement& s);
     std::unique_ptr<Statement> convertWhile(const ASTWhileStatement& w);
 
+    void fixRectSampling(std::vector<std::unique_ptr<Expression>>& arguments);
     void checkValid(const Expression& expr);
     void markWrittenTo(const Expression& expr, bool readWrite);
 
diff --git a/src/sksl/sksl.include b/src/sksl/sksl.include
index 11e3710..3d730d4 100644
--- a/src/sksl/sksl.include
+++ b/src/sksl/sksl.include
@@ -281,6 +281,7 @@
 */
 
 $gvec4 texture($gsampler2DRect sampler, vec2 P);
+$gvec4 texture($gsampler2DRect sampler, vec3 P);
 
 /*
 float texture(sampler2DRectShadow sampler, vec3 P);
@@ -312,7 +313,6 @@
 float textureProj(sampler1DShadow sampler, vec4 P, float bias);
 float textureProj(sampler2DShadow sampler, vec4 P);
 float textureProj(sampler2DShadow sampler, vec4 P, float bias);
-$gvec4 textureProj($gsampler2DRect sampler, vec3 P);
 $gvec4 textureProj($gsampler2DRect sampler, vec4 P);
 float textureProj(sampler2DRectShadow sampler, vec4 P);
 $gvec4 textureLod($gsampler1D sampler, float P, float lod);
diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp
index 51a1f63..6151b94 100644
--- a/tests/SkSLGLSLTest.cpp
+++ b/tests/SkSLGLSLTest.cpp
@@ -864,4 +864,43 @@
          "}\n");
 }
 
+DEF_TEST(SkSLRectangleTexture, r) {
+    test(r,
+         "uniform sampler2D test;"
+         "void main() {"
+         "    sk_FragColor = texture(test, vec2(1));"
+         "}",
+         *SkSL::ShaderCapsFactory::Default(),
+         "#version 400\n"
+         "out vec4 sk_FragColor;\n"
+         "uniform sampler2D test;\n"
+         "void main() {\n"
+         "    sk_FragColor = texture(test, vec2(1.0));\n"
+         "}\n");
+    test(r,
+         "uniform sampler2DRect test;"
+         "void main() {"
+         "    sk_FragColor = texture(test, vec2(1));"
+         "}",
+         *SkSL::ShaderCapsFactory::Default(),
+         "#version 400\n"
+         "out vec4 sk_FragColor;\n"
+         "uniform sampler2DRect test;\n"
+         "void main() {\n"
+         "    sk_FragColor = texture(test, textureSize(test) * vec2(1.0));\n"
+         "}\n");
+    test(r,
+         "uniform sampler2DRect test;"
+         "void main() {"
+         "    sk_FragColor = texture(test, vec3(1));"
+         "}",
+         *SkSL::ShaderCapsFactory::Default(),
+         "#version 400\n"
+         "out vec4 sk_FragColor;\n"
+         "uniform sampler2DRect test;\n"
+         "void main() {\n"
+         "    sk_FragColor = texture(test, vec3(textureSize(test), 1.0) * vec3(1.0));\n"
+         "}\n");
+}
+
 #endif