diff options
| author | 2010-06-22 18:56:38 -0700 | |
|---|---|---|
| committer | 2010-06-23 12:36:03 -0700 | |
| commit | bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4 (patch) | |
| tree | b38978e88e8434e0a4bd8ac8e5c70bf2af26b3ea /libs | |
| 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
Diffstat (limited to 'libs')
| -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 |
4 files changed, 246 insertions, 5 deletions
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 |