Merged op dispatch in OpReorderer
bug:22480459
Also switches std::functions to function pointers on OpReorderer, and
switches AssetAtlas' entry getter methods to using pixelRef pointers,
so it's clear they're the keys.
Change-Id: I3040ce5ff4e178a8364e0fd7ab0876ada7d4de05
diff --git a/libs/hwui/OpReorderer.h b/libs/hwui/OpReorderer.h
index 00df8b0..fc77c61 100644
--- a/libs/hwui/OpReorderer.h
+++ b/libs/hwui/OpReorderer.h
@@ -58,7 +58,8 @@
}
class OpReorderer : public CanvasStateClient {
- typedef std::function<void(void*, const RecordedOp&, const BakedOpState&)> BakedOpDispatcher;
+ typedef void (*BakedOpReceiver)(void*, const BakedOpState&);
+ typedef void (*MergedOpReceiver)(void*, const MergedBakedOpList& opList);
/**
* Stores the deferred render operations and state used to compute ordering
@@ -87,7 +88,7 @@
void deferMergeableOp(LinearAllocator& allocator,
BakedOpState* op, batchid_t batchId, mergeid_t mergeId);
- void replayBakedOpsImpl(void* arg, BakedOpDispatcher* receivers) const;
+ void replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers, MergedOpReceiver*) const;
bool empty() const {
return mBatches.empty();
@@ -132,19 +133,44 @@
* It constructs a lookup array of lambdas, which allows a recorded BakeOpState to use
* state->op->opId to lookup a receiver that will be called when the op is replayed.
*
- * For example a BitmapOp would resolve, via the lambda lookup, to calling:
- *
- * StaticDispatcher::onBitmapOp(Renderer& renderer, const BitmapOp& op, const BakedOpState& state);
*/
-#define BAKED_OP_RECEIVER(Type) \
- [](void* internalRenderer, const RecordedOp& op, const BakedOpState& state) { \
- StaticDispatcher::on##Type(*(static_cast<Renderer*>(internalRenderer)), static_cast<const Type&>(op), state); \
- },
template <typename StaticDispatcher, typename Renderer>
void replayBakedOps(Renderer& renderer) {
- static BakedOpDispatcher receivers[] = {
- MAP_OPS(BAKED_OP_RECEIVER)
+ /**
+ * defines a LUT of lambdas which allow a recorded BakedOpState to use state->op->opId to
+ * dispatch the op via a method on a static dispatcher when the op is replayed.
+ *
+ * For example a BitmapOp would resolve, via the lambda lookup, to calling:
+ *
+ * StaticDispatcher::onBitmapOp(Renderer& renderer, const BitmapOp& op, const BakedOpState& state);
+ */
+ #define X(Type) \
+ [](void* renderer, const BakedOpState& state) { \
+ StaticDispatcher::on##Type(*(static_cast<Renderer*>(renderer)), static_cast<const Type&>(*(state.op)), state); \
+ },
+ static BakedOpReceiver unmergedReceivers[] = {
+ MAP_OPS(X)
};
+ #undef X
+
+ /**
+ * defines a LUT of lambdas which allow merged arrays of BakedOpState* to be passed to a
+ * static dispatcher when the group of merged ops is replayed. Unmergeable ops trigger
+ * a LOG_ALWAYS_FATAL().
+ */
+ #define X(Type) \
+ [](void* renderer, const MergedBakedOpList& opList) { \
+ LOG_ALWAYS_FATAL("op type %d does not support merging", opList.states[0]->op->opId); \
+ },
+ #define Y(Type) \
+ [](void* renderer, const MergedBakedOpList& opList) { \
+ StaticDispatcher::onMerged##Type##s(*(static_cast<Renderer*>(renderer)), opList); \
+ },
+ static MergedOpReceiver mergedReceivers[] = {
+ MAP_OPS_BASED_ON_MERGEABILITY(X, Y)
+ };
+ #undef X
+ #undef Y
// Relay through layers in reverse order, since layers
// later in the list will be drawn by earlier ones
@@ -153,18 +179,18 @@
if (layer.renderNode) {
// cached HW layer - can't skip layer if empty
renderer.startRepaintLayer(layer.offscreenBuffer, layer.repaintRect);
- layer.replayBakedOpsImpl((void*)&renderer, receivers);
+ layer.replayBakedOpsImpl((void*)&renderer, unmergedReceivers, mergedReceivers);
renderer.endLayer();
} else if (!layer.empty()) { // save layer - skip entire layer if empty
layer.offscreenBuffer = renderer.startTemporaryLayer(layer.width, layer.height);
- layer.replayBakedOpsImpl((void*)&renderer, receivers);
+ layer.replayBakedOpsImpl((void*)&renderer, unmergedReceivers, mergedReceivers);
renderer.endLayer();
}
}
const LayerReorderer& fbo0 = mLayerReorderers[0];
renderer.startFrame(fbo0.width, fbo0.height, fbo0.repaintRect);
- fbo0.replayBakedOpsImpl((void*)&renderer, receivers);
+ fbo0.replayBakedOpsImpl((void*)&renderer, unmergedReceivers, mergedReceivers);
renderer.endFrame();
}
@@ -213,7 +239,7 @@
void deferRenderNodeOp(const RenderNodeOp& op);
- void replayBakedOpsImpl(void* arg, BakedOpDispatcher* receivers);
+ void replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers);
SkPath* createFrameAllocatedPath() {
mFrameAllocatedPaths.emplace_back(new SkPath);