Add support for ColorFilters.

Color filters are fully supported and can be used with shaders.

Change-Id: Id90ccf1c81cb462f2431f366f3f8f710d7971e04
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 187e9d8..d694039 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -132,6 +132,7 @@
 
     mCurrentProgram = NULL;
     mShader = NULL;
+    mColorFilter = NULL;
 
     memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
 
@@ -460,7 +461,6 @@
     const float u2 = srcRight / width;
     const float v2 = srcBottom / height;
 
-    // TODO: Do this in the shader
     resetDrawTextureTexCoords(u1, v1, u2, v2);
 
     drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture, paint);
@@ -552,6 +552,8 @@
     mModelView.loadIdentity();
 
     GLuint textureUnit = 0;
+    // Needs to be set prior to calling FontRenderer::getTexture()
+    glActiveTexture(gTextureUnits[textureUnit]);
 
     ProgramDescription description;
     description.hasTexture = true;
@@ -559,10 +561,14 @@
     if (mShader) {
         mShader->describe(description, mExtensions);
     }
+    if (mColorFilter) {
+        mColorFilter->describe(description, mExtensions);
+    }
 
     useProgram(mProgramCache.get(description));
     mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform);
 
+    // Text is always blended, no need to check the shader
     chooseBlending(true, mode);
     bindTexture(mFontRenderer.getTexture(), GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit);
     glUniform1i(mCurrentProgram->getUniform("sampler"), textureUnit);
@@ -578,6 +584,9 @@
     if (mShader) {
         mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit);
     }
+    if (mColorFilter) {
+        mColorFilter->setupProgram(mCurrentProgram);
+    }
 
     // TODO: Implement scale properly
     const Rect& clip = mSnapshot->getLocalClip();
@@ -604,6 +613,18 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// Color filters
+///////////////////////////////////////////////////////////////////////////////
+
+void OpenGLRenderer::resetColorFilter() {
+    mColorFilter = NULL;
+}
+
+void OpenGLRenderer::setupColorFilter(SkiaColorFilter* filter) {
+    mColorFilter = filter;
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // Drawing implementation
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -631,6 +652,9 @@
     if (mShader) {
         mShader->describe(description, mExtensions);
     }
+    if (mColorFilter) {
+        mColorFilter->describe(description, mExtensions);
+    }
 
     // Build and use the appropriate shader
     useProgram(mProgramCache.get(description));
@@ -654,6 +678,9 @@
     if (mShader) {
         mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit);
     }
+    if (mColorFilter) {
+        mColorFilter->setupProgram(mCurrentProgram);
+    }
 
     // Draw the mesh
     glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
@@ -680,6 +707,9 @@
         GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount) {
     ProgramDescription description;
     description.hasTexture = true;
+    if (mColorFilter) {
+        mColorFilter->describe(description, mExtensions);
+    }
 
     mModelView.loadTranslate(left, top, 0.0f);
     mModelView.scale(right - left, bottom - top, 1.0f);
@@ -703,6 +733,11 @@
             gMeshStride, vertices);
     glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords);
 
+    // Color filter
+    if (mColorFilter) {
+        mColorFilter->setupProgram(mCurrentProgram);
+    }
+
     if (!indices) {
         glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
     } else {
@@ -712,8 +747,6 @@
 }
 
 void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, bool isPremultiplied) {
-    // In theory we should not blend if the mode is Src, but it's rare enough
-    // that it's not worth it
     blend = blend || mode != SkXfermode::kSrcOver_Mode;
     if (blend) {
         if (!mBlend) {