diff options
Diffstat (limited to 'libs/hwui')
| -rw-r--r-- | libs/hwui/DisplayListOp.h | 4 | ||||
| -rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 4 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 8 | ||||
| -rw-r--r-- | libs/hwui/RenderNode.cpp | 15 | ||||
| -rw-r--r-- | libs/hwui/TessellationCache.cpp | 112 | ||||
| -rw-r--r-- | libs/hwui/TessellationCache.h | 40 | ||||
| -rw-r--r-- | libs/hwui/TreeInfo.h | 11 | ||||
| -rw-r--r-- | libs/hwui/thread/Task.h | 4 |
8 files changed, 107 insertions, 91 deletions
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 233f3f0..d578ef5 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -1118,8 +1118,8 @@ public: const DeferredDisplayState& state) { DrawStrokableOp::onDefer(renderer, deferInfo, state); if (!mPaint->getPathEffect()) { - renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, - mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy, mPaint); + renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, *mPaint, + mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy); } } diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 0e47c6e..fc4d40b 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -308,6 +308,10 @@ status_t DisplayListRenderer::drawOval(float left, float top, float right, float status_t DisplayListRenderer::drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) { + if (fabs(sweepAngle) > 360.0f) { + return drawOval(left, top, right, bottom, paint); + } + paint = refPaint(paint); addDrawOp(new (alloc()) DrawArcOp(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint)); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 8f3872a..6397478 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -2556,8 +2556,8 @@ status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float return drawShape(left, top, texture, p); } - const VertexBuffer* vertexBuffer = mCaches.tessellationCache.getRoundRect(*currentTransform(), - right - left, bottom - top, rx, ry, p); + const VertexBuffer* vertexBuffer = mCaches.tessellationCache.getRoundRect( + *currentTransform(), *p, right - left, bottom - top, rx, ry); return drawVertexBuffer(left, top, *vertexBuffer, p); } @@ -2611,10 +2611,6 @@ status_t OpenGLRenderer::drawArc(float left, float top, float right, float botto return DrawGlInfo::kStatusDone; } - if (fabs(sweepAngle) >= 360.0f) { - return drawOval(left, top, right, bottom, p); - } - // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180) if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != 0 || useCenter) { mCaches.activeTexture(0); diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 05f4edf..3d93383 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -20,6 +20,7 @@ #include "RenderNode.h" #include <algorithm> +#include <string> #include <SkCanvas.h> #include <algorithm> @@ -158,7 +159,10 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { applyLayerPropertiesToLayer(info); damageSelf(info); } else if (mLayer->layer.getWidth() != getWidth() || mLayer->layer.getHeight() != getHeight()) { - LayerRenderer::resizeLayer(mLayer, getWidth(), getHeight()); + if (!LayerRenderer::resizeLayer(mLayer, getWidth(), getHeight())) { + LayerRenderer::destroyLayer(mLayer); + mLayer = 0; + } damageSelf(info); } @@ -166,6 +170,15 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { info.damageAccumulator->peekAtDirty(&dirty); info.damageAccumulator->popTransform(); + if (!mLayer) { + if (info.errorHandler) { + std::string msg = "Unable to create layer for "; + msg += getName(); + info.errorHandler->onError(msg); + } + return; + } + if (!dirty.isEmpty()) { mLayer->updateDeferred(this, dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom); } diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp index ef3d0d7..08b54ff 100644 --- a/libs/hwui/TessellationCache.cpp +++ b/libs/hwui/TessellationCache.cpp @@ -39,6 +39,8 @@ namespace uirenderer { TessellationCache::Description::Description() : type(kNone) + , scaleX(1.0f) + , scaleY(1.0f) , aa(false) , cap(SkPaint::kDefault_Cap) , style(SkPaint::kFill_Style) @@ -46,21 +48,13 @@ TessellationCache::Description::Description() memset(&shape, 0, sizeof(Shape)); } -TessellationCache::Description::Description(Type type) +TessellationCache::Description::Description(Type type, const Matrix4& transform, const SkPaint& paint) : type(type) - , aa(false) - , cap(SkPaint::kDefault_Cap) - , style(SkPaint::kFill_Style) - , strokeWidth(1.0f) { - memset(&shape, 0, sizeof(Shape)); -} - -TessellationCache::Description::Description(Type type, const SkPaint* paint) - : type(type) - , aa(paint->isAntiAlias()) - , cap(paint->getStrokeCap()) - , style(paint->getStyle()) - , strokeWidth(paint->getStrokeWidth()) { + , aa(paint.isAntiAlias()) + , cap(paint.getStrokeCap()) + , style(paint.getStyle()) + , strokeWidth(paint.getStrokeWidth()) { + PathTessellator::extractTessellationScales(transform, &scaleX, &scaleY); memset(&shape, 0, sizeof(Shape)); } @@ -70,10 +64,20 @@ hash_t TessellationCache::Description::hash() const { hash = JenkinsHashMix(hash, cap); hash = JenkinsHashMix(hash, style); hash = JenkinsHashMix(hash, android::hash_type(strokeWidth)); + hash = JenkinsHashMix(hash, android::hash_type(scaleX)); + hash = JenkinsHashMix(hash, android::hash_type(scaleY)); hash = JenkinsHashMixBytes(hash, (uint8_t*) &shape, sizeof(Shape)); return JenkinsHashWhiten(hash); } +void TessellationCache::Description::setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const { + matrix->loadScale(scaleX, scaleY, 1.0f); + paint->setAntiAlias(aa); + paint->setStrokeCap(cap); + paint->setStyle(style); + paint->setStrokeWidth(strokeWidth); +} + TessellationCache::ShadowDescription::ShadowDescription() : nodeKey(NULL) { memset(&matrixData, 0, 16 * sizeof(float)); @@ -96,20 +100,15 @@ hash_t TessellationCache::ShadowDescription::hash() const { class TessellationCache::TessellationTask : public Task<VertexBuffer*> { public: - TessellationTask(Tessellator tessellator, const Description& description, - const SkPaint* paint) + TessellationTask(Tessellator tessellator, const Description& description) : tessellator(tessellator) - , description(description) - , paint(*paint) { + , description(description) { } ~TessellationTask() {} Tessellator tessellator; Description description; - - //copied, since input paint may not be immutable - const SkPaint paint; }; class TessellationCache::TessellationProcessor : public TaskProcessor<VertexBuffer*> { @@ -121,7 +120,7 @@ public: virtual void onProcess(const sp<Task<VertexBuffer*> >& task) { TessellationTask* t = static_cast<TessellationTask*>(task.get()); ATRACE_NAME("shape tessellation"); - VertexBuffer* buffer = t->tessellator(t->description, t->paint); + VertexBuffer* buffer = t->tessellator(t->description); t->setResult(buffer); } }; @@ -416,21 +415,12 @@ void TessellationCache::getShadowBuffers(const Matrix4* drawTransform, const Rec // Tessellation precaching /////////////////////////////////////////////////////////////////////////////// -static VertexBuffer* tessellatePath(const SkPath& path, const SkPaint* paint, - float scaleX, float scaleY) { - VertexBuffer* buffer = new VertexBuffer(); - Matrix4 matrix; - matrix.loadScale(scaleX, scaleY, 1); - PathTessellator::tessellatePath(path, paint, matrix, *buffer); - return buffer; -} - TessellationCache::Buffer* TessellationCache::getOrCreateBuffer( - const Description& entry, Tessellator tessellator, const SkPaint* paint) { + const Description& entry, Tessellator tessellator) { Buffer* buffer = mCache.get(entry); if (!buffer) { // not cached, enqueue a task to fill the buffer - sp<TessellationTask> task = new TessellationTask(tessellator, entry, paint); + sp<TessellationTask> task = new TessellationTask(tessellator, entry); buffer = new Buffer(task); if (mProcessor == NULL) { @@ -442,43 +432,49 @@ TessellationCache::Buffer* TessellationCache::getOrCreateBuffer( return buffer; } +static VertexBuffer* tessellatePath(const TessellationCache::Description& description, + const SkPath& path) { + Matrix4 matrix; + SkPaint paint; + description.setupMatrixAndPaint(&matrix, &paint); + VertexBuffer* buffer = new VertexBuffer(); + PathTessellator::tessellatePath(path, &paint, matrix, *buffer); + return buffer; +} + /////////////////////////////////////////////////////////////////////////////// -// Rounded rects +// RoundRect /////////////////////////////////////////////////////////////////////////////// -static VertexBuffer* tessellateRoundRect(const TessellationCache::Description& description, - const SkPaint& paint) { - SkRect rect = SkRect::MakeWH(description.shape.roundRect.mWidth, - description.shape.roundRect.mHeight); - float rx = description.shape.roundRect.mRx; - float ry = description.shape.roundRect.mRy; - if (paint.getStyle() == SkPaint::kStrokeAndFill_Style) { - float outset = paint.getStrokeWidth() / 2; +static VertexBuffer* tessellateRoundRect(const TessellationCache::Description& description) { + SkRect rect = SkRect::MakeWH(description.shape.roundRect.width, + description.shape.roundRect.height); + float rx = description.shape.roundRect.rx; + float ry = description.shape.roundRect.ry; + if (description.style == SkPaint::kStrokeAndFill_Style) { + float outset = description.strokeWidth / 2; rect.outset(outset, outset); rx += outset; ry += outset; } SkPath path; path.addRoundRect(rect, rx, ry); - return tessellatePath(path, &paint, - description.shape.roundRect.mScaleX, description.shape.roundRect.mScaleY); + return tessellatePath(description, path); } -TessellationCache::Buffer* TessellationCache::getRoundRectBuffer(const Matrix4& transform, - float width, float height, float rx, float ry, const SkPaint* paint) { - Description entry(Description::kRoundRect, paint); - entry.shape.roundRect.mWidth = width; - entry.shape.roundRect.mHeight = height; - entry.shape.roundRect.mRx = rx; - entry.shape.roundRect.mRy = ry; - PathTessellator::extractTessellationScales(transform, - &entry.shape.roundRect.mScaleX, &entry.shape.roundRect.mScaleY); - - return getOrCreateBuffer(entry, &tessellateRoundRect, paint); +TessellationCache::Buffer* TessellationCache::getRoundRectBuffer( + const Matrix4& transform, const SkPaint& paint, + float width, float height, float rx, float ry) { + Description entry(Description::kRoundRect, transform, paint); + entry.shape.roundRect.width = width; + entry.shape.roundRect.height = height; + entry.shape.roundRect.rx = rx; + entry.shape.roundRect.ry = ry; + return getOrCreateBuffer(entry, &tessellateRoundRect); } -const VertexBuffer* TessellationCache::getRoundRect(const Matrix4& transform, - float width, float height, float rx, float ry, const SkPaint* paint) { - return getRoundRectBuffer(transform, width, height, rx, ry, paint)->getVertexBuffer(); +const VertexBuffer* TessellationCache::getRoundRect(const Matrix4& transform, const SkPaint& paint, + float width, float height, float rx, float ry) { + return getRoundRectBuffer(transform, paint, width, height, rx, ry)->getVertexBuffer(); } }; // namespace uirenderer diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h index d4ff943..688a699 100644 --- a/libs/hwui/TessellationCache.h +++ b/libs/hwui/TessellationCache.h @@ -50,30 +50,28 @@ public: enum Type { kNone, kRoundRect, - kAmbientShadow, - kSpotShadow }; Type type; + float scaleX; + float scaleY; bool aa; SkPaint::Cap cap; SkPaint::Style style; float strokeWidth; union Shape { struct RoundRect { - float mScaleX; - float mScaleY; - float mWidth; - float mHeight; - float mRx; - float mRy; + float width; + float height; + float rx; + float ry; } roundRect; } shape; Description(); - Description(Type type); - Description(Type type, const SkPaint* paint); + Description(Type type, const Matrix4& transform, const SkPaint& paint); hash_t hash() const; + void setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const; }; struct ShadowDescription { @@ -123,12 +121,12 @@ public: // TODO: precache/get for Oval, Lines, Points, etc. - void precacheRoundRect(const Matrix4& transform, - float width, float height, float rx, float ry, const SkPaint* paint) { - getRoundRectBuffer(transform, width, height, rx, ry, paint); + void precacheRoundRect(const Matrix4& transform, const SkPaint& paint, + float width, float height, float rx, float ry) { + getRoundRectBuffer(transform, paint, width, height, rx, ry); } - const VertexBuffer* getRoundRect(const Matrix4& transform, - float width, float height, float rx, float ry, const SkPaint* paint); + const VertexBuffer* getRoundRect(const Matrix4& transform, const SkPaint& paint, + float width, float height, float rx, float ry); void precacheShadows(const Matrix4* drawTransform, const Rect& localClip, bool opaque, const SkPath* casterPerimeter, @@ -146,14 +144,14 @@ private: class TessellationTask; class TessellationProcessor; + typedef VertexBuffer* (*Tessellator)(const Description&); - typedef VertexBuffer* (*Tessellator)(const Description&, const SkPaint&); + Buffer* getRectBuffer(const Matrix4& transform, const SkPaint& paint, + float width, float height); + Buffer* getRoundRectBuffer(const Matrix4& transform, const SkPaint& paint, + float width, float height, float rx, float ry); - Buffer* getRoundRectBuffer(const Matrix4& transform, - float width, float height, float rx, float ry, const SkPaint* paint); - - Buffer* getOrCreateBuffer(const Description& entry, - Tessellator tessellator, const SkPaint* paint); + Buffer* getOrCreateBuffer(const Description& entry, Tessellator tessellator); uint32_t mSize; uint32_t mMaxSize; diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h index 0fc0cef..f67e434 100644 --- a/libs/hwui/TreeInfo.h +++ b/libs/hwui/TreeInfo.h @@ -16,6 +16,8 @@ #ifndef TREEINFO_H #define TREEINFO_H +#include <string> + #include <utils/Timers.h> #include "DamageAccumulator.h" @@ -35,6 +37,13 @@ protected: ~AnimationHook() {} }; +class ErrorHandler { +public: + virtual void onError(const std::string& message) = 0; +protected: + ~ErrorHandler() {} +}; + // This would be a struct, but we want to PREVENT_COPY_AND_ASSIGN class TreeInfo { PREVENT_COPY_AND_ASSIGN(TreeInfo); @@ -65,6 +74,7 @@ public: , prepareTextures(mode == MODE_FULL) , damageAccumulator(NullDamageAccumulator::instance()) , renderer(0) + , errorHandler(0) {} const TraversalMode mode; @@ -78,6 +88,7 @@ public: // The renderer that will be drawing the next frame. Use this to push any // layer updates or similar. May be NULL. OpenGLRenderer* renderer; + ErrorHandler* errorHandler; struct Out { Out() diff --git a/libs/hwui/thread/Task.h b/libs/hwui/thread/Task.h index 9a211a2..30b6ff2 100644 --- a/libs/hwui/thread/Task.h +++ b/libs/hwui/thread/Task.h @@ -17,8 +17,6 @@ #ifndef ANDROID_HWUI_TASK_H #define ANDROID_HWUI_TASK_H -#define ATRACE_TAG ATRACE_TAG_VIEW - #include <utils/RefBase.h> #include <utils/Trace.h> @@ -40,7 +38,7 @@ public: virtual ~Task() { } T getResult() const { - ATRACE_NAME("waitForTask"); + ScopedTrace tracer(ATRACE_TAG_VIEW, "waitForTask"); return mFuture->get(); } |
