summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp49
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h9
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp56
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h3
-rw-r--r--Source/WebCore/platform/graphics/android/context/RTree.cpp17
-rw-r--r--Source/WebCore/platform/graphics/android/context/RTree.h8
-rw-r--r--Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp15
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp10
-rw-r--r--Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp108
-rw-r--r--Source/WebCore/platform/graphics/android/utils/LinearAllocator.h17
-rw-r--r--Source/WebKit/android/jni/PicturePile.cpp38
-rw-r--r--Source/WebKit/android/jni/PicturePile.h2
-rw-r--r--Tools/android/webkitmerge/Android.mk2
13 files changed, 179 insertions, 155 deletions
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
index 7f4352b..9cb81e6 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -116,7 +116,6 @@ GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
static_cast<HTMLCanvasElement*>(renderLayer->renderer()->node()));
} else
m_contentLayer = new LayerAndroid(renderLayer);
- m_dirtyRegion.setEmpty();
gDebugGraphicsLayerAndroidInstances++;
}
@@ -695,7 +694,7 @@ bool GraphicsLayerAndroid::repaint()
PaintingPhase phase(this);
// Paint the background into a separate context.
phase.set(GraphicsLayerPaintBackground);
- if (!paintContext(m_contentLayer, layerBounds))
+ if (!paintContext(m_contentLayer, m_contentLayerContent))
return false;
// Construct the foreground layer and draw.
@@ -712,11 +711,17 @@ bool GraphicsLayerAndroid::repaint()
// Paint everything else into the main recording canvas.
phase.clear(GraphicsLayerPaintBackground);
+ // Invalidate the entire layer for now, as webkit will only send the
+ // setNeedsDisplayInRect() for the visible (clipped) scrollable area,
+ // offsetting the invals by the scroll position would not be enough.
+ // TODO: have webkit send us invals even for non visible area
+ m_foregroundLayerContent.invalidate(IntRect(0, 0, contentsRect.width(), contentsRect.height()));
+
// Paint at 0,0.
IntSize scroll = layer->scrolledContentOffset();
layer->scrollToOffset(0, 0);
// At this point, it doesn't matter if painting failed.
- (void) paintContext(m_foregroundLayer, contentsRect);
+ (void) paintContext(m_foregroundLayer, m_foregroundLayerContent);
layer->scrollToOffset(scroll.width(), scroll.height());
// Construct the clip layer for masking the contents.
@@ -741,13 +746,8 @@ bool GraphicsLayerAndroid::repaint()
// Set the scrollable bounds of the layer.
setScrollLimits(static_cast<ScrollableLayerAndroid*>(m_foregroundLayer), layer);
- // Invalidate the entire layer for now, as webkit will only send the
- // setNeedsDisplayInRect() for the visible (clipped) scrollable area,
- // offsetting the invals by the scroll position would not be enough.
- // TODO: have webkit send us invals even for non visible area
- SkRegion region;
- region.setRect(0, 0, contentsRect.width(), contentsRect.height());
- m_foregroundLayer->markAsDirty(region);
+ m_foregroundLayer->markAsDirty(m_foregroundLayerContent.dirtyRegion());
+ m_foregroundLayerContent.dirtyRegion().setEmpty();
} else if (m_contentLayer->isFixedBackground()) {
SkPicture* picture = new SkPicture();
SkCanvas* canvas = picture->beginRecording(layerBounds.width(),
@@ -784,13 +784,13 @@ bool GraphicsLayerAndroid::repaint()
GraphicsLayerAndroid* replicatedLayer = static_cast<GraphicsLayerAndroid*>(replicaLayer());
if (replicatedLayer->maskLayer()) {
GraphicsLayerAndroid* mask = static_cast<GraphicsLayerAndroid*>(replicatedLayer->maskLayer());
- mask->paintContext(mask->m_contentLayer, layerBounds, false);
+ mask->paintContext(mask->m_contentLayer, m_contentLayerContent);
}
}
// If there is no contents clip, we can draw everything into one
// picture.
- bool painting = paintContext(m_contentLayer, layerBounds);
+ bool painting = paintContext(m_contentLayer, m_contentLayerContent);
if (!painting)
return false;
// Check for a scrollable iframe and report the scrolling
@@ -811,8 +811,8 @@ bool GraphicsLayerAndroid::repaint()
m_contentLayer->getSize().width(),
m_contentLayer->getSize().height());
- m_contentLayer->markAsDirty(m_dirtyRegion);
- m_dirtyRegion.setEmpty();
+ m_contentLayer->markAsDirty(m_contentLayerContent.dirtyRegion());
+ m_contentLayerContent.dirtyRegion().setEmpty();
m_needsRepaint = false;
return true;
@@ -820,8 +820,8 @@ bool GraphicsLayerAndroid::repaint()
if (m_needsRepaint && m_image && m_newImage) {
// We need to tell the GL thread that we will need to repaint the
// texture. Only do so if we effectively have a new image!
- m_contentLayer->markAsDirty(m_dirtyRegion);
- m_dirtyRegion.setEmpty();
+ m_contentLayer->markAsDirty(m_contentLayerContent.dirtyRegion());
+ m_contentLayerContent.dirtyRegion().setEmpty();
m_newImage = false;
m_needsRepaint = false;
return true;
@@ -835,19 +835,14 @@ void GraphicsLayerAndroid::paintContents(GraphicsContext* gc, IntRect& dirty)
}
bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer,
- const IntRect& rect,
- bool checkOptimisations)
+ PicturePile& picture)
{
if (!layer)
return false;
TRACE_METHOD();
- // TODO: we might be able to reuse an existing picture instead of recreating it.
- // we can't do that because of transparency -- for now, we just create
- // a new picture every time.
- WebCore::PicturePile picture;
- picture.setSize(IntSize(rect.width(), rect.height()));
+ picture.setSize(IntSize(layer->getWidth(), layer->getHeight()));
// TODO: add content checks (text, opacity, etc.)
picture.updatePicturesIfNeeded(this);
@@ -870,11 +865,9 @@ void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
return;
}
- SkRegion region;
- region.setRect(rect.x(), rect.y(),
- rect.x() + rect.width(),
- rect.y() + rect.height());
- m_dirtyRegion.op(region, SkRegion::kUnion_Op);
+ m_contentLayerContent.invalidate(enclosingIntRect(rect));
+ if (m_foregroundLayer)
+ m_foregroundLayerContent.invalidate(enclosingIntRect(rect));
m_needsRepaint = true;
askForSync();
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
index b40459d..28d4b09 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
@@ -154,9 +154,7 @@ private:
bool repaint();
void needsNotifyClient();
- bool paintContext(LayerAndroid* layer,
- const IntRect& rect,
- bool checkOptimisations = true);
+ bool paintContext(LayerAndroid* layer, PicturePile& picture);
bool m_needsSyncChildren;
bool m_needsSyncMask;
@@ -167,12 +165,13 @@ private:
bool m_newImage;
Image* m_image;
- SkRegion m_dirtyRegion;
-
LayerAndroid* m_contentLayer;
FixedBackgroundImageLayerAndroid* m_fixedBackgroundLayer;
LayerAndroid* m_foregroundLayer;
LayerAndroid* m_foregroundClipLayer;
+
+ PicturePile m_contentLayerContent;
+ PicturePile m_foregroundLayerContent;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp
index 464224a..2a7db11 100644
--- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp
+++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp
@@ -43,7 +43,7 @@
#include "wtf/HashSet.h"
#include "wtf/StringHasher.h"
-#define NEW_OP(X) new (operationHeap()) GraphicsOperation::X
+#define NEW_OP(X) new (heap()) GraphicsOperation::X
#define USE_CLIPPING_PAINTER true
@@ -133,7 +133,7 @@ public:
~CanvasState() {
ALOGV("Delete %p", this);
for (size_t i = 0; i < m_operations.size(); i++)
- delete m_operations[i];
+ m_operations[i]->~RecordingData();
m_operations.clear();
}
@@ -202,15 +202,10 @@ private:
// Careful, ordering matters here. Ordering is first constructed == last destroyed,
// so we have to make sure our Heap is the first thing listed so that it is
// the last thing destroyed.
- LinearAllocator m_operationHeap;
- LinearAllocator m_canvasStateHeap;
- // Used by both PlatformGraphicsContext::State and SkPaint, as both are
- // roughly the same size (72 bytes vs. 76 bytes, respectively)
- LinearAllocator m_stateHeap;
+ LinearAllocator m_heap;
public:
RecordingImpl()
- : m_canvasStateHeap(sizeof(CanvasState))
- , m_stateHeap(sizeof(SkPaint))
+ : m_tree(&m_heap)
, m_nodeCount(0)
{
}
@@ -225,7 +220,7 @@ public:
StateHashSet::iterator it = m_states.find(inState);
if (it != m_states.end())
return (*it);
- void* buf = m_stateHeap.alloc(sizeof(PlatformGraphicsContext::State));
+ void* buf = heap()->alloc(sizeof(PlatformGraphicsContext::State));
PlatformGraphicsContext::State* state = new (buf) PlatformGraphicsContext::State(*inState);
m_states.add(state);
return state;
@@ -235,7 +230,7 @@ public:
SkPaintHashSet::iterator it = m_paints.find(&inPaint);
if (it != m_paints.end())
return (*it);
- void* buf = m_stateHeap.alloc(sizeof(SkPaint));
+ void* buf = heap()->alloc(sizeof(SkPaint));
SkPaint* paint = new (buf) SkPaint(inPaint);
m_paints.add(paint);
return paint;
@@ -284,12 +279,17 @@ public:
toState->playback(context, fromId, toId);
}
- LinearAllocator* operationHeap() { return &m_operationHeap; }
- LinearAllocator* canvasStateHeap() { return &m_canvasStateHeap; }
+ LinearAllocator* heap() { return &m_heap; }
RTree::RTree m_tree;
int m_nodeCount;
+ void dumpMemoryStats() {
+ static const char* PREFIX = " ";
+ ALOGD("Heap:");
+ m_heap.dumpMemoryStats(PREFIX);
+ }
+
private:
void clearStates() {
@@ -495,12 +495,14 @@ PlatformGraphicsContextRecording::PlatformGraphicsContextRecording(Recording* re
mRecording->setRecording(new RecordingImpl());
mMatrixStack.append(SkMatrix::I());
mCurrentMatrix = &(mMatrixStack.last());
- pushStateOperation(new (canvasStateHeap()) CanvasState(0));
+ pushStateOperation(new (heap()) CanvasState(0));
}
PlatformGraphicsContextRecording::~PlatformGraphicsContextRecording()
{
ALOGV("RECORDING: end");
+ IF_ALOGV()
+ mRecording->recording()->dumpMemoryStats();
}
bool PlatformGraphicsContextRecording::isPaintingDisabled()
@@ -521,7 +523,7 @@ SkCanvas* PlatformGraphicsContextRecording::recordingCanvas()
void PlatformGraphicsContextRecording::beginTransparencyLayer(float opacity)
{
CanvasState* parent = mRecordingStateStack.last().mCanvasState;
- pushStateOperation(new (canvasStateHeap()) CanvasState(parent, opacity));
+ pushStateOperation(new (heap()) CanvasState(parent, opacity));
}
void PlatformGraphicsContextRecording::endTransparencyLayer()
@@ -533,7 +535,7 @@ void PlatformGraphicsContextRecording::save()
{
PlatformGraphicsContext::save();
CanvasState* parent = mRecordingStateStack.last().mCanvasState;
- pushStateOperation(new (canvasStateHeap()) CanvasState(parent));
+ pushStateOperation(new (heap()) CanvasState(parent));
pushMatrix();
}
@@ -900,9 +902,9 @@ void PlatformGraphicsContextRecording::drawPosText(const void* inText, size_t by
}
FloatRect bounds = approximateTextBounds(byteLength / sizeof(uint16_t), inPos, inPaint);
const SkPaint* paint = mRecording->recording()->getSkPaint(inPaint);
- int posSize = sizeof(SkPoint) * paint->countText(inText, byteLength);
- void* text = operationHeap()->alloc(posSize + byteLength);
- SkPoint* pos = (SkPoint*) ((char*)text + byteLength);
+ size_t posSize = sizeof(SkPoint) * paint->countText(inText, byteLength);
+ void* text = heap()->alloc(byteLength);
+ SkPoint* pos = (SkPoint*) heap()->alloc(posSize);
memcpy(text, inText, byteLength);
memcpy(pos, inPos, posSize);
appendDrawingOperation(NEW_OP(DrawPosText)(text, byteLength, pos, paint), bounds);
@@ -942,7 +944,7 @@ void PlatformGraphicsContextRecording::popStateOperation()
state.mCanvasState, state.mCanvasState->isTransparencyLayer());
mRecording->recording()->removeCanvasState(state.mCanvasState);
state.mCanvasState->~CanvasState();
- canvasStateHeap()->rewindTo(state.mCanvasState);
+ heap()->rewindIfLastAlloc(state.mCanvasState, sizeof(CanvasState));
} else {
ALOGV("RECORDING: popStateOperation: %p(isLayer=%d)",
state.mCanvasState, state.mCanvasState->isTransparencyLayer());
@@ -1025,7 +1027,6 @@ void PlatformGraphicsContextRecording::appendDrawingOperation(
if (ibounds.isEmpty()) {
ALOGV("RECORDING: Operation %s() was clipped out", operation->name());
operation->~Operation();
- operationHeap()->rewindTo(operation);
return;
}
if (operation->isOpaque()
@@ -1038,25 +1039,20 @@ void PlatformGraphicsContextRecording::appendDrawingOperation(
}
ALOGV("RECORDING: appendOperation %p->%s() bounds " INT_RECT_FORMAT, operation, operation->name(),
INT_RECT_ARGS(ibounds));
- RecordingData* data = new RecordingData(operation, mRecording->recording()->m_nodeCount++);
+ RecordingData* data = new (heap()) RecordingData(operation, mRecording->recording()->m_nodeCount++);
mRecording->recording()->m_tree.insert(ibounds, data);
}
void PlatformGraphicsContextRecording::appendStateOperation(GraphicsOperation::Operation* operation)
{
ALOGV("RECORDING: appendOperation %p->%s()", operation, operation->name());
- RecordingData* data = new RecordingData(operation, mRecording->recording()->m_nodeCount++);
+ RecordingData* data = new (heap()) RecordingData(operation, mRecording->recording()->m_nodeCount++);
mRecordingStateStack.last().mCanvasState->adoptAndAppend(data);
}
-LinearAllocator* PlatformGraphicsContextRecording::operationHeap()
-{
- return mRecording->recording()->operationHeap();
-}
-
-LinearAllocator* PlatformGraphicsContextRecording::canvasStateHeap()
+LinearAllocator* PlatformGraphicsContextRecording::heap()
{
- return mRecording->recording()->canvasStateHeap();
+ return mRecording->recording()->heap();
}
} // WebCore
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h
index d62eb8a..b1018e7 100644
--- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h
+++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h
@@ -160,8 +160,7 @@ private:
void popMatrix();
IntRect calculateFinalBounds(FloatRect bounds);
IntRect calculateCoveredBounds(FloatRect bounds);
- LinearAllocator* operationHeap();
- LinearAllocator* canvasStateHeap();
+ LinearAllocator* heap();
SkPicture* mPicture;
SkMatrix* mCurrentMatrix;
diff --git a/Source/WebCore/platform/graphics/android/context/RTree.cpp b/Source/WebCore/platform/graphics/android/context/RTree.cpp
index fa048b7..2e24c34 100644
--- a/Source/WebCore/platform/graphics/android/context/RTree.cpp
+++ b/Source/WebCore/platform/graphics/android/context/RTree.cpp
@@ -33,6 +33,15 @@
#include "AndroidLog.h"
#include "LinearAllocator.h"
+namespace WebCore {
+
+void* RecordingData::operator new(size_t size, LinearAllocator* allocator)
+{
+ return allocator->alloc(size);
+}
+
+}
+
namespace RTree {
#ifdef DEBUG
@@ -123,12 +132,12 @@ int computeDeltaArea(Node* node, int& minx, int& miny,
//
//////////////////////////////////////////////////////////////////////
-RTree::RTree(int M)
+RTree::RTree(WebCore::LinearAllocator* allocator, int M)
+ : m_allocator(allocator)
{
m_maxChildren = M;
m_listA = new ElementList(M);
m_listB = new ElementList(M);
- m_allocator = new WebCore::LinearAllocator(sizeof(Node));
m_root = Node::create(this);
}
@@ -137,7 +146,6 @@ RTree::~RTree()
delete m_listA;
delete m_listB;
deleteNode(m_root);
- delete m_allocator;
}
void RTree::insert(WebCore::IntRect& bounds, WebCore::RecordingData* payload)
@@ -263,7 +271,8 @@ Node::~Node()
for (unsigned i = 0; i < m_nbChildren; i++)
m_tree->deleteNode(m_children[i]);
delete[] m_children;
- delete m_payload;
+ if (m_payload)
+ m_payload->~RecordingData();
}
void Node::setParent(Node* node)
diff --git a/Source/WebCore/platform/graphics/android/context/RTree.h b/Source/WebCore/platform/graphics/android/context/RTree.h
index 366e3d1..50962ef 100644
--- a/Source/WebCore/platform/graphics/android/context/RTree.h
+++ b/Source/WebCore/platform/graphics/android/context/RTree.h
@@ -46,6 +46,12 @@ public:
size_t m_orderBy;
GraphicsOperation::Operation* m_operation;
+
+ void* operator new(size_t size, LinearAllocator* allocator);
+
+ // Purposely not implemented - use a LinearAllocator please
+ void* operator new(size_t size);
+ void operator delete(void* ptr);
};
} // namespace WebCore
@@ -58,7 +64,7 @@ class Node;
class RTree {
public:
// M -- max number of children per node
- RTree(int M = 10);
+ RTree(WebCore::LinearAllocator* allocator, int M = 10);
~RTree();
void insert(WebCore::IntRect& bounds, WebCore::RecordingData* payload);
diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp
index 67d1259..84ce910 100644
--- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp
@@ -803,13 +803,14 @@ bool LayerAndroid::drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle st
r.set(m_clippingRect.x(), m_clippingRect.y(),
m_clippingRect.x() + m_clippingRect.width(),
m_clippingRect.y() + m_clippingRect.height());
- canvas->clipRect(r);
- SkMatrix matrix;
- GLUtils::toSkMatrix(matrix, m_drawTransform);
- SkMatrix canvasMatrix = canvas->getTotalMatrix();
- matrix.postConcat(canvasMatrix);
- canvas->setMatrix(matrix);
- onDraw(canvas, m_drawOpacity, 0, style);
+ if (canvas->clipRect(r)) {
+ SkMatrix matrix;
+ GLUtils::toSkMatrix(matrix, m_drawTransform);
+ SkMatrix canvasMatrix = canvas->getTotalMatrix();
+ matrix.postConcat(canvasMatrix);
+ canvas->setMatrix(matrix);
+ onDraw(canvas, m_drawOpacity, 0, style);
+ }
}
if (!drawChildren)
diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp
index e584b81..aa18898 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp
@@ -57,7 +57,7 @@
// number to cap the layer tile texturs, it worked on both phones and tablets.
// TODO: after merge the pool of base tiles and layer tiles, we should revisit
// the logic of allocation management.
-#define MAX_TEXTURE_ALLOCATION ((6+TILE_PREFETCH_DISTANCE*2)*(5+TILE_PREFETCH_DISTANCE*2)*4)
+#define MAX_TEXTURE_ALLOCATION ((10+TILE_PREFETCH_DISTANCE*2)*(7+TILE_PREFETCH_DISTANCE*2)*4)
#define TILE_WIDTH 256
#define TILE_HEIGHT 256
@@ -105,10 +105,10 @@ TilesManager::TilesManager()
, m_eglContext(EGL_NO_CONTEXT)
{
ALOGV("TilesManager ctor");
- m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
- m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
- m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
- m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
+ m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2);
+ m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2);
+ m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2);
+ m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2);
m_textureGenerators = new sp<TexturesGenerator>[NUM_TEXTURES_GENERATORS];
for (int i = 0; i < NUM_TEXTURES_GENERATORS; i++) {
diff --git a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp
index 8aa1616..b945944 100644
--- a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp
+++ b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp
@@ -33,17 +33,16 @@
namespace WebCore {
-// The ideal size of a page allocation
-#define TARGET_PAGE_SIZE 16384 // 16kb
-
-// our pool needs to big enough to hold at least this many items
-#define MIN_OBJECT_COUNT 4
+// The ideal size of a page allocation (these need to be multiples of 4)
+#define INITIAL_PAGE_SIZE ((size_t)4096) // 4kb
+#define MAX_PAGE_SIZE ((size_t)131072) // 128kb
// The maximum amount of wasted space we can have per page
// Allocations exceeding this will have their own dedicated page
// If this is too low, we will malloc too much
// Too high, and we may waste too much space
-#define MAX_WASTE_SIZE ((size_t)256)
+// Must be smaller than INITIAL_PAGE_SIZE
+#define MAX_WASTE_SIZE ((size_t)1024)
#define ALIGN(x) (x + (x % sizeof(int)))
@@ -98,21 +97,17 @@ private:
Page* m_nextPage;
};
-LinearAllocator::LinearAllocator(size_t averageAllocSize)
- : m_next(0)
+LinearAllocator::LinearAllocator()
+ : m_pageSize(INITIAL_PAGE_SIZE)
+ , m_maxAllocSize(MAX_WASTE_SIZE)
+ , m_next(0)
, m_currentPage(0)
, m_pages(0)
+ , m_totalAllocated(0)
+ , m_wastedSpace(0)
+ , m_pageCount(0)
+ , m_dedicatedPageCount(0)
{
- if (averageAllocSize) {
- int usable_page_size = TARGET_PAGE_SIZE - sizeof(LinearAllocator::Page);
- int pcount = usable_page_size / averageAllocSize;
- if (pcount < MIN_OBJECT_COUNT)
- pcount = MIN_OBJECT_COUNT;
- m_pageSize = pcount * averageAllocSize + sizeof(LinearAllocator::Page);
- } else
- m_pageSize = TARGET_PAGE_SIZE;
- m_pageSize = ALIGN(m_pageSize);
- m_maxAllocSize = std::min(MAX_WASTE_SIZE, (m_pageSize - sizeof(LinearAllocator::Page)));
}
LinearAllocator::~LinearAllocator(void)
@@ -136,11 +131,21 @@ void* LinearAllocator::end(Page* p)
return ((char*)p) + m_pageSize;
}
+bool LinearAllocator::fitsInCurrentPage(size_t size)
+{
+ return m_next && ((char*)m_next + size) <= end(m_currentPage);
+}
+
void LinearAllocator::ensureNext(size_t size)
{
- if (m_next && ((char*)m_next + size) <= end(m_currentPage))
+ if (fitsInCurrentPage(size))
return;
- Page* p = newPage();
+ if (m_currentPage && m_pageSize < MAX_PAGE_SIZE) {
+ m_pageSize = std::min(MAX_PAGE_SIZE, m_pageSize * 2);
+ m_pageSize = ALIGN(m_pageSize);
+ }
+ m_wastedSpace += m_pageSize;
+ Page* p = newPage(m_pageSize);
if (m_currentPage)
m_currentPage->setNext(p);
m_currentPage = p;
@@ -149,25 +154,14 @@ void LinearAllocator::ensureNext(size_t size)
m_next = start(m_currentPage);
}
-unsigned LinearAllocator::memusage()
-{
- unsigned memusage = 0;
- Page* p = m_pages;
- while (p) {
- memusage += m_pageSize;
- p = p->next();
- }
- return memusage;
-}
-
void* LinearAllocator::alloc(size_t size)
{
size = ALIGN(size);
- if (size > m_maxAllocSize) {
+ if (size > m_maxAllocSize && !fitsInCurrentPage(size)) {
+ ALOGV("Exceeded max size %d > %d", size, m_maxAllocSize);
// Allocation is too large, create a dedicated page for the allocation
- ADD_ALLOCATION(size);
- void* buf = malloc(size + sizeof(LinearAllocator::Page));
- Page* page = new (buf) Page();
+ Page* page = newPage(size);
+ m_dedicatedPageCount++;
page->setNext(m_pages);
m_pages = page;
if (!m_currentPage)
@@ -177,21 +171,55 @@ void* LinearAllocator::alloc(size_t size)
ensureNext(size);
void* ptr = m_next;
m_next = ((char*)m_next) + size;
+ m_wastedSpace -= size;
return ptr;
}
-void LinearAllocator::rewindTo(void* ptr)
+void LinearAllocator::rewindIfLastAlloc(void* ptr, size_t allocSize)
{
// Don't bother rewinding across pages
- if (ptr >= start(m_currentPage) && ptr < end(m_currentPage))
+ if (ptr >= start(m_currentPage) && ptr < end(m_currentPage)
+ && ptr == ((char*)m_next - allocSize)) {
+ m_totalAllocated -= allocSize;
+ m_wastedSpace += allocSize;
m_next = ptr;
+ }
}
-LinearAllocator::Page* LinearAllocator::newPage()
+LinearAllocator::Page* LinearAllocator::newPage(size_t pageSize)
{
- ADD_ALLOCATION(m_pageSize);
- void* buf = malloc(m_pageSize);
+ pageSize += sizeof(LinearAllocator::Page);
+ ADD_ALLOCATION(pageSize);
+ m_totalAllocated += pageSize;
+ m_pageCount++;
+ void* buf = malloc(pageSize);
return new (buf) Page();
}
+static const char* toSize(size_t value, float& result)
+{
+ if (value < 2000) {
+ result = value;
+ return "B";
+ }
+ if (value < 2000000) {
+ result = value / 1024.0f;
+ return "KB";
+ }
+ result = value / 1048576.0f;
+ return "MB";
+}
+
+void LinearAllocator::dumpMemoryStats(const char* prefix)
+{
+ float prettySize;
+ const char* prettySuffix;
+ prettySuffix = toSize(m_totalAllocated, prettySize);
+ ALOGD("%sTotal allocated: %.2f%s", prefix, prettySize, prettySuffix);
+ prettySuffix = toSize(m_wastedSpace, prettySize);
+ ALOGD("%sWasted space: %.2f%s (%.1f%%)", prefix, prettySize, prettySuffix,
+ (float) m_wastedSpace / (float) m_totalAllocated * 100.0f);
+ ALOGD("%sPages %d (dedicated %d)", prefix, m_pageCount, m_dedicatedPageCount);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h
index 1f3265c..8cabf7c 100644
--- a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h
+++ b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h
@@ -31,29 +31,36 @@ namespace WebCore {
class LinearAllocator
{
public:
- LinearAllocator(size_t averageAllocSize = 0);
+ LinearAllocator();
~LinearAllocator();
void* alloc(size_t size);
- void rewindTo(void*);
+ void rewindIfLastAlloc(void* ptr, size_t allocSize);
+
+ void dumpMemoryStats(const char* prefix = "");
private:
LinearAllocator(const LinearAllocator& other);
class Page;
- Page* newPage();
+ Page* newPage(size_t pageSize);
+ bool fitsInCurrentPage(size_t size);
void ensureNext(size_t size);
void* start(Page *p);
void* end(Page* p);
- unsigned memusage();
-
size_t m_pageSize;
size_t m_maxAllocSize;
void* m_next;
Page* m_currentPage;
Page* m_pages;
+
+ // Memory usage tracking
+ size_t m_totalAllocated;
+ size_t m_wastedSpace;
+ size_t m_pageCount;
+ size_t m_dedicatedPageCount;
};
} // namespace WebCore
diff --git a/Source/WebKit/android/jni/PicturePile.cpp b/Source/WebKit/android/jni/PicturePile.cpp
index 91f3e74..f995e92 100644
--- a/Source/WebKit/android/jni/PicturePile.cpp
+++ b/Source/WebKit/android/jni/PicturePile.cpp
@@ -55,16 +55,6 @@ static SkIRect toSkIRect(const IntRect& rect) {
return SkIRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height());
}
-static IntRect extractClipBounds(SkCanvas* canvas, const IntSize& size) {
- SkRect clip;
- if (!canvas->getClipBounds(&clip)) {
- ALOGW("Empty clip!");
- return IntRect();
- }
- clip.intersect(0, 0, size.width(), size.height());
- return enclosingIntRect(clip);
-}
-
PictureContainer::PictureContainer(const PictureContainer& other)
: picture(other.picture)
, area(other.area)
@@ -94,11 +84,10 @@ void PicturePile::draw(SkCanvas* canvas)
* the rect bounds of the SkRegion for the clip, so this still can't be
* used for translucent surfaces
*/
- IntRect clipBounds = extractClipBounds(canvas, m_size);
- if (clipBounds.isEmpty())
+ if (canvas->quickReject(SkRect::MakeWH(m_size.width(), m_size.height()),
+ SkCanvas::kBW_EdgeType))
return;
- SkRegion clipRegion(toSkIRect(clipBounds));
- drawWithClipRecursive(canvas, clipRegion, m_pile.size() - 1);
+ drawWithClipRecursive(canvas, m_pile.size() - 1);
}
void PicturePile::clearPrerenders()
@@ -107,24 +96,23 @@ void PicturePile::clearPrerenders()
m_pile[i].prerendered.clear();
}
-void PicturePile::drawWithClipRecursive(SkCanvas* canvas, SkRegion& clipRegion,
- int index)
+void PicturePile::drawWithClipRecursive(SkCanvas* canvas, int index)
{
// TODO: Add some debug visualizations of this
- if (index < 0 || clipRegion.isEmpty())
+ if (index < 0)
return;
PictureContainer& pc = m_pile[index];
- IntRect intersection = clipRegion.getBounds();
- intersection.intersect(pc.area);
- if (pc.picture && !intersection.isEmpty()) {
- clipRegion.op(intersection, SkRegion::kDifference_Op);
- drawWithClipRecursive(canvas, clipRegion, index - 1);
- int saved = canvas->save();
- if (canvas->clipRect(intersection))
+ if (pc.picture && !canvas->quickReject(pc.area, SkCanvas::kBW_EdgeType)) {
+ int saved = canvas->save(SkCanvas::kClip_SaveFlag);
+ if (canvas->clipRect(pc.area, SkRegion::kDifference_Op))
+ drawWithClipRecursive(canvas, index - 1);
+ canvas->restoreToCount(saved);
+ saved = canvas->save(SkCanvas::kClip_SaveFlag);
+ if (canvas->clipRect(pc.area))
drawPicture(canvas, pc);
canvas->restoreToCount(saved);
} else
- drawWithClipRecursive(canvas, clipRegion, index - 1);
+ drawWithClipRecursive(canvas, index - 1);
}
// Used by WebViewCore
diff --git a/Source/WebKit/android/jni/PicturePile.h b/Source/WebKit/android/jni/PicturePile.h
index 6e3e46d..1f99054 100644
--- a/Source/WebKit/android/jni/PicturePile.h
+++ b/Source/WebKit/android/jni/PicturePile.h
@@ -113,7 +113,7 @@ private:
void updatePicture(PicturePainter* painter, PictureContainer& container);
Picture* recordPicture(PicturePainter* painter, PictureContainer& container);
void appendToPile(const IntRect& inval, const IntRect& originalInval = IntRect());
- void drawWithClipRecursive(SkCanvas* canvas, SkRegion& clipRegion, int index);
+ void drawWithClipRecursive(SkCanvas* canvas, int index);
void drawPicture(SkCanvas* canvas, PictureContainer& pc);
IntSize m_size;
diff --git a/Tools/android/webkitmerge/Android.mk b/Tools/android/webkitmerge/Android.mk
index 2ff1538..19f1cde 100644
--- a/Tools/android/webkitmerge/Android.mk
+++ b/Tools/android/webkitmerge/Android.mk
@@ -19,6 +19,4 @@ LOCAL_SRC_FILES := webkitmerge.cpp
LOCAL_MODULE := webkitmerge
-LOCAL_MODULE_TAGS := eng
-
include $(BUILD_HOST_EXECUTABLE)