Early kickoff of shadow tasks
bug:26562703
Change-Id: I7cdf18f2c662380bd31c7ffeefd5c3f569e5c1c6
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 7ecc743..ca1f8f94 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -663,13 +663,7 @@
}
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 10c4698..55ea935 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -45,13 +45,11 @@
* 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 87844f9..a542c26 100644
--- a/libs/hwui/BakedOpState.cpp
+++ b/libs/hwui/BakedOpState.cpp
@@ -63,16 +63,11 @@
}
}
-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 a457212..9528587 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -32,17 +32,11 @@
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 @@
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 @@
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 dea9934..5df2e46 100644
--- a/libs/hwui/FrameBuilder.h
+++ b/libs/hwui/FrameBuilder.h
@@ -55,14 +55,24 @@
*/
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 @@
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 30d5c29..593d690 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 @@
* 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 0835c29..461e819 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -160,45 +160,6 @@
// 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 @@
~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 @@
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 06e567e..977c2d9e 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 @@
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 @@
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 e7cf3ec..d411621 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 @@
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::setLightCenter(const Vector3& lightCenter) {
#if HWUI_NEW_OPS
- mLightCenter = lightCenter;
+ mLightGeometry.center = lightCenter;
#else
if (!mCanvas) return;
mCanvas->setLightCenter(lightCenter);
@@ -345,7 +341,7 @@
#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 270fb1f..63a7977 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 @@
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 f9c2b67..7845eb4 100644
--- a/libs/hwui/tests/microbench/FrameBuilderBench.cpp
+++ b/libs/hwui/tests/microbench/FrameBuilderBench.cpp
@@ -37,7 +37,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 618df14..f49dd3f 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -30,7 +30,8 @@
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 @@
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 @@
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 @@
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 @@
});
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 @@
});
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 @@
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 @@
}
});
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 @@
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 @@
});
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 @@
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 @@
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 @@
});
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
});
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 @@
});
}
-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 @@
});
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 @@
}
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 @@
});
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 @@
}
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 @@
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 @@
});
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 @@
});
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 @@
});
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 4a635fb..da786c7 100644
--- a/libs/hwui/tests/unit/LeakCheckTests.cpp
+++ b/libs/hwui/tests/unit/LeakCheckTests.cpp
@@ -27,7 +27,8 @@
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 @@
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);
}