diff options
author | 2010-06-22 18:56:38 -0700 | |
---|---|---|
committer | 2010-06-23 12:36:03 -0700 | |
commit | bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4 (patch) | |
tree | b38978e88e8434e0a4bd8ac8e5c70bf2af26b3ea | |
parent | 03f0292744094ec107ffce71301c394503a31ded (diff) |
Add implementations for clipRect(), save() and restore().
The current implementation of clipRect() does not apply local transformations
before setting the new clip.
Change-Id: I5997871bb638dfcd1a8ef96354846af52427e445
-rw-r--r-- | core/java/android/view/GLES20Canvas.java | 45 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 60 | ||||
-rw-r--r-- | libs/hwui/Matrix.cpp | 10 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 70 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 46 | ||||
-rw-r--r-- | libs/hwui/Rect.h | 125 |
6 files changed, 324 insertions, 32 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index d8fa850a17f8..fbfea95f6a72 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -137,9 +137,10 @@ class GLES20Canvas extends Canvas { @Override public boolean clipRect(float left, float top, float right, float bottom) { - // TODO: Implement - return false; + return nClipRect(mRenderer, left, top, right, bottom); } + + private native boolean nClipRect(int renderer, float left, float top, float right, float bottom); @Override public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) { @@ -148,14 +149,14 @@ class GLES20Canvas extends Canvas { @Override public boolean clipRect(int left, int top, int right, int bottom) { - // TODO: Implement - return false; + return nClipRect(mRenderer, left, top, right, bottom); } + + private native boolean nClipRect(int renderer, int left, int top, int right, int bottom); @Override public boolean clipRect(Rect rect) { - // TODO: Implement - return false; + return clipRect(rect.left, rect.top, rect.right, rect.bottom); } @Override @@ -165,8 +166,7 @@ class GLES20Canvas extends Canvas { @Override public boolean clipRect(RectF rect) { - // TODO: Implement - return false; + return clipRect(rect.left, rect.top, rect.right, rect.bottom); } @Override @@ -198,14 +198,12 @@ class GLES20Canvas extends Canvas { @Override public boolean quickReject(Path path, EdgeType type) { - // TODO: Implement - return false; + throw new UnsupportedOperationException(); } @Override public boolean quickReject(RectF rect, EdgeType type) { - // TODO: Implement - return false; + return quickReject(rect.left, rect.top, rect.right, rect.bottom, type); } /////////////////////////////////////////////////////////////////////////// @@ -254,16 +252,16 @@ class GLES20Canvas extends Canvas { @Override public int save() { - // TODO: Implement - return 0; + return nSave(mRenderer, 0); } - + @Override public int save(int saveFlags) { - // TODO: Implement - return 0; + return nSave(mRenderer, saveFlags); } + private native int nSave(int renderer, int flags); + @Override public int saveLayer(RectF bounds, Paint paint, int saveFlags) { // TODO: Implement @@ -292,19 +290,24 @@ class GLES20Canvas extends Canvas { @Override public void restore() { - // TODO: Implement + nRestore(mRenderer); } + + private native void nRestore(int renderer); @Override public void restoreToCount(int saveCount) { - // TODO: Implement + nRestoreToCount(mRenderer, saveCount); } + private native void nRestoreToCount(int renderer, int saveCount); + @Override public int getSaveCount() { - // TODO: Implement - return 0; + return nGetSaveCount(mRenderer); } + + private native int nGetSaveCount(int renderer); /////////////////////////////////////////////////////////////////////////// // Filtering diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 57660836093e..8c2a04cb2706 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -54,7 +54,47 @@ static void android_view_GLES20Renderer_prepare(JNIEnv* env, jobject canvas, jin } // ---------------------------------------------------------------------------- -// Draw color +// State +// ---------------------------------------------------------------------------- + +static jint android_view_GLES20Renderer_save(JNIEnv* env, jobject canvas, jint renderer, + jint flags) { + + return UI->save(flags); +} + +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, jint renderer) { + UI->restore(); +} + +static void android_view_GLES20Renderer_restoreToCount(JNIEnv* env, jobject canvas, jint renderer, + jint saveCount) { + + UI->restoreToCount(saveCount); +} + +// ---------------------------------------------------------------------------- +// Clipping +// ---------------------------------------------------------------------------- + +static bool android_view_GLES20Renderer_clipRectF(JNIEnv* env, jobject canvas, jint renderer, + jfloat left, jfloat top, jfloat right, jfloat bottom) { + + return UI->clipRect(left, top, right, bottom); +} + +static bool android_view_GLES20Renderer_clipRect(JNIEnv* env, jobject canvas, jint renderer, + jint left, jint top, jint right, jint bottom) { + + return UI->clipRect(float(left), float(top), float(right), float(bottom)); +} + +// ---------------------------------------------------------------------------- +// Drawing // ---------------------------------------------------------------------------- static void android_view_GLES20Renderer_drawColor(JNIEnv* env, jobject canvas, jint renderer, @@ -70,12 +110,20 @@ static void android_view_GLES20Renderer_drawColor(JNIEnv* env, jobject canvas, j const char* const kClassPathName = "android/view/GLES20Canvas"; static JNINativeMethod gMethods[] = { - { "nCreateRenderer", "()I", (void*) android_view_GLES20Renderer_createRenderer }, - { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Renderer_destroyRenderer }, - { "nSetViewport", "(III)V", (void*) android_view_GLES20Renderer_setViewport }, - { "nPrepare", "(I)V", (void*) android_view_GLES20Renderer_prepare }, + { "nCreateRenderer", "()I", (void*) android_view_GLES20Renderer_createRenderer }, + { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Renderer_destroyRenderer }, + { "nSetViewport", "(III)V", (void*) android_view_GLES20Renderer_setViewport }, + { "nPrepare", "(I)V", (void*) android_view_GLES20Renderer_prepare }, + + { "nSave", "(II)I", (void*) android_view_GLES20Renderer_save }, + { "nRestore", "(I)V", (void*) android_view_GLES20Renderer_restore }, + { "nRestoreToCount", "(II)V", (void*) android_view_GLES20Renderer_restoreToCount }, + { "nGetSaveCount", "(I)I", (void*) android_view_GLES20Renderer_getSaveCount }, + + { "nClipRect", "(IFFFF)Z", (void*) android_view_GLES20Renderer_clipRectF }, + { "nClipRect", "(IIIII)Z", (void*) android_view_GLES20Renderer_clipRect }, - { "nDrawColor", "(III)V", (void*) android_view_GLES20Renderer_drawColor }, + { "nDrawColor", "(III)V", (void*) android_view_GLES20Renderer_drawColor }, }; int register_android_view_GLES20Canvas(JNIEnv* env) { diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp index 68b245b7e822..638c1b8fe8ac 100644 --- a/libs/hwui/Matrix.cpp +++ b/libs/hwui/Matrix.cpp @@ -140,10 +140,12 @@ void Matrix4::loadOrtho(float left, float right, float bottom, float top, float } void Matrix4::dump() const { - LOGD("%f %f %f %f", mMat[0], mMat[4], mMat[ 8], mMat[12]); - LOGD("%f %f %f %f", mMat[1], mMat[5], mMat[ 9], mMat[13]); - LOGD("%f %f %f %f", mMat[2], mMat[6], mMat[10], mMat[14]); - LOGD("%f %f %f %f", mMat[3], mMat[7], mMat[11], mMat[15]); + LOGD("Matrix4["); + LOGD(" %f %f %f %f", mMat[0], mMat[4], mMat[ 8], mMat[12]); + LOGD(" %f %f %f %f", mMat[1], mMat[5], mMat[ 9], mMat[13]); + LOGD(" %f %f %f %f", mMat[2], mMat[6], mMat[10], mMat[14]); + LOGD(" %f %f %f %f", mMat[3], mMat[7], mMat[11], mMat[15]); + LOGD("]"); } }; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 35825d2467d7..1416ce15d7f4 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -35,6 +35,9 @@ namespace android { OpenGLRenderer::OpenGLRenderer() { LOGD("Create OpenGLRenderer"); + + mSnapshot = new Snapshot; + mSaveCount = 0; } OpenGLRenderer::~OpenGLRenderer() { @@ -47,13 +50,80 @@ void OpenGLRenderer::setViewport(int width, int height) { mat4 ortho; ortho.loadOrtho(0, width, height, 0, 0, 1); ortho.copyTo(mOrthoMatrix); + + mWidth = width; + mHeight = height; } void OpenGLRenderer::prepare() { 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); +} + +int OpenGLRenderer::getSaveCount() const { + return mSaveCount; +} + +int OpenGLRenderer::save(int flags) { + return saveSnapshot(); +} + +void OpenGLRenderer::restore() { + if (mSaveCount == 0) return; + + if (restoreSnapshot()) { + setScissorFromClip(); + } +} + +void OpenGLRenderer::restoreToCount(int saveCount) { + if (saveCount <= 0 || saveCount > mSaveCount) return; + + bool restoreClip = false; + + while (mSaveCount != saveCount - 1) { + restoreClip |= restoreSnapshot(); + } + + if (restoreClip) { + setScissorFromClip(); + } +} + +int OpenGLRenderer::saveSnapshot() { + mSnapshot = new Snapshot(mSnapshot); + mSaveCount++; + return mSaveCount; +} + +bool OpenGLRenderer::restoreSnapshot() { + // TODO: handle local transformations + bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet; + + mSaveCount--; + mSnapshot = mSnapshot->previous; + + return restoreClip; +} + +void OpenGLRenderer::setScissorFromClip() { + Rect clip = mSnapshot->clipRect; + glScissor(clip.left, clip.top, clip.getWidth(), clip.getHeight()); +} + +bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom) { + // TODO: take local translate transform into account + bool clipped = mSnapshot->clipRect.intersect(left, top, right, bottom); + if (clipped) { + mSnapshot->flags |= Snapshot::kFlagClipSet; + setScissorFromClip(); + } + return clipped; } void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 12363360b65f..8a541fcf3a81 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -19,8 +19,32 @@ #include <SkXfermode.h> +#include <utils/RefBase.h> + +#include "Rect.h" + namespace android { +class Snapshot: public LightRefBase<Snapshot> { +public: + Snapshot() { } + + Snapshot(const sp<Snapshot> s): clipRect(s->clipRect), flags(0), previous(s) { } + + enum Flags { + kFlagClipSet = 0x1, + }; + + // Clipping rectangle at the time of this snapshot + Rect clipRect; + + // Dirty flags + int flags; + + // Previous snapshot in the frames stack + sp<Snapshot> previous; +}; // struct Snapshot + class OpenGLRenderer { public: OpenGLRenderer(); @@ -29,12 +53,32 @@ public: void setViewport(int width, int height); void prepare(); + int getSaveCount() const; + int save(int flags); + void restore(); + void restoreToCount(int saveCount); + + bool clipRect(float left, float top, float right, float bottom); + void drawColor(int color, SkXfermode::Mode mode); private: + int saveSnapshot(); + bool restoreSnapshot(); + + void setScissorFromClip(); + + // Dimensions of the drawing surface + int mWidth, mHeight; + // Matrix used for ortho projection in shaders float mOrthoMatrix[16]; -}; + + // Number of saved states + int mSaveCount; + // Current state + sp<Snapshot> mSnapshot; +}; // class OpenGLRenderer }; // namespace android diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h new file mode 100644 index 000000000000..724bd1a2b742 --- /dev/null +++ b/libs/hwui/Rect.h @@ -0,0 +1,125 @@ +/* + * 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_RECT_H +#define ANDROID_RECT_H + +namespace android { + +/////////////////////////////////////////////////////////////////////////////// +// Structs +/////////////////////////////////////////////////////////////////////////////// + +struct Rect { + float left; + float top; + float right; + float bottom; + + Rect(): left(0), top(0), right(0), bottom(0) { } + + Rect(const Rect& r) { + set(r); + } + + Rect(Rect& r) { + set(r); + } + + Rect& operator=(const Rect& r) { + set(r); + return *this; + } + + Rect& operator=(Rect& r) { + set(r); + return *this; + } + + friend int operator==(const Rect& a, const Rect& b) { + return !memcmp(&a, &b, sizeof(a)); + } + + friend int operator!=(const Rect& a, const Rect& b) { + return memcmp(&a, &b, sizeof(a)); + } + + bool isEmpty() const { + return left >= right || top >= bottom; + } + + void setEmpty() { + memset(this, 0, sizeof(*this)); + } + + void set(float left, float top, float right, float bottom) { + this->left = left; + this->right = right; + this->top = top; + this->bottom = bottom; + } + + void set(const Rect& r) { + set(r.left, r.top, r.right, r.bottom); + } + + float getWidth() const { + return right - left; + } + + float getHeight() const { + return bottom - top; + } + + bool intersects(float left, float top, float right, float bottom) const { + return left < right && top < bottom && + this->left < this->right && this->top < this->bottom && + this->left < right && left < this->right && + this->top < bottom && top < this->bottom; + } + + bool intersects(const Rect& r) const { + return intersects(r.left, r.top, r.right, r.bottom); + } + + bool intersect(float left, float top, float right, float bottom) { + if (left < right && top < bottom && !this->isEmpty() && + this->left < right && left < this->right && + this->top < bottom && top < this->bottom) { + + if (this->left < left) this->left = left; + if (this->top < top) this->top = top; + if (this->right > right) this->right = right; + if (this->bottom > bottom) this->bottom = bottom; + + return true; + } + return false; + } + + bool intersect(const Rect& r) { + return intersect(r.left, r.top, r.right, r.bottom); + } + + void dump() const { + LOGD("Rect[l=%f t=%f r=%f b=%f]", left, top, right, bottom); + } + +}; // struct Rect + +}; // namespace android + +#endif // ANDROID_RECT_H |