diff options
39 files changed, 598 insertions, 298 deletions
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 779dba5..5fe9a1f 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -853,6 +853,7 @@ bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer, if (!layer) return false; + TRACE_METHOD(); SkPicture* picture = paintPicture(rect); if (!picture) return false; diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp index 9e6208d..829be2e 100644 --- a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp +++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp @@ -13,8 +13,7 @@ namespace WebCore { -GraphicsOperationCollection::GraphicsOperationCollection(const IntRect& drawArea) - : m_drawArea(drawArea) +GraphicsOperationCollection::GraphicsOperationCollection() { } @@ -44,9 +43,9 @@ bool GraphicsOperationCollection::isEmpty() return !m_operations.size(); } -AutoGraphicsOperationCollection::AutoGraphicsOperationCollection(const IntRect& area) +AutoGraphicsOperationCollection::AutoGraphicsOperationCollection() { - m_graphicsOperationCollection = new GraphicsOperationCollection(area); + m_graphicsOperationCollection = new GraphicsOperationCollection(); m_platformGraphicsContext = new PlatformGraphicsContextRecording(m_graphicsOperationCollection); m_graphicsContext = new GraphicsContext(m_platformGraphicsContext); } diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h index 9d7b530..d3fc16b 100644 --- a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h +++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h @@ -39,7 +39,7 @@ class PlatformGraphicsContext; class GraphicsOperationCollection : public SkRefCnt { public: - GraphicsOperationCollection(const IntRect& drawArea); + GraphicsOperationCollection(); ~GraphicsOperationCollection(); void apply(PlatformGraphicsContext* context); @@ -48,13 +48,12 @@ public: bool isEmpty(); private: - IntRect m_drawArea; Vector<GraphicsOperation::Operation*> m_operations; }; class AutoGraphicsOperationCollection { public: - AutoGraphicsOperationCollection(const IntRect& area); + AutoGraphicsOperationCollection(); ~AutoGraphicsOperationCollection(); GraphicsContext* context() { return m_graphicsContext; } GraphicsOperationCollection* picture() { return m_graphicsOperationCollection; } diff --git a/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp b/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp index 5551965..d827c44 100644 --- a/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp +++ b/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp @@ -3,79 +3,87 @@ #if USE(ACCELERATED_COMPOSITING) +#define WRITE_VAL(format, ...) (snprintf(m_valueBuffer, BUF_SIZE, format, __VA_ARGS__), writeEntry(label, m_valueBuffer)) + namespace WebCore { -void lwrite(FILE* file, const char* str) +void LayerDumper::writeIntVal(const char* label, int value) { - fwrite(str, sizeof(char), strlen(str), file); + WRITE_VAL("%d", value); } -void writeIndent(FILE* file, int indentLevel) +void LayerDumper::writeHexVal(const char* label, int value) { - if (indentLevel) - fprintf(file, "%*s", indentLevel*2, " "); + WRITE_VAL("%x", value); } -void writeln(FILE* file, int indentLevel, const char* str) +void LayerDumper::writeFloatVal(const char* label, float value) { - writeIndent(file, indentLevel); - lwrite(file, str); - lwrite(file, "\n"); + WRITE_VAL("%.3f", value); } -void writeIntVal(FILE* file, int indentLevel, const char* str, int value) +void LayerDumper::writePoint(const char* label, SkPoint point) { - writeIndent(file, indentLevel); - fprintf(file, "%s = %d;\n", str, value); + WRITE_VAL("{ x = %.3f; y = %.3f; }", point.fX, point.fY); } -void writeHexVal(FILE* file, int indentLevel, const char* str, int value) +void LayerDumper::writeIntPoint(const char* label, IntPoint point) { - writeIndent(file, indentLevel); - fprintf(file, "%s = %x;\n", str, value); + WRITE_VAL("{ x = %d; y = %d; }", point.x(), point.y()); } -void writeFloatVal(FILE* file, int indentLevel, const char* str, float value) +void LayerDumper::writeSize(const char* label, SkSize size) { - writeIndent(file, indentLevel); - fprintf(file, "%s = %.3f;\n", str, value); + WRITE_VAL("{ w = %.3f; h = %.3f; }", size.width(), size.height()); } -void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point) +void LayerDumper::writeRect(const char* label, SkRect rect) { - writeIndent(file, indentLevel); - fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY); + WRITE_VAL("{ x = %.3f; y = %.3f; w = %.3f; h = %.3f; }", + rect.fLeft, rect.fTop, rect.width(), rect.height()); } -void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point) +void LayerDumper::writeMatrix(const char* label, const TransformationMatrix& matrix) { - writeIndent(file, indentLevel); - fprintf(file, "%s = { x = %d; y = %d; };\n", str, point.x(), point.y()); + WRITE_VAL("{ (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f)," + "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) }", + matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(), + matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(), + matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(), + matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()); } -void writeSize(FILE* file, int indentLevel, const char* str, SkSize size) +void LayerDumper::writeLength(const char* label, SkLength value) { - writeIndent(file, indentLevel); - fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height()); + if (value.defined()) + WRITE_VAL("{ type = %d; value = %.2f; }", value.type, value.value); + else + writeEntry(label, "<undefined>"); } -void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect) +void FileLayerDumper::beginLayer(const char* className, const LayerAndroid* layerPtr) { - writeIndent(file, indentLevel); - fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n", - str, rect.fLeft, rect.fTop, rect.width(), rect.height()); + LayerDumper::beginLayer(className, layerPtr); + writeLine("{"); + writeHexVal("layer", (int)layerPtr); } -void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix) +void FileLayerDumper::endLayer() { - writeIndent(file, indentLevel); - fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f)," - "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n", - str, - matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(), - matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(), - matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(), - matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()); + writeLine("}"); + LayerDumper::endLayer(); +} + +void FileLayerDumper::writeEntry(const char* label, const char* value) +{ + fprintf(m_file, "%*s%s = %s\n", (m_indentLevel + 1) * 2, " ", label, value); +} + +void FileLayerDumper::writeLine(const char* str) +{ + if (m_indentLevel) + fprintf(m_file, "%*s", m_indentLevel * 2, " "); + fprintf(m_file, "%s\n", str); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/layers/DumpLayer.h b/Source/WebCore/platform/graphics/android/layers/DumpLayer.h index 5b30952..9fd3365 100644 --- a/Source/WebCore/platform/graphics/android/layers/DumpLayer.h +++ b/Source/WebCore/platform/graphics/android/layers/DumpLayer.h @@ -17,7 +17,9 @@ #ifndef DumpLayer_h #define DumpLayer_h +#include "FixedPositioning.h" #include "IntPoint.h" +#include "LayerAndroid.h" #include "SkPoint.h" #include "SkRect.h" #include "SkSize.h" @@ -50,17 +52,59 @@ namespace WebCore { -void lwrite(FILE* file, const char* str); -void writeIndent(FILE* file, int indentLevel); -void writeln(FILE* file, int indentLevel, const char* str); -void writeIntVal(FILE* file, int indentLevel, const char* str, int value); -void writeHexVal(FILE* file, int indentLevel, const char* str, int value); -void writeFloatVal(FILE* file, int indentLevel, const char* str, float value); -void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point); -void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point); -void writeSize(FILE* file, int indentLevel, const char* str, SkSize size); -void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect); -void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix); +class LayerDumper { +public: + LayerDumper(int initialIndentLevel = 0) + : m_indentLevel(initialIndentLevel) + {} + virtual ~LayerDumper() {} + + virtual void beginLayer(const char* className, const LayerAndroid* layerPtr) {} + + virtual void endLayer() {} + + virtual void beginChildren(int childCount) { + m_indentLevel++; + } + virtual void endChildren() { + m_indentLevel--; + } + + void writeIntVal(const char* label, int value); + void writeHexVal(const char* label, int value); + void writeFloatVal(const char* label, float value); + void writePoint(const char* label, SkPoint value); + void writeIntPoint(const char* label, IntPoint value); + void writeSize(const char* label, SkSize value); + void writeRect(const char* label, SkRect value); + void writeMatrix(const char* label, const TransformationMatrix& value); + void writeLength(const char* label, SkLength value); + +protected: + virtual void writeEntry(const char* label, const char* value) = 0; + + int m_indentLevel; + +private: + static const int BUF_SIZE = 4096; + char m_valueBuffer[BUF_SIZE]; +}; + +class FileLayerDumper : public LayerDumper { +public: + FileLayerDumper(FILE* file) + : m_file(file) + {} + + virtual void beginLayer(const char* className, const LayerAndroid* layerPtr); + virtual void endLayer(); +protected: + virtual void writeEntry(const char* label, const char* value); + +private: + void writeLine(const char* str); + FILE* m_file; +}; } diff --git a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp index 82afe8f..aa204f8 100644 --- a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp +++ b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp @@ -86,25 +86,17 @@ void FixedPositioning::contentDraw(SkCanvas* canvas, Layer::PaintStyle style) } } -void writeLength(FILE* file, int indentLevel, const char* str, SkLength length) +void FixedPositioning::dumpLayer(LayerDumper* dumper) const { - if (!length.defined()) - return; - writeIndent(file, indentLevel); - fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value); -} - -void FixedPositioning::dumpLayer(FILE* file, int indentLevel) const -{ - writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft); - writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop); - writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight); - writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom); - writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft); - writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop); - writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight); - writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom); - writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect); + dumper->writeLength("fixedLeft", m_fixedLeft); + dumper->writeLength("fixedTop", m_fixedTop); + dumper->writeLength("fixedRight", m_fixedRight); + dumper->writeLength("fixedBottom", m_fixedBottom); + dumper->writeLength("fixedMarginLeft", m_fixedMarginLeft); + dumper->writeLength("fixedMarginTop", m_fixedMarginTop); + dumper->writeLength("fixedMarginRight", m_fixedMarginRight); + dumper->writeLength("fixedMarginBottom", m_fixedMarginBottom); + dumper->writeRect("fixedRect", m_fixedRect); } BackgroundImagePositioning::BackgroundImagePositioning(LayerAndroid* layer, const BackgroundImagePositioning& position) diff --git a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h index e273a25..ac838c8 100644 --- a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h +++ b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h @@ -130,7 +130,7 @@ public: void contentDraw(SkCanvas* canvas, Layer::PaintStyle style); - void dumpLayer(FILE*, int indentLevel) const; + void dumpLayer(LayerDumper*) const; // ViewStateSerializer friends friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream); diff --git a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp index 3532542..4481f55 100644 --- a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp @@ -29,10 +29,10 @@ IFrameLayerAndroid* IFrameLayerAndroid::updatePosition(SkRect viewport, return this; } -void IFrameLayerAndroid::dumpLayer(FILE* file, int indentLevel) const +void IFrameLayerAndroid::dumpLayer(LayerDumper* dumper) const { - writeIntVal(file, indentLevel + 1, "m_isIframe", true); - writeIntPoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset); + LayerAndroid::dumpLayer(dumper); + dumper->writeIntPoint("m_iframeOffset", m_iframeOffset); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h index f2fbf49..08e7212 100644 --- a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h @@ -53,7 +53,7 @@ public: virtual IFrameLayerAndroid* updatePosition(SkRect viewport, IFrameLayerAndroid* parentIframeLayer); - virtual void dumpLayer(FILE*, int indentLevel) const; + virtual void dumpLayer(LayerDumper*) const; const IntPoint& iframeOffset() const { return m_iframeOffset; } diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp index d709a9c..dde7e9b 100644 --- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp @@ -598,7 +598,7 @@ void LayerAndroid::showLayer(int indent) m_clippingRect.width(), m_clippingRect.height()); ALOGD("%s s:%x %s %s (%d) [%d:%x - 0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) " "clip (%d, %d, %d, %d) %s %s m_content(%x), pic w: %d h: %d originalLayer: %x %d", - spaces, m_surface, m_haveClip ? "CLIP LAYER" : "", subclassName().ascii().data(), + spaces, m_surface, m_haveClip ? "CLIP LAYER" : "", subclassName(), subclassType(), uniqueId(), this, m_owningLayer, needsTexture() ? "needsTexture" : "", m_imageCRC ? "hasImage" : "", @@ -951,60 +951,42 @@ void LayerAndroid::setFixedPosition(FixedPositioning* position) { m_fixedPosition = position; } -void LayerAndroid::dumpLayer(FILE* file, int indentLevel) const +void LayerAndroid::dumpLayer(LayerDumper* dumper) const { - writeHexVal(file, indentLevel + 1, "layer", (int)this); - writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId); - writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip); - writeIntVal(file, indentLevel + 1, "isFixed", isPositionFixed()); + dumper->writeIntVal("layerId", m_uniqueId); + dumper->writeIntVal("haveClip", m_haveClip); + dumper->writeIntVal("isFixed", isPositionFixed()); - writeFloatVal(file, indentLevel + 1, "opacity", getOpacity()); - writeSize(file, indentLevel + 1, "size", getSize()); - writePoint(file, indentLevel + 1, "position", getPosition()); - writePoint(file, indentLevel + 1, "anchor", getAnchorPoint()); + dumper->writeFloatVal("opacity", getOpacity()); + dumper->writeSize("size", getSize()); + dumper->writePoint("position", getPosition()); + dumper->writePoint("anchor", getAnchorPoint()); - writeMatrix(file, indentLevel + 1, "drawMatrix", m_drawTransform); - writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform); - writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect)); + dumper->writeMatrix("drawMatrix", m_drawTransform); + dumper->writeMatrix("transformMatrix", m_transform); + dumper->writeRect("clippingRect", SkRect(m_clippingRect)); if (m_content) { - writeIntVal(file, indentLevel + 1, "m_content.width", m_content->width()); - writeIntVal(file, indentLevel + 1, "m_content.height", m_content->height()); + dumper->writeIntVal("m_content.width", m_content->width()); + dumper->writeIntVal("m_content.height", m_content->height()); } if (m_fixedPosition) - return m_fixedPosition->dumpLayer(file, indentLevel); + m_fixedPosition->dumpLayer(dumper); } -void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const +void LayerAndroid::dumpLayers(LayerDumper* dumper) const { - writeln(file, indentLevel, "{"); - - dumpLayer(file, indentLevel); + dumper->beginLayer(subclassName(), this); + dumpLayer(dumper); + dumper->beginChildren(countChildren()); if (countChildren()) { - writeln(file, indentLevel + 1, "children = ["); - for (int i = 0; i < countChildren(); i++) { - if (i > 0) - writeln(file, indentLevel + 1, ", "); - getChild(i)->dumpLayers(file, indentLevel + 1); - } - writeln(file, indentLevel + 1, "];"); + for (int i = 0; i < countChildren(); i++) + getChild(i)->dumpLayers(dumper); } - writeln(file, indentLevel, "}"); -} - -void LayerAndroid::dumpToLog() const -{ - FILE* file = fopen("/data/data/com.android.browser/layertmp", "w"); - dumpLayers(file, 0); - fclose(file); - file = fopen("/data/data/com.android.browser/layertmp", "r"); - char buffer[512]; - bzero(buffer, sizeof(buffer)); - while (fgets(buffer, sizeof(buffer), file)) - SkDebugf("%s", buffer); - fclose(file); + dumper->endChildren(); + dumper->endLayer(); } LayerAndroid* LayerAndroid::findById(int match) diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h index f821d89..312ad7b 100644 --- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h @@ -73,6 +73,7 @@ class IFrameLayerAndroid; class LayerMergeState; class RenderLayer; class PaintedSurface; +class LayerDumper; class TexturesResult { public: @@ -100,7 +101,7 @@ public: CanvasLayer, BaseLayer } SubclassType; typedef enum { InvalidateNone = 0, InvalidateLayers } InvalidateFlags; - String subclassName() + const char* subclassName() const { switch (subclassType()) { case LayerAndroid::StandardLayer: @@ -195,17 +196,8 @@ public: bool hasAnimations() const; void addDirtyArea(); - virtual void dumpLayer(FILE*, int indentLevel) const; - void dumpLayers(FILE*, int indentLevel) const; - void dumpToLog() const; + void dumpLayers(LayerDumper*) const; - /** Call this with the current viewport (scrolling, zoom) to update - the position of the fixed layers. - - This call is recursive, so it should be called on the root of the - hierarchy. - */ - void updateLayerPositions(SkRect viewPort, IFrameLayerAndroid* parentIframeLayer = 0); virtual IFrameLayerAndroid* updatePosition(SkRect viewport, IFrameLayerAndroid* parentIframeLayer); @@ -297,6 +289,14 @@ public: } protected: + virtual void dumpLayer(LayerDumper*) const; + /** Call this with the current viewport (scrolling, zoom) to update + the position of the fixed layers. + + This call is recursive, so it should be called on the root of the + hierarchy. + */ + void updateLayerPositions(SkRect viewPort, IFrameLayerAndroid* parentIframeLayer = 0); virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style); virtual InvalidateFlags onSetHwAccelerated(bool hwAccelerated) { return InvalidateNone; } TransformationMatrix m_drawTransform; diff --git a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp index 4398146..f012c42 100644 --- a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp +++ b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp @@ -1,6 +1,10 @@ +#define LOG_TAG "PictureLayerContent" +#define LOG_NDEBUG 1 + #include "config.h" #include "PictureLayerContent.h" +#include "AndroidLog.h" #include "InspectorCanvas.h" #include "SkPicture.h" @@ -90,6 +94,7 @@ void PictureLayerContent::draw(SkCanvas* canvas) if (!m_picture) return; + TRACE_METHOD(); android::Mutex::Autolock lock(m_drawLock); SkRect r = SkRect::MakeWH(width(), height()); canvas->clipRect(r); diff --git a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp index b648e72..5d516af 100644 --- a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp +++ b/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp @@ -1,6 +1,10 @@ +#define LOG_TAG "PicturePileLayerContent" +#define LOG_NDEBUG 1 + #include "config.h" #include "PicturePileLayerContent.h" +#include "AndroidLog.h" #include "SkCanvas.h" #include "SkPicture.h" @@ -13,6 +17,7 @@ PicturePileLayerContent::PicturePileLayerContent(const PicturePile& picturePile) void PicturePileLayerContent::draw(SkCanvas* canvas) { + TRACE_METHOD(); android::Mutex::Autolock lock(m_drawLock); m_picturePile.draw(canvas); } diff --git a/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp b/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp index bfa0789..a68c01a 100644 --- a/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp @@ -384,6 +384,7 @@ bool GLUtils::isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor) // If the bitmap is the pure color, skip the transfer step, and update the Tile Info. // This check is taking < 1ms if we do full bitmap check per tile. // TODO: use the SkPicture to determine whether or not a tile is single color. + TRACE_METHOD(); pureColor = Color(Color::transparent); bitmap.lockPixels(); bool sameColor = true; @@ -483,6 +484,7 @@ void GLUtils::updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBi bool GLUtils::updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap) { + TRACE_METHOD(); SkAutoLockPixels alp(bitmap); if (!bitmap.getPixels()) return false; diff --git a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp index 3fcbdb2..c1b91a3 100644 --- a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp @@ -79,12 +79,12 @@ bool PaintTileOperation::operator==(const QueuedOperation* operation) return op->m_tile == m_tile; } -void PaintTileOperation::run() +void PaintTileOperation::run(BaseRenderer* renderer) { TRACE_METHOD(); if (m_tile) { - m_tile->paintBitmap(m_painter); + m_tile->paintBitmap(m_painter, renderer); m_tile->setRepaintPending(false); m_tile = 0; } diff --git a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h index c82cdcd..ecd3ce9 100644 --- a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h +++ b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h @@ -42,7 +42,7 @@ public: GLWebViewState* state, bool isLowResPrefetch); virtual ~PaintTileOperation(); virtual bool operator==(const QueuedOperation* operation); - virtual void run(); + virtual void run(BaseRenderer* renderer); virtual void* uniquePtr() { return m_tile; } // returns a rendering priority for m_tile, lower values are processed faster virtual int priority(); diff --git a/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h b/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h index 7625528..fe6f8a3 100644 --- a/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h +++ b/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h @@ -28,10 +28,12 @@ namespace WebCore { +class BaseRenderer; + class QueuedOperation { public: virtual ~QueuedOperation() {} - virtual void run() = 0; + virtual void run(BaseRenderer* renderer) = 0; virtual bool operator==(const QueuedOperation* operation) = 0; virtual void* uniquePtr() = 0; virtual int priority() = 0; diff --git a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp index 47e5c17..a67a890 100644 --- a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp @@ -42,20 +42,17 @@ namespace WebCore { -SkBitmap* RasterRenderer::g_bitmap = 0; - -RasterRenderer::RasterRenderer() : BaseRenderer(BaseRenderer::Raster) +RasterRenderer::RasterRenderer() + : BaseRenderer(BaseRenderer::Raster) + , m_bitmapIsPureColor(false) { + m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, + TilesManager::instance()->tileWidth(), + TilesManager::instance()->tileHeight()); + m_bitmap.allocPixels(); #ifdef DEBUG_COUNT ClassTracker::instance()->increment("RasterRenderer"); #endif - if (!g_bitmap) { - g_bitmap = new SkBitmap(); - g_bitmap->setConfig(SkBitmap::kARGB_8888_Config, - TilesManager::instance()->tileWidth(), - TilesManager::instance()->tileHeight()); - g_bitmap->allocPixels(); - } } RasterRenderer::~RasterRenderer() @@ -67,9 +64,14 @@ RasterRenderer::~RasterRenderer() void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) { + TRACE_METHOD(); + if (renderInfo.baseTile->isLayerTile()) { - g_bitmap->setIsOpaque(false); - g_bitmap->eraseARGB(0, 0, 0, 0); + m_bitmap.setIsOpaque(false); + + // clear bitmap if necessary + if (!m_bitmapIsPureColor || m_bitmapPureColor != Color::transparent) + m_bitmap.eraseARGB(0, 0, 0, 0); } else { Color defaultBackground = Color::white; Color* background = renderInfo.tilePainter->background(); @@ -78,12 +80,15 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can background = &defaultBackground; } ALOGV("setupCanvas use background on Base Layer %x", background->rgb()); - g_bitmap->setIsOpaque(!background->hasAlpha()); - g_bitmap->eraseARGB(background->alpha(), background->red(), - background->green(), background->blue()); + m_bitmap.setIsOpaque(!background->hasAlpha()); + + // fill background color if necessary + if (!m_bitmapIsPureColor || m_bitmapPureColor != *background) + m_bitmap.eraseARGB(background->alpha(), background->red(), + background->green(), background->blue()); } - SkDevice* device = new SkDevice(*g_bitmap); + SkDevice* device = new SkDevice(m_bitmap); canvas->setDevice(device); @@ -92,14 +97,15 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can void RasterRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) { - const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); - GLUtils::paintTextureWithBitmap(&renderInfo, bitmap); + GLUtils::paintTextureWithBitmap(&renderInfo, m_bitmap); } void RasterRenderer::checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) { - const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); - renderInfo.isPureColor = GLUtils::isPureColorBitmap(bitmap, renderInfo.pureColor); + m_bitmapIsPureColor = GLUtils::isPureColorBitmap(m_bitmap, m_bitmapPureColor); + + renderInfo.isPureColor = m_bitmapIsPureColor; + renderInfo.pureColor = m_bitmapPureColor; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h index 39e00f2..34b57ca 100644 --- a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h +++ b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h @@ -46,14 +46,14 @@ public: ~RasterRenderer(); protected: - virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas); virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas); virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas); private: - static SkBitmap* g_bitmap; - + SkBitmap m_bitmap; + bool m_bitmapIsPureColor; + Color m_bitmapPureColor; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp index 73466d3..96a4a16 100644 --- a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp @@ -218,7 +218,7 @@ void Surface::prepareGL(bool layerTilesDisabled, bool updateWithBlit) ALOGV("prepareGL on Surf %p with SurfBack %p, %d layers, first layer %s (%d) " "prepareArea(%d, %d - %d x %d) fullArea(%d, %d - %d x %d)", this, m_surfaceBacking, m_layers.size(), - getFirstLayer()->subclassName().ascii().data(), + getFirstLayer()->subclassName(), getFirstLayer()->uniqueId(), prepareArea.x(), prepareArea.y(), prepareArea.width(), prepareArea.height(), fullArea.x(), fullArea.y(), fullArea.width(), fullArea.height()); @@ -253,7 +253,7 @@ bool Surface::drawGL(bool layerTilesDisabled) bool askRedraw = false; if (m_surfaceBacking && !tilesDisabled) { ALOGV("drawGL on Surf %p with SurfBack %p, first layer %s (%d)", this, m_surfaceBacking, - getFirstLayer()->subclassName().ascii().data(), getFirstLayer()->uniqueId()); + getFirstLayer()->subclassName(), getFirstLayer()->uniqueId()); bool force3dContentVisible = true; IntRect drawArea = visibleContentArea(force3dContentVisible); @@ -420,6 +420,14 @@ bool Surface::blitFromContents(Tile* tile) if (!singleLayer() || !tile || !getFirstLayer() || !getFirstLayer()->content()) return false; + if (tile->frontTexture() != tile->lastDrawnTexture()) { + // the below works around an issue where glTexSubImage2d can't update a + // texture that hasn't drawn yet by drawing it off screen. + // glFlush() and glFinish() work also, but are likely more wasteful. + SkRect rect = SkRect::MakeXYWH(-100, -100, 0, 0); + FloatRect fillPortion(0, 0, 0, 0); + tile->frontTexture()->drawGL(false, rect, 1.0f, 0, false, true, fillPortion); + } LayerContent* content = getFirstLayer()->content(); // Extract the dirty rect from the region. Note that this is *NOT* constrained // to this tile diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp index 174720f..1270498 100644 --- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp @@ -38,6 +38,10 @@ namespace WebCore { using namespace android::uirenderer; +// Tag used to display current number of SurfaceCollections. +// Note: this will only work if one webview is actively drawing at a time. +static const char* COLLECTION_COUNT_TAG = "CollectionCount"; + SurfaceCollectionManager::SurfaceCollectionManager() : m_drawingCollection(0) , m_paintingCollection(0) @@ -87,6 +91,12 @@ void SurfaceCollectionManager::swap() m_paintingCollection = m_queuedCollection; m_queuedCollection = 0; + if (ATRACE_ENABLED()) { + ATRACE_INT(COLLECTION_COUNT_TAG, + (m_drawingCollection ? 1 : 0) + + (m_paintingCollection ? 1 : 0)); + } + ALOGV("SWAPPING COMPLETE, D %p, P %p, Q %p", m_drawingCollection, m_paintingCollection, m_queuedCollection); } @@ -106,6 +116,8 @@ void SurfaceCollectionManager::clearCollections() m_paintingCollection = 0; SkSafeUnref(m_queuedCollection); m_queuedCollection = 0; + + ATRACE_INT(COLLECTION_COUNT_TAG, 0); } void SurfaceCollectionManager::updatePaintingCollection(SurfaceCollection* newCollection) @@ -126,8 +138,10 @@ bool SurfaceCollectionManager::updateWithSurfaceCollection(SurfaceCollection* ne if (!newCollection || brandNew) { clearCollections(); - if (brandNew) + if (brandNew) { updatePaintingCollection(newCollection); + ATRACE_INT(COLLECTION_COUNT_TAG, 1); + } return false; } @@ -157,6 +171,13 @@ bool SurfaceCollectionManager::updateWithSurfaceCollection(SurfaceCollection* ne // don't have painting collection, paint this one! updatePaintingCollection(newCollection); } + + if (ATRACE_ENABLED()) { + ATRACE_INT(COLLECTION_COUNT_TAG, + (m_drawingCollection ? 1 : 0) + + (m_paintingCollection ? 1 : 0) + + (m_queuedCollection ? 1 : 0)); + } return m_drawingCollection && TilesManager::instance()->useDoubleBuffering(); } @@ -225,12 +246,12 @@ int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, int returnFlags = 0; bool didCollectionSwap = false; + bool tryFastBlit = !m_fastSwapMode; if (m_paintingCollection) { ALOGV("preparing painting collection %p", m_paintingCollection); m_paintingCollection->evaluateAnimations(currentTime); - bool tryFastBlit = !m_fastSwapMode; m_paintingCollection->prepareGL(visibleContentRect, tryFastBlit); m_paintingCollection->computeTexturesAmount(texturesResultPtr); @@ -261,6 +282,9 @@ int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, && m_drawingCollection->isReady())) { // either a swap just occurred, or there is no more work to be done: do a full draw m_drawingCollection->swapTiles(); + + if (didCollectionSwap && m_paintingCollection) + m_paintingCollection->prepareGL(visibleContentRect, tryFastBlit); returnFlags |= DrawGlInfo::kStatusDraw; } else { // current collection not ready - invoke functor in process mode @@ -286,6 +310,9 @@ int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, if (didCollectionSwap || m_fastSwapMode || (drawingReady && !m_paintingCollection)) m_drawingCollection->swapTiles(); + if (didCollectionSwap && m_paintingCollection) + m_paintingCollection->prepareGL(visibleContentRect, tryFastBlit); + if (drawingReady) { // exit fast swap mode, as content is up to date m_fastSwapMode = false; diff --git a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp index cc94c9c..74e663a 100644 --- a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp @@ -32,6 +32,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "AndroidLog.h" +#include "BaseRenderer.h" #include "GLUtils.h" #include "PaintTileOperation.h" #include "TilesManager.h" @@ -39,6 +40,19 @@ namespace WebCore { +TexturesGenerator::TexturesGenerator(TilesManager* instance) + : Thread(false) + , m_tilesManager(instance) + , m_deferredMode(false) + , m_renderer(0) +{ +} + +TexturesGenerator::~TexturesGenerator() +{ + delete m_renderer; +} + bool TexturesGenerator::tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter) { android::Mutex::Autolock lock(mRequestedOperationsLock); @@ -83,12 +97,11 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) i++; } } - delete filter; } status_t TexturesGenerator::readyToRun() { - ALOGV("Thread ready to run"); + m_renderer = BaseRenderer::createRenderer(); return NO_ERROR; } @@ -165,7 +178,9 @@ bool TexturesGenerator::threadLoop() if (currentOperation) { ALOGV("threadLoop, painting the request with priority %d", currentOperation->priority()); - currentOperation->run(); + // swap out the renderer if necessary + BaseRenderer::swapRendererIfNeeded(m_renderer); + currentOperation->run(m_renderer); } mRequestedOperationsLock.lock(); diff --git a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h index 290ad08..2998330 100644 --- a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h +++ b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h @@ -29,7 +29,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "QueuedOperation.h" -#include "TilePainter.h" +#include "TransferQueue.h" #include <wtf/HashMap.h> #include <wtf/Vector.h> @@ -43,10 +43,9 @@ class TilesManager; class TexturesGenerator : public Thread { public: - TexturesGenerator(TilesManager* instance) : Thread(false) - , m_tilesManager(instance) - , m_deferredMode(false) { } - virtual ~TexturesGenerator() { } + TexturesGenerator(TilesManager* instance); + virtual ~TexturesGenerator(); + virtual status_t readyToRun(); bool tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter); @@ -68,6 +67,7 @@ private: android::Condition mRequestedOperationsCond; TilesManager* m_tilesManager; + BaseRenderer* m_renderer; bool m_deferredMode; // defer painting for one second if best in queue has priority diff --git a/Source/WebCore/platform/graphics/android/rendering/Tile.cpp b/Source/WebCore/platform/graphics/android/rendering/Tile.cpp index e674884..76be981 100644 --- a/Source/WebCore/platform/graphics/android/rendering/Tile.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/Tile.cpp @@ -33,7 +33,7 @@ #include "AndroidLog.h" #include "GLUtils.h" -#include "RasterRenderer.h" +#include "BaseRenderer.h" #include "TextureInfo.h" #include "TileTexture.h" #include "TilesManager.h" @@ -52,6 +52,7 @@ Tile::Tile(bool isLayerTile) , m_y(-1) , m_frontTexture(0) , m_backTexture(0) + , m_lastDrawnTexture(0) , m_scale(1) , m_dirty(true) , m_repaintsPending(0) @@ -63,7 +64,6 @@ Tile::Tile(bool isLayerTile) #ifdef DEBUG_COUNT ClassTracker::instance()->increment("Tile"); #endif - m_renderer = BaseRenderer::createRenderer(); } Tile::~Tile() @@ -73,8 +73,6 @@ Tile::~Tile() if (m_frontTexture) m_frontTexture->release(this); - delete m_renderer; - #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("Tile"); #endif @@ -242,6 +240,7 @@ bool Tile::drawGL(float opacity, const SkRect& rect, float scale, m_frontTexture->drawGL(isLayerTile(), rect, opacity, transform, forceBlending, usePointSampling, fillPortion); + m_lastDrawnTexture = m_frontTexture; return true; } @@ -295,7 +294,7 @@ bool Tile::isTileVisible(const IntRect& viewTileBounds) } // This is called from the texture generation thread -void Tile::paintBitmap(TilePainter* painter) +void Tile::paintBitmap(TilePainter* painter, BaseRenderer* renderer) { // We acquire the values below atomically. This ensures that we are reading // values correctly across cores. Further, once we have these values they @@ -326,8 +325,6 @@ void Tile::paintBitmap(TilePainter* painter) return; } - // swap out the renderer if necessary - BaseRenderer::swapRendererIfNeeded(m_renderer); // setup the common renderInfo fields; TileRenderInfo renderInfo; renderInfo.x = x; @@ -341,7 +338,7 @@ void Tile::paintBitmap(TilePainter* painter) const float tileWidth = renderInfo.tileSize.width(); const float tileHeight = renderInfo.tileSize.height(); - m_renderer->renderTiledContent(renderInfo); + renderer->renderTiledContent(renderInfo); m_atomicSync.lock(); diff --git a/Source/WebCore/platform/graphics/android/rendering/Tile.h b/Source/WebCore/platform/graphics/android/rendering/Tile.h index 2dc5414..f467bb0 100644 --- a/Source/WebCore/platform/graphics/android/rendering/Tile.h +++ b/Source/WebCore/platform/graphics/android/rendering/Tile.h @@ -28,7 +28,6 @@ #if USE(ACCELERATED_COMPOSITING) -#include "BaseRenderer.h" #include "FloatPoint.h" #include "SkRect.h" #include "SkRegion.h" @@ -39,9 +38,10 @@ namespace WebCore { +class BaseRenderer; +class GLWebViewState; class TextureInfo; class TileTexture; -class GLWebViewState; /** * An individual tile that is used to construct part of a webpage's BaseLayer of @@ -107,7 +107,7 @@ public: const FloatRect& fillPortion); // the only thread-safe function called by the background thread - void paintBitmap(TilePainter* painter); + void paintBitmap(TilePainter* painter, BaseRenderer* renderer); bool intersectWithRect(int x, int y, int tileWidth, int tileHeight, float scale, const SkRect& dirtyRect, @@ -127,6 +127,7 @@ public: int y() const { return m_y; } TileTexture* frontTexture() { return m_frontTexture; } TileTexture* backTexture() { return m_backTexture; } + TileTexture* lastDrawnTexture() { return m_lastDrawnTexture; } // only used for prioritization - the higher, the more relevant the tile is unsigned long long drawCount() { return m_drawCount; } @@ -151,6 +152,7 @@ private: TileTexture* m_frontTexture; TileTexture* m_backTexture; + TileTexture* m_lastDrawnTexture; float m_scale; // used to signal that the that the tile is out-of-date and needs to be @@ -169,8 +171,6 @@ private: // across all threads and cores. android::Mutex m_atomicSync; - BaseRenderer* m_renderer; - bool m_isLayerTile; // the most recent GL draw before this tile was prepared. used for diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp index 0b4ba7b..e584b81 100644 --- a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp @@ -65,6 +65,10 @@ #define LAYER_TEXTURES_DESTROY_TIMEOUT 60 // If we do not need layers for 60 seconds, free the textures +// Eventually this should be dynamically be determined, and smart scheduling +// between the generators should be implemented +#define NUM_TEXTURES_GENERATORS 1 + namespace WebCore { int TilesManager::getMaxTextureAllocation() @@ -105,10 +109,21 @@ TilesManager::TilesManager() m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); - m_pixmapsGenerationThread = new TexturesGenerator(this); - m_pixmapsGenerationThread->run("TexturesGenerator"); + + m_textureGenerators = new sp<TexturesGenerator>[NUM_TEXTURES_GENERATORS]; + for (int i = 0; i < NUM_TEXTURES_GENERATORS; i++) { + m_textureGenerators[i] = new TexturesGenerator(this); + ALOGD("Starting TG #%d, %p", i, m_textureGenerators[i].get()); + m_textureGenerators[i]->run("TexturesGenerator"); + } } +TilesManager::~TilesManager() +{ + delete[] m_textureGenerators; +} + + void TilesManager::allocateTextures() { int nbTexturesToAllocate = m_currentTextureCount - m_textures.size(); @@ -488,6 +503,29 @@ void TilesManager::updateTilesIfContextVerified() return; } +void TilesManager::removeOperationsForFilter(OperationFilter* filter) +{ + for (int i = 0; i < NUM_TEXTURES_GENERATORS; i++) + m_textureGenerators[i]->removeOperationsForFilter(filter); + delete filter; +} + +bool TilesManager::tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter) +{ + for (int i = 0; i < NUM_TEXTURES_GENERATORS; i++) { + if (m_textureGenerators[i]->tryUpdateOperationWithPainter(tile, painter)) + return true; + } + return false; +} + +void TilesManager::scheduleOperation(QueuedOperation* operation) +{ + // TODO: painter awareness, store prefer awareness, store preferred thread into painter + m_scheduleThread = (m_scheduleThread + 1) % NUM_TEXTURES_GENERATORS; + m_textureGenerators[m_scheduleThread]->scheduleOperation(operation); +} + int TilesManager::tileWidth() { return TILE_WIDTH; diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesManager.h b/Source/WebCore/platform/graphics/android/rendering/TilesManager.h index f0d2eac..0781ef6 100644 --- a/Source/WebCore/platform/graphics/android/rendering/TilesManager.h +++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.h @@ -53,23 +53,9 @@ public: return gInstance != 0; } - void removeOperationsForFilter(OperationFilter* filter) - { - m_pixmapsGenerationThread->removeOperationsForFilter(filter); - } - - bool tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter) - { - return m_pixmapsGenerationThread->tryUpdateOperationWithPainter(tile, painter); - } - - void scheduleOperation(QueuedOperation* operation) - { - m_pixmapsGenerationThread->scheduleOperation(operation); - } - ShaderProgram* shader() { return &m_shader; } TransferQueue* transferQueue(); + VideoLayerManager* videoLayerManager() { return &m_videoLayerManager; } void updateTilesIfContextVerified(); @@ -165,8 +151,15 @@ public: return m_drawGLCount; } + // operations on/for texture generator threads + void removeOperationsForFilter(OperationFilter* filter); + bool tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter); + void scheduleOperation(QueuedOperation* operation); + private: TilesManager(); + ~TilesManager(); + int m_scheduleThread; void discardTexturesVector(unsigned long long sparedDrawCount, WTF::Vector<TileTexture*>& textures, @@ -198,7 +191,7 @@ private: unsigned int m_contentUpdates; // nr of successful tiled paints unsigned int m_webkitContentUpdates; // nr of paints from webkit - sp<TexturesGenerator> m_pixmapsGenerationThread; + sp<TexturesGenerator>* m_textureGenerators; android::Mutex m_texturesLock; diff --git a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp index f37afa4..e329191 100644 --- a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp @@ -32,6 +32,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "AndroidLog.h" +#include "BaseRenderer.h" #include "DrawQuadData.h" #include "GLUtils.h" #include "Tile.h" @@ -391,6 +392,7 @@ void TransferQueue::updateDirtyTiles() void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap) { + TRACE_METHOD(); if (!tryUpdateQueueWithBitmap(renderInfo, bitmap)) { // failed placing bitmap in queue, discard tile's texture so it will be // re-enqueued (and repainted) diff --git a/Source/WebCore/plugins/android/PluginViewAndroid.cpp b/Source/WebCore/plugins/android/PluginViewAndroid.cpp index fdf6e03..2cc95b1 100644 --- a/Source/WebCore/plugins/android/PluginViewAndroid.cpp +++ b/Source/WebCore/plugins/android/PluginViewAndroid.cpp @@ -405,7 +405,7 @@ bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPErr // our interface query is valid with no NPP instance *result = NPERR_GENERIC_ERROR; - switch (variable) { + switch ((int)variable) { case NPNVisOfflineBool: { if (value != NULL) { bool* retValue = static_cast<bool*>(value); @@ -422,7 +422,7 @@ bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPErr return true; } default: - ; // do nothing + break; // do nothing } (void)anp_getInterface(variable, value, result); @@ -490,7 +490,7 @@ void PluginView::setNPWindowIfNeeded() bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* result) { - switch (variable) { + switch ((int)variable) { case NPNVWindowNPObject: { NPObject* windowScriptObject = m_parentFrame->script()->windowScriptNPObject(); @@ -581,7 +581,7 @@ NPError PluginView::platformSetValue(NPPVariable variable, void* value) { NPError error = NPERR_GENERIC_ERROR; - switch (variable) { + switch ((int)variable) { case kRequestDrawingModel_ANPSetValue: { ANPDrawingModel model = reinterpret_cast<ANPDrawingModel>(value); if (m_window->setDrawingModel(model)) diff --git a/Source/WebKit/android/AndroidLog.h b/Source/WebKit/android/AndroidLog.h index f034d35..6b6c1a0 100644 --- a/Source/WebKit/android/AndroidLog.h +++ b/Source/WebKit/android/AndroidLog.h @@ -30,6 +30,8 @@ #define LOG_TAG __FILE__ #endif +#define ATRACE_TAG ATRACE_TAG_WEBVIEW + #include <cutils/log.h> #include <utils/Trace.h> #include <wtf/CurrentTime.h> @@ -58,7 +60,7 @@ extern FILE* gRenderTreeFile; #define INT_RECT_FORMAT "[x=%d,y=%d,w=%d,h=%d]" #define INT_RECT_ARGS(ir) ir.x(), ir.y(), ir.width(), ir.height() -#define TRACE_METHOD() android::ScopedTrace __st(ATRACE_TAG_WEBVIEW, __func__); +#define TRACE_METHOD() android::ScopedTrace __st(ATRACE_TAG, __func__); #define TIME_METHOD() MethodTimer __method_timer(__func__) class MethodTimer { diff --git a/Source/WebKit/android/jni/PicturePile.cpp b/Source/WebKit/android/jni/PicturePile.cpp index ccdfa59..6a36ccf 100644 --- a/Source/WebKit/android/jni/PicturePile.cpp +++ b/Source/WebKit/android/jni/PicturePile.cpp @@ -35,11 +35,17 @@ #include "PlatformGraphicsContextSkia.h" #include "SkCanvas.h" #include "SkNWayCanvas.h" -#include "SkPicture.h" #include "SkPixelRef.h" #include "SkRect.h" #include "SkRegion.h" +#if USE_RECORDING_CONTEXT +#include "GraphicsOperationCollection.h" +#include "PlatformGraphicsContextRecording.h" +#else +#include "SkPicture.h" +#endif + #define ENABLE_PRERENDERED_INVALS true #define MAX_OVERLAP_COUNT 2 #define MAX_OVERLAP_AREA .7 @@ -57,6 +63,20 @@ static IntRect extractClipBounds(SkCanvas* canvas, const IntSize& size) { return enclosingIntRect(clip); } +PictureContainer::PictureContainer(const PictureContainer& other) + : picture(other.picture) + , area(other.area) + , dirty(other.dirty) + , prerendered(other.prerendered) +{ + SkSafeRef(picture); +} + +PictureContainer::~PictureContainer() +{ + SkSafeUnref(picture); +} + PicturePile::PicturePile(const PicturePile& other) : m_size(other.m_size) , m_pile(other.m_pile) @@ -64,15 +84,6 @@ PicturePile::PicturePile(const PicturePile& other) { } -PicturePile::PicturePile(SkPicture* picture) -{ - m_size = IntSize(picture->width(), picture->height()); - PictureContainer pc(IntRect(0, 0, m_size.width(), m_size.height())); - pc.picture = picture; - pc.dirty = false; - m_pile.append(pc); -} - void PicturePile::draw(SkCanvas* canvas) { /* Loop down recursively, subtracting the previous clip from the SkRegion, @@ -81,7 +92,6 @@ void PicturePile::draw(SkCanvas* canvas) * the rect bounds of the SkRegion for the clip, so this still can't be * used for translucent surfaces */ - TRACE_METHOD(); IntRect clipBounds = extractClipBounds(canvas, m_size); SkRegion clipRegion(toSkIRect(clipBounds)); drawWithClipRecursive(canvas, clipRegion, m_pile.size() - 1); @@ -107,8 +117,7 @@ void PicturePile::drawWithClipRecursive(SkCanvas* canvas, SkRegion& clipRegion, drawWithClipRecursive(canvas, clipRegion, index - 1); int saved = canvas->save(); canvas->clipRect(intersection); - canvas->translate(pc.area.x(), pc.area.y()); - canvas->drawPicture(*pc.picture); + drawPicture(canvas, pc); canvas->restoreToCount(saved); } else drawWithClipRecursive(canvas, clipRegion, index - 1); @@ -163,43 +172,8 @@ void PicturePile::updatePicturesIfNeeded(PicturePainter* painter) void PicturePile::updatePicture(PicturePainter* painter, PictureContainer& pc) { - /* The ref counting here is a bit unusual. What happens is begin/end recording - * will ref/unref the recording canvas. However, 'canvas' might be pointing - * at an SkNWayCanvas instead of the recording canvas, which needs to be - * unref'd. Thus what we do is ref the recording canvas so that we can - * always unref whatever canvas we have at the end. - */ TRACE_METHOD(); - SkPicture* picture = new SkPicture(); - SkCanvas* canvas = picture->beginRecording(pc.area.width(), pc.area.height(), - SkPicture::kUsePathBoundsForClip_RecordingFlag); - SkSafeRef(canvas); - canvas->translate(-pc.area.x(), -pc.area.y()); - IntRect drawArea = pc.area; - if (pc.prerendered.get()) { - SkCanvas* prerender = painter->createPrerenderCanvas(pc.prerendered.get()); - if (!prerender) { - ALOGV("Failed to create prerendered for " INT_RECT_FORMAT, - INT_RECT_ARGS(pc.prerendered->area)); - pc.prerendered.clear(); - } else { - drawArea.unite(pc.prerendered->area); - SkNWayCanvas* nwayCanvas = new SkNWayCanvas(drawArea.width(), drawArea.height()); - nwayCanvas->translate(-drawArea.x(), -drawArea.y()); - nwayCanvas->addCanvas(canvas); - nwayCanvas->addCanvas(prerender); - SkSafeUnref(canvas); - SkSafeUnref(prerender); - canvas = nwayCanvas; - } - } - WebCore::PlatformGraphicsContextSkia pgc(canvas); - WebCore::GraphicsContext gc(&pgc); - ALOGV("painting picture: " INT_RECT_FORMAT, INT_RECT_ARGS(drawArea)); - painter->paintContents(&gc, drawArea); - SkSafeUnref(canvas); - picture->endRecording(); - + Picture* picture = recordPicture(painter, pc); SkSafeUnref(pc.picture); pc.picture = picture; pc.dirty = false; @@ -298,4 +272,69 @@ PrerenderedInval* PicturePile::prerenderedInvalForArea(const IntRect& area) return 0; } +#if USE_RECORDING_CONTEXT +void PicturePile::drawPicture(SkCanvas* canvas, PictureContainer& pc) +{ + PlatformGraphicsContextSkia pgc(canvas); + pc.picture->apply(&pgc); +} + +Picture* PicturePile::recordPicture(PicturePainter* painter, PictureContainer& pc) +{ + // TODO: Support? Not needed? + pc.prerendered.clear(); + GraphicsOperationCollection* picture = new GraphicsOperationCollection(); + WebCore::PlatformGraphicsContextRecording pgc(picture); + WebCore::GraphicsContext gc(&pgc); + painter->paintContents(&gc, pc.area); + return picture; +} +#else +void PicturePile::drawPicture(SkCanvas* canvas, PictureContainer& pc) +{ + canvas->translate(pc.area.x(), pc.area.y()); + pc.picture->draw(canvas); +} + +Picture* PicturePile::recordPicture(PicturePainter* painter, PictureContainer& pc) +{ + /* The ref counting here is a bit unusual. What happens is begin/end recording + * will ref/unref the recording canvas. However, 'canvas' might be pointing + * at an SkNWayCanvas instead of the recording canvas, which needs to be + * unref'd. Thus what we do is ref the recording canvas so that we can + * always unref whatever canvas we have at the end. + */ + SkPicture* picture = new SkPicture(); + SkCanvas* canvas = picture->beginRecording(pc.area.width(), pc.area.height(), + SkPicture::kUsePathBoundsForClip_RecordingFlag); + SkSafeRef(canvas); + canvas->translate(-pc.area.x(), -pc.area.y()); + IntRect drawArea = pc.area; + if (pc.prerendered.get()) { + SkCanvas* prerender = painter->createPrerenderCanvas(pc.prerendered.get()); + if (!prerender) { + ALOGV("Failed to create prerendered for " INT_RECT_FORMAT, + INT_RECT_ARGS(pc.prerendered->area)); + pc.prerendered.clear(); + } else { + drawArea.unite(pc.prerendered->area); + SkNWayCanvas* nwayCanvas = new SkNWayCanvas(drawArea.width(), drawArea.height()); + nwayCanvas->translate(-drawArea.x(), -drawArea.y()); + nwayCanvas->addCanvas(canvas); + nwayCanvas->addCanvas(prerender); + SkSafeUnref(canvas); + SkSafeUnref(prerender); + canvas = nwayCanvas; + } + } + WebCore::PlatformGraphicsContextSkia pgc(canvas); + WebCore::GraphicsContext gc(&pgc); + ALOGV("painting picture: " INT_RECT_FORMAT, INT_RECT_ARGS(drawArea)); + painter->paintContents(&gc, drawArea); + SkSafeUnref(canvas); + picture->endRecording(); + return picture; +} +#endif + } // namespace WebCore diff --git a/Source/WebKit/android/jni/PicturePile.h b/Source/WebKit/android/jni/PicturePile.h index b28a792..bdcf4f5 100644 --- a/Source/WebKit/android/jni/PicturePile.h +++ b/Source/WebKit/android/jni/PicturePile.h @@ -38,7 +38,17 @@ #include <wtf/ThreadSafeRefCounted.h> #include <wtf/Vector.h> +#define USE_RECORDING_CONTEXT false +#if USE_RECORDING_CONTEXT +namespace WebCore { +class GraphicsOperationCollection; +} +typedef WebCore::GraphicsOperationCollection Picture; +#else class SkPicture; +typedef SkPicture Picture; +#endif + class SkCanvas; namespace WebCore { @@ -57,7 +67,7 @@ public: class PictureContainer { public: - SkPicture* picture; + Picture* picture; IntRect area; bool dirty; RefPtr<PrerenderedInval> prerendered; @@ -68,26 +78,14 @@ public: , dirty(true) {} - PictureContainer(const PictureContainer& other) - : picture(other.picture) - , area(other.area) - , dirty(other.dirty) - , prerendered(other.prerendered) - { - SkSafeRef(picture); - } - - ~PictureContainer() - { - SkSafeUnref(picture); - } + PictureContainer(const PictureContainer& other); + ~PictureContainer(); }; class PicturePile { public: PicturePile() {} PicturePile(const PicturePile& other); - PicturePile(SkPicture* picture); const IntSize& size() { return m_size; } @@ -107,8 +105,10 @@ public: private: void applyWebkitInvals(); 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 drawPicture(SkCanvas* canvas, PictureContainer& pc); IntSize m_size; Vector<PictureContainer> m_pile; diff --git a/Source/WebKit/android/jni/ViewStateSerializer.cpp b/Source/WebKit/android/jni/ViewStateSerializer.cpp index 02ddca6..8963837 100644 --- a/Source/WebKit/android/jni/ViewStateSerializer.cpp +++ b/Source/WebKit/android/jni/ViewStateSerializer.cpp @@ -30,6 +30,7 @@ #include "BaseLayerAndroid.h" #include "CreateJavaOutputStreamAdaptor.h" +#include "DumpLayer.h" #include "FixedPositioning.h" #include "ImagesManager.h" #include "IFrameContentLayerAndroid.h" @@ -56,6 +57,68 @@ enum LayerTypes { LTFixedLayerAndroid = 3 }; +#define ID "mID" +#define LEFT "layout:mLeft" +#define TOP "layout:mTop" +#define WIDTH "layout:getWidth()" +#define HEIGHT "layout:getHeight()" + +class HierarchyLayerDumper : public LayerDumper { +public: + HierarchyLayerDumper(SkWStream* stream, int level) + : LayerDumper(level) + , m_stream(stream) + {} + + virtual void beginLayer(const char* className, const LayerAndroid* layerPtr) { + LayerDumper::beginLayer(className, layerPtr); + for (int i = 0; i < m_indentLevel; i++) { + m_stream->writeText(" "); + } + m_stream->writeText(className); + m_stream->writeText("@"); + m_stream->writeHexAsText(layerPtr->uniqueId()); + m_stream->writeText(" "); + + writeHexVal(ID, (int) layerPtr); + writeIntVal(LEFT, layerPtr->getPosition().fX); + writeIntVal(TOP, layerPtr->getPosition().fY); + writeIntVal(WIDTH, layerPtr->getWidth()); + writeIntVal(HEIGHT, layerPtr->getHeight()); + } + + virtual void beginChildren(int childCount) { + m_stream->writeText("\n"); + LayerDumper::beginChildren(childCount); + } + +protected: + virtual void writeEntry(const char* label, const char* value) { + m_stream->writeText(label); + m_stream->writeText("="); + int len = strlen(value); + m_stream->writeDecAsText(len); + m_stream->writeText(","); + m_stream->writeText(value); + m_stream->writeText(" "); + } + +private: + SkWStream* m_stream; +}; + +static void nativeDumpLayerHierarchy(JNIEnv* env, jobject, jint jbaseLayer, jint level, + jobject jstream, jbyteArray jstorage) +{ + SkWStream *stream = CreateJavaOutputStreamAdaptor(env, jstream, jstorage); + BaseLayerAndroid* baseLayer = reinterpret_cast<BaseLayerAndroid*>(jbaseLayer); + SkSafeRef(baseLayer); + HierarchyLayerDumper dumper(stream, level); + baseLayer->dumpLayers(&dumper); + SkSafeUnref(baseLayer); + delete stream; +} + static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer, jobject jstream, jbyteArray jstorage) { @@ -478,6 +541,8 @@ LayerAndroid* deserializeLayer(int version, SkStream* stream) * JNI registration */ static JNINativeMethod gSerializerMethods[] = { + { "nativeDumpLayerHierarchy", "(IILjava/io/OutputStream;[B)V", + (void*) nativeDumpLayerHierarchy }, { "nativeSerializeViewState", "(ILjava/io/OutputStream;[B)Z", (void*) nativeSerializeViewState }, { "nativeDeserializeViewState", "(ILjava/io/InputStream;[B)I", diff --git a/Source/WebKit/android/jni/WebSettings.cpp b/Source/WebKit/android/jni/WebSettings.cpp index 7ee9033..7d0c190 100644 --- a/Source/WebKit/android/jni/WebSettings.cpp +++ b/Source/WebKit/android/jni/WebSettings.cpp @@ -150,6 +150,7 @@ struct FieldIds { env->DeleteLocalRef(autoFillProfileClass); #endif mOverrideCacheMode = env->GetFieldID(clazz, "mOverrideCacheMode", "I"); + mPasswordEchoEnabled = env->GetFieldID(clazz, "mPasswordEchoEnabled", "Z"); ALOG_ASSERT(mLayoutAlgorithm, "Could not find field mLayoutAlgorithm"); ALOG_ASSERT(mTextSize, "Could not find field mTextSize"); @@ -193,6 +194,7 @@ struct FieldIds { ALOG_ASSERT(mMaximumDecodedImageSize, "Could not find field mMaximumDecodedImageSize"); ALOG_ASSERT(mUseDoubleTree, "Could not find field mUseDoubleTree"); ALOG_ASSERT(mPageCacheCapacity, "Could not find field mPageCacheCapacity"); + ALOG_ASSERT(mPasswordEchoEnabled, "Could not find field mPasswordEchoEnabled"); jclass enumClass = env->FindClass("java/lang/Enum"); ALOG_ASSERT(enumClass, "Could not find Enum class!"); @@ -278,6 +280,7 @@ struct FieldIds { jfieldID mAutoFillProfilePhoneNumber; #endif jfieldID mOverrideCacheMode; + jfieldID mPasswordEchoEnabled; }; static struct FieldIds* gFieldIds; @@ -610,8 +613,9 @@ public: // has no style attached to it. http://trac.webkit.org/changeset/79799 s->setDeveloperExtrasEnabled(true); s->setSpatialNavigationEnabled(true); - - s->setPasswordEchoEnabled(true); + bool echoPassword = env->GetBooleanField(obj, + gFieldIds->mPasswordEchoEnabled); + s->setPasswordEchoEnabled(echoPassword); } }; diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index 31d5535..b0317c06 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -423,7 +423,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m , m_mainFrame(mainframe) , m_popupReply(0) , m_blockTextfieldUpdates(false) - , m_focusBoundsChanged(false) , m_skipContentDraw(false) , m_textGeneration(0) , m_maxXScroll(320/4) @@ -728,13 +727,6 @@ void WebViewCore::clearContent() updateLocale(); } -bool WebViewCore::focusBoundsChanged() -{ - bool result = m_focusBoundsChanged; - m_focusBoundsChanged = false; - return result; -} - void WebViewCore::paintContents(WebCore::GraphicsContext* gc, WebCore::IntRect& dirty) { WebCore::FrameView* view = m_mainFrame->view(); @@ -1216,7 +1208,7 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height, m_mainFrame->view()->forceLayout(); // scroll to restore current screen center - if (node) { + if (node && node->inDocument()) { const WebCore::IntRect& newBounds = node->getRect(); if ((osw && osh && bounds.width() && bounds.height()) && (bounds != newBounds)) { @@ -1604,6 +1596,20 @@ bool WebViewCore::isLtr(const Position& position) return isLtr; } +static Node* findInputParent(Node* node) +{ + Node* testNode = node; + while (testNode) { + RenderObject* renderer = testNode->renderer(); + if (renderer + && (renderer->isTextArea() || renderer->isTextControl())) { + return testNode; + } + testNode = testNode->parentOrHostNode(); + } + return node; +} + SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) { bool isCaret = selection.isCaret(); @@ -1648,6 +1654,18 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) ? SelectText::RightHandle : SelectText::LeftHandle; setSelectionCaretInfo(selectTextContainer, extent, frameOffset, SelectText::ExtentHandle, extentHandleType, extentOffset, affinity); + IntRect clipRect; + if (selection.isContentEditable()) { + Node* editable = findInputParent(base.anchorNode()); + RenderObject* render = editable->renderer(); + if (render && render->isBox() && !render->isBody()) { + RenderBox* renderBox = toRenderBox(render); + clipRect = renderBox->clientBoxRect(); + FloatPoint pos = renderBox->localToAbsolute(clipRect.location()); + clipRect.setX(pos.x()); + clipRect.setY(pos.y()); + } + } Node* stopNode = range->pastLastNode(); for (Node* node = range->firstNode(); node != stopNode; node = node->traverseNextNode()) { @@ -1661,7 +1679,8 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) int layerId = platformLayerIdFromNode(node, &layer); Vector<IntRect> rects; renderText->absoluteRectsForRange(rects, startOffset, endOffset, true); - selectTextContainer->addHighlightRegion(layer, rects, frameOffset); + selectTextContainer->addHighlightRegion(layer, rects, frameOffset, + clipRect); } } selectTextContainer->setText(range->text()); @@ -4799,11 +4818,6 @@ static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jint nativeClass, WebCore::SchemeRegistry::registerURLSchemeAsLocal(jstringToWtfString(env, scheme)); } -static bool FocusBoundsChanged(JNIEnv* env, jobject obj, jint nativeClass) -{ - return reinterpret_cast<WebViewCore*>(nativeClass)->focusBoundsChanged(); -} - static void Pause(JNIEnv* env, jobject obj, jint nativeClass) { // This is called for the foreground tab when the browser is put to the @@ -5005,8 +5019,6 @@ static int FindNext(JNIEnv* env, jobject obj, jint nativeClass, static JNINativeMethod gJavaWebViewCoreMethods[] = { { "nativeClearContent", "(I)V", (void*) ClearContent }, - { "nativeFocusBoundsChanged", "(I)Z", - (void*) FocusBoundsChanged } , { "nativeKey", "(IIIIZZZZ)Z", (void*) Key }, { "nativeContentInvalidateAll", "(I)V", diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h index ba35005..def09d7 100644 --- a/Source/WebKit/android/jni/WebViewCore.h +++ b/Source/WebKit/android/jni/WebViewCore.h @@ -509,8 +509,6 @@ namespace android { // reset the picture set to empty void clearContent(); - bool focusBoundsChanged(); - // record content in a new BaseLayerAndroid, copying the layer tree as well WebCore::BaseLayerAndroid* recordContent(SkIPoint* ); @@ -760,7 +758,6 @@ namespace android { // Used in passToJS to avoid updating the UI text field until after the // key event has been processed. bool m_blockTextfieldUpdates; - bool m_focusBoundsChanged; bool m_skipContentDraw; // Passed in with key events to know when they were generated. Store it // with the cache so that we can ignore stale text changes. diff --git a/Source/WebKit/android/nav/DrawExtra.cpp b/Source/WebKit/android/nav/DrawExtra.cpp index 2f57dc1..a7d686c 100644 --- a/Source/WebKit/android/nav/DrawExtra.cpp +++ b/Source/WebKit/android/nav/DrawExtra.cpp @@ -52,7 +52,8 @@ SkRegion* RegionLayerDrawExtra::getHighlightRegionsForLayer(const LayerAndroid* } void RegionLayerDrawExtra::addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects, - const IntPoint& additionalOffset) + const IntPoint& additionalOffset, + const IntRect& clipRect) { if (rects.isEmpty()) return; @@ -66,6 +67,11 @@ void RegionLayerDrawExtra::addHighlightRegion(const LayerAndroid* layer, const V WebViewCore::layerToAbsoluteOffset(layer, offset); for (size_t i = 0; i < rects.size(); i++) { IntRect r = rects.at(i); + if (!clipRect.isEmpty()) { + r.intersect(clipRect); + if (r.isEmpty()) + continue; // don't add it to the region + } r.move(-offset.x(), -offset.y()); region->op(r.x(), r.y(), r.maxX(), r.maxY(), SkRegion::kUnion_Op); } diff --git a/Source/WebKit/android/nav/DrawExtra.h b/Source/WebKit/android/nav/DrawExtra.h index cc94476..1850b6b 100644 --- a/Source/WebKit/android/nav/DrawExtra.h +++ b/Source/WebKit/android/nav/DrawExtra.h @@ -65,7 +65,8 @@ public: virtual ~RegionLayerDrawExtra(); void addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects, - const IntPoint& additionalOffset = IntPoint()); + const IntPoint& additionalOffset = IntPoint(), + const IntRect& clipRect = IntRect()); virtual void draw(SkCanvas*, LayerAndroid*); virtual void drawGL(GLExtras*, const LayerAndroid*); diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp index 8b6d5f0..c708c25 100644 --- a/Source/WebKit/android/nav/WebView.cpp +++ b/Source/WebKit/android/nav/WebView.cpp @@ -32,6 +32,7 @@ #include "BaseLayerAndroid.h" #include "BaseRenderer.h" #include "DrawExtra.h" +#include "DumpLayer.h" #include "Frame.h" #include "GLWebViewState.h" #include "GraphicsJNI.h" @@ -316,7 +317,7 @@ void draw(SkCanvas* canvas, SkColor bgColor, DrawExtras extras) // call this to be sure we've adjusted for any scrolling or animations // before we actually draw - m_baseLayer->updateLayerPositions(m_visibleContentRect); + m_baseLayer->updatePositionsRecursive(m_visibleContentRect); m_baseLayer->updatePositions(); // We have to set the canvas' matrix on the base layer @@ -740,6 +741,20 @@ bool isHandleLeft(SelectText::HandleId handleId) return (selectText->getHandleType(handleId) == SelectText::LeftHandle); } +bool isPointVisible(int layerId, int contentX, int contentY) +{ + bool isVisible = true; + const TransformationMatrix* transform = getLayerTransform(layerId); + if (transform) { + // layer is guaranteed to be non-NULL because of getLayerTransform + LayerAndroid* layer = m_baseLayer->findById(layerId); + IntRect rect = layer->visibleContentArea(); + rect = transform->mapRect(rect); + isVisible = rect.contains(contentX, contentY); + } + return isVisible; +} + private: // local state for WebView bool m_isDrawingPaused; // private to getFrameCache(); other functions operate in a different thread @@ -981,6 +996,28 @@ static void nativeCopyBaseContentToPicture(JNIEnv *env, jobject obj, jobject pic GET_NATIVE_VIEW(env, obj)->copyBaseContentToPicture(picture); } +static jboolean nativeDumpLayerContentToPicture(JNIEnv *env, jobject obj, jint instance, + jstring jclassName, jint layerId, jobject pict) +{ + bool success = false; + SkPicture* picture = GraphicsJNI::getNativePicture(env, pict); + std::string classname = jstringToStdString(env, jclassName); + BaseLayerAndroid* baseLayer = reinterpret_cast<WebView*>(instance)->getBaseLayer(); + LayerAndroid* layer = baseLayer->findById(layerId); + SkSafeRef(layer); + if (layer && layer->subclassName() == classname) { + LayerContent* content = layer->content(); + if (content) { + SkCanvas* canvas = picture->beginRecording(content->width(), content->height()); + content->draw(canvas); + picture->endRecording(); + success = true; + } + } + SkSafeUnref(layer); + return success; +} + static bool nativeHasContent(JNIEnv *env, jobject obj) { return GET_NATIVE_VIEW(env, obj)->hasContent(); @@ -1173,7 +1210,8 @@ static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl) if (baseLayer) { FILE* file = fopen(LAYERS_TREE_LOG_FILE,"w"); if (file) { - baseLayer->dumpLayers(file, 0); + WebCore::FileLayerDumper dumper(file); + baseLayer->dumpLayers(&dumper); fclose(file); } } @@ -1304,6 +1342,13 @@ static bool nativeIsHandleLeft(JNIEnv *env, jobject obj, jint nativeView, return webview->isHandleLeft(static_cast<SelectText::HandleId>(handleId)); } +static bool nativeIsPointVisible(JNIEnv *env, jobject obj, jint nativeView, + jint layerId, jint contentX, jint contentY) +{ + WebView* webview = reinterpret_cast<WebView*>(nativeView); + return webview->isPointVisible(layerId, contentX, contentY); +} + /* * JNI registration */ @@ -1334,6 +1379,8 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeGetBaseLayer }, { "nativeCopyBaseContentToPicture", "(Landroid/graphics/Picture;)V", (void*) nativeCopyBaseContentToPicture }, + { "nativeDumpLayerContentToPicture", "(ILjava/lang/String;ILandroid/graphics/Picture;)Z", + (void*) nativeDumpLayerContentToPicture }, { "nativeHasContent", "()Z", (void*) nativeHasContent }, { "nativeDiscardAllTextures", "()V", @@ -1384,6 +1431,8 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeFindMaxVisibleRect }, { "nativeIsHandleLeft", "(II)Z", (void*) nativeIsHandleLeft }, + { "nativeIsPointVisible", "(IIII)Z", + (void*) nativeIsPointVisible }, }; int registerWebView(JNIEnv* env) |