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.cpp86
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h16
-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/fonts/FontPlatformData.h36
-rw-r--r--Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp155
-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--Source/WebKit/android/jni/WebViewCore.cpp42
-rw-r--r--Tools/android/webkitmerge/Android.mk2
16 files changed, 346 insertions, 264 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..c70a67d 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,8 @@ 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));
+ mRecordingStateStack.last().disableOpaqueTracking();
}
void PlatformGraphicsContextRecording::endTransparencyLayer()
@@ -533,7 +536,7 @@ void PlatformGraphicsContextRecording::save()
{
PlatformGraphicsContext::save();
CanvasState* parent = mRecordingStateStack.last().mCanvasState;
- pushStateOperation(new (canvasStateHeap()) CanvasState(parent));
+ pushStateOperation(new (heap()) CanvasState(parent));
pushMatrix();
}
@@ -686,13 +689,13 @@ const SkMatrix& PlatformGraphicsContextRecording::getTotalMatrix()
void PlatformGraphicsContextRecording::addInnerRoundedRectClip(const IntRect& rect,
int thickness)
{
- mRecordingStateStack.last().setHasComplexClip();
+ mRecordingStateStack.last().disableOpaqueTracking();
appendStateOperation(NEW_OP(InnerRoundedRectClip)(rect, thickness));
}
void PlatformGraphicsContextRecording::canvasClip(const Path& path)
{
- mRecordingStateStack.last().setHasComplexClip();
+ mRecordingStateStack.last().disableOpaqueTracking();
clip(path);
}
@@ -705,7 +708,7 @@ bool PlatformGraphicsContextRecording::clip(const FloatRect& rect)
bool PlatformGraphicsContextRecording::clip(const Path& path)
{
- mRecordingStateStack.last().setHasComplexClip();
+ mRecordingStateStack.last().disableOpaqueTracking();
clipState(path.boundingRect());
appendStateOperation(NEW_OP(ClipPath)(path));
return true;
@@ -720,21 +723,21 @@ bool PlatformGraphicsContextRecording::clipConvexPolygon(size_t numPoints,
bool PlatformGraphicsContextRecording::clipOut(const IntRect& r)
{
- mRecordingStateStack.last().setHasComplexClip();
+ mRecordingStateStack.last().disableOpaqueTracking();
appendStateOperation(NEW_OP(ClipOut)(r));
return true;
}
bool PlatformGraphicsContextRecording::clipOut(const Path& path)
{
- mRecordingStateStack.last().setHasComplexClip();
+ mRecordingStateStack.last().disableOpaqueTracking();
appendStateOperation(NEW_OP(ClipPath)(path, true));
return true;
}
bool PlatformGraphicsContextRecording::clipPath(const Path& pathToClip, WindRule clipRule)
{
- mRecordingStateStack.last().setHasComplexClip();
+ mRecordingStateStack.last().disableOpaqueTracking();
clipState(pathToClip.boundingRect());
GraphicsOperation::ClipPath* operation = NEW_OP(ClipPath)(pathToClip);
operation->setWindRule(clipRule);
@@ -900,9 +903,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);
@@ -928,7 +931,9 @@ void PlatformGraphicsContextRecording::clipState(const FloatRect& clip)
void PlatformGraphicsContextRecording::pushStateOperation(CanvasState* canvasState)
{
ALOGV("RECORDING: pushStateOperation: %p(isLayer=%d)", canvasState, canvasState->isTransparencyLayer());
- mRecordingStateStack.append(canvasState);
+
+ RecordingState* parent = mRecordingStateStack.isEmpty() ? 0 : &(mRecordingStateStack.last());
+ mRecordingStateStack.append(RecordingState(canvasState, parent));
mRecording->recording()->addCanvasState(canvasState);
}
@@ -942,7 +947,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());
@@ -998,6 +1003,13 @@ IntRect PlatformGraphicsContextRecording::calculateFinalBounds(FloatRect bounds)
IntRect PlatformGraphicsContextRecording::calculateCoveredBounds(FloatRect bounds)
{
+ if (mRecordingStateStack.last().mOpaqueTrackingDisabled
+ || m_state->alpha != 1.0f
+ || (m_state->mode != SkXfermode::kSrc_Mode && m_state->mode != SkXfermode::kSrcOver_Mode)
+ || !mCurrentMatrix->rectStaysRect()) {
+ return IntRect();
+ }
+
SkRect translated;
mCurrentMatrix->mapRect(&translated, bounds);
FloatRect ftrect = translated;
@@ -1025,38 +1037,28 @@ void PlatformGraphicsContextRecording::appendDrawingOperation(
if (ibounds.isEmpty()) {
ALOGV("RECORDING: Operation %s() was clipped out", operation->name());
operation->~Operation();
- operationHeap()->rewindTo(operation);
return;
}
- if (operation->isOpaque()
- && !untranslatedBounds.isEmpty()
- && operation->m_state->alpha == 1.0f
- && mCurrentMatrix->rectStaysRect()
- && !state.mHasComplexClip) {
+ if (operation->isOpaque() && !untranslatedBounds.isEmpty()) {
// if the operation maps to an opaque rect, record the area it will cover
operation->setOpaqueRect(calculateCoveredBounds(untranslatedBounds));
}
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..061ee0e 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;
@@ -169,22 +168,23 @@ private:
Recording* mRecording;
class RecordingState {
public:
- RecordingState(CanvasState* state)
+ RecordingState(CanvasState* state, const RecordingState* parent)
: mCanvasState(state)
, mHasDrawing(false)
- , mHasClip(false)
- , mHasComplexClip(false)
+ , mHasClip(parent ? parent->mHasClip : false)
+ , mOpaqueTrackingDisabled(parent ? parent->mOpaqueTrackingDisabled : false)
+ , mBounds(parent ? parent->mBounds : FloatRect())
{}
RecordingState(const RecordingState& other)
: mCanvasState(other.mCanvasState)
, mHasDrawing(other.mHasDrawing)
, mHasClip(other.mHasClip)
- , mHasComplexClip(false)
+ , mOpaqueTrackingDisabled(other.mOpaqueTrackingDisabled)
, mBounds(other.mBounds)
{}
- void setHasComplexClip() { mHasComplexClip = true; }
+ void disableOpaqueTracking() { mOpaqueTrackingDisabled = true; }
void clip(const FloatRect& rect)
{
@@ -199,7 +199,7 @@ private:
CanvasState* mCanvasState;
bool mHasDrawing;
bool mHasClip;
- bool mHasComplexClip;
+ bool mOpaqueTrackingDisabled;
FloatRect mBounds;
};
Vector<RecordingState> mRecordingStateStack;
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/fonts/FontPlatformData.h b/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h
index 02a0cea..afae949 100644
--- a/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h
@@ -33,12 +33,13 @@
#include "FontOrientation.h"
#include "TextOrientation.h"
#include <wtf/text/StringImpl.h>
+#include "SkLanguage.h"
+#include "SkPaint.h"
#ifndef NDEBUG
#include "PlatformString.h"
#endif
-class SkPaint;
class SkTypeface;
struct HB_FaceRec_;
@@ -62,13 +63,13 @@ public:
~FontPlatformData();
FontPlatformData(WTF::HashTableDeletedValueType)
- : mTypeface(hashTableDeletedFontValue()) { }
+ : m_typeface(hashTableDeletedFontValue()) { }
bool isHashTableDeletedValue() const {
- return mTypeface == hashTableDeletedFontValue();
+ return m_typeface == hashTableDeletedFontValue();
}
- FontOrientation orientation() const { return mOrientation; }
- void setOrientation(FontOrientation orientation) { mOrientation = orientation; }
+ FontOrientation orientation() const { return m_orientation; }
+ void setOrientation(FontOrientation orientation) { m_orientation = orientation; }
FontPlatformData& operator=(const FontPlatformData&);
bool operator==(const FontPlatformData& a) const;
@@ -80,7 +81,7 @@ public:
// -------------------------------------------------------------------------
uint32_t uniqueID() const;
- float size() const { return mTextSize; }
+ float size() const { return m_textSize; }
unsigned hash() const;
int emSizeInFontUnits() const;
bool isFixedPitch() const;
@@ -90,10 +91,12 @@ public:
#endif
HB_FaceRec_* harfbuzzFace() const;
- SkTypeface* typeface() const { return mTypeface; }
+ SkTypeface* typeface() const { return m_typeface; }
- bool isFakeBold() const { return mFakeBold; }
- bool isFakeItalic() const { return mFakeItalic; }
+ bool isFakeBold() const { return m_fakeBold; }
+ bool isFakeItalic() const { return m_fakeItalic; }
+
+ static void setDefaultLanguage(const char* language);
private:
class RefCountedHarfbuzzFace : public RefCounted<RefCountedHarfbuzzFace> {
@@ -115,14 +118,15 @@ private:
HB_FaceRec_* m_harfbuzzFace;
};
- SkTypeface* mTypeface;
- float mTextSize;
- mutable int mEmSizeInFontUnits;
- bool mFakeBold;
- bool mFakeItalic;
- FontOrientation mOrientation;
- TextOrientation mTextOrientation;
+ SkTypeface* m_typeface;
+ float m_textSize;
+ mutable int m_emSizeInFontUnits;
+ bool m_fakeBold;
+ bool m_fakeItalic;
+ FontOrientation m_orientation;
+ TextOrientation m_textOrientation;
mutable RefPtr<RefCountedHarfbuzzFace> m_harfbuzzFace;
+ static SkLanguage s_defaultLanguage;
static SkTypeface* hashTableDeletedFontValue() {
return reinterpret_cast<SkTypeface*>(-1);
diff --git a/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp
index fc254c0..f3e4227 100644
--- a/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp
@@ -41,26 +41,26 @@
//#define COUNT_FONTPLATFORMDATA_LIFE
#ifdef COUNT_FONTPLATFORMDATA_LIFE
-static int gCount;
-static int gMaxCount;
+static int g_count;
+static int g_maxCount;
static void inc_count()
{
- if (++gCount > gMaxCount)
+ if (++g_count > g_maxCount)
{
- gMaxCount = gCount;
- SkDebugf("---------- FontPlatformData %d\n", gMaxCount);
+ g_maxCount = g_count;
+ SkDebugf("---------- FontPlatformData %d\n", g_maxCount);
}
}
-static void dec_count() { --gCount; }
+static void dec_count() { --g_count; }
#else
#define inc_count()
#define dec_count()
#endif
#ifdef TRACE_FONTPLATFORMDATA_LIFE
- #define trace(num) SkDebugf("FontPlatformData%d %p %g %d %d\n", num, mTypeface, mTextSize, mFakeBold, mFakeItalic)
+ #define trace(num) SkDebugf("FontPlatformData%d %p %g %d %d\n", num, m_typeface, m_textSize, m_fakeBold, m_fakeItalic)
#else
#define trace(num)
#endif
@@ -75,8 +75,8 @@ FontPlatformData::RefCountedHarfbuzzFace::~RefCountedHarfbuzzFace()
}
FontPlatformData::FontPlatformData()
- : mTypeface(NULL), mTextSize(0), mEmSizeInFontUnits(0), mFakeBold(false), mFakeItalic(false),
- mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight)
+ : m_typeface(NULL), m_textSize(0), m_emSizeInFontUnits(0), m_fakeBold(false), m_fakeItalic(false),
+ m_orientation(Horizontal), m_textOrientation(TextOrientationVerticalRight)
{
inc_count();
trace(1);
@@ -84,30 +84,29 @@ FontPlatformData::FontPlatformData()
FontPlatformData::FontPlatformData(const FontPlatformData& src)
{
- if (hashTableDeletedFontValue() != src.mTypeface) {
- SkSafeRef(src.mTypeface);
+ if (hashTableDeletedFontValue() != src.m_typeface) {
+ SkSafeRef(src.m_typeface);
}
- mTypeface = src.mTypeface;
- mTextSize = src.mTextSize;
- mEmSizeInFontUnits = src.mEmSizeInFontUnits;
- mFakeBold = src.mFakeBold;
- mFakeItalic = src.mFakeItalic;
+ m_typeface = src.m_typeface;
+ m_textSize = src.m_textSize;
+ m_emSizeInFontUnits = src.m_emSizeInFontUnits;
+ m_fakeBold = src.m_fakeBold;
+ m_fakeItalic = src.m_fakeItalic;
m_harfbuzzFace = src.m_harfbuzzFace;
- mOrientation = src.mOrientation;
- mTextOrientation = src.mTextOrientation;
-
+ m_orientation = src.m_orientation;
+ m_textOrientation = src.m_textOrientation;
inc_count();
trace(2);
}
FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic,
FontOrientation orientation, TextOrientation textOrientation)
- : mTypeface(tf), mTextSize(textSize), mEmSizeInFontUnits(0), mFakeBold(fakeBold), mFakeItalic(fakeItalic),
- mOrientation(orientation), mTextOrientation(textOrientation)
+ : m_typeface(tf), m_textSize(textSize), m_emSizeInFontUnits(0), m_fakeBold(fakeBold), m_fakeItalic(fakeItalic),
+ m_orientation(orientation), m_textOrientation(textOrientation)
{
- if (hashTableDeletedFontValue() != mTypeface) {
- SkSafeRef(mTypeface);
+ if (hashTableDeletedFontValue() != m_typeface) {
+ SkSafeRef(m_typeface);
}
inc_count();
@@ -115,11 +114,11 @@ FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold
}
FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize)
- : mTypeface(src.mTypeface), mTextSize(textSize), mEmSizeInFontUnits(src.mEmSizeInFontUnits), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic),
- mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation), m_harfbuzzFace(src.m_harfbuzzFace)
+ : m_typeface(src.m_typeface), m_textSize(textSize), m_emSizeInFontUnits(src.m_emSizeInFontUnits), m_fakeBold(src.m_fakeBold), m_fakeItalic(src.m_fakeItalic),
+ m_orientation(src.m_orientation), m_textOrientation(src.m_textOrientation), m_harfbuzzFace(src.m_harfbuzzFace)
{
- if (hashTableDeletedFontValue() != mTypeface) {
- SkSafeRef(mTypeface);
+ if (hashTableDeletedFontValue() != m_typeface) {
+ SkSafeRef(m_typeface);
}
inc_count();
@@ -127,20 +126,20 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize)
}
FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
- : mTypeface(NULL), mTextSize(size), mEmSizeInFontUnits(0), mFakeBold(bold), mFakeItalic(oblique),
- mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight)
+ : m_typeface(NULL), m_textSize(size), m_emSizeInFontUnits(0), m_fakeBold(bold), m_fakeItalic(oblique),
+ m_orientation(Horizontal), m_textOrientation(TextOrientationVerticalRight)
{
inc_count();
trace(5);
}
FontPlatformData::FontPlatformData(const FontPlatformData& src, SkTypeface* tf)
- : mTypeface(tf), mTextSize(src.mTextSize), mEmSizeInFontUnits(0), mFakeBold(src.mFakeBold),
- mFakeItalic(src.mFakeItalic), mOrientation(src.mOrientation),
- mTextOrientation(src.mTextOrientation)
+ : m_typeface(tf), m_textSize(src.m_textSize), m_emSizeInFontUnits(0), m_fakeBold(src.m_fakeBold),
+ m_fakeItalic(src.m_fakeItalic), m_orientation(src.m_orientation),
+ m_textOrientation(src.m_textOrientation)
{
- if (hashTableDeletedFontValue() != mTypeface) {
- SkSafeRef(mTypeface);
+ if (hashTableDeletedFontValue() != m_typeface) {
+ SkSafeRef(m_typeface);
}
inc_count();
@@ -154,61 +153,67 @@ FontPlatformData::~FontPlatformData()
SkDebugf("----------- ~FontPlatformData\n");
#endif
- if (hashTableDeletedFontValue() != mTypeface) {
- SkSafeUnref(mTypeface);
+ if (hashTableDeletedFontValue() != m_typeface) {
+ SkSafeUnref(m_typeface);
}
}
int FontPlatformData::emSizeInFontUnits() const
{
- if (mEmSizeInFontUnits)
- return mEmSizeInFontUnits;
+ if (m_emSizeInFontUnits)
+ return m_emSizeInFontUnits;
SkAdvancedTypefaceMetrics* metrics = 0;
- if (mTypeface)
- metrics = mTypeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo);
+ if (m_typeface)
+ metrics = m_typeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo);
if (metrics) {
- mEmSizeInFontUnits = metrics->fEmSize;
+ m_emSizeInFontUnits = metrics->fEmSize;
metrics->unref();
} else
- mEmSizeInFontUnits = 1000; // default value copied from Skia.
- return mEmSizeInFontUnits;
+ m_emSizeInFontUnits = 1000; // default value copied from Skia.
+ return m_emSizeInFontUnits;
}
FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
{
- if (hashTableDeletedFontValue() != src.mTypeface) {
- SkSafeRef(src.mTypeface);
+ if (hashTableDeletedFontValue() != src.m_typeface) {
+ SkSafeRef(src.m_typeface);
}
- if (hashTableDeletedFontValue() != mTypeface) {
- SkSafeUnref(mTypeface);
+ if (hashTableDeletedFontValue() != m_typeface) {
+ SkSafeUnref(m_typeface);
}
- mTypeface = src.mTypeface;
- mEmSizeInFontUnits = src.mEmSizeInFontUnits;
- mTextSize = src.mTextSize;
- mFakeBold = src.mFakeBold;
- mFakeItalic = src.mFakeItalic;
+ m_typeface = src.m_typeface;
+ m_emSizeInFontUnits = src.m_emSizeInFontUnits;
+ m_textSize = src.m_textSize;
+ m_fakeBold = src.m_fakeBold;
+ m_fakeItalic = src.m_fakeItalic;
m_harfbuzzFace = src.m_harfbuzzFace;
- mOrientation = src.mOrientation;
- mTextOrientation = src.mTextOrientation;
+ m_orientation = src.m_orientation;
+ m_textOrientation = src.m_textOrientation;
return *this;
}
+SkLanguage FontPlatformData::s_defaultLanguage;
+void FontPlatformData::setDefaultLanguage(const char* language) {
+ s_defaultLanguage = SkLanguage(language);
+}
+
void FontPlatformData::setupPaint(SkPaint* paint) const
{
- if (hashTableDeletedFontValue() == mTypeface)
+ if (hashTableDeletedFontValue() == m_typeface)
paint->setTypeface(0);
else
- paint->setTypeface(mTypeface);
+ paint->setTypeface(m_typeface);
paint->setAntiAlias(true);
paint->setSubpixelText(true);
paint->setHinting(SkPaint::kSlight_Hinting);
- paint->setTextSize(SkFloatToScalar(mTextSize));
- paint->setFakeBoldText(mFakeBold);
- paint->setTextSkewX(mFakeItalic ? -SK_Scalar1/4 : 0);
+ paint->setTextSize(SkFloatToScalar(m_textSize));
+ paint->setFakeBoldText(m_fakeBold);
+ paint->setTextSkewX(m_fakeItalic ? -SK_Scalar1/4 : 0);
+ paint->setLanguage(s_defaultLanguage);
#ifndef SUPPORT_COMPLEX_SCRIPTS
paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
#endif
@@ -216,44 +221,44 @@ void FontPlatformData::setupPaint(SkPaint* paint) const
uint32_t FontPlatformData::uniqueID() const
{
- if (hashTableDeletedFontValue() == mTypeface)
+ if (hashTableDeletedFontValue() == m_typeface)
return SkTypeface::UniqueID(0);
else
- return SkTypeface::UniqueID(mTypeface);
+ return SkTypeface::UniqueID(m_typeface);
}
bool FontPlatformData::operator==(const FontPlatformData& a) const
{
- return mTypeface == a.mTypeface &&
- mTextSize == a.mTextSize &&
- mFakeBold == a.mFakeBold &&
- mFakeItalic == a.mFakeItalic &&
- mOrientation == a.mOrientation &&
- mTextOrientation == a.mTextOrientation;
+ return m_typeface == a.m_typeface &&
+ m_textSize == a.m_textSize &&
+ m_fakeBold == a.m_fakeBold &&
+ m_fakeItalic == a.m_fakeItalic &&
+ m_orientation == a.m_orientation &&
+ m_textOrientation == a.m_textOrientation;
}
unsigned FontPlatformData::hash() const
{
unsigned h;
- if (hashTableDeletedFontValue() == mTypeface) {
- h = reinterpret_cast<unsigned>(mTypeface);
+ if (hashTableDeletedFontValue() == m_typeface) {
+ h = reinterpret_cast<unsigned>(m_typeface);
} else {
- h = SkTypeface::UniqueID(mTypeface);
+ h = SkTypeface::UniqueID(m_typeface);
}
- uint32_t sizeAsInt = *reinterpret_cast<const uint32_t*>(&mTextSize);
+ uint32_t sizeAsInt = *reinterpret_cast<const uint32_t*>(&m_textSize);
- h ^= 0x01010101 * ((static_cast<int>(mTextOrientation) << 3) | (static_cast<int>(mOrientation) << 2) |
- ((int)mFakeBold << 1) | (int)mFakeItalic);
+ h ^= 0x01010101 * ((static_cast<int>(m_textOrientation) << 3) | (static_cast<int>(m_orientation) << 2) |
+ ((int)m_fakeBold << 1) | (int)m_fakeItalic);
h ^= sizeAsInt;
return h;
}
bool FontPlatformData::isFixedPitch() const
{
- if (mTypeface && (mTypeface != hashTableDeletedFontValue()))
- return mTypeface->isFixedWidth();
+ if (m_typeface && (m_typeface != hashTableDeletedFontValue()))
+ return m_typeface->isFixedWidth();
else
return false;
}
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/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp
index fd5e9c4..920119b 100644
--- a/Source/WebKit/android/jni/WebViewCore.cpp
+++ b/Source/WebKit/android/jni/WebViewCore.cpp
@@ -134,6 +134,7 @@
#include "autofill/WebAutofill.h"
#include "htmlediting.h"
#include "markup.h"
+#include "unicode/uloc.h"
#include "visible_units.h"
#include <JNIHelp.h>
@@ -4407,6 +4408,44 @@ void WebViewCore::getLocale(String& language, String& region)
region = String(propRegn, 2);
}
+// generate bcp47 identifier for the supplied language/region
+static void toLanguageTag(char* output, size_t outSize, const String& language,
+ const String& region) {
+ if (output == NULL || outSize <= 0)
+ return;
+ String locale = language;
+ locale.append('_');
+ locale.append(region);
+ char canonicalChars[ULOC_FULLNAME_CAPACITY];
+ UErrorCode uErr = U_ZERO_ERROR;
+ uloc_canonicalize(locale.ascii().data(), canonicalChars,
+ ULOC_FULLNAME_CAPACITY, &uErr);
+ if (U_SUCCESS(uErr)) {
+ char likelyChars[ULOC_FULLNAME_CAPACITY];
+ uErr = U_ZERO_ERROR;
+ uloc_addLikelySubtags(canonicalChars, likelyChars,
+ ULOC_FULLNAME_CAPACITY, &uErr);
+ if (U_SUCCESS(uErr)) {
+ uErr = U_ZERO_ERROR;
+ uloc_toLanguageTag(likelyChars, output, outSize, FALSE, &uErr);
+ if (U_SUCCESS(uErr)) {
+ return;
+ } else {
+ ALOGD("uloc_toLanguageTag(\"%s\") failed: %s", likelyChars,
+ u_errorName(uErr));
+ }
+ } else {
+ ALOGD("uloc_addLikelySubtags(\"%s\") failed: %s", canonicalChars,
+ u_errorName(uErr));
+ }
+ } else {
+ ALOGD("uloc_canonicalize(\"%s\") failed: %s", locale.ascii().data(),
+ u_errorName(uErr));
+ }
+ // unable to build a proper language identifier
+ output[0] = '\0';
+}
+
void WebViewCore::updateLocale()
{
static String prevLang;
@@ -4421,6 +4460,9 @@ void WebViewCore::updateLocale()
prevRegn = region;
GlyphPageTreeNode::resetRoots();
fontCache()->invalidate();
+ char langTag[ULOC_FULLNAME_CAPACITY];
+ toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, language, region);
+ FontPlatformData::setDefaultLanguage(langTag);
}
}
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)