diff options
12 files changed, 325 insertions, 167 deletions
diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk index cd5764f..10eb822 100644 --- a/Source/WebCore/Android.mk +++ b/Source/WebCore/Android.mk @@ -642,6 +642,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/graphics/android/SharedBufferStream.cpp \ \ platform/graphics/android/context/GraphicsContextAndroid.cpp \ + platform/graphics/android/context/GraphicsOperation.cpp \ platform/graphics/android/context/PlatformGraphicsContext.cpp \ platform/graphics/android/context/PlatformGraphicsContextRecording.cpp \ platform/graphics/android/context/PlatformGraphicsContextSkia.cpp \ diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.cpp new file mode 100644 index 0000000..ab6e676 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.cpp @@ -0,0 +1,55 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#define LOG_TAG "GraphicsOperation" + +#include "config.h" +#include "GraphicsOperation.h" + +#include "AndroidLog.h" +#include "LinearAllocator.h" + +namespace WebCore { +namespace GraphicsOperation { + +void* Operation::operator new(size_t size, LinearAllocator* allocator) +{ + return allocator->alloc(size); +} + +void* Operation::operator new(size_t size) +{ + ALOGE("Cannot allocate a new Operation directly!"); + CRASH(); + return (void*) 0xBADBEEF; +} + +void Operation::operator delete(void*) +{ + ALOGE("Cannot call delete on an Operation!"); + CRASH(); +} + +} // namespace GraphicsOperation +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h index 604206b..9bbf6b9 100644 --- a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h +++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h @@ -42,14 +42,49 @@ #define TYPE_CASE(type) case type: return #type; +#define DEBUG_GRAPHICS_OPERATIONS false + +#if DEBUG_GRAPHICS_OPERATIONS +#define TYPE(x) virtual OperationType type() { return x; } +#else +#define TYPE(x) +#endif + namespace WebCore { class CanvasState; +class LinearAllocator; namespace GraphicsOperation { class Operation { public: + Operation() + : m_state(0) + , m_canvasState(0) + {} + + 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); + + // This m_state is applied by ourselves + PlatformGraphicsContext::State* m_state; + // This is the canvas state that this operation needs + // Only used for drawing operations, state operations will be undefined + CanvasState* m_canvasState; + + bool apply(PlatformGraphicsContext* context) { + if (m_state) + context->setRawState(m_state); + return applyImpl(context); + } + virtual bool applyImpl(PlatformGraphicsContext* context) = 0; + virtual ~Operation() {} + +#if DEBUG_GRAPHICS_OPERATIONS typedef enum { UndefinedOperation // Matrix operations , ConcatCTMOperation @@ -82,28 +117,6 @@ public: , DrawPosTextOperation } OperationType; - Operation() - : m_state(0) - , m_canvasState(0) - {} - - // This m_state is applied by ourselves - PlatformGraphicsContext::State* m_state; - // This is the canvas state that this operation needs - // Only used for drawing operations, state operations will be undefined - CanvasState* m_canvasState; - IntRect m_globalBounds; - - bool apply(PlatformGraphicsContext* context) { - if (m_state) - context->setRawState(m_state); - return applyImpl(context); - } - virtual bool applyImpl(PlatformGraphicsContext* context) = 0; - virtual ~Operation() {} - virtual OperationType type() { return UndefinedOperation; } - virtual String parameters() { return ""; } - virtual void subtractOpaqueClip(FloatRect& clip) {} const char* name() { switch (type()) { @@ -140,6 +153,8 @@ public: } return "Undefined"; } +#endif + TYPE(UndefinedOperation) }; //************************************** @@ -153,7 +168,7 @@ public: context->concatCTM(m_matrix); return true; } - virtual OperationType type() { return ConcatCTMOperation; } + TYPE(ConcatCTMOperation) private: AffineTransform m_matrix; }; @@ -165,7 +180,7 @@ public: context->rotate(m_angle); return true; } - virtual OperationType type() { return RotateOperation; } + TYPE(RotateOperation) private: float m_angle; }; @@ -177,7 +192,7 @@ public: context->scale(m_scale); return true; } - virtual OperationType type() { return ScaleOperation; } + TYPE(ScaleOperation) private: FloatSize m_scale; }; @@ -189,7 +204,7 @@ public: context->translate(m_x, m_y); return true; } - virtual OperationType type() { return TranslateOperation; } + TYPE(TranslateOperation) private: float m_x; float m_y; @@ -207,7 +222,7 @@ public: context->addInnerRoundedRectClip(m_rect, m_thickness); return true; } - virtual OperationType type() { return InnerRoundedRectClipOperation; } + TYPE(InnerRoundedRectClipOperation) private: IntRect m_rect; int m_thickness; @@ -219,12 +234,7 @@ public: virtual bool applyImpl(PlatformGraphicsContext* context) { return context->clip(m_rect); } - virtual OperationType type() { return ClipOperation; } - virtual String parameters() { - return String::format("[x=%.2f,y=%.2f,w=%.2f,h=%.2f]", - m_rect.x(), m_rect.y(), - m_rect.width(), m_rect.height()); - } + TYPE(ClipOperation) private: const FloatRect m_rect; }; @@ -243,7 +253,7 @@ public: else return context->clip(m_path); } - virtual OperationType type() { return ClipPathOperation; } + TYPE(ClipPathOperation) private: const Path m_path; bool m_clipOut; @@ -257,7 +267,7 @@ public: virtual bool applyImpl(PlatformGraphicsContext* context) { return context->clipOut(m_rect); } - virtual OperationType type() { return ClipOutOperation; } + TYPE(ClipOutOperation) private: const IntRect m_rect; }; @@ -269,7 +279,7 @@ public: context->clearRect(m_rect); return true; } - virtual OperationType type() { return ClearRectOperation; } + TYPE(ClearRectOperation) private: FloatRect m_rect; }; @@ -287,7 +297,7 @@ public: context->drawBitmapPattern(m_bitmap, m_matrix, m_operator, m_destRect); return true; } - virtual OperationType type() { return DrawBitmapPatternOperation; } + TYPE(DrawBitmapPatternOperation) private: SkBitmap m_bitmap; SkMatrix m_matrix; @@ -304,12 +314,7 @@ public: context->drawBitmapRect(m_bitmap, &m_srcR, m_dstR, m_operator); return true; } - virtual OperationType type() { return DrawBitmapRectOperation; } - virtual String parameters() { - return String::format("%.2f, %.2f - %.2f x %.2f", - m_dstR.fLeft, m_dstR.fTop, - m_dstR.width(), m_dstR.height()); - } + TYPE(DrawBitmapRectOperation) private: SkBitmap m_bitmap; SkIRect m_srcR; @@ -328,7 +333,7 @@ public: context->drawConvexPolygon(4, m_points, m_shouldAntiAlias); return true; } - virtual OperationType type() { return DrawConvexPolygonQuadOperation; } + TYPE(DrawConvexPolygonQuadOperation) private: bool m_shouldAntiAlias; FloatPoint m_points[4]; @@ -341,7 +346,7 @@ public: context->drawEllipse(m_rect); return true; } - virtual OperationType type() { return DrawEllipseOperation; } + TYPE(DrawEllipseOperation) private: IntRect m_rect; }; @@ -358,7 +363,7 @@ public: context->drawFocusRing(m_rects, m_width, m_offset, m_color); return true; } - virtual OperationType type() { return DrawFocusRingOperation; } + TYPE(DrawFocusRingOperation) private: Vector<IntRect> m_rects; int m_width; @@ -374,7 +379,7 @@ public: context->drawLine(m_point1, m_point2); return true; } - virtual OperationType type() { return DrawLineOperation; } + TYPE(DrawLineOperation) private: IntPoint m_point1; IntPoint m_point2; @@ -388,7 +393,7 @@ public: context->drawLineForText(m_point, m_width); return true; } - virtual OperationType type() { return DrawLineForTextOperation; } + TYPE(DrawLineForTextOperation) private: FloatPoint m_point; float m_width; @@ -403,7 +408,7 @@ public: context->drawLineForTextChecking(m_point, m_width, m_lineStyle); return true; } - virtual OperationType type() { return DrawLineForTextCheckingOperation; } + TYPE(DrawLineForTextCheckingOperation) private: FloatPoint m_point; float m_width; @@ -417,7 +422,7 @@ public: context->drawRect(m_rect); return true; } - virtual OperationType type() { return DrawRectOperation; } + TYPE(DrawRectOperation) private: IntRect m_rect; }; @@ -430,7 +435,7 @@ public: context->fillPath(m_path, m_fillRule); return true; } - virtual OperationType type() { return FillPathOperation; } + TYPE(FillPathOperation) private: Path m_path; WindRule m_fillRule; @@ -447,7 +452,7 @@ public: context->fillRect(m_rect); return true; } - virtual OperationType type() { return FillRectOperation; } + TYPE(FillRectOperation) private: FloatRect m_rect; Color m_color; @@ -475,7 +480,7 @@ public: m_color); return true; } - virtual OperationType type() { return FillRoundedRectOperation; } + TYPE(FillRoundedRectOperation) private: IntRect m_rect; IntSize m_topLeft; @@ -496,7 +501,7 @@ public: context->strokeArc(m_rect, m_startAngle, m_angleSpan); return true; } - virtual OperationType type() { return StrokeArcOperation; } + TYPE(StrokeArcOperation) private: IntRect m_rect; int m_startAngle; @@ -510,7 +515,7 @@ public: context->strokePath(m_path); return true; } - virtual OperationType type() { return StrokePathOperation; } + TYPE(StrokePathOperation) private: Path m_path; }; @@ -524,7 +529,7 @@ public: context->strokeRect(m_rect, m_lineWidth); return true; } - virtual OperationType type() { return StrokeRectOperation; } + TYPE(StrokeRectOperation) private: FloatRect m_rect; float m_lineWidth; @@ -554,7 +559,7 @@ public: context->getCanvas()->drawPosText(m_text, m_byteLength, m_pos, m_paint); return true; } - virtual OperationType type() { return DrawPosTextOperation; } + TYPE(DrawPosTextOperation) private: void* m_text; size_t m_byteLength; diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp index f9d7f21..367abda 100644 --- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp @@ -161,7 +161,7 @@ bool PlatformGraphicsContext::State::setupShadowPaint(SkPaint* paint, SkPoint* o // HTMLCanvasElement have shadows ignore transforms set. This // allows us to distinguish between CSS and Canvas shadows which // have different rendering specifications. - uint32_t flags = SkBlurMaskFilter::kHighQuality_BlurFlag; + uint32_t flags = SkBlurMaskFilter::kNone_BlurFlag; if (shadowsIgnoreTransforms) { offset->fY = -offset->fY; flags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag; @@ -169,7 +169,7 @@ bool PlatformGraphicsContext::State::setupShadowPaint(SkPaint* paint, SkPoint* o if (shadow.blur > 0) { paint->setMaskFilter(SkBlurMaskFilter::Create(shadow.blur, - SkBlurMaskFilter::kNormal_BlurStyle))->unref(); + SkBlurMaskFilter::kNormal_BlurStyle, flags))->unref(); } return SkColorGetA(shadow.color) && (shadow.blur || shadow.dx || shadow.dy); } @@ -395,7 +395,7 @@ void PlatformGraphicsContext::setupPaintCommon(SkPaint* paint) const // allows us to distinguish between CSS and Canvas shadows which // have different rendering specifications. SkScalar dy = m_state->shadow.dy; - uint32_t flags = SkBlurDrawLooper::kHighQuality_BlurFlag; + uint32_t flags = SkBlurDrawLooper::kNone_BlurFlag; if (shadowsIgnoreTransforms()) { dy = -dy; flags |= SkBlurDrawLooper::kIgnoreTransform_BlurFlag; diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp index a2163ce..b0ab3ac 100644 --- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp @@ -35,6 +35,7 @@ #include "Font.h" #include "GraphicsContext.h" #include "GraphicsOperation.h" +#include "LinearAllocator.h" #include "PlatformGraphicsContextSkia.h" #include "RTree.h" @@ -42,6 +43,8 @@ #include "wtf/HashSet.h" #include "wtf/StringHasher.h" +#define NEW_OP(X) new (operationHeap()) GraphicsOperation::X + namespace WebCore { static FloatRect approximateTextBounds(size_t numGlyphs, @@ -164,6 +167,10 @@ public: return m_isTransparencyLayer; } + void* operator new(size_t size, LinearAllocator* la) { + return la->alloc(size); + } + private: CanvasState *m_parent; bool m_isTransparencyLayer; @@ -172,9 +179,18 @@ private: }; class RecordingImpl { +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; + LinearAllocator m_stateHeap; public: RecordingImpl() - : m_nodeCount(0) + : m_canvasStateHeap(sizeof(CanvasState)) + , m_stateHeap(sizeof(PlatformGraphicsContext::State)) + , m_nodeCount(0) { } @@ -187,8 +203,8 @@ public: StateHashSet::iterator it = m_states.find(inState); if (it != m_states.end()) return (*it); - // TODO: Use a custom allocator - PlatformGraphicsContext::State* state = new PlatformGraphicsContext::State(*inState); + void* buf = m_stateHeap.alloc(sizeof(PlatformGraphicsContext::State)); + PlatformGraphicsContext::State* state = new (buf) PlatformGraphicsContext::State(*inState); m_states.add(state); return state; } @@ -236,6 +252,9 @@ public: toState->playback(context, fromId, toId); } + LinearAllocator* operationHeap() { return &m_operationHeap; } + LinearAllocator* canvasStateHeap() { return &m_canvasStateHeap; } + RTree::RTree m_tree; int m_nodeCount; @@ -244,13 +263,13 @@ private: void clearStates() { StateHashSet::iterator end = m_states.end(); for (StateHashSet::iterator it = m_states.begin(); it != end; ++it) - delete (*it); + (*it)->~State(); m_states.clear(); } void clearCanvasStates() { for (size_t i = 0; i < m_canvasStates.size(); i++) - delete m_canvasStates[i]; + m_canvasStates[i]->~CanvasState(); m_canvasStates.clear(); } @@ -299,7 +318,7 @@ void Recording::draw(SkCanvas* canvas) op->m_canvasState, nodes[i]->m_orderBy); currState = op->m_canvasState; lastOperationId = nodes[i]->m_orderBy; - ALOGV("apply: %p->%s(%s)", op, op->name(), op->parameters().ascii().data()); + ALOGV("apply: %p->%s()", op, op->name()); op->apply(&context); } while (currState) { @@ -338,7 +357,7 @@ PlatformGraphicsContextRecording::PlatformGraphicsContextRecording(Recording* re mRecording->setRecording(new RecordingImpl()); mMatrixStack.append(SkMatrix::I()); mCurrentMatrix = &(mMatrixStack.last()); - pushStateOperation(new CanvasState(0)); + pushStateOperation(new (canvasStateHeap()) CanvasState(0)); } bool PlatformGraphicsContextRecording::isPaintingDisabled() @@ -359,7 +378,7 @@ SkCanvas* PlatformGraphicsContextRecording::recordingCanvas() void PlatformGraphicsContextRecording::beginTransparencyLayer(float opacity) { CanvasState* parent = mRecordingStateStack.last().mCanvasState; - pushStateOperation(new CanvasState(parent, opacity)); + pushStateOperation(new (canvasStateHeap()) CanvasState(parent, opacity)); } void PlatformGraphicsContextRecording::endTransparencyLayer() @@ -371,7 +390,7 @@ void PlatformGraphicsContextRecording::save() { PlatformGraphicsContext::save(); CanvasState* parent = mRecordingStateStack.last().mCanvasState; - pushStateOperation(new CanvasState(parent)); + pushStateOperation(new (canvasStateHeap()) CanvasState(parent)); pushMatrix(); } @@ -490,26 +509,26 @@ void PlatformGraphicsContextRecording::setStrokeThickness(float f) void PlatformGraphicsContextRecording::concatCTM(const AffineTransform& affine) { mCurrentMatrix->preConcat(affine); - appendStateOperation(new GraphicsOperation::ConcatCTM(affine)); + appendStateOperation(NEW_OP(ConcatCTM)(affine)); } void PlatformGraphicsContextRecording::rotate(float angleInRadians) { float value = angleInRadians * (180.0f / 3.14159265f); mCurrentMatrix->preRotate(SkFloatToScalar(value)); - appendStateOperation(new GraphicsOperation::Rotate(angleInRadians)); + appendStateOperation(NEW_OP(Rotate)(angleInRadians)); } void PlatformGraphicsContextRecording::scale(const FloatSize& size) { mCurrentMatrix->preScale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height())); - appendStateOperation(new GraphicsOperation::Scale(size)); + appendStateOperation(NEW_OP(Scale)(size)); } void PlatformGraphicsContextRecording::translate(float x, float y) { mCurrentMatrix->preTranslate(SkFloatToScalar(x), SkFloatToScalar(y)); - appendStateOperation(new GraphicsOperation::Translate(x, y)); + appendStateOperation(NEW_OP(Translate)(x, y)); } const SkMatrix& PlatformGraphicsContextRecording::getTotalMatrix() @@ -524,7 +543,7 @@ const SkMatrix& PlatformGraphicsContextRecording::getTotalMatrix() void PlatformGraphicsContextRecording::addInnerRoundedRectClip(const IntRect& rect, int thickness) { - appendStateOperation(new GraphicsOperation::InnerRoundedRectClip(rect, thickness)); + appendStateOperation(NEW_OP(InnerRoundedRectClip)(rect, thickness)); } void PlatformGraphicsContextRecording::canvasClip(const Path& path) @@ -535,14 +554,14 @@ void PlatformGraphicsContextRecording::canvasClip(const Path& path) bool PlatformGraphicsContextRecording::clip(const FloatRect& rect) { clipState(rect); - appendStateOperation(new GraphicsOperation::Clip(rect)); + appendStateOperation(NEW_OP(Clip)(rect)); return true; } bool PlatformGraphicsContextRecording::clip(const Path& path) { clipState(path.boundingRect()); - appendStateOperation(new GraphicsOperation::ClipPath(path)); + appendStateOperation(NEW_OP(ClipPath)(path)); return true; } @@ -555,20 +574,20 @@ bool PlatformGraphicsContextRecording::clipConvexPolygon(size_t numPoints, bool PlatformGraphicsContextRecording::clipOut(const IntRect& r) { - appendStateOperation(new GraphicsOperation::ClipOut(r)); + appendStateOperation(NEW_OP(ClipOut)(r)); return true; } bool PlatformGraphicsContextRecording::clipOut(const Path& path) { - appendStateOperation(new GraphicsOperation::ClipPath(path, true)); + appendStateOperation(NEW_OP(ClipPath)(path, true)); return true; } bool PlatformGraphicsContextRecording::clipPath(const Path& pathToClip, WindRule clipRule) { clipState(pathToClip.boundingRect()); - GraphicsOperation::ClipPath* operation = new GraphicsOperation::ClipPath(pathToClip); + GraphicsOperation::ClipPath* operation = NEW_OP(ClipPath)(pathToClip); operation->setWindRule(clipRule); appendStateOperation(operation); return true; @@ -576,7 +595,7 @@ bool PlatformGraphicsContextRecording::clipPath(const Path& pathToClip, WindRule void PlatformGraphicsContextRecording::clearRect(const FloatRect& rect) { - appendDrawingOperation(new GraphicsOperation::ClearRect(rect), rect); + appendDrawingOperation(NEW_OP(ClearRect)(rect), rect); } //************************************** @@ -588,7 +607,7 @@ void PlatformGraphicsContextRecording::drawBitmapPattern( CompositeOperator compositeOp, const FloatRect& destRect) { appendDrawingOperation( - new GraphicsOperation::DrawBitmapPattern(bitmap, matrix, compositeOp, destRect), + NEW_OP(DrawBitmapPattern)(bitmap, matrix, compositeOp, destRect), destRect); } @@ -596,7 +615,7 @@ void PlatformGraphicsContextRecording::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, const SkRect& dst, CompositeOperator op) { - appendDrawingOperation(new GraphicsOperation::DrawBitmapRect(bitmap, *src, dst, op), dst); + appendDrawingOperation(NEW_OP(DrawBitmapRect)(bitmap, *src, dst, op), dst); } void PlatformGraphicsContextRecording::drawConvexPolygon(size_t numPoints, @@ -611,12 +630,12 @@ void PlatformGraphicsContextRecording::drawConvexPolygon(size_t numPoints, } FloatRect bounds; bounds.fitToPoints(points[0], points[1], points[2], points[3]); - appendDrawingOperation(new GraphicsOperation::DrawConvexPolygonQuad(points, shouldAntialias), bounds); + appendDrawingOperation(NEW_OP(DrawConvexPolygonQuad)(points, shouldAntialias), bounds); } void PlatformGraphicsContextRecording::drawEllipse(const IntRect& rect) { - appendDrawingOperation(new GraphicsOperation::DrawEllipse(rect), rect); + appendDrawingOperation(NEW_OP(DrawEllipse)(rect), rect); } void PlatformGraphicsContextRecording::drawFocusRing(const Vector<IntRect>& rects, @@ -628,7 +647,7 @@ void PlatformGraphicsContextRecording::drawFocusRing(const Vector<IntRect>& rect IntRect bounds = rects[0]; for (size_t i = 1; i < rects.size(); i++) bounds.unite(rects[i]); - appendDrawingOperation(new GraphicsOperation::DrawFocusRing(rects, width, offset, color), bounds); + appendDrawingOperation(NEW_OP(DrawFocusRing)(rects, width, offset, color), bounds); } void PlatformGraphicsContextRecording::drawHighlightForText( @@ -657,41 +676,41 @@ void PlatformGraphicsContextRecording::drawLine(const IntPoint& point1, float width = m_state->strokeThickness; if (!width) width = 1; bounds.inflate(width); - appendDrawingOperation(new GraphicsOperation::DrawLine(point1, point2), bounds); + appendDrawingOperation(NEW_OP(DrawLine)(point1, point2), bounds); } void PlatformGraphicsContextRecording::drawLineForText(const FloatPoint& pt, float width) { FloatRect bounds(pt.x(), pt.y(), width, m_state->strokeThickness); - appendDrawingOperation(new GraphicsOperation::DrawLineForText(pt, width), bounds); + appendDrawingOperation(NEW_OP(DrawLineForText)(pt, width), bounds); } void PlatformGraphicsContextRecording::drawLineForTextChecking(const FloatPoint& pt, float width, GraphicsContext::TextCheckingLineStyle lineStyle) { FloatRect bounds(pt.x(), pt.y(), width, m_state->strokeThickness); - appendDrawingOperation(new GraphicsOperation::DrawLineForTextChecking(pt, width, lineStyle), bounds); + appendDrawingOperation(NEW_OP(DrawLineForTextChecking)(pt, width, lineStyle), bounds); } void PlatformGraphicsContextRecording::drawRect(const IntRect& rect) { - appendDrawingOperation(new GraphicsOperation::DrawRect(rect), rect); + appendDrawingOperation(NEW_OP(DrawRect)(rect), rect); } void PlatformGraphicsContextRecording::fillPath(const Path& pathToFill, WindRule fillRule) { - appendDrawingOperation(new GraphicsOperation::FillPath(pathToFill, fillRule), pathToFill.boundingRect()); + appendDrawingOperation(NEW_OP(FillPath)(pathToFill, fillRule), pathToFill.boundingRect()); } void PlatformGraphicsContextRecording::fillRect(const FloatRect& rect) { - appendDrawingOperation(new GraphicsOperation::FillRect(rect), rect); + appendDrawingOperation(NEW_OP(FillRect)(rect), rect); } void PlatformGraphicsContextRecording::fillRect(const FloatRect& rect, const Color& color) { - GraphicsOperation::FillRect* operation = new GraphicsOperation::FillRect(rect); + GraphicsOperation::FillRect* operation = NEW_OP(FillRect)(rect); operation->setColor(color); appendDrawingOperation(operation, rect); } @@ -701,26 +720,26 @@ void PlatformGraphicsContextRecording::fillRoundedRect( const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color) { - appendDrawingOperation(new GraphicsOperation::FillRoundedRect(rect, topLeft, + appendDrawingOperation(NEW_OP(FillRoundedRect)(rect, topLeft, topRight, bottomLeft, bottomRight, color), rect); } void PlatformGraphicsContextRecording::strokeArc(const IntRect& r, int startAngle, int angleSpan) { - appendDrawingOperation(new GraphicsOperation::StrokeArc(r, startAngle, angleSpan), r); + appendDrawingOperation(NEW_OP(StrokeArc)(r, startAngle, angleSpan), r); } void PlatformGraphicsContextRecording::strokePath(const Path& pathToStroke) { - appendDrawingOperation(new GraphicsOperation::StrokePath(pathToStroke), pathToStroke.boundingRect()); + appendDrawingOperation(NEW_OP(StrokePath)(pathToStroke), pathToStroke.boundingRect()); } void PlatformGraphicsContextRecording::strokeRect(const FloatRect& rect, float lineWidth) { FloatRect bounds = rect; bounds.inflate(lineWidth); - appendDrawingOperation(new GraphicsOperation::StrokeRect(rect, lineWidth), bounds); + appendDrawingOperation(NEW_OP(StrokeRect)(rect, lineWidth), bounds); } void PlatformGraphicsContextRecording::drawPosText(const void* text, size_t byteLength, @@ -730,7 +749,7 @@ void PlatformGraphicsContextRecording::drawPosText(const void* text, size_t byte ALOGE("Unsupported text encoding! %d", paint.getTextEncoding()); } FloatRect bounds = approximateTextBounds(byteLength / sizeof(uint16_t), pos, paint); - appendDrawingOperation(new GraphicsOperation::DrawPosText(text, byteLength, pos, paint), bounds); + appendDrawingOperation(NEW_OP(DrawPosText)(text, byteLength, pos, paint), bounds); } void PlatformGraphicsContextRecording::clipState(const FloatRect& clip) @@ -757,7 +776,8 @@ void PlatformGraphicsContextRecording::popStateOperation() ALOGV("popStateOperation is deleting %p(isLayer=%d)", state.mCanvasState, state.mCanvasState->isTransparencyLayer()); mRecording->recording()->removeCanvasState(state.mCanvasState); - delete state.mCanvasState; + state.mCanvasState->~CanvasState(); + canvasStateHeap()->rewindTo(state.mCanvasState); } else { ALOGV("popStateOperation: %p(isLayer=%d)", state.mCanvasState, state.mCanvasState->isTransparencyLayer()); @@ -824,13 +844,12 @@ void PlatformGraphicsContextRecording::appendDrawingOperation( WebCore::IntRect ibounds = calculateFinalBounds(untranslatedBounds); if (ibounds.isEmpty()) { - ALOGV("Operation %s(%s) was clipped out", operation->name(), - operation->parameters().ascii().data()); - delete operation; + ALOGV("Operation %s() was clipped out", operation->name()); + operation->~Operation(); + operationHeap()->rewindTo(operation); return; } ALOGV("appendOperation %p->%s()", operation, operation->name()); - operation->m_globalBounds = ibounds; RecordingData* data = new RecordingData(operation, mRecording->recording()->m_nodeCount++); mRecording->recording()->m_tree.insert(ibounds, data); } @@ -842,4 +861,14 @@ void PlatformGraphicsContextRecording::appendStateOperation(GraphicsOperation::O mRecordingStateStack.last().mCanvasState->adoptAndAppend(data); } +LinearAllocator* PlatformGraphicsContextRecording::operationHeap() +{ + return mRecording->recording()->operationHeap(); +} + +LinearAllocator* PlatformGraphicsContextRecording::canvasStateHeap() +{ + return mRecording->recording()->canvasStateHeap(); +} + } // WebCore diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h index 3af1e2f..991e13f 100644 --- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h @@ -37,7 +37,9 @@ class Operation; } class CanvasState; +class LinearAllocator; class RecordingImpl; + class Recording : public SkRefCnt { public: Recording() @@ -152,6 +154,8 @@ private: void pushMatrix(); void popMatrix(); IntRect calculateFinalBounds(FloatRect bounds); + LinearAllocator* operationHeap(); + LinearAllocator* canvasStateHeap(); 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 c6b9854..fa048b7 100644 --- a/Source/WebCore/platform/graphics/android/context/RTree.cpp +++ b/Source/WebCore/platform/graphics/android/context/RTree.cpp @@ -166,15 +166,13 @@ void RTree::display() void* RTree::allocateNode() { - return m_allocator->alloc(); + return m_allocator->alloc(sizeof(Node)); } void RTree::deleteNode(Node* n) { - if (n) { + if (n) n->~Node(); - m_allocator->dealloc(n); - } } ////////////////////////////////////////////////////////////////////// @@ -187,6 +185,7 @@ ElementList::ElementList(int size) , m_minY(0) , m_maxY(0) , m_area(0) + , m_didTighten(false) { m_children = new Node*[size]; } @@ -196,22 +195,26 @@ ElementList::~ElementList() delete[] m_children; } -void ElementList::add(Node* node, bool doTighten) +void ElementList::add(Node* node) { m_children[m_nbChildren] = node; m_nbChildren++; - if (doTighten) - tighten(); + m_didTighten = false; } void ElementList::tighten() { + if (m_didTighten) + return; recomputeBounds(m_minX, m_minY, m_maxX, m_maxY, m_nbChildren, m_children, &m_area); + m_didTighten = true; } int ElementList::delta(Node* node) { + if (!m_didTighten) + tighten(); return computeDeltaArea(node, m_minX, m_minY, m_maxX, m_maxY); } @@ -223,6 +226,7 @@ void ElementList::removeAll() m_minY = 0; m_maxY = 0; m_area = 0; + m_didTighten = false; } void ElementList::display() { @@ -308,19 +312,21 @@ int Node::delta(Node* node) return computeDeltaArea(node, m_minX, m_minY, m_maxX, m_maxY); } -void Node::add(Node* node) +void Node::simpleAdd(Node* node) { node->setParent(this); if (!m_children) m_children = new Node*[m_tree->m_maxChildren + 1]; m_children[m_nbChildren] = node; m_nbChildren++; - Node* NN = 0; +} +void Node::add(Node* node) +{ + simpleAdd(node); + Node* NN = 0; if (m_nbChildren > m_tree->m_maxChildren) NN = split(); - else - tighten(); adjustTree(this, NN); } @@ -439,11 +445,12 @@ Node* Node::split() // Use the list to rebuild the nodes removeAll(); for (unsigned int i = 0; i < listA->m_nbChildren; i++) - add(listA->m_children[i]); + simpleAdd(listA->m_children[i]); Node* NN = Node::create(m_tree); for (unsigned int i = 0; i < listB->m_nbChildren; i++) - NN->add(listB->m_children[i]); + NN->simpleAdd(listB->m_children[i]); + NN->tighten(); return NN; } @@ -455,36 +462,52 @@ bool Node::isRoot() void Node::adjustTree(Node* N, Node* NN) { + bool callParent = N->updateBounds(); + if (N->isRoot() && NN) { // build new root Node* root = Node::create(m_tree); #ifdef DEBUG ALOGV("-> node %d created as new root", root->m_tid); #endif - root->add(N); - root->add(NN); + root->simpleAdd(N); + root->simpleAdd(NN); + root->tighten(); m_tree->m_root = root; return; } + if (N->isRoot()) return; if (N->m_parent) { - N->m_parent->tighten(); if (NN) N->m_parent->add(NN); - else + else if (callParent) adjustTree(N->m_parent, 0); } } +bool Node::updateBounds() +{ + int ominx = m_minX; + int ominy = m_minY; + int omaxx = m_maxX; + int omaxy = m_maxY; + tighten(); + if ((ominx != m_minX) + || (ominy != m_minY) + || (omaxx != m_maxX) + || (omaxy != m_maxY)) + return true; + return false; +} + #ifdef DEBUG static int gMaxLevel = 0; static int gNbNodes = 0; static int gNbElements = 0; -#endif -#ifdef DEBUG void Node::drawTree(int level) { if (level == 0) { diff --git a/Source/WebCore/platform/graphics/android/context/RTree.h b/Source/WebCore/platform/graphics/android/context/RTree.h index 4ad8986..366e3d1 100644 --- a/Source/WebCore/platform/graphics/android/context/RTree.h +++ b/Source/WebCore/platform/graphics/android/context/RTree.h @@ -41,7 +41,7 @@ public: , m_operation(ops) {} ~RecordingData() { - delete m_operation; + m_operation->~Operation(); } size_t m_orderBy; @@ -88,7 +88,7 @@ public: ElementList(int size); ~ElementList(); - void add(Node* n, bool doTighten = true); + void add(Node* n); void tighten(); int delta(Node* n); void removeAll(); @@ -104,6 +104,7 @@ private: int m_minY; int m_maxY; int m_area; + bool m_didTighten; }; class Node { @@ -133,6 +134,7 @@ private: void setParent(Node* n); Node* findNode(Node* n); + void simpleAdd(Node* n); void add(Node* n); void remove(Node* n); void destroy(int index); @@ -140,6 +142,7 @@ private: Node* split(); void adjustTree(Node* N, Node* NN); void tighten(); + bool updateBounds(); int delta(Node* n); bool overlap(int minx, int miny, int maxx, int maxy); diff --git a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp index e7617b1..1899557 100644 --- a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp +++ b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp @@ -27,7 +27,6 @@ #define LOG_NDEBUG 1 #include "config.h" - #include "LinearAllocator.h" #include "AndroidLog.h" @@ -40,6 +39,33 @@ namespace WebCore { // our pool needs to big enough to hold at least this many items #define MIN_OBJECT_COUNT 4 +#if LOG_NDEBUG +#define ADD_ALLOCATION(size) +#define RM_ALLOCATION(size) +#else +#include <utils/Thread.h> +static size_t s_totalAllocations = 0; +static double s_lastLogged = 0; +static android::Mutex s_mutex; + +static void _logUsageLocked() { + double now = currentTimeMS(); + if (now - s_lastLogged > 5) { + s_lastLogged = now; + ALOGV("Total memory usage: %d kb", s_totalAllocations / 1024); + } +} + +static void _addAllocation(size_t size) { + android::AutoMutex lock(s_mutex); + s_totalAllocations += size; + _logUsageLocked(); +} + +#define ADD_ALLOCATION(size) _addAllocation(size); +#define RM_ALLOCATION(size) _addAllocation(-size); +#endif + class LinearAllocator::Page { public: Page* next() { return m_nextPage; } @@ -64,30 +90,29 @@ private: Page* m_nextPage; }; -LinearAllocator::LinearAllocator(size_t allocSize) - : m_allocSize(allocSize) - , m_allocCount(0) - , m_next(0) +LinearAllocator::LinearAllocator(size_t averageAllocSize) + : m_next(0) , m_currentPage(0) , m_pages(0) { - int usable_page_size = TARGET_PAGE_SIZE - sizeof(LinearAllocator::Page); - int pcount = usable_page_size / allocSize; - if (pcount < MIN_OBJECT_COUNT) - pcount = MIN_OBJECT_COUNT; - m_pageSize = pcount * allocSize + sizeof(LinearAllocator::Page); + 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_maxAllocSize = (m_pageSize - sizeof(LinearAllocator::Page)); } LinearAllocator::~LinearAllocator(void) { - if (m_allocCount) - ALOGW("Leaked allocations!"); - IF_ALOGV() - ALOGV("Freeing to %dkb", memusage() >> 10); Page* p = m_pages; while (p) { Page* next = p->next(); delete p; + RM_ALLOCATION(m_pageSize); p = next; } } @@ -102,9 +127,9 @@ void* LinearAllocator::end(Page* p) return ((char*)p) + m_pageSize; } -void LinearAllocator::ensureNext() +void LinearAllocator::ensureNext(size_t size) { - if (m_next && m_next < end(m_currentPage)) + if (m_next && ((char*)m_next + size) <= end(m_currentPage)) return; Page* p = newPage(); if (m_currentPage) @@ -113,9 +138,6 @@ void LinearAllocator::ensureNext() if (!m_pages) m_pages = m_currentPage; m_next = start(m_currentPage); - - IF_ALOGV() - ALOGV("Allocator grew to %dkb", memusage() >> 10); } unsigned LinearAllocator::memusage() @@ -129,28 +151,28 @@ unsigned LinearAllocator::memusage() return memusage; } -void* LinearAllocator::alloc() +void* LinearAllocator::alloc(size_t size) { - m_allocCount++; - ensureNext(); + if (size > m_maxAllocSize) { + ALOGE("Allocation too large! (%d exceeds max size %d)", size, m_maxAllocSize); + return 0; + } + ensureNext(size); void* ptr = m_next; - m_next = ((char*)m_next) + m_allocSize; + m_next = ((char*)m_next) + size; return ptr; } -void LinearAllocator::dealloc(void* ptr) +void LinearAllocator::rewindTo(void* ptr) { - m_allocCount--; - if (m_next > start(m_currentPage)) { - // If this happened to be the previous allocation, just rewind m_next - void* prev = ((char*)m_next) - m_allocSize; - if (ptr == prev) - m_next = prev; - } + // Don't bother rewinding across pages + if (ptr >= start(m_currentPage) && ptr < end(m_currentPage)) + m_next = ptr; } LinearAllocator::Page* LinearAllocator::newPage() { + ADD_ALLOCATION(m_pageSize); void* buf = malloc(m_pageSize); return new (buf) Page(); } diff --git a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h index b0c584b..1f3265c 100644 --- a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h +++ b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h @@ -31,11 +31,11 @@ namespace WebCore { class LinearAllocator { public: - LinearAllocator(size_t allocSize); + LinearAllocator(size_t averageAllocSize = 0); ~LinearAllocator(); - void* alloc(); - void dealloc(void*); + void* alloc(size_t size); + void rewindTo(void*); private: LinearAllocator(const LinearAllocator& other); @@ -43,15 +43,14 @@ private: class Page; Page* newPage(); - void ensureNext(); + void ensureNext(size_t size); void* start(Page *p); void* end(Page* p); unsigned memusage(); - size_t m_allocSize; - size_t m_allocCount; size_t m_pageSize; + size_t m_maxAllocSize; void* m_next; Page* m_currentPage; Page* m_pages; diff --git a/Source/WebKit/android/jni/MockGeolocation.cpp b/Source/WebKit/android/jni/MockGeolocation.cpp index 164c37d..d588010 100755 --- a/Source/WebKit/android/jni/MockGeolocation.cpp +++ b/Source/WebKit/android/jni/MockGeolocation.cpp @@ -32,6 +32,7 @@ #include <GeolocationError.h> #include <GeolocationPosition.h> +#include "JNIHelp.h" #include "ScopedLocalRef.h" #include <wtf/CurrentTime.h> diff --git a/Source/WebKit/android/jni/PicturePile.cpp b/Source/WebKit/android/jni/PicturePile.cpp index 0731977..91f3e74 100644 --- a/Source/WebKit/android/jni/PicturePile.cpp +++ b/Source/WebKit/android/jni/PicturePile.cpp @@ -153,14 +153,30 @@ void PicturePile::setSize(const IntSize& size) { if (m_size == size) return; + IntSize oldSize = m_size; m_size = size; - // TODO: See above about just adding invals for new content - m_pile.clear(); - m_webkitInvals.clear(); - if (!size.isEmpty()) { - IntRect area(0, 0, size.width(), size.height()); - m_webkitInvals.append(area); - m_pile.append(area); + if (size.width() <= oldSize.width() && size.height() <= oldSize.height()) { + // We are shrinking - huzzah, nothing to do! + // TODO: Loop through and throw out Pictures that are now clipped out + } else if (oldSize.width() == size.width()) { + // Only changing vertically + IntRect rect(0, std::min(oldSize.height(), size.height()), + size.width(), std::abs(oldSize.height() - size.height())); + invalidate(rect); + } else if (oldSize.height() == size.height()) { + // Only changing horizontally + IntRect rect(std::min(oldSize.width(), size.width()), 0, + std::abs(oldSize.width() - size.width()), size.height()); + invalidate(rect); + } else { + // Both width & height changed, full inval :( + m_pile.clear(); + m_webkitInvals.clear(); + if (!size.isEmpty()) { + IntRect area(0, 0, size.width(), size.height()); + m_webkitInvals.append(area); + m_pile.append(area); + } } } |