Fix all LA memory leaks forever!
Bug: 27072626 Or at least fix this one and make it harder to leak going forward. static_asserts are cool, use them liberally Also makes allocation via LA (slightly) faster by fixing create* variants to use rvalue references & std::forward, preventing an accidental pass-by-value Change-Id: I18fd696a93dd6ea49c8d8c587d4c8bee56dbfdf5
This commit is contained in:
@@ -100,7 +100,7 @@ public:
|
||||
static BakedOpState* tryConstruct(LinearAllocator& allocator,
|
||||
Snapshot& snapshot, const RecordedOp& recordedOp) {
|
||||
if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
|
||||
BakedOpState* bakedState = new (allocator) BakedOpState(
|
||||
BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
|
||||
allocator, snapshot, recordedOp, false);
|
||||
if (bakedState->computedState.clippedBounds.isEmpty()) {
|
||||
// bounds are empty, so op is rejected
|
||||
@@ -124,7 +124,7 @@ public:
|
||||
? (recordedOp.paint && recordedOp.paint->getStyle() != SkPaint::kFill_Style)
|
||||
: true;
|
||||
|
||||
BakedOpState* bakedState = new (allocator) BakedOpState(
|
||||
BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
|
||||
allocator, snapshot, recordedOp, expandForStroke);
|
||||
if (bakedState->computedState.clippedBounds.isEmpty()) {
|
||||
// bounds are empty, so op is rejected
|
||||
@@ -140,16 +140,12 @@ public:
|
||||
if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
|
||||
|
||||
// clip isn't empty, so construct the op
|
||||
return new (allocator) BakedOpState(allocator, snapshot, shadowOpPtr);
|
||||
return allocator.create_trivial<BakedOpState>(allocator, snapshot, shadowOpPtr);
|
||||
}
|
||||
|
||||
static BakedOpState* directConstruct(LinearAllocator& allocator,
|
||||
const ClipRect* clip, const Rect& dstRect, const RecordedOp& recordedOp) {
|
||||
return new (allocator) BakedOpState(clip, dstRect, recordedOp);
|
||||
}
|
||||
|
||||
static void* operator new(size_t size, LinearAllocator& allocator) {
|
||||
return allocator.alloc(size);
|
||||
return allocator.create_trivial<BakedOpState>(clip, dstRect, recordedOp);
|
||||
}
|
||||
|
||||
// computed state:
|
||||
@@ -162,6 +158,8 @@ public:
|
||||
const RecordedOp* op;
|
||||
|
||||
private:
|
||||
friend class LinearAllocator;
|
||||
|
||||
BakedOpState(LinearAllocator& allocator, Snapshot& snapshot,
|
||||
const RecordedOp& recordedOp, bool expandForStroke)
|
||||
: computedState(allocator, snapshot, recordedOp, expandForStroke)
|
||||
|
||||
@@ -45,7 +45,7 @@ struct DirtyStack {
|
||||
};
|
||||
|
||||
DamageAccumulator::DamageAccumulator() {
|
||||
mHead = (DirtyStack*) mAllocator.alloc(sizeof(DirtyStack));
|
||||
mHead = mAllocator.create_trivial<DirtyStack>();
|
||||
memset(mHead, 0, sizeof(DirtyStack));
|
||||
// Create a root that we will not pop off
|
||||
mHead->prev = mHead;
|
||||
@@ -78,7 +78,7 @@ void DamageAccumulator::computeCurrentTransform(Matrix4* outMatrix) const {
|
||||
|
||||
void DamageAccumulator::pushCommon() {
|
||||
if (!mHead->next) {
|
||||
DirtyStack* nextFrame = (DirtyStack*) mAllocator.alloc(sizeof(DirtyStack));
|
||||
DirtyStack* nextFrame = mAllocator.create_trivial<DirtyStack>();
|
||||
nextFrame->next = nullptr;
|
||||
nextFrame->prev = mHead;
|
||||
mHead->next = nextFrame;
|
||||
|
||||
@@ -49,11 +49,6 @@ typedef const void* mergeid_t;
|
||||
|
||||
class DeferredDisplayState {
|
||||
public:
|
||||
static void* operator new(size_t size) = delete;
|
||||
static void* operator new(size_t size, LinearAllocator& allocator) {
|
||||
return allocator.alloc(size);
|
||||
}
|
||||
|
||||
// global op bounds, mapped by mMatrix to be in screen space coordinates, clipped
|
||||
Rect mBounds;
|
||||
|
||||
@@ -124,7 +119,7 @@ private:
|
||||
DeferredDisplayList(const DeferredDisplayList& other); // disallow copy
|
||||
|
||||
DeferredDisplayState* createState() {
|
||||
return new (mAllocator) DeferredDisplayState();
|
||||
return mAllocator.create_trivial<DeferredDisplayState>();
|
||||
}
|
||||
|
||||
void tryRecycleState(DeferredDisplayState* state) {
|
||||
|
||||
@@ -251,7 +251,7 @@ private:
|
||||
inline const T* refBuffer(const T* srcBuffer, int32_t count) {
|
||||
if (!srcBuffer) return nullptr;
|
||||
|
||||
T* dstBuffer = (T*) mDisplayList->allocator.alloc(count * sizeof(T));
|
||||
T* dstBuffer = (T*) mDisplayList->allocator.alloc<T>(count * sizeof(T));
|
||||
memcpy(dstBuffer, srcBuffer, count * sizeof(T));
|
||||
return dstBuffer;
|
||||
}
|
||||
@@ -320,8 +320,7 @@ private:
|
||||
// correctly, such as creating the bitmap from scratch, drawing with it, changing its
|
||||
// contents, and drawing again. The only fix would be to always copy it the first time,
|
||||
// which doesn't seem worth the extra cycles for this unlikely case.
|
||||
SkBitmap* localBitmap = new (alloc()) SkBitmap(bitmap);
|
||||
alloc().autoDestroy(localBitmap);
|
||||
SkBitmap* localBitmap = alloc().create<SkBitmap>(bitmap);
|
||||
mDisplayList->bitmapResources.push_back(localBitmap);
|
||||
return localBitmap;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,9 @@ public:
|
||||
static void operator delete(void* ptr) { LOG_ALWAYS_FATAL("delete not supported"); }
|
||||
static void* operator new(size_t size) = delete; /** PURPOSELY OMITTED **/
|
||||
static void* operator new(size_t size, LinearAllocator& allocator) {
|
||||
return allocator.alloc(size);
|
||||
// FIXME: Quick hack to keep old pipeline working, delete this when
|
||||
// we no longer need to support HWUI_NEWOPS := false
|
||||
return allocator.alloc<char>(size);
|
||||
}
|
||||
|
||||
enum OpLogFlag {
|
||||
|
||||
@@ -209,7 +209,7 @@ void FrameBuilder::deferNodePropsAndOps(RenderNode& node) {
|
||||
// not rejected, so defer render as either Layer, or direct (possibly wrapped in saveLayer)
|
||||
if (node.getLayer()) {
|
||||
// HW layer
|
||||
LayerOp* drawLayerOp = new (mAllocator) LayerOp(node);
|
||||
LayerOp* drawLayerOp = mAllocator.create_trivial<LayerOp>(node);
|
||||
BakedOpState* bakedOpState = tryBakeOpState(*drawLayerOp);
|
||||
if (bakedOpState) {
|
||||
// Node's layer already deferred, schedule it to render into parent layer
|
||||
@@ -220,13 +220,13 @@ void FrameBuilder::deferNodePropsAndOps(RenderNode& node) {
|
||||
// (temp layers are clipped to viewport, since they don't persist offscreen content)
|
||||
SkPaint saveLayerPaint;
|
||||
saveLayerPaint.setAlpha(properties.getAlpha());
|
||||
deferBeginLayerOp(*new (mAllocator) BeginLayerOp(
|
||||
deferBeginLayerOp(*mAllocator.create_trivial<BeginLayerOp>(
|
||||
saveLayerBounds,
|
||||
Matrix4::identity(),
|
||||
nullptr, // no record-time clip - need only respect defer-time one
|
||||
&saveLayerPaint));
|
||||
deferNodeOps(node);
|
||||
deferEndLayerOp(*new (mAllocator) EndLayerOp());
|
||||
deferEndLayerOp(*mAllocator.create_trivial<EndLayerOp>());
|
||||
} else {
|
||||
deferNodeOps(node);
|
||||
}
|
||||
@@ -549,7 +549,7 @@ void FrameBuilder::deferBitmapRectOp(const BitmapRectOp& op) {
|
||||
void FrameBuilder::deferVectorDrawableOp(const VectorDrawableOp& op) {
|
||||
const SkBitmap& bitmap = op.vectorDrawable->getBitmapUpdateIfDirty();
|
||||
SkPaint* paint = op.vectorDrawable->getPaint();
|
||||
const BitmapRectOp* resolvedOp = new (mAllocator) BitmapRectOp(op.unmappedBounds,
|
||||
const BitmapRectOp* resolvedOp = mAllocator.create_trivial<BitmapRectOp>(op.unmappedBounds,
|
||||
op.localMatrix,
|
||||
op.localClip,
|
||||
paint,
|
||||
@@ -565,7 +565,7 @@ void FrameBuilder::deferCirclePropsOp(const CirclePropsOp& op) {
|
||||
float y = *(op.y);
|
||||
float radius = *(op.radius);
|
||||
Rect unmappedBounds(x - radius, y - radius, x + radius, y + radius);
|
||||
const OvalOp* resolvedOp = new (mAllocator) OvalOp(
|
||||
const OvalOp* resolvedOp = mAllocator.create_trivial<OvalOp>(
|
||||
unmappedBounds,
|
||||
op.localMatrix,
|
||||
op.localClip,
|
||||
@@ -626,7 +626,7 @@ void FrameBuilder::deferRoundRectOp(const RoundRectOp& op) {
|
||||
void FrameBuilder::deferRoundRectPropsOp(const RoundRectPropsOp& op) {
|
||||
// allocate a temporary round rect op (with mAllocator, so it persists until render), so the
|
||||
// renderer doesn't have to handle the RoundRectPropsOp type, and so state baking is simple.
|
||||
const RoundRectOp* resolvedOp = new (mAllocator) RoundRectOp(
|
||||
const RoundRectOp* resolvedOp = mAllocator.create_trivial<RoundRectOp>(
|
||||
Rect(*(op.left), *(op.top), *(op.right), *(op.bottom)),
|
||||
op.localMatrix,
|
||||
op.localClip,
|
||||
@@ -754,7 +754,7 @@ void FrameBuilder::deferEndLayerOp(const EndLayerOp& /* ignored */) {
|
||||
|
||||
// record the draw operation into the previous layer's list of draw commands
|
||||
// uses state from the associated beginLayerOp, since it has all the state needed for drawing
|
||||
LayerOp* drawLayerOp = new (mAllocator) LayerOp(
|
||||
LayerOp* drawLayerOp = mAllocator.create_trivial<LayerOp>(
|
||||
beginLayerOp.unmappedBounds,
|
||||
beginLayerOp.localMatrix,
|
||||
beginLayerOp.localClip,
|
||||
@@ -788,7 +788,7 @@ void FrameBuilder::deferBeginUnclippedLayerOp(const BeginUnclippedLayerOp& op) {
|
||||
/**
|
||||
* First, defer an operation to copy out the content from the rendertarget into a layer.
|
||||
*/
|
||||
auto copyToOp = new (mAllocator) CopyToLayerOp(op, layerHandle);
|
||||
auto copyToOp = mAllocator.create_trivial<CopyToLayerOp>(op, layerHandle);
|
||||
BakedOpState* bakedState = BakedOpState::directConstruct(mAllocator,
|
||||
&(currentLayer().viewportClip), dstRect, *copyToOp);
|
||||
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::CopyToLayer);
|
||||
@@ -803,7 +803,7 @@ void FrameBuilder::deferBeginUnclippedLayerOp(const BeginUnclippedLayerOp& op) {
|
||||
* And stash an operation to copy that layer back under the rendertarget until
|
||||
* a balanced EndUnclippedLayerOp is seen
|
||||
*/
|
||||
auto copyFromOp = new (mAllocator) CopyFromLayerOp(op, layerHandle);
|
||||
auto copyFromOp = mAllocator.create_trivial<CopyFromLayerOp>(op, layerHandle);
|
||||
bakedState = BakedOpState::directConstruct(mAllocator,
|
||||
&(currentLayer().viewportClip), dstRect, *copyFromOp);
|
||||
currentLayer().activeUnclippedSaveLayers.push_back(bakedState);
|
||||
|
||||
@@ -64,10 +64,6 @@ protected:
|
||||
|
||||
class OpBatch : public BatchBase {
|
||||
public:
|
||||
static void* operator new(size_t size, LinearAllocator& allocator) {
|
||||
return allocator.alloc(size);
|
||||
}
|
||||
|
||||
OpBatch(batchid_t batchId, BakedOpState* op)
|
||||
: BatchBase(batchId, op, false) {
|
||||
}
|
||||
@@ -80,10 +76,6 @@ public:
|
||||
|
||||
class MergingOpBatch : public BatchBase {
|
||||
public:
|
||||
static void* operator new(size_t size, LinearAllocator& allocator) {
|
||||
return allocator.alloc(size);
|
||||
}
|
||||
|
||||
MergingOpBatch(batchid_t batchId, BakedOpState* op)
|
||||
: BatchBase(batchId, op, true)
|
||||
, mClipSideFlags(op->computedState.clipSideFlags) {
|
||||
@@ -247,7 +239,7 @@ void LayerBuilder::flushLayerClears(LinearAllocator& allocator) {
|
||||
// put the verts in the frame allocator, since
|
||||
// 1) SimpleRectsOps needs verts, not rects
|
||||
// 2) even if mClearRects stored verts, std::vectors will move their contents
|
||||
Vertex* const verts = (Vertex*) allocator.alloc(vertCount * sizeof(Vertex));
|
||||
Vertex* const verts = (Vertex*) allocator.alloc<Vertex>(vertCount * sizeof(Vertex));
|
||||
|
||||
Vertex* currentVert = verts;
|
||||
Rect bounds = mClearRects[0];
|
||||
@@ -264,7 +256,7 @@ void LayerBuilder::flushLayerClears(LinearAllocator& allocator) {
|
||||
// Flush all of these clears with a single draw
|
||||
SkPaint* paint = allocator.create<SkPaint>();
|
||||
paint->setXfermodeMode(SkXfermode::kClear_Mode);
|
||||
SimpleRectsOp* op = new (allocator) SimpleRectsOp(bounds,
|
||||
SimpleRectsOp* op = allocator.create_trivial<SimpleRectsOp>(bounds,
|
||||
Matrix4::identity(), nullptr, paint,
|
||||
verts, vertCount);
|
||||
BakedOpState* bakedState = BakedOpState::directConstruct(allocator,
|
||||
@@ -292,7 +284,7 @@ void LayerBuilder::deferUnmergeableOp(LinearAllocator& allocator,
|
||||
targetBatch->batchOp(op);
|
||||
} else {
|
||||
// new non-merging batch
|
||||
targetBatch = new (allocator) OpBatch(batchId, op);
|
||||
targetBatch = allocator.create<OpBatch>(batchId, op);
|
||||
mBatchLookup[batchId] = targetBatch;
|
||||
mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch);
|
||||
}
|
||||
@@ -323,7 +315,7 @@ void LayerBuilder::deferMergeableOp(LinearAllocator& allocator,
|
||||
targetBatch->mergeOp(op);
|
||||
} else {
|
||||
// new merging batch
|
||||
targetBatch = new (allocator) MergingOpBatch(batchId, op);
|
||||
targetBatch = allocator.create<MergingOpBatch>(batchId, op);
|
||||
mMergingBatchLookup[batchId].insert(std::make_pair(mergeId, targetBatch));
|
||||
|
||||
mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch);
|
||||
|
||||
@@ -83,9 +83,9 @@ void RecordingCanvas::onViewportInitialized() {
|
||||
|
||||
void RecordingCanvas::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {
|
||||
if (removed.flags & Snapshot::kFlagIsFboLayer) {
|
||||
addOp(new (alloc()) EndLayerOp());
|
||||
addOp(alloc().create_trivial<EndLayerOp>());
|
||||
} else if (removed.flags & Snapshot::kFlagIsLayer) {
|
||||
addOp(new (alloc()) EndUnclippedLayerOp());
|
||||
addOp(alloc().create_trivial<EndUnclippedLayerOp>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ int RecordingCanvas::saveLayer(float left, float top, float right, float bottom,
|
||||
snapshot.resetClip(clip.left, clip.top, clip.right, clip.bottom);
|
||||
snapshot.roundRectClipState = nullptr;
|
||||
|
||||
addOp(new (alloc()) BeginLayerOp(
|
||||
addOp(alloc().create_trivial<BeginLayerOp>(
|
||||
unmappedBounds,
|
||||
*previous.transform, // transform to *draw* with
|
||||
previousClip, // clip to *draw* with
|
||||
@@ -175,7 +175,7 @@ int RecordingCanvas::saveLayer(float left, float top, float right, float bottom,
|
||||
} else {
|
||||
snapshot.flags |= Snapshot::kFlagIsLayer;
|
||||
|
||||
addOp(new (alloc()) BeginUnclippedLayerOp(
|
||||
addOp(alloc().create_trivial<BeginUnclippedLayerOp>(
|
||||
unmappedBounds,
|
||||
*mState.currentSnapshot()->transform,
|
||||
getRecordedClip(),
|
||||
@@ -241,7 +241,7 @@ void RecordingCanvas::drawColor(int color, SkXfermode::Mode mode) {
|
||||
}
|
||||
|
||||
void RecordingCanvas::drawPaint(const SkPaint& paint) {
|
||||
addOp(new (alloc()) RectOp(
|
||||
addOp(alloc().create_trivial<RectOp>(
|
||||
mState.getRenderTargetClipBounds(), // OK, since we've not passed transform
|
||||
Matrix4::identity(),
|
||||
getRecordedClip(),
|
||||
@@ -261,7 +261,7 @@ void RecordingCanvas::drawPoints(const float* points, int floatCount, const SkPa
|
||||
if (floatCount < 2) return;
|
||||
floatCount &= ~0x1; // round down to nearest two
|
||||
|
||||
addOp(new (alloc()) PointsOp(
|
||||
addOp(alloc().create_trivial<PointsOp>(
|
||||
calcBoundsOfPoints(points, floatCount),
|
||||
*mState.currentSnapshot()->transform,
|
||||
getRecordedClip(),
|
||||
@@ -272,7 +272,7 @@ void RecordingCanvas::drawLines(const float* points, int floatCount, const SkPai
|
||||
if (floatCount < 4) return;
|
||||
floatCount &= ~0x3; // round down to nearest four
|
||||
|
||||
addOp(new (alloc()) LinesOp(
|
||||
addOp(alloc().create_trivial<LinesOp>(
|
||||
calcBoundsOfPoints(points, floatCount),
|
||||
*mState.currentSnapshot()->transform,
|
||||
getRecordedClip(),
|
||||
@@ -280,7 +280,7 @@ void RecordingCanvas::drawLines(const float* points, int floatCount, const SkPai
|
||||
}
|
||||
|
||||
void RecordingCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
|
||||
addOp(new (alloc()) RectOp(
|
||||
addOp(alloc().create_trivial<RectOp>(
|
||||
Rect(left, top, right, bottom),
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
@@ -290,7 +290,7 @@ void RecordingCanvas::drawRect(float left, float top, float right, float bottom,
|
||||
void RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint) {
|
||||
if (rects == nullptr) return;
|
||||
|
||||
Vertex* rectData = (Vertex*) mDisplayList->allocator.alloc(vertexCount * sizeof(Vertex));
|
||||
Vertex* rectData = (Vertex*) mDisplayList->allocator.alloc<Vertex>(vertexCount * sizeof(Vertex));
|
||||
Vertex* vertex = rectData;
|
||||
|
||||
float left = FLT_MAX;
|
||||
@@ -313,7 +313,7 @@ void RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const
|
||||
right = std::max(right, r);
|
||||
bottom = std::max(bottom, b);
|
||||
}
|
||||
addOp(new (alloc()) SimpleRectsOp(
|
||||
addOp(alloc().create_trivial<SimpleRectsOp>(
|
||||
Rect(left, top, right, bottom),
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
@@ -347,7 +347,7 @@ void RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
|
||||
}
|
||||
void RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom,
|
||||
float rx, float ry, const SkPaint& paint) {
|
||||
addOp(new (alloc()) RoundRectOp(
|
||||
addOp(alloc().create_trivial<RoundRectOp>(
|
||||
Rect(left, top, right, bottom),
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
@@ -367,7 +367,7 @@ void RecordingCanvas::drawRoundRect(
|
||||
mDisplayList->ref(ry);
|
||||
mDisplayList->ref(paint);
|
||||
refBitmapsInShader(paint->value.getShader());
|
||||
addOp(new (alloc()) RoundRectPropsOp(
|
||||
addOp(alloc().create_trivial<RoundRectPropsOp>(
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
&paint->value,
|
||||
@@ -389,7 +389,7 @@ void RecordingCanvas::drawCircle(
|
||||
mDisplayList->ref(radius);
|
||||
mDisplayList->ref(paint);
|
||||
refBitmapsInShader(paint->value.getShader());
|
||||
addOp(new (alloc()) CirclePropsOp(
|
||||
addOp(alloc().create_trivial<CirclePropsOp>(
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
&paint->value,
|
||||
@@ -397,7 +397,7 @@ void RecordingCanvas::drawCircle(
|
||||
}
|
||||
|
||||
void RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
|
||||
addOp(new (alloc()) OvalOp(
|
||||
addOp(alloc().create_trivial<OvalOp>(
|
||||
Rect(left, top, right, bottom),
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
@@ -406,7 +406,7 @@ void RecordingCanvas::drawOval(float left, float top, float right, float bottom,
|
||||
|
||||
void RecordingCanvas::drawArc(float left, float top, float right, float bottom,
|
||||
float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
|
||||
addOp(new (alloc()) ArcOp(
|
||||
addOp(alloc().create_trivial<ArcOp>(
|
||||
Rect(left, top, right, bottom),
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
@@ -415,7 +415,7 @@ void RecordingCanvas::drawArc(float left, float top, float right, float bottom,
|
||||
}
|
||||
|
||||
void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
|
||||
addOp(new (alloc()) PathOp(
|
||||
addOp(alloc().create_trivial<PathOp>(
|
||||
Rect(path.getBounds()),
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
@@ -424,7 +424,7 @@ void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
|
||||
|
||||
void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
|
||||
mDisplayList->ref(tree);
|
||||
addOp(new (alloc()) VectorDrawableOp(
|
||||
addOp(alloc().create_trivial<VectorDrawableOp>(
|
||||
tree,
|
||||
Rect(tree->getBounds()),
|
||||
*(mState.currentSnapshot()->transform),
|
||||
@@ -475,7 +475,7 @@ void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float sr
|
||||
drawBitmap(&bitmap, paint);
|
||||
restore();
|
||||
} else {
|
||||
addOp(new (alloc()) BitmapRectOp(
|
||||
addOp(alloc().create_trivial<BitmapRectOp>(
|
||||
Rect(dstLeft, dstTop, dstRight, dstBottom),
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
@@ -487,7 +487,7 @@ void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float sr
|
||||
void RecordingCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
|
||||
const float* vertices, const int* colors, const SkPaint* paint) {
|
||||
int vertexCount = (meshWidth + 1) * (meshHeight + 1);
|
||||
addOp(new (alloc()) BitmapMeshOp(
|
||||
addOp(alloc().create_trivial<BitmapMeshOp>(
|
||||
calcBoundsOfPoints(vertices, vertexCount * 2),
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
@@ -499,7 +499,7 @@ void RecordingCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int
|
||||
void RecordingCanvas::drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& patch,
|
||||
float dstLeft, float dstTop, float dstRight, float dstBottom,
|
||||
const SkPaint* paint) {
|
||||
addOp(new (alloc()) PatchOp(
|
||||
addOp(alloc().create_trivial<PatchOp>(
|
||||
Rect(dstLeft, dstTop, dstRight, dstBottom),
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
@@ -515,7 +515,7 @@ void RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, i
|
||||
positions = refBuffer<float>(positions, glyphCount * 2);
|
||||
|
||||
// TODO: either must account for text shadow in bounds, or record separate ops for text shadows
|
||||
addOp(new (alloc()) TextOp(
|
||||
addOp(alloc().create_trivial<TextOp>(
|
||||
Rect(boundsLeft, boundsTop, boundsRight, boundsBottom),
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
@@ -527,7 +527,7 @@ void RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int glyphCount, con
|
||||
float hOffset, float vOffset, const SkPaint& paint) {
|
||||
if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
|
||||
glyphs = refBuffer<glyph_t>(glyphs, glyphCount);
|
||||
addOp(new (alloc()) TextOnPathOp(
|
||||
addOp(alloc().create_trivial<TextOnPathOp>(
|
||||
mState.getLocalClipBounds(), // TODO: explicitly define bounds
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
@@ -535,7 +535,7 @@ void RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int glyphCount, con
|
||||
}
|
||||
|
||||
void RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
|
||||
addOp(new (alloc()) BitmapOp(
|
||||
addOp(alloc().create_trivial<BitmapOp>(
|
||||
Rect(bitmap->width(), bitmap->height()),
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
@@ -544,7 +544,7 @@ void RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
|
||||
|
||||
void RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
|
||||
auto&& stagingProps = renderNode->stagingProperties();
|
||||
RenderNodeOp* op = new (alloc()) RenderNodeOp(
|
||||
RenderNodeOp* op = alloc().create_trivial<RenderNodeOp>(
|
||||
Rect(stagingProps.getWidth(), stagingProps.getHeight()),
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
@@ -570,7 +570,7 @@ void RecordingCanvas::drawLayer(DeferredLayerUpdater* layerHandle) {
|
||||
Matrix4 totalTransform(*(mState.currentSnapshot()->transform));
|
||||
totalTransform.multiply(layer->getTransform());
|
||||
|
||||
addOp(new (alloc()) TextureLayerOp(
|
||||
addOp(alloc().create_trivial<TextureLayerOp>(
|
||||
Rect(layer->getWidth(), layer->getHeight()),
|
||||
totalTransform,
|
||||
getRecordedClip(),
|
||||
@@ -579,7 +579,7 @@ void RecordingCanvas::drawLayer(DeferredLayerUpdater* layerHandle) {
|
||||
|
||||
void RecordingCanvas::callDrawGLFunction(Functor* functor) {
|
||||
mDisplayList->functors.push_back(functor);
|
||||
addOp(new (alloc()) FunctorOp(
|
||||
addOp(alloc().create_trivial<FunctorOp>(
|
||||
mState.getLocalClipBounds(), // TODO: explicitly define bounds
|
||||
*(mState.currentSnapshot()->transform),
|
||||
getRecordedClip(),
|
||||
|
||||
@@ -219,7 +219,7 @@ private:
|
||||
inline const T* refBuffer(const T* srcBuffer, int32_t count) {
|
||||
if (!srcBuffer) return nullptr;
|
||||
|
||||
T* dstBuffer = (T*) mDisplayList->allocator.alloc(count * sizeof(T));
|
||||
T* dstBuffer = (T*) mDisplayList->allocator.alloc<T>(count * sizeof(T));
|
||||
memcpy(dstBuffer, srcBuffer, count * sizeof(T));
|
||||
return dstBuffer;
|
||||
}
|
||||
@@ -290,8 +290,7 @@ private:
|
||||
// correctly, such as creating the bitmap from scratch, drawing with it, changing its
|
||||
// contents, and drawing again. The only fix would be to always copy it the first time,
|
||||
// which doesn't seem worth the extra cycles for this unlikely case.
|
||||
SkBitmap* localBitmap = new (alloc()) SkBitmap(bitmap);
|
||||
alloc().autoDestroy(localBitmap);
|
||||
SkBitmap* localBitmap = alloc().create<SkBitmap>(bitmap);
|
||||
mDisplayList->bitmapResources.push_back(localBitmap);
|
||||
return localBitmap;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class RoundRectClipState {
|
||||
public:
|
||||
/** static void* operator new(size_t size); PURPOSELY OMITTED, allocator only **/
|
||||
static void* operator new(size_t size, LinearAllocator& allocator) {
|
||||
return allocator.alloc(size);
|
||||
return allocator.alloc<RoundRectClipState>(size);
|
||||
}
|
||||
|
||||
bool areaRequiresRoundRectClip(const Rect& rect) const {
|
||||
@@ -67,7 +67,7 @@ class ProjectionPathMask {
|
||||
public:
|
||||
/** static void* operator new(size_t size); PURPOSELY OMITTED, allocator only **/
|
||||
static void* operator new(size_t size, LinearAllocator& allocator) {
|
||||
return allocator.alloc(size);
|
||||
return allocator.alloc<ProjectionPathMask>(size);
|
||||
}
|
||||
|
||||
const SkPath* projectionMask;
|
||||
|
||||
@@ -30,7 +30,7 @@ struct SimplePair {
|
||||
TEST(LinearAllocator, create) {
|
||||
LinearAllocator la;
|
||||
EXPECT_EQ(0u, la.usedSize());
|
||||
la.alloc(64);
|
||||
la.alloc<char>(64);
|
||||
// There's some internal tracking as well as padding
|
||||
// so the usedSize isn't strictly defined
|
||||
EXPECT_LE(64u, la.usedSize());
|
||||
@@ -50,13 +50,12 @@ TEST(LinearAllocator, dtor) {
|
||||
la.create<TestUtils::SignalingDtor>()->setSignal(destroyed + i);
|
||||
la.create<SimplePair>();
|
||||
}
|
||||
la.alloc(100);
|
||||
la.alloc<char>(100);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
auto sd = new (la) TestUtils::SignalingDtor(destroyed + 5 + i);
|
||||
la.autoDestroy(sd);
|
||||
new (la) SimplePair();
|
||||
la.create<TestUtils::SignalingDtor>(destroyed + 5 + i);
|
||||
la.create_trivial<SimplePair>();
|
||||
}
|
||||
la.alloc(100);
|
||||
la.alloc<char>(100);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
EXPECT_EQ(0, destroyed[i]);
|
||||
}
|
||||
@@ -70,7 +69,7 @@ TEST(LinearAllocator, rewind) {
|
||||
int destroyed = 0;
|
||||
{
|
||||
LinearAllocator la;
|
||||
auto addr = la.alloc(100);
|
||||
auto addr = la.alloc<char>(100);
|
||||
EXPECT_LE(100u, la.usedSize());
|
||||
la.rewindIfLastAlloc(addr, 100);
|
||||
EXPECT_GT(16u, la.usedSize());
|
||||
|
||||
@@ -81,10 +81,6 @@ static void _addAllocation(int count) {
|
||||
|
||||
#define min(x,y) (((x) < (y)) ? (x) : (y))
|
||||
|
||||
void* operator new(std::size_t size, android::uirenderer::LinearAllocator& la) {
|
||||
return la.alloc(size);
|
||||
}
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
@@ -171,7 +167,7 @@ void LinearAllocator::ensureNext(size_t size) {
|
||||
mNext = start(mCurrentPage);
|
||||
}
|
||||
|
||||
void* LinearAllocator::alloc(size_t size) {
|
||||
void* LinearAllocator::allocImpl(size_t size) {
|
||||
size = ALIGN(size);
|
||||
if (size > mMaxAllocSize && !fitsInCurrentPage(size)) {
|
||||
ALOGV("Exceeded max size %zu > %zu", size, mMaxAllocSize);
|
||||
@@ -196,7 +192,7 @@ void LinearAllocator::addToDestructionList(Destructor dtor, void* addr) {
|
||||
"DestructorNode must have standard layout");
|
||||
static_assert(std::is_trivially_destructible<DestructorNode>::value,
|
||||
"DestructorNode must be trivially destructable");
|
||||
auto node = new (*this) DestructorNode();
|
||||
auto node = new (allocImpl(sizeof(DestructorNode))) DestructorNode();
|
||||
node->dtor = dtor;
|
||||
node->addr = addr;
|
||||
node->next = mDtorList;
|
||||
|
||||
@@ -52,30 +52,36 @@ public:
|
||||
* The lifetime of the returned buffers is tied to that of the LinearAllocator. If calling
|
||||
* delete() on an object stored in a buffer is needed, it should be overridden to use
|
||||
* rewindIfLastAlloc()
|
||||
*
|
||||
* Note that unlike create, for alloc the type is purely for compile-time error
|
||||
* checking and does not affect size.
|
||||
*/
|
||||
void* alloc(size_t size);
|
||||
template<class T>
|
||||
void* alloc(size_t size) {
|
||||
static_assert(std::is_trivially_destructible<T>::value,
|
||||
"Error, type is non-trivial! did you mean to use create()?");
|
||||
return allocImpl(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates an instance of the template type with the given construction parameters
|
||||
* and adds it to the automatic destruction list.
|
||||
*/
|
||||
template<class T, typename... Params>
|
||||
T* create(Params... params) {
|
||||
T* ret = new (*this) T(params...);
|
||||
autoDestroy(ret);
|
||||
T* create(Params&&... params) {
|
||||
T* ret = new (allocImpl(sizeof(T))) T(std::forward<Params>(params)...);
|
||||
if (!std::is_trivially_destructible<T>::value) {
|
||||
auto dtor = [](void* ret) { ((T*)ret)->~T(); };
|
||||
addToDestructionList(dtor, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the pointer to the tracking list to have its destructor called
|
||||
* when the LinearAllocator is destroyed.
|
||||
*/
|
||||
template<class T>
|
||||
void autoDestroy(T* addr) {
|
||||
if (!std::is_trivially_destructible<T>::value) {
|
||||
auto dtor = [](void* addr) { ((T*)addr)->~T(); };
|
||||
addToDestructionList(dtor, addr);
|
||||
}
|
||||
template<class T, typename... Params>
|
||||
T* create_trivial(Params&&... params) {
|
||||
static_assert(std::is_trivially_destructible<T>::value,
|
||||
"Error, called create_trivial on a non-trivial type");
|
||||
return new (allocImpl(sizeof(T))) T(std::forward<Params>(params)...);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,6 +120,8 @@ private:
|
||||
DestructorNode* next = nullptr;
|
||||
};
|
||||
|
||||
void* allocImpl(size_t size);
|
||||
|
||||
void addToDestructionList(Destructor, void* addr);
|
||||
void runDestructorFor(void* addr);
|
||||
Page* newPage(size_t pageSize);
|
||||
@@ -159,7 +167,7 @@ public:
|
||||
: linearAllocator(other.linearAllocator) {}
|
||||
|
||||
T* allocate(size_t num, const void* = 0) {
|
||||
return (T*)(linearAllocator.alloc(num * sizeof(T)));
|
||||
return (T*)(linearAllocator.alloc<void*>(num * sizeof(T)));
|
||||
}
|
||||
|
||||
void deallocate(pointer p, size_t num) {
|
||||
@@ -187,6 +195,4 @@ public:
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
|
||||
void* operator new(std::size_t size, android::uirenderer::LinearAllocator& la);
|
||||
|
||||
#endif // ANDROID_LINEARALLOCATOR_H
|
||||
|
||||
Reference in New Issue
Block a user