Add support for transformations.

This change adds partial support for the following transforms:
- scale()
- translate()
- rotate()
- setMatrix()
- getMatrix()

The transform is stored in a snapshot and saved/restored as needed.
The transform is currently not applied to the clip rect and is not
mapped to the vertex shader.

Change-Id: Id48993453311200804149917d0c126a4d0471226
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 638c1b8..cbbce382f2 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -22,30 +22,32 @@
 
 #include <utils/Log.h>
 
+#include <SkMatrix.h>
+
 #include "Matrix.h"
 
 namespace android {
 
 void Matrix4::loadIdentity() {
-	mMat[0]  = 1;
-	mMat[1]  = 0;
-	mMat[2]  = 0;
-	mMat[3]  = 0;
+	mMat[0]  = 1.0f;
+	mMat[1]  = 0.0f;
+	mMat[2]  = 0.0f;
+	mMat[3]  = 0.0f;
 
-	mMat[4]  = 0;
-	mMat[5]  = 1;
-	mMat[6]  = 0;
-	mMat[7]  = 0;
+	mMat[4]  = 0.0f;
+	mMat[5]  = 1.0f;
+	mMat[6]  = 0.0f;
+	mMat[7]  = 0.0f;
 
-	mMat[8]  = 0;
-	mMat[9]  = 0;
-	mMat[10] = 1;
-	mMat[11] = 0;
+	mMat[8]  = 0.0f;
+	mMat[9]  = 0.0f;
+	mMat[10] = 1.0f;
+	mMat[11] = 0.0f;
 
-	mMat[12] = 0;
-	mMat[13] = 0;
-	mMat[14] = 0;
-	mMat[15] = 1;
+	mMat[12] = 0.0f;
+	mMat[13] = 0.0f;
+	mMat[14] = 0.0f;
+	mMat[15] = 1.0f;
 }
 
 void Matrix4::load(const float* v) {
@@ -56,6 +58,40 @@
 	memcpy(mMat, v.mMat, sizeof(mMat));
 }
 
+void Matrix4::load(const SkMatrix& v) {
+	memset(mMat, 0, sizeof(mMat));
+
+	mMat[0]  = v[SkMatrix::kMScaleX];
+	mMat[4]  = v[SkMatrix::kMSkewX];
+	mMat[12] = v[SkMatrix::kMTransX];
+
+	mMat[1]  = v[SkMatrix::kMSkewY];
+	mMat[5]  = v[SkMatrix::kMScaleY];
+	mMat[13] = v[SkMatrix::kMTransY];
+
+	mMat[3]  = v[SkMatrix::kMPersp0];
+	mMat[7]  = v[SkMatrix::kMPersp1];
+	mMat[15] = v[SkMatrix::kMPersp2];
+
+	mMat[10] = 1.0f;
+}
+
+void Matrix4::copyTo(SkMatrix& v) const {
+	v.reset();
+
+	v.set(SkMatrix::kMScaleX, mMat[0]);
+	v.set(SkMatrix::kMSkewX,  mMat[4]);
+	v.set(SkMatrix::kMTransX, mMat[12]);
+
+	v.set(SkMatrix::kMSkewY,  mMat[1]);
+	v.set(SkMatrix::kMScaleY, mMat[5]);
+	v.set(SkMatrix::kMTransY, mMat[13]);
+
+	v.set(SkMatrix::kMPersp0, mMat[3]);
+	v.set(SkMatrix::kMPersp1, mMat[7]);
+	v.set(SkMatrix::kMPersp2, mMat[15]);
+}
+
 void Matrix4::copyTo(float* v) const {
 	memcpy(v, mMat, sizeof(mMat));
 }
@@ -75,13 +111,13 @@
 }
 
 void Matrix4::loadRotate(float angle, float x, float y, float z) {
-	mMat[3]  = 0;
-	mMat[7]  = 0;
-	mMat[11] = 0;
-	mMat[12] = 0;
-	mMat[13] = 0;
-	mMat[14] = 0;
-	mMat[15] = 1;
+	mMat[3]  = 0.0f;
+	mMat[7]  = 0.0f;
+	mMat[11] = 0.0f;
+	mMat[12] = 0.0f;
+	mMat[13] = 0.0f;
+	mMat[14] = 0.0f;
+	mMat[15] = 1.0f;
 
 	angle *= float(M_PI / 180.0f);
 	float c = cosf(angle);
@@ -131,9 +167,9 @@
 
 void Matrix4::loadOrtho(float left, float right, float bottom, float top, float near, float far) {
     loadIdentity();
-    mMat[0]  = 2 / (right - left);
-    mMat[5]  = 2 / (top - bottom);
-    mMat[10] = -2 / (far - near);
+    mMat[0]  = 2.0f / (right - left);
+    mMat[5]  = 2.0f / (top - bottom);
+    mMat[10] = -2.0f / (far - near);
     mMat[12] = -(right + left) / (right - left);
     mMat[13] = -(top + bottom) / (top - bottom);
     mMat[14] = -(far + near) / (far - near);
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 51014a9..80f3fd6 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_MATRIX_H
 #define ANDROID_MATRIX_H
 
+#include <SkMatrix.h>
+
 namespace android {
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -37,10 +39,15 @@
 		load(v);
 	}
 
+	Matrix4(const SkMatrix& v) {
+		load(v);
+	}
+
 	void loadIdentity();
 
 	void load(const float* v);
 	void load(const Matrix4& v);
+	void load(const SkMatrix& v);
 
 	void loadTranslate(float x, float y, float z);
 	void loadScale(float sx, float sy, float sz);
@@ -74,10 +81,11 @@
 	}
 
 	void copyTo(float* v) const;
+	void copyTo(SkMatrix& v) const;
 
 	void dump() const;
 
-//private:
+private:
     inline float get(int i, int j) const {
         return mMat[i * 4 + j];
     }
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 1416ce1..e19795e7 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -33,17 +33,22 @@
 
 namespace android {
 
+///////////////////////////////////////////////////////////////////////////////
+// Constructors/destructor
+///////////////////////////////////////////////////////////////////////////////
+
 OpenGLRenderer::OpenGLRenderer() {
     LOGD("Create OpenGLRenderer");
-
-    mSnapshot = new Snapshot;
-    mSaveCount = 0;
 }
 
 OpenGLRenderer::~OpenGLRenderer() {
     LOGD("Destroy OpenGLRenderer");
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// Setup
+///////////////////////////////////////////////////////////////////////////////
+
 void OpenGLRenderer::setViewport(int width, int height) {
     glViewport(0, 0, width, height);
 
@@ -56,15 +61,23 @@
 }
 
 void OpenGLRenderer::prepare() {
+	mSnapshot = &mFirstSnapshot;
+	mSaveCount = 0;
+
     glDisable(GL_SCISSOR_TEST);
 
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     glClear(GL_COLOR_BUFFER_BIT);
 
     glEnable(GL_SCISSOR_TEST);
+
     mSnapshot->clipRect.set(0.0f, 0.0f, mWidth, mHeight);
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// State management
+///////////////////////////////////////////////////////////////////////////////
+
 int OpenGLRenderer::getSaveCount() const {
 	return mSaveCount;
 }
@@ -97,8 +110,7 @@
 
 int OpenGLRenderer::saveSnapshot() {
 	mSnapshot = new Snapshot(mSnapshot);
-	mSaveCount++;
-	return mSaveCount;
+	return ++mSaveCount;
 }
 
 bool OpenGLRenderer::restoreSnapshot() {
@@ -106,14 +118,50 @@
 	bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet;
 
 	mSaveCount--;
-	mSnapshot = mSnapshot->previous;
+
+	// Do not merge these two lines!
+	sp<Snapshot> previous = mSnapshot->previous;
+	mSnapshot = previous;
 
 	return restoreClip;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// Transforms
+///////////////////////////////////////////////////////////////////////////////
+
+void OpenGLRenderer::translate(float dx, float dy) {
+	mSnapshot->transform.translate(dx, dy, 0.0f);
+}
+
+void OpenGLRenderer::rotate(float degrees) {
+	mSnapshot->transform.rotate(degrees, 0.0f, 0.0f, 1.0f);
+}
+
+void OpenGLRenderer::scale(float sx, float sy) {
+	mSnapshot->transform.scale(sx, sy, 1.0f);
+}
+
+void OpenGLRenderer::setMatrix(SkMatrix* matrix) {
+	mSnapshot->transform.load(*matrix);
+}
+
+void OpenGLRenderer::getMatrix(SkMatrix* matrix) {
+	mSnapshot->transform.copyTo(*matrix);
+}
+
+void OpenGLRenderer::concatMatrix(SkMatrix* matrix) {
+	mat4 m(*matrix);
+	mSnapshot->transform.multiply(m);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Clipping
+///////////////////////////////////////////////////////////////////////////////
+
 void OpenGLRenderer::setScissorFromClip() {
-	Rect clip = mSnapshot->clipRect;
-	glScissor(clip.left, clip.top, clip.getWidth(), clip.getHeight());
+	Rect* clip = &(mSnapshot->clipRect);
+	glScissor(clip->left, clip->top, clip->getWidth(), clip->getHeight());
 }
 
 bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom) {
@@ -126,6 +174,10 @@
 	return clipped;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// Drawing
+///////////////////////////////////////////////////////////////////////////////
+
 void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
 	LOGD("Drawing color");
 }
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 8a541fc..595768c 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -17,24 +17,36 @@
 #ifndef ANDROID_OPENGL_RENDERER_H
 #define ANDROID_OPENGL_RENDERER_H
 
+#include <SkMatrix.h>
 #include <SkXfermode.h>
 
 #include <utils/RefBase.h>
 
+#include "Matrix.h"
 #include "Rect.h"
 
 namespace android {
 
+///////////////////////////////////////////////////////////////////////////////
+// Support
+///////////////////////////////////////////////////////////////////////////////
+
 class Snapshot: public LightRefBase<Snapshot> {
 public:
-	Snapshot() { }
+	Snapshot() {
+	}
 
-	Snapshot(const sp<Snapshot> s): clipRect(s->clipRect), flags(0), previous(s) { }
+	Snapshot(const sp<Snapshot> s): transform(s->transform), clipRect(s->clipRect),
+				flags(0), previous(s) {
+	}
 
 	enum Flags {
 		kFlagClipSet = 0x1,
 	};
 
+	// Local transformations
+	mat4 transform;
+
 	// Clipping rectangle at the time of this snapshot
 	Rect clipRect;
 
@@ -45,6 +57,10 @@
 	sp<Snapshot> previous;
 }; // struct Snapshot
 
+///////////////////////////////////////////////////////////////////////////////
+// Renderer
+///////////////////////////////////////////////////////////////////////////////
+
 class OpenGLRenderer {
 public:
     OpenGLRenderer();
@@ -58,6 +74,14 @@
     void restore();
     void restoreToCount(int saveCount);
 
+    void translate(float dx, float dy);
+    void rotate(float degrees);
+    void scale(float sx, float sy);
+
+    void setMatrix(SkMatrix* matrix);
+    void getMatrix(SkMatrix* matrix);
+    void concatMatrix(SkMatrix* matrix);
+
     bool clipRect(float left, float top, float right, float bottom);
 
     void drawColor(int color, SkXfermode::Mode mode);
@@ -76,6 +100,8 @@
 
     // Number of saved states
     int mSaveCount;
+    // Base state
+    Snapshot mFirstSnapshot;
     // Current state
     sp<Snapshot> mSnapshot;
 }; // class OpenGLRenderer