diff options
21 files changed, 500 insertions, 117 deletions
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 3cbf43e..2807163 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -352,7 +352,6 @@ void GraphicsLayerAndroid::setSize(const FloatSize& size) } m_contentLayer->setSize(size.width(), size.height()); - m_contentLayer->setContent(0); setNeedsDisplay(); askForSync(); } @@ -844,24 +843,18 @@ bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer, TRACE_METHOD(); - if (!layer->content()) { - WebCore::PicturePile picture; - picture.setSize(IntSize(m_size.width(), m_size.height())); - PicturePileLayerContent* content = new PicturePileLayerContent(picture); - layer->setContent(content); - SkSafeUnref(content); - } - - PicturePileLayerContent* pcontent = static_cast<PicturePileLayerContent*>(layer->content()); - WebCore::PicturePile* layerContent = pcontent->picturePile(); - - // TODO: we might be able to reuse an existing picture instead of resetting it. - // we can't do that because of transparency -- for now, we just invalidate everything. - layerContent->reset(); - layerContent->setSize(IntSize(m_size.width(), m_size.height())); + // 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(m_size.width(), m_size.height())); // TODO: add content checks (text, opacity, etc.) - layerContent->updatePicturesIfNeeded(this); + picture.updatePicturesIfNeeded(this); + + PicturePileLayerContent* content = new PicturePileLayerContent(picture); + layer->setContent(content); + SkSafeUnref(content); return true; } diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h index 9ecf5c5..fc3b8bc 100644 --- a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h +++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h @@ -51,10 +51,8 @@ class Operation { public: typedef enum { UndefinedOperation // State management - , BeginTransparencyLayerOperation - , EndTransparencyLayerOperation + , TransparencyLayerOperation , SaveOperation - , RestoreOperation // State setters , SetAlphaOperation , SetCompositeOpOperation @@ -124,10 +122,8 @@ public: switch (type()) { TYPE_CASE(UndefinedOperation) // State management - TYPE_CASE(BeginTransparencyLayerOperation) - TYPE_CASE(EndTransparencyLayerOperation) + TYPE_CASE(TransparencyLayerOperation) TYPE_CASE(SaveOperation) - TYPE_CASE(RestoreOperation) // State setters TYPE_CASE(SetAlphaOperation) TYPE_CASE(SetCompositeOpOperation) @@ -180,28 +176,9 @@ public: // State management //************************************** -class BeginTransparencyLayer : public Operation { -public: - BeginTransparencyLayer(const float opacity) : m_opacity(opacity) {} - virtual bool applyImpl(PlatformGraphicsContext* context) { - context->beginTransparencyLayer(m_opacity); - return true; - } - virtual OperationType type() { return BeginTransparencyLayerOperation; } -private: - float m_opacity; -}; -class EndTransparencyLayer : public Operation { -public: - EndTransparencyLayer() {} - virtual bool applyImpl(PlatformGraphicsContext* context) { - context->endTransparencyLayer(); - return true; - } - virtual OperationType type() { return EndTransparencyLayerOperation; } -}; class Save : public Operation { public: + Save() : m_saveMatrix(true) {} virtual bool applyImpl(PlatformGraphicsContext* context) { context->save(); m_operations.apply(context); @@ -210,9 +187,27 @@ public: } virtual OperationType type() { return SaveOperation; } GraphicsOperationCollection* operations() { return &m_operations; } + bool saveMatrix() { return m_saveMatrix; } FloatRect bounds; -private: +protected: GraphicsOperationCollection m_operations; + bool m_saveMatrix : 1; +}; + +class TransparencyLayer : public Save { +public: + TransparencyLayer(const float opacity) : m_opacity(opacity) { + m_saveMatrix = false; + } + virtual bool applyImpl(PlatformGraphicsContext* context) { + context->beginTransparencyLayer(m_opacity); + m_operations.apply(context); + context->endTransparencyLayer(); + return true; + } + virtual OperationType type() { return TransparencyLayerOperation; } +private: + float m_opacity; }; //************************************** diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp index ba7f1a9..f11154d 100644 --- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp @@ -159,12 +159,13 @@ void Recording::setRecording(RecordingImpl* impl) PlatformGraphicsContextRecording::PlatformGraphicsContextRecording(Recording* recording) : PlatformGraphicsContext() , mPicture(0) - , mCurrentMatrix(&mRootMatrix) , mRecording(recording) , mOperationState(0) , mOperationMatrix(0) + , m_hasText(false) + , m_isEmpty(true) { - mRootMatrix.setIdentity(); + pushMatrix(); if (mRecording) mRecording->setRecording(new RecordingImpl()); } @@ -189,8 +190,9 @@ void PlatformGraphicsContextRecording::endRecording(const SkRect& bounds) GraphicsOperation::DrawComplexText* text = new GraphicsOperation::DrawComplexText(mPicture); appendDrawingOperation(text, bounds); mPicture = 0; -} + m_hasText = true; +} //************************************** // State management @@ -198,35 +200,24 @@ void PlatformGraphicsContextRecording::endRecording(const SkRect& bounds) void PlatformGraphicsContextRecording::beginTransparencyLayer(float opacity) { - appendStateOperation(new GraphicsOperation::BeginTransparencyLayer(opacity)); + pushSaveOperation(new GraphicsOperation::TransparencyLayer(opacity)); } void PlatformGraphicsContextRecording::endTransparencyLayer() { - appendStateOperation(new GraphicsOperation::EndTransparencyLayer()); + popSaveOperation(); } void PlatformGraphicsContextRecording::save() { PlatformGraphicsContext::save(); - mRecordingStateStack.append(new GraphicsOperation::Save()); - mCurrentMatrix = &(mRecordingStateStack.last().mMatrix); - mCurrentMatrix->setIdentity(); + pushSaveOperation(new GraphicsOperation::Save()); } void PlatformGraphicsContextRecording::restore() { PlatformGraphicsContext::restore(); - RecordingState state = mRecordingStateStack.last(); - mRecordingStateStack.removeLast(); - if (mRecordingStateStack.size()) - mCurrentMatrix = &(mRecordingStateStack.last().mMatrix); - else - mCurrentMatrix = &mRootMatrix; - if (state.mHasDrawing) - appendDrawingOperation(state.mSaveOperation, state.mBounds); - else - delete state.mSaveOperation; + popSaveOperation(); } //************************************** @@ -366,13 +357,10 @@ void PlatformGraphicsContextRecording::translate(float x, float y) const SkMatrix& PlatformGraphicsContextRecording::getTotalMatrix() { // Each RecordingState tracks the delta from its "parent" SkMatrix - if (mRecordingStateStack.size()) { - mTotalMatrix = mRootMatrix; - for (size_t i = 0; i < mRecordingStateStack.size(); i++) - mTotalMatrix.preConcat(mRecordingStateStack[i].mMatrix); - return mTotalMatrix; - } - return mRootMatrix; + mTotalMatrix = mMatrixStack.first(); + for (size_t i = 1; i < mMatrixStack.size(); i++) + mTotalMatrix.preConcat(mMatrixStack[i]); + return mTotalMatrix; } //************************************** @@ -577,6 +565,37 @@ void PlatformGraphicsContextRecording::clipState(const FloatRect& clip) } } +void PlatformGraphicsContextRecording::pushSaveOperation(GraphicsOperation::Save* saveOp) +{ + mRecordingStateStack.append(saveOp); + if (saveOp->saveMatrix()) + pushMatrix(); +} + +void PlatformGraphicsContextRecording::popSaveOperation() +{ + RecordingState state = mRecordingStateStack.last(); + mRecordingStateStack.removeLast(); + if (state.mSaveOperation->saveMatrix()) + popMatrix(); + if (state.mHasDrawing) + appendDrawingOperation(state.mSaveOperation, state.mBounds); + else + delete state.mSaveOperation; +} + +void PlatformGraphicsContextRecording::pushMatrix() +{ + mMatrixStack.append(SkMatrix::I()); + mCurrentMatrix = &(mMatrixStack.last()); +} + +void PlatformGraphicsContextRecording::popMatrix() +{ + mMatrixStack.removeLast(); + mCurrentMatrix = &(mMatrixStack.last()); +} + void PlatformGraphicsContextRecording::appendDrawingOperation( GraphicsOperation::Operation* operation, const FloatRect& untranslatedBounds) { @@ -584,6 +603,7 @@ void PlatformGraphicsContextRecording::appendDrawingOperation( ALOGW("Empty bounds for %s(%s)!", operation->name(), operation->parameters().ascii().data()); return; } + m_isEmpty = false; SkRect bounds; mCurrentMatrix->mapRect(&bounds, untranslatedBounds); if (mRecordingStateStack.size()) { @@ -596,7 +616,7 @@ void PlatformGraphicsContextRecording::appendDrawingOperation( if (!mOperationState) mOperationState = mRecording->recording()->getState(m_state); if (!mOperationMatrix) - mOperationMatrix = mRecording->recording()->cloneMatrix(mRootMatrix); + mOperationMatrix = mRecording->recording()->cloneMatrix(mMatrixStack.first()); operation->m_state = mOperationState; operation->m_matrix = mOperationMatrix; RecordingData* data = new RecordingData(operation, mRecording->recording()->m_nodeCount++); @@ -617,7 +637,7 @@ void PlatformGraphicsContextRecording::appendStateOperation(GraphicsOperation::O void PlatformGraphicsContextRecording::onCurrentMatrixChanged() { - if (mCurrentMatrix == &mRootMatrix) + if (mCurrentMatrix == &(mMatrixStack.first())) mOperationMatrix = 0; } diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h index 3affff3..89f9bbb 100644 --- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h @@ -136,6 +136,8 @@ public: virtual void strokePath(const Path& pathToStroke); virtual void strokeRect(const FloatRect& rect, float lineWidth); + bool hasText() { return m_hasText; } + bool isEmpty() { return m_isEmpty; } private: virtual bool shadowsIgnoreTransforms() const { @@ -146,9 +148,12 @@ private: void appendDrawingOperation(GraphicsOperation::Operation* operation, const FloatRect& bounds); void appendStateOperation(GraphicsOperation::Operation* operation); void onCurrentMatrixChanged(); + void pushSaveOperation(GraphicsOperation::Save* saveOp); + void popSaveOperation(); + void pushMatrix(); + void popMatrix(); SkPicture* mPicture; - SkMatrix mRootMatrix; SkMatrix* mCurrentMatrix; // Used for getTotalMatrix, is not valid elsewhere SkMatrix mTotalMatrix; @@ -167,7 +172,6 @@ private: , mHasDrawing(other.mHasDrawing) , mHasClip(other.mHasClip) , mBounds(other.mBounds) - , mMatrix(other.mMatrix) {} void addBounds(const FloatRect& bounds) @@ -187,11 +191,14 @@ private: bool mHasDrawing; bool mHasClip; FloatRect mBounds; - SkMatrix mMatrix; }; Vector<RecordingState> mRecordingStateStack; + Vector<SkMatrix> mMatrixStack; State* mOperationState; SkMatrix* mOperationMatrix; + + bool m_hasText; + bool m_isEmpty; }; } diff --git a/Source/WebCore/platform/graphics/android/context/RTree.cpp b/Source/WebCore/platform/graphics/android/context/RTree.cpp index fef30b3..69ecf29 100644 --- a/Source/WebCore/platform/graphics/android/context/RTree.cpp +++ b/Source/WebCore/platform/graphics/android/context/RTree.cpp @@ -318,8 +318,10 @@ void Node::add(Node* node) Node* NN = 0; if (m_nbChildren > m_tree->m_maxChildren) NN = split(); + else + tighten(); + adjustTree(this, NN); - tighten(); } void Node::remove(Node* node) @@ -462,6 +464,9 @@ void Node::adjustTree(Node* N, Node* NN) if (N->isRoot()) return; + if (N->m_parent) + N->m_parent->tighten(); + if (NN && N->m_parent) N->m_parent->add(NN); } diff --git a/Source/WebCore/platform/graphics/android/layers/LayerContent.h b/Source/WebCore/platform/graphics/android/layers/LayerContent.h index 10b6507..a18e4c8 100644 --- a/Source/WebCore/platform/graphics/android/layers/LayerContent.h +++ b/Source/WebCore/platform/graphics/android/layers/LayerContent.h @@ -42,7 +42,7 @@ class LayerContent : public SkRefCnt { public: virtual int width() = 0; virtual int height() = 0; - virtual bool isEmpty() { return !width() || !height(); } + bool isEmpty() { return !width() || !height(); } virtual void setCheckForOptimisations(bool check) = 0; virtual void checkForOptimisations() = 0; virtual bool hasText() = 0; diff --git a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp index f012c42..e40c9b6 100644 --- a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp +++ b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp @@ -45,16 +45,6 @@ int PictureLayerContent::height() return m_picture->height(); } -bool PictureLayerContent::isEmpty() -{ - if (!m_picture) - return true; - if (m_picture->width() == 0 - || m_picture->height() == 0) - return true; - return false; -} - void PictureLayerContent::checkForOptimisations() { if (!m_checkedContent) diff --git a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h index 1567f44..cf633cb 100644 --- a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h +++ b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h @@ -38,7 +38,6 @@ public: virtual int width(); virtual int height(); - virtual bool isEmpty(); virtual void setCheckForOptimisations(bool check) { m_checkedContent = !check; } virtual void checkForOptimisations(); virtual bool hasText(); diff --git a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp index 5d516af..1167bda 100644 --- a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp +++ b/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp @@ -12,6 +12,8 @@ namespace WebCore { PicturePileLayerContent::PicturePileLayerContent(const PicturePile& picturePile) : m_picturePile(picturePile) + , m_hasText(picturePile.hasText()) + , m_hasContent(!picturePile.isEmpty()) { } @@ -20,6 +22,9 @@ void PicturePileLayerContent::draw(SkCanvas* canvas) TRACE_METHOD(); android::Mutex::Autolock lock(m_drawLock); m_picturePile.draw(canvas); + + if (CC_UNLIKELY(!m_hasContent)) + ALOGW("Warning: painting PicturePile without content!"); } void PicturePileLayerContent::serialize(SkWStream* stream) diff --git a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.h b/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.h index f2b7c61..9f3a263 100644 --- a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.h +++ b/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.h @@ -35,11 +35,13 @@ class PicturePileLayerContent : public LayerContent { public: PicturePileLayerContent(const PicturePile& picturePile); - virtual int width() { return m_picturePile.size().width(); } - virtual int height() { return m_picturePile.size().height(); } + // return 0 when no content, so don't have to paint + virtual int width() { return m_hasContent ? m_picturePile.size().width() : 0; } + virtual int height() { return m_hasContent ? m_picturePile.size().height() : 0; } + virtual void setCheckForOptimisations(bool check) {} - virtual void checkForOptimisations() {} - virtual bool hasText() { return true; } + virtual void checkForOptimisations() {} // already performed, stored in m_hasText/m_hasContent + virtual bool hasText() { return m_hasText; } virtual void draw(SkCanvas* canvas); virtual void serialize(SkWStream* stream); virtual PrerenderedInval* prerenderForRect(const IntRect& dirty); @@ -48,6 +50,8 @@ public: private: PicturePile m_picturePile; + bool m_hasText; + bool m_hasContent; }; } // WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp index 6f679da..65e28f9 100644 --- a/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp @@ -34,6 +34,7 @@ #include "AndroidLog.h" #include "GaneshRenderer.h" #include "GLUtils.h" +#include "InstrumentedPlatformCanvas.h" #include "RasterRenderer.h" #include "SkBitmap.h" #include "SkBitmapRef.h" @@ -94,7 +95,8 @@ void BaseRenderer::renderTiledContent(TileRenderInfo& renderInfo) const bool visualIndicator = TilesManager::instance()->getShowVisualIndicator(); const SkSize& tileSize = renderInfo.tileSize; - SkCanvas canvas; + InstrumentedPlatformCanvas canvas(TilesManager::instance()->tileWidth(), + TilesManager::instance()->tileHeight()); setupCanvas(renderInfo, &canvas); if (!canvas.getDevice()) { @@ -112,10 +114,8 @@ void BaseRenderer::renderTiledContent(TileRenderInfo& renderInfo) canvas.translate(-renderInfo.x * tileSize.width(), -renderInfo.y * tileSize.height()); canvas.scale(renderInfo.scale, renderInfo.scale); renderInfo.tilePainter->paint(&canvas); - if (renderInfo.baseTile && renderInfo.baseTile->backTexture()) - checkForPureColor(renderInfo, &canvas); - else - renderInfo.isPureColor = false; + + checkForPureColor(renderInfo, canvas); if (visualIndicator) { double after = currentTimeMS(); @@ -144,6 +144,13 @@ void BaseRenderer::renderTiledContent(TileRenderInfo& renderInfo) renderingComplete(renderInfo, &canvas); } +void BaseRenderer::checkForPureColor(TileRenderInfo& renderInfo, InstrumentedPlatformCanvas& canvas) +{ + renderInfo.isPureColor = canvas.isSolidColor(); + renderInfo.pureColor = canvas.solidColor(); + deviceCheckForPureColor(renderInfo, &canvas); +} + } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h index b25a50e..dc8831a 100644 --- a/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h +++ b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h @@ -37,6 +37,7 @@ class SkDevice; namespace WebCore { +class InstrumentedPlatformCanvas; class TextureInfo; class TilePainter; class Tile; @@ -87,7 +88,10 @@ protected: virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; - virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; + void checkForPureColor(TileRenderInfo& renderInfo, InstrumentedPlatformCanvas& canvas); + + // performs additional pure color check, renderInfo.isPureColor may already be set to true + virtual void deviceCheckForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; void drawTileInfo(SkCanvas* canvas, const TileRenderInfo& renderInfo, int updateCount, double renderDuration); diff --git a/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h index cdd9f3e..77982e8 100644 --- a/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h +++ b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h @@ -48,9 +48,7 @@ protected: virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas); virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas); - virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) { - renderInfo.isPureColor = false; - } + virtual void deviceCheckForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) {} }; diff --git a/Source/WebCore/platform/graphics/android/rendering/InstrumentedPlatformCanvas.h b/Source/WebCore/platform/graphics/android/rendering/InstrumentedPlatformCanvas.h new file mode 100644 index 0000000..faa5bcd --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/InstrumentedPlatformCanvas.h @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2011 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef InstrumentedPlatformCanvas_h +#define InstrumentedPlatformCanvas_h + +#include "SkCanvas.h" + +#define DEBUG_SKIA_DRAWING 0 +#if DEBUG_SKIA_DRAWING +#define WRAPCANVAS_LOG_ENTRY(...) do { \ + fprintf(stderr, "%s ", __FUNCTION__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ +} while (0) +#else +#define WRAPCANVAS_LOG_ENTRY(...) ((void)0) +#endif + +namespace WebCore { + +class InstrumentedPlatformCanvas : public SkCanvas { +public: + InstrumentedPlatformCanvas(int width, int height) + : m_size(width, height) + , m_isSolidColor(true) + , m_solidColor(0, 0, 0, 0) + { + } + + virtual ~InstrumentedPlatformCanvas() { } + + bool isSolidColor() const { return m_isSolidColor; } + Color solidColor() const { return m_solidColor; } + + // overrides from SkCanvas + virtual int save(SaveFlags flags = kMatrixClip_SaveFlag) + { + WRAPCANVAS_LOG_ENTRY(""); + return SkCanvas::save(flags); + } + + virtual int saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + return SkCanvas::saveLayer(bounds, paint, flags); + } + + virtual void restore() + { + WRAPCANVAS_LOG_ENTRY(""); + SkCanvas::restore(); + } + + virtual bool translate(SkScalar dx, SkScalar dy) + { + WRAPCANVAS_LOG_ENTRY(""); + return SkCanvas::translate(dx, dy); + } + + virtual bool scale(SkScalar sx, SkScalar sy) + { + WRAPCANVAS_LOG_ENTRY(""); + return SkCanvas::scale(sx, sy); + } + + virtual bool rotate(SkScalar degrees) + { + WRAPCANVAS_LOG_ENTRY(""); + return SkCanvas::rotate(degrees); + } + + virtual bool skew(SkScalar sx, SkScalar sy) + { + WRAPCANVAS_LOG_ENTRY(""); + return SkCanvas::skew(sx, sy); + } + + virtual bool concat(const SkMatrix& matrix) + { + WRAPCANVAS_LOG_ENTRY(""); + return SkCanvas::concat(matrix); + } + + virtual void setMatrix(const SkMatrix& matrix) + { + WRAPCANVAS_LOG_ENTRY(""); + SkCanvas::setMatrix(matrix); + } + + virtual bool clipRect(const SkRect& rect, SkRegion::Op op) + { + WRAPCANVAS_LOG_ENTRY(""); + return SkCanvas::clipRect(rect, op); + } + + virtual bool clipPath(const SkPath& path, SkRegion::Op op) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + return SkCanvas::clipPath(path, op); + } + + virtual bool clipRegion(const SkRegion& region, SkRegion::Op op) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + return SkCanvas::clipRegion(region, op); + } + + virtual void clear(SkColor color) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = true; + m_solidColor = Color(color); + SkCanvas::clear(color); + } + + virtual void drawPaint(const SkPaint& paint) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawPaint(paint); + } + + virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[], + const SkPaint& paint) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawPoints(mode, count, pts, paint); + } + + virtual void drawRect(const SkRect& rect, const SkPaint& paint) + { +#if DEBUG_SKIA_DRAWING + IntRect rectToDraw(rect); + WRAPCANVAS_LOG_ENTRY("rect = (x=%d,y=%d,width=%d,height=%d)", INT_RECT_ARGS(rectToDraw); +#endif + IntRect canvasRect(IntPoint(), m_size); + if (m_isSolidColor + && getTotalMatrix().rectStaysRect() + && getTotalClip().contains(canvasRect)) { + const SkMatrix& matrix = getTotalMatrix(); + SkRect mapped; + matrix.mapRect(&mapped, rect); + if (mapped.contains(canvasRect)) { + Color color = solidColor(paint); + m_isSolidColor = color.isValid(); + m_solidColor = color; + } else + m_isSolidColor = false; + } else + m_isSolidColor = false; + SkCanvas::drawRect(rect, paint); + } + + virtual void drawPath(const SkPath& path, const SkPaint& paint) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawPath(path, paint); + } + + virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, + SkScalar top, const SkPaint* paint) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawBitmap(bitmap, left, top, paint); + } + + virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, + const SkRect& dst, const SkPaint* paint) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawBitmapRect(bitmap, src, dst, paint); + } + + virtual void drawBitmapMatrix(const SkBitmap& bitmap, + const SkMatrix& matrix, const SkPaint* paint) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawBitmapMatrix(bitmap, matrix, paint); + } + + virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, + const SkRect& dst, const SkPaint* paint = 0) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawBitmapNine(bitmap, center, dst, paint); + } + + virtual void drawSprite(const SkBitmap& bitmap, int left, int top, + const SkPaint* paint) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawSprite(bitmap, left, top, paint); + } + + virtual void drawText(const void* text, size_t byteLength, SkScalar x, + SkScalar y, const SkPaint& paint) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawText(text, byteLength, x, y, paint); + } + + virtual void drawPosText(const void* text, size_t byteLength, + const SkPoint pos[], const SkPaint& paint) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawPosText(text, byteLength, pos, paint); + } + + virtual void drawPosTextH(const void* text, size_t byteLength, + const SkScalar xpos[], SkScalar constY, const SkPaint& paint) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawPosTextH(text, byteLength, xpos, constY, paint); + } + + virtual void drawTextOnPath(const void* text, size_t byteLength, + const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawTextOnPath(text, byteLength, path, matrix, paint); + } + + virtual void drawPicture(SkPicture& picture) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawPicture(picture); + } + + virtual void drawVertices(VertexMode mode, int vertexCount, + const SkPoint vertices[], const SkPoint texs[], + const SkColor colors[], SkXfermode* xfermode, + const uint16_t indices[], int indexCount, const SkPaint& paint) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawVertices(mode, vertexCount, vertices, texs, + colors, xfermode, indices, indexCount, paint); + } + + virtual void drawData(const void* data, size_t size) + { + WRAPCANVAS_LOG_ENTRY(""); + m_isSolidColor = false; + SkCanvas::drawData(data, size); + } + +private: + Color solidColor(const SkPaint& paint) + { + if (paint.getStyle() != SkPaint::kFill_Style) + return Color(); + if (paint.getLooper() || paint.getShader()) + return Color(); + + SkXfermode::Mode mode; + SkXfermode::AsMode(paint.getXfermode(), &mode); + if (mode == SkXfermode::kClear_Mode) + return Color(0, 0, 0, 0); + + if ((mode == SkXfermode::kSrcOver_Mode && paint.getAlpha() == 255) + || mode == SkXfermode::kSrc_Mode) + return Color(paint.getColor()); + return Color(); + } + + IntSize m_size; + bool m_isSolidColor; + Color m_solidColor; + SkPaint m_solidPaint; +}; + +} // namespace WebCore + +#endif // InstrumentedPlatformCanvas_h diff --git a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp index 5c78ad9..fd26380 100644 --- a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp @@ -101,12 +101,16 @@ void RasterRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanva GLUtils::paintTextureWithBitmap(&renderInfo, m_bitmap); } -void RasterRenderer::checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) +void RasterRenderer::deviceCheckForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) { - m_bitmapIsPureColor = GLUtils::isPureColorBitmap(m_bitmap, m_bitmapPureColor); + if (!renderInfo.isPureColor) { + // base renderer may have already determined isPureColor, so only do the + // brute force check if needed + renderInfo.isPureColor = GLUtils::isPureColorBitmap(m_bitmap, renderInfo.pureColor); + } - renderInfo.isPureColor = m_bitmapIsPureColor; - renderInfo.pureColor = m_bitmapPureColor; + m_bitmapIsPureColor = renderInfo.isPureColor; + m_bitmapPureColor = renderInfo.pureColor; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h index 34b57ca..791c6b6 100644 --- a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h +++ b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h @@ -48,7 +48,7 @@ public: protected: virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas); virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas); - virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas); + virtual void deviceCheckForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas); private: SkBitmap m_bitmap; diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp index d7f6535..5b11df6 100644 --- a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp @@ -40,13 +40,15 @@ namespace WebCore { SurfaceBacking::SurfaceBacking(bool isBaseSurface) + : m_frontTileGrid(new TileGrid(isBaseSurface)) + , m_backTileGrid(new TileGrid(isBaseSurface)) + , m_lowResTileGrid(new TileGrid(isBaseSurface)) + , m_scale(-1) + , m_futureScale(-1) + , m_zooming(false) + , m_hasAllowedZoom(false) + { - m_frontTileGrid = new TileGrid(isBaseSurface); - m_backTileGrid = new TileGrid(isBaseSurface); - m_lowResTileGrid = new TileGrid(isBaseSurface); - m_scale = -1; - m_futureScale = -1; - m_zooming = false; #ifdef DEBUG_COUNT ClassTracker::instance()->increment("SurfaceBacking"); #endif @@ -67,9 +69,16 @@ void SurfaceBacking::prepareGL(GLWebViewState* state, bool allowZoom, TilePainter* painter, bool aggressiveRendering, bool updateWithBlit) { + // If the surface backing has ever zoomed beyond 1.0 scale, it's always + // allowed to (so repaints aren't necessary when allowZoom toggles). If not, + // and allowZoom is false, don't allow scale greater than 1.0 + m_hasAllowedZoom |= allowZoom; float scale = state->scale(); - if (scale > 1 && !allowZoom) + bool scaleOverridden = false; + if (scale > 1 && !m_hasAllowedZoom) { scale = 1; + scaleOverridden = true; + } if (m_scale == -1) { m_scale = scale; @@ -78,7 +87,10 @@ void SurfaceBacking::prepareGL(GLWebViewState* state, bool allowZoom, if (m_futureScale != scale) { m_futureScale = scale; - m_zoomUpdateTime = WTF::currentTime() + SurfaceBacking::s_zoomUpdateDelay; + if (scaleOverridden) + m_zoomUpdateTime = 0; // start rendering immediately + else + m_zoomUpdateTime = WTF::currentTime() + SurfaceBacking::s_zoomUpdateDelay; m_zooming = true; // release back TileGrid's TileTextures, so they can be reused immediately diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h index 5709f2a..06929e1 100644 --- a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h @@ -95,6 +95,7 @@ private: float m_futureScale; double m_zoomUpdateTime; bool m_zooming; + bool m_hasAllowedZoom; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp index bd63c38..e7617b1 100644 --- a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp +++ b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp @@ -24,7 +24,7 @@ */ #define LOG_TAG "LinearAllocator" -#define LOG_NDEBUG 0 +#define LOG_NDEBUG 1 #include "config.h" diff --git a/Source/WebKit/android/jni/PicturePile.cpp b/Source/WebKit/android/jni/PicturePile.cpp index b69c131..554bd1b 100644 --- a/Source/WebKit/android/jni/PicturePile.cpp +++ b/Source/WebKit/android/jni/PicturePile.cpp @@ -277,6 +277,24 @@ PrerenderedInval* PicturePile::prerenderedInvalForArea(const IntRect& area) return 0; } +bool PicturePile::hasText() const +{ + for (size_t i = 0; i < m_pile.size(); i++) { + if (m_pile[i].hasText) + return true; + } + return false; +} + +bool PicturePile::isEmpty() const +{ + for (size_t i = 0; i < m_pile.size(); i++) { + if (m_pile[i].picture) + return false; + } + return true; +} + #if USE_RECORDING_CONTEXT void PicturePile::drawPicture(SkCanvas* canvas, PictureContainer& pc) { @@ -286,12 +304,18 @@ void PicturePile::drawPicture(SkCanvas* canvas, PictureContainer& pc) Picture* PicturePile::recordPicture(PicturePainter* painter, PictureContainer& pc) { - // TODO: Support? Not needed? - pc.prerendered.clear(); + pc.prerendered.clear(); // TODO: Support? Not needed? + Recording* picture = new Recording(); WebCore::PlatformGraphicsContextRecording pgc(picture); WebCore::GraphicsContext gc(&pgc); painter->paintContents(&gc, pc.area); + pc.hasText = pgc.hasText(); + if (pgc.isEmpty()) { + SkSafeUnref(picture); + picture = 0; + } + return picture; } #else @@ -336,6 +360,10 @@ Picture* PicturePile::recordPicture(PicturePainter* painter, PictureContainer& p WebCore::GraphicsContext gc(&pgc); ALOGV("painting picture: " INT_RECT_FORMAT, INT_RECT_ARGS(drawArea)); painter->paintContents(&gc, drawArea); + + // TODO: consider paint-time checking for these with SkPicture painting? + pc.hasText = true; + SkSafeUnref(canvas); picture->endRecording(); return picture; diff --git a/Source/WebKit/android/jni/PicturePile.h b/Source/WebKit/android/jni/PicturePile.h index a8175d9..6e3e46d 100644 --- a/Source/WebKit/android/jni/PicturePile.h +++ b/Source/WebKit/android/jni/PicturePile.h @@ -38,7 +38,7 @@ #include <wtf/ThreadSafeRefCounted.h> #include <wtf/Vector.h> -#define USE_RECORDING_CONTEXT false +#define USE_RECORDING_CONTEXT true #if USE_RECORDING_CONTEXT namespace WebCore { class Recording; @@ -71,11 +71,13 @@ public: IntRect area; bool dirty; RefPtr<PrerenderedInval> prerendered; + bool hasText; PictureContainer(const IntRect& area) : picture(0) , area(area) , dirty(true) + , hasText(false) {} PictureContainer(const PictureContainer& other); @@ -102,6 +104,10 @@ public: SkRegion& dirtyRegion() { return m_dirtyRegion; } PrerenderedInval* prerenderedInvalForArea(const IntRect& area); + // UI-side methods used to check content, after construction/updates are complete + bool hasText() const; + bool isEmpty() const; + private: void applyWebkitInvals(); void updatePicture(PicturePainter* painter, PictureContainer& container); |