From 8aef54fa17f2a3753d9a8f2027629bc480088f69 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Wed, 1 Sep 2010 15:13:49 -0700 Subject: Add support for Canvas flags on save. This is required for the rewrite of layers support. Change-Id: I5c0867dcf5aeb0392c8d0fbab05febb0eaff70d9 --- core/java/android/view/GLES20Canvas.java | 2 +- libs/hwui/OpenGLRenderer.cpp | 77 +++++++++++++++------------ libs/hwui/OpenGLRenderer.h | 4 +- libs/hwui/Rect.h | 4 +- libs/hwui/SkiaShader.cpp | 4 +- libs/hwui/Snapshot.h | 91 +++++++++++++++++++++----------- 6 files changed, 110 insertions(+), 72 deletions(-) diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 65cb182..11a5d69 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -320,7 +320,7 @@ class GLES20Canvas extends Canvas { @Override public int save() { - return nSave(mRenderer, 0); + return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG); } @Override diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 02f5dc5..47ab355 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -127,7 +127,8 @@ void OpenGLRenderer::setViewport(int width, int height) { } void OpenGLRenderer::prepare() { - mSnapshot = new Snapshot(mFirstSnapshot); + mSnapshot = new Snapshot(mFirstSnapshot, + SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); mSaveCount = 1; glViewport(0, 0, mWidth, mHeight); @@ -175,7 +176,7 @@ int OpenGLRenderer::getSaveCount() const { } int OpenGLRenderer::save(int flags) { - return saveSnapshot(); + return saveSnapshot(flags); } void OpenGLRenderer::restore() { @@ -192,8 +193,8 @@ void OpenGLRenderer::restoreToCount(int saveCount) { } } -int OpenGLRenderer::saveSnapshot() { - mSnapshot = new Snapshot(mSnapshot); +int OpenGLRenderer::saveSnapshot(int flags) { + mSnapshot = new Snapshot(mSnapshot, flags); return mSaveCount++; } @@ -231,7 +232,7 @@ bool OpenGLRenderer::restoreSnapshot() { int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom, const SkPaint* p, int flags) { - int count = saveSnapshot(); + int count = saveSnapshot(flags); int alpha = 255; SkXfermode::Mode mode; @@ -258,13 +259,13 @@ int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom, int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int flags) { - int count = saveSnapshot(); - if (alpha > 0 && !mSnapshot->invisible) { - createLayer(mSnapshot, left, top, right, bottom, alpha, SkXfermode::kSrcOver_Mode, flags); + if (alpha == 0xff) { + return saveLayer(left, top, right, bottom, NULL, flags); } else { - mSnapshot->invisible = true; + SkPaint paint; + paint.setAlpha(alpha); + return saveLayer(left, top, right, bottom, &paint, flags); } - return count; } bool OpenGLRenderer::createLayer(sp snapshot, float left, float top, @@ -272,8 +273,12 @@ bool OpenGLRenderer::createLayer(sp snapshot, float left, float top, LAYER_LOGD("Requesting layer %fx%f", right - left, bottom - top); LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize()); + Rect bounds(left, top, right, bottom); + // TODO: Apply transformations and treat layers in screen coordinates + // mSnapshot->transform->mapRect(bounds); + GLuint previousFbo = snapshot->previous.get() ? snapshot->previous->fbo : 0; - LayerSize size(right - left, bottom - top); + LayerSize size(bounds.getWidth(), bounds.getHeight()); Layer* layer = mCaches.layerCache.get(size, previousFbo); if (!layer) { @@ -290,24 +295,26 @@ bool OpenGLRenderer::createLayer(sp snapshot, float left, float top, layer->mode = mode; layer->alpha = alpha / 255.0f; - layer->layer.set(left, top, right, bottom); + layer->layer.set(bounds); // Save the layer in the snapshot snapshot->flags |= Snapshot::kFlagIsLayer; snapshot->layer = layer; snapshot->fbo = layer->fbo; - snapshot->transform.loadTranslate(-left, -top, 0.0f); - snapshot->setClip(0.0f, 0.0f, right - left, bottom - top); - snapshot->viewport.set(0.0f, 0.0f, right - left, bottom - top); - snapshot->height = bottom - top; + // TODO: Temporary until real layer support is implemented + snapshot->resetTransform(-bounds.left, -bounds.top, 0.0f); + // TODO: Temporary until real layer support is implemented + snapshot->resetClip(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight()); + snapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight()); + snapshot->height = bounds.getHeight(); snapshot->flags |= Snapshot::kFlagDirtyOrtho; snapshot->orthoMatrix.load(mOrthoMatrix); setScissorFromClip(); // Change the ortho projection - glViewport(0, 0, right - left, bottom - top); - mOrthoMatrix.loadOrtho(0.0f, right - left, bottom - top, 0.0f, -1.0f, 1.0f); + glViewport(0, 0, bounds.getWidth(), bounds.getHeight()); + mOrthoMatrix.loadOrtho(0.0f, bounds.getWidth(), bounds.getHeight(), 0.0f, -1.0f, 1.0f); return true; } @@ -323,8 +330,8 @@ void OpenGLRenderer::composeLayer(sp current, sp previous) { glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo); // Restore the clip from the previous snapshot - const Rect& clip = previous->clipRect; - glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight()); + const Rect& clip = *previous->clipRect; + glScissor(clip.left, previous->height - clip.bottom, clip.getWidth(), clip.getHeight()); Layer* layer = current->layer; const Rect& rect = layer->layer; @@ -355,28 +362,28 @@ void OpenGLRenderer::composeLayer(sp current, sp previous) { /////////////////////////////////////////////////////////////////////////////// void OpenGLRenderer::translate(float dx, float dy) { - mSnapshot->transform.translate(dx, dy, 0.0f); + mSnapshot->transform->translate(dx, dy, 0.0f); } void OpenGLRenderer::rotate(float degrees) { - mSnapshot->transform.rotate(degrees, 0.0f, 0.0f, 1.0f); + mSnapshot->transform->rotate(degrees, 0.0f, 0.0f, 1.0f); } void OpenGLRenderer::scale(float sx, float sy) { - mSnapshot->transform.scale(sx, sy, 1.0f); + mSnapshot->transform->scale(sx, sy, 1.0f); } void OpenGLRenderer::setMatrix(SkMatrix* matrix) { - mSnapshot->transform.load(*matrix); + mSnapshot->transform->load(*matrix); } void OpenGLRenderer::getMatrix(SkMatrix* matrix) { - mSnapshot->transform.copyTo(*matrix); + mSnapshot->transform->copyTo(*matrix); } void OpenGLRenderer::concatMatrix(SkMatrix* matrix) { mat4 m(*matrix); - mSnapshot->transform.multiply(m); + mSnapshot->transform->multiply(m); } /////////////////////////////////////////////////////////////////////////////// @@ -384,7 +391,7 @@ void OpenGLRenderer::concatMatrix(SkMatrix* matrix) { /////////////////////////////////////////////////////////////////////////////// void OpenGLRenderer::setScissorFromClip() { - const Rect& clip = mSnapshot->clipRect; + const Rect& clip = *mSnapshot->clipRect; glScissor(clip.left, mSnapshot->height - clip.bottom, clip.getWidth(), clip.getHeight()); } @@ -396,8 +403,8 @@ bool OpenGLRenderer::quickReject(float left, float top, float right, float botto if (mSnapshot->invisible) return true; Rect r(left, top, right, bottom); - mSnapshot->transform.mapRect(r); - return !mSnapshot->clipRect.intersects(r); + mSnapshot->transform->mapRect(r); + return !mSnapshot->clipRect->intersects(r); } bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { @@ -405,7 +412,7 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, if (clipped) { setScissorFromClip(); } - return !mSnapshot->clipRect.isEmpty(); + return !mSnapshot->clipRect->isEmpty(); } /////////////////////////////////////////////////////////////////////////////// @@ -501,7 +508,7 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { if (mSnapshot->invisible) return; - const Rect& clip = mSnapshot->clipRect; + const Rect& clip = *mSnapshot->clipRect; drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true); } @@ -538,7 +545,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float scaleX = paint->getTextScaleX(); bool applyScaleX = scaleX < 0.9999f || scaleX > 1.0001f; if (applyScaleX) { - save(0); + save(SkCanvas::kMatrix_SaveFlag); translate(x - (x * scaleX), 0.0f); scale(scaleX, 1.0f); } @@ -747,7 +754,7 @@ void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t } else { mModelView.loadIdentity(); } - mCaches.currentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); + mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform); glUniform4f(mCaches.currentProgram->color, r, g, b, a); textureUnit++; @@ -852,7 +859,7 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot mModelView.loadTranslate(left, top, 0.0f); mModelView.scale(right - left, bottom - top, 1.0f); if (!ignoreTransform) { - mCaches.currentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); + mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform); } else { mat4 identity; mCaches.currentProgram->set(mOrthoMatrix, mModelView, identity); @@ -900,7 +907,7 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b mModelView.scale(right - left, bottom - top, 1.0f); useProgram(mCaches.programCache.get(description)); - mCaches.currentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); + mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform); chooseBlending(blend || alpha < 1.0f, mode); diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index d0e04b2..0e90d20 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -108,9 +108,11 @@ private: * The new snapshot is saved in mSnapshot and the previous snapshot * is linked from mSnapshot->previous. * + * @param flags The save flags; see SkCanvas for more information + * * @return The new save count. This value can be passed to #restoreToCount() */ - int saveSnapshot(); + int saveSnapshot(int flags); /** * Restores the current snapshot; mSnapshot becomes mSnapshot->previous. diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h index 7be0c34..6b22c2b 100644 --- a/libs/hwui/Rect.h +++ b/libs/hwui/Rect.h @@ -91,11 +91,11 @@ struct Rect { set(r.left, r.top, r.right, r.bottom); } - float getWidth() const { + inline float getWidth() const { return right - left; } - float getHeight() const { + inline float getHeight() const { return bottom - top; } diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index c7a01b1..a5e0f78 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -167,12 +167,12 @@ void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelV shaderMatrix.mapPoint(start.left, start.top); shaderMatrix.mapPoint(start.right, start.bottom); } - snapshot.transform.mapRect(start); + snapshot.transform->mapRect(start); const float gradientX = start.right - start.left; const float gradientY = start.bottom - start.top; - mat4 screenSpace(snapshot.transform); + mat4 screenSpace(*snapshot.transform); screenSpace.multiply(modelView); // Uniforms diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h index 97e7cae..da48243 100644 --- a/libs/hwui/Snapshot.h +++ b/libs/hwui/Snapshot.h @@ -22,6 +22,7 @@ #include +#include #include #include "Layer.h" @@ -42,27 +43,40 @@ namespace uirenderer { */ class Snapshot: public LightRefBase { public: - Snapshot(): invisible(false), flags(0), previous(NULL), layer(NULL), fbo(0) { } + Snapshot(): invisible(false), flags(0), previous(NULL), layer(NULL), fbo(0) { + transform = &mTransformRoot; + clipRect = &mClipRectRoot; + } /** - * 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. + * Copies the specified snapshot/ The specified snapshot is stored as + * the previous snapshot. */ - Snapshot(const sp& s): + Snapshot(const sp& s, int saveFlags): height(s->height), - transform(s->transform), - clipRect(s->clipRect), invisible(s->invisible), flags(0), previous(s), layer(NULL), fbo(s->fbo), viewport(s->viewport) { + if (saveFlags & SkCanvas::kMatrix_SaveFlag) { + mTransformRoot.load(*s->transform); + transform = &mTransformRoot; + } else { + transform = s->transform; + } + + if (saveFlags & SkCanvas::kClip_SaveFlag) { + mClipRectRoot.set(*s->clipRect); + clipRect = &mClipRectRoot; + } else { + clipRect = s->clipRect; + } + if ((s->flags & Snapshot::kFlagClipSet) && !(s->flags & Snapshot::kFlagDirtyLocalClip)) { - localClip.set(s->localClip); + mLocalClip.set(s->mLocalClip); } else { flags |= Snapshot::kFlagDirtyLocalClip; } @@ -99,23 +113,23 @@ public: bool clipped = false; Rect r(left, top, right, bottom); - transform.mapRect(r); + transform->mapRect(r); switch (op) { case SkRegion::kDifference_Op: break; case SkRegion::kIntersect_Op: - clipped = clipRect.intersect(r); + clipped = clipRect->intersect(r); break; case SkRegion::kUnion_Op: - clipped = clipRect.unionWith(r); + clipped = clipRect->unionWith(r); break; case SkRegion::kXOR_Op: break; case SkRegion::kReverseDifference_Op: break; case SkRegion::kReplace_Op: - clipRect.set(r); + clipRect->set(r); clipped = true; break; } @@ -131,39 +145,40 @@ public: * Sets the current clip. */ void setClip(float left, float top, float right, float bottom) { - clipRect.set(left, top, right, bottom); + clipRect->set(left, top, right, bottom); flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip; } const Rect& getLocalClip() { if (flags & Snapshot::kFlagDirtyLocalClip) { mat4 inverse; - inverse.loadInverse(transform); + inverse.loadInverse(*transform); - localClip.set(clipRect); - inverse.mapRect(localClip); + mLocalClip.set(*clipRect); + inverse.mapRect(mLocalClip); flags &= ~Snapshot::kFlagDirtyLocalClip; } - return localClip; + return mLocalClip; } - /** - * Height of the framebuffer the snapshot is rendering into. - */ - int height; + // TODO: Temporary + void resetTransform(float x, float y, float z) { + transform = &mTransformRoot; + transform->loadTranslate(x, y, z); + } - /** - * Local transformation. Holds the current translation, scale and - * rotation values. - */ - mat4 transform; + // TODO: Temporary + void resetClip(float left, float top, float right, float bottom) { + clipRect = &mClipRectRoot; + clipRect->set(left, top, right, bottom); + flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip; + } /** - * Current clip region. The clip is stored in canvas-space coordinates, - * (screen-space coordinates in the regular case.) + * Height of the framebuffer the snapshot is rendering into. */ - Rect clipRect; + int height; /** * If true, the layer won't be rendered. @@ -196,8 +211,22 @@ public: */ mat4 orthoMatrix; + /** + * Local transformation. Holds the current translation, scale and + * rotation values. + */ + mat4* transform; + + /** + * Current clip region. The clip is stored in canvas-space coordinates, + * (screen-space coordinates in the regular case.) + */ + Rect* clipRect; + private: - Rect localClip; + mat4 mTransformRoot; + Rect mClipRectRoot; + Rect mLocalClip; }; // class Snapshot -- cgit v1.1