diff options
author | 2016-02-11 00:36:34 +0000 | |
---|---|---|
committer | 2016-02-11 00:36:34 +0000 | |
commit | e537330ead4111cae74668bbc25a332e186d6c91 (patch) | |
tree | d73486362948e23296173ce418594bb654acea13 | |
parent | 499d83f21e7ffb687788bba1668b05fe38f6ebaf (diff) |
Revert "Fix all LA memory leaks forever!"
This reverts commit 499d83f21e7ffb687788bba1668b05fe38f6ebaf.
Change-Id: Ia893ae16ebbeae68e49cd13a20587104b73d39a0
-rw-r--r-- | libs/hwui/BakedOpState.h | 14 | ||||
-rw-r--r-- | libs/hwui/DamageAccumulator.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/DeferredDisplayList.h | 5 | ||||
-rw-r--r-- | libs/hwui/DisplayListCanvas.h | 5 | ||||
-rw-r--r-- | libs/hwui/DisplayListOp.h | 4 | ||||
-rw-r--r-- | libs/hwui/FrameBuilder.cpp | 18 | ||||
-rw-r--r-- | libs/hwui/LayerBuilder.cpp | 16 | ||||
-rw-r--r-- | libs/hwui/RecordingCanvas.cpp | 52 | ||||
-rw-r--r-- | libs/hwui/RecordingCanvas.h | 5 | ||||
-rw-r--r-- | libs/hwui/Snapshot.h | 4 | ||||
-rw-r--r-- | libs/hwui/tests/unit/LinearAllocatorTests.cpp | 13 | ||||
-rw-r--r-- | libs/hwui/utils/LinearAllocator.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/utils/LinearAllocator.h | 40 |
13 files changed, 100 insertions, 88 deletions
diff --git a/libs/hwui/BakedOpState.h b/libs/hwui/BakedOpState.h index 5a5845af81b9..3db28c982469 100644 --- a/libs/hwui/BakedOpState.h +++ b/libs/hwui/BakedOpState.h @@ -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 = 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 @@ public: ? (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 @@ public: 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 @@ public: 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 6d5833b3be86..c2e14a29f29e 100644 --- a/libs/hwui/DamageAccumulator.cpp +++ b/libs/hwui/DamageAccumulator.cpp @@ -45,7 +45,7 @@ struct DirtyStack { }; 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::computeCurrentTransform(Matrix4* outMatrix) const { 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 5c66b470381d..2d5979f2f1a7 100644 --- a/libs/hwui/DeferredDisplayList.h +++ b/libs/hwui/DeferredDisplayList.h @@ -50,6 +50,9 @@ 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; @@ -121,7 +124,7 @@ private: 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 a703e227fc8d..e5711e35a88b 100644 --- a/libs/hwui/DisplayListCanvas.h +++ b/libs/hwui/DisplayListCanvas.h @@ -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<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 @@ 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 = 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 98315d0a416a..20501ba3c1d9 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -64,9 +64,7 @@ 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) { - // 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 4f51036b336e..185accec1ef6 100644 --- a/libs/hwui/FrameBuilder.cpp +++ b/libs/hwui/FrameBuilder.cpp @@ -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 = 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 @@ 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(*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::deferBitmapRectOp(const BitmapRectOp& op) { 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 @@ 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 = mAllocator.create_trivial<OvalOp>( + const OvalOp* resolvedOp = new (mAllocator) 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 = 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 @@ 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 = mAllocator.create_trivial<LayerOp>( + LayerOp* drawLayerOp = new (mAllocator) 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 = 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 @@ 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 = 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 1ba3bf26c0d4..7170d4fbeea7 100644 --- a/libs/hwui/LayerBuilder.cpp +++ b/libs/hwui/LayerBuilder.cpp @@ -64,6 +64,10 @@ 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) { } @@ -76,6 +80,10 @@ 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) { @@ -239,7 +247,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<Vertex>(vertCount * sizeof(Vertex)); + Vertex* const verts = (Vertex*) allocator.alloc(vertCount * sizeof(Vertex)); Vertex* currentVert = verts; Rect bounds = mClearRects[0]; @@ -256,7 +264,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 = 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 @@ void LayerBuilder::deferUnmergeableOp(LinearAllocator& allocator, 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 @@ void LayerBuilder::deferMergeableOp(LinearAllocator& allocator, 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 269e590892d3..16929b8ac8ee 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -83,9 +83,9 @@ void RecordingCanvas::onViewportInitialized() { 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 @@ 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(alloc().create_trivial<BeginLayerOp>( + addOp(new (alloc()) 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(alloc().create_trivial<BeginUnclippedLayerOp>( + addOp(new (alloc()) 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(alloc().create_trivial<RectOp>( + addOp(new (alloc()) 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(alloc().create_trivial<PointsOp>( + addOp(new (alloc()) 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(alloc().create_trivial<LinesOp>( + addOp(new (alloc()) 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(alloc().create_trivial<RectOp>( + addOp(new (alloc()) 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<Vertex>(vertexCount * sizeof(Vertex)); + Vertex* rectData = (Vertex*) mDisplayList->allocator.alloc(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(alloc().create_trivial<SimpleRectsOp>( + addOp(new (alloc()) 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(alloc().create_trivial<RoundRectOp>( + addOp(new (alloc()) 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(alloc().create_trivial<RoundRectPropsOp>( + addOp(new (alloc()) 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(alloc().create_trivial<CirclePropsOp>( + addOp(new (alloc()) 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(alloc().create_trivial<OvalOp>( + addOp(new (alloc()) 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(alloc().create_trivial<ArcOp>( + addOp(new (alloc()) 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(alloc().create_trivial<PathOp>( + addOp(new (alloc()) 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(alloc().create_trivial<VectorDrawableOp>( + addOp(new (alloc()) 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(alloc().create_trivial<BitmapRectOp>( + addOp(new (alloc()) 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(alloc().create_trivial<BitmapMeshOp>( + addOp(new (alloc()) 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(alloc().create_trivial<PatchOp>( + addOp(new (alloc()) 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(alloc().create_trivial<TextOp>( + addOp(new (alloc()) 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(alloc().create_trivial<TextOnPathOp>( + addOp(new (alloc()) 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(alloc().create_trivial<BitmapOp>( + addOp(new (alloc()) 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 = alloc().create_trivial<RenderNodeOp>( + RenderNodeOp* op = new (alloc()) 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(alloc().create_trivial<TextureLayerOp>( + addOp(new (alloc()) 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(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 719872d35169..cc14e6111cec 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -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<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 @@ 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 = 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 0ac2f1411140..dbaa905b0728 100644 --- a/libs/hwui/Snapshot.h +++ b/libs/hwui/Snapshot.h @@ -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<RoundRectClipState>(size); + return allocator.alloc(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<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 402a09c55e8f..5c442901045e 100644 --- a/libs/hwui/tests/unit/LinearAllocatorTests.cpp +++ b/libs/hwui/tests/unit/LinearAllocatorTests.cpp @@ -30,7 +30,7 @@ struct SimplePair { 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 @@ TEST(LinearAllocator, dtor) { 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 @@ TEST(LinearAllocator, rewind) { 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 5bba420a258f..e6a4c03156b4 100644 --- a/libs/hwui/utils/LinearAllocator.cpp +++ b/libs/hwui/utils/LinearAllocator.cpp @@ -81,6 +81,10 @@ 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 { @@ -167,7 +171,7 @@ void LinearAllocator::ensureNext(size_t size) { 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 @@ 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 (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 0a0e1858cd91..dcbc0dda951a 100644 --- a/libs/hwui/utils/LinearAllocator.h +++ b/libs/hwui/utils/LinearAllocator.h @@ -52,36 +52,30 @@ 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. */ - 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 @@ private: 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 @@ public: : 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 @@ public: }; // namespace uirenderer }; // namespace android +void* operator new(std::size_t size, android::uirenderer::LinearAllocator& la); + #endif // ANDROID_LINEARALLOCATOR_H |