summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/Android.common.mk6
-rw-r--r--libs/hwui/DisplayListCanvas.cpp21
-rw-r--r--libs/hwui/DisplayListCanvas.h2
-rw-r--r--libs/hwui/FrameInfo.h16
-rw-r--r--libs/hwui/FrameInfoVisualizer.cpp118
-rw-r--r--libs/hwui/FrameInfoVisualizer.h16
-rwxr-xr-xlibs/hwui/OpenGLRenderer.h16
-rw-r--r--libs/hwui/RenderNode.cpp21
-rw-r--r--libs/hwui/TextureCache.cpp10
-rw-r--r--libs/hwui/TextureCache.h5
-rw-r--r--libs/hwui/utils/RingBuffer.h4
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) {