Revert "Fix all LA memory leaks forever!"
This reverts commit 499d83f21e7ffb687788bba1668b05fe38f6ebaf.
Change-Id: Ia893ae16ebbeae68e49cd13a20587104b73d39a0
diff --git a/libs/hwui/BakedOpState.h b/libs/hwui/BakedOpState.h
index 5a5845a..3db28c9 100644
--- a/libs/hwui/BakedOpState.h
+++ b/libs/hwui/BakedOpState.h
@@ -100,7 +100,7 @@
static BakedOpState* tryConstruct(LinearAllocator& allocator,
Snapshot& snapshot, const RecordedOp& recordedOp) {
if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
- BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
+ BakedOpState* bakedState = new (allocator) BakedOpState(
allocator, snapshot, recordedOp, false);
if (bakedState->computedState.clippedBounds.isEmpty()) {
// bounds are empty, so op is rejected
@@ -124,7 +124,7 @@
? (recordedOp.paint && recordedOp.paint->getStyle() != SkPaint::kFill_Style)
: true;
- BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
+ BakedOpState* bakedState = new (allocator) BakedOpState(
allocator, snapshot, recordedOp, expandForStroke);
if (bakedState->computedState.clippedBounds.isEmpty()) {
// bounds are empty, so op is rejected
@@ -140,12 +140,16 @@
if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
// clip isn't empty, so construct the op
- return allocator.create_trivial<BakedOpState>(allocator, snapshot, shadowOpPtr);
+ return new (allocator) BakedOpState(allocator, snapshot, shadowOpPtr);
}
static BakedOpState* directConstruct(LinearAllocator& allocator,
const ClipRect* clip, const Rect& dstRect, const RecordedOp& recordedOp) {
- return allocator.create_trivial<BakedOpState>(clip, dstRect, recordedOp);
+ return new (allocator) BakedOpState(clip, dstRect, recordedOp);
+ }
+
+ static void* operator new(size_t size, LinearAllocator& allocator) {
+ return allocator.alloc(size);
}
// computed state:
@@ -158,8 +162,6 @@
const RecordedOp* op;
private:
- friend class LinearAllocator;
-
BakedOpState(LinearAllocator& allocator, Snapshot& snapshot,
const RecordedOp& recordedOp, bool expandForStroke)
: computedState(allocator, snapshot, recordedOp, expandForStroke)
diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp
index 6d5833b..c2e14a2 100644
--- a/libs/hwui/DamageAccumulator.cpp
+++ b/libs/hwui/DamageAccumulator.cpp
@@ -45,7 +45,7 @@
};
DamageAccumulator::DamageAccumulator() {
- mHead = mAllocator.create_trivial<DirtyStack>();
+ mHead = (DirtyStack*) mAllocator.alloc(sizeof(DirtyStack));
memset(mHead, 0, sizeof(DirtyStack));
// Create a root that we will not pop off
mHead->prev = mHead;
@@ -78,7 +78,7 @@
void DamageAccumulator::pushCommon() {
if (!mHead->next) {
- DirtyStack* nextFrame = mAllocator.create_trivial<DirtyStack>();
+ DirtyStack* nextFrame = (DirtyStack*) mAllocator.alloc(sizeof(DirtyStack));
nextFrame->next = nullptr;
nextFrame->prev = mHead;
mHead->next = nextFrame;
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
index 5c66b47..2d5979f 100644
--- a/libs/hwui/DeferredDisplayList.h
+++ b/libs/hwui/DeferredDisplayList.h
@@ -50,6 +50,9 @@
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;
@@ -121,7 +124,7 @@
DeferredDisplayList(const DeferredDisplayList& other); // disallow copy
DeferredDisplayState* createState() {
- return mAllocator.create_trivial<DeferredDisplayState>();
+ return new (mAllocator) DeferredDisplayState();
}
void tryRecycleState(DeferredDisplayState* state) {
diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h
index a703e22..e5711e3 100644
--- a/libs/hwui/DisplayListCanvas.h
+++ b/libs/hwui/DisplayListCanvas.h
@@ -251,7 +251,7 @@
inline const T* refBuffer(const T* srcBuffer, int32_t count) {
if (!srcBuffer) return nullptr;
- T* dstBuffer = (T*) mDisplayList->allocator.alloc<T>(count * sizeof(T));
+ T* dstBuffer = (T*) mDisplayList->allocator.alloc(count * sizeof(T));
memcpy(dstBuffer, srcBuffer, count * sizeof(T));
return dstBuffer;
}
@@ -320,7 +320,8 @@
// 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 = alloc().create<SkBitmap>(bitmap);
+ SkBitmap* localBitmap = new (alloc()) SkBitmap(bitmap);
+ alloc().autoDestroy(localBitmap);
mDisplayList->bitmapResources.push_back(localBitmap);
return localBitmap;
}
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 98315d0a..20501ba 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -64,9 +64,7 @@
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) {
- // 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);
+ return allocator.alloc(size);
}
enum OpLogFlag {
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 4f51036..185acce 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -209,7 +209,7 @@
// not rejected, so defer render as either Layer, or direct (possibly wrapped in saveLayer)
if (node.getLayer()) {
// HW layer
- LayerOp* drawLayerOp = mAllocator.create_trivial<LayerOp>(node);
+ LayerOp* drawLayerOp = new (mAllocator) LayerOp(node);
BakedOpState* bakedOpState = tryBakeOpState(*drawLayerOp);
if (bakedOpState) {
// Node's layer already deferred, schedule it to render into parent layer
@@ -220,13 +220,13 @@
// (temp layers are clipped to viewport, since they don't persist offscreen content)
SkPaint saveLayerPaint;
saveLayerPaint.setAlpha(properties.getAlpha());
- deferBeginLayerOp(*mAllocator.create_trivial<BeginLayerOp>(
+ deferBeginLayerOp(*new (mAllocator) BeginLayerOp(
saveLayerBounds,
Matrix4::identity(),
nullptr, // no record-time clip - need only respect defer-time one
&saveLayerPaint));
deferNodeOps(node);
- deferEndLayerOp(*mAllocator.create_trivial<EndLayerOp>());
+ deferEndLayerOp(*new (mAllocator) EndLayerOp());
} else {
deferNodeOps(node);
}
@@ -549,7 +549,7 @@
void FrameBuilder::deferVectorDrawableOp(const VectorDrawableOp& op) {
const SkBitmap& bitmap = op.vectorDrawable->getBitmapUpdateIfDirty();
SkPaint* paint = op.vectorDrawable->getPaint();
- const BitmapRectOp* resolvedOp = mAllocator.create_trivial<BitmapRectOp>(op.unmappedBounds,
+ const BitmapRectOp* resolvedOp = new (mAllocator) BitmapRectOp(op.unmappedBounds,
op.localMatrix,
op.localClip,
paint,
@@ -565,7 +565,7 @@
float y = *(op.y);
float radius = *(op.radius);
Rect unmappedBounds(x - radius, y - radius, x + radius, y + radius);
- const OvalOp* resolvedOp = mAllocator.create_trivial<OvalOp>(
+ const OvalOp* resolvedOp = new (mAllocator) OvalOp(
unmappedBounds,
op.localMatrix,
op.localClip,
@@ -626,7 +626,7 @@
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 = mAllocator.create_trivial<RoundRectOp>(
+ const RoundRectOp* resolvedOp = new (mAllocator) RoundRectOp(
Rect(*(op.left), *(op.top), *(op.right), *(op.bottom)),
op.localMatrix,
op.localClip,
@@ -754,7 +754,7 @@
// 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 = mAllocator.create_trivial<LayerOp>(
+ LayerOp* drawLayerOp = new (mAllocator) LayerOp(
beginLayerOp.unmappedBounds,
beginLayerOp.localMatrix,
beginLayerOp.localClip,
@@ -788,7 +788,7 @@
/**
* First, defer an operation to copy out the content from the rendertarget into a layer.
*/
- auto copyToOp = mAllocator.create_trivial<CopyToLayerOp>(op, layerHandle);
+ auto copyToOp = new (mAllocator) CopyToLayerOp(op, layerHandle);
BakedOpState* bakedState = BakedOpState::directConstruct(mAllocator,
&(currentLayer().viewportClip), dstRect, *copyToOp);
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::CopyToLayer);
@@ -803,7 +803,7 @@
* And stash an operation to copy that layer back under the rendertarget until
* a balanced EndUnclippedLayerOp is seen
*/
- auto copyFromOp = mAllocator.create_trivial<CopyFromLayerOp>(op, layerHandle);
+ auto copyFromOp = new (mAllocator) CopyFromLayerOp(op, layerHandle);
bakedState = BakedOpState::directConstruct(mAllocator,
&(currentLayer().viewportClip), dstRect, *copyFromOp);
currentLayer().activeUnclippedSaveLayers.push_back(bakedState);
diff --git a/libs/hwui/LayerBuilder.cpp b/libs/hwui/LayerBuilder.cpp
index 1ba3bf2..7170d4f 100644
--- a/libs/hwui/LayerBuilder.cpp
+++ b/libs/hwui/LayerBuilder.cpp
@@ -64,6 +64,10 @@
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) {
}
@@ -76,6 +80,10 @@
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) {
@@ -239,7 +247,7 @@
// 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<Vertex>(vertCount * sizeof(Vertex));
+ Vertex* const verts = (Vertex*) allocator.alloc(vertCount * sizeof(Vertex));
Vertex* currentVert = verts;
Rect bounds = mClearRects[0];
@@ -256,7 +264,7 @@
// Flush all of these clears with a single draw
SkPaint* paint = allocator.create<SkPaint>();
paint->setXfermodeMode(SkXfermode::kClear_Mode);
- SimpleRectsOp* op = allocator.create_trivial<SimpleRectsOp>(bounds,
+ SimpleRectsOp* op = new (allocator) SimpleRectsOp(bounds,
Matrix4::identity(), nullptr, paint,
verts, vertCount);
BakedOpState* bakedState = BakedOpState::directConstruct(allocator,
@@ -284,7 +292,7 @@
targetBatch->batchOp(op);
} else {
// new non-merging batch
- targetBatch = allocator.create<OpBatch>(batchId, op);
+ targetBatch = new (allocator) OpBatch(batchId, op);
mBatchLookup[batchId] = targetBatch;
mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch);
}
@@ -315,7 +323,7 @@
targetBatch->mergeOp(op);
} else {
// new merging batch
- targetBatch = allocator.create<MergingOpBatch>(batchId, op);
+ targetBatch = new (allocator) MergingOpBatch(batchId, op);
mMergingBatchLookup[batchId].insert(std::make_pair(mergeId, targetBatch));
mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch);
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 269e590..16929b8 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -83,9 +83,9 @@
void RecordingCanvas::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {
if (removed.flags & Snapshot::kFlagIsFboLayer) {
- addOp(alloc().create_trivial<EndLayerOp>());
+ addOp(new (alloc()) EndLayerOp());
} else if (removed.flags & Snapshot::kFlagIsLayer) {
- addOp(alloc().create_trivial<EndUnclippedLayerOp>());
+ addOp(new (alloc()) EndUnclippedLayerOp());
}
}
@@ -167,7 +167,7 @@
snapshot.resetClip(clip.left, clip.top, clip.right, clip.bottom);
snapshot.roundRectClipState = nullptr;
- addOp(alloc().create_trivial<BeginLayerOp>(
+ addOp(new (alloc()) BeginLayerOp(
unmappedBounds,
*previous.transform, // transform to *draw* with
previousClip, // clip to *draw* with
@@ -175,7 +175,7 @@
} else {
snapshot.flags |= Snapshot::kFlagIsLayer;
- addOp(alloc().create_trivial<BeginUnclippedLayerOp>(
+ addOp(new (alloc()) BeginUnclippedLayerOp(
unmappedBounds,
*mState.currentSnapshot()->transform,
getRecordedClip(),
@@ -241,7 +241,7 @@
}
void RecordingCanvas::drawPaint(const SkPaint& paint) {
- addOp(alloc().create_trivial<RectOp>(
+ addOp(new (alloc()) RectOp(
mState.getRenderTargetClipBounds(), // OK, since we've not passed transform
Matrix4::identity(),
getRecordedClip(),
@@ -261,7 +261,7 @@
if (floatCount < 2) return;
floatCount &= ~0x1; // round down to nearest two
- addOp(alloc().create_trivial<PointsOp>(
+ addOp(new (alloc()) PointsOp(
calcBoundsOfPoints(points, floatCount),
*mState.currentSnapshot()->transform,
getRecordedClip(),
@@ -272,7 +272,7 @@
if (floatCount < 4) return;
floatCount &= ~0x3; // round down to nearest four
- addOp(alloc().create_trivial<LinesOp>(
+ addOp(new (alloc()) LinesOp(
calcBoundsOfPoints(points, floatCount),
*mState.currentSnapshot()->transform,
getRecordedClip(),
@@ -280,7 +280,7 @@
}
void RecordingCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
- addOp(alloc().create_trivial<RectOp>(
+ addOp(new (alloc()) RectOp(
Rect(left, top, right, bottom),
*(mState.currentSnapshot()->transform),
getRecordedClip(),
@@ -290,7 +290,7 @@
void RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint) {
if (rects == nullptr) return;
- Vertex* rectData = (Vertex*) mDisplayList->allocator.alloc<Vertex>(vertexCount * sizeof(Vertex));
+ Vertex* rectData = (Vertex*) mDisplayList->allocator.alloc(vertexCount * sizeof(Vertex));
Vertex* vertex = rectData;
float left = FLT_MAX;
@@ -313,7 +313,7 @@
right = std::max(right, r);
bottom = std::max(bottom, b);
}
- addOp(alloc().create_trivial<SimpleRectsOp>(
+ addOp(new (alloc()) SimpleRectsOp(
Rect(left, top, right, bottom),
*(mState.currentSnapshot()->transform),
getRecordedClip(),
@@ -347,7 +347,7 @@
}
void RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom,
float rx, float ry, const SkPaint& paint) {
- addOp(alloc().create_trivial<RoundRectOp>(
+ addOp(new (alloc()) RoundRectOp(
Rect(left, top, right, bottom),
*(mState.currentSnapshot()->transform),
getRecordedClip(),
@@ -367,7 +367,7 @@
mDisplayList->ref(ry);
mDisplayList->ref(paint);
refBitmapsInShader(paint->value.getShader());
- addOp(alloc().create_trivial<RoundRectPropsOp>(
+ addOp(new (alloc()) RoundRectPropsOp(
*(mState.currentSnapshot()->transform),
getRecordedClip(),
&paint->value,
@@ -389,7 +389,7 @@
mDisplayList->ref(radius);
mDisplayList->ref(paint);
refBitmapsInShader(paint->value.getShader());
- addOp(alloc().create_trivial<CirclePropsOp>(
+ addOp(new (alloc()) CirclePropsOp(
*(mState.currentSnapshot()->transform),
getRecordedClip(),
&paint->value,
@@ -397,7 +397,7 @@
}
void RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
- addOp(alloc().create_trivial<OvalOp>(
+ addOp(new (alloc()) OvalOp(
Rect(left, top, right, bottom),
*(mState.currentSnapshot()->transform),
getRecordedClip(),
@@ -406,7 +406,7 @@
void RecordingCanvas::drawArc(float left, float top, float right, float bottom,
float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
- addOp(alloc().create_trivial<ArcOp>(
+ addOp(new (alloc()) ArcOp(
Rect(left, top, right, bottom),
*(mState.currentSnapshot()->transform),
getRecordedClip(),
@@ -415,7 +415,7 @@
}
void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
- addOp(alloc().create_trivial<PathOp>(
+ addOp(new (alloc()) PathOp(
Rect(path.getBounds()),
*(mState.currentSnapshot()->transform),
getRecordedClip(),
@@ -424,7 +424,7 @@
void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
mDisplayList->ref(tree);
- addOp(alloc().create_trivial<VectorDrawableOp>(
+ addOp(new (alloc()) VectorDrawableOp(
tree,
Rect(tree->getBounds()),
*(mState.currentSnapshot()->transform),
@@ -475,7 +475,7 @@
drawBitmap(&bitmap, paint);
restore();
} else {
- addOp(alloc().create_trivial<BitmapRectOp>(
+ addOp(new (alloc()) BitmapRectOp(
Rect(dstLeft, dstTop, dstRight, dstBottom),
*(mState.currentSnapshot()->transform),
getRecordedClip(),
@@ -487,7 +487,7 @@
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(alloc().create_trivial<BitmapMeshOp>(
+ addOp(new (alloc()) BitmapMeshOp(
calcBoundsOfPoints(vertices, vertexCount * 2),
*(mState.currentSnapshot()->transform),
getRecordedClip(),
@@ -499,7 +499,7 @@
void RecordingCanvas::drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& patch,
float dstLeft, float dstTop, float dstRight, float dstBottom,
const SkPaint* paint) {
- addOp(alloc().create_trivial<PatchOp>(
+ addOp(new (alloc()) PatchOp(
Rect(dstLeft, dstTop, dstRight, dstBottom),
*(mState.currentSnapshot()->transform),
getRecordedClip(),
@@ -515,7 +515,7 @@
positions = refBuffer<float>(positions, glyphCount * 2);
// TODO: either must account for text shadow in bounds, or record separate ops for text shadows
- addOp(alloc().create_trivial<TextOp>(
+ addOp(new (alloc()) TextOp(
Rect(boundsLeft, boundsTop, boundsRight, boundsBottom),
*(mState.currentSnapshot()->transform),
getRecordedClip(),
@@ -527,7 +527,7 @@
float hOffset, float vOffset, const SkPaint& paint) {
if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
glyphs = refBuffer<glyph_t>(glyphs, glyphCount);
- addOp(alloc().create_trivial<TextOnPathOp>(
+ addOp(new (alloc()) TextOnPathOp(
mState.getLocalClipBounds(), // TODO: explicitly define bounds
*(mState.currentSnapshot()->transform),
getRecordedClip(),
@@ -535,7 +535,7 @@
}
void RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
- addOp(alloc().create_trivial<BitmapOp>(
+ addOp(new (alloc()) BitmapOp(
Rect(bitmap->width(), bitmap->height()),
*(mState.currentSnapshot()->transform),
getRecordedClip(),
@@ -544,7 +544,7 @@
void RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
auto&& stagingProps = renderNode->stagingProperties();
- RenderNodeOp* op = alloc().create_trivial<RenderNodeOp>(
+ RenderNodeOp* op = new (alloc()) RenderNodeOp(
Rect(stagingProps.getWidth(), stagingProps.getHeight()),
*(mState.currentSnapshot()->transform),
getRecordedClip(),
@@ -570,7 +570,7 @@
Matrix4 totalTransform(*(mState.currentSnapshot()->transform));
totalTransform.multiply(layer->getTransform());
- addOp(alloc().create_trivial<TextureLayerOp>(
+ addOp(new (alloc()) TextureLayerOp(
Rect(layer->getWidth(), layer->getHeight()),
totalTransform,
getRecordedClip(),
@@ -579,7 +579,7 @@
void RecordingCanvas::callDrawGLFunction(Functor* functor) {
mDisplayList->functors.push_back(functor);
- addOp(alloc().create_trivial<FunctorOp>(
+ addOp(new (alloc()) FunctorOp(
mState.getLocalClipBounds(), // TODO: explicitly define bounds
*(mState.currentSnapshot()->transform),
getRecordedClip(),
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 719872d..cc14e61 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -219,7 +219,7 @@
inline const T* refBuffer(const T* srcBuffer, int32_t count) {
if (!srcBuffer) return nullptr;
- T* dstBuffer = (T*) mDisplayList->allocator.alloc<T>(count * sizeof(T));
+ T* dstBuffer = (T*) mDisplayList->allocator.alloc(count * sizeof(T));
memcpy(dstBuffer, srcBuffer, count * sizeof(T));
return dstBuffer;
}
@@ -290,7 +290,8 @@
// 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 = alloc().create<SkBitmap>(bitmap);
+ SkBitmap* localBitmap = new (alloc()) SkBitmap(bitmap);
+ alloc().autoDestroy(localBitmap);
mDisplayList->bitmapResources.push_back(localBitmap);
return localBitmap;
}
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 0ac2f14..dbaa905 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -46,7 +46,7 @@
public:
/** static void* operator new(size_t size); PURPOSELY OMITTED, allocator only **/
static void* operator new(size_t size, LinearAllocator& allocator) {
- return allocator.alloc<RoundRectClipState>(size);
+ return allocator.alloc(size);
}
bool areaRequiresRoundRectClip(const Rect& rect) const {
@@ -67,7 +67,7 @@
public:
/** static void* operator new(size_t size); PURPOSELY OMITTED, allocator only **/
static void* operator new(size_t size, LinearAllocator& allocator) {
- return allocator.alloc<ProjectionPathMask>(size);
+ return allocator.alloc(size);
}
const SkPath* projectionMask;
diff --git a/libs/hwui/tests/unit/LinearAllocatorTests.cpp b/libs/hwui/tests/unit/LinearAllocatorTests.cpp
index 402a09c..5c4429010 100644
--- a/libs/hwui/tests/unit/LinearAllocatorTests.cpp
+++ b/libs/hwui/tests/unit/LinearAllocatorTests.cpp
@@ -30,7 +30,7 @@
TEST(LinearAllocator, create) {
LinearAllocator la;
EXPECT_EQ(0u, la.usedSize());
- la.alloc<char>(64);
+ la.alloc(64);
// There's some internal tracking as well as padding
// so the usedSize isn't strictly defined
EXPECT_LE(64u, la.usedSize());
@@ -50,12 +50,13 @@
la.create<TestUtils::SignalingDtor>()->setSignal(destroyed + i);
la.create<SimplePair>();
}
- la.alloc<char>(100);
+ la.alloc(100);
for (int i = 0; i < 5; i++) {
- la.create<TestUtils::SignalingDtor>(destroyed + 5 + i);
- la.create_trivial<SimplePair>();
+ auto sd = new (la) TestUtils::SignalingDtor(destroyed + 5 + i);
+ la.autoDestroy(sd);
+ new (la) SimplePair();
}
- la.alloc<char>(100);
+ la.alloc(100);
for (int i = 0; i < 10; i++) {
EXPECT_EQ(0, destroyed[i]);
}
@@ -69,7 +70,7 @@
int destroyed = 0;
{
LinearAllocator la;
- auto addr = la.alloc<char>(100);
+ auto addr = la.alloc(100);
EXPECT_LE(100u, la.usedSize());
la.rewindIfLastAlloc(addr, 100);
EXPECT_GT(16u, la.usedSize());
diff --git a/libs/hwui/utils/LinearAllocator.cpp b/libs/hwui/utils/LinearAllocator.cpp
index 5bba420..e6a4c03 100644
--- a/libs/hwui/utils/LinearAllocator.cpp
+++ b/libs/hwui/utils/LinearAllocator.cpp
@@ -81,6 +81,10 @@
#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 {
@@ -167,7 +171,7 @@
mNext = start(mCurrentPage);
}
-void* LinearAllocator::allocImpl(size_t size) {
+void* LinearAllocator::alloc(size_t size) {
size = ALIGN(size);
if (size > mMaxAllocSize && !fitsInCurrentPage(size)) {
ALOGV("Exceeded max size %zu > %zu", size, mMaxAllocSize);
@@ -192,7 +196,7 @@
"DestructorNode must have standard layout");
static_assert(std::is_trivially_destructible<DestructorNode>::value,
"DestructorNode must be trivially destructable");
- auto node = new (allocImpl(sizeof(DestructorNode))) DestructorNode();
+ auto node = new (*this) DestructorNode();
node->dtor = dtor;
node->addr = addr;
node->next = mDtorList;
diff --git a/libs/hwui/utils/LinearAllocator.h b/libs/hwui/utils/LinearAllocator.h
index 0a0e185..dcbc0dd 100644
--- a/libs/hwui/utils/LinearAllocator.h
+++ b/libs/hwui/utils/LinearAllocator.h
@@ -52,36 +52,30 @@
* 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.
*/
- 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);
- }
+ void* alloc(size_t 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 (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);
- }
+ T* create(Params... params) {
+ T* ret = new (*this) T(params...);
+ autoDestroy(ret);
return ret;
}
- 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)...);
+ /**
+ * 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);
+ }
}
/**
@@ -120,8 +114,6 @@
DestructorNode* next = nullptr;
};
- void* allocImpl(size_t size);
-
void addToDestructionList(Destructor, void* addr);
void runDestructorFor(void* addr);
Page* newPage(size_t pageSize);
@@ -167,7 +159,7 @@
: linearAllocator(other.linearAllocator) {}
T* allocate(size_t num, const void* = 0) {
- return (T*)(linearAllocator.alloc<void*>(num * sizeof(T)));
+ return (T*)(linearAllocator.alloc(num * sizeof(T)));
}
void deallocate(pointer p, size_t num) {
@@ -195,4 +187,6 @@
}; // namespace uirenderer
}; // namespace android
+void* operator new(std::size_t size, android::uirenderer::LinearAllocator& la);
+
#endif // ANDROID_LINEARALLOCATOR_H