Add support for circular gradients to the GL renderer.

This change also adds full support for local transformation matrices on
sweep and radial gradients.

Change-Id: Id8773bc0766575190e3f3d51984fc5e57b266c3f
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index c5d9767..9e1f6c2 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -209,6 +209,30 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// Circular gradient shader
+///////////////////////////////////////////////////////////////////////////////
+
+SkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float radius,
+        uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
+        SkMatrix* matrix, bool blend):
+        SkiaSweepGradientShader(kCircularGradient, x, y, colors, positions, count, key,
+                tileMode, matrix, blend),
+        mRadius(radius) {
+}
+
+void SkiaCircularGradientShader::describe(ProgramDescription& description,
+        const Extensions& extensions) {
+    description.hasGradient = true;
+    description.gradientType = ProgramDescription::kGradientCircular;
+}
+
+void SkiaCircularGradientShader::setupProgram(Program* program, const mat4& modelView,
+        const Snapshot& snapshot, GLuint* textureUnit) {
+    SkiaSweepGradientShader::setupProgram(program, modelView, snapshot, textureUnit);
+    glUniform1f(program->getUniform("gradientRadius"), 1.0f / mRadius);
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // Sweep gradient shader
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -219,6 +243,13 @@
         mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) {
 }
 
+SkiaSweepGradientShader::SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors,
+        float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
+        SkMatrix* matrix, bool blend):
+        SkiaShader(type, key, tileMode, tileMode, matrix, blend),
+        mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) {
+}
+
 SkiaSweepGradientShader::~SkiaSweepGradientShader() {
     delete[] mColors;
     delete[] mPositions;
@@ -243,10 +274,15 @@
     float left = mX;
     float top = mY;
 
+    mat4 shaderMatrix;
     if (mMatrix) {
-        mat4 shaderMatrix(*mMatrix);
+        shaderMatrix.load(*mMatrix);
         shaderMatrix.mapPoint(left, top);
     }
+
+    mat4 copy(shaderMatrix);
+    shaderMatrix.loadInverse(copy);
+
     snapshot.transform->mapPoint(left, top);
 
     mat4 screenSpace(*snapshot.transform);
@@ -255,6 +291,7 @@
     // Uniforms
     bindTexture(texture->id, gTileModes[mTileX], gTileModes[mTileY], textureSlot);
     glUniform1i(program->getUniform("gradientSampler"), textureSlot);
+    glUniformMatrix4fv(program->getUniform("gradientMatrix"), 1, GL_FALSE, &shaderMatrix.data[0]);
     glUniform2f(program->getUniform("gradientStart"), left, top);
     glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
 }