From db8c9a6a4d9bf8c39f834b25611926caf21380f6 Mon Sep 17 00:00:00 2001 From: Chet Haase Date: Wed, 21 Mar 2012 18:54:18 -0700 Subject: Optimization of alpha with DisplayList properties Some views (such as ImageView and TextView) handle non-opaque alpha values directly. This was originally an optimization, but we can handle it faster in many cases without this optimization when DisplayList properties are enabled. Basically, if a view has non-overlapping rendering, we set the alpha value directly on the renderer (the equivalent of setting it on the Paint object) and draw each primitive with that alpha value. Doing it this way avoids re-creating DisplayLists while getting the same speedup that onSetAlpha() used to get pre-DisplayList properties. Change-Id: I0f7827f075d3b35093a882d4adbb300a1063c288 --- libs/hwui/DisplayListRenderer.cpp | 28 +++++++++++++++++----------- libs/hwui/DisplayListRenderer.h | 5 +++++ libs/hwui/OpenGLRenderer.cpp | 2 ++ libs/hwui/OpenGLRenderer.h | 4 ++++ libs/hwui/Snapshot.cpp | 4 ++-- libs/hwui/Snapshot.h | 11 +++++++++++ 6 files changed, 41 insertions(+), 13 deletions(-) (limited to 'libs') diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index f37bfd2f9c12..9f2bacdef24d 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -112,6 +112,7 @@ void DisplayList::initProperties() { mClipChildren = true; mAlpha = 1; mMultipliedAlpha = 255; + mHasOverlappingRendering = true; mTranslationX = 0; mTranslationY = 0; mRotation = 0; @@ -772,18 +773,23 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t width, ui } } if (mAlpha < 1 && !mCaching) { - // TODO: should be able to store the size of a DL at record time and not - // have to pass it into this call. In fact, this information might be in the - // location/size info that we store with the new native transform data. - int flags = SkCanvas::kHasAlphaLayer_SaveFlag; - if (mClipChildren) { - flags |= SkCanvas::kClipToLayer_SaveFlag; + if (!mHasOverlappingRendering) { + DISPLAY_LIST_LOGD("%s%s %.2f", indent, "SetAlpha", mAlpha); + renderer.setAlpha(mAlpha); + } else { + // TODO: should be able to store the size of a DL at record time and not + // have to pass it into this call. In fact, this information might be in the + // location/size info that we store with the new native transform data. + int flags = SkCanvas::kHasAlphaLayer_SaveFlag; + if (mClipChildren) { + flags |= SkCanvas::kClipToLayer_SaveFlag; + } + DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha", + (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, + mMultipliedAlpha, flags); + renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop, + mMultipliedAlpha, flags); } - DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha", - (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, - mMultipliedAlpha, flags); - renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop, - mMultipliedAlpha, flags); } if (mClipChildren) { DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f, diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 38b0a6d6f173..fe0c94d9a2e3 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -181,6 +181,10 @@ public: } } + void setHasOverlappingRendering(bool hasOverlappingRendering) { + mHasOverlappingRendering = hasOverlappingRendering; + } + void setTranslationX(float translationX) { if (translationX != mTranslationX) { mTranslationX = translationX; @@ -496,6 +500,7 @@ private: bool mClipChildren; float mAlpha; int mMultipliedAlpha; + bool mHasOverlappingRendering; float mTranslationX, mTranslationY; float mRotation, mRotationX, mRotationY; float mScaleX, mScaleY; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 115787c87ebc..ec9b56b4ca2d 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1101,6 +1101,7 @@ void OpenGLRenderer::setupDrawColor(int color) { void OpenGLRenderer::setupDrawColor(int color, int alpha) { mColorA = alpha / 255.0f; + mColorA *= mSnapshot->alpha; // Second divide of a by 255 is an optimization, allowing us to simply multiply // the rgb values by a instead of also dividing by 255 const float a = mColorA / 255.0f; @@ -2800,6 +2801,7 @@ void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mod *mode = SkXfermode::kSrcOver_Mode; *alpha = 255; } + *alpha *= mSnapshot->alpha; } SkXfermode::Mode OpenGLRenderer::getXfermode(SkXfermode* mode) { diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index b6519047eead..ab137ccec98f 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -85,6 +85,10 @@ public: virtual int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int flags); + virtual void setAlpha(float alpha) { + mSnapshot->alpha = alpha; + } + virtual void translate(float dx, float dy); virtual void rotate(float degrees); virtual void scale(float sx, float sy); diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp index de2c6745cc97..5d5961a14004 100644 --- a/libs/hwui/Snapshot.cpp +++ b/libs/hwui/Snapshot.cpp @@ -26,7 +26,7 @@ namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0), - invisible(false), empty(false) { + invisible(false), empty(false), alpha(1.0f) { transform = &mTransformRoot; clipRect = &mClipRectRoot; @@ -41,7 +41,7 @@ Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0), Snapshot::Snapshot(const sp& s, int saveFlags): flags(0), previous(s), layer(NULL), fbo(s->fbo), invisible(s->invisible), empty(false), - viewport(s->viewport), height(s->height) { + viewport(s->viewport), height(s->height), alpha(s->alpha) { clipRegion = NULL; diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h index b2bc879760e4..30b03fc33db6 100644 --- a/libs/hwui/Snapshot.h +++ b/libs/hwui/Snapshot.h @@ -208,6 +208,17 @@ public: */ Region* region; + /** + * Current alpha value. This value is 1 by default, but may be set by a DisplayList which + * has translucent rendering in a non-overlapping View. This value will be used by + * the renderer to set the alpha in the current color being used for ensuing drawing + * operations. The value is inherited by child snapshots because the same value should + * be applied to descendents of the current DisplayList (for example, a TextView contains + * the base alpha value which should be applied to the child DisplayLists used for drawing + * the actual text). + */ + float alpha; + private: void ensureClipRegion(); void copyClipRectFromRegion(); -- cgit v1.2.3-59-g8ed1b