Reduced the complexity of layers composition.

This change also refactors the code base a bit by moving classes out of
OpenGLRenderer into separate headers/implementations. This makes the code
more manageable.

This change also adds documentation for implementation methods. The
undocumented methods are simply Skia's Canvas methods.

Change-Id: I54c68b443580a0129251dddc1a7ac95813d5289e
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 54829a2d..fd76811 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -3,7 +3,8 @@
 
 LOCAL_SRC_FILES:= \
 	Matrix.cpp \
-	OpenGLRenderer.cpp
+	OpenGLRenderer.cpp \
+	Program.cpp
 
 LOCAL_C_INCLUDES += \
 	$(JNI_H_INCLUDE) \
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index e9c7791..877d3bb 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "Matrix"
+#define LOG_TAG "OpenGLRenderer"
 
 #include <math.h>
 #include <stdlib.h>
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 786b927..e764778 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -20,19 +20,11 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
+#include <SkCanvas.h>
+
 #include <utils/Log.h>
 
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <SkCanvas.h>
-#include <SkPaint.h>
-#include <SkXfermode.h>
-
 #include "OpenGLRenderer.h"
-#include "Matrix.h"
 
 namespace android {
 namespace uirenderer {
@@ -57,7 +49,7 @@
 const GLsizei gDrawColorVertexStride = sizeof(SimpleVertex);
 const GLsizei gDrawColorVertexCount = 4;
 
-const TextureVertex gDrawTextureVertices[] = {
+TextureVertex gDrawTextureVertices[] = {
         FV(0.0f, 0.0f, 0.0f, 1.0f),
         FV(1.0f, 0.0f, 1.0f, 1.0f),
         FV(0.0f, 1.0f, 0.0f, 0.0f),
@@ -66,134 +58,15 @@
 const GLsizei gDrawTextureVertexStride = sizeof(TextureVertex);
 const GLsizei gDrawTextureVertexCount = 4;
 
-///////////////////////////////////////////////////////////////////////////////
-// Shaders
-///////////////////////////////////////////////////////////////////////////////
-
-#define SHADER_SOURCE(name, source) const char* name = #source
-
-#include "shaders/drawColor.vert"
-#include "shaders/drawColor.frag"
-
-#include "shaders/drawTexture.vert"
-#include "shaders/drawTexture.frag"
-
-Program::Program(const char* vertex, const char* fragment) {
-    vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
-    fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
-
-    id = glCreateProgram();
-    glAttachShader(id, vertexShader);
-    glAttachShader(id, fragmentShader);
-    glLinkProgram(id);
-
-    GLint status;
-    glGetProgramiv(id, GL_LINK_STATUS, &status);
-    if (status != GL_TRUE) {
-        GLint infoLen = 0;
-        glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);
-        if (infoLen > 1) {
-            char* log = (char*) malloc(sizeof(char) * infoLen);
-            glGetProgramInfoLog(id, infoLen, 0, log);
-            LOGE("Error while linking shaders: %s", log);
-            delete log;
-        }
-        glDeleteProgram(id);
-    }
-}
-
-Program::~Program() {
-    glDeleteShader(vertexShader);
-    glDeleteShader(fragmentShader);
-    glDeleteProgram(id);
-}
-
-void Program::use() {
-    glUseProgram(id);
-}
-
-int Program::addAttrib(const char* name) {
-    int slot = glGetAttribLocation(id, name);
-    attributes.add(name, slot);
-    return slot;
-}
-
-int Program::getAttrib(const char* name) {
-    return attributes.valueFor(name);
-}
-
-int Program::addUniform(const char* name) {
-    int slot = glGetUniformLocation(id, name);
-    uniforms.add(name, slot);
-    return slot;
-}
-
-int Program::getUniform(const char* name) {
-    return uniforms.valueFor(name);
-}
-
-GLuint Program::buildShader(const char* source, GLenum type) {
-    GLuint shader = glCreateShader(type);
-    glShaderSource(shader, 1, &source, 0);
-    glCompileShader(shader);
-
-    GLint status;
-    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
-    if (status != GL_TRUE) {
-        // Some drivers return wrong values for GL_INFO_LOG_LENGTH
-        // use a fixed size instead
-        GLchar log[512];
-        glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]);
-        LOGE("Error while compiling shader: %s", log);
-        glDeleteShader(shader);
-    }
-
-    return shader;
-}
-
-DrawColorProgram::DrawColorProgram():
-        Program(gDrawColorVertexShader, gDrawColorFragmentShader) {
-    getAttribsAndUniforms();
-}
-
-DrawColorProgram::DrawColorProgram(const char* vertex, const char* fragment):
-        Program(vertex, fragment) {
-    getAttribsAndUniforms();
-}
-
-void DrawColorProgram::getAttribsAndUniforms() {
-    position = addAttrib("position");
-    color = addAttrib("color");
-    projection = addUniform("projection");
-    modelView = addUniform("modelView");
-    transform = addUniform("transform");
-}
-
-void DrawColorProgram::use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix,
-        const GLfloat* transformMatrix) {
-    Program::use();
-    glUniformMatrix4fv(projection, 1, GL_FALSE, projectionMatrix);
-    glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewMatrix);
-    glUniformMatrix4fv(transform, 1, GL_FALSE, transformMatrix);
-}
-
-DrawTextureProgram::DrawTextureProgram():
-        DrawColorProgram(gDrawTextureVertexShader, gDrawTextureFragmentShader) {
-    texCoords = addAttrib("texCoords");
-    sampler = addUniform("sampler");
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Support
-///////////////////////////////////////////////////////////////////////////////
-
-const Rect& Snapshot::getMappedClip() {
-    if (flags & kFlagDirtyTransform) {
-        flags &= ~kFlagDirtyTransform;
-        mappedClip.set(clipRect);
-        transform.mapRect(mappedClip);
-    }
-    return mappedClip;
+static inline void resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) {
+    gDrawTextureVertices[0].texture[0] = u1;
+    gDrawTextureVertices[0].texture[1] = v2;
+    gDrawTextureVertices[1].texture[0] = u2;
+    gDrawTextureVertices[1].texture[1] = v2;
+    gDrawTextureVertices[2].texture[0] = u1;
+    gDrawTextureVertices[2].texture[1] = v1;
+    gDrawTextureVertices[3].texture[0] = u2;
+    gDrawTextureVertices[3].texture[1] = v1;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -292,11 +165,28 @@
         // Most of the time, previous->fbo will be 0 to bind the default buffer
         glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo);
 
-        const Rect& layer = current->layer;
-        clipRect(layer.left, layer.top, layer.right, layer.bottom);
-        mSnapshot->transform.loadIdentity();
+        // Restore the clip from the previous snapshot
+        const Rect& clip = previous->getMappedClip();
+        glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight());
 
-        drawTextureRect(0.0f, 0.0f, mWidth, mHeight, current->texture, current->alpha);
+        // Compute the correct texture coordinates for the FBO texture
+        // The texture is currently as big as the window but drawn with
+        // a quad of the appropriate size
+        const Rect& layer = current->layer;
+        Rect texCoords(current->layer);
+        mSnapshot->transform.mapRect(texCoords);
+
+        const float u1 = texCoords.left / float(mWidth);
+        const float v1 = (mHeight - texCoords.top) / float(mHeight);
+        const float u2 = texCoords.right / float(mWidth);
+        const float v2 = (mHeight - texCoords.bottom) / float(mHeight);
+
+        resetDrawTextureTexCoords(u1, v1, u2, v1);
+
+        drawTextureRect(layer.left, layer.top, layer.right, layer.bottom,
+                current->texture, current->alpha);
+
+        resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);
 
         glDeleteFramebuffers(1, &current->fbo);
         glDeleteTextures(1, &current->texture);
@@ -337,11 +227,14 @@
     // The FBO will not be scaled, so we can use lower quality filtering
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
     // TODO ***** IMPORTANT *****
     // Creating a texture-backed FBO works only if the texture is the same size
     // as the original rendering buffer (in this case, mWidth and mHeight.)
     // This is expensive and wasteful and must be fixed.
+    // TODO Additionally we should use an FBO cache
 
     const GLsizei width = mWidth; //right - left;
     const GLsizei height = mHeight; //bottom - right;
@@ -425,7 +318,6 @@
      *     const Rect& clip = mSnapshot->getMappedClip();
      *     return !clip.intersects(r);
      */
-
     Rect r(left, top, right, bottom);
     return !mSnapshot->clipRect.intersects(r);
 }
@@ -485,7 +377,7 @@
 
     mDrawTextureShader->use(&mOrthoMatrix[0], &mModelView.data[0], &mSnapshot->transform.data[0]);
 
-    // TODO Correctly set the blend function
+    // TODO Correctly set the blend function, based on texture format and xfermode
     glEnable(GL_BLEND);
     glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
 
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 527bf3e..1e031b8 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -23,11 +23,12 @@
 #include <SkMatrix.h>
 #include <SkXfermode.h>
 
-#include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
 
 #include "Matrix.h"
+#include "Program.h"
 #include "Rect.h"
+#include "Snapshot.h"
 
 namespace android {
 namespace uirenderer {
@@ -36,122 +37,30 @@
 // Support
 ///////////////////////////////////////////////////////////////////////////////
 
-class Snapshot: public LightRefBase<Snapshot> {
-public:
-    Snapshot() {
-    }
-
-    Snapshot(const sp<Snapshot> s):
-            transform(s->transform),
-            clipRect(s->clipRect),
-            flags(kFlagDirtyTransform),
-            previous(s),
-            layer(0.0f, 0.0f, 0.0f, 0.0f),
-            texture(0),
-            fbo(0),
-            alpha(255) {
-    }
-
-    enum Flags {
-        kFlagClipSet = 0x1,
-        kFlagDirtyTransform = 0x2,
-        kFlagIsLayer = 0x4,
-    };
-
-    const Rect& getMappedClip();
-
-    // Local transformations
-    mat4 transform;
-
-    // Clipping rectangle at the time of this snapshot
-    Rect clipRect;
-
-    // Dirty flags
-    int flags;
-
-    // Previous snapshot in the frames stack
-    sp<Snapshot> previous;
-
-    // Layer, only set if kFlagIsLayer is set
-    Rect layer;
-    GLuint texture;
-    GLuint fbo;
-    float alpha;
-
-private:
-    // Clipping rectangle mapped with the transform
-    Rect mappedClip;
-}; // class Snapshot
-
+/**
+ * Simple structure to describe a vertex with a position.
+ * This is used to draw filled rectangles without a texture.
+ */
 struct SimpleVertex {
     float position[2];
 }; // struct SimpleVertex
 
+/**
+ * Simple structure to describe a vertex with a position and a texture.
+ */
 struct TextureVertex {
     float position[2];
     float texture[2];
 }; // struct TextureVertex
 
-class Program: public LightRefBase<Program> {
-public:
-    Program(const char* vertex, const char* fragment);
-    ~Program();
-
-    void use();
-
-protected:
-    int addAttrib(const char* name);
-    int getAttrib(const char* name);
-
-    int addUniform(const char* name);
-    int getUniform(const char* name);
-
-private:
-    GLuint buildShader(const char* source, GLenum type);
-
-    // Handle of the OpenGL program
-    GLuint id;
-
-    // Handles of the shaders
-    GLuint vertexShader;
-    GLuint fragmentShader;
-
-    // Keeps track of attributes and uniforms slots
-    KeyedVector<const char*, int> attributes;
-    KeyedVector<const char*, int> uniforms;
-}; // class Program
-
-class DrawColorProgram: public Program {
-public:
-    DrawColorProgram();
-    DrawColorProgram(const char* vertex, const char* fragment);
-
-    void use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix,
-             const GLfloat* transformMatrix);
-
-    int position;
-    int color;
-
-    int projection;
-    int modelView;
-    int transform;
-
-protected:
-    void getAttribsAndUniforms();
-};
-
-class DrawTextureProgram: public DrawColorProgram {
-public:
-    DrawTextureProgram();
-
-    int sampler;
-    int texCoords;
-};
-
 ///////////////////////////////////////////////////////////////////////////////
 // Renderer
 ///////////////////////////////////////////////////////////////////////////////
 
+/**
+ * OpenGL renderer used to draw accelerated 2D graphics. The API is a
+ * simplified version of Skia's Canvas API.
+ */
 class OpenGLRenderer {
 public:
     OpenGLRenderer();
@@ -184,12 +93,52 @@
     void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
 
 private:
+    /**
+     * Saves the current state of the renderer as a new snapshot.
+     * The new snapshot is saved in mSnapshot and the previous snapshot
+     * is linked from mSnapshot->previous.
+     *
+     * @return The new save count. This value can be passed to #restoreToCount()
+     */
     int saveSnapshot();
+
+    /**
+     * Restores the current snapshot; mSnapshot becomes mSnapshot->previous.
+     *
+     * @return True if the clip should be also reapplied by calling
+     *         #setScissorFromClip().
+     */
     bool restoreSnapshot();
 
+    /**
+     * Sets the clipping rectangle using glScissor. The clip is defined by
+     * the current snapshot's clipRect member.
+     */
     void setScissorFromClip();
 
+    /**
+     * Draws a colored rectangle with the specified color. The specified coordinates
+     * are transformed by the current snapshot's transform matrix.
+     *
+     * @param left The left coordinate of the rectangle
+     * @param top The top coordinate of the rectangle
+     * @param right The right coordinate of the rectangle
+     * @param bottom The bottom coordinate of the rectangle
+     * @param color The rectangle's ARGB color, defined as a packed 32 bits word
+     */
     void drawColorRect(float left, float top, float right, float bottom, int color);
+
+    /**
+     * Draws a textured rectangle with the specified texture. The specified coordinates
+     * are transformed by the current snapshot's transform matrix.
+     *
+     * @param left The left coordinate of the rectangle
+     * @param top The top coordinate of the rectangle
+     * @param right The right coordinate of the rectangle
+     * @param bottom The bottom coordinate of the rectangle
+     * @param texture The texture name to map onto the rectangle
+     * @param alpha An additional translucency parameter, between 0.0f and 1.0f
+     */
     void drawTextureRect(float left, float top, float right, float bottom, GLuint texture,
             float alpha);
 
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
new file mode 100644
index 0000000..2acddfc
--- /dev/null
+++ b/libs/hwui/Program.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include "Program.h"
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Shaders
+///////////////////////////////////////////////////////////////////////////////
+
+#define SHADER_SOURCE(name, source) const char* name = #source
+
+#include "shaders/drawColor.vert"
+#include "shaders/drawColor.frag"
+
+#include "shaders/drawTexture.vert"
+#include "shaders/drawTexture.frag"
+
+///////////////////////////////////////////////////////////////////////////////
+// Base program
+///////////////////////////////////////////////////////////////////////////////
+
+Program::Program(const char* vertex, const char* fragment) {
+    vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
+    fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
+
+    id = glCreateProgram();
+    glAttachShader(id, vertexShader);
+    glAttachShader(id, fragmentShader);
+    glLinkProgram(id);
+
+    GLint status;
+    glGetProgramiv(id, GL_LINK_STATUS, &status);
+    if (status != GL_TRUE) {
+        GLint infoLen = 0;
+        glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);
+        if (infoLen > 1) {
+            char* log = (char*) malloc(sizeof(char) * infoLen);
+            glGetProgramInfoLog(id, infoLen, 0, log);
+            LOGE("Error while linking shaders: %s", log);
+            delete log;
+        }
+        glDeleteProgram(id);
+    }
+}
+
+Program::~Program() {
+    glDeleteShader(vertexShader);
+    glDeleteShader(fragmentShader);
+    glDeleteProgram(id);
+}
+
+void Program::use() {
+    glUseProgram(id);
+}
+
+int Program::addAttrib(const char* name) {
+    int slot = glGetAttribLocation(id, name);
+    attributes.add(name, slot);
+    return slot;
+}
+
+int Program::getAttrib(const char* name) {
+    return attributes.valueFor(name);
+}
+
+int Program::addUniform(const char* name) {
+    int slot = glGetUniformLocation(id, name);
+    uniforms.add(name, slot);
+    return slot;
+}
+
+int Program::getUniform(const char* name) {
+    return uniforms.valueFor(name);
+}
+
+GLuint Program::buildShader(const char* source, GLenum type) {
+    GLuint shader = glCreateShader(type);
+    glShaderSource(shader, 1, &source, 0);
+    glCompileShader(shader);
+
+    GLint status;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+    if (status != GL_TRUE) {
+        // Some drivers return wrong values for GL_INFO_LOG_LENGTH
+        // use a fixed size instead
+        GLchar log[512];
+        glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]);
+        LOGE("Error while compiling shader: %s", log);
+        glDeleteShader(shader);
+    }
+
+    return shader;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Draw color
+///////////////////////////////////////////////////////////////////////////////
+
+DrawColorProgram::DrawColorProgram():
+        Program(gDrawColorVertexShader, gDrawColorFragmentShader) {
+    getAttribsAndUniforms();
+}
+
+DrawColorProgram::DrawColorProgram(const char* vertex, const char* fragment):
+        Program(vertex, fragment) {
+    getAttribsAndUniforms();
+}
+
+void DrawColorProgram::getAttribsAndUniforms() {
+    position = addAttrib("position");
+    color = addAttrib("color");
+    projection = addUniform("projection");
+    modelView = addUniform("modelView");
+    transform = addUniform("transform");
+}
+
+void DrawColorProgram::use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix,
+        const GLfloat* transformMatrix) {
+    Program::use();
+    glUniformMatrix4fv(projection, 1, GL_FALSE, projectionMatrix);
+    glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewMatrix);
+    glUniformMatrix4fv(transform, 1, GL_FALSE, transformMatrix);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Draw texture
+///////////////////////////////////////////////////////////////////////////////
+
+DrawTextureProgram::DrawTextureProgram():
+        DrawColorProgram(gDrawTextureVertexShader, gDrawTextureFragmentShader) {
+    texCoords = addAttrib("texCoords");
+    sampler = addUniform("sampler");
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
new file mode 100644
index 0000000..ee16a92
--- /dev/null
+++ b/libs/hwui/Program.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_PROGRAM_H
+#define ANDROID_UI_PROGRAM_H
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+
+namespace android {
+namespace uirenderer {
+
+/**
+ * A program holds a vertex and a fragment shader. It offers several utility
+ * methods to query attributes and uniforms.
+ */
+class Program: public LightRefBase<Program> {
+public:
+    /**
+     * Creates a new program with the specified vertex and fragment
+     * shaders sources.
+     */
+    Program(const char* vertex, const char* fragment);
+    ~Program();
+
+    /**
+     * Binds this program to the GL context.
+     */
+    void use();
+
+protected:
+    /**
+     * Adds an attribute with the specified name.
+     *
+     * @return The OpenGL name of the attribute.
+     */
+    int addAttrib(const char* name);
+    /**
+     * Returns the OpenGL name of the specified attribute.
+     */
+    int getAttrib(const char* name);
+
+    /**
+     * Adds a uniform with the specified name.
+     *
+     * @return The OpenGL name of the uniform.
+     */
+    int addUniform(const char* name);
+    /**
+     * Returns the OpenGL name of the specified uniform.
+     */
+    int getUniform(const char* name);
+
+private:
+    /**
+     * Compiles the specified shader of the specified type.
+     *
+     * @return The name of the compiled shader.
+     */
+    GLuint buildShader(const char* source, GLenum type);
+
+    // Name of the OpenGL program
+    GLuint id;
+
+    // Name of the shaders
+    GLuint vertexShader;
+    GLuint fragmentShader;
+
+    // Keeps track of attributes and uniforms slots
+    KeyedVector<const char*, int> attributes;
+    KeyedVector<const char*, int> uniforms;
+}; // class Program
+
+/**
+ * Program used to draw vertices with a simple color. The shaders must
+ * specify the following attributes:
+ *      vec4 position, position of the vertex
+ *      vec4 color, RGBA color of the vertex
+ *
+ * And the following uniforms:
+ *      mat4 projection, the projection matrix
+ *      mat4 modelView, the modelView matrix
+ *      mat4 transform, an extra transformation matrix
+ */
+class DrawColorProgram: public Program {
+public:
+    DrawColorProgram();
+    DrawColorProgram(const char* vertex, const char* fragment);
+
+    /**
+     * Binds the program with the specified projection, modelView and
+     * transform matrices.
+     */
+    void use(const GLfloat* projectionMatrix, const GLfloat* modelViewMatrix,
+             const GLfloat* transformMatrix);
+
+    /**
+     * Name of the position attribute.
+     */
+    int position;
+    /**
+     * Name of the color attribute.
+     */
+    int color;
+
+    /**
+     * Name of the projection uniform.
+     */
+    int projection;
+    /**
+     * Name of the modelView uniform.
+     */
+    int modelView;
+    /**
+     * Name of the transform uniform.
+     */
+    int transform;
+
+protected:
+    void getAttribsAndUniforms();
+};
+
+/**
+ * Program used to draw textured vertices. In addition to everything that the
+ * DrawColorProgram supports, the following two attributes must be specified:
+ *      sampler2D sampler, the texture sampler
+ *      vec2 texCoords, the texture coordinates of the vertex
+ */
+class DrawTextureProgram: public DrawColorProgram {
+public:
+    DrawTextureProgram();
+
+    int sampler;
+    int texCoords;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_UI_PROGRAM_H
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index b382dc3..ad57550 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_UI_RECT_H
 #define ANDROID_UI_RECT_H
 
+#include <utils/Log.h>
+
 namespace android {
 namespace uirenderer {
 
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
new file mode 100644
index 0000000..9a9be2d
--- /dev/null
+++ b/libs/hwui/Snapshot.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_SNAPSHOT_H
+#define ANDROID_UI_SNAPSHOT_H
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <utils/RefBase.h>
+
+#include "Matrix.h"
+#include "Rect.h"
+
+namespace android {
+namespace uirenderer {
+
+/**
+ * A snapshot holds information about the current state of the rendering
+ * surface. A snapshot is usually created whenever the user calls save()
+ * and discarded when the user calls restore(). Once a snapshot is created,
+ * it can hold information for deferred rendering.
+ *
+ * Each snapshot has a link to a previous snapshot, indicating the previous
+ * state of the renderer.
+ */
+class Snapshot: public LightRefBase<Snapshot> {
+public:
+    Snapshot() {
+    }
+
+    /**
+     * Copies the specified snapshot. Only the transform and clip rectangle
+     * are copied. The layer information is set to 0 and the transform is
+     * assumed to be dirty. The specified snapshot is stored as the previous
+     * snapshot.
+     */
+    Snapshot(const sp<Snapshot> s):
+            transform(s->transform),
+            clipRect(s->clipRect),
+            flags(kFlagDirtyTransform),
+            previous(s),
+            layer(0.0f, 0.0f, 0.0f, 0.0f),
+            texture(0),
+            fbo(0),
+            alpha(255) {
+    }
+
+    /**
+     * Various flags set on #flags.
+     */
+    enum Flags {
+        /**
+         * Indicates that the clip region was modified. When this
+         * snapshot is restored so must the clip.
+         */
+        kFlagClipSet = 0x1,
+        /**
+         * Indicates that the snapshot holds new transform
+         * information.
+         */
+        kFlagDirtyTransform = 0x2,
+        /**
+         * Indicates that this snapshot was created when saving
+         * a new layer.
+         */
+        kFlagIsLayer = 0x4,
+    };
+
+    /**
+     * Returns the current clip region mapped by the current transform.
+     */
+    const Rect& getMappedClip() {
+        if (flags & kFlagDirtyTransform) {
+            flags &= ~kFlagDirtyTransform;
+            mappedClip.set(clipRect);
+            transform.mapRect(mappedClip);
+        }
+        return mappedClip;
+    }
+
+    /**
+     * Local transformation. Holds the current translation, scale and
+     * rotation values.
+     */
+    mat4 transform;
+
+    /**
+     * Current clip region.
+     */
+    Rect clipRect;
+
+    /**
+     * Dirty flags.
+     */
+    int flags;
+
+    /**
+     * Previous snapshot.
+     */
+    sp<Snapshot> previous;
+
+    /**
+     * Coordinates of the layer corresponding to this snapshot.
+     * Only set when the flag kFlagIsLayer is set.
+     */
+    Rect layer;
+    /**
+     * Name of the texture used to render the layer.
+     * Only set when the flag kFlagIsLayer is set.
+     */
+    GLuint texture;
+    /**
+     * Name of the FBO used to render the layer.
+     * Only set when the flag kFlagIsLayer is set.
+     */
+    GLuint fbo;
+    /**
+     * Opacity of the layer.
+     * Only set when the flag kFlagIsLayer is set.
+     */
+    float alpha;
+
+private:
+    // Clipping rectangle mapped with the transform
+    Rect mappedClip;
+}; // class Snapshot
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_UI_SNAPSHOT_H