diff options
| author | Romain Guy <romainguy@google.com> | 2010-06-23 17:47:49 -0700 |
|---|---|---|
| committer | Romain Guy <romainguy@google.com> | 2010-06-23 17:47:49 -0700 |
| commit | f6a11b8a9e25ff9861bbba19251bea84d8a5daf2 (patch) | |
| tree | c44f214f59f2206de152585d97b23e2bfaa1b3b0 | |
| parent | bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4 (diff) | |
| download | frameworks_base-f6a11b8a9e25ff9861bbba19251bea84d8a5daf2.zip frameworks_base-f6a11b8a9e25ff9861bbba19251bea84d8a5daf2.tar.gz frameworks_base-f6a11b8a9e25ff9861bbba19251bea84d8a5daf2.tar.bz2 | |
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
| -rw-r--r-- | core/java/android/view/GLES20Canvas.java | 27 | ||||
| -rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 100 | ||||
| -rw-r--r-- | graphics/java/android/graphics/Matrix.java | 5 | ||||
| -rw-r--r-- | libs/hwui/Matrix.cpp | 94 | ||||
| -rw-r--r-- | libs/hwui/Matrix.h | 10 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 68 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.h | 30 |
7 files changed, 254 insertions, 80 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index fbfea95..8df2e86 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -212,8 +212,10 @@ class GLES20Canvas extends Canvas { @Override public void translate(float dx, float dy) { - // TODO: Implement + nTranslate(mRenderer, dx, dy); } + + private native void nTranslate(int renderer, float dx, float dy); @Override public void skew(float sx, float sy) { @@ -222,30 +224,39 @@ class GLES20Canvas extends Canvas { @Override public void rotate(float degrees) { - // TODO: Implement + nRotate(mRenderer, degrees); } + + private native void nRotate(int renderer, float degrees); @Override public void scale(float sx, float sy) { - // TODO: Implement + nScale(mRenderer, sx, sy); } - + private native void nScale(int renderer, float sx, float sy); + @Override public void setMatrix(Matrix matrix) { - // TODO: Implement + nSetMatrix(mRenderer, matrix.native_instance); } + + private native void nSetMatrix(int renderer, int matrix); @Override - public void getMatrix(Matrix ctm) { - // TODO: Implement + public void getMatrix(Matrix matrix) { + nGetMatrix(mRenderer, matrix.native_instance); } + + private native void nGetMatrix(int renderer, int matrix); @Override public void concat(Matrix matrix) { - // TODO: Implement + nConcatMatrix(mRenderer, matrix.native_instance); } + private native void nConcatMatrix(int renderer, int matrix); + /////////////////////////////////////////////////////////////////////////// // State management /////////////////////////////////////////////////////////////////////////// diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 8c2a04c..1ca172d 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -18,12 +18,11 @@ #include <nativehelper/JNIHelp.h> #include <android_runtime/AndroidRuntime.h> +#include <SkMatrix.h> #include <SkXfermode.h> #include <OpenGLRenderer.h> -#define UI ((OpenGLRenderer*) renderer) - namespace android { // ---------------------------------------------------------------------------- @@ -34,73 +33,104 @@ static OpenGLRenderer* android_view_GLES20Renderer_createRenderer(JNIEnv* env, j return new OpenGLRenderer; } -static void android_view_GLES20Renderer_destroyRenderer(JNIEnv* env, jobject canvas, jint renderer) { - delete UI; +static void android_view_GLES20Renderer_destroyRenderer(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer) { + delete renderer; } // ---------------------------------------------------------------------------- // Setup // ---------------------------------------------------------------------------- -static void android_view_GLES20Renderer_setViewport(JNIEnv* env, jobject canvas, jint renderer, - jint width, jint height) { - - UI->setViewport(width, height); +static void android_view_GLES20Renderer_setViewport(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, jint width, jint height) { + renderer->setViewport(width, height); } -static void android_view_GLES20Renderer_prepare(JNIEnv* env, jobject canvas, jint renderer) { - - UI->prepare(); +static void android_view_GLES20Renderer_prepare(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer) { + renderer->prepare(); } // ---------------------------------------------------------------------------- // State // ---------------------------------------------------------------------------- -static jint android_view_GLES20Renderer_save(JNIEnv* env, jobject canvas, jint renderer, +static jint android_view_GLES20Renderer_save(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer, jint flags) { + return renderer->save(flags); +} - return UI->save(flags); +static jint android_view_GLES20Renderer_getSaveCount(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer) { + return renderer->getSaveCount(); } -static jint android_view_GLES20Renderer_getSaveCount(JNIEnv* env, jobject canvas, jint renderer) { - return UI->getSaveCount(); +static void android_view_GLES20Renderer_restore(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer) { + renderer->restore(); } -static void android_view_GLES20Renderer_restore(JNIEnv* env, jobject canvas, jint renderer) { - UI->restore(); +static void android_view_GLES20Renderer_restoreToCount(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, jint saveCount) { + renderer->restoreToCount(saveCount); } -static void android_view_GLES20Renderer_restoreToCount(JNIEnv* env, jobject canvas, jint renderer, - jint saveCount) { +// ---------------------------------------------------------------------------- +// Clipping +// ---------------------------------------------------------------------------- + +static bool android_view_GLES20Renderer_clipRectF(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom) { + return renderer->clipRect(left, top, right, bottom); +} - UI->restoreToCount(saveCount); +static bool android_view_GLES20Renderer_clipRect(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, jint left, jint top, jint right, jint bottom) { + return renderer->clipRect(float(left), float(top), float(right), float(bottom)); } // ---------------------------------------------------------------------------- -// Clipping +// Transforms // ---------------------------------------------------------------------------- -static bool android_view_GLES20Renderer_clipRectF(JNIEnv* env, jobject canvas, jint renderer, - jfloat left, jfloat top, jfloat right, jfloat bottom) { +static void android_view_GLES20Renderer_translate(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, jfloat dx, jfloat dy) { + renderer->translate(dx, dy); +} - return UI->clipRect(left, top, right, bottom); +static void android_view_GLES20Renderer_rotate(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, jfloat degrees) { + renderer->rotate(degrees); } -static bool android_view_GLES20Renderer_clipRect(JNIEnv* env, jobject canvas, jint renderer, - jint left, jint top, jint right, jint bottom) { +static void android_view_GLES20Renderer_scale(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, jfloat sx, jfloat sy) { + renderer->scale(sx, sy); +} - return UI->clipRect(float(left), float(top), float(right), float(bottom)); +static void android_view_GLES20Renderer_setMatrix(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, SkMatrix* matrix) { + renderer->setMatrix(matrix); +} + +static void android_view_GLES20Renderer_getMatrix(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, SkMatrix* matrix) { + renderer->getMatrix(matrix); +} + +static void android_view_GLES20Renderer_concatMatrix(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, SkMatrix* matrix) { + renderer->concatMatrix(matrix); } // ---------------------------------------------------------------------------- // Drawing // ---------------------------------------------------------------------------- -static void android_view_GLES20Renderer_drawColor(JNIEnv* env, jobject canvas, jint renderer, - jint color, jint mode) { - - UI->drawColor(color, (SkXfermode::Mode) mode); +static void android_view_GLES20Renderer_drawColor(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, jint color, jint mode) { + renderer->drawColor(color, (SkXfermode::Mode) mode); } // ---------------------------------------------------------------------------- @@ -123,6 +153,14 @@ static JNINativeMethod gMethods[] = { { "nClipRect", "(IFFFF)Z", (void*) android_view_GLES20Renderer_clipRectF }, { "nClipRect", "(IIIII)Z", (void*) android_view_GLES20Renderer_clipRect }, + { "nTranslate", "(IFF)V", (void*) android_view_GLES20Renderer_translate }, + { "nRotate", "(IF)V", (void*) android_view_GLES20Renderer_rotate }, + { "nScale", "(IFF)V", (void*) android_view_GLES20Renderer_scale }, + + { "nSetMatrix", "(II)V", (void*) android_view_GLES20Renderer_setMatrix }, + { "nGetMatrix", "(II)V", (void*) android_view_GLES20Renderer_getMatrix }, + { "nConcatMatrix", "(II)V", (void*) android_view_GLES20Renderer_concatMatrix }, + { "nDrawColor", "(III)V", (void*) android_view_GLES20Renderer_drawColor }, }; diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java index f549900..b336995 100644 --- a/graphics/java/android/graphics/Matrix.java +++ b/graphics/java/android/graphics/Matrix.java @@ -37,7 +37,10 @@ public class Matrix { public static final int MPERSP_1 = 7; //!< use with getValues/setValues public static final int MPERSP_2 = 8; //!< use with getValues/setValues - /* package */ int native_instance; + /** + * @hide + */ + public int native_instance; /** * Create an identity matrix diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp index 638c1b8..cbbce38 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[4] = 0; - mMat[5] = 1; - mMat[6] = 0; - mMat[7] = 0; - - mMat[8] = 0; - mMat[9] = 0; - mMat[10] = 1; - mMat[11] = 0; - - mMat[12] = 0; - mMat[13] = 0; - mMat[14] = 0; - mMat[15] = 1; + mMat[0] = 1.0f; + mMat[1] = 0.0f; + mMat[2] = 0.0f; + mMat[3] = 0.0f; + + mMat[4] = 0.0f; + mMat[5] = 1.0f; + mMat[6] = 0.0f; + mMat[7] = 0.0f; + + mMat[8] = 0.0f; + mMat[9] = 0.0f; + mMat[10] = 1.0f; + mMat[11] = 0.0f; + + 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 @@ void Matrix4::load(const Matrix4& v) { 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::loadScale(float sx, float sy, float sz) { } 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::loadMultiply(const Matrix4& u, const Matrix4& v) { 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 @@ public: 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 @@ public: } 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..e19795e 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::setViewport(int width, int height) { } 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 @@ void OpenGLRenderer::restoreToCount(int saveCount) { int OpenGLRenderer::saveSnapshot() { mSnapshot = new Snapshot(mSnapshot); - mSaveCount++; - return mSaveCount; + return ++mSaveCount; } bool OpenGLRenderer::restoreSnapshot() { @@ -106,14 +118,50 @@ bool OpenGLRenderer::restoreSnapshot() { 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 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom) 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 @@ public: sp<Snapshot> previous; }; // struct Snapshot +/////////////////////////////////////////////////////////////////////////////// +// Renderer +/////////////////////////////////////////////////////////////////////////////// + class OpenGLRenderer { public: OpenGLRenderer(); @@ -58,6 +74,14 @@ public: 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 @@ private: // Number of saved states int mSaveCount; + // Base state + Snapshot mFirstSnapshot; // Current state sp<Snapshot> mSnapshot; }; // class OpenGLRenderer |
