diff options
author | 2016-01-15 16:15:30 -0800 | |
---|---|---|
committer | 2016-02-02 17:10:25 -0800 | |
commit | 6e068c0182f6f85bccb855a647510724d1c65a13 (patch) | |
tree | 8ee074307867bfcdc9c8a708aa6ae03f1d9b7ecc | |
parent | d38308e4d0599836f9c5446ba9d6edbc0713c428 (diff) |
Early kickoff of shadow tasks
bug:26562703
Change-Id: I7cdf18f2c662380bd31c7ffeefd5c3f569e5c1c6
-rw-r--r-- | libs/hwui/BakedOpDispatcher.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/BakedOpRenderer.h | 8 | ||||
-rw-r--r-- | libs/hwui/BakedOpState.cpp | 15 | ||||
-rw-r--r-- | libs/hwui/FrameBuilder.cpp | 47 | ||||
-rw-r--r-- | libs/hwui/FrameBuilder.h | 22 | ||||
-rw-r--r-- | libs/hwui/RecordedOp.h | 21 | ||||
-rw-r--r-- | libs/hwui/TessellationCache.cpp | 64 | ||||
-rw-r--r-- | libs/hwui/TessellationCache.h | 43 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 10 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.h | 3 | ||||
-rw-r--r-- | libs/hwui/tests/microbench/FrameBuilderBench.cpp | 17 | ||||
-rw-r--r-- | libs/hwui/tests/unit/FrameBuilderTests.cpp | 81 | ||||
-rw-r--r-- | libs/hwui/tests/unit/LeakCheckTests.cpp | 8 |
13 files changed, 187 insertions, 160 deletions
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp index 7ecc743b700c..ca1f8f94f382 100644 --- a/libs/hwui/BakedOpDispatcher.cpp +++ b/libs/hwui/BakedOpDispatcher.cpp @@ -663,13 +663,7 @@ static void renderShadow(BakedOpRenderer& renderer, const BakedOpState& state, f } void BakedOpDispatcher::onShadowOp(BakedOpRenderer& renderer, const ShadowOp& op, const BakedOpState& state) { - TessellationCache::vertexBuffer_pair_t buffers; - renderer.caches().tessellationCache.getShadowBuffers(&state.computedState.transform, - op.localClipRect, op.casterAlpha >= 1.0f, op.casterPath, - &op.shadowMatrixXY, &op.shadowMatrixZ, - op.lightCenter, renderer.getLightInfo().lightRadius, - buffers); - + TessellationCache::vertexBuffer_pair_t buffers = *(op.shadowTask->getResult()); renderShadow(renderer, state, op.casterAlpha, buffers.first, buffers.second); } diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h index 10c469875150..55ea93531bc7 100644 --- a/libs/hwui/BakedOpRenderer.h +++ b/libs/hwui/BakedOpRenderer.h @@ -45,13 +45,11 @@ public: * Position agnostic shadow lighting info. Used with all shadow ops in scene. */ struct LightInfo { - LightInfo() : LightInfo(0, 0, 0) {} - LightInfo(float lightRadius, uint8_t ambientShadowAlpha, + LightInfo() : LightInfo(0, 0) {} + LightInfo(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) - : lightRadius(lightRadius) - , ambientShadowAlpha(ambientShadowAlpha) + : ambientShadowAlpha(ambientShadowAlpha) , spotShadowAlpha(spotShadowAlpha) {} - float lightRadius; uint8_t ambientShadowAlpha; uint8_t spotShadowAlpha; }; diff --git a/libs/hwui/BakedOpState.cpp b/libs/hwui/BakedOpState.cpp index 87844f9840d7..a542c26b41b8 100644 --- a/libs/hwui/BakedOpState.cpp +++ b/libs/hwui/BakedOpState.cpp @@ -63,16 +63,11 @@ ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& s } } -ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot) { - transform = *snapshot.transform; - - // Since the op doesn't have known bounds, we conservatively set the mapped bounds - // to the current clipRect, and clipSideFlags to Full. - clipState = snapshot.mutateClipArea().serializeClip(allocator); - LOG_ALWAYS_FATAL_IF(!clipState, "clipState required"); - clippedBounds = clipState->rect; - clipSideFlags = OpClipSideFlags::Full; -} +ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot) + : transform(*snapshot.transform) + , clipState(snapshot.mutateClipArea().serializeClip(allocator)) + , clippedBounds(clipState->rect) + , clipSideFlags(OpClipSideFlags::Full) {} ResolvedRenderState::ResolvedRenderState(const ClipRect* viewportRect, const Rect& dstRect) : transform(Matrix4::identity()) diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp index a45721249542..9528587ed860 100644 --- a/libs/hwui/FrameBuilder.cpp +++ b/libs/hwui/FrameBuilder.cpp @@ -32,17 +32,11 @@ namespace uirenderer { FrameBuilder::FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip, uint32_t viewportWidth, uint32_t viewportHeight, - const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter) - : FrameBuilder(layers, clip, viewportWidth, viewportHeight, nodes, lightCenter, - Rect(0, 0, 0, 0)) { -} - - -FrameBuilder::FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip, - uint32_t viewportWidth, uint32_t viewportHeight, - const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter, - const Rect &contentDrawBounds) - : mCanvasState(*this) { + const std::vector< sp<RenderNode> >& nodes, + const LightGeometry& lightGeometry, const Rect &contentDrawBounds, Caches* caches) + : mCanvasState(*this) + , mCaches(caches) + , mLightRadius(lightGeometry.radius) { ATRACE_NAME("prepare drawing commands"); mLayerBuilders.reserve(layers.entries().size()); @@ -54,7 +48,7 @@ FrameBuilder::FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip, mLayerStack.push_back(0); mCanvasState.initializeSaveStack(viewportWidth, viewportHeight, clip.fLeft, clip.fTop, clip.fRight, clip.fBottom, - lightCenter); + lightGeometry.center); // Render all layers to be updated, in order. Defer in reverse order, so that they'll be // updated in the order they're passed in (mLayerBuilders are issued to Renderer in reverse) @@ -366,13 +360,28 @@ void FrameBuilder::deferShadow(const RenderNodeOp& casterNodeOp) { casterPath = frameAllocatedPath; } - ShadowOp* shadowOp = new (mAllocator) ShadowOp(casterNodeOp, casterAlpha, casterPath, - mCanvasState.getLocalClipBounds(), - mCanvasState.currentSnapshot()->getRelativeLightCenter()); - BakedOpState* bakedOpState = BakedOpState::tryShadowOpConstruct( - mAllocator, *mCanvasState.writableSnapshot(), shadowOp); - if (CC_LIKELY(bakedOpState)) { - currentLayer().deferUnmergeableOp(mAllocator, bakedOpState, OpBatchType::Shadow); + + if (CC_LIKELY(!mCanvasState.getRenderTargetClipBounds().isEmpty())) { + Matrix4 shadowMatrixXY(casterNodeOp.localMatrix); + Matrix4 shadowMatrixZ(casterNodeOp.localMatrix); + node.applyViewPropertyTransforms(shadowMatrixXY, false); + node.applyViewPropertyTransforms(shadowMatrixZ, true); + + LOG_ALWAYS_FATAL_IF(!mCaches, "Caches needed for shadows"); + sp<TessellationCache::ShadowTask> task = mCaches->tessellationCache.getShadowTask( + mCanvasState.currentTransform(), + mCanvasState.getLocalClipBounds(), + casterAlpha >= 1.0f, + casterPath, + &shadowMatrixXY, &shadowMatrixZ, + mCanvasState.currentSnapshot()->getRelativeLightCenter(), + mLightRadius); + ShadowOp* shadowOp = mAllocator.create<ShadowOp>(task, casterAlpha); + BakedOpState* bakedOpState = BakedOpState::tryShadowOpConstruct( + mAllocator, *mCanvasState.writableSnapshot(), shadowOp); + if (CC_LIKELY(bakedOpState)) { + currentLayer().deferUnmergeableOp(mAllocator, bakedOpState, OpBatchType::Shadow); + } } } diff --git a/libs/hwui/FrameBuilder.h b/libs/hwui/FrameBuilder.h index dea9934e9a1b..5df2e46078b8 100644 --- a/libs/hwui/FrameBuilder.h +++ b/libs/hwui/FrameBuilder.h @@ -55,14 +55,24 @@ class Rect; */ class FrameBuilder : public CanvasStateClient { public: + struct LightGeometry { + Vector3 center; + float radius; + }; + + // TODO: remove FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip, uint32_t viewportWidth, uint32_t viewportHeight, - const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter); + const std::vector< sp<RenderNode> >& nodes, + const LightGeometry& lightGeometry, + Caches* caches) + : FrameBuilder(layers, clip, viewportWidth, viewportHeight, nodes, lightGeometry, Rect(), caches) {} FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip, uint32_t viewportWidth, uint32_t viewportHeight, - const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter, - const Rect &contentDrawBounds); + const std::vector< sp<RenderNode> >& nodes, + const LightGeometry& lightGeometry, + const Rect &contentDrawBounds, Caches* caches); virtual ~FrameBuilder() {} @@ -215,7 +225,11 @@ private: CanvasState mCanvasState; - // contains ResolvedOps and Batches + Caches* mCaches = nullptr; + + float mLightRadius; + + // contains single-frame objects, such as BakedOpStates, LayerBuilders, Batches LinearAllocator mAllocator; }; diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h index 30d5c293c4bb..593d690f2b43 100644 --- a/libs/hwui/RecordedOp.h +++ b/libs/hwui/RecordedOp.h @@ -21,6 +21,7 @@ #include "Matrix.h" #include "Rect.h" #include "RenderNode.h" +#include "TessellationCache.h" #include "utils/LinearAllocator.h" #include "Vector.h" @@ -333,25 +334,13 @@ struct RoundRectPropsOp : RecordedOp { * State construction handles these properties specially, ignoring matrix/bounds. */ struct ShadowOp : RecordedOp { - ShadowOp(const RenderNodeOp& casterOp, float casterAlpha, const SkPath* casterPath, - const Rect& localClipRect, const Vector3& lightCenter) + ShadowOp(sp<TessellationCache::ShadowTask>& shadowTask, float casterAlpha) : RecordedOp(RecordedOpId::ShadowOp, Rect(), Matrix4::identity(), nullptr, nullptr) - , shadowMatrixXY(casterOp.localMatrix) - , shadowMatrixZ(casterOp.localMatrix) - , casterAlpha(casterAlpha) - , casterPath(casterPath) - , localClipRect(localClipRect) - , lightCenter(lightCenter) { - const RenderNode& node = *casterOp.renderNode; - node.applyViewPropertyTransforms(shadowMatrixXY, false); - node.applyViewPropertyTransforms(shadowMatrixZ, true); + , shadowTask(shadowTask) + , casterAlpha(casterAlpha) { }; - Matrix4 shadowMatrixXY; - Matrix4 shadowMatrixZ; + sp<TessellationCache::ShadowTask> shadowTask; const float casterAlpha; - const SkPath* casterPath; - const Rect localClipRect; - const Vector3 lightCenter; }; struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?) diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp index 0835c29aee97..461e8190c974 100644 --- a/libs/hwui/TessellationCache.cpp +++ b/libs/hwui/TessellationCache.cpp @@ -160,45 +160,6 @@ private: // Shadow tessellation task processing /////////////////////////////////////////////////////////////////////////////// -class ShadowTask : public Task<TessellationCache::vertexBuffer_pair_t*> { -public: - ShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque, - const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ, - const Vector3& lightCenter, float lightRadius) - : drawTransform(*drawTransform) - , localClip(localClip) - , opaque(opaque) - , casterPerimeter(*casterPerimeter) - , transformXY(*transformXY) - , transformZ(*transformZ) - , lightCenter(lightCenter) - , lightRadius(lightRadius) { - } - - ~ShadowTask() { - TessellationCache::vertexBuffer_pair_t* bufferPair = getResult(); - delete bufferPair->getFirst(); - delete bufferPair->getSecond(); - delete bufferPair; - } - - /* Note - we deep copy all task parameters, because *even though* pointers into Allocator - * controlled objects (like the SkPath and Matrix4s) should be safe for the entire frame, - * certain Allocators are destroyed before trim() is called to flush incomplete tasks. - * - * These deep copies could be avoided, long term, by cancelling or flushing outstanding tasks - * before tearning down single-frame LinearAllocators. - */ - const Matrix4 drawTransform; - const Rect localClip; - bool opaque; - const SkPath casterPerimeter; - const Matrix4 transformXY; - const Matrix4 transformZ; - const Vector3 lightCenter; - const float lightRadius; -}; - static void mapPointFakeZ(Vector3& point, const mat4* transformXY, const mat4* transformZ) { // map z coordinate with true 3d matrix point.z = transformZ->mapZ(point); @@ -288,7 +249,7 @@ public: ~ShadowProcessor() {} virtual void onProcess(const sp<Task<TessellationCache::vertexBuffer_pair_t*> >& task) override { - ShadowTask* t = static_cast<ShadowTask*>(task.get()); + TessellationCache::ShadowTask* t = static_cast<TessellationCache::ShadowTask*>(task.get()); ATRACE_NAME("shadow tessellation"); VertexBuffer* ambientBuffer = new VertexBuffer; @@ -415,6 +376,29 @@ void TessellationCache::getShadowBuffers(const Matrix4* drawTransform, const Rec outBuffers = *(task->getResult()); } +sp<TessellationCache::ShadowTask> TessellationCache::getShadowTask( + const Matrix4* drawTransform, const Rect& localClip, + bool opaque, const SkPath* casterPerimeter, + const Matrix4* transformXY, const Matrix4* transformZ, + const Vector3& lightCenter, float lightRadius) { + ShadowDescription key(casterPerimeter, drawTransform); + ShadowTask* task = static_cast<ShadowTask*>(mShadowCache.get(key)); + if (!task) { + precacheShadows(drawTransform, localClip, opaque, casterPerimeter, + transformXY, transformZ, lightCenter, lightRadius); + task = static_cast<ShadowTask*>(mShadowCache.get(key)); + } + LOG_ALWAYS_FATAL_IF(task == nullptr, "shadow not precached"); + return task; +} + +TessellationCache::ShadowTask::~ShadowTask() { + TessellationCache::vertexBuffer_pair_t* bufferPair = getResult(); + delete bufferPair->getFirst(); + delete bufferPair->getSecond(); + delete bufferPair; +} + /////////////////////////////////////////////////////////////////////////////// // Tessellation precaching /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h index 06e567e114e2..977c2d9e9f8a 100644 --- a/libs/hwui/TessellationCache.h +++ b/libs/hwui/TessellationCache.h @@ -26,6 +26,7 @@ #include "utils/Pair.h" #include <SkPaint.h> +#include <SkPath.h> #include <utils/LruCache.h> #include <utils/Mutex.h> @@ -33,7 +34,6 @@ class SkBitmap; class SkCanvas; -class SkPath; struct SkRect; namespace android { @@ -89,6 +89,40 @@ public: hash_t hash() const; }; + class ShadowTask : public Task<TessellationCache::vertexBuffer_pair_t*> { + public: + ShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque, + const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ, + const Vector3& lightCenter, float lightRadius) + : drawTransform(*drawTransform) + , localClip(localClip) + , opaque(opaque) + , casterPerimeter(*casterPerimeter) + , transformXY(*transformXY) + , transformZ(*transformZ) + , lightCenter(lightCenter) + , lightRadius(lightRadius) { + } + + ~ShadowTask(); + + /* Note - we deep copy all task parameters, because *even though* pointers into Allocator + * controlled objects (like the SkPath and Matrix4s) should be safe for the entire frame, + * certain Allocators are destroyed before trim() is called to flush incomplete tasks. + * + * These deep copies could be avoided, long term, by cancelling or flushing outstanding + * tasks before tearing down single-frame LinearAllocators. + */ + const Matrix4 drawTransform; + const Rect localClip; + bool opaque; + const SkPath casterPerimeter; + const Matrix4 transformXY; + const Matrix4 transformZ; + const Vector3 lightCenter; + const float lightRadius; + }; + TessellationCache(); ~TessellationCache(); @@ -133,17 +167,22 @@ public: const VertexBuffer* getRoundRect(const Matrix4& transform, const SkPaint& paint, float width, float height, float rx, float ry); + // TODO: delete these when switching to HWUI_NEW_OPS void precacheShadows(const Matrix4* drawTransform, const Rect& localClip, bool opaque, const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ, const Vector3& lightCenter, float lightRadius); - void getShadowBuffers(const Matrix4* drawTransform, const Rect& localClip, bool opaque, const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ, const Vector3& lightCenter, float lightRadius, vertexBuffer_pair_t& outBuffers); + sp<ShadowTask> getShadowTask(const Matrix4* drawTransform, const Rect& localClip, + bool opaque, const SkPath* casterPerimeter, + const Matrix4* transformXY, const Matrix4* transformZ, + const Vector3& lightCenter, float lightRadius); + private: class Buffer; class TessellationTask; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index e7cf3ecd2b72..d4116218e5e1 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -33,10 +33,6 @@ #include "utils/GLUtils.h" #include "utils/TimeUtils.h" -#if HWUI_NEW_OPS -#include "FrameBuilder.h" -#endif - #include <cutils/properties.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <private/hwui/DrawGlInfo.h> @@ -152,7 +148,7 @@ bool CanvasContext::pauseSurface(ANativeWindow* window) { void CanvasContext::setup(int width, int height, float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { #if HWUI_NEW_OPS - mLightInfo.lightRadius = lightRadius; + mLightGeometry.radius = lightRadius; mLightInfo.ambientShadowAlpha = ambientShadowAlpha; mLightInfo.spotShadowAlpha = spotShadowAlpha; #else @@ -163,7 +159,7 @@ void CanvasContext::setup(int width, int height, float lightRadius, void CanvasContext::setLightCenter(const Vector3& lightCenter) { #if HWUI_NEW_OPS - mLightCenter = lightCenter; + mLightGeometry.center = lightCenter; #else if (!mCanvas) return; mCanvas->setLightCenter(lightCenter); @@ -345,7 +341,7 @@ void CanvasContext::draw() { #if HWUI_NEW_OPS FrameBuilder frameBuilder(mLayerUpdateQueue, dirty, frame.width(), frame.height(), - mRenderNodes, mLightCenter, mContentDrawBounds); + mRenderNodes, mLightGeometry, mContentDrawBounds, &Caches::getInstance()); mLayerUpdateQueue.clear(); BakedOpRenderer renderer(Caches::getInstance(), mRenderThread.renderState(), mOpaque, mLightInfo); diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 270fb1fead83..63a7977f0cc9 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -31,6 +31,7 @@ #if HWUI_NEW_OPS #include "BakedOpDispatcher.h" #include "BakedOpRenderer.h" +#include "FrameBuilder.h" #endif #include <cutils/compiler.h> @@ -197,7 +198,7 @@ private: OpenGLRenderer* mCanvas = nullptr; #if HWUI_NEW_OPS BakedOpRenderer::LightInfo mLightInfo; - Vector3 mLightCenter = { 0, 0, 0 }; + FrameBuilder::LightGeometry mLightGeometry = { {0, 0, 0}, 0 }; #endif bool mHaveNewSurface = false; diff --git a/libs/hwui/tests/microbench/FrameBuilderBench.cpp b/libs/hwui/tests/microbench/FrameBuilderBench.cpp index f9c2b671fdf3..7845eb4fa8e2 100644 --- a/libs/hwui/tests/microbench/FrameBuilderBench.cpp +++ b/libs/hwui/tests/microbench/FrameBuilderBench.cpp @@ -37,7 +37,8 @@ using namespace android::uirenderer::renderthread; using namespace android::uirenderer::test; const LayerUpdateQueue sEmptyLayerUpdateQueue; -const Vector3 sLightCenter = {100, 100, 100}; +const FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50}; +const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 }; static std::vector<sp<RenderNode>> createTestNodeList() { auto node = TestUtils::createNode(0, 0, 200, 200, @@ -67,7 +68,7 @@ void BM_FrameBuilder_defer::Run(int iters) { StartBenchmarkTiming(); for (int i = 0; i < iters; i++) { FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200, - nodes, sLightCenter); + nodes, sLightGeometry, nullptr); MicroBench::DoNotOptimize(&frameBuilder); } StopBenchmarkTiming(); @@ -77,7 +78,6 @@ BENCHMARK_NO_ARG(BM_FrameBuilder_deferAndRender); void BM_FrameBuilder_deferAndRender::Run(int iters) { TestUtils::runOnRenderThread([this, iters](RenderThread& thread) { auto nodes = createTestNodeList(); - BakedOpRenderer::LightInfo lightInfo = {50.0f, 128, 128 }; RenderState& renderState = thread.renderState(); Caches& caches = Caches::getInstance(); @@ -85,9 +85,9 @@ void BM_FrameBuilder_deferAndRender::Run(int iters) { StartBenchmarkTiming(); for (int i = 0; i < iters; i++) { FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200, - nodes, sLightCenter); + nodes, sLightGeometry, nullptr); - BakedOpRenderer renderer(caches, renderState, true, lightInfo); + BakedOpRenderer renderer(caches, renderState, true, sLightInfo); frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer); MicroBench::DoNotOptimize(&renderer); } @@ -119,7 +119,7 @@ static void benchDeferScene(testing::Benchmark& benchmark, int iters, const char for (int i = 0; i < iters; i++) { FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, gDisplay.h, - nodes, sLightCenter); + nodes, sLightGeometry, nullptr); MicroBench::DoNotOptimize(&frameBuilder); } benchmark.StopBenchmarkTiming(); @@ -129,7 +129,6 @@ static void benchDeferAndRenderScene(testing::Benchmark& benchmark, int iters, const char* sceneName) { TestUtils::runOnRenderThread([&benchmark, iters, sceneName](RenderThread& thread) { auto nodes = getSyncedSceneNodes(sceneName); - BakedOpRenderer::LightInfo lightInfo = {50.0f, 128, 128 }; // TODO! RenderState& renderState = thread.renderState(); Caches& caches = Caches::getInstance(); @@ -138,9 +137,9 @@ static void benchDeferAndRenderScene(testing::Benchmark& benchmark, for (int i = 0; i < iters; i++) { FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, gDisplay.h, - nodes, sLightCenter); + nodes, sLightGeometry, nullptr); - BakedOpRenderer renderer(caches, renderState, true, lightInfo); + BakedOpRenderer renderer(caches, renderState, true, sLightInfo); frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer); MicroBench::DoNotOptimize(&renderer); } diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp index 618df140deda..f49dd3f6bc81 100644 --- a/libs/hwui/tests/unit/FrameBuilderTests.cpp +++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp @@ -30,7 +30,8 @@ namespace android { namespace uirenderer { const LayerUpdateQueue sEmptyLayerUpdateQueue; -const Vector3 sLightCenter = {100, 100, 100}; +const FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50}; + /** * Virtual class implemented by each test to redirect static operation / state transitions to @@ -132,7 +133,7 @@ TEST(FrameBuilder, simple) { canvas.drawBitmap(bitmap, 10, 10, nullptr); }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); SimpleTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(4, renderer.getIndex()); // 2 ops + start + end @@ -158,7 +159,7 @@ TEST(FrameBuilder, simpleStroke) { canvas.drawPoint(50, 50, strokedPaint); }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); SimpleStrokeTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(1, renderer.getIndex()); @@ -173,7 +174,7 @@ TEST(FrameBuilder, simpleRejection) { canvas.restore(); }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); FailRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); @@ -208,7 +209,7 @@ TEST(FrameBuilder, simpleBatching) { }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); SimpleBatchingTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(2 * LOOPS, renderer.getIndex()) @@ -250,7 +251,7 @@ TEST(FrameBuilder, DISABLED_clippedMerging) { }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); ClippedMergingTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(4, renderer.getIndex()); @@ -278,7 +279,7 @@ TEST(FrameBuilder, textMerging) { TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); TextMergingTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(2, renderer.getIndex()) << "Expect 2 ops"; @@ -309,7 +310,7 @@ TEST(FrameBuilder, textStrikethrough) { } }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 2000), 200, 2000, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); TextStrikethroughTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(2 * LOOPS, renderer.getIndex()) @@ -343,7 +344,7 @@ RENDERTHREAD_TEST(FrameBuilder, textureLayer) { canvas.restore(); }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); TextureLayerTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(1, renderer.getIndex()); @@ -388,7 +389,7 @@ TEST(FrameBuilder, renderNode) { }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - TestUtils::createSyncedNodeList(parent), sLightCenter); + TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr); RenderNodeTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); } @@ -412,7 +413,7 @@ TEST(FrameBuilder, clipped) { FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver - 200, 200, TestUtils::createSyncedNodeList(node), sLightCenter); + 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); ClippedTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); } @@ -454,7 +455,7 @@ TEST(FrameBuilder, saveLayer_simple) { canvas.restore(); }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); SaveLayerSimpleTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(4, renderer.getIndex()); @@ -526,7 +527,7 @@ TEST(FrameBuilder, saveLayer_nested) { }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(800, 800), 800, 800, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); SaveLayerNestedTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(10, renderer.getIndex()); @@ -546,7 +547,7 @@ TEST(FrameBuilder, saveLayer_contentRejection) { canvas.restore(); }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); FailRenderer renderer; // should see no ops, even within the layer, since the layer should be rejected @@ -589,7 +590,7 @@ TEST(FrameBuilder, saveLayerUnclipped_simple) { canvas.restore(); }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); SaveLayerUnclippedSimpleTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(4, renderer.getIndex()); @@ -643,7 +644,7 @@ TEST(FrameBuilder, saveLayerUnclipped_mergedClears) { canvas.restoreToCount(restoreTo); }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); SaveLayerUnclippedMergedClearsTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(10, renderer.getIndex()) @@ -705,7 +706,7 @@ TEST(FrameBuilder, saveLayerUnclipped_complex) { canvas.restore(); }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(600, 600), 600, 600, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); SaveLayerUnclippedComplexTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(12, renderer.getIndex()); @@ -763,7 +764,7 @@ RENDERTHREAD_TEST(FrameBuilder, hwLayer_simple) { layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75)); FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - syncedNodeList, sLightCenter); + syncedNodeList, sLightGeometry, nullptr); HwLayerSimpleTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(6, renderer.getIndex()); @@ -864,7 +865,7 @@ RENDERTHREAD_TEST(FrameBuilder, hwLayer_complex) { layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200)); FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - syncedList, sLightCenter); + syncedList, sLightGeometry, nullptr); HwLayerComplexTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(13, renderer.getIndex()); @@ -913,7 +914,7 @@ TEST(FrameBuilder, zReorder) { drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, - TestUtils::createSyncedNodeList(parent), sLightCenter); + TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr); ZReorderTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(10, renderer.getIndex()); @@ -996,7 +997,7 @@ TEST(FrameBuilder, projectionReorder) { }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, - TestUtils::createSyncedNodeList(parent), sLightCenter); + TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr); ProjectionReorderTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(3, renderer.getIndex()); @@ -1014,18 +1015,18 @@ static sp<RenderNode> createWhiteRectShadowCaster(float translationZ) { }); } -TEST(FrameBuilder, shadow) { +RENDERTHREAD_TEST(FrameBuilder, shadow) { class ShadowTestRenderer : public TestRendererBase { public: void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { EXPECT_EQ(0, mIndex++); EXPECT_FLOAT_EQ(1.0f, op.casterAlpha); - EXPECT_TRUE(op.casterPath->isRect(nullptr)); - EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowMatrixXY); + EXPECT_TRUE(op.shadowTask->casterPerimeter.isRect(nullptr)); + EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowTask->transformXY); Matrix4 expectedZ; expectedZ.loadTranslate(0, 0, 5); - EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowMatrixZ); + EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowTask->transformZ); } void onRectOp(const RectOp& op, const BakedOpState& state) override { EXPECT_EQ(1, mIndex++); @@ -1039,13 +1040,13 @@ TEST(FrameBuilder, shadow) { }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - TestUtils::createSyncedNodeList(parent), sLightCenter); + TestUtils::createSyncedNodeList(parent), sLightGeometry, &Caches::getInstance()); ShadowTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(2, renderer.getIndex()); } -TEST(FrameBuilder, shadowSaveLayer) { +RENDERTHREAD_TEST(FrameBuilder, shadowSaveLayer) { class ShadowSaveLayerTestRenderer : public TestRendererBase { public: OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { @@ -1054,8 +1055,8 @@ TEST(FrameBuilder, shadowSaveLayer) { } void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { EXPECT_EQ(1, mIndex++); - EXPECT_FLOAT_EQ(50, op.lightCenter.x); - EXPECT_FLOAT_EQ(40, op.lightCenter.y); + EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); + EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); } void onRectOp(const RectOp& op, const BakedOpState& state) override { EXPECT_EQ(2, mIndex++); @@ -1080,7 +1081,9 @@ TEST(FrameBuilder, shadowSaveLayer) { }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - TestUtils::createSyncedNodeList(parent), (Vector3) { 100, 100, 100 }); + TestUtils::createSyncedNodeList(parent), + (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, + &Caches::getInstance()); ShadowSaveLayerTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(5, renderer.getIndex()); @@ -1094,8 +1097,9 @@ RENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) { } void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { EXPECT_EQ(1, mIndex++); - EXPECT_FLOAT_EQ(50, op.lightCenter.x); - EXPECT_FLOAT_EQ(40, op.lightCenter.y); + EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); + EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); + EXPECT_FLOAT_EQ(30, op.shadowTask->lightRadius); } void onRectOp(const RectOp& op, const BakedOpState& state) override { EXPECT_EQ(2, mIndex++); @@ -1130,7 +1134,9 @@ RENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) { LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100)); FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - syncedList, (Vector3) { 100, 100, 100 }); + syncedList, + (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30}, + &Caches::getInstance()); ShadowHwLayerTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(5, renderer.getIndex()); @@ -1159,7 +1165,9 @@ TEST(FrameBuilder, shadowLayering) { }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - TestUtils::createSyncedNodeList(parent), sLightCenter); + TestUtils::createSyncedNodeList(parent), + (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, + &Caches::getInstance()); ShadowLayeringTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(4, renderer.getIndex()); @@ -1187,7 +1195,7 @@ static void testProperty(std::function<void(RenderProperties&)> propSetupCallbac }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200, - TestUtils::createSyncedNodeList(node), sLightCenter); + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); PropertyTestRenderer renderer(opValidateCallback); frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op"; @@ -1328,7 +1336,8 @@ void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData, }); auto nodes = TestUtils::createSyncedNodeList(node); // sync before querying height - FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, nodes, sLightCenter); + FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, + nodes, sLightGeometry, nullptr); SaveLayerAlphaClipTestRenderer renderer(outObservedData); frameBuilder.replayBakedOps<TestDispatcher>(renderer); diff --git a/libs/hwui/tests/unit/LeakCheckTests.cpp b/libs/hwui/tests/unit/LeakCheckTests.cpp index 4a635fb1b8c8..da786c7d9d46 100644 --- a/libs/hwui/tests/unit/LeakCheckTests.cpp +++ b/libs/hwui/tests/unit/LeakCheckTests.cpp @@ -27,7 +27,8 @@ using namespace android; using namespace android::uirenderer; const LayerUpdateQueue sEmptyLayerUpdateQueue; -const Vector3 sLightCenter = {100, 100, 100}; +const FrameBuilder::LightGeometry sLightGeometery = { {100, 100, 100}, 50}; +const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 }; RENDERTHREAD_TEST(LeakCheck, saveLayerUnclipped_simple) { auto node = TestUtils::createNode(0, 0, 200, 200, @@ -36,12 +37,11 @@ RENDERTHREAD_TEST(LeakCheck, saveLayerUnclipped_simple) { canvas.drawRect(0, 0, 200, 200, SkPaint()); canvas.restore(); }); - BakedOpRenderer::LightInfo lightInfo = {50.0f, 128, 128}; RenderState& renderState = renderThread.renderState(); Caches& caches = Caches::getInstance(); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, - TestUtils::createSyncedNodeList(node), sLightCenter); - BakedOpRenderer renderer(caches, renderState, true, lightInfo); + TestUtils::createSyncedNodeList(node), sLightGeometery, nullptr); + BakedOpRenderer renderer(caches, renderState, true, sLightInfo); frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer); } |