diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/hwui/Android.common.mk | 6 | ||||
| -rw-r--r-- | libs/hwui/DisplayListCanvas.cpp | 21 | ||||
| -rw-r--r-- | libs/hwui/DisplayListCanvas.h | 2 | ||||
| -rw-r--r-- | libs/hwui/FrameInfo.h | 16 | ||||
| -rw-r--r-- | libs/hwui/FrameInfoVisualizer.cpp | 118 | ||||
| -rw-r--r-- | libs/hwui/FrameInfoVisualizer.h | 16 | ||||
| -rwxr-xr-x | libs/hwui/OpenGLRenderer.h | 16 | ||||
| -rw-r--r-- | libs/hwui/RenderNode.cpp | 21 | ||||
| -rw-r--r-- | libs/hwui/TextureCache.cpp | 10 | ||||
| -rw-r--r-- | libs/hwui/TextureCache.h | 5 | ||||
| -rw-r--r-- | libs/hwui/utils/RingBuffer.h | 4 |
11 files changed, 137 insertions, 98 deletions
diff --git a/libs/hwui/Android.common.mk b/libs/hwui/Android.common.mk index a5bfde736334..95905956fb78 100644 --- a/libs/hwui/Android.common.mk +++ b/libs/hwui/Android.common.mk @@ -118,5 +118,9 @@ endif # Defaults for ATRACE_TAG and LOG_TAG for libhwui LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_VIEW -DLOG_TAG=\"OpenGLRenderer\" +LOCAL_CFLAGS += -Wall -Wno-unused-parameter -Wunreachable-code -LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter -Wunreachable-code +# b/21698669 +ifneq ($(USE_CLANG_PLATFORM_BUILD),true) + LOCAL_CFLAGS += -Werror +endif diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp index cbb6fd5ef286..900a6214a22b 100644 --- a/libs/hwui/DisplayListCanvas.cpp +++ b/libs/hwui/DisplayListCanvas.cpp @@ -352,6 +352,7 @@ void DisplayListCanvas::drawRoundRect( mDisplayListData->ref(rx); mDisplayListData->ref(ry); mDisplayListData->ref(paint); + refBitmapsInShader(paint->value.getShader()); addDrawOp(new (alloc()) DrawRoundRectPropsOp(&left->value, &top->value, &right->value, &bottom->value, &rx->value, &ry->value, &paint->value)); } @@ -366,6 +367,7 @@ void DisplayListCanvas::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPri mDisplayListData->ref(y); mDisplayListData->ref(radius); mDisplayListData->ref(paint); + refBitmapsInShader(paint->value.getShader()); addDrawOp(new (alloc()) DrawCirclePropsOp(&x->value, &y->value, &radius->value, &paint->value)); } @@ -565,5 +567,24 @@ size_t DisplayListCanvas::addRenderNodeOp(DrawRenderNodeOp* op) { return opIndex; } +void DisplayListCanvas::refBitmapsInShader(const SkShader* shader) { + if (!shader) return; + + // If this paint has an SkShader that has an SkBitmap add + // it to the bitmap pile + SkBitmap bitmap; + SkShader::TileMode xy[2]; + if (shader->asABitmap(&bitmap, nullptr, xy) == SkShader::kDefault_BitmapType) { + refBitmap(bitmap); + return; + } + SkShader::ComposeRec rec; + if (shader->asACompose(&rec)) { + refBitmapsInShader(rec.fShaderA); + refBitmapsInShader(rec.fShaderB); + return; + } +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h index d997ef464863..edfda620ffae 100644 --- a/libs/hwui/DisplayListCanvas.h +++ b/libs/hwui/DisplayListCanvas.h @@ -263,6 +263,7 @@ private: size_t addDrawOp(DrawOp* op); size_t addRenderNodeOp(DrawRenderNodeOp* op); + void refBitmapsInShader(const SkShader* shader); template<class T> inline const T* refBuffer(const T* srcBuffer, int32_t count) { @@ -311,6 +312,7 @@ private: // replaceValueFor() performs an add if the entry doesn't exist mPaintMap.replaceValueFor(key, cachedPaint); + refBitmapsInShader(cachedPaint->getShader()); } return cachedPaint; diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h index 681525416959..23339cec1741 100644 --- a/libs/hwui/FrameInfo.h +++ b/libs/hwui/FrameInfo.h @@ -116,16 +116,28 @@ public: set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag); } - int64_t operator[](FrameInfoIndex index) const { + inline int64_t operator[](FrameInfoIndex index) const { if (index == FrameInfoIndex::NumIndexes) return 0; return mFrameInfo[static_cast<int>(index)]; } - int64_t operator[](int index) const { + inline int64_t operator[](int index) const { if (index < 0 || index >= static_cast<int>(FrameInfoIndex::NumIndexes)) return 0; return mFrameInfo[index]; } + inline int64_t duration(FrameInfoIndex start, FrameInfoIndex end) const { + int64_t endtime = mFrameInfo[static_cast<int>(end)]; + int64_t starttime = mFrameInfo[static_cast<int>(start)]; + int64_t gap = endtime - starttime; + gap = starttime > 0 ? gap : 0; + return gap > 0 ? gap : 0; + } + + inline int64_t totalDuration() const { + return duration(FrameInfoIndex::IntendedVsync, FrameInfoIndex::FrameCompleted); + } + private: inline int64_t& set(FrameInfoIndex index) { return mFrameInfo[static_cast<int>(index)]; diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp index 9557cb09a4c6..7f9d9b9da7b6 100644 --- a/libs/hwui/FrameInfoVisualizer.cpp +++ b/libs/hwui/FrameInfoVisualizer.cpp @@ -28,13 +28,14 @@ #define PROFILE_DRAW_DP_PER_MS 7 // Must be NUM_ELEMENTS in size -static const SkColor CURRENT_FRAME_COLOR = 0xcf5faa4d; static const SkColor THRESHOLD_COLOR = 0xff5faa4d; -static const SkColor BAR_ALPHA = 0xCF000000; +static const SkColor BAR_FAST_ALPHA = 0x8F000000; +static const SkColor BAR_JANKY_ALPHA = 0xDF000000; // We could get this from TimeLord and use the actual frame interval, but // this is good enough #define FRAME_THRESHOLD 16 +#define FRAME_THRESHOLD_NS 16000000 namespace android { namespace uirenderer { @@ -45,12 +46,10 @@ struct BarSegment { SkColor color; }; -static const std::array<BarSegment,9> Bar {{ - { FrameInfoIndex::IntendedVsync, FrameInfoIndex::Vsync, 0x00695C }, - { FrameInfoIndex::Vsync, FrameInfoIndex::HandleInputStart, 0x00796B }, - { FrameInfoIndex::HandleInputStart, FrameInfoIndex::AnimationStart, 0x00897B }, - { FrameInfoIndex::AnimationStart, FrameInfoIndex::PerformTraversalsStart, 0x009688 }, - { FrameInfoIndex::PerformTraversalsStart, FrameInfoIndex::DrawStart, 0x26A69A}, +static const std::array<BarSegment,7> Bar {{ + { FrameInfoIndex::IntendedVsync, FrameInfoIndex::HandleInputStart, 0x00796B }, + { FrameInfoIndex::HandleInputStart, FrameInfoIndex::PerformTraversalsStart, 0x388E3C }, + { FrameInfoIndex::PerformTraversalsStart, FrameInfoIndex::DrawStart, 0x689F38}, { FrameInfoIndex::DrawStart, FrameInfoIndex::SyncStart, 0x2196F3}, { FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart, 0x4FC3F7}, { FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::SwapBuffers, 0xF44336}, @@ -74,7 +73,6 @@ void FrameInfoVisualizer::setDensity(float density) { if (CC_UNLIKELY(mDensity != density)) { mDensity = density; mVerticalUnit = dpToPx(PROFILE_DRAW_DP_PER_MS, density); - mHorizontalUnit = dpToPx(PROFILE_DRAW_WIDTH, density); mThresholdStroke = dpToPx(PROFILE_DRAW_THRESHOLD_STROKE_WIDTH, density); } } @@ -103,73 +101,109 @@ void FrameInfoVisualizer::draw(OpenGLRenderer* canvas) { } if (mType == ProfileType::Bars) { - initializeRects(canvas->getViewportHeight()); + // Patch up the current frame to pretend we ended here. CanvasContext + // will overwrite these values with the real ones after we return. + // This is a bit nicer looking than the vague green bar, as we have + // valid data for almost all the stages and a very good idea of what + // the issue stage will look like, too + FrameInfo& info = mFrameSource.back(); + info.markSwapBuffers(); + info.markFrameCompleted(); + + initializeRects(canvas->getViewportHeight(), canvas->getViewportWidth()); drawGraph(canvas); - drawCurrentFrame(canvas->getViewportHeight(), canvas); drawThreshold(canvas); } } void FrameInfoVisualizer::createData() { - if (mRects.get()) return; + if (mFastRects.get()) return; - mRects.reset(new float[mFrameSource.capacity() * 4]); + mFastRects.reset(new float[mFrameSource.capacity() * 4]); + mJankyRects.reset(new float[mFrameSource.capacity() * 4]); } void FrameInfoVisualizer::destroyData() { - mRects.reset(nullptr); + mFastRects.reset(nullptr); + mJankyRects.reset(nullptr); } -void FrameInfoVisualizer::initializeRects(const int baseline) { - float left = 0; +void FrameInfoVisualizer::initializeRects(const int baseline, const int width) { + // Target the 95% mark for the current frame + float right = width * .95; + float baseLineWidth = right / mFrameSource.capacity(); + mNumFastRects = 0; + mNumJankyRects = 0; + int fast_i = 0, janky_i = 0; // Set the bottom of all the shapes to the baseline - for (size_t i = 0; i < (mFrameSource.capacity() * 4); i += 4) { + for (int fi = mFrameSource.size() - 1; fi >= 0; fi--) { + if (mFrameSource[fi][FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame) { + continue; + } + float lineWidth = baseLineWidth; + float* rect; + int ri; // Rects are LTRB - mRects[i + 0] = left; - mRects[i + 1] = baseline; - left += mHorizontalUnit; - mRects[i + 2] = left; - mRects[i + 3] = baseline; + if (mFrameSource[fi].totalDuration() <= FRAME_THRESHOLD_NS) { + rect = mFastRects.get(); + ri = fast_i; + fast_i += 4; + mNumFastRects++; + } else { + rect = mJankyRects.get(); + ri = janky_i; + janky_i += 4; + mNumJankyRects++; + lineWidth *= 2; + } + + rect[ri + 0] = right - lineWidth; + rect[ri + 1] = baseline; + rect[ri + 2] = right; + rect[ri + 3] = baseline; + right -= lineWidth; } } void FrameInfoVisualizer::nextBarSegment(FrameInfoIndex start, FrameInfoIndex end) { - for (size_t fi = 0, ri = 0; fi < mFrameSource.size(); fi++, ri += 4) { - // TODO: Skipped frames will leave little holes in the graph, but this - // is better than bogus and freaky lines, so... + int fast_i = (mNumFastRects - 1) * 4; + int janky_i = (mNumJankyRects - 1) * 4;; + for (size_t fi = 0; fi < mFrameSource.size(); fi++) { if (mFrameSource[fi][FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame) { continue; } + float* rect; + int ri; + // Rects are LTRB + if (mFrameSource[fi].totalDuration() <= FRAME_THRESHOLD_NS) { + rect = mFastRects.get(); + ri = fast_i; + fast_i -= 4; + } else { + rect = mJankyRects.get(); + ri = janky_i; + janky_i -= 4; + } + // Set the bottom to the old top (build upwards) - mRects[ri + 3] = mRects[ri + 1]; + rect[ri + 3] = rect[ri + 1]; // Move the top up by the duration - mRects[ri + 1] -= mVerticalUnit * duration(fi, start, end); + rect[ri + 1] -= mVerticalUnit * duration(fi, start, end); } } void FrameInfoVisualizer::drawGraph(OpenGLRenderer* canvas) { SkPaint paint; for (size_t i = 0; i < Bar.size(); i++) { - paint.setColor(Bar[i].color | BAR_ALPHA); nextBarSegment(Bar[i].start, Bar[i].end); - canvas->drawRects(mRects.get(), (mFrameSource.size() - 1) * 4, &paint); + paint.setColor(Bar[i].color | BAR_FAST_ALPHA); + canvas->drawRects(mFastRects.get(), mNumFastRects * 4, &paint); + paint.setColor(Bar[i].color | BAR_JANKY_ALPHA); + canvas->drawRects(mJankyRects.get(), mNumJankyRects * 4, &paint); } } -void FrameInfoVisualizer::drawCurrentFrame(const int baseline, OpenGLRenderer* canvas) { - // This draws a solid rect over the entirety of the current frame's shape - // To do so we use the bottom of mRects[0] and the top of mRects[NUM_ELEMENTS-1] - // which will therefore fully overlap the previously drawn rects - SkPaint paint; - paint.setColor(CURRENT_FRAME_COLOR); - size_t fi = mFrameSource.size() - 1; - size_t ri = fi * 4; - float top = baseline - (mVerticalUnit * duration(fi, - FrameInfoIndex::IntendedVsync, FrameInfoIndex::IssueDrawCommandsStart)); - canvas->drawRect(mRects[ri], top, mRects[ri + 2], baseline, &paint); -} - void FrameInfoVisualizer::drawThreshold(OpenGLRenderer* canvas) { SkPaint paint; paint.setColor(THRESHOLD_COLOR); diff --git a/libs/hwui/FrameInfoVisualizer.h b/libs/hwui/FrameInfoVisualizer.h index 3fa458659124..f1dc95419868 100644 --- a/libs/hwui/FrameInfoVisualizer.h +++ b/libs/hwui/FrameInfoVisualizer.h @@ -54,10 +54,9 @@ private: void createData(); void destroyData(); - void initializeRects(const int baseline); + void initializeRects(const int baseline, const int width); void nextBarSegment(FrameInfoIndex start, FrameInfoIndex end); void drawGraph(OpenGLRenderer* canvas); - void drawCurrentFrame(const int baseline, OpenGLRenderer* canvas); void drawThreshold(OpenGLRenderer* canvas); inline float duration(size_t index, FrameInfoIndex start, FrameInfoIndex end) { @@ -75,17 +74,12 @@ private: FrameInfoSource& mFrameSource; int mVerticalUnit = 0; - int mHorizontalUnit = 0; int mThresholdStroke = 0; - /* - * mRects represents an array of rect shapes, divided into NUM_ELEMENTS - * groups such that each group is drawn with the same paint. - * For example mRects[0] is the array of rect floats suitable for - * OpenGLRenderer:drawRects() that makes up all the FrameTimingData:record - * information. - */ - std::unique_ptr<float[]> mRects; + int mNumFastRects; + std::unique_ptr<float[]> mFastRects; + int mNumJankyRects; + std::unique_ptr<float[]> mJankyRects; bool mShowDirtyRegions = false; SkRect mDirtyRegion; diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 29fbf0c985d7..5850dc671889 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -524,22 +524,6 @@ protected: inline float getLayerAlpha(const Layer* layer) const; /** - * Safely retrieves the ColorFilter from the given Paint. If the paint is - * null then null is returned. - */ - static inline SkColorFilter* getColorFilter(const SkPaint* paint) { - return paint ? paint->getColorFilter() : nullptr; - } - - /** - * Safely retrieves the Shader from the given Paint. If the paint is - * null then null is returned. - */ - static inline const SkShader* getShader(const SkPaint* paint) { - return paint ? paint->getShader() : nullptr; - } - - /** * Set to true to suppress error checks at the end of a frame. */ virtual bool suppressErrorChecks() const { diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 7d3b41e009a6..4ac43625db07 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -83,11 +83,12 @@ void RenderNode::setStagingDisplayList(DisplayListData* data) { * display list. This function should remain in sync with the replay() function. */ void RenderNode::output(uint32_t level) { - ALOGD("%*sStart display list (%p, %s%s%s%s%s)", (level - 1) * 2, "", this, + ALOGD("%*sStart display list (%p, %s%s%s%s%s%s)", (level - 1) * 2, "", this, getName(), (MathUtils::isZero(properties().getAlpha()) ? ", zero alpha" : ""), (properties().hasShadow() ? ", casting shadow" : ""), (isRenderable() ? "" : ", empty"), + (properties().getProjectBackwards() ? ", projected" : ""), (mLayer != nullptr ? ", on HW Layer" : "")); ALOGD("%*s%s %d", level * 2, "", "Save", SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); @@ -520,10 +521,10 @@ void RenderNode::computeOrderingImpl( Vector<DrawRenderNodeOp*>* projectionChildren = nullptr; const mat4* projectionTransform = nullptr; if (isProjectionReceiver && !child->properties().getProjectBackwards()) { - // if receiving projections, collect projecting descendent + // if receiving projections, collect projecting descendant - // Note that if a direct descendent is projecting backwards, we pass it's - // grandparent projection collection, since it shouldn't project onto it's + // Note that if a direct descendant is projecting backwards, we pass its + // grandparent projection collection, since it shouldn't project onto its // parent, where it will already be drawing. projectionOutline = properties().getOutline().getPath(); projectionChildren = &mProjectedNodes; @@ -802,7 +803,8 @@ void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& template <class T> void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { if (mDisplayListData->isEmpty()) { - DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, getName()); + DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", handler.level() * 2, "", + this, getName()); return; } @@ -814,7 +816,8 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { if (useViewProperties) { const Outline& outline = properties().getOutline(); if (properties().getAlpha() <= 0 || (outline.getShouldClip() && outline.isEmpty())) { - DISPLAY_LIST_LOGD("%*sRejected display list (%p, %s)", level * 2, "", this, getName()); + DISPLAY_LIST_LOGD("%*sRejected display list (%p, %s)", handler.level() * 2, "", + this, getName()); return; } } @@ -833,7 +836,7 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { handler(new (alloc) SaveOp(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag), PROPERTY_SAVECOUNT, properties().getClipToBounds()); - DISPLAY_LIST_LOGD("%*sSave %d %d", (level + 1) * 2, "", + DISPLAY_LIST_LOGD("%*sSave %d %d", (handler.level() + 1) * 2, "", SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo); if (useViewProperties) { @@ -880,11 +883,11 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { } } - DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo); + DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (handler.level() + 1) * 2, "", restoreTo); handler(new (alloc) RestoreToCountOp(restoreTo), PROPERTY_SAVECOUNT, properties().getClipToBounds()); - DISPLAY_LIST_LOGD("%*sDone (%p, %s)", level * 2, "", this, getName()); + DISPLAY_LIST_LOGD("%*sDone (%p, %s)", handler.level() * 2, "", this, getName()); handler.endMark(); } diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index e59688c708ef..5147e987253b 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -215,16 +215,6 @@ Texture* TextureCache::get(const SkBitmap* bitmap) { return texture; } -Texture* TextureCache::getTransient(const SkBitmap* bitmap) { - Texture* texture = new Texture(Caches::getInstance()); - texture->bitmapSize = bitmap->rowBytes() * bitmap->height(); - texture->cleanup = true; - - generateTexture(bitmap, texture, false); - - return texture; -} - void TextureCache::releaseTexture(uint32_t pixelRefStableID) { Mutex::Autolock _l(mLock); mGarbage.push(pixelRefStableID); diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h index a2c6380cacc2..e7fc990a6588 100644 --- a/libs/hwui/TextureCache.h +++ b/libs/hwui/TextureCache.h @@ -80,11 +80,6 @@ public: * cannot be found in the cache, a new texture is generated. */ Texture* get(const SkBitmap* bitmap); - /** - * Returns the texture associated with the specified bitmap. The generated - * texture is not kept in the cache. The caller must destroy the texture. - */ - Texture* getTransient(const SkBitmap* bitmap); /** * Removes the texture associated with the specified pixelRef. This is meant diff --git a/libs/hwui/utils/RingBuffer.h b/libs/hwui/utils/RingBuffer.h index d822cb2fe0b5..6895f07fd60a 100644 --- a/libs/hwui/utils/RingBuffer.h +++ b/libs/hwui/utils/RingBuffer.h @@ -43,11 +43,11 @@ public: } T& front() { - return this[0]; + return (*this)[0]; } T& back() { - return this[size() - 1]; + return (*this)[size() - 1]; } T& operator[](size_t index) { |