diff options
Diffstat (limited to 'Source/WebCore')
198 files changed, 7213 insertions, 5713 deletions
diff --git a/Source/WebCore/Android.derived.v8bindings.mk b/Source/WebCore/Android.derived.v8bindings.mk index 546cefe..509d21e 100644 --- a/Source/WebCore/Android.derived.v8bindings.mk +++ b/Source/WebCore/Android.derived.v8bindings.mk @@ -31,7 +31,7 @@ js_binding_scripts := \ $(LOCAL_PATH)/bindings/scripts/generate-bindings.pl # Add ACCELERATED_COMPOSITING=1 and ENABLE_3D_RENDERING=1 for layers support -FEATURE_DEFINES := ENABLE_ORIENTATION_EVENTS=1 ENABLE_TOUCH_EVENTS=1 ENABLE_DATABASE=1 ENABLE_OFFLINE_WEB_APPLICATIONS=1 ENABLE_DOM_STORAGE=1 ENABLE_VIDEO=1 ENABLE_GEOLOCATION=1 ENABLE_CONNECTION=1 ENABLE_APPLICATION_INSTALLED=1 ENABLE_XPATH=1 ENABLE_XSLT=1 ENABLE_DEVICE_ORIENTATION=1 ENABLE_FILE_READER=1 ENABLE_BLOB=1 ENABLE_WEB_TIMING=1 +FEATURE_DEFINES := ENABLE_ORIENTATION_EVENTS=1 ENABLE_TOUCH_EVENTS=1 ENABLE_DATABASE=1 ENABLE_OFFLINE_WEB_APPLICATIONS=1 ENABLE_DOM_STORAGE=1 ENABLE_VIDEO=1 ENABLE_GEOLOCATION=1 ENABLE_CONNECTION=1 ENABLE_APPLICATION_INSTALLED=1 ENABLE_XPATH=1 ENABLE_XSLT=1 ENABLE_DEVICE_ORIENTATION=1 ENABLE_FILE_READER=1 ENABLE_BLOB=1 ENABLE_WEB_TIMING=1 ENABLE_MEDIA_CAPTURE=1 # The defines above should be identical to those for JSC. FEATURE_DEFINES += V8_BINDING diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk index 816b163..794a4a8 100644 --- a/Source/WebCore/Android.mk +++ b/Source/WebCore/Android.mk @@ -633,66 +633,73 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/graphics/StringTruncator.cpp \ platform/graphics/WidthIterator.cpp \ \ - platform/graphics/android/AndroidAnimation.cpp \ - platform/graphics/android/BaseLayerAndroid.cpp \ - platform/graphics/android/BaseRenderer.cpp \ - platform/graphics/android/BaseTile.cpp \ - platform/graphics/android/BaseTileTexture.cpp \ platform/graphics/android/BitmapAllocatorAndroid.cpp \ - platform/graphics/android/ClassTracker.cpp \ - platform/graphics/android/DumpLayer.cpp \ - platform/graphics/android/FixedPositioning.cpp \ - platform/graphics/android/FontAndroid.cpp \ - platform/graphics/android/FontCacheAndroid.cpp \ - platform/graphics/android/FontCustomPlatformData.cpp \ - platform/graphics/android/FontDataAndroid.cpp \ - platform/graphics/android/FontPlatformDataAndroid.cpp \ - platform/graphics/android/GaneshContext.cpp \ - platform/graphics/android/GaneshRenderer.cpp \ - platform/graphics/android/GLExtras.cpp \ - platform/graphics/android/GLUtils.cpp \ - platform/graphics/android/GLWebViewState.cpp \ - platform/graphics/android/GlyphMapAndroid.cpp \ - platform/graphics/android/GradientAndroid.cpp \ - platform/graphics/android/GraphicsContextAndroid.cpp \ platform/graphics/android/GraphicsLayerAndroid.cpp \ - platform/graphics/android/IFrameContentLayerAndroid.cpp \ - platform/graphics/android/IFrameLayerAndroid.cpp \ + platform/graphics/android/GLWebViewState.cpp \ platform/graphics/android/ImageAndroid.cpp \ platform/graphics/android/ImageBufferAndroid.cpp \ platform/graphics/android/ImageSourceAndroid.cpp \ - platform/graphics/android/ImagesManager.cpp \ - platform/graphics/android/ImageTexture.cpp \ - platform/graphics/android/InspectorCanvas.cpp \ - platform/graphics/android/Layer.cpp \ - platform/graphics/android/LayerAndroid.cpp \ - platform/graphics/android/LayerGroup.cpp \ - platform/graphics/android/MediaLayer.cpp \ - platform/graphics/android/MediaTexture.cpp \ - platform/graphics/android/PaintTileOperation.cpp \ platform/graphics/android/PathAndroid.cpp \ platform/graphics/android/PatternAndroid.cpp \ - platform/graphics/android/PictureLayerContent.cpp \ - platform/graphics/android/PictureSetLayerContent.cpp \ - platform/graphics/android/PlatformGraphicsContext.cpp \ - platform/graphics/android/PerformanceMonitor.cpp \ - platform/graphics/android/RasterRenderer.cpp \ - platform/graphics/android/ScrollableLayerAndroid.cpp \ platform/graphics/android/SharedBufferStream.cpp \ - platform/graphics/android/ShaderProgram.cpp \ - platform/graphics/android/TextureInfo.cpp \ - platform/graphics/android/TexturesGenerator.cpp \ - platform/graphics/android/TilesManager.cpp \ - platform/graphics/android/TilesProfiler.cpp \ - platform/graphics/android/TiledPage.cpp \ - platform/graphics/android/TiledTexture.cpp \ - platform/graphics/android/TransferQueue.cpp \ - platform/graphics/android/SurfaceCollection.cpp \ - platform/graphics/android/SurfaceCollectionManager.cpp \ - platform/graphics/android/VerticalTextMap.cpp \ - platform/graphics/android/VideoLayerAndroid.cpp \ - platform/graphics/android/VideoLayerManager.cpp \ - platform/graphics/android/ZoomManager.cpp \ + \ + platform/graphics/android/context/GraphicsContextAndroid.cpp \ + platform/graphics/android/context/GraphicsOperationCollection.cpp \ + platform/graphics/android/context/PlatformGraphicsContext.cpp \ + platform/graphics/android/context/PlatformGraphicsContextRecording.cpp \ + platform/graphics/android/context/PlatformGraphicsContextSkia.cpp \ + \ + platform/graphics/android/fonts/FontAndroid.cpp \ + platform/graphics/android/fonts/FontCacheAndroid.cpp \ + platform/graphics/android/fonts/FontCustomPlatformData.cpp \ + platform/graphics/android/fonts/FontDataAndroid.cpp \ + platform/graphics/android/fonts/FontPlatformDataAndroid.cpp \ + platform/graphics/android/fonts/GlyphMapAndroid.cpp \ + platform/graphics/android/fonts/VerticalTextMap.cpp \ + \ + platform/graphics/android/layers/AndroidAnimation.cpp \ + platform/graphics/android/layers/BaseLayerAndroid.cpp \ + platform/graphics/android/layers/CanvasLayer.cpp \ + platform/graphics/android/layers/CanvasTexture.cpp \ + platform/graphics/android/layers/DumpLayer.cpp \ + platform/graphics/android/layers/FixedPositioning.cpp \ + platform/graphics/android/layers/IFrameContentLayerAndroid.cpp \ + platform/graphics/android/layers/IFrameLayerAndroid.cpp \ + platform/graphics/android/layers/Layer.cpp \ + platform/graphics/android/layers/LayerAndroid.cpp \ + platform/graphics/android/layers/MediaLayer.cpp \ + platform/graphics/android/layers/MediaTexture.cpp \ + platform/graphics/android/layers/PictureLayerContent.cpp \ + platform/graphics/android/layers/PictureSetLayerContent.cpp \ + platform/graphics/android/layers/ScrollableLayerAndroid.cpp \ + platform/graphics/android/layers/VideoLayerAndroid.cpp \ + platform/graphics/android/layers/VideoLayerManager.cpp \ + \ + platform/graphics/android/rendering/BaseRenderer.cpp \ + platform/graphics/android/rendering/GaneshContext.cpp \ + platform/graphics/android/rendering/GaneshRenderer.cpp \ + platform/graphics/android/rendering/GLExtras.cpp \ + platform/graphics/android/rendering/GLUtils.cpp \ + platform/graphics/android/rendering/ImagesManager.cpp \ + platform/graphics/android/rendering/ImageTexture.cpp \ + platform/graphics/android/rendering/InspectorCanvas.cpp \ + platform/graphics/android/rendering/PaintTileOperation.cpp \ + platform/graphics/android/rendering/RasterRenderer.cpp \ + platform/graphics/android/rendering/ShaderProgram.cpp \ + platform/graphics/android/rendering/Surface.cpp \ + platform/graphics/android/rendering/SurfaceBacking.cpp \ + platform/graphics/android/rendering/SurfaceCollection.cpp \ + platform/graphics/android/rendering/SurfaceCollectionManager.cpp \ + platform/graphics/android/rendering/TextureInfo.cpp \ + platform/graphics/android/rendering/TexturesGenerator.cpp \ + platform/graphics/android/rendering/Tile.cpp \ + platform/graphics/android/rendering/TileGrid.cpp \ + platform/graphics/android/rendering/TileTexture.cpp \ + platform/graphics/android/rendering/TilesManager.cpp \ + platform/graphics/android/rendering/TilesProfiler.cpp \ + platform/graphics/android/rendering/TransferQueue.cpp \ + \ + platform/graphics/android/utils/ClassTracker.cpp ifeq ($(ENABLE_SVG), true) LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ @@ -720,6 +727,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/graphics/skia/FloatPointSkia.cpp \ platform/graphics/skia/FloatRectSkia.cpp \ platform/graphics/skia/GlyphPageTreeNodeSkia.cpp \ + platform/graphics/skia/GradientSkia.cpp \ platform/graphics/skia/IntPointSkia.cpp \ platform/graphics/skia/IntRectSkia.cpp \ platform/graphics/skia/NativeImageSkia.cpp \ @@ -1264,5 +1272,5 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ # For complex scripts(Arabic, Thai, Hindi...). ifeq ($(SUPPORT_COMPLEX_SCRIPTS),true) LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ - platform/graphics/android/HarfbuzzSkia.cpp + platform/graphics/android/fonts/HarfbuzzSkia.cpp endif diff --git a/Source/WebCore/WebCore.exp.in b/Source/WebCore/WebCore.exp.in index f110846..c6c76bf 100644 --- a/Source/WebCore/WebCore.exp.in +++ b/Source/WebCore/WebCore.exp.in @@ -1595,7 +1595,6 @@ __ZN7WebCore17HTMLPlugInElement11getNPObjectEv __ZNK7WebCore14SecurityOrigin9canAccessEPKS0_ __ZNK7WebCore4KURL10protocolIsEPKc __ZNK7WebCore4KURL7hasPathEv -__ZNK7WebCore4KURL9prettyURLEv #endif #if ENABLE(ORIENTATION_EVENTS) diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp index b78a6d0..06e895d 100644 --- a/Source/WebCore/css/CSSParser.cpp +++ b/Source/WebCore/css/CSSParser.cpp @@ -5383,6 +5383,8 @@ bool CSSParser::parseRadialGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea // parseFillPosition advances the args next pointer. parseFillPosition(args, centerX, centerY); a = args->current(); + if (!a) + return false; if (centerX || centerY) { // Comma diff --git a/Source/WebCore/css/CSSPrimitiveValue.cpp b/Source/WebCore/css/CSSPrimitiveValue.cpp index 04f1089..237844e 100644 --- a/Source/WebCore/css/CSSPrimitiveValue.cpp +++ b/Source/WebCore/css/CSSPrimitiveValue.cpp @@ -316,7 +316,8 @@ double CSSPrimitiveValue::computeLengthDouble(RenderStyle* style, RenderStyle* r break; case CSS_REMS: applyZoomMultiplier = false; - factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize(); + if (rootStyle) + factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize(); break; case CSS_PX: break; diff --git a/Source/WebCore/css/CSSStyleSelector.cpp b/Source/WebCore/css/CSSStyleSelector.cpp index 0b6fd35..2424349 100644 --- a/Source/WebCore/css/CSSStyleSelector.cpp +++ b/Source/WebCore/css/CSSStyleSelector.cpp @@ -1194,7 +1194,8 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document) documentStyle->setVisuallyOrdered(document->visuallyOrdered()); documentStyle->setZoom(frame ? frame->pageZoomFactor() : 1); documentStyle->setPageScaleTransform(frame ? frame->pageScaleFactor() : 1); - + documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ONLY); + Element* docElement = document->documentElement(); RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0; if (docElementRenderer) { @@ -4966,6 +4967,11 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) applyProperty(CSSPropertyFontStyle, font->style.get()); applyProperty(CSSPropertyFontVariant, font->variant.get()); applyProperty(CSSPropertyFontWeight, font->weight.get()); + // The previous properties can dirty our font but they don't try to read the font's + // properties back, which is safe. However if font-size is using the 'ex' unit, it will + // need query the dirtied font's x-height to get the computed size. To be safe in this + // case, let's just update the font now. + updateFont(); applyProperty(CSSPropertyFontSize, font->size.get()); m_lineHeightValue = font->lineHeight.get(); diff --git a/Source/WebCore/css/WebKitCSSKeyframesRule.cpp b/Source/WebCore/css/WebKitCSSKeyframesRule.cpp index 3b41f43..497bd19 100644 --- a/Source/WebCore/css/WebKitCSSKeyframesRule.cpp +++ b/Source/WebCore/css/WebKitCSSKeyframesRule.cpp @@ -66,7 +66,8 @@ void WebKitCSSKeyframesRule::setName(const String& name) // Since the name is used in the keyframe map list in CSSStyleSelector, we need // to recompute the style sheet to get the updated name. - stylesheet()->styleSheetChanged(); + if (stylesheet()) + stylesheet()->styleSheetChanged(); } unsigned WebKitCSSKeyframesRule::length() const diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp index 1b5f55b..7fc628c 100644 --- a/Source/WebCore/dom/Document.cpp +++ b/Source/WebCore/dom/Document.cpp @@ -4083,6 +4083,8 @@ void Document::setTransformSource(PassOwnPtr<TransformSource> source) void Document::setDesignMode(InheritedBool value) { m_designMode = value; + for (Frame* frame = m_frame; frame && frame->document(); frame = frame->tree()->traverseNext(m_frame)) + frame->document()->scheduleForcedStyleRecalc(); } Document::InheritedBool Document::getDesignMode() const diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp index 0967ef5..da4312c 100644 --- a/Source/WebCore/dom/Node.cpp +++ b/Source/WebCore/dom/Node.cpp @@ -770,7 +770,7 @@ bool Node::isContentEditable() const bool Node::rendererIsEditable(EditableLevel editableLevel) const { - if (document()->inDesignMode() || (document()->frame() && document()->frame()->page() && document()->frame()->page()->isEditable())) + if (document()->frame() && document()->frame()->page() && document()->frame()->page()->isEditable()) return true; // Ideally we'd call ASSERT(!needsStyleRecalc()) here, but @@ -1614,7 +1614,7 @@ SVGUseElement* Node::svgShadowHost() const } #endif -Node* Node::shadowAncestorNode() +Node* Node::shadowAncestorNode() const { #if ENABLE(SVG) // SVG elements living in a shadow tree only occur when <use> created them. @@ -1622,18 +1622,18 @@ Node* Node::shadowAncestorNode() // but the actual shadow tree element - as main difference to the HTML forms // shadow tree concept. (This function _could_ be made virtual - opinions?) if (isSVGElement()) - return this; + return const_cast<Node*>(this); #endif Node* root = shadowTreeRootNode(); if (root) return root->shadowHost(); - return this; + return const_cast<Node*>(this); } -Node* Node::shadowTreeRootNode() +Node* Node::shadowTreeRootNode() const { - Node* root = this; + Node* root = const_cast<Node*>(this); while (root) { if (root->isShadowRoot() || root->isSVGShadowRoot()) return root; diff --git a/Source/WebCore/dom/Node.h b/Source/WebCore/dom/Node.h index 08b1921..76355c3 100644 --- a/Source/WebCore/dom/Node.h +++ b/Source/WebCore/dom/Node.h @@ -218,8 +218,8 @@ public: virtual bool isShadowBoundary() const { return false; } virtual bool canHaveLightChildRendererWithShadow() const { return false; } - Node* shadowAncestorNode(); - Node* shadowTreeRootNode(); + Node* shadowAncestorNode() const; + Node* shadowTreeRootNode() const; bool isInShadowTree(); // Node's parent, shadow tree host, or SVG use. ContainerNode* parentOrHostNode() const; diff --git a/Source/WebCore/dom/Range.cpp b/Source/WebCore/dom/Range.cpp index 469a94a..268687f 100644 --- a/Source/WebCore/dom/Range.cpp +++ b/Source/WebCore/dom/Range.cpp @@ -51,6 +51,8 @@ using namespace std; static WTF::RefCountedLeakCounter rangeCounter("Range"); #endif +typedef Vector<RefPtr<Node> > NodeVector; + inline Range::Range(PassRefPtr<Document> ownerDocument) : m_ownerDocument(ownerDocument) , m_start(m_ownerDocument) @@ -662,8 +664,6 @@ static inline unsigned lengthOfContentsInNode(Node* node) PassRefPtr<DocumentFragment> Range::processContents(ActionType action, ExceptionCode& ec) { - typedef Vector<RefPtr<Node> > NodeVector; - RefPtr<DocumentFragment> fragment; if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) fragment = DocumentFragment::create(m_ownerDocument.get()); @@ -873,9 +873,14 @@ PassRefPtr<Node> Range::processAncestorsAndTheirSiblings(ActionType action, Node // FIXME: This assertion may fail if DOM is modified during mutation event // FIXME: Share code with Range::processNodes ASSERT(!firstChildInAncestorToProcess || firstChildInAncestorToProcess->parentNode() == ancestor); - RefPtr<Node> next; - for (Node* child = firstChildInAncestorToProcess.get(); child; child = next.get()) { - next = direction == ProcessContentsForward ? child->nextSibling() : child->previousSibling(); + + NodeVector nodes; + for (Node* child = firstChildInAncestorToProcess.get(); child; + child = (direction == ProcessContentsForward) ? child->nextSibling() : child->previousSibling()) + nodes.append(child); + + for (NodeVector::const_iterator it = nodes.begin(); it != nodes.end(); it++) { + Node* child = it->get(); switch (action) { case DELETE_CONTENTS: ancestor->removeChild(child, ec); diff --git a/Source/WebCore/editing/ApplyStyleCommand.cpp b/Source/WebCore/editing/ApplyStyleCommand.cpp index c9649d0..4f1bc93 100644 --- a/Source/WebCore/editing/ApplyStyleCommand.cpp +++ b/Source/WebCore/editing/ApplyStyleCommand.cpp @@ -1316,8 +1316,10 @@ void ApplyStyleCommand::surroundNodeRangeWithElement(PassRefPtr<Node> passedStar RefPtr<Node> node = startNode; while (node) { RefPtr<Node> next = node->nextSibling(); - removeNode(node); - appendNode(node, element); + if (node->isContentEditable()) { + removeNode(node); + appendNode(node, element); + } if (node == endNode) break; node = next; diff --git a/Source/WebCore/editing/CompositeEditCommand.cpp b/Source/WebCore/editing/CompositeEditCommand.cpp index cf2959a..bf515d7 100644 --- a/Source/WebCore/editing/CompositeEditCommand.cpp +++ b/Source/WebCore/editing/CompositeEditCommand.cpp @@ -781,7 +781,7 @@ void CompositeEditCommand::cloneParagraphUnderNewElement(Position& start, Positi appendNode(topNode, blockElement); RefPtr<Node> lastNode = topNode; - if (start.deprecatedNode() != outerNode) { + if (start.deprecatedNode() != outerNode && lastNode->isElementNode()) { Vector<RefPtr<Node> > ancestors; // Insert each node from innerNode to outerNode (excluded) in a list. diff --git a/Source/WebCore/fileapi/DOMFileSystemBase.cpp b/Source/WebCore/fileapi/DOMFileSystemBase.cpp index eafb815..5a2627f 100644 --- a/Source/WebCore/fileapi/DOMFileSystemBase.cpp +++ b/Source/WebCore/fileapi/DOMFileSystemBase.cpp @@ -63,7 +63,7 @@ bool DOMFileSystemBase::crackFileSystemURL(const KURL& url, AsyncFileSystem::Typ return false; KURL originURL(ParsedURLString, url.path()); - String path = originURL.path(); + String path = decodeURLEscapeSequences(originURL.path()); if (path.isEmpty() || path[0] != '/') return false; path = path.substring(1); diff --git a/Source/WebCore/html/HTMLAnchorElement.cpp b/Source/WebCore/html/HTMLAnchorElement.cpp index 4636f20..b05e7f5 100644 --- a/Source/WebCore/html/HTMLAnchorElement.cpp +++ b/Source/WebCore/html/HTMLAnchorElement.cpp @@ -405,7 +405,10 @@ void HTMLAnchorElement::setPathname(const String& value) String HTMLAnchorElement::port() const { - return String::number(href().port()); + if (href().hasPort()) + return String::number(href().port()); + + return ""; } void HTMLAnchorElement::setPort(const String& value) diff --git a/Source/WebCore/html/HTMLAttributeNames.in b/Source/WebCore/html/HTMLAttributeNames.in index 5e0fe7b..578f717 100644 --- a/Source/WebCore/html/HTMLAttributeNames.in +++ b/Source/WebCore/html/HTMLAttributeNames.in @@ -58,6 +58,7 @@ bgcolor bgproperties border bordercolor +capture cellpadding cellspacing char diff --git a/Source/WebCore/html/HTMLCanvasElement.cpp b/Source/WebCore/html/HTMLCanvasElement.cpp index 9f51f10..e67cbf9 100644 --- a/Source/WebCore/html/HTMLCanvasElement.cpp +++ b/Source/WebCore/html/HTMLCanvasElement.cpp @@ -45,6 +45,7 @@ #include "MIMETypeRegistry.h" #include "Page.h" #include "RenderHTMLCanvas.h" +#include "RenderLayer.h" #include "Settings.h" #include <math.h> #include <stdio.h> @@ -225,6 +226,11 @@ void HTMLCanvasElement::didDraw(const FloatRect& rect) return; m_dirtyRect.unite(r); +#if PLATFORM(ANDROID) + // We handle invals ourselves and don't want webkit to repaint if we + // have put the canvas on a layer + if (!ro->hasLayer()) +#endif ro->repaintRectangle(enclosingIntRect(m_dirtyRect)); } diff --git a/Source/WebCore/html/HTMLCanvasElement.h b/Source/WebCore/html/HTMLCanvasElement.h index 207c384..e485835 100644 --- a/Source/WebCore/html/HTMLCanvasElement.h +++ b/Source/WebCore/html/HTMLCanvasElement.h @@ -128,6 +128,10 @@ public: void makeRenderingResultsAvailable(); +#if PLATFORM(ANDROID) + void clearDirtyRect() { m_dirtyRect = FloatRect(); } +#endif + private: HTMLCanvasElement(const QualifiedName&, Document*); diff --git a/Source/WebCore/html/HTMLElement.cpp b/Source/WebCore/html/HTMLElement.cpp index b2b57a2..82e33d1 100644 --- a/Source/WebCore/html/HTMLElement.cpp +++ b/Source/WebCore/html/HTMLElement.cpp @@ -682,11 +682,6 @@ void HTMLElement::setContentEditable(Attribute* attr) attr->decl()->removeProperty(CSSPropertyWordWrap, false); attr->decl()->removeProperty(CSSPropertyWebkitNbspMode, false); attr->decl()->removeProperty(CSSPropertyWebkitLineBreak, false); - } else if (equalIgnoringCase(enabled, "inherit")) { - addCSSProperty(attr, CSSPropertyWebkitUserModify, CSSValueInherit); - attr->decl()->removeProperty(CSSPropertyWordWrap, false); - attr->decl()->removeProperty(CSSPropertyWebkitNbspMode, false); - attr->decl()->removeProperty(CSSPropertyWebkitLineBreak, false); } else if (equalIgnoringCase(enabled, "plaintext-only")) { addCSSProperty(attr, CSSPropertyWebkitUserModify, CSSValueReadWritePlaintextOnly); addCSSProperty(attr, CSSPropertyWordWrap, CSSValueBreakWord); diff --git a/Source/WebCore/html/HTMLInputElement.cpp b/Source/WebCore/html/HTMLInputElement.cpp index 2b262e4..36cdf51 100644 --- a/Source/WebCore/html/HTMLInputElement.cpp +++ b/Source/WebCore/html/HTMLInputElement.cpp @@ -1588,4 +1588,24 @@ void HTMLInputElement::handleBeforeTextInsertedEvent(Event* event) InputElement::handleBeforeTextInsertedEvent(m_data, this, this, event); } +#if PLATFORM(ANDROID) && ENABLE(MEDIA_CAPTURE) +String HTMLInputElement::capture() const +{ + if (!isFileUpload()) { + // capture has no meaning on anything other than file pickers. + return String(); + } + + String capture = fastGetAttribute(captureAttr).lower(); + if (capture == "camera" + || capture == "camcorder" + || capture == "microphone" + || capture == "filesystem") + return capture; + // According to the HTML Media Capture specification, the invalid and + // missing default value is filesystem. + return "filesystem"; +} +#endif + } // namespace diff --git a/Source/WebCore/html/HTMLInputElement.h b/Source/WebCore/html/HTMLInputElement.h index 2a98b13..58d86ac 100644 --- a/Source/WebCore/html/HTMLInputElement.h +++ b/Source/WebCore/html/HTMLInputElement.h @@ -200,6 +200,10 @@ public: void updateCheckedRadioButtons(); bool lastChangeWasUserEdit() const; + +#if PLATFORM(ANDROID) && ENABLE(MEDIA_CAPTURE) + String capture() const; +#endif protected: HTMLInputElement(const QualifiedName&, Document*, HTMLFormElement*, bool createdByParser); diff --git a/Source/WebCore/html/HTMLInputElement.idl b/Source/WebCore/html/HTMLInputElement.idl index f346e10..e1937e4 100644 --- a/Source/WebCore/html/HTMLInputElement.idl +++ b/Source/WebCore/html/HTMLInputElement.idl @@ -107,6 +107,9 @@ module html { attribute [Reflect, EnabledAtRuntime] boolean webkitGrammar; attribute [DontEnum] EventListener onwebkitspeechchange; #endif +#if defined(WTF_PLATFORM_ANDROID) && defined(ENABLE_MEDIA_CAPTURE) && ENABLE_MEDIA_CAPTURE + attribute [Reflect] DOMString capture; +#endif }; } diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp index 5cd2ddd..46e8a12 100644 --- a/Source/WebCore/html/HTMLMediaElement.cpp +++ b/Source/WebCore/html/HTMLMediaElement.cpp @@ -238,7 +238,9 @@ void HTMLMediaElement::attributeChanged(Attribute* attr, bool preserveDecls) #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO) if (controls()) { if (!hasMediaControls()) { - ensureMediaControls(); + if (!createMediaControls()) + return; + mediaControls()->reset(); } mediaControls()->show(); @@ -2739,13 +2741,18 @@ bool HTMLMediaElement::hasMediaControls() return node && node->isMediaControls(); } -void HTMLMediaElement::ensureMediaControls() +bool HTMLMediaElement::createMediaControls() { if (hasMediaControls()) - return; + return true; ExceptionCode ec; - ensureShadowRoot()->appendChild(MediaControls::create(this), ec); + RefPtr<MediaControls> controls = MediaControls::create(this); + if (!controls) + return false; + + ensureShadowRoot()->appendChild(controls, ec); + return true; } void* HTMLMediaElement::preDispatchEventHandler(Event* event) @@ -2753,7 +2760,9 @@ void* HTMLMediaElement::preDispatchEventHandler(Event* event) if (event && event->type() == eventNames().webkitfullscreenchangeEvent) { if (controls()) { if (!hasMediaControls()) { - ensureMediaControls(); + if (!createMediaControls()) + return 0; + mediaControls()->reset(); } mediaControls()->show(); diff --git a/Source/WebCore/html/HTMLMediaElement.h b/Source/WebCore/html/HTMLMediaElement.h index 2144ea1..0b11861 100644 --- a/Source/WebCore/html/HTMLMediaElement.h +++ b/Source/WebCore/html/HTMLMediaElement.h @@ -325,7 +325,7 @@ private: void refreshCachedTime() const; bool hasMediaControls(); - void ensureMediaControls(); + bool createMediaControls(); virtual void* preDispatchEventHandler(Event*); diff --git a/Source/WebCore/html/shadow/TextControlInnerElements.h b/Source/WebCore/html/shadow/TextControlInnerElements.h index 2340970..886fbf8 100644 --- a/Source/WebCore/html/shadow/TextControlInnerElements.h +++ b/Source/WebCore/html/shadow/TextControlInnerElements.h @@ -101,9 +101,8 @@ private: virtual void detach(); virtual bool isSpinButtonElement() const { return true; } - // FIXME: shadowAncestorNode() should be const. - virtual bool isEnabledFormControl() const { return static_cast<Element*>(const_cast<SpinButtonElement*>(this)->shadowAncestorNode())->isEnabledFormControl(); } - virtual bool isReadOnlyFormControl() const { return static_cast<Element*>(const_cast<SpinButtonElement*>(this)->shadowAncestorNode())->isReadOnlyFormControl(); } + virtual bool isEnabledFormControl() const { return static_cast<Element*>(shadowAncestorNode())->isEnabledFormControl(); } + virtual bool isReadOnlyFormControl() const { return static_cast<Element*>(shadowAncestorNode())->isReadOnlyFormControl(); } virtual void defaultEventHandler(Event*); void startRepeatingTimer(); void stopRepeatingTimer(); diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp index f999fdb..670cf1f 100644 --- a/Source/WebCore/loader/FrameLoader.cpp +++ b/Source/WebCore/loader/FrameLoader.cpp @@ -993,7 +993,8 @@ void FrameLoader::loadArchive(PassRefPtr<Archive> prpArchive) ObjectContentType FrameLoader::defaultObjectContentType(const KURL& url, const String& mimeTypeIn, bool shouldPreferPlugInsForImages) { String mimeType = mimeTypeIn; - String extension = url.path().substring(url.path().reverseFind('.') + 1); + String decodedPath = decodeURLEscapeSequences(url.path()); + String extension = decodedPath.substring(decodedPath.reverseFind('.') + 1); // We don't use MIMETypeRegistry::getMIMETypeForPath() because it returns "application/octet-stream" upon failure if (mimeType.isEmpty()) diff --git a/Source/WebCore/loader/cache/CachedResourceLoader.cpp b/Source/WebCore/loader/cache/CachedResourceLoader.cpp index 91c0629..fe25a93 100644 --- a/Source/WebCore/loader/cache/CachedResourceLoader.cpp +++ b/Source/WebCore/loader/cache/CachedResourceLoader.cpp @@ -293,6 +293,8 @@ bool CachedResourceLoader::canRequest(CachedResource::Type type, const KURL& url } #if ENABLE(LINK_PREFETCH) case CachedResource::LinkResource: + if (!m_document->settings()->linkPrefetchEnabled()) + return false; break; #endif } diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp index a737754..45450b5 100644 --- a/Source/WebCore/page/EventHandler.cpp +++ b/Source/WebCore/page/EventHandler.cpp @@ -3224,15 +3224,7 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) // When sending a touch cancel event, use empty touches and targetTouches lists. bool isTouchCancelEvent = (state == PlatformTouchPoint::TouchCancelled); RefPtr<TouchList>& effectiveTouches(isTouchCancelEvent ? emptyList : touches); -#if PLATFORM(ANDROID) - AtomicString stateName(eventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state))); - if (event.type() == TouchLongPress) - stateName = eventNames().touchlongpressEvent; - else if (event.type() == TouchDoubleTap) - stateName = eventNames().touchdoubletapEvent; -#else const AtomicString& stateName(eventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state))); -#endif const EventTargetSet& targetsForState = changedTouches[state].m_targets; for (EventTargetSet::const_iterator it = targetsForState.begin(); it != targetsForState.end(); ++it) { diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp index f332074..8f2958c 100644 --- a/Source/WebCore/page/FrameView.cpp +++ b/Source/WebCore/page/FrameView.cpp @@ -1745,6 +1745,11 @@ void FrameView::scheduleRelayout() m_frame->ownerRenderer()->setNeedsLayout(true, true); } +#ifdef ANDROID_FLATTEN_FRAMESET + if (m_frame->ownerRenderer() && m_frame->ownerElement()->hasTagName(frameTag)) + m_frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc(); +#endif + int delay = m_frame->document()->minimumLayoutDelay(); if (m_layoutTimer.isActive() && m_delayedLayout && !delay) unscheduleRelayout(); diff --git a/Source/WebCore/page/Location.cpp b/Source/WebCore/page/Location.cpp index 4835a83..fb68a09 100644 --- a/Source/WebCore/page/Location.cpp +++ b/Source/WebCore/page/Location.cpp @@ -63,8 +63,7 @@ String Location::href() const if (!m_frame) return String(); - const KURL& url = this->url(); - return url.hasPath() ? url.prettyURL() : url.prettyURL() + "/"; + return url().string(); } String Location::protocol() const @@ -83,7 +82,7 @@ String Location::host() const // Note: this is the IE spec. The NS spec swaps the two, it says // "The hostname property is the concatenation of the host and port properties, separated by a colon." const KURL& url = this->url(); - return url.port() ? url.host() + ":" + String::number(url.port()) : url.host(); + return url.hasPort() ? url.host() + ":" + String::number(url.port()) : url.host(); } String Location::hostname() const @@ -100,7 +99,7 @@ String Location::port() const return String(); const KURL& url = this->url(); - return url.port() ? String::number(url.port()) : ""; + return url.hasPort() ? String::number(url.port()) : ""; } String Location::pathname() const @@ -147,15 +146,6 @@ String Location::getParameter(const String& name) const return parameters.get(name); } -String Location::toString() const -{ - if (!m_frame) - return String(); - - const KURL& url = this->url(); - return url.hasPath() ? url.prettyURL() : url.prettyURL() + "/"; -} - void Location::setHref(const String& urlString, DOMWindow* activeWindow, DOMWindow* firstWindow) { if (!m_frame) @@ -199,7 +189,7 @@ void Location::setPort(const String& portString, DOMWindow* activeWindow, DOMWin return; KURL url = m_frame->document()->url(); int port = portString.toInt(); - if (port < 0 || port > 0xFFFF) + if (port < 0 || port > 0xFFFF || portString.isEmpty()) url.removePort(); else url.setPort(port); diff --git a/Source/WebCore/page/Location.h b/Source/WebCore/page/Location.h index 1b68cee..0e89ecf 100644 --- a/Source/WebCore/page/Location.h +++ b/Source/WebCore/page/Location.h @@ -29,9 +29,9 @@ #ifndef Location_h #define Location_h -#include <wtf/Forward.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> +#include <wtf/text/WTFString.h> namespace WebCore { @@ -71,7 +71,7 @@ public: String hash() const; String origin() const; - String toString() const; + String toString() const { return href(); } String getParameter(const String&) const; diff --git a/Source/WebCore/page/Settings.cpp b/Source/WebCore/page/Settings.cpp index c26a0fc..f668f3e 100644 --- a/Source/WebCore/page/Settings.cpp +++ b/Source/WebCore/page/Settings.cpp @@ -149,6 +149,9 @@ Settings::Settings(Page* page) // they can't use by. Leaving enabled for now to not change existing behavior. , m_downloadableBinaryFontsEnabled(true) , m_xssAuditorEnabled(false) +#if ENABLE(LINK_PREFETCH) + , m_linkPrefetchEnabled(true) +#endif , m_acceleratedCompositingEnabled(true) , m_acceleratedCompositingFor3DTransformsEnabled(true) , m_acceleratedCompositingForVideoEnabled(true) @@ -823,6 +826,13 @@ void Settings::setXSSAuditorEnabled(bool xssAuditorEnabled) m_xssAuditorEnabled = xssAuditorEnabled; } +#if ENABLE(LINK_PREFETCH) +void Settings::setLinkPrefetchEnabled(bool linkPrefetchEnabled) +{ + m_linkPrefetchEnabled = linkPrefetchEnabled; +} +#endif + void Settings::setAcceleratedCompositingEnabled(bool enabled) { if (m_acceleratedCompositingEnabled == enabled) diff --git a/Source/WebCore/page/Settings.h b/Source/WebCore/page/Settings.h index 2bb222d..2cf7715 100644 --- a/Source/WebCore/page/Settings.h +++ b/Source/WebCore/page/Settings.h @@ -352,6 +352,11 @@ namespace WebCore { void setXSSAuditorEnabled(bool); bool xssAuditorEnabled() const { return m_xssAuditorEnabled; } +#if ENABLE(LINK_PREFETCH) + void setLinkPrefetchEnabled(bool); + bool linkPrefetchEnabled() const { return m_linkPrefetchEnabled; } +#endif + void setCanvasUsesAcceleratedDrawing(bool); bool canvasUsesAcceleratedDrawing() const { return m_canvasUsesAcceleratedDrawing; } @@ -567,6 +572,9 @@ namespace WebCore { bool m_acceleratedDrawingEnabled : 1; bool m_downloadableBinaryFontsEnabled : 1; bool m_xssAuditorEnabled : 1; +#if ENABLE(LINK_PREFETCH) + bool m_linkPrefetchEnabled : 1; +#endif bool m_acceleratedCompositingEnabled : 1; bool m_acceleratedCompositingFor3DTransformsEnabled : 1; bool m_acceleratedCompositingForVideoEnabled : 1; diff --git a/Source/WebCore/platform/FileChooser.h b/Source/WebCore/platform/FileChooser.h index ac5e0e6..6c382d1 100644 --- a/Source/WebCore/platform/FileChooser.h +++ b/Source/WebCore/platform/FileChooser.h @@ -50,6 +50,9 @@ public: virtual String acceptTypes() = 0; virtual void chooseIconForFiles(FileChooser*, const Vector<String>&) = 0; virtual ~FileChooserClient(); +#if PLATFORM(ANDROID) && ENABLE(MEDIA_CAPTURE) + virtual String capture() = 0; +#endif }; class FileChooser : public RefCounted<FileChooser> { @@ -79,6 +82,10 @@ public: // Acceptable MIME types. It's an 'accept' attribute value of the corresponding INPUT element. String acceptTypes() const { return m_client ? m_client->acceptTypes() : String(); } +#if PLATFORM(ANDROID) && ENABLE(MEDIA_CAPTURE) + String capture() const { return m_client ? m_client->capture() : String(); } +#endif + private: FileChooser(FileChooserClient*, const Vector<String>& initialFilenames); void initialize(); diff --git a/Source/WebCore/platform/KURL.cpp b/Source/WebCore/platform/KURL.cpp index 88ad3d9..234d749 100644 --- a/Source/WebCore/platform/KURL.cpp +++ b/Source/WebCore/platform/KURL.cpp @@ -708,7 +708,7 @@ String KURL::query() const String KURL::path() const { - return decodeURLEscapeSequences(m_string.substring(m_portEnd, m_pathEnd - m_portEnd)); + return m_string.substring(m_portEnd, m_pathEnd - m_portEnd); } bool KURL::setProtocol(const String& s) @@ -866,7 +866,7 @@ void KURL::setPath(const String& s) parse(m_string.left(m_portEnd) + encodeWithURLEscapeSequences(path) + m_string.substring(m_pathEnd)); } -String KURL::prettyURL() const +String KURL::deprecatedString() const { if (!m_isValid) return m_string; @@ -996,7 +996,7 @@ static void appendEscapingBadChars(char*& buffer, const char* strStart, size_t l buffer = p; } -static void escapeAndAppendFragment(char*& buffer, const char* strStart, size_t length) +static void escapeAndAppendNonHierarchicalPart(char*& buffer, const char* strStart, size_t length) { char* p = buffer; @@ -1137,6 +1137,23 @@ static inline bool hostPortIsEmptyButCredentialsArePresent(int hostStart, int po return userEndChar == '@' && hostStart == portEnd; } +static bool isNonFileHierarchicalScheme(const char* scheme, size_t schemeLength) +{ + switch (schemeLength) { + case 2: + return equal("ws", 2, scheme, schemeLength); + case 3: + return equal("ftp", 3, scheme, schemeLength) || equal("wss", 3, scheme, schemeLength); + case 4: + return equal("http", 4, scheme, schemeLength); + case 5: + return equal("https", 5, scheme, schemeLength); + case 6: + return equal("gopher", 6, scheme, schemeLength); + } + return false; +} + void KURL::parse(const char* url, const String* originalString) { if (!url || url[0] == '\0') { @@ -1173,6 +1190,7 @@ void KURL::parse(const char* url, const String* originalString) int portEnd; bool hierarchical = url[schemeEnd + 1] == '/'; + bool hasSecondSlash = hierarchical && url[schemeEnd + 2] == '/'; bool isFile = schemeEnd == 4 && matchLetter(url[0], 'f') @@ -1186,12 +1204,15 @@ void KURL::parse(const char* url, const String* originalString) && matchLetter(url[3], 'p') && (url[4] == ':' || (matchLetter(url[4], 's') && url[5] == ':')); - if (hierarchical && url[schemeEnd + 2] == '/') { + if ((hierarchical && hasSecondSlash) || isNonFileHierarchicalScheme(url, schemeEnd)) { // The part after the scheme is either a net_path or an abs_path whose first path segment is empty. // Attempt to find an authority. - // FIXME: Authority characters may be scanned twice, and it would be nice to be faster. - userStart += 2; + + if (hierarchical) + userStart++; + if (hasSecondSlash) + userStart++; userEnd = userStart; int colonPos = 0; @@ -1394,12 +1415,14 @@ void KURL::parse(const char* url, const String* originalString) m_userStart = m_userEnd = m_passwordEnd = m_hostEnd = m_portEnd = p - buffer.data(); // For canonicalization, ensure we have a '/' for no path. - // Do this only for hierarchical URL with protocol http or https. - if (m_protocolInHTTPFamily && hierarchical && pathEnd == pathStart) + // Do this only for URL with protocol http or https. + if (m_protocolInHTTPFamily && pathEnd == pathStart) *p++ = '/'; // add path, escaping bad characters - if (!hierarchical || !hasSlashDotOrDotDot(url)) + if (!hierarchical) + escapeAndAppendNonHierarchicalPart(p, url + pathStart, pathEnd - pathStart); + else if (!hasSlashDotOrDotDot(url)) appendEscapingBadChars(p, url + pathStart, pathEnd - pathStart); else { CharBuffer pathBuffer(pathEnd - pathStart + 1); @@ -1425,7 +1448,7 @@ void KURL::parse(const char* url, const String* originalString) // add fragment, escaping bad characters if (fragmentEnd != queryEnd) { *p++ = '#'; - escapeAndAppendFragment(p, url + fragmentStart, fragmentEnd - fragmentStart); + escapeAndAppendNonHierarchicalPart(p, url + fragmentStart, fragmentEnd - fragmentStart); } m_fragmentEnd = p - buffer.data(); diff --git a/Source/WebCore/platform/KURL.h b/Source/WebCore/platform/KURL.h index db2dd42..192c10b 100644 --- a/Source/WebCore/platform/KURL.h +++ b/Source/WebCore/platform/KURL.h @@ -152,7 +152,9 @@ public: String baseAsString() const; - String prettyURL() const; + // This function is only used by location.href. It's likely we shouldn't + // use it for that purpose, but more study is necessary before we remove it. + String deprecatedString() const; String fileSystemPath() const; // Returns true if the current URL's protocol is the same as the null- diff --git a/Source/WebCore/platform/KURLGoogle.cpp b/Source/WebCore/platform/KURLGoogle.cpp index 0d11b99..54bcf16 100644 --- a/Source/WebCore/platform/KURLGoogle.cpp +++ b/Source/WebCore/platform/KURLGoogle.cpp @@ -593,7 +593,6 @@ String KURL::query() const String KURL::path() const { - // Note: KURL.cpp unescapes here. return m_url.componentString(m_url.m_parsed.path); } @@ -670,16 +669,12 @@ void KURL::setPort(unsigned short i) { KURLGooglePrivate::Replacements replacements; String portStr; - if (i) { - portStr = String::number(i); - replacements.SetPort( - reinterpret_cast<const url_parse::UTF16Char*>(portStr.characters()), - url_parse::Component(0, portStr.length())); - } else { - // Clear any existing port when it is set to 0. - replacements.ClearPort(); - } + portStr = String::number(i); + replacements.SetPort( + reinterpret_cast<const url_parse::UTF16Char*>(portStr.characters()), + url_parse::Component(0, portStr.length())); + m_url.replaceComponents(replacements); } @@ -772,7 +767,7 @@ void KURL::setPath(const String& path) // On Mac, this just seems to return the same URL, but with "/foo/bar" for // file: URLs instead of file:///foo/bar. We don't bother with any of this, // at least for now. -String KURL::prettyURL() const +String KURL::deprecatedString() const { if (!m_url.m_isValid) return String(); diff --git a/Source/WebCore/platform/PlatformTouchEvent.h b/Source/WebCore/platform/PlatformTouchEvent.h index 2ca7c99..f7524b4 100644 --- a/Source/WebCore/platform/PlatformTouchEvent.h +++ b/Source/WebCore/platform/PlatformTouchEvent.h @@ -52,10 +52,6 @@ enum TouchEventType { , TouchMove , TouchEnd , TouchCancel -#if PLATFORM(ANDROID) - , TouchLongPress - , TouchDoubleTap -#endif }; class PlatformTouchEvent { diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.cpp b/Source/WebCore/platform/android/RenderThemeAndroid.cpp index ee406c2..173cfea 100644 --- a/Source/WebCore/platform/android/RenderThemeAndroid.cpp +++ b/Source/WebCore/platform/android/RenderThemeAndroid.cpp @@ -88,7 +88,7 @@ const float scaleFactor[RenderSkinAndroid::ResolutionCount] = { static SkCanvas* getCanvasFromInfo(const PaintInfo& info) { - return info.context->platformContext()->mCanvas; + return info.context->platformContext()->getCanvas(); } static android::WebFrame* getWebFrame(const Node* node) @@ -341,6 +341,8 @@ bool RenderThemeAndroid::paintMediaFullscreenButton(RenderObject* o, const Paint bool translucent = false; if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) translucent = true; + if (!getCanvasFromInfo(paintInfo)) + return true; RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::FULLSCREEN, translucent); return false; } @@ -350,6 +352,8 @@ bool RenderThemeAndroid::paintMediaMuteButton(RenderObject* o, const PaintInfo& bool translucent = false; if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) translucent = true; + if (!getCanvasFromInfo(paintInfo)) + return true; RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::MUTE, translucent); return false; } @@ -360,6 +364,8 @@ bool RenderThemeAndroid::paintMediaPlayButton(RenderObject* o, const PaintInfo& if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) translucent = true; if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(o->node())) { + if (!getCanvasFromInfo(paintInfo)) + return true; if (btn->displayType() == MediaPlayButton) RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::PLAY, translucent); else @@ -374,6 +380,8 @@ bool RenderThemeAndroid::paintMediaSeekBackButton(RenderObject* o, const PaintIn bool translucent = false; if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) translucent = true; + if (!getCanvasFromInfo(paintInfo)) + return true; RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::REWIND, translucent); return false; } @@ -383,6 +391,8 @@ bool RenderThemeAndroid::paintMediaSeekForwardButton(RenderObject* o, const Pain bool translucent = false; if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) translucent = true; + if (!getCanvasFromInfo(paintInfo)) + return true; RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::FORWARD, translucent); return false; } @@ -392,6 +402,8 @@ bool RenderThemeAndroid::paintMediaControlsBackground(RenderObject* o, const Pai bool translucent = false; if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) translucent = true; + if (!getCanvasFromInfo(paintInfo)) + return true; RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::BACKGROUND_SLIDER, translucent, 0, false); @@ -403,6 +415,8 @@ bool RenderThemeAndroid::paintMediaSliderTrack(RenderObject* o, const PaintInfo& bool translucent = false; if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) translucent = true; + if (!getCanvasFromInfo(paintInfo)) + return true; RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::SLIDER_TRACK, translucent, o); return false; @@ -413,6 +427,8 @@ bool RenderThemeAndroid::paintMediaSliderThumb(RenderObject* o, const PaintInfo& bool translucent = false; if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag)) translucent = true; + if (!getCanvasFromInfo(paintInfo)) + return true; RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::SLIDER_THUMB, translucent, 0, false); diff --git a/Source/WebCore/platform/graphics/Font.h b/Source/WebCore/platform/graphics/Font.h index beafdc7..664c3af 100644 --- a/Source/WebCore/platform/graphics/Font.h +++ b/Source/WebCore/platform/graphics/Font.h @@ -171,7 +171,13 @@ private: float getGlyphsAndAdvancesForSimpleText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const; void drawSimpleText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const; void drawEmphasisMarksForSimpleText(GraphicsContext*, const TextRun&, const AtomicString& mark, const FloatPoint&, int from, int to) const; +#if PLATFORM(ANDROID) +public: +#endif void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const; +#if PLATFORM(ANDROID) +private: +#endif void drawGlyphBuffer(GraphicsContext*, const GlyphBuffer&, const FloatPoint&) const; void drawEmphasisMarks(GraphicsContext* context, const GlyphBuffer&, const AtomicString&, const FloatPoint&) const; float floatWidthForSimpleText(const TextRun&, GlyphBuffer*, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; diff --git a/Source/WebCore/platform/graphics/FontPlatformData.h b/Source/WebCore/platform/graphics/FontPlatformData.h index a32215d..36ccbb0 100644 --- a/Source/WebCore/platform/graphics/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/FontPlatformData.h @@ -36,7 +36,7 @@ #elif (PLATFORM(EFL) || PLATFORM(GTK)) && USE(PANGO) #include "pango/FontPlatformData.h" #elif PLATFORM(ANDROID) -#include "android/FontPlatformData.h" +#include "android/fonts/FontPlatformData.h" #else #ifndef FontPlatformData_h diff --git a/Source/WebCore/platform/graphics/Gradient.cpp b/Source/WebCore/platform/graphics/Gradient.cpp index 7541646..7e3984f 100644 --- a/Source/WebCore/platform/graphics/Gradient.cpp +++ b/Source/WebCore/platform/graphics/Gradient.cpp @@ -221,7 +221,7 @@ void Gradient::setGradientSpaceTransform(const AffineTransform& gradientSpaceTra setPlatformGradientSpaceTransform(gradientSpaceTransformation); } -#if !(USE(SKIA) && !PLATFORM(ANDROID)) && !USE(CAIRO) +#if !USE(SKIA) && !USE(CAIRO) void Gradient::setPlatformGradientSpaceTransform(const AffineTransform&) { } diff --git a/Source/WebCore/platform/graphics/Gradient.h b/Source/WebCore/platform/graphics/Gradient.h index 7595896..ec22efe 100644 --- a/Source/WebCore/platform/graphics/Gradient.h +++ b/Source/WebCore/platform/graphics/Gradient.h @@ -58,14 +58,9 @@ typedef QGradient* PlatformGradient; typedef struct _cairo_pattern cairo_pattern_t; typedef cairo_pattern_t* PlatformGradient; #elif USE(SKIA) -#if PLATFORM(ANDROID) -#include "SkShader.h" -typedef class PlatformGradientRec* PlatformGradient; -#else class SkShader; typedef class SkShader* PlatformGradient; typedef class SkShader* PlatformPattern; -#endif #elif PLATFORM(HAIKU) class BGradient; typedef BGradient* PlatformGradient; @@ -116,9 +111,6 @@ namespace WebCore { #if OS(WINCE) && !PLATFORM(QT) const Vector<ColorStop, 2>& getStops() const; #else -#if PLATFORM(ANDROID) - SkShader* getShader(SkShader::TileMode); -#endif PlatformGradient platformGradient(); #endif diff --git a/Source/WebCore/platform/graphics/GraphicsContext.cpp b/Source/WebCore/platform/graphics/GraphicsContext.cpp index e032714..d8ea160 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext.cpp +++ b/Source/WebCore/platform/graphics/GraphicsContext.cpp @@ -662,7 +662,7 @@ CompositeOperator GraphicsContext::compositeOperation() const return m_state.compositeOperator; } -#if !(USE(SKIA) && !PLATFORM(ANDROID)) +#if !USE(SKIA) void GraphicsContext::setPlatformFillGradient(Gradient*) { } @@ -688,7 +688,7 @@ void GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags mode) } #endif -#if !PLATFORM(QT) && !USE(CAIRO) && !(USE(SKIA) && !PLATFORM(ANDROID)) && !PLATFORM(HAIKU) && !PLATFORM(OPENVG) +#if !PLATFORM(QT) && !USE(CAIRO) && !USE(SKIA) && !PLATFORM(OPENVG) void GraphicsContext::setPlatformStrokeStyle(StrokeStyle) { } diff --git a/Source/WebCore/platform/graphics/GraphicsContext.h b/Source/WebCore/platform/graphics/GraphicsContext.h index ed43cf0..5c60e98 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext.h +++ b/Source/WebCore/platform/graphics/GraphicsContext.h @@ -287,8 +287,6 @@ namespace WebCore { #endif #if PLATFORM(ANDROID) - // initialize a paint for bitmaps - void setupBitmapPaint(SkPaint*); // initialize a paint for filling void setupFillPaint(SkPaint*); // initialize a paint for stroking @@ -301,10 +299,6 @@ namespace WebCore { // returns true if there is a valid (non-transparent) stroke color bool willStroke() const; - // may return NULL, since we lazily allocate the path. This is the path - // that is drawn by drawPath() - const SkPath* getCurrPath() const; - /** platform-specific factory method to return a bitmap graphicscontext, called by <canvas> when we need to draw offscreen. Caller is responsible for deleting the context. Use drawOffscreenContext() to draw the context's image diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp deleted file mode 100644 index 7e0a719..0000000 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "BaseLayerAndroid" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "BaseLayerAndroid.h" - -#include "AndroidLog.h" -#include "ClassTracker.h" -#include "GLUtils.h" -#include "LayerGroup.h" -#include "ShaderProgram.h" -#include "SkCanvas.h" -#include "TilesManager.h" -#include <GLES2/gl2.h> - -// TODO: dynamically determine based on DPI -#define PREFETCH_SCALE_MODIFIER 0.3 -#define PREFETCH_OPACITY 1 -#define PREFETCH_X_DIST 0 -#define PREFETCH_Y_DIST 1 - -namespace WebCore { - -using namespace android; - -BaseLayerAndroid::BaseLayerAndroid() -#if USE(ACCELERATED_COMPOSITING) - : m_color(Color::white) - , m_content(0) - , m_scrollState(NotScrolling) -#endif -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("BaseLayerAndroid"); -#endif -} - -BaseLayerAndroid::~BaseLayerAndroid() -{ - SkSafeUnref(m_content); -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("BaseLayerAndroid"); -#endif -} - -void BaseLayerAndroid::setContent(LayerContent* content) -{ - SkSafeRef(content); - SkSafeUnref(m_content); - m_content = content; - // FIXME: We cannot set the size of the base layer because it will screw up - // the matrix used. We need to fix matrix computation for the base layer - // and then we can set the size. - // setSize(src.width(), src.height()); -} - -bool BaseLayerAndroid::drawCanvas(SkCanvas* canvas) -{ - android::Mutex::Autolock lock(m_drawLock); - if (m_content && !m_content->isEmpty()) - m_content->draw(canvas); - return true; -} - -#if USE(ACCELERATED_COMPOSITING) - -void BaseLayerAndroid::prefetchBasePicture(const SkRect& viewport, float currentScale, - TiledPage* prefetchTiledPage, bool draw) -{ - SkIRect bounds; - float prefetchScale = currentScale * PREFETCH_SCALE_MODIFIER; - - float invTileWidth = (prefetchScale) - / TilesManager::instance()->tileWidth(); - float invTileHeight = (prefetchScale) - / TilesManager::instance()->tileHeight(); - bool goingDown = m_state->goingDown(); - bool goingLeft = m_state->goingLeft(); - - - ALOGV("fetch rect %f %f %f %f, scale %f", - viewport.fLeft, - viewport.fTop, - viewport.fRight, - viewport.fBottom, - currentScale); - - bounds.fLeft = static_cast<int>(floorf(viewport.fLeft * invTileWidth)) - PREFETCH_X_DIST; - bounds.fTop = static_cast<int>(floorf(viewport.fTop * invTileHeight)) - PREFETCH_Y_DIST; - bounds.fRight = static_cast<int>(ceilf(viewport.fRight * invTileWidth)) + PREFETCH_X_DIST; - bounds.fBottom = static_cast<int>(ceilf(viewport.fBottom * invTileHeight)) + PREFETCH_Y_DIST; - - ALOGV("prefetch rect %d %d %d %d, scale %f, preparing page %p", - bounds.fLeft, bounds.fTop, - bounds.fRight, bounds.fBottom, - prefetchScale, - prefetchTiledPage); - - prefetchTiledPage->setScale(prefetchScale); - prefetchTiledPage->updateTileDirtiness(); - prefetchTiledPage->prepare(goingDown, goingLeft, bounds, - TiledPage::ExpandedBounds); - prefetchTiledPage->swapBuffersIfReady(bounds, - prefetchScale); - if (draw) - prefetchTiledPage->prepareForDrawGL(PREFETCH_OPACITY, bounds); -} - -bool BaseLayerAndroid::isReady() -{ - ZoomManager* zoomManager = m_state->zoomManager(); - if (ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState()) { - ALOGV("base layer not ready, still zooming"); - return false; // still zooming - } - - if (!m_state->frontPage()->isReady(m_state->preZoomBounds())) { - ALOGV("base layer not ready, front page not done painting"); - return false; - } - - return true; -} - -void BaseLayerAndroid::swapTiles() -{ - m_state->frontPage()->swapBuffersIfReady(m_state->preZoomBounds(), - m_state->zoomManager()->currentScale()); - - m_state->backPage()->swapBuffersIfReady(m_state->preZoomBounds(), - m_state->zoomManager()->currentScale()); -} - -void BaseLayerAndroid::setIsPainting() -{ - ALOGV("BLA %p setIsPainting, dirty %d", this, isDirty()); - m_state->invalRegion(m_dirtyRegion); - m_dirtyRegion.setEmpty(); -} - -void BaseLayerAndroid::mergeInvalsInto(BaseLayerAndroid* replacementLayer) -{ - replacementLayer->markAsDirty(m_dirtyRegion); -} - -void BaseLayerAndroid::prepareGL(const SkRect& viewport, float scale, double currentTime) -{ - ALOGV("prepareGL BLA %p, m_state %p", this, m_state); - - ZoomManager* zoomManager = m_state->zoomManager(); - - bool goingDown = m_state->goingDown(); - bool goingLeft = m_state->goingLeft(); - - const SkIRect& viewportTileBounds = m_state->viewportTileBounds(); - ALOGV("drawBasePicture, TX: %d, TY: %d scale %.2f", viewportTileBounds.fLeft, - viewportTileBounds.fTop, scale); - - // Query the resulting state from the zoom manager - bool prepareNextTiledPage = zoomManager->needPrepareNextTiledPage(); - - // Display the current page - TiledPage* tiledPage = m_state->frontPage(); - TiledPage* nextTiledPage = m_state->backPage(); - tiledPage->setScale(zoomManager->currentScale()); - - // Let's prepare the page if needed so that it will start painting - if (prepareNextTiledPage) { - nextTiledPage->setScale(scale); - m_state->setFutureViewport(viewportTileBounds); - - nextTiledPage->updateTileDirtiness(); - - nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds, - TiledPage::VisibleBounds); - // Cancel pending paints for the foreground page - TilesManager::instance()->removePaintOperationsForPage(tiledPage, false); - } - - // If we fired a request, let's check if it's ready to use - if (zoomManager->didFireRequest()) { - if (nextTiledPage->swapBuffersIfReady(viewportTileBounds, - zoomManager->futureScale())) - zoomManager->setReceivedRequest(); // transition to received request state - } - - float transparency = 1; - bool doZoomPageSwap = false; - - // If the page is ready, display it. We do a short transition between - // the two pages (current one and future one with the new scale factor) - if (zoomManager->didReceivedRequest()) { - float nextTiledPageTransparency = 1; - m_state->resetFrameworkInval(); - zoomManager->processTransition(currentTime, scale, &doZoomPageSwap, - &nextTiledPageTransparency, &transparency); - nextTiledPage->prepareForDrawGL(nextTiledPageTransparency, viewportTileBounds); - } - - const SkIRect& preZoomBounds = m_state->preZoomBounds(); - - bool zooming = ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState(); - - if (doZoomPageSwap) { - zoomManager->setCurrentScale(scale); - m_state->swapPages(); - } - - tiledPage->updateTileDirtiness(); - - // paint what's needed unless we're zooming, since the new tiles won't - // be relevant soon anyway - if (!zooming) - tiledPage->prepare(goingDown, goingLeft, preZoomBounds, - TiledPage::ExpandedBounds); - - ALOGV("scrollState %d, zooming %d", m_scrollState, zooming); - - // prefetch in the nextTiledPage if unused by zooming (even if not scrolling - // since we want the tiles to be ready before they're needed) - bool usePrefetchPage = !zooming; - nextTiledPage->setIsPrefetchPage(usePrefetchPage); - if (usePrefetchPage) { - // if the non-prefetch page isn't missing tiles, don't bother drawing - // prefetch page - bool drawPrefetchPage = tiledPage->hasMissingContent(preZoomBounds); - prefetchBasePicture(viewport, scale, nextTiledPage, drawPrefetchPage); - } - - tiledPage->prepareForDrawGL(transparency, preZoomBounds); -} - -void BaseLayerAndroid::drawBasePictureInGL() -{ - m_state->backPage()->drawGL(); - m_state->frontPage()->drawGL(); -} - -void BaseLayerAndroid::updateLayerPositions(const SkRect& visibleRect) -{ - LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0)); - if (!compositedRoot) - return; - TransformationMatrix ident; - compositedRoot->updateLayerPositions(visibleRect); - FloatRect clip(0, 0, content()->width(), content()->height()); - - // Note that this function may be called (and should still work) with no m_state in SW mode - // TODO: is this the best thing to do in software rendering - float scale = m_state ? m_state->scale() : 1.0f; - compositedRoot->updateGLPositionsAndScale(ident, clip, 1, scale); - -#ifdef DEBUG - compositedRoot->showLayer(0); - ALOGV("We have %d layers, %d textured", - compositedRoot->nbLayers(), - compositedRoot->nbTexturedLayers()); -#endif -} - -#endif // USE(ACCELERATED_COMPOSITING) - -void BaseLayerAndroid::drawGL(float scale) -{ - ALOGV("drawGL BLA %p", this); - - // TODO: consider moving drawBackground outside of prepare (into tree manager) - m_state->drawBackground(m_color); - drawBasePictureInGL(); - m_state->glExtras()->drawGL(0); -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h deleted file mode 100644 index 5560f58..0000000 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef BaseLayerAndroid_h -#define BaseLayerAndroid_h - -#include <utils/threads.h> - -#include "Color.h" -#include "Layer.h" -#include "PictureSet.h" -#include "LayerContent.h" - -namespace WebCore { - -class TiledPage; - -class BaseLayerAndroid : public Layer { - -public: - enum ScrollState { - NotScrolling = 0, - Scrolling = 1, - ScrollingFinishPaint = 2 - }; - - BaseLayerAndroid(); - virtual ~BaseLayerAndroid(); - -#if USE(ACCELERATED_COMPOSITING) - void setBackgroundColor(Color& color) { m_color = color; } - Color getBackgroundColor() { return m_color; } -#endif - void setContent(LayerContent* content); - LayerContent* content() { return m_content; } - - // This method will paint using the current PictureSet onto - // the passed canvas. We used it to paint the GL tiles as well as - // WebView::copyBaseContentToPicture(), so a lock is necessary as - // we are running in different threads. - virtual bool drawCanvas(SkCanvas* canvas); - - void updateLayerPositions(const SkRect& visibleRect); - void prepareGL(const SkRect& visibleRect, float scale, double currentTime); - void drawGL(float scale); - - // rendering asset management - void swapTiles(); - void setIsDrawing(bool isDrawing); - void setIsPainting(); - void mergeInvalsInto(BaseLayerAndroid* replacementLayer); - bool isReady(); - -private: -#if USE(ACCELERATED_COMPOSITING) - void prefetchBasePicture(const SkRect& viewport, float currentScale, - TiledPage* prefetchTiledPage, bool draw); - void drawBasePictureInGL(); - - android::Mutex m_drawLock; - Color m_color; -#endif - LayerContent* m_content; - - ScrollState m_scrollState; -}; - -} // namespace WebCore - -#endif // BaseLayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index 663addb..8581a8e 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -37,19 +37,16 @@ #include "GLUtils.h" #include "ImagesManager.h" #include "LayerAndroid.h" +#include "private/hwui/DrawGlInfo.h" #include "ScrollableLayerAndroid.h" #include "SkPath.h" #include "TilesManager.h" +#include "TransferQueue.h" #include "SurfaceCollection.h" #include "SurfaceCollectionManager.h" #include <pthread.h> #include <wtf/CurrentTime.h> -#define FIRST_TILED_PAGE_ID 1 -#define SECOND_TILED_PAGE_ID 2 - -#define FRAMERATE_CAP 0.01666 // We cap at 60 fps - // log warnings if scale goes outside this range #define MIN_SCALE_WARNING 0.1 #define MAX_SCALE_WARNING 10 @@ -66,27 +63,16 @@ namespace WebCore { using namespace android; GLWebViewState::GLWebViewState() - : m_zoomManager(this) - , m_usePageA(true) - , m_frameworkInval(0, 0, 0, 0) - , m_frameworkLayersInval(0, 0, 0, 0) + : m_frameworkLayersInval(0, 0, 0, 0) , m_isScrolling(false) , m_isViewportScrolling(false) , m_goingDown(true) , m_goingLeft(false) - , m_expandedTileBoundsX(0) - , m_expandedTileBoundsY(0) , m_scale(1) , m_layersRenderingMode(kAllTextures) - , m_surfaceCollectionManager(this) + , m_surfaceCollectionManager() { m_viewport.setEmpty(); - m_futureViewportTileBounds.setEmpty(); - m_viewportTileBounds.setEmpty(); - m_preZoomBounds.setEmpty(); - - m_tiledPageA = new TiledPage(FIRST_TILED_PAGE_ID, this); - m_tiledPageB = new TiledPage(SECOND_TILED_PAGE_ID, this); #ifdef DEBUG_COUNT ClassTracker::instance()->increment("GLWebViewState"); @@ -100,14 +86,6 @@ GLWebViewState::GLWebViewState() GLWebViewState::~GLWebViewState() { - // We have to destroy the two tiled pages first as their destructor - // may depend on the existence of this GLWebViewState and some of its - // instance variables in order to complete. - // Explicitely, currently we need to have the m_paintingBaseLayer around - // in order to complete any pending paint operations (the tiled pages - // will remove any pending operations, and wait if one is underway). - delete m_tiledPageA; - delete m_tiledPageB; #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("GLWebViewState"); #endif @@ -117,19 +95,17 @@ GLWebViewState::~GLWebViewState() bool GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, bool showVisualIndicator, bool isPictureAfterFirstLayout) { - if (!layer || isPictureAfterFirstLayout) { - // TODO: move this into SurfaceCollectionManager - m_zoomManager.swapPages(); // reset zoom state - m_tiledPageA->discardTextures(); - m_tiledPageB->discardTextures(); + if (!layer || isPictureAfterFirstLayout) m_layersRenderingMode = kAllTextures; - } + + SurfaceCollection* collection = 0; if (layer) { - ALOGV("new base layer %p, with child %p", layer, layer->getChild(0)); + ALOGV("layer tree %p, with child %p", layer, layer->getChild(0)); layer->setState(this); + collection = new SurfaceCollection(layer); } bool queueFull = m_surfaceCollectionManager.updateWithSurfaceCollection( - new SurfaceCollection(layer), isPictureAfterFirstLayout); + collection, isPictureAfterFirstLayout); m_glExtras.setDrawExtra(0); #ifdef MEASURES_PERF @@ -145,85 +121,6 @@ bool GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, bool showVisualIndica void GLWebViewState::scrollLayer(int layerId, int x, int y) { m_surfaceCollectionManager.updateScrollableLayer(layerId, x, y); - - // TODO: only inval the area of the scrolled layer instead of - // doing a fullInval() - if (m_layersRenderingMode == kSingleSurfaceRendering) - fullInval(); -} - -void GLWebViewState::invalRegion(const SkRegion& region) -{ - if (m_layersRenderingMode == kSingleSurfaceRendering) { - // TODO: do the union of both layer trees to compute - // the minimum inval instead of doing a fullInval() - fullInval(); - return; - } - SkRegion::Iterator iterator(region); - while (!iterator.done()) { - SkIRect r = iterator.rect(); - IntRect ir(r.fLeft, r.fTop, r.width(), r.height()); - inval(ir); - iterator.next(); - } -} - -void GLWebViewState::inval(const IntRect& rect) -{ - if (!rect.isEmpty()) { - // find which tiles fall within the invalRect and mark them as dirty - m_tiledPageA->invalidateRect(rect); - m_tiledPageB->invalidateRect(rect); - if (m_frameworkInval.isEmpty()) - m_frameworkInval = rect; - else - m_frameworkInval.unite(rect); - ALOGV("intermediate invalRect(%d, %d, %d, %d) after unite with rect %d %d %d %d", m_frameworkInval.x(), - m_frameworkInval.y(), m_frameworkInval.width(), m_frameworkInval.height(), - rect.x(), rect.y(), rect.width(), rect.height()); - } - TilesManager::instance()->getProfiler()->nextInval(rect, zoomManager()->currentScale()); -} - -void GLWebViewState::paintBaseLayerContent(SkCanvas* canvas) -{ - m_surfaceCollectionManager.drawCanvas(canvas, m_layersRenderingMode == kSingleSurfaceRendering); -} - -TiledPage* GLWebViewState::sibling(TiledPage* page) -{ - return (page == m_tiledPageA) ? m_tiledPageB : m_tiledPageA; -} - -TiledPage* GLWebViewState::frontPage() -{ - android::Mutex::Autolock lock(m_tiledPageLock); - return m_usePageA ? m_tiledPageA : m_tiledPageB; -} - -TiledPage* GLWebViewState::backPage() -{ - android::Mutex::Autolock lock(m_tiledPageLock); - return m_usePageA ? m_tiledPageB : m_tiledPageA; -} - -void GLWebViewState::swapPages() -{ - android::Mutex::Autolock lock(m_tiledPageLock); - m_usePageA ^= true; - TiledPage* oldPage = m_usePageA ? m_tiledPageB : m_tiledPageA; - zoomManager()->swapPages(); - oldPage->discardTextures(); -} - -int GLWebViewState::baseContentWidth() -{ - return m_surfaceCollectionManager.baseContentWidth(); -} -int GLWebViewState::baseContentHeight() -{ - return m_surfaceCollectionManager.baseContentHeight(); } void GLWebViewState::setViewport(const SkRect& viewport, float scale) @@ -235,20 +132,19 @@ void GLWebViewState::setViewport(const SkRect& viewport, float scale) int viewMaxTileX = static_cast<int>(ceilf((viewport.width()-1) * invTileContentWidth)) + 1; int viewMaxTileY = static_cast<int>(ceilf((viewport.height()-1) * invTileContentHeight)) + 1; - TilesManager* manager = TilesManager::instance(); - int maxTextureCount = (viewMaxTileX + m_expandedTileBoundsX * 2) * - (viewMaxTileY + m_expandedTileBoundsY * 2) * (manager->highEndGfx() ? 4 : 2); + TilesManager* tilesManager = TilesManager::instance(); + int maxTextureCount = viewMaxTileX * viewMaxTileY * (tilesManager->highEndGfx() ? 4 : 2); - manager->setMaxTextureCount(maxTextureCount); - m_tiledPageA->updateBaseTileSize(); - m_tiledPageB->updateBaseTileSize(); + tilesManager->setMaxTextureCount(maxTextureCount); + // TODO: investigate whether we can move this return earlier. if ((m_viewport == viewport) - && (zoomManager()->futureScale() == scale)) { + && (m_scale == scale)) { // everything below will stay the same, early return. m_isViewportScrolling = false; return; } + m_scale = scale; m_goingDown = m_viewport.fTop - viewport.fTop <= 0; m_goingLeft = m_viewport.fLeft - viewport.fLeft >= 0; @@ -257,16 +153,9 @@ void GLWebViewState::setViewport(const SkRect& viewport, float scale) m_isViewportScrolling = m_viewport != viewport && SkRect::Intersects(m_viewport, viewport); m_viewport = viewport; - ALOGV("New VIEWPORT %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f currentScale: %.2f futureScale: %.2f)", + ALOGV("New VIEWPORT %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f )", m_viewport.fLeft, m_viewport.fTop, m_viewport.fRight, m_viewport.fBottom, - m_viewport.width(), m_viewport.height(), scale, - zoomManager()->currentScale(), zoomManager()->futureScale()); - - m_viewportTileBounds.set( - static_cast<int>(floorf(viewport.fLeft * invTileContentWidth)), - static_cast<int>(floorf(viewport.fTop * invTileContentHeight)), - static_cast<int>(ceilf(viewport.fRight * invTileContentWidth)), - static_cast<int>(ceilf(viewport.fBottom * invTileContentHeight))); + m_viewport.width(), m_viewport.height(), scale); } #ifdef MEASURES_PERF @@ -282,14 +171,6 @@ void GLWebViewState::dumpMeasures() } #endif // MEASURES_PERF -void GLWebViewState::resetFrameworkInval() -{ - m_frameworkInval.setX(0); - m_frameworkInval.setY(0); - m_frameworkInval.setWidth(0); - m_frameworkInval.setHeight(0); -} - void GLWebViewState::addDirtyArea(const IntRect& rect) { if (rect.isEmpty()) @@ -311,29 +192,10 @@ void GLWebViewState::resetLayersDirtyArea() m_frameworkLayersInval.setHeight(0); } -void GLWebViewState::drawBackground(Color& backgroundColor) -{ - if (TilesManager::instance()->invertedScreen()) { - float color = 1.0 - ((((float) backgroundColor.red() / 255.0) + - ((float) backgroundColor.green() / 255.0) + - ((float) backgroundColor.blue() / 255.0)) / 3.0); - glClearColor(color, color, color, 1); - } else { - glClearColor((float)backgroundColor.red() / 255.0, - (float)backgroundColor.green() / 255.0, - (float)backgroundColor.blue() / 255.0, 1); - } - glClear(GL_COLOR_BUFFER_BIT); -} - double GLWebViewState::setupDrawing(const IntRect& viewRect, const SkRect& visibleRect, const IntRect& webViewRect, int titleBarHeight, const IntRect& screenClip, float scale) { - int left = viewRect.x(); - int top = viewRect.y(); - int width = viewRect.width(); - int height = viewRect.height(); TilesManager* tilesManager = TilesManager::instance(); // Make sure GL resources are created on the UI thread. @@ -350,20 +212,12 @@ double GLWebViewState::setupDrawing(const IntRect& viewRect, const SkRect& visib transferQueue->initGLResources(TilesManager::tileWidth(), TilesManager::tileHeight()); } - // TODO: Add the video GL resource re-initialization code here. - shader->setupDrawing(viewRect, visibleRect, webViewRect, titleBarHeight, screenClip, scale); - shader->calculateAnimationDelta(); - - glViewport(left + shader->getAnimationDeltaX(), - top - shader->getAnimationDeltaY(), - width, height); double currentTime = WTF::currentTime(); setViewport(visibleRect, scale); - m_zoomManager.processNewScale(currentTime, scale); return currentTime; } @@ -429,67 +283,57 @@ bool GLWebViewState::setLayersRenderingMode(TexturesResult& nbTexturesNeeded) m_layersRenderingMode = kSingleSurfaceRendering; // update the base surface if needed - if (m_layersRenderingMode != layersRenderingMode - && invalBase) { - m_tiledPageA->discardTextures(); - m_tiledPageB->discardTextures(); - fullInval(); - return true; - } - return false; -} - -void GLWebViewState::fullInval() -{ - // TODO -- use base layer's size. - IntRect ir(0, 0, 1E6, 1E6); - inval(ir); + // TODO: inval base layergroup when going into single surface mode + return (m_layersRenderingMode != layersRenderingMode && invalBase); } -bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, - IntRect& webViewRect, int titleBarHeight, - IntRect& clip, float scale, - bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr) +// -rect(viewRect) is the webViewRect with inverted Y, in screen coordinate. +// -viewport(visibleRect) is the visible area in document coordinate. +// They are both based on webViewRect and calculated in Java side. +// +// -clip is the final glViewport value in screen coordinate, and it contains the +// animation translation/scale and FBO offset. +// +// TODO: Try to decrease the number of parameters as some info is redundant. +int GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, + IntRect& webViewRect, int titleBarHeight, + IntRect& clip, float scale, + bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr, + bool shouldDraw) { TilesManager* tilesManager = TilesManager::instance(); - m_scale = scale; - tilesManager->getProfiler()->nextFrame(viewport.fLeft, viewport.fTop, - viewport.fRight, viewport.fBottom, - scale); + if (shouldDraw) + tilesManager->getProfiler()->nextFrame(viewport.fLeft, viewport.fTop, + viewport.fRight, viewport.fBottom, + scale); tilesManager->incDrawGLCount(); - float viewWidth = (viewport.fRight - viewport.fLeft) * TILE_PREFETCH_RATIO; - float viewHeight = (viewport.fBottom - viewport.fTop) * TILE_PREFETCH_RATIO; - bool noPrefetch = tilesManager->useMinimalMemory() || !tilesManager->highEndGfx(); - bool useHorzPrefetch = noPrefetch ? 0 : viewWidth < baseContentWidth(); - bool useVertPrefetch = noPrefetch ? 0 : viewHeight < baseContentHeight(); - m_expandedTileBoundsX = (useHorzPrefetch) ? TILE_PREFETCH_DISTANCE : 0; - m_expandedTileBoundsY = (useVertPrefetch) ? TILE_PREFETCH_DISTANCE : 0; - - ALOGV("drawGL, rect(%d, %d, %d, %d), viewport(%.2f, %.2f, %.2f, %.2f)", + ALOGV("drawGL, rect/viewRect(%d, %d, %d, %d), viewport/visibleRect(%.2f, %.2f, %.2f, %.2f)", rect.x(), rect.y(), rect.width(), rect.height(), viewport.fLeft, viewport.fTop, viewport.fRight, viewport.fBottom); ALOGV("drawGL, invalRect(%d, %d, %d, %d), webViewRect(%d, %d, %d, %d)" - "clip (%d, %d, %d, %d), scale %f", + "clip/glViewport (%d, %d, %d, %d), scale %f titleBarHeight %d", invalRect->x(), invalRect->y(), invalRect->width(), invalRect->height(), webViewRect.x(), webViewRect.y(), webViewRect.width(), webViewRect.height(), - clip.x(), clip.y(), clip.width(), clip.height(), scale); + clip.x(), clip.y(), clip.width(), clip.height(), scale, titleBarHeight); resetLayersDirtyArea(); if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING) ALOGW("WARNING, scale seems corrupted before update: %e", scale); - // Here before we draw, update the BaseTile which has updated content. + // Here before we draw, update the Tile which has updated content. // Inside this function, just do GPU blits from the transfer queue into - // the BaseTiles' texture. - tilesManager->transferQueue()->updateDirtyBaseTiles(); + // the Tiles' texture. + tilesManager->transferQueue()->updateDirtyTiles(); // Upload any pending ImageTexture // Return true if we still have some images to upload. // TODO: upload as many textures as possible within a certain time limit - bool ret = ImagesManager::instance()->prepareTextures(this); + int returnFlags = 0; + if (ImagesManager::instance()->prepareTextures(this)) + returnFlags |= uirenderer::DrawGlInfo::kStatusDraw; if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING) { ALOGW("WARNING, scale seems corrupted after update: %e", scale); @@ -497,20 +341,17 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, } // gather the textures we can use - tilesManager->gatherLayerTextures(); + tilesManager->gatherTextures(); double currentTime = setupDrawing(rect, viewport, webViewRect, titleBarHeight, clip, scale); - TexturesResult nbTexturesNeeded; bool fastSwap = isScrolling() || m_layersRenderingMode == kSingleSurfaceRendering; m_glExtras.setViewport(viewport); - ret |= m_surfaceCollectionManager.drawGL(currentTime, rect, viewport, - scale, fastSwap, - collectionsSwappedPtr, newCollectionHasAnimPtr, - &nbTexturesNeeded); - if (!ret) - resetFrameworkInval(); + returnFlags |= m_surfaceCollectionManager.drawGL(currentTime, rect, viewport, + scale, fastSwap, + collectionsSwappedPtr, newCollectionHasAnimPtr, + &nbTexturesNeeded, shouldDraw); int nbTexturesForImages = ImagesManager::instance()->nbTextures(); ALOGV("*** We have %d textures for images, %d full, %d clipped, total %d / %d", @@ -519,39 +360,28 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, nbTexturesNeeded.clipped + nbTexturesForImages); nbTexturesNeeded.full += nbTexturesForImages; nbTexturesNeeded.clipped += nbTexturesForImages; - ret |= setLayersRenderingMode(nbTexturesNeeded); + + if (setLayersRenderingMode(nbTexturesNeeded)) + returnFlags |= uirenderer::DrawGlInfo::kStatusDraw | uirenderer::DrawGlInfo::kStatusInvoke; glBindBuffer(GL_ARRAY_BUFFER, 0); // Clean up GL textures for video layer. tilesManager->videoLayerManager()->deleteUnusedTextures(); - ret |= tilesManager->invertedScreenSwitch(); - if (ret) { - // ret==true && empty inval region means we've inval'd everything, + if (returnFlags & uirenderer::DrawGlInfo::kStatusDraw) { + // returnFlags & kStatusDraw && empty inval region means we've inval'd everything, // but don't have new content. Keep redrawing full view (0,0,0,0) // until tile generation catches up and we swap pages. - bool fullScreenInval = m_frameworkInval.isEmpty(); - - if (tilesManager->invertedScreenSwitch()) { - fullScreenInval = true; - tilesManager->setInvertedScreenSwitch(false); - } + bool fullScreenInval = m_frameworkLayersInval.isEmpty(); if (!fullScreenInval) { - FloatRect frameworkInval = tilesManager->shader()->rectInInvScreenCoord( - m_frameworkInval); - // Inflate the invalidate rect to avoid precision lost. - frameworkInval.inflate(1); - IntRect inval(frameworkInval.x(), frameworkInval.y(), - frameworkInval.width(), frameworkInval.height()); - - inval.unite(m_frameworkLayersInval); + m_frameworkLayersInval.inflate(1); - invalRect->setX(inval.x()); - invalRect->setY(inval.y()); - invalRect->setWidth(inval.width()); - invalRect->setHeight(inval.height()); + invalRect->setX(m_frameworkLayersInval.x()); + invalRect->setY(m_frameworkLayersInval.y()); + invalRect->setWidth(m_frameworkLayersInval.width()); + invalRect->setHeight(m_frameworkLayersInval.height()); ALOGV("invalRect(%d, %d, %d, %d)", inval.x(), inval.y(), inval.width(), inval.height()); @@ -568,13 +398,12 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, invalRect->setWidth(0); invalRect->setHeight(0); } - } else { - resetFrameworkInval(); } - showFrameInfo(rect, *collectionsSwappedPtr); + if (shouldDraw) + showFrameInfo(rect, *collectionsSwappedPtr); - return ret; + return returnFlags; } void GLWebViewState::showFrameInfo(const IntRect& rect, bool collectionsSwapped) diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h index fcdd07c..2b28619 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.h +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h @@ -35,9 +35,7 @@ #include "SkCanvas.h" #include "SkRect.h" #include "SkRegion.h" -#include "TiledPage.h" #include "SurfaceCollectionManager.h" -#include "ZoomManager.h" #include <utils/threads.h> // Performance measurements probe @@ -51,9 +49,6 @@ // HW limit or save further in the GPU memory consumption. #define TILE_PREFETCH_DISTANCE 1 -// ratio of content to view required for prefetching to enable -#define TILE_PREFETCH_RATIO 1.2 - namespace WebCore { class BaseLayerAndroid; @@ -98,7 +93,7 @@ class TexturesResult; // there is a need to be called again (i.e. if we do not have up to date // textures or a transition is going on). // -// Tiles are implemented as a BaseTile. It knows how to paint itself with the +// Tiles are implemented as a Tile. It knows how to paint itself with the // PictureSet, and to display itself. A GL texture is usually associated to it. // // We also works with two TiledPages -- one to display the page at the @@ -112,13 +107,13 @@ class TexturesResult; // Texture allocation // ------------------ // -// Obviously we cannot have every BaseTile having a GL texture -- we need to +// Obviously we cannot have every Tile having a GL texture -- we need to // get the GL textures from an existing pool, and reuse them. // // The way we do it is that when we call TiledPage::prepare(), we group the // tiles we need (i.e. in the viewport and dirty) into a TilesSet and call -// BaseTile::reserveTexture() for each tile (which ensures there is a specific -// GL textures backing the BaseTiles). +// Tile::reserveTexture() for each tile (which ensures there is a specific +// GL textures backing the Tiles). // // reserveTexture() will ask the TilesManager for a texture. The allocation // mechanism goal is to (in order): @@ -130,7 +125,7 @@ class TexturesResult; // we prepare() a TiledPage. Also during each prepare() we compute which tiles // are dirty based on the info we have received from webkit. // -// BaseTile Invalidation +// Tile Invalidation // ------------------ // // We do not want to redraw a tile if the tile is up-to-date. A tile is @@ -154,9 +149,9 @@ class TexturesResult; // // The next operation is to schedule this TilesSet to be painted // (TilesManager::schedulePaintForTilesSet()). TexturesGenerator -// will get the TilesSet and ask the BaseTiles in it to be painted. +// will get the TilesSet and ask the Tiles in it to be painted. // -// BaseTile::paintBitmap() will paint the texture using the BaseLayer's +// Tile::paintBitmap() will paint the texture using the BaseLayer's // PictureSet (calling TiledPage::paintBaseLayerContent() which in turns // calls GLWebViewState::paintBaseLayerContent()). // @@ -171,62 +166,32 @@ public: GLWebViewState(); ~GLWebViewState(); - ZoomManager* zoomManager() { return &m_zoomManager; } - const SkIRect& futureViewport() const { return m_futureViewportTileBounds; } - void setFutureViewport(const SkIRect& viewport) { m_futureViewportTileBounds = viewport; } - - void paintBaseLayerContent(SkCanvas* canvas); bool setBaseLayer(BaseLayerAndroid* layer, bool showVisualIndicator, bool isPictureAfterFirstLayout); void paintExtras(); GLExtras* glExtras() { return &m_glExtras; } - TiledPage* sibling(TiledPage* page); - TiledPage* frontPage(); - TiledPage* backPage(); - void swapPages(); - - // dimensions of the current base layer - int baseContentWidth(); - int baseContentHeight(); - - // a rect containing the coordinates of all tiles in the current viewport - const SkIRect& viewportTileBounds() const { return m_viewportTileBounds; } - // a rect containing the viewportTileBounds before there was a scale change - const SkIRect& preZoomBounds() const { return m_preZoomBounds; } - void setPreZoomBounds(const SkIRect& bounds) { m_preZoomBounds = bounds; } - void setIsScrolling(bool isScrolling) { m_isScrolling = isScrolling; } bool isScrolling() { return m_isScrolling || m_isViewportScrolling; } - void drawBackground(Color& backgroundColor); - bool setLayersRenderingMode(TexturesResult&); - void fullInval(); - bool drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, - IntRect& webViewRect, int titleBarHeight, - IntRect& clip, float scale, - bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr); + int drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, + IntRect& webViewRect, int titleBarHeight, + IntRect& clip, float scale, + bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr, + bool shouldDraw); #ifdef MEASURES_PERF void dumpMeasures(); #endif - void resetFrameworkInval(); void addDirtyArea(const IntRect& rect); void resetLayersDirtyArea(); bool goingDown() { return m_goingDown; } bool goingLeft() { return m_goingLeft; } - void setDirection(bool goingDown, bool goingLeft) { - m_goingDown = goingDown; - m_goingLeft = goingLeft; - } - - int expandedTileBoundsX() { return m_expandedTileBoundsX; } - int expandedTileBoundsY() { return m_expandedTileBoundsY; } float scale() { return m_scale; } @@ -242,10 +207,7 @@ public: LayersRenderingMode layersRenderingMode() { return m_layersRenderingMode; } void scrollLayer(int layerId, int x, int y); - void invalRegion(const SkRegion& region); - private: - void inval(const IntRect& rect); void setViewport(const SkRect& viewport, float scale); double setupDrawing(const IntRect& viewRect, const SkRect& visibleRect, const IntRect& webViewRect, int titleBarHeight, @@ -255,18 +217,7 @@ private: float b, float a); double m_prevDrawTime; - ZoomManager m_zoomManager; - android::Mutex m_tiledPageLock; SkRect m_viewport; - SkIRect m_viewportTileBounds; - SkIRect m_futureViewportTileBounds; - SkIRect m_preZoomBounds; - - bool m_usePageA; - TiledPage* m_tiledPageA; - TiledPage* m_tiledPageB; - IntRect m_lastInval; - IntRect m_frameworkInval; IntRect m_frameworkLayersInval; #ifdef MEASURES_PERF @@ -282,9 +233,6 @@ private: bool m_goingDown; bool m_goingLeft; - int m_expandedTileBoundsX; - int m_expandedTileBoundsY; - float m_scale; LayersRenderingMode m_layersRenderingMode; diff --git a/Source/WebCore/platform/graphics/android/GradientAndroid.cpp b/Source/WebCore/platform/graphics/android/GradientAndroid.cpp deleted file mode 100644 index 6007a0a..0000000 --- a/Source/WebCore/platform/graphics/android/GradientAndroid.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2006, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "Gradient.h" - -#include "android_graphics.h" -#include "CSSParser.h" -#include "GraphicsContext.h" -#include "NotImplemented.h" -#include "SkCanvas.h" -#include "SkColorShader.h" -#include "SkGradientShader.h" -#include "SkPaint.h" - -class PlatformGradientRec { -public: - PlatformGradientRec() : m_shader(NULL) {} - ~PlatformGradientRec() { SkSafeUnref(m_shader); } - - SkShader* m_shader; - SkShader::TileMode m_tileMode; - int m_colorCountWhenShaderWasBuilt; -}; - -namespace WebCore { - -void Gradient::platformDestroy() -{ - delete m_gradient; - m_gradient = 0; -} - -static U8CPU F2B(float x) -{ - return (int)(x * 255); -} - -SkShader* Gradient::getShader(SkShader::TileMode mode) -{ - if (NULL == m_gradient) - m_gradient = new PlatformGradientRec; - else if (mode == m_gradient->m_tileMode) - return m_gradient->m_shader; - - // need to ensure that the m_stops array is sorted. We call getColor() - // which, as a side effect, does the sort. - // TODO: refactor Gradient.h to formally expose a sort method - { - float r, g, b, a; - this->getColor(0, &r, &g, &b, &a); - } - - SkPoint pts[2] = { m_p0, m_p1 }; // convert to SkPoint - - const size_t count = m_stops.size(); - SkAutoMalloc storage(count * (sizeof(SkColor) + sizeof(SkScalar))); - SkColor* colors = (SkColor*)storage.get(); - SkScalar* pos = (SkScalar*)(colors + count); - - Vector<ColorStop>::iterator iter = m_stops.begin(); - for (int i = 0; iter != m_stops.end(); i++) { - pos[i] = SkFloatToScalar(iter->stop); - colors[i] = SkColorSetARGB(F2B(iter->alpha), F2B(iter->red), - F2B(iter->green), F2B(iter->blue)); - ++iter; - } - - SkShader* s; - if (m_radial) - s = SkGradientShader::CreateTwoPointRadial(pts[0], - SkFloatToScalar(m_r0), - pts[1], - SkFloatToScalar(m_r1), - colors, pos, count, mode); - else - s = SkGradientShader::CreateLinear(pts, colors, pos, count, mode); - - if (NULL == s) - s = new SkColorShader(0); - - // zap our previous shader, if present - SkSafeUnref(m_gradient->m_shader); - m_gradient->m_shader = s; - m_gradient->m_tileMode = mode; - SkMatrix matrix = m_gradientSpaceTransformation; - s->setLocalMatrix(matrix); - - return s; -} - -void Gradient::fill(GraphicsContext* context, const FloatRect& rect) -{ - SkPaint paint; - // we don't care about the mode, so try to use the existing one - SkShader::TileMode mode = m_gradient ? m_gradient->m_tileMode : - SkShader::kClamp_TileMode; - - paint.setAntiAlias(true); - paint.setShader(this->getShader(mode)); - android_gc2canvas(context)->drawRect(rect, paint); -} - - -} //namespace diff --git a/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp deleted file mode 100644 index 0aa1ae6..0000000 --- a/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp +++ /dev/null @@ -1,1295 +0,0 @@ -/* - * Copyright 2006, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "config.h" -#include "GraphicsContext.h" - -#include "AffineTransform.h" -#include "Font.h" -#include "Gradient.h" -#include "NotImplemented.h" -#include "Path.h" -#include "Pattern.h" -#include "PlatformGraphicsContext.h" -#include "SkBitmapRef.h" -#include "SkBlurDrawLooper.h" -#include "SkBlurMaskFilter.h" -#include "SkCanvas.h" -#include "SkColorPriv.h" -#include "SkCornerPathEffect.h" -#include "SkDashPathEffect.h" -#include "SkDevice.h" -#include "SkGradientShader.h" -#include "SkPaint.h" -#include "SkString.h" -#include "SkiaUtils.h" -#include "TransformationMatrix.h" -#include "android_graphics.h" - -using namespace std; - -#define GC2CANVAS(ctx) (ctx)->m_data->getPlatformGfxCtx()->mCanvas - -namespace WebCore { - -static int RoundToInt(float x) -{ - return (int)roundf(x); -} - -template <typename T> T* deepCopyPtr(const T* src) -{ - return src ? new T(*src) : 0; -} - -// Set a bitmap shader that mimics dashing by width-on, width-off. -// Returns false if it could not succeed (e.g. there was an existing shader) -static bool setBitmapDash(SkPaint* paint, int width) { - if (width <= 0 || paint->getShader()) - return false; - - SkColor c = paint->getColor(); - - SkBitmap bm; - bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 1); - bm.allocPixels(); - bm.lockPixels(); - - // set the ON pixel - *bm.getAddr32(0, 0) = SkPreMultiplyARGB(0xFF, SkColorGetR(c), - SkColorGetG(c), SkColorGetB(c)); - // set the OFF pixel - *bm.getAddr32(1, 0) = 0; - bm.unlockPixels(); - - SkMatrix matrix; - matrix.setScale(SkIntToScalar(width), SK_Scalar1); - - SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode, - SkShader::kClamp_TileMode); - s->setLocalMatrix(matrix); - - paint->setShader(s)->unref(); - return true; -} - -// TODO / questions - -// alpha: how does this interact with the alpha in Color? multiply them together? -// mode: do I always respect this? If so, then -// the rgb() & 0xFF000000 check will abort drawing too often -// Is Color premultiplied or not? If it is, then I can't blindly pass it to paint.setColor() - -struct ShadowRec { - SkScalar blur; - SkScalar dx; - SkScalar dy; - SkColor color; // alpha>0 means valid shadow - ShadowRec(SkScalar b = 0, - SkScalar x = 0, - SkScalar y = 0, - SkColor c = 0) // by default, alpha=0, so no shadow - : blur(b), dx(x), dy(y), color(c) - {}; -}; - -class GraphicsContextPlatformPrivate { -public: - struct State { - SkPathEffect* pathEffect; - float miterLimit; - float alpha; - float strokeThickness; - SkPaint::Cap lineCap; - SkPaint::Join lineJoin; - SkXfermode::Mode mode; - int dashRatio; // Ratio of the length of a dash to its width - ShadowRec shadow; - SkColor fillColor; - SkColor strokeColor; - bool useAA; - - State() - : pathEffect(0) - , miterLimit(4) - , alpha(1) - , strokeThickness(0) // Same as default in GraphicsContextPrivate.h - , lineCap(SkPaint::kDefault_Cap) - , lineJoin(SkPaint::kDefault_Join) - , mode(SkXfermode::kSrcOver_Mode) - , dashRatio(3) - , fillColor(SK_ColorBLACK) - , strokeColor(SK_ColorBLACK) - , useAA(true) - { - } - - State(const State& other) - : pathEffect(other.pathEffect) - , miterLimit(other.miterLimit) - , alpha(other.alpha) - , strokeThickness(other.strokeThickness) - , lineCap(other.lineCap) - , lineJoin(other.lineJoin) - , mode(other.mode) - , dashRatio(other.dashRatio) - , shadow(other.shadow) - , fillColor(other.fillColor) - , strokeColor(other.strokeColor) - , useAA(other.useAA) - { - SkSafeRef(pathEffect); - } - - ~State() - { - SkSafeUnref(pathEffect); - } - - void setShadow(int radius, int dx, int dy, SkColor c) - { - // Cut the radius in half, to visually match the effect seen in - // safari browser - shadow.blur = SkScalarHalf(SkIntToScalar(radius)); - shadow.dx = SkIntToScalar(dx); - shadow.dy = SkIntToScalar(dy); - shadow.color = c; - } - - bool setupShadowPaint(GraphicsContext* ctx, SkPaint* paint, SkPoint* offset) - { - paint->setAntiAlias(true); - paint->setDither(true); - paint->setXfermodeMode(mode); - paint->setColor(shadow.color); - offset->set(shadow.dx, shadow.dy); - - // Currently, only GraphicsContexts associated with the - // HTMLCanvasElement have shadows ignore transforms set. This - // allows us to distinguish between CSS and Canvas shadows which - // have different rendering specifications. - uint32_t flags = SkBlurMaskFilter::kHighQuality_BlurFlag; - if (ctx->shadowsIgnoreTransforms()) { - offset->fY = -offset->fY; - flags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag; - } - - if (shadow.blur > 0) { - paint->setMaskFilter(SkBlurMaskFilter::Create(shadow.blur, - SkBlurMaskFilter::kNormal_BlurStyle))->unref(); - } - return SkColorGetA(shadow.color) && (shadow.blur || shadow.dx || shadow.dy); - } - - SkColor applyAlpha(SkColor c) const - { - int s = RoundToInt(alpha * 256); - if (s >= 256) - return c; - if (s < 0) - return 0; - - int a = SkAlphaMul(SkColorGetA(c), s); - return (c & 0x00FFFFFF) | (a << 24); - } - }; - - GraphicsContextPlatformPrivate(GraphicsContext* gfxCtx, PlatformGraphicsContext* platformGfxCtx) - : m_parentGfxCtx(gfxCtx) - , m_platformGfxCtx(platformGfxCtx) - , m_stateStack(sizeof(State)) - { - State* state = static_cast<State*>(m_stateStack.push_back()); - new (state) State(); - m_state = state; - } - - ~GraphicsContextPlatformPrivate() - { - // We force restores so we don't leak any subobjects owned by our - // stack of State records. - while (m_stateStack.count() > 0) - this->restore(); - - if (m_platformGfxCtx && m_platformGfxCtx->deleteUs()) - delete m_platformGfxCtx; - } - - void save() - { - State* newState = static_cast<State*>(m_stateStack.push_back()); - new (newState) State(*m_state); - m_state = newState; - } - - void restore() - { - m_state->~State(); - m_stateStack.pop_back(); - m_state = static_cast<State*>(m_stateStack.back()); - } - - void setFillColor(const Color& c) - { - m_state->fillColor = c.rgb(); - } - - void setStrokeColor(const Color& c) - { - m_state->strokeColor = c.rgb(); - } - - void setStrokeThickness(float f) - { - m_state->strokeThickness = f; - } - - void setupPaintCommon(SkPaint* paint) const - { - paint->setAntiAlias(m_state->useAA); - paint->setDither(true); - paint->setXfermodeMode(m_state->mode); - if (SkColorGetA(m_state->shadow.color) > 0) { - - // Currently, only GraphicsContexts associated with the - // HTMLCanvasElement have shadows ignore transforms set. This - // allows us to distinguish between CSS and Canvas shadows which - // have different rendering specifications. - SkScalar dy = m_state->shadow.dy; - uint32_t flags = SkBlurDrawLooper::kHighQuality_BlurFlag; - if (m_parentGfxCtx->shadowsIgnoreTransforms()) { - dy = -dy; - flags |= SkBlurDrawLooper::kIgnoreTransform_BlurFlag; - flags |= SkBlurDrawLooper::kOverrideColor_BlurFlag; - } - - SkDrawLooper* looper = new SkBlurDrawLooper(m_state->shadow.blur, - m_state->shadow.dx, - dy, - m_state->shadow.color, - flags); - paint->setLooper(looper)->unref(); - } - } - - void setupPaintFill(SkPaint* paint) const - { - this->setupPaintCommon(paint); - paint->setColor(m_state->applyAlpha(m_state->fillColor)); - } - - void setupPaintBitmap(SkPaint* paint) const - { - this->setupPaintCommon(paint); - // We only want the global alpha for bitmaps, - // so just give applyAlpha opaque black - paint->setColor(m_state->applyAlpha(0xFF000000)); - } - - // Sets up the paint for stroking. Returns true if the style is really - // just a dash of squares (the size of the paint's stroke-width. - bool setupPaintStroke(SkPaint* paint, SkRect* rect, bool isHLine = false) - { - this->setupPaintCommon(paint); - paint->setColor(m_state->applyAlpha(m_state->strokeColor)); - - float width = m_state->strokeThickness; - - // This allows dashing and dotting to work properly for hairline strokes - // FIXME: Should we only do this for dashed and dotted strokes? - if (!width) - width = 1; - - paint->setStyle(SkPaint::kStroke_Style); - paint->setStrokeWidth(SkFloatToScalar(width)); - paint->setStrokeCap(m_state->lineCap); - paint->setStrokeJoin(m_state->lineJoin); - paint->setStrokeMiter(SkFloatToScalar(m_state->miterLimit)); - - if (rect && (RoundToInt(width) & 1)) - rect->inset(-SK_ScalarHalf, -SK_ScalarHalf); - - SkPathEffect* pe = m_state->pathEffect; - if (pe) { - paint->setPathEffect(pe); - return false; - } - switch (m_parentGfxCtx->strokeStyle()) { - case NoStroke: - case SolidStroke: - width = 0; - break; - case DashedStroke: - width = m_state->dashRatio * width; - break; - // No break - case DottedStroke: - break; - } - - if (width > 0) { - // Return true if we're basically a dotted dash of squares - bool justSqrs = RoundToInt(width) == RoundToInt(paint->getStrokeWidth()); - - if (justSqrs || !isHLine || !setBitmapDash(paint, width)) { -#if 0 - // this is slow enough that we just skip it for now - // see http://b/issue?id=4163023 - SkScalar intervals[] = { width, width }; - pe = new SkDashPathEffect(intervals, 2, 0); - paint->setPathEffect(pe)->unref(); -#endif - } - return justSqrs; - } - return false; - } - - PlatformGraphicsContext* getPlatformGfxCtx() - { - return m_platformGfxCtx; - } - - State* getState() - { - return m_state; - } -private: - State* m_state; - GraphicsContext* m_parentGfxCtx; // Back-ptr to our parent - PlatformGraphicsContext* m_platformGfxCtx; - SkDeque m_stateStack; - // Not supported yet - State& operator=(const State&); -}; - -static SkShader::TileMode SpreadMethod2TileMode(GradientSpreadMethod sm) -{ - SkShader::TileMode mode = SkShader::kClamp_TileMode; - - switch (sm) { - case SpreadMethodPad: - mode = SkShader::kClamp_TileMode; - break; - case SpreadMethodReflect: - mode = SkShader::kMirror_TileMode; - break; - case SpreadMethodRepeat: - mode = SkShader::kRepeat_TileMode; - break; - } - return mode; -} - -static void extactShader(SkPaint* paint, Pattern* pat, Gradient* grad) -{ - if (pat) { - // platformPattern() returns a cached obj - paint->setShader(pat->platformPattern(AffineTransform())); - } else if (grad) { - // grad->getShader() returns a cached obj - GradientSpreadMethod sm = grad->spreadMethod(); - paint->setShader(grad->getShader(SpreadMethod2TileMode(sm))); - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////// - -GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height) -{ - PlatformGraphicsContext* pgc = new PlatformGraphicsContext(); - - SkBitmap bitmap; - - bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); - bitmap.allocPixels(); - bitmap.eraseColor(0); - pgc->mCanvas->setBitmapDevice(bitmap); - - GraphicsContext* ctx = new GraphicsContext(pgc); - return ctx; -} - -//////////////////////////////////////////////////////////////////////////////////////////////// - -void GraphicsContext::platformInit(PlatformGraphicsContext* gc) -{ - m_data = new GraphicsContextPlatformPrivate(this, gc); - setPaintingDisabled(!gc || !gc->mCanvas); -} - -void GraphicsContext::platformDestroy() -{ - delete m_data; -} - -void GraphicsContext::savePlatformState() -{ - // Save our private State - m_data->save(); - // Save our native canvas - GC2CANVAS(this)->save(); -} - -void GraphicsContext::restorePlatformState() -{ - // Restore our private State - m_data->restore(); - // Restore our native canvas - GC2CANVAS(this)->restore(); -} - -bool GraphicsContext::willFill() const -{ - return m_data->getState()->fillColor; -} - -bool GraphicsContext::willStroke() const -{ - return m_data->getState()->strokeColor; -} - -// Draws a filled rectangle with a stroked border. -void GraphicsContext::drawRect(const IntRect& rect) -{ - if (paintingDisabled()) - return; - - SkPaint paint; - SkRect r(rect); - - if (fillColor().alpha()) { - m_data->setupPaintFill(&paint); - GC2CANVAS(this)->drawRect(r, paint); - } - - // According to GraphicsContext.h, stroking inside drawRect always means - // a stroke of 1 inside the rect. - if (strokeStyle() != NoStroke && strokeColor().alpha()) { - paint.reset(); - m_data->setupPaintStroke(&paint, &r); - paint.setPathEffect(0); // No dashing please - paint.setStrokeWidth(SK_Scalar1); // Always just 1.0 width - r.inset(SK_ScalarHalf, SK_ScalarHalf); // Ensure we're "inside" - GC2CANVAS(this)->drawRect(r, paint); - } -} - -// This is only used to draw borders. -void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) -{ - if (paintingDisabled()) - return; - - StrokeStyle style = strokeStyle(); - if (style == NoStroke) - return; - - SkPaint paint; - SkCanvas* canvas = GC2CANVAS(this); - const int idx = SkAbs32(point2.x() - point1.x()); - const int idy = SkAbs32(point2.y() - point1.y()); - - // Special-case horizontal and vertical lines that are really just dots - if (m_data->setupPaintStroke(&paint, 0, !idy) && (!idx || !idy)) { - const SkScalar diameter = paint.getStrokeWidth(); - const SkScalar radius = SkScalarHalf(diameter); - SkScalar x = SkIntToScalar(SkMin32(point1.x(), point2.x())); - SkScalar y = SkIntToScalar(SkMin32(point1.y(), point2.y())); - SkScalar dx, dy; - int count; - SkRect bounds; - - if (!idy) { // Horizontal - bounds.set(x, y - radius, x + SkIntToScalar(idx), y + radius); - x += radius; - dx = diameter * 2; - dy = 0; - count = idx; - } else { // Vertical - bounds.set(x - radius, y, x + radius, y + SkIntToScalar(idy)); - y += radius; - dx = 0; - dy = diameter * 2; - count = idy; - } - - // The actual count is the number of ONs we hit alternating - // ON(diameter), OFF(diameter), ... - { - SkScalar width = SkScalarDiv(SkIntToScalar(count), diameter); - // Now compute the number of cells (ON and OFF) - count = SkScalarRound(width); - // Now compute the number of ONs - count = (count + 1) >> 1; - } - - SkAutoMalloc storage(count * sizeof(SkPoint)); - SkPoint* verts = (SkPoint*)storage.get(); - // Now build the array of vertices to past to drawPoints - for (int i = 0; i < count; i++) { - verts[i].set(x, y); - x += dx; - y += dy; - } - - paint.setStyle(SkPaint::kFill_Style); - paint.setPathEffect(0); - - // Clipping to bounds is not required for correctness, but it does - // allow us to reject the entire array of points if we are completely - // offscreen. This is common in a webpage for android, where most of - // the content is clipped out. If drawPoints took an (optional) bounds - // parameter, that might even be better, as we would *just* use it for - // culling, and not both wacking the canvas' save/restore stack. - canvas->save(SkCanvas::kClip_SaveFlag); - canvas->clipRect(bounds); - canvas->drawPoints(SkCanvas::kPoints_PointMode, count, verts, paint); - canvas->restore(); - } else { - SkPoint pts[2] = { point1, point2 }; - canvas->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint); - } -} - -static void setrectForUnderline(SkRect* r, GraphicsContext* context, const FloatPoint& point, int yOffset, float width) -{ - float lineThickness = context->strokeThickness(); -#if 0 - if (lineThickness < 1) // Do we really need/want this? - lineThickness = 1; -#endif - r->fLeft = point.x(); - r->fTop = point.y() + yOffset; - r->fRight = r->fLeft + width; - r->fBottom = r->fTop + lineThickness; -} - -void GraphicsContext::drawLineForText(const FloatPoint& pt, float width, bool) -{ - if (paintingDisabled()) - return; - - SkRect r; - setrectForUnderline(&r, this, pt, 0, width); - - SkPaint paint; - paint.setAntiAlias(true); - paint.setColor(this->strokeColor().rgb()); - - GC2CANVAS(this)->drawRect(r, paint); -} - -// TODO: Should we draw different based on TextCheckingLineStyle? -void GraphicsContext::drawLineForTextChecking(const FloatPoint& pt, float width, TextCheckingLineStyle) -{ - if (paintingDisabled()) - return; - - SkRect r; - setrectForUnderline(&r, this, pt, 0, width); - - SkPaint paint; - paint.setAntiAlias(true); - paint.setColor(SK_ColorRED); // Is this specified somewhere? - - GC2CANVAS(this)->drawRect(r, paint); -} - -// This method is only used to draw the little circles used in lists. -void GraphicsContext::drawEllipse(const IntRect& rect) -{ - if (paintingDisabled()) - return; - - SkPaint paint; - SkRect oval(rect); - - if (fillColor().rgb() & 0xFF000000) { - m_data->setupPaintFill(&paint); - GC2CANVAS(this)->drawOval(oval, paint); - } - if (strokeStyle() != NoStroke) { - paint.reset(); - m_data->setupPaintStroke(&paint, &oval); - GC2CANVAS(this)->drawOval(oval, paint); - } -} - -static inline int fastMod(int value, int max) -{ - int sign = SkExtractSign(value); - - value = SkApplySign(value, sign); - if (value >= max) - value %= max; - return SkApplySign(value, sign); -} - -void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan) -{ - if (paintingDisabled()) - return; - - SkPath path; - SkPaint paint; - SkRect oval(r); - - if (strokeStyle() == NoStroke) { - m_data->setupPaintFill(&paint); // We want the fill color - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(SkFloatToScalar(this->strokeThickness())); - } else - m_data->setupPaintStroke(&paint, 0); - - // We do this before converting to scalar, so we don't overflow SkFixed - startAngle = fastMod(startAngle, 360); - angleSpan = fastMod(angleSpan, 360); - - path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan)); - GC2CANVAS(this)->drawPath(path, paint); -} - -void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias) -{ - if (paintingDisabled()) - return; - - if (numPoints <= 1) - return; - - SkPaint paint; - SkPath path; - - path.incReserve(numPoints); - path.moveTo(SkFloatToScalar(points[0].x()), SkFloatToScalar(points[0].y())); - for (size_t i = 1; i < numPoints; i++) - path.lineTo(SkFloatToScalar(points[i].x()), SkFloatToScalar(points[i].y())); - - if (GC2CANVAS(this)->quickReject(path, shouldAntialias ? - SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType)) { - return; - } - - if (fillColor().rgb() & 0xFF000000) { - m_data->setupPaintFill(&paint); - paint.setAntiAlias(shouldAntialias); - GC2CANVAS(this)->drawPath(path, paint); - } - - if (strokeStyle() != NoStroke) { - paint.reset(); - m_data->setupPaintStroke(&paint, 0); - paint.setAntiAlias(shouldAntialias); - GC2CANVAS(this)->drawPath(path, paint); - } -} - -void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, - const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace) -{ - if (paintingDisabled()) - return; - - SkPaint paint; - SkPath path; - SkScalar radii[8]; - - radii[0] = SkIntToScalar(topLeft.width()); - radii[1] = SkIntToScalar(topLeft.height()); - radii[2] = SkIntToScalar(topRight.width()); - radii[3] = SkIntToScalar(topRight.height()); - radii[4] = SkIntToScalar(bottomRight.width()); - radii[5] = SkIntToScalar(bottomRight.height()); - radii[6] = SkIntToScalar(bottomLeft.width()); - radii[7] = SkIntToScalar(bottomLeft.height()); - path.addRoundRect(rect, radii); - - m_data->setupPaintFill(&paint); - paint.setColor(color.rgb()); - GC2CANVAS(this)->drawPath(path, paint); -} - -void GraphicsContext::fillRect(const FloatRect& rect) -{ - save(); - SkPaint paint; - - m_data->setupPaintFill(&paint); - - extactShader(&paint, - m_state.fillPattern.get(), - m_state.fillGradient.get()); - - GC2CANVAS(this)->drawRect(rect, paint); - restore(); -} - -void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace) -{ - if (paintingDisabled()) - return; - - if (color.rgb() & 0xFF000000) { - save(); - SkPaint paint; - - m_data->setupPaintCommon(&paint); - paint.setColor(color.rgb()); // Punch in the specified color - paint.setShader(0); // In case we had one set - - // Sometimes we record and draw portions of the page, using clips - // for each portion. The problem with this is that webkit, sometimes, - // sees that we're only recording a portion, and they adjust some of - // their rectangle coordinates accordingly (e.g. - // RenderBoxModelObject::paintFillLayerExtended() which calls - // rect.intersect(paintInfo.rect) and then draws the bg with that - // rect. The result is that we end up drawing rects that are meant to - // seam together (one for each portion), but if the rects have - // fractional coordinates (e.g. we are zoomed by a fractional amount) - // we will double-draw those edges, resulting in visual cracks or - // artifacts. - - // The fix seems to be to just turn off antialasing for rects (this - // entry-point in GraphicsContext seems to have been sufficient, - // though perhaps we'll find we need to do this as well in fillRect(r) - // as well.) Currently setupPaintCommon() enables antialiasing. - - // Since we never show the page rotated at a funny angle, disabling - // antialiasing seems to have no real down-side, and it does fix the - // bug when we're zoomed (and drawing portions that need to seam). - paint.setAntiAlias(false); - - GC2CANVAS(this)->drawRect(rect, paint); - restore(); - } -} - -void GraphicsContext::clip(const FloatRect& rect) -{ - if (paintingDisabled()) - return; - - GC2CANVAS(this)->clipRect(rect); -} - -void GraphicsContext::clip(const Path& path) -{ - if (paintingDisabled()) - return; - - GC2CANVAS(this)->clipPath(*path.platformPath(), SkRegion::kIntersect_Op, true); -} - -void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) -{ - if (paintingDisabled()) - return; - - SkPath path; - SkRect r(rect); - - path.addOval(r, SkPath::kCW_Direction); - // Only perform the inset if we won't invert r - if (2 * thickness < rect.width() && 2 * thickness < rect.height()) { - // Adding one to the thickness doesn't make the border too thick as - // it's painted over afterwards. But without this adjustment the - // border appears a little anemic after anti-aliasing. - r.inset(SkIntToScalar(thickness + 1), SkIntToScalar(thickness + 1)); - path.addOval(r, SkPath::kCCW_Direction); - } - GC2CANVAS(this)->clipPath(path, SkRegion::kIntersect_Op, true); -} - -void GraphicsContext::canvasClip(const Path& path) -{ - clip(path); -} - -void GraphicsContext::clipOut(const IntRect& r) -{ - if (paintingDisabled()) - return; - - GC2CANVAS(this)->clipRect(r, SkRegion::kDifference_Op); -} - -#if ENABLE(SVG) -void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule) -{ - if (paintingDisabled()) - return; - - SkPath path = *pathToClip.platformPath(); - path.setFillType(clipRule == RULE_EVENODD ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType); - GC2CANVAS(this)->clipPath(path); -} -#endif - -void GraphicsContext::clipOut(const Path& p) -{ - if (paintingDisabled()) - return; - - GC2CANVAS(this)->clipPath(*p.platformPath(), SkRegion::kDifference_Op); -} - -////////////////////////////////////////////////////////////////////////////////////////////////// - -#if SVG_SUPPORT -KRenderingDeviceContext* GraphicsContext::createRenderingDeviceContext() -{ - return new KRenderingDeviceContextQuartz(platformContext()); -} -#endif - -// These are the flags we need when we call saveLayer for transparency. -// Since it does not appear that webkit intends this to also save/restore -// the matrix or clip, I do not give those flags (for performance) -#define TRANSPARENCY_SAVEFLAGS \ - (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | \ - SkCanvas::kFullColorLayer_SaveFlag) - -void GraphicsContext::beginTransparencyLayer(float opacity) -{ - if (paintingDisabled()) - return; - - SkCanvas* canvas = GC2CANVAS(this); - canvas->saveLayerAlpha(0, (int)(opacity * 255), TRANSPARENCY_SAVEFLAGS); -} - -void GraphicsContext::endTransparencyLayer() -{ - if (paintingDisabled()) - return; - - GC2CANVAS(this)->restore(); -} - -/////////////////////////////////////////////////////////////////////////// - -void GraphicsContext::setupBitmapPaint(SkPaint* paint) -{ - m_data->setupPaintBitmap(paint); -} - -void GraphicsContext::setupFillPaint(SkPaint* paint) -{ - m_data->setupPaintFill(paint); -} - -void GraphicsContext::setupStrokePaint(SkPaint* paint) -{ - m_data->setupPaintStroke(paint, 0); -} - -bool GraphicsContext::setupShadowPaint(SkPaint* paint, SkPoint* offset) -{ - return m_data->getState()->setupShadowPaint(this, paint, offset); -} - -void GraphicsContext::setPlatformStrokeColor(const Color& c, ColorSpace) -{ - m_data->setStrokeColor(c); -} - -void GraphicsContext::setPlatformStrokeThickness(float f) -{ - m_data->setStrokeThickness(f); -} - -void GraphicsContext::setPlatformFillColor(const Color& c, ColorSpace) -{ - m_data->setFillColor(c); -} - -void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const Color& color, ColorSpace) -{ - if (paintingDisabled()) - return; - - if (blur <= 0) - this->clearPlatformShadow(); - - SkColor c; - if (color.isValid()) - c = color.rgb(); - else - c = SkColorSetARGB(0xFF / 3, 0, 0, 0); // "std" Apple shadow color - m_data->getState()->setShadow(blur, size.width(), size.height(), c); -} - -void GraphicsContext::clearPlatformShadow() -{ - if (paintingDisabled()) - return; - - m_data->getState()->setShadow(0, 0, 0, 0); -} - -/////////////////////////////////////////////////////////////////////////////// - -void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width */, int /* offset */, const Color& color) -{ - if (paintingDisabled()) - return; - - unsigned rectCount = rects.size(); - if (!rectCount) - return; - - SkRegion focusRingRegion; - const SkScalar focusRingOutset = WebCoreFloatToSkScalar(0.8); - for (unsigned i = 0; i < rectCount; i++) { - SkIRect r = rects[i]; - r.inset(-focusRingOutset, -focusRingOutset); - focusRingRegion.op(r, SkRegion::kUnion_Op); - } - - SkPath path; - SkPaint paint; - paint.setAntiAlias(true); - paint.setStyle(SkPaint::kStroke_Style); - - paint.setColor(color.rgb()); - paint.setStrokeWidth(focusRingOutset * 2); - paint.setPathEffect(new SkCornerPathEffect(focusRingOutset * 2))->unref(); - focusRingRegion.getBoundaryPath(&path); - platformContext()->mCanvas->drawPath(path, paint); -} - -void GraphicsContext::drawFocusRing(const Path&, int, int, const Color&) -{ - // Do nothing, since we draw the focus ring independently. -} - -PlatformGraphicsContext* GraphicsContext::platformContext() const -{ - ASSERT(!paintingDisabled()); - return m_data->getPlatformGfxCtx(); -} - -void GraphicsContext::setMiterLimit(float limit) -{ - m_data->getState()->miterLimit = limit; -} - -void GraphicsContext::setAlpha(float alpha) -{ - m_data->getState()->alpha = alpha; -} - -void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op) -{ - m_data->getState()->mode = WebCoreCompositeToSkiaComposite(op); -} - -void GraphicsContext::clearRect(const FloatRect& rect) -{ - if (paintingDisabled()) - return; - - SkPaint paint; - - m_data->setupPaintFill(&paint); - paint.setXfermodeMode(SkXfermode::kClear_Mode); - GC2CANVAS(this)->drawRect(rect, paint); -} - -void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) -{ - if (paintingDisabled()) - return; - - SkPaint paint; - - m_data->setupPaintStroke(&paint, 0); - paint.setStrokeWidth(SkFloatToScalar(lineWidth)); - GC2CANVAS(this)->drawRect(rect, paint); -} - -void GraphicsContext::setLineCap(LineCap cap) -{ - switch (cap) { - case ButtCap: - m_data->getState()->lineCap = SkPaint::kButt_Cap; - break; - case RoundCap: - m_data->getState()->lineCap = SkPaint::kRound_Cap; - break; - case SquareCap: - m_data->getState()->lineCap = SkPaint::kSquare_Cap; - break; - default: - SkDEBUGF(("GraphicsContext::setLineCap: unknown LineCap %d\n", cap)); - break; - } -} - -#if ENABLE(SVG) -void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset) -{ - if (paintingDisabled()) - return; - - size_t dashLength = dashes.size(); - if (!dashLength) - return; - - size_t count = !(dashLength % 2) ? dashLength : dashLength * 2; - SkScalar* intervals = new SkScalar[count]; - - for (unsigned int i = 0; i < count; i++) - intervals[i] = SkFloatToScalar(dashes[i % dashLength]); - SkPathEffect **effectPtr = &m_data->getState()->pathEffect; - SkSafeUnref(*effectPtr); - *effectPtr = new SkDashPathEffect(intervals, count, SkFloatToScalar(dashOffset)); - - delete[] intervals; -} -#endif - -void GraphicsContext::setLineJoin(LineJoin join) -{ - switch (join) { - case MiterJoin: - m_data->getState()->lineJoin = SkPaint::kMiter_Join; - break; - case RoundJoin: - m_data->getState()->lineJoin = SkPaint::kRound_Join; - break; - case BevelJoin: - m_data->getState()->lineJoin = SkPaint::kBevel_Join; - break; - default: - SkDEBUGF(("GraphicsContext::setLineJoin: unknown LineJoin %d\n", join)); - break; - } -} - -void GraphicsContext::scale(const FloatSize& size) -{ - if (paintingDisabled()) - return; - GC2CANVAS(this)->scale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height())); -} - -void GraphicsContext::rotate(float angleInRadians) -{ - if (paintingDisabled()) - return; - GC2CANVAS(this)->rotate(SkFloatToScalar(angleInRadians * (180.0f / 3.14159265f))); -} - -void GraphicsContext::translate(float x, float y) -{ - if (paintingDisabled()) - return; - GC2CANVAS(this)->translate(SkFloatToScalar(x), SkFloatToScalar(y)); -} - -void GraphicsContext::concatCTM(const AffineTransform& affine) -{ - if (paintingDisabled()) - return; - GC2CANVAS(this)->concat(affine); -} - -// This is intended to round the rect to device pixels (through the CTM) -// and then invert the result back into source space, with the hope that when -// it is drawn (through the matrix), it will land in the "right" place (i.e. -// on pixel boundaries). - -// For android, we record this geometry once and then draw it though various -// scale factors as the user zooms, without re-recording. Thus this routine -// should just leave the original geometry alone. - -// If we instead draw into bitmap tiles, we should then perform this -// transform -> round -> inverse step. - -FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMode) -{ - return rect; -} - -////////////////////////////////////////////////////////////////////////////////////////////////// - -void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) -{ -// Appears to be PDF specific, so we ignore it -#if 0 -if (paintingDisabled()) - return; - -CFURLRef urlRef = link.createCFURL(); -if (urlRef) { - CGContextRef context = platformContext(); - - // Get the bounding box to handle clipping. - CGRect box = CGContextGetClipBoundingBox(context); - - IntRect intBox((int)box.origin.x, (int)box.origin.y, (int)box.size.width, (int)box.size.height); - IntRect rect = destRect; - rect.intersect(intBox); - - CGPDFContextSetURLForRect(context, urlRef, - CGRectApplyAffineTransform(rect, CGContextGetCTM(context))); - - CFRelease(urlRef); -} -#endif -} - -void GraphicsContext::setPlatformShouldAntialias(bool useAA) -{ - if (paintingDisabled()) - return; - m_data->getState()->useAA = useAA; -} - -AffineTransform GraphicsContext::getCTM() const -{ - const SkMatrix& m = GC2CANVAS(this)->getTotalMatrix(); - return AffineTransform(SkScalarToDouble(m.getScaleX()), // a - SkScalarToDouble(m.getSkewY()), // b - SkScalarToDouble(m.getSkewX()), // c - SkScalarToDouble(m.getScaleY()), // d - SkScalarToDouble(m.getTranslateX()), // e - SkScalarToDouble(m.getTranslateY())); // f -} - -void GraphicsContext::setCTM(const AffineTransform& transform) -{ - // The SkPicture mode of Skia does not support SkCanvas::setMatrix(), so we - // can not simply use that method here. We could calculate the transform - // required to achieve the desired matrix and use SkCanvas::concat(), but - // there's currently no need for this. - ASSERT_NOT_REACHED(); -} - -/////////////////////////////////////////////////////////////////////////////// - -void GraphicsContext::fillPath(const Path& pathToFill) -{ - SkPath* path = pathToFill.platformPath(); - if (paintingDisabled() || !path) - return; - - switch (this->fillRule()) { - case RULE_NONZERO: - path->setFillType(SkPath::kWinding_FillType); - break; - case RULE_EVENODD: - path->setFillType(SkPath::kEvenOdd_FillType); - break; - } - - SkPaint paint; - m_data->setupPaintFill(&paint); - - extactShader(&paint, - m_state.fillPattern.get(), - m_state.fillGradient.get()); - - GC2CANVAS(this)->drawPath(*path, paint); -} - -void GraphicsContext::strokePath(const Path& pathToStroke) -{ - const SkPath* path = pathToStroke.platformPath(); - if (paintingDisabled() || !path) - return; - - SkPaint paint; - m_data->setupPaintStroke(&paint, 0); - - extactShader(&paint, - m_state.strokePattern.get(), - m_state.strokeGradient.get()); - - GC2CANVAS(this)->drawPath(*path, paint); -} - -InterpolationQuality GraphicsContext::imageInterpolationQuality() const -{ - notImplemented(); - return InterpolationDefault; -} - -void GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode) -{ -#if 0 - enum InterpolationQuality { - InterpolationDefault, - InterpolationNone, - InterpolationLow, - InterpolationMedium, - InterpolationHigh - }; -#endif - // TODO: record this, so we can know when to use bitmap-filtering when we draw - // ... not sure how meaningful this will be given our playback model. - - // Certainly safe to do nothing for the present. -} - -void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias) -{ - if (paintingDisabled()) - return; - - if (numPoints <= 1) - return; - - // FIXME: IMPLEMENT! -} - -void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, const FloatPoint& point, int h, const Color& backgroundColor, ColorSpace colorSpace, int from, int to, bool isActive) -{ - if (paintingDisabled()) - return; - - IntRect rect = (IntRect)font.selectionRectForText(run, point, h, from, to); - if (isActive) - fillRect(rect, backgroundColor, colorSpace); - else { - int x = rect.x(), y = rect.y(), w = rect.width(), h = rect.height(); - const int t = 3, t2 = t * 2; - - fillRect(IntRect(x, y, w, t), backgroundColor, colorSpace); - fillRect(IntRect(x, y+h-t, w, t), backgroundColor, colorSpace); - fillRect(IntRect(x, y+t, t, h-t2), backgroundColor, colorSpace); - fillRect(IntRect(x+w-t, y+t, t, h-t2), backgroundColor, colorSpace); - } -} - -} // namespace WebCore - -/////////////////////////////////////////////////////////////////////////////// - -SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc) -{ - return gc->platformContext()->mCanvas; -} diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 2f9b379..00e6918 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -25,6 +25,7 @@ #include "AndroidAnimation.h" #include "AndroidLog.h" #include "Animation.h" +#include "CanvasLayer.h" #include "FloatRect.h" #include "FixedPositioning.h" #include "GraphicsContext.h" @@ -33,11 +34,12 @@ #include "Image.h" #include "ImagesManager.h" #include "Layer.h" +#include "LayerAndroid.h" #include "Length.h" #include "MediaLayer.h" #include "PictureLayerContent.h" #include "PlatformBridge.h" -#include "PlatformGraphicsContext.h" +#include "PlatformGraphicsContextSkia.h" #include "RenderLayerBacking.h" #include "RenderView.h" #include "RotateTransformOperation.h" @@ -119,7 +121,11 @@ GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) : m_foregroundClipLayer(0) { RenderLayer* renderLayer = renderLayerFromClient(m_client); - m_contentLayer = new LayerAndroid(renderLayer); + if (renderLayer && renderLayer->renderer()->isCanvas()) { + m_contentLayer = new CanvasLayer(renderLayer, + static_cast<HTMLCanvasElement*>(renderLayer->renderer()->node())); + } else + m_contentLayer = new LayerAndroid(renderLayer); m_dirtyRegion.setEmpty(); gDebugGraphicsLayerAndroidInstances++; } @@ -290,11 +296,10 @@ void GraphicsLayerAndroid::setPosition(const FloatPoint& point) GraphicsLayer::setPosition(point); -#ifdef LAYER_DEBUG_2 ALOGV("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)", this, point.x(), point.y(), m_position.x(), m_position.y(), m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height()); -#endif + m_contentLayer->setPosition(point.x(), point.y()); askForSync(); } @@ -709,7 +714,7 @@ bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer, return false; } - PlatformGraphicsContext platformContext(canvas); + PlatformGraphicsContextSkia platformContext(canvas); GraphicsContext graphicsContext(&platformContext); paintGraphicsLayerContents(graphicsContext, rect); diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h index 27dfde2..97f974e 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h @@ -23,7 +23,6 @@ #include "Frame.h" #include "GraphicsLayer.h" #include "GraphicsLayerClient.h" -#include "LayerAndroid.h" #include "LayerContent.h" #include "RefPtr.h" #include "ScrollableLayerAndroid.h" @@ -37,6 +36,7 @@ class SkRegion; namespace WebCore { +class LayerAndroid; class ScrollableLayerAndroid; class GraphicsLayerAndroid : public GraphicsLayer { diff --git a/Source/WebCore/platform/graphics/android/ImageAndroid.cpp b/Source/WebCore/platform/graphics/android/ImageAndroid.cpp index 8e0c112..08f72e0 100644 --- a/Source/WebCore/platform/graphics/android/ImageAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/ImageAndroid.cpp @@ -172,20 +172,7 @@ static void round_scaled(SkIRect* dst, const WebCore::FloatRect& src, SkScalarRound(SkFloatToScalar((src.y() + src.height()) * sy))); } -static inline void fixPaintForBitmapsThatMaySeam(SkPaint* paint) { - /* Bitmaps may be drawn to seem next to other images. If we are drawn - zoomed, or at fractional coordinates, we may see cracks/edges if - we antialias, because that will cause us to draw the same pixels - more than once (e.g. from the left and right bitmaps that share - an edge). - - Disabling antialiasing fixes this, and since so far we are never - rotated at non-multiple-of-90 angles, this seems to do no harm - */ - paint->setAntiAlias(false); -} - -void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, +void BitmapImage::draw(GraphicsContext* gc, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp) { @@ -222,14 +209,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, return; } - SkCanvas* canvas = ctxt->platformContext()->mCanvas; - SkPaint paint; - - ctxt->setupBitmapPaint(&paint); // need global alpha among other things - paint.setFilterBitmap(true); - paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp)); - fixPaintForBitmapsThatMaySeam(&paint); - canvas->drawBitmapRect(bitmap, &srcR, dstR, &paint); + gc->platformContext()->drawBitmapRect(bitmap, &srcR, dstR, compositeOp); #ifdef TRACE_SUBSAMPLED_BITMAPS if (bitmap.width() != image->origWidth() || @@ -248,26 +228,19 @@ void BitmapImage::setURL(const String& str) /////////////////////////////////////////////////////////////////////////////// -void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, +void Image::drawPattern(GraphicsContext* gc, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator compositeOp, const FloatRect& destRect) { SkBitmapRef* image = this->nativeImageForCurrentFrame(); - if (!image) { // If it's too early we won't have an image yet. + if (!image || destRect.isEmpty()) return; - } // in case we get called with an incomplete bitmap const SkBitmap& origBitmap = image->bitmap(); - if (origBitmap.getPixels() == NULL && origBitmap.pixelRef() == NULL) { + if (origBitmap.getPixels() == NULL && origBitmap.pixelRef() == NULL) return; - } - - SkRect dstR(destRect); - if (dstR.isEmpty()) { - return; - } SkIRect srcR; // we may have to scale if the image has been subsampled (so save RAM) @@ -278,11 +251,9 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, if (imageIsSubSampled) { scaleX = (float)image->origWidth() / origBitmap.width(); scaleY = (float)image->origHeight() / origBitmap.height(); -// SkDebugf("----- subsampled %g %g\n", scaleX, scaleY); round_scaled(&srcR, srcRect, 1 / scaleX, 1 / scaleY); - } else { + } else round(&srcR, srcRect); - } // now extract the proper subset of the src image SkBitmap bitmap; @@ -291,19 +262,6 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, return; } - SkCanvas* canvas = ctxt->platformContext()->mCanvas; - SkPaint paint; - ctxt->setupBitmapPaint(&paint); // need global alpha among other things - - SkShader* shader = SkShader::CreateBitmapShader(bitmap, - SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode); - paint.setShader(shader)->unref(); - // now paint is the only owner of shader - paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp)); - paint.setFilterBitmap(true); - fixPaintForBitmapsThatMaySeam(&paint); - SkMatrix matrix(patternTransform); if (imageIsSubSampled) { @@ -316,26 +274,8 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, float tx = phase.x() + srcRect.x() * patternTransform.a(); float ty = phase.y() + srcRect.y() * patternTransform.d(); matrix.postTranslate(SkFloatToScalar(tx), SkFloatToScalar(ty)); - shader->setLocalMatrix(matrix); -#if 0 - SkDebugf("--- drawPattern: src [%g %g %g %g] dst [%g %g %g %g] transform [%g %g %g %g %g %g] matrix [%g %g %g %g %g %g]\n", - srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(), - destRect.x(), destRect.y(), destRect.width(), destRect.height(), - patternTransform.a(), patternTransform.b(), patternTransform.c(), - patternTransform.d(), patternTransform.e(), patternTransform.f(), - matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); -#endif - canvas->drawRect(dstR, paint); -#ifdef TRACE_SUBSAMPLED_BITMAPS - if (bitmap.width() != image->origWidth() || - bitmap.height() != image->origHeight()) { - SkDebugf("--- Image::drawPattern [%d %d] orig [%d %d] dst [%g %g]\n", - bitmap.width(), bitmap.height(), - image->origWidth(), image->origHeight(), - SkScalarToFloat(dstR.width()), SkScalarToFloat(dstR.height())); - } -#endif + gc->platformContext()->drawBitmapPattern(bitmap, matrix, compositeOp, destRect); } // missingImage, textAreaResizeCorner diff --git a/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp b/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp index f148881..e56f424 100644 --- a/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp @@ -82,7 +82,10 @@ PassRefPtr<Image> ImageBuffer::copyImage() const { ASSERT(context()); - SkCanvas* canvas = context()->platformContext()->mCanvas; + SkCanvas* canvas = context()->platformContext()->getCanvas(); + if (!canvas) + return 0; + SkDevice* device = canvas->getDevice(); const SkBitmap& orig = device->accessBitmap(false); diff --git a/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp b/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp deleted file mode 100644 index ed6d046..0000000 --- a/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "PerformanceMonitor" -#define LOG_NDEBUG 1 - -#include "PerformanceMonitor.h" - -#include "AndroidLog.h" -#include <wtf/text/CString.h> - -namespace WebCore { - -PerformanceMonitor::PerformanceMonitor() -{ -} - -PerformanceMonitor::~PerformanceMonitor() -{ -} - -void PerformanceMonitor::start(const String &tag) -{ - if (tag.isEmpty()) - return; - PerfItem *item; - if (m_tags.contains(tag)) - item = m_tags.get(tag); - else { - item = new PerfItem(); - m_tags.set(tag, item); - } - gettimeofday(&(item->start_time), NULL); -} - -void PerformanceMonitor::stop(const String &tag) -{ - if (!m_tags.contains(tag)) - return; - PerfItem *item = m_tags.get(tag); - struct timeval end; - gettimeofday(&end, NULL); - long seconds, useconds; - seconds = end.tv_sec - item->start_time.tv_sec; - useconds = end.tv_usec - item->start_time.tv_usec; - - float mtime = (seconds * 1000.0) + (useconds/1000.0); - - if (item->average_ms) { - item->average_ms = (item->average_ms + mtime) / 2; - } else - item->average_ms = mtime; -} - -float PerformanceMonitor::getAverageDuration(const String &tag) -{ - if (tag.isEmpty() || !m_tags.contains(tag)) - return 0; - return m_tags.get(tag)->average_ms; -} - -void PerformanceMonitor::display(int limit) -{ - bool shown = false; - HashMap<String, PerfItem*, StringHash>::iterator end = m_tags.end(); - for (HashMap<String, PerfItem*, StringHash>::iterator it = m_tags.begin(); it != end; ++it) { - PerfItem* item = it->second; - if (item->average_ms > limit) { - if (!shown) { - ALOGD("=== DISPLAY MONITOR ===="); - shown = true; - } - ALOGD("item %s took longer than %d ms: %.2f", it->first.latin1().data(), limit, item->average_ms); - } - } - if (shown) - ALOGD("=== END DISPLAY MONITOR ===="); -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/PerformanceMonitor.h b/Source/WebCore/platform/graphics/android/PerformanceMonitor.h deleted file mode 100644 index 4ebbf6a..0000000 --- a/Source/WebCore/platform/graphics/android/PerformanceMonitor.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef PerformanceMonitor_h -#define PerformanceMonitor_h - -#include "config.h" - -#include <wtf/HashMap.h> -#include <wtf/text/StringHash.h> -#include <sys/time.h> -#include <unistd.h> - -namespace WebCore { - -struct PerfItem { - PerfItem() : average_ms(0), start_time() {} - float average_ms; - struct timeval start_time; -}; - -class PerformanceMonitor { -public: - PerformanceMonitor(); - virtual ~PerformanceMonitor(); - void start(const String &tag); - void stop(const String &tag); - float getAverageDuration(const String &tag); - void display(int limit); - -private: - HashMap<String, PerfItem*, StringHash> m_tags; -}; - -} - -#endif // PerformanceMonitor_h diff --git a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp deleted file mode 100644 index 098534c..0000000 --- a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2006, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "Node.h" -#include "PlatformGraphicsContext.h" -#include "SkCanvas.h" - -namespace WebCore { - -PlatformGraphicsContext::PlatformGraphicsContext(SkCanvas* canvas) - : mCanvas(canvas), m_deleteCanvas(false) -{ -} - -PlatformGraphicsContext::PlatformGraphicsContext() - : mCanvas(new SkCanvas), m_deleteCanvas(true) -{ -} - -PlatformGraphicsContext::~PlatformGraphicsContext() -{ - if (m_deleteCanvas) { -// printf("-------------------- deleting offscreen canvas\n"); - delete mCanvas; - } -} - -} // WebCore diff --git a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h deleted file mode 100644 index 80ea5d6..0000000 --- a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2006, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef platform_graphics_context_h -#define platform_graphics_context_h - -#include "IntRect.h" -#include "RenderSkinAndroid.h" -#include "SkCanvas.h" -#include "SkPicture.h" -#include "SkTDArray.h" - -class SkCanvas; - -namespace WebCore { - - class GraphicsContext; - -class PlatformGraphicsContext { -public: - PlatformGraphicsContext(); - // Pass in a recording canvas, and an array of button information to be - // updated. - PlatformGraphicsContext(SkCanvas* canvas); - ~PlatformGraphicsContext(); - - SkCanvas* mCanvas; - - bool deleteUs() const { return m_deleteCanvas; } -private: - bool m_deleteCanvas; -}; - -} -#endif diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp b/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp deleted file mode 100644 index a4c0ac8..0000000 --- a/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "SurfaceCollection" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "SurfaceCollection.h" - -#include "AndroidLog.h" -#include "BaseLayerAndroid.h" -#include "ClassTracker.h" -#include "LayerAndroid.h" -#include "LayerGroup.h" -#include "GLWebViewState.h" -#include "ScrollableLayerAndroid.h" -#include "TilesManager.h" - -namespace WebCore { - -//////////////////////////////////////////////////////////////////////////////// -// TILED PAINTING / GROUPS // -//////////////////////////////////////////////////////////////////////////////// - -SurfaceCollection::SurfaceCollection(BaseLayerAndroid* baseLayer) - : m_baseLayer(baseLayer) - , m_compositedRoot(0) -{ - if (!m_baseLayer) - return; - - SkSafeRef(m_baseLayer); - if (m_baseLayer->countChildren()) { - m_compositedRoot = static_cast<LayerAndroid*>(m_baseLayer->getChild(0)); - - // calculate draw transforms and z values - SkRect visibleRect = SkRect::MakeLTRB(0, 0, 1, 1); - m_baseLayer->updateLayerPositions(visibleRect); - - // allocate groups for layers, merging where possible - ALOGV("new tree, allocating groups for tree %p", m_baseLayer); - - LayerMergeState layerMergeState(&m_layerGroups); - m_compositedRoot->assignGroups(&layerMergeState); - } - - // set the layergroups' and tiledpages' update count, to be drawn on painted tiles - unsigned int updateCount = TilesManager::instance()->incWebkitContentUpdates(); - for (unsigned int i = 0; i < m_layerGroups.size(); i++) - m_layerGroups[i]->setUpdateCount(updateCount); - m_baseLayer->state()->frontPage()->setUpdateCount(updateCount); - m_baseLayer->state()->backPage()->setUpdateCount(updateCount); - -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("SurfaceCollection"); -#endif -} - -SurfaceCollection::~SurfaceCollection() -{ - SkSafeUnref(m_baseLayer); - for (unsigned int i = 0; i < m_layerGroups.size(); i++) - SkSafeUnref(m_layerGroups[i]); - m_layerGroups.clear(); - -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("SurfaceCollection"); -#endif -} - -void SurfaceCollection::prepareGL(const SkRect& visibleRect, float scale, double currentTime) -{ - if (!m_baseLayer) - return; - - m_baseLayer->prepareGL(visibleRect, scale, currentTime); - - if (m_compositedRoot) { - m_baseLayer->updateLayerPositions(visibleRect); - bool layerTilesDisabled = m_compositedRoot->state()->layersRenderingMode() - > GLWebViewState::kClippedTextures; - for (unsigned int i = 0; i < m_layerGroups.size(); i++) - m_layerGroups[i]->prepareGL(layerTilesDisabled); - } -} - -bool SurfaceCollection::drawGL(const SkRect& visibleRect, float scale) -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->show(); -#endif - - if (!m_baseLayer) - return false; - - m_baseLayer->drawGL(scale); - - bool needsRedraw = false; - if (m_compositedRoot) { - m_baseLayer->updateLayerPositions(visibleRect); - bool layerTilesDisabled = m_compositedRoot->state()->layersRenderingMode() - > GLWebViewState::kClippedTextures; - for (unsigned int i = 0; i < m_layerGroups.size(); i++) - needsRedraw |= m_layerGroups[i]->drawGL(layerTilesDisabled); - } - - return needsRedraw; -} - -void SurfaceCollection::swapTiles() -{ - if (!m_baseLayer) - return; - - m_baseLayer->swapTiles(); - - for (unsigned int i = 0; i < m_layerGroups.size(); i++) - m_layerGroups[i]->swapTiles(); -} - -bool SurfaceCollection::isReady() -{ - if (!m_baseLayer) - return true; - - if (!m_baseLayer->isReady()) - return false; - - if (!m_compositedRoot) - return true; - - // Override layer readiness check for single surface mode - if (m_compositedRoot->state()->layersRenderingMode() > GLWebViewState::kClippedTextures) { - // TODO: single surface mode should be properly double buffered - return true; - } - - for (unsigned int i = 0; i < m_layerGroups.size(); i++) { - if (!m_layerGroups[i]->isReady()) { - ALOGV("layer group %p isn't ready", m_layerGroups[i]); - return false; - } - } - return true; -} - -void SurfaceCollection::computeTexturesAmount(TexturesResult* result) -{ - for (unsigned int i = 0; i < m_layerGroups.size(); i++) - m_layerGroups[i]->computeTexturesAmount(result); -} - -void SurfaceCollection::drawCanvas(SkCanvas* canvas, bool drawLayers) -{ - // TODO: move this functionality out! - if (!m_baseLayer) - return; - - m_baseLayer->drawCanvas(canvas); - - // draw the layers onto the same canvas (for single surface mode) - if (drawLayers && m_compositedRoot) - m_compositedRoot->drawCanvas(canvas, true, Layer::FlattenedLayers); -} - - -//////////////////////////////////////////////////////////////////////////////// -// RECURSIVE ANIMATION / INVALS / LAYERS // -//////////////////////////////////////////////////////////////////////////////// - -void SurfaceCollection::setIsPainting(SurfaceCollection* drawingSurface) -{ - if (!m_baseLayer) - return; - - m_baseLayer->setIsPainting(); - - if (!drawingSurface) - return; - - for (unsigned int i = 0; i < m_layerGroups.size(); i++) { - LayerGroup* newLayerGroup = m_layerGroups[i]; - if (!newLayerGroup->needsTexture()) - continue; - - for (unsigned int j = 0; j < drawingSurface->m_layerGroups.size(); j++) { - LayerGroup* oldLayerGroup = drawingSurface->m_layerGroups[j]; - if (newLayerGroup->tryUpdateLayerGroup(oldLayerGroup)) - break; - } - } -} - -void SurfaceCollection::setIsDrawing() -{ - if (m_compositedRoot) - m_compositedRoot->initAnimations(); -} - -void SurfaceCollection::mergeInvalsInto(SurfaceCollection* replacementSurface) -{ - if (!m_baseLayer) - return; - - m_baseLayer->mergeInvalsInto(replacementSurface->m_baseLayer); - - if (m_compositedRoot && replacementSurface->m_compositedRoot) - m_compositedRoot->mergeInvalsInto(replacementSurface->m_compositedRoot); -} - -void SurfaceCollection::evaluateAnimations(double currentTime) -{ - if (m_compositedRoot) - m_compositedRoot->evaluateAnimations(currentTime); -} - -bool SurfaceCollection::hasCompositedLayers() -{ - return m_compositedRoot != 0; -} - -bool SurfaceCollection::hasCompositedAnimations() -{ - return m_compositedRoot != 0 && m_compositedRoot->hasAnimations(); -} - -int SurfaceCollection::baseContentWidth() -{ - // TODO: move this functionality out! - return m_baseLayer ? m_baseLayer->content()->width() : 0; -} - -int SurfaceCollection::baseContentHeight() -{ - // TODO: move this functionality out! - return m_baseLayer ? m_baseLayer->content()->height() : 0; -} - -void SurfaceCollection::updateScrollableLayer(int layerId, int x, int y) -{ - if (m_compositedRoot) { - LayerAndroid* layer = m_compositedRoot->findById(layerId); - if (layer && layer->contentIsScrollable()) - static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y); - } -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp deleted file mode 100644 index afa2014..0000000 --- a/Source/WebCore/platform/graphics/android/TiledPage.cpp +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "TiledPage" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "TiledPage.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidLog.h" -#include "GLUtils.h" -#include "IntRect.h" -#include "PaintTileOperation.h" -#include "SkPaint.h" -#include "SkPaintFlagsDrawFilter.h" -#include "TilesManager.h" - -namespace WebCore { - -using namespace android; - -TiledPage::TiledPage(int id, GLWebViewState* state) - : m_baseTiles(0) - , m_baseTileSize(0) - , m_id(id) - , m_scale(1) - , m_invScale(1) - , m_glWebViewState(state) - , m_prepare(false) - , m_isPrefetchPage(false) - , m_willDraw(false) -{ - m_baseTiles = new BaseTile[TilesManager::getMaxTextureAllocation() + 1]; -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("TiledPage"); -#endif -} - -void TiledPage::updateBaseTileSize() -{ - // This value must be at least 1 greater than the max number of allowed - // textures. This is because prepare() asks for a tile before it reserves - // a texture for that tile. If all textures are currently in use by the - // page then there will be no available tile and having the extra tile - // ensures that this does not happen. After claiming the extra tile the call - // to reserveTexture() will cause some other tile in the page to lose it's - // texture and become available, thus ensuring that we always have at least - // one tile that is available. - int baseTileSize = TilesManager::instance()->maxTextureCount() + 1; - if (baseTileSize > m_baseTileSize) - m_baseTileSize = baseTileSize; -} - -TiledPage::~TiledPage() -{ - TilesManager* tilesManager = TilesManager::instance(); - // In order to delete the page we must ensure that none of its BaseTiles are - // currently painting or scheduled to be painted by the TextureGenerator - tilesManager->removeOperationsForPage(this); - // Discard the transfer queue after the removal operation to make sure - // no tiles for this page will be left in the transfer queue. - tilesManager->transferQueue()->setPendingDiscardWithLock(); - delete[] m_baseTiles; -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("TiledPage"); -#endif -} - -BaseTile* TiledPage::getBaseTile(int x, int y) const -{ - // TODO: replace loop over array with HashMap indexing - for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tile.x() == x && tile.y() == y) - return &tile; - } - return 0; -} - -void TiledPage::discardTextures() -{ - for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - tile.discardTextures(); - } - return; -} - -void TiledPage::invalidateRect(const IntRect& inval) -{ -#ifdef DEBUG - // Given the current scale level we need to mark the appropriate tiles as dirty - const float invTileContentWidth = m_scale / TilesManager::tileWidth(); - const float invTileContentHeight = m_scale / TilesManager::tileHeight(); - - const int firstDirtyTileX = static_cast<int>(floorf(inval.x() * invTileContentWidth)); - const int firstDirtyTileY = static_cast<int>(floorf(inval.y() * invTileContentHeight)); - const int lastDirtyTileX = static_cast<int>(ceilf(inval.maxX() * invTileContentWidth)); - const int lastDirtyTileY = static_cast<int>(ceilf(inval.maxY() * invTileContentHeight)); - - ALOGV("Marking X %d-%d and Y %d-%d dirty", - firstDirtyTileX, lastDirtyTileX, firstDirtyTileY, lastDirtyTileY); -#endif - // We defer marking the tile as dirty until the next time we need to prepare - // to draw. - m_invalRegion.op(inval.x(), inval.y(), inval.maxX(), inval.maxY(), SkRegion::kUnion_Op); -} - -void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds) -{ - for (int i = 0; i < tilesInRow; i++) { - int x = firstTileX; - - // If we are goingLeft, we want to schedule the tiles starting from the - // right (and to the left if not). This is because tiles are appended to - // the list and the texture uploader goes through the set front to back. - if (goingLeft) - x += (tilesInRow - 1) - i; - else - x += i; - - BaseTile* currentTile = 0; - BaseTile* availableTile = 0; - for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tile.x() == x && tile.y() == y) { - currentTile = &tile; - break; - } - - if (!availableTile || (tile.drawCount() < availableTile->drawCount())) - availableTile = &tile; - } - - if (!currentTile && availableTile) { - ALOGV("STEALING tile %d, %d (draw count %llu) for tile %d, %d", - availableTile->x(), availableTile->y(), availableTile->drawCount(), x, y); - availableTile->discardTextures(); // don't wait for textures to be stolen - currentTile = availableTile; - } - - if (!currentTile) { - ALOGV("ERROR: No tile available for tile %d %d", x, y); - } - - if (currentTile) { - currentTile->setGLWebViewState(m_glWebViewState); - currentTile->setPage(this); - - currentTile->setContents(x, y, m_scale); - - // TODO: move below (which is largely the same for layers / tiled - // page) into prepare() function - - // ensure there is a texture associated with the tile and then check to - // see if the texture is dirty and in need of repainting - if (currentTile->isDirty() || !currentTile->frontTexture()) - currentTile->reserveTexture(); - if (currentTile->backTexture() - && currentTile->isDirty() - && !currentTile->isRepaintPending()) { - PaintTileOperation *operation = new PaintTileOperation(currentTile, this); - TilesManager::instance()->scheduleOperation(operation); - } - } - } -} - -void TiledPage::updateTileDirtiness() -{ - if (!m_glWebViewState || m_invalRegion.isEmpty()) - return; - - for (int x = 0; x < m_baseTileSize; x++) - m_baseTiles[x].markAsDirty(m_invalRegion); - - // clear the invalidated region as all tiles within that region have now - // been marked as dirty. - m_invalRegion.setEmpty(); -} - -void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds, PrepareBounds bounds) -{ - if (!m_glWebViewState) - return; - - TilesManager::instance()->gatherTextures(); - m_scrollingDown = goingDown; - - int firstTileX = tileBounds.fLeft; - int firstTileY = tileBounds.fTop; - int nbTilesWidth = tileBounds.width(); - int nbTilesHeight = tileBounds.height(); - - if (bounds == ExpandedBounds) { - // prepare tiles outside of the visible bounds - int expandX = m_glWebViewState->expandedTileBoundsX(); - int expandY = m_glWebViewState->expandedTileBoundsY(); - - firstTileX -= expandX; - nbTilesWidth += expandX * 2; - - firstTileY -= expandY; - nbTilesHeight += expandY * 2; - } - - // crop the tile bounds in each dimension to the larger of the base layer or viewport - float maxBaseX = m_glWebViewState->baseContentWidth() * m_scale / TilesManager::tileWidth(); - float maxBaseY = m_glWebViewState->baseContentHeight() * m_scale / TilesManager::tileHeight(); - int maxX = std::max(static_cast<int>(ceilf(maxBaseX)), - m_glWebViewState->viewportTileBounds().width()); - int maxY = std::max(static_cast<int>(ceilf(maxBaseY)), - m_glWebViewState->viewportTileBounds().height()); - - // adjust perimeter to not go outside cropped region - if (firstTileX < 0) { - nbTilesWidth += firstTileX; - firstTileX = 0; - } - if (firstTileY < 0) { - nbTilesHeight += firstTileY; - firstTileY = 0; - } - nbTilesWidth = std::min(nbTilesWidth, maxX - firstTileX + 1); - nbTilesHeight = std::min(nbTilesHeight, maxY - firstTileY + 1); - - // check against corrupted scale values giving bad height/width (use float to avoid overflow) - float numTiles = static_cast<float>(nbTilesHeight) * static_cast<float>(nbTilesWidth); - if (numTiles > TilesManager::getMaxTextureAllocation() || nbTilesHeight < 1 || nbTilesWidth < 1) - { - ALOGE("ERROR: We don't have enough tiles for this page!" - " nbTilesHeight %d nbTilesWidth %d", nbTilesHeight, nbTilesWidth); - return; - } - for (int i = 0; i < nbTilesHeight; i++) - prepareRow(goingLeft, nbTilesWidth, firstTileX, firstTileY + i, tileBounds); - - m_prepare = true; -} - -bool TiledPage::hasMissingContent(const SkIRect& tileBounds) -{ - int neededTiles = tileBounds.width() * tileBounds.height(); - for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tileBounds.contains(tile.x(), tile.y())) { - if (tile.frontTexture()) - neededTiles--; - } - } - return neededTiles > 0; -} - -bool TiledPage::isReady(const SkIRect& tileBounds) -{ - int neededTiles = tileBounds.width() * tileBounds.height(); - ALOGV("tiled page %p needs %d ready tiles", this, neededTiles); - for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tileBounds.contains(tile.x(), tile.y())) { - if (tile.isTileReady()) - neededTiles--; - } - } - ALOGV("tiled page %p still needs %d ready tiles", this, neededTiles); - return neededTiles == 0; -} - -bool TiledPage::swapBuffersIfReady(const SkIRect& tileBounds, float scale) -{ - if (!m_glWebViewState) - return false; - - if (!m_invalRegion.isEmpty() && !m_prepare) - return false; - - if (m_scale != scale) - return false; - - int swaps = 0; - bool fullSwap = true; - for (int x = tileBounds.fLeft; x < tileBounds.fRight; x++) { - for (int y = tileBounds.fTop; y < tileBounds.fBottom; y++) { - BaseTile* t = getBaseTile(x, y); - if (!t || !t->isTileReady()) - fullSwap = false; - } - } - - // swap every tile on page (even if off screen) - for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tile.swapTexturesIfNeeded()) - swaps++; - } - - ALOGV("%p greedy swapped %d textures, returning %d", this, swaps, fullSwap); - return fullSwap; -} - -void TiledPage::prepareForDrawGL(float opacity, const SkIRect& tileBounds) -{ - m_willDraw = true; - m_opacity = opacity; - m_tileBounds = tileBounds; -} - -void TiledPage::drawGL() -{ - if (!m_glWebViewState || m_opacity == 0 || !m_willDraw) - return; - - const float tileWidth = TilesManager::tileWidth() * m_invScale; - const float tileHeight = TilesManager::tileHeight() * m_invScale; - - for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - bool tileInView = m_tileBounds.contains(tile.x(), tile.y()); - if (tileInView) { - SkRect rect; - rect.fLeft = tile.x() * tileWidth; - rect.fTop = tile.y() * tileHeight; - rect.fRight = rect.fLeft + tileWidth; - rect.fBottom = rect.fTop + tileHeight; - - tile.drawGL(m_opacity, rect, m_scale, 0); - } - - TilesManager::instance()->getProfiler()->nextTile(tile, m_invScale, tileInView); - } - m_willDraw = false; // don't redraw until re-prepared -} - -bool TiledPage::paint(BaseTile* tile, SkCanvas* canvas) -{ - static SkPaintFlagsDrawFilter prefetchFilter(SkPaint::kAllFlags, - SkPaint::kAntiAlias_Flag); - - if (!m_glWebViewState) - return false; - - if (isPrefetchPage()) - canvas->setDrawFilter(&prefetchFilter); - - m_glWebViewState->paintBaseLayerContent(canvas); - return true; -} - -TiledPage* TiledPage::sibling() -{ - if (!m_glWebViewState) - return 0; - return m_glWebViewState->sibling(this); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/TiledPage.h b/Source/WebCore/platform/graphics/android/TiledPage.h deleted file mode 100644 index 5587618..0000000 --- a/Source/WebCore/platform/graphics/android/TiledPage.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TiledPage_h -#define TiledPage_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "BaseTile.h" -#include "SkCanvas.h" -#include "SkRegion.h" - -#include "TilePainter.h" - -namespace WebCore { - -class GLWebViewState; -class IntRect; - -/** - * The TiledPage represents a map of BaseTiles covering the viewport. Each - * GLWebViewState contains two TiledPages, one to display the page at the - * current scale factor, and another in the background that we use to paint the - * page at a different scale factor. For instance, when we zoom using one - * TiledPage its tiles are scaled in hardware and therefore are subject to a - * loss of quality. To address this when the user finishes zooming we paint the - * background TilePage at the new scale factor. When the background TilePage is - * ready, we swap it with the currently displaying TiledPage. - */ -class TiledPage : public TilePainter { -public: - enum PrepareBounds { - ExpandedBounds = 0, - VisibleBounds = 1 - }; - - TiledPage(int id, GLWebViewState* state); - ~TiledPage(); - - // returns the other TiledPage who shares the same GLWebViewState - TiledPage* sibling(); - - // prepare the page for display on the screen - void prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds, PrepareBounds bounds); - - // update tiles with inval information - void updateTileDirtiness(); - - // returns true if the page can't draw the entire region (may still be stale) - bool hasMissingContent(const SkIRect& tileBounds); - - bool isReady(const SkIRect& tileBounds); - - // swap 'buffers' by swapping each modified texture - bool swapBuffersIfReady(const SkIRect& tileBounds, float scale); - // save the opacity and bounds to be drawn in drawGL() - void prepareForDrawGL(float opacity, const SkIRect& tileBounds); - // draw the page on the screen - void drawGL(); - - // TilePainter implementation - // used by individual tiles to generate the bitmap for their tile - bool paint(BaseTile* tile, SkCanvas* canvas); - - // used by individual tiles to get the information about the current picture - GLWebViewState* glWebViewState() { return m_glWebViewState; } - - float scale() const { return m_scale; } - - //TODO: clear all textures if this is called with a new value - void setScale(float scale) { m_scale = scale; m_invScale = 1 / scale; } - - void invalidateRect(const IntRect& invalRect); - void discardTextures(); - void updateBaseTileSize(); - bool scrollingDown() { return m_scrollingDown; } - bool isPrefetchPage() { return m_isPrefetchPage; } - void setIsPrefetchPage(bool isPrefetch) { m_isPrefetchPage = isPrefetch; } - -private: - void prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds); - - BaseTile* getBaseTile(int x, int y) const; - - // array of tiles used to compose a page. The tiles are allocated in the - // constructor to prevent them from potentially being allocated on the stack - BaseTile* m_baseTiles; - // stores the number of tiles in the m_baseTiles array. This enables us to - // quickly iterate over the array without have to check it's size - int m_baseTileSize; - int m_id; - float m_scale; - float m_invScale; - GLWebViewState* m_glWebViewState; - - - SkRegion m_invalRegion; // in content coordinates - bool m_prepare; - bool m_scrollingDown; - bool m_isPrefetchPage; - - // info saved in prepare, used in drawGL() - bool m_willDraw; - SkIRect m_tileBounds; - float m_opacity; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // TiledPage_h diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp deleted file mode 100644 index 039e28c..0000000 --- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "TiledTexture" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "TiledTexture.h" - -#include "AndroidLog.h" -#include "PaintTileOperation.h" -#include "SkCanvas.h" -#include "SkPicture.h" -#include "TilesManager.h" - -#include <wtf/CurrentTime.h> - -namespace WebCore { - -TiledTexture::~TiledTexture() -{ -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("TiledTexture"); -#endif - removeTiles(); -} - -bool TiledTexture::isReady() -{ - bool tilesAllReady = true; - bool tilesVisible = false; - for (unsigned int i = 0; i < m_tiles.size(); i++) { - BaseTile* tile = m_tiles[i]; - if (tile->isTileVisible(m_area)) { - tilesVisible = true; - if (!tile->isTileReady()) { - tilesAllReady = false; - break; - } - } - } - // For now, if no textures are available, consider ourselves as ready - // in order to unblock the zooming process. - // FIXME: have a better system -- maybe keeping the last scale factor - // able to fully render everything - ALOGV("TT %p, ready %d, visible %d, texturesRemain %d", - this, tilesAllReady, tilesVisible, - TilesManager::instance()->layerTexturesRemain()); - - return !TilesManager::instance()->layerTexturesRemain() - || !tilesVisible || tilesAllReady; -} - -void TiledTexture::swapTiles() -{ - int swaps = 0; - for (unsigned int i = 0; i < m_tiles.size(); i++) - if (m_tiles[i]->swapTexturesIfNeeded()) - swaps++; - ALOGV("TT %p swapping, swaps = %d", this, swaps); -} - -IntRect TiledTexture::computeTilesArea(const IntRect& contentArea, float scale) -{ - IntRect computedArea; - IntRect area(contentArea.x() * scale, - contentArea.y() * scale, - ceilf(contentArea.width() * scale), - ceilf(contentArea.height() * scale)); - - ALOGV("TT %p prepare, scale %f, area %d x %d", this, scale, area.width(), area.height()); - - if (area.width() == 0 && area.height() == 0) { - computedArea.setWidth(0); - computedArea.setHeight(0); - return computedArea; - } - - int tileWidth = TilesManager::instance()->layerTileWidth(); - int tileHeight = TilesManager::instance()->layerTileHeight(); - - computedArea.setX(area.x() / tileWidth); - computedArea.setY(area.y() / tileHeight); - float right = (area.x() + area.width()) / (float) tileWidth; - float bottom = (area.y() + area.height()) / (float) tileHeight; - computedArea.setWidth(ceilf(right) - computedArea.x()); - computedArea.setHeight(ceilf(bottom) - computedArea.y()); - return computedArea; -} - -void TiledTexture::prepareGL(GLWebViewState* state, float scale, - const IntRect& prepareArea, TilePainter* painter) -{ - // first, how many tiles do we need - m_area = computeTilesArea(prepareArea, scale); - if (m_area.isEmpty()) - return; - - ALOGV("prepare TiledTexture %p with scale %.2f, prepareArea " - " %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles", - this, scale, - prepareArea.x(), prepareArea.y(), - prepareArea.width(), prepareArea.height(), - m_area.x(), m_area.y(), - m_area.width(), m_area.height()); - - bool goingDown = m_prevTileY < m_area.y(); - m_prevTileY = m_area.y(); - - if (scale != m_scale) - TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(painter, scale)); - - m_scale = scale; - - // apply dirty region to affected tiles - if (!m_dirtyRegion.isEmpty()) { - for (unsigned int i = 0; i < m_tiles.size(); i++) - m_tiles[i]->markAsDirty(m_dirtyRegion); - m_dirtyRegion.setEmpty(); - } - - for (int i = 0; i < m_area.width(); i++) { - if (goingDown) { - for (int j = 0; j < m_area.height(); j++) - prepareTile(m_area.x() + i, m_area.y() + j, painter); - } else { - for (int j = m_area.height() - 1; j >= 0; j--) - prepareTile(m_area.x() + i, m_area.y() + j, painter); - } - } -} - -void TiledTexture::markAsDirty(const SkRegion& invalRegion) -{ - ALOGV("TT %p markAsDirty, current region empty %d, new empty %d", - this, m_dirtyRegion.isEmpty(), invalRegion.isEmpty()); - m_dirtyRegion.op(invalRegion, SkRegion::kUnion_Op); -} - -void TiledTexture::prepareTile(int x, int y, TilePainter* painter) -{ - BaseTile* tile = getTile(x, y); - if (!tile) { - tile = new BaseTile(true); - m_tiles.append(tile); - } - - ALOGV("preparing tile %p at %d, %d, painter is %p", tile, x, y, painter); - tile->setContents(x, y, m_scale); - - // TODO: move below (which is largely the same for layers / tiled page) into - // prepareGL() function - - if (tile->isDirty() || !tile->frontTexture()) - tile->reserveTexture(); - - if (tile->backTexture() && tile->isDirty() && !tile->isRepaintPending()) { - ALOGV("painting TT %p's tile %d %d for LG %p", this, x, y, painter); - PaintTileOperation *operation = new PaintTileOperation(tile, painter); - TilesManager::instance()->scheduleOperation(operation); - } -} - -BaseTile* TiledTexture::getTile(int x, int y) -{ - for (unsigned int i = 0; i <m_tiles.size(); i++) { - BaseTile* tile = m_tiles[i]; - if (tile->x() == x && tile->y() == y) - return tile; - } - return 0; -} - -int TiledTexture::nbTextures(IntRect& area, float scale) -{ - IntRect tileBounds = computeTilesArea(area, scale); - int numberTextures = tileBounds.width() * tileBounds.height(); - - // add the number of dirty tiles in the bounds, as they take up double - // textures for double buffering - for (unsigned int i = 0; i <m_tiles.size(); i++) { - BaseTile* tile = m_tiles[i]; - if (tile->isDirty() - && tile->x() >= tileBounds.x() && tile->x() <= tileBounds.maxX() - && tile->y() >= tileBounds.y() && tile->y() <= tileBounds.maxY()) - numberTextures++; - } - return numberTextures; -} - -bool TiledTexture::drawGL(const IntRect& visibleArea, float opacity, - const TransformationMatrix* transform) -{ - m_area = computeTilesArea(visibleArea, m_scale); - if (m_area.width() == 0 || m_area.height() == 0) - return false; - - float m_invScale = 1 / m_scale; - const float tileWidth = TilesManager::layerTileWidth() * m_invScale; - const float tileHeight = TilesManager::layerTileHeight() * m_invScale; - - int drawn = 0; - bool askRedraw = false; - for (unsigned int i = 0; i < m_tiles.size(); i++) { - BaseTile* tile = m_tiles[i]; - - if (tile->isTileVisible(m_area)) { - askRedraw |= !tile->isTileReady(); - SkRect rect; - rect.fLeft = tile->x() * tileWidth; - rect.fTop = tile->y() * tileHeight; - rect.fRight = rect.fLeft + tileWidth; - rect.fBottom = rect.fTop + tileHeight; - ALOGV("tile %p (layer tile: %d) %d,%d at scale %.2f vs %.2f [ready: %d] dirty: %d", - tile, tile->isLayerTile(), tile->x(), tile->y(), - tile->scale(), m_scale, tile->isTileReady(), tile->isDirty()); - tile->drawGL(opacity, rect, m_scale, transform); - if (tile->frontTexture()) - drawn++; - } - } - ALOGV("TT %p drew %d tiles, redraw due to notready %d, scale %f", - this, drawn, askRedraw, m_scale); - - // need to redraw if some visible tile wasn't ready - return askRedraw; -} - -void TiledTexture::removeTiles() -{ - for (unsigned int i = 0; i < m_tiles.size(); i++) { - delete m_tiles[i]; - } - m_tiles.clear(); -} - -void TiledTexture::discardTextures() -{ - ALOGV("TT %p discarding textures", this); - for (unsigned int i = 0; i < m_tiles.size(); i++) - m_tiles[i]->discardTextures(); -} - -bool TiledTexture::owns(BaseTileTexture* texture) -{ - for (unsigned int i = 0; i < m_tiles.size(); i++) { - BaseTile* tile = m_tiles[i]; - if (tile->frontTexture() == texture) - return true; - if (tile->backTexture() == texture) - return true; - } - return false; -} - -DualTiledTexture::DualTiledTexture() -{ - m_textureA = new TiledTexture(); - m_textureB = new TiledTexture(); - m_frontTexture = m_textureA; - m_backTexture = m_textureB; - m_scale = -1; - m_futureScale = -1; - m_zooming = false; -} - -DualTiledTexture::~DualTiledTexture() -{ - delete m_textureA; - delete m_textureB; -} - -void DualTiledTexture::prepareGL(GLWebViewState* state, bool allowZoom, - const IntRect& prepareArea, TilePainter* painter) -{ - // If we are zooming, we will use the previously used area, to prevent the - // frontTexture to try to allocate more tiles than what it has already - if (!m_zooming) - m_preZoomPrepareArea = prepareArea; - - float scale = state->scale(); - if (scale > 1 && !allowZoom) - scale = 1; - - if (m_scale == -1) { - m_scale = scale; - m_futureScale = scale; - } - - if (m_futureScale != scale) { - m_futureScale = scale; - m_zoomUpdateTime = WTF::currentTime() + DualTiledTexture::s_zoomUpdateDelay; - m_zooming = true; - } - - ALOGV("Prepare DTT %p with scale %.2f, m_scale %.2f, futureScale: %.2f, zooming: %d, f %p, b %p", - this, scale, m_scale, m_futureScale, m_zooming, - m_frontTexture, m_backTexture); - - if (m_scale > 0) - m_frontTexture->prepareGL(state, m_scale, m_preZoomPrepareArea, painter); - - // If we had a scheduled update - if (m_zooming && m_zoomUpdateTime < WTF::currentTime()) { - m_backTexture->prepareGL(state, m_futureScale, prepareArea, painter); - if (m_backTexture->isReady()) { - m_backTexture->swapTiles(); - swap(); - m_zooming = false; - } - } -} - -void DualTiledTexture::swap() -{ - m_frontTexture = m_frontTexture == m_textureA ? m_textureB : m_textureA; - m_backTexture = m_backTexture == m_textureA ? m_textureB : m_textureA; - m_scale = m_futureScale; - m_backTexture->discardTextures(); -} - -bool DualTiledTexture::drawGL(const IntRect& visibleArea, float opacity, - const TransformationMatrix* transform) -{ - bool needsRepaint = m_frontTexture->drawGL(visibleArea, opacity, transform); - needsRepaint |= m_zooming; - needsRepaint |= (m_scale <= 0); - return needsRepaint; -} - -void DualTiledTexture::markAsDirty(const SkRegion& dirtyArea) -{ - m_backTexture->markAsDirty(dirtyArea); - m_frontTexture->markAsDirty(dirtyArea); -} - -void DualTiledTexture::swapTiles() -{ - m_backTexture->swapTiles(); - m_frontTexture->swapTiles(); -} - -bool DualTiledTexture::owns(BaseTileTexture* texture) -{ - bool owns = m_textureA->owns(texture); - owns |= m_textureB->owns(texture); - return owns; -} - -void DualTiledTexture::computeTexturesAmount(TexturesResult* result, LayerAndroid* layer) -{ - // TODO: shouldn't use layer, as this DTT may paint multiple layers - if (!layer) - return; - - IntRect unclippedArea = layer->unclippedArea(); - IntRect clippedVisibleArea = layer->visibleArea(); - - // get two numbers here: - // - textures needed for a clipped area - // - textures needed for an un-clipped area - TiledTexture* tiledTexture = m_zooming ? m_backTexture : m_frontTexture; - int nbTexturesUnclipped = tiledTexture->nbTextures(unclippedArea, m_scale); - int nbTexturesClipped = tiledTexture->nbTextures(clippedVisibleArea, m_scale); - - // Set kFixedLayers level - if (layer->isPositionFixed()) - result->fixed += nbTexturesClipped; - - // Set kScrollableAndFixedLayers level - if (layer->contentIsScrollable() - || layer->isPositionFixed()) - result->scrollable += nbTexturesClipped; - - // Set kClippedTextures level - result->clipped += nbTexturesClipped; - - // Set kAllTextures level - if (layer->contentIsScrollable()) - result->full += nbTexturesClipped; - else - result->full += nbTexturesUnclipped; -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.h b/Source/WebCore/platform/graphics/android/TiledTexture.h deleted file mode 100644 index cf7c77c..0000000 --- a/Source/WebCore/platform/graphics/android/TiledTexture.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TiledTexture_h -#define TiledTexture_h - -#include "BaseTile.h" -#include "BaseTileTexture.h" -#include "ClassTracker.h" -#include "IntRect.h" -#include "LayerAndroid.h" -#include "SkRefCnt.h" -#include "SkRegion.h" -#include "TextureOwner.h" -#include "TilePainter.h" - -class SkCanvas; - -namespace WebCore { - -class TiledTexture { -public: - TiledTexture() - : m_prevTileX(0) - , m_prevTileY(0) - , m_scale(1) - , m_swapWhateverIsReady(false) - { - m_dirtyRegion.setEmpty(); -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("TiledTexture"); -#endif - } - - virtual ~TiledTexture(); - - IntRect computeTilesArea(const IntRect& contentArea, float scale); - - void prepareGL(GLWebViewState* state, float scale, - const IntRect& prepareArea, TilePainter* painter); - void swapTiles(); - bool drawGL(const IntRect& visibleArea, float opacity, const TransformationMatrix* transform); - - void prepareTile(int x, int y, TilePainter* painter); - void markAsDirty(const SkRegion& dirtyArea); - - BaseTile* getTile(int x, int y); - - void removeTiles(); - void discardTextures(); - bool owns(BaseTileTexture* texture); - - float scale() { return m_scale; } - bool isReady(); - - int nbTextures(IntRect& area, float scale); - -private: - bool tileIsVisible(BaseTile* tile); - - Vector<BaseTile*> m_tiles; - - // tile coordinates in viewport, set in prepareGL() - IntRect m_area; - - SkRegion m_dirtyRegion; - - int m_prevTileX; - int m_prevTileY; - float m_scale; - - bool m_swapWhateverIsReady; -}; - -class DualTiledTexture : public SkRefCnt { -// TODO: investigate webkit threadsafe ref counting -public: - DualTiledTexture(); - ~DualTiledTexture(); - void prepareGL(GLWebViewState* state, bool allowZoom, - const IntRect& prepareArea, TilePainter* painter); - void swapTiles(); - void swap(); - bool drawGL(const IntRect& visibleArea, float opacity, const TransformationMatrix* transform); - void markAsDirty(const SkRegion& dirtyArea); - bool owns(BaseTileTexture* texture); - void computeTexturesAmount(TexturesResult* result, LayerAndroid* layer); - void discardTextures() - { - m_textureA->discardTextures(); - m_textureB->discardTextures(); - } - bool isReady() - { - return !m_zooming && m_frontTexture->isReady(); - } - - int nbTextures(IntRect& area, float scale) - { - // TODO: consider the zooming case for the backTexture - if (!m_frontTexture) - return 0; - return m_frontTexture->nbTextures(area, scale); - } - -private: - // Delay before we schedule a new tile at the new scale factor - static const double s_zoomUpdateDelay = 0.2; // 200 ms - - TiledTexture* m_frontTexture; - TiledTexture* m_backTexture; - TiledTexture* m_textureA; - TiledTexture* m_textureB; - float m_scale; - float m_futureScale; - double m_zoomUpdateTime; - bool m_zooming; - IntRect m_preZoomPrepareArea; -}; - -} // namespace WebCore - -#endif // TiledTexture_h diff --git a/Source/WebCore/platform/graphics/android/ZoomManager.cpp b/Source/WebCore/platform/graphics/android/ZoomManager.cpp deleted file mode 100644 index 35100ae..0000000 --- a/Source/WebCore/platform/graphics/android/ZoomManager.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_TAG "ZoomManager" -#define LOG_NDEBUG 1 - -#include "config.h" -#include "ZoomManager.h" - -#include "AndroidLog.h" -#include "GLWebViewState.h" - -#if USE(ACCELERATED_COMPOSITING) - -namespace WebCore { - -using namespace android; - -ZoomManager::ZoomManager(GLWebViewState* state) - : m_scaleRequestState(kNoScaleRequest) - , m_currentScale(-1) - , m_futureScale(-1) - , m_layersScale(-1) - , m_updateTime(-1) - , m_transitionTime(-1) - , m_glWebViewState(state) -{ -} - -void ZoomManager::scheduleUpdate(const double& currentTime, - const SkIRect& viewport, float scale) -{ - // if no update time, set it - if (updateTime() == -1) { - m_scaleRequestState = kWillScheduleRequest; - setUpdateTime(currentTime + s_updateInitialDelay); - setFutureScale(scale); - m_glWebViewState->setFutureViewport(viewport); - return; - } - - if (currentTime < updateTime()) - return; - - // we reached the scheduled update time, check if we can update - if (futureScale() == scale) { - // we are still with the previous scale, let's go - // with the update - m_scaleRequestState = kRequestNewScale; - setUpdateTime(-1); - } else { - // we reached the update time, but the planned update was for - // a different scale factor -- meaning the user is still probably - // in the process of zooming. Let's push the update time a bit. - setUpdateTime(currentTime + s_updateDelay); - setFutureScale(scale); - m_glWebViewState->setFutureViewport(viewport); - } -} - -double ZoomManager::zoomInTransitionTime(double currentTime) -{ - if (m_transitionTime == -1) - m_transitionTime = currentTime + s_zoomInTransitionDelay; - return m_transitionTime; -} - -double ZoomManager::zoomOutTransitionTime(double currentTime) -{ - if (m_transitionTime == -1) - m_transitionTime = currentTime + s_zoomOutTransitionDelay; - return m_transitionTime; -} - -float ZoomManager::zoomInTransparency(double currentTime) -{ - float t = zoomInTransitionTime(currentTime) - currentTime; - t *= s_invZoomInTransitionDelay; - return fmin(1, fmax(0, t)); -} - -float ZoomManager::zoomOutTransparency(double currentTime) -{ - float t = zoomOutTransitionTime(currentTime) - currentTime; - t *= s_invZoomOutTransitionDelay; - return fmin(1, fmax(0, t)); -} - -bool ZoomManager::swapPages() -{ - bool reset = m_scaleRequestState != kNoScaleRequest; - m_scaleRequestState = kNoScaleRequest; - return reset; -} - -void ZoomManager::processNewScale(double currentTime, float scale) -{ - m_prepareNextTiledPage = false; - m_zooming = false; - const SkIRect& viewportTileBounds = m_glWebViewState->viewportTileBounds(); - - if (scale == m_currentScale - || m_glWebViewState->preZoomBounds().isEmpty()) - m_glWebViewState->setPreZoomBounds(viewportTileBounds); - - // If we have a different scale than the current one, we have to - // decide what to do. The current behaviour is to delay an update, - // so that we do not slow down zooming unnecessarily. - if ((m_currentScale != scale - && (m_scaleRequestState == ZoomManager::kNoScaleRequest - || m_futureScale != scale)) - || m_scaleRequestState == ZoomManager::kWillScheduleRequest) { - - // schedule the new Zoom request - scheduleUpdate(currentTime, viewportTileBounds, scale); - - // If it's a new request, we will have to prepare the page. - if (m_scaleRequestState == ZoomManager::kRequestNewScale) - m_prepareNextTiledPage = true; - } - - // If the viewport has changed since we scheduled the request, we also need - // to prepare. - if ((m_scaleRequestState == ZoomManager::kRequestNewScale - || m_scaleRequestState == ZoomManager::kReceivedNewScale) - && m_glWebViewState->futureViewport() != viewportTileBounds) - m_prepareNextTiledPage = true; - - // Checking if we are zooming... - if (m_scaleRequestState != ZoomManager::kNoScaleRequest) { - m_prepareNextTiledPage = true; - m_zooming = true; - } - - // Get the current scale; if we are zooming, we don't change the scale - // factor immediately (see BaseLayerAndroid::drawBasePictureInGL()), but - // we change the scaleRequestState. When the state is kReceivedNewScale - // (see setReceivedRequest()), we can use the future scale instead of - // the current scale to request new textures. After a transition time, - // the scaleRequestState will be reset and the current scale will be set - // to the future scale. - m_layersScale = m_currentScale; -} - -void ZoomManager::processTransition(double currentTime, float scale, - bool* doSwap, float* backPageTransparency, - float* frontPageTransparency) -{ - if (scale < m_currentScale) - *backPageTransparency = 1 - zoomOutTransparency(currentTime); - else - *frontPageTransparency = zoomInTransparency(currentTime); - - // The transition between the two page is finished - if (currentTime > transitionTime(currentTime, scale)) { - resetTransitionTime(); - *doSwap = true; - } -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/ZoomManager.h b/Source/WebCore/platform/graphics/android/ZoomManager.h deleted file mode 100644 index dd04c5d..0000000 --- a/Source/WebCore/platform/graphics/android/ZoomManager.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2011, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ZoomManager_h -#define ZoomManager_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "SkRect.h" - -namespace WebCore { - -class GLWebViewState; - -class ZoomManager { -public: - enum GLScaleStates { - kNoScaleRequest = 0, - kWillScheduleRequest = 1, - kRequestNewScale = 2, - kReceivedNewScale = 3 - }; - typedef int32_t GLScaleState; - - ZoomManager(GLWebViewState* state); - - void scheduleUpdate(const double& currentTime, const SkIRect& viewport, float scale); - - GLScaleState scaleRequestState() const { return m_scaleRequestState; } - void setScaleRequestState(GLScaleState state) { m_scaleRequestState = state; } - float currentScale() const { return m_currentScale; } - void setCurrentScale(float scale) { m_currentScale = scale; } - float futureScale() const { return m_futureScale; } - void setFutureScale(float scale) { m_futureScale = scale; } - float layersScale() const { return m_layersScale; } - double zoomInTransitionTime(double currentTime); - double zoomOutTransitionTime(double currentTime); - float zoomInTransparency(double currentTime); - float zoomOutTransparency(double currentTime); - void resetTransitionTime() { m_transitionTime = -1; } - double updateTime() const { return m_updateTime; } - void setUpdateTime(double value) { m_updateTime = value; } - - // state used by BaseLayerAndroid - bool needPrepareNextTiledPage() { return m_prepareNextTiledPage; } - bool zooming() { return m_zooming; } - - bool didFireRequest() { return m_scaleRequestState == ZoomManager::kRequestNewScale; } - void setReceivedRequest() { - m_scaleRequestState = ZoomManager::kReceivedNewScale; - m_layersScale = m_futureScale; - } - bool didReceivedRequest() { return m_scaleRequestState == ZoomManager::kReceivedNewScale; } - - double transitionTime(double currentTime, float scale) { - return (scale < m_currentScale) ? zoomOutTransitionTime(currentTime) - : zoomInTransitionTime(currentTime); - } - void processTransition(double currentTime, float scale, bool* doSwap, - float* backPageTransparency, float* frontPageTransparency); - - bool swapPages(); - - void processNewScale(double currentTime, float scale); - -private: - // Delay between scheduling a new page when the scale - // factor changes (i.e. zooming in or out) - static const double s_updateInitialDelay = 0.3; // 300 ms - // If the scale factor continued to change and we completed - // the original delay, we push back the update by this value - static const double s_updateDelay = 0.1; // 100 ms - - // Delay for the transition between the two pages - static const double s_zoomInTransitionDelay = 0.1; // 100 ms - static const double s_invZoomInTransitionDelay = 10; - static const double s_zoomOutTransitionDelay = 0.2; // 200 ms - static const double s_invZoomOutTransitionDelay = 5; - - GLScaleState m_scaleRequestState; - float m_currentScale; - float m_futureScale; - float m_layersScale; - double m_updateTime; - double m_transitionTime; - - bool m_prepareNextTiledPage; - bool m_zooming; - - GLWebViewState* m_glWebViewState; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // ZoomManager_h diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp new file mode 100644 index 0000000..f2d1400 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp @@ -0,0 +1,663 @@ +/* + * Copyright 2006, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "config.h" +#include "GraphicsContext.h" + +#include "AffineTransform.h" +#include "Font.h" +#include "Gradient.h" +#include "NotImplemented.h" +#include "Path.h" +#include "Pattern.h" +#include "PlatformGraphicsContext.h" +#include "PlatformGraphicsContextSkia.h" +#include "SkBitmapRef.h" +#include "SkBlurDrawLooper.h" +#include "SkBlurMaskFilter.h" +#include "SkCanvas.h" +#include "SkColorPriv.h" +#include "SkCornerPathEffect.h" +#include "SkDashPathEffect.h" +#include "SkDevice.h" +#include "SkGradientShader.h" +#include "SkPaint.h" +#include "SkString.h" +#include "SkiaUtils.h" +#include "TransformationMatrix.h" +#include "android_graphics.h" + +using namespace std; + +namespace WebCore { + +// This class just holds onto a PlatformContextSkia for GraphicsContext. +class GraphicsContextPlatformPrivate { + WTF_MAKE_NONCOPYABLE(GraphicsContextPlatformPrivate); +public: + GraphicsContextPlatformPrivate(PlatformGraphicsContext* platformContext) + : m_context(platformContext) { } + + PlatformGraphicsContext* context() { return m_context; } + +private: + // Non-owning pointer to the PlatformContext. + PlatformGraphicsContext* m_context; +}; + +static void syncPlatformContext(GraphicsContext* gc) +{ + // Stroke and fill sometimes reference each other, so always + // sync them both to make sure our state is consistent. + + PlatformGraphicsContext* pgc = gc->platformContext(); + Gradient* grad = gc->state().fillGradient.get(); + Pattern* pat = gc->state().fillPattern.get(); + + if (grad) + pgc->setFillShader(grad->platformGradient()); + else if (pat) + pgc->setFillShader(pat->platformPattern(AffineTransform())); + else + pgc->setFillColor(gc->state().fillColor); + + grad = gc->state().strokeGradient.get(); + pat = gc->state().strokePattern.get(); + + if (grad) + pgc->setStrokeShader(grad->platformGradient()); + else if (pat) + pgc->setStrokeShader(pat->platformPattern(AffineTransform())); + else + pgc->setStrokeColor(gc->state().strokeColor); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height) +{ + PlatformGraphicsContextSkia* pgc = new PlatformGraphicsContextSkia(new SkCanvas, true); + + SkBitmap bitmap; + + bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); + bitmap.allocPixels(); + bitmap.eraseColor(0); + pgc->getCanvas()->setBitmapDevice(bitmap); + + GraphicsContext* ctx = new GraphicsContext(pgc); + return ctx; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +void GraphicsContext::platformInit(PlatformGraphicsContext* gc) +{ + if (gc) + gc->setGraphicsContext(this); + m_data = new GraphicsContextPlatformPrivate(gc); + setPaintingDisabled(!gc || gc->isPaintingDisabled()); +} + +void GraphicsContext::platformDestroy() +{ + delete m_data; +} + +void GraphicsContext::savePlatformState() +{ + if (paintingDisabled()) + return; + platformContext()->save(); +} + +void GraphicsContext::restorePlatformState() +{ + if (paintingDisabled()) + return; + platformContext()->restore(); +} + +bool GraphicsContext::willFill() const +{ + return m_state.fillColor.rgb(); +} + +bool GraphicsContext::willStroke() const +{ + return m_state.strokeColor.rgb(); +} + +// Draws a filled rectangle with a stroked border. +void GraphicsContext::drawRect(const IntRect& rect) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->drawRect(rect); +} + +// This is only used to draw borders. +void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->drawLine(point1, point2); +} + +void GraphicsContext::drawLineForText(const FloatPoint& pt, float width, bool /* printing */) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->drawLineForText(pt, width); +} + +void GraphicsContext::drawLineForTextChecking(const FloatPoint& pt, float width, + TextCheckingLineStyle style) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->drawLineForTextChecking(pt, width, style); +} + +// This method is only used to draw the little circles used in lists. +void GraphicsContext::drawEllipse(const IntRect& rect) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->drawEllipse(rect); +} + +void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->strokeArc(r, startAngle, angleSpan); +} + +void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, + bool shouldAntialias) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->drawConvexPolygon(numPoints, points, shouldAntialias); +} + +void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, + const IntSize& bottomLeft, const IntSize& bottomRight, + const Color& color, ColorSpace colorSpace) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->fillRoundedRect(rect, topLeft, topRight, + bottomLeft, bottomRight, color, colorSpace); +} + +void GraphicsContext::fillRect(const FloatRect& rect) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->fillRect(rect); +} + +void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->fillRect(rect, color, colorSpace); +} + +void GraphicsContext::clip(const FloatRect& rect) +{ + if (paintingDisabled()) + return; + + platformContext()->clip(rect); +} + +void GraphicsContext::clip(const Path& path) +{ + if (paintingDisabled()) + return; + + platformContext()->clip(path); +} + +void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) +{ + if (paintingDisabled()) + return; + + platformContext()->addInnerRoundedRectClip(rect, thickness); +} + +void GraphicsContext::canvasClip(const Path& path) +{ + if (paintingDisabled()) + return; + + platformContext()->canvasClip(path); +} + +void GraphicsContext::clipOut(const IntRect& r) +{ + if (paintingDisabled()) + return; + + platformContext()->clipOut(r); +} + +#if ENABLE(SVG) +void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule) +{ + if (paintingDisabled()) + return; + + platformContext()->clipPath(pathToClip, clipRule); +} +#endif + +void GraphicsContext::clipOut(const Path& p) +{ + if (paintingDisabled()) + return; + + platformContext()->clipOut(p); +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +#if SVG_SUPPORT +KRenderingDeviceContext* GraphicsContext::createRenderingDeviceContext() +{ + return new KRenderingDeviceContextQuartz(platformContext()); +} +#endif + +void GraphicsContext::beginTransparencyLayer(float opacity) +{ + if (paintingDisabled()) + return; + + platformContext()->beginTransparencyLayer(opacity); +} + +void GraphicsContext::endTransparencyLayer() +{ + if (paintingDisabled()) + return; + + platformContext()->endTransparencyLayer(); +} + +/////////////////////////////////////////////////////////////////////////// + +void GraphicsContext::setupFillPaint(SkPaint* paint) +{ + if (paintingDisabled()) + return; + syncPlatformContext(this); + platformContext()->setupPaintFill(paint); +} + +void GraphicsContext::setupStrokePaint(SkPaint* paint) +{ + if (paintingDisabled()) + return; + syncPlatformContext(this); + platformContext()->setupPaintStroke(paint, 0); +} + +bool GraphicsContext::setupShadowPaint(SkPaint* paint, SkPoint* offset) +{ + if (paintingDisabled()) + return false; + syncPlatformContext(this); + return platformContext()->setupPaintShadow(paint, offset); +} + +void GraphicsContext::setPlatformStrokeColor(const Color& c, ColorSpace) +{ +} + +void GraphicsContext::setPlatformStrokeThickness(float f) +{ + if (paintingDisabled()) + return; + platformContext()->setStrokeThickness(f); +} + +void GraphicsContext::setPlatformStrokeStyle(StrokeStyle style) +{ + if (paintingDisabled()) + return; + platformContext()->setStrokeStyle(style); +} + +void GraphicsContext::setPlatformFillColor(const Color& c, ColorSpace) +{ +} + +void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const Color& color, ColorSpace) +{ + if (paintingDisabled()) + return; + + if (blur <= 0) + this->clearPlatformShadow(); + + SkColor c; + if (color.isValid()) + c = color.rgb(); + else + c = SkColorSetARGB(0xFF / 3, 0, 0, 0); // "std" Apple shadow color + platformContext()->setShadow(blur, size.width(), size.height(), c); +} + +void GraphicsContext::clearPlatformShadow() +{ + if (paintingDisabled()) + return; + + platformContext()->setShadow(0, 0, 0, 0); +} + +/////////////////////////////////////////////////////////////////////////////// + +void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->drawFocusRing(rects, width, offset, color); +} + +void GraphicsContext::drawFocusRing(const Path&, int, int, const Color&) +{ + // Do nothing, since we draw the focus ring independently. +} + +PlatformGraphicsContext* GraphicsContext::platformContext() const +{ + ASSERT(!paintingDisabled()); + return m_data->context(); +} + +void GraphicsContext::setMiterLimit(float limit) +{ + if (paintingDisabled()) + return; + platformContext()->setMiterLimit(limit); +} + +void GraphicsContext::setAlpha(float alpha) +{ + if (paintingDisabled()) + return; + platformContext()->setAlpha(alpha); +} + +void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op) +{ + if (paintingDisabled()) + return; + platformContext()->setCompositeOperation(op); +} + +void GraphicsContext::clearRect(const FloatRect& rect) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->clearRect(rect); +} + +void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->strokeRect(rect, lineWidth); +} + +void GraphicsContext::setLineCap(LineCap cap) +{ + if (paintingDisabled()) + return; + platformContext()->setLineCap(cap); +} + +#if ENABLE(SVG) +void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset) +{ + if (paintingDisabled()) + return; + + platformContext()->setLineDash(dashes, dashOffset); +} +#endif + +void GraphicsContext::setLineJoin(LineJoin join) +{ + if (paintingDisabled()) + return; + platformContext()->setLineJoin(join); +} + +void GraphicsContext::scale(const FloatSize& size) +{ + if (paintingDisabled()) + return; + platformContext()->scale(size); +} + +void GraphicsContext::rotate(float angleInRadians) +{ + if (paintingDisabled()) + return; + platformContext()->rotate(angleInRadians); +} + +void GraphicsContext::translate(float x, float y) +{ + if (paintingDisabled()) + return; + platformContext()->translate(x, y); +} + +void GraphicsContext::concatCTM(const AffineTransform& affine) +{ + if (paintingDisabled()) + return; + platformContext()->concatCTM(affine); +} + +// This is intended to round the rect to device pixels (through the CTM) +// and then invert the result back into source space, with the hope that when +// it is drawn (through the matrix), it will land in the "right" place (i.e. +// on pixel boundaries). + +// For android, we record this geometry once and then draw it though various +// scale factors as the user zooms, without re-recording. Thus this routine +// should just leave the original geometry alone. + +// If we instead draw into bitmap tiles, we should then perform this +// transform -> round -> inverse step. + +FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMode) +{ + return rect; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) +{ +// Appears to be PDF specific, so we ignore it +} + +void GraphicsContext::setPlatformShouldAntialias(bool useAA) +{ + if (paintingDisabled()) + return; + platformContext()->setShouldAntialias(useAA); +} + +void GraphicsContext::setPlatformFillGradient(Gradient* fillGradient) +{ +} + +void GraphicsContext::setPlatformFillPattern(Pattern* fillPattern) +{ +} + +void GraphicsContext::setPlatformStrokeGradient(Gradient* strokeGradient) +{ +} + +void GraphicsContext::setPlatformStrokePattern(Pattern* strokePattern) +{ +} + +AffineTransform GraphicsContext::getCTM() const +{ + if (paintingDisabled()) + return AffineTransform(); + const SkMatrix& m = platformContext()->getTotalMatrix(); + return AffineTransform(SkScalarToDouble(m.getScaleX()), // a + SkScalarToDouble(m.getSkewY()), // b + SkScalarToDouble(m.getSkewX()), // c + SkScalarToDouble(m.getScaleY()), // d + SkScalarToDouble(m.getTranslateX()), // e + SkScalarToDouble(m.getTranslateY())); // f +} + +void GraphicsContext::setCTM(const AffineTransform& transform) +{ + // The SkPicture mode of Skia does not support SkCanvas::setMatrix(), so we + // can not simply use that method here. We could calculate the transform + // required to achieve the desired matrix and use SkCanvas::concat(), but + // there's currently no need for this. + ASSERT_NOT_REACHED(); +} + +/////////////////////////////////////////////////////////////////////////////// + +void GraphicsContext::fillPath(const Path& pathToFill) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->fillPath(pathToFill, fillRule()); +} + +void GraphicsContext::strokePath(const Path& pathToStroke) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->strokePath(pathToStroke); +} + +InterpolationQuality GraphicsContext::imageInterpolationQuality() const +{ + notImplemented(); + return InterpolationDefault; +} + +void GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode) +{ +#if 0 + enum InterpolationQuality { + InterpolationDefault, + InterpolationNone, + InterpolationLow, + InterpolationMedium, + InterpolationHigh + }; +#endif + // TODO: record this, so we can know when to use bitmap-filtering when we draw + // ... not sure how meaningful this will be given our playback model. + + // Certainly safe to do nothing for the present. +} + +void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint*, + bool antialias) +{ + if (paintingDisabled()) + return; + + if (numPoints <= 1) + return; + + // FIXME: IMPLEMENT! +} + +void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, + const FloatPoint& point, int h, + const Color& backgroundColor, + ColorSpace colorSpace, int from, + int to, bool isActive) +{ + if (paintingDisabled()) + return; + + syncPlatformContext(this); + platformContext()->drawHighlightForText(font, run, point, h, backgroundColor, + colorSpace, from, to, isActive); +} + +} // namespace WebCore + +/////////////////////////////////////////////////////////////////////////////// + +SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc) +{ + return gc->platformContext()->getCanvas(); +} diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h new file mode 100644 index 0000000..927ff0a --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h @@ -0,0 +1,809 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GraphicsOperation_h +#define GraphicsOperation_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "Color.h" +#include "FloatRect.h" +#include "GlyphBuffer.h" +#include "Font.h" +#include "IntRect.h" +#include "PlatformGraphicsContext.h" +#include "PlatformGraphicsContextSkia.h" +#include "SkCanvas.h" +#include "SkShader.h" +#include "SkRefCnt.h" + +#include <utils/threads.h> +#include <wtf/text/CString.h> + +#define TYPE_CASE(type) case type: return #type; + +namespace WebCore { + +namespace GraphicsOperation { + +class Operation : public SkRefCnt { +public: + typedef enum { UndefinedOperation + // State management + , BeginTransparencyLayerOperation + , EndTransparencyLayerOperation + , SaveOperation + , RestoreOperation + // State setters + , SetAlphaOperation + , SetCompositeOpOperation + , SetFillColorOperation + , SetFillShaderOperation + , SetLineCapOperation + , SetLineDashOperation + , SetLineJoinOperation + , SetMiterLimitOperation + , SetShadowOperation + , SetShouldAntialiasOperation + , SetStrokeColorOperation + , SetStrokeShaderOperation + , SetStrokeStyleOperation + , SetStrokeThicknessOperation + // Paint setup + , SetupPaintFillOperation + , SetupPaintShadowOperation + , SetupPaintStrokeOperation + // Matrix operations + , ConcatCTMOperation + , ScaleOperation + , RotateOperation + , TranslateOperation + // Clipping + , InnerRoundedRectClipOperation + , ClipOperation + , ClipPathOperation + , ClipOutOperation + , ClearRectOperation + // Drawing + , DrawBitmapPatternOperation + , DrawBitmapRectOperation + , DrawEllipseOperation + , DrawLineOperation + , DrawLineForTextOperation + , DrawLineForTextCheckingOperation + , DrawRectOperation + , FillPathOperation + , FillRectOperation + , FillRoundedRectOperation + , StrokeArcOperation + , StrokePathOperation + , StrokeRectOperation + // Text + , DrawComplexTextOperation + , DrawTextOperation + } OperationType; + + virtual void apply(PlatformGraphicsContext* context) = 0; + virtual ~Operation() {} + virtual OperationType type() { return UndefinedOperation; } + virtual String parameters() { return ""; } + String name() + { + switch (type()) { + TYPE_CASE(UndefinedOperation) + // State management + TYPE_CASE(BeginTransparencyLayerOperation) + TYPE_CASE(EndTransparencyLayerOperation) + TYPE_CASE(SaveOperation) + TYPE_CASE(RestoreOperation) + // State setters + TYPE_CASE(SetAlphaOperation) + TYPE_CASE(SetCompositeOpOperation) + TYPE_CASE(SetFillColorOperation) + TYPE_CASE(SetFillShaderOperation) + TYPE_CASE(SetLineCapOperation) + TYPE_CASE(SetLineDashOperation) + TYPE_CASE(SetLineJoinOperation) + TYPE_CASE(SetMiterLimitOperation) + TYPE_CASE(SetShadowOperation) + TYPE_CASE(SetShouldAntialiasOperation) + TYPE_CASE(SetStrokeColorOperation) + TYPE_CASE(SetStrokeShaderOperation) + TYPE_CASE(SetStrokeStyleOperation) + TYPE_CASE(SetStrokeThicknessOperation) + // Paint setup + TYPE_CASE(SetupPaintFillOperation) + TYPE_CASE(SetupPaintShadowOperation) + TYPE_CASE(SetupPaintStrokeOperation) + // Matrix operations + TYPE_CASE(ConcatCTMOperation) + TYPE_CASE(ScaleOperation) + TYPE_CASE(RotateOperation) + TYPE_CASE(TranslateOperation) + // Clipping + TYPE_CASE(InnerRoundedRectClipOperation) + TYPE_CASE(ClipOperation) + TYPE_CASE(ClipPathOperation) + TYPE_CASE(ClipOutOperation) + TYPE_CASE(ClearRectOperation) + // Drawing + TYPE_CASE(DrawBitmapPatternOperation) + TYPE_CASE(DrawBitmapRectOperation) + TYPE_CASE(DrawEllipseOperation) + TYPE_CASE(DrawLineOperation) + TYPE_CASE(DrawLineForTextOperation) + TYPE_CASE(DrawLineForTextCheckingOperation) + TYPE_CASE(DrawRectOperation) + TYPE_CASE(FillPathOperation) + TYPE_CASE(FillRectOperation) + TYPE_CASE(FillRoundedRectOperation) + TYPE_CASE(StrokeArcOperation) + TYPE_CASE(StrokePathOperation) + TYPE_CASE(StrokeRectOperation) + // Text + TYPE_CASE(DrawComplexTextOperation) + TYPE_CASE(DrawTextOperation) + } + return "Undefined"; + } +}; + +//************************************** +// State management +//************************************** + +class BeginTransparencyLayer : public Operation { +public: + BeginTransparencyLayer(const float opacity) : m_opacity(opacity) {} + virtual void apply(PlatformGraphicsContext* context) { context->beginTransparencyLayer(m_opacity); } + virtual OperationType type() { return BeginTransparencyLayerOperation; } +private: + float m_opacity; +}; +class EndTransparencyLayer : public Operation { +public: + EndTransparencyLayer() {} + virtual void apply(PlatformGraphicsContext* context) { context->endTransparencyLayer(); } + virtual OperationType type() { return EndTransparencyLayerOperation; } +}; +class Save : public Operation { +public: + virtual void apply(PlatformGraphicsContext* context) { context->save(); } + virtual OperationType type() { return SaveOperation; } +}; +class Restore : public Operation { +public: + virtual void apply(PlatformGraphicsContext* context) { context->restore(); } + virtual OperationType type() { return RestoreOperation; } +}; + +//************************************** +// State setters +//************************************** + +class SetAlpha : public Operation { +public: + SetAlpha(const float alpha) : m_alpha(alpha) {} + virtual void apply(PlatformGraphicsContext* context) { context->setAlpha(m_alpha); } + virtual OperationType type() { return SetAlphaOperation; } +private: + float m_alpha; +}; + +class SetCompositeOperation : public Operation { +public: + SetCompositeOperation(CompositeOperator op) : m_operator(op) {} + virtual void apply(PlatformGraphicsContext* context) { + context->setCompositeOperation(m_operator); + } + virtual OperationType type() { return SetCompositeOpOperation; } +private: + CompositeOperator m_operator; +}; + +class SetFillColor : public Operation { +public: + SetFillColor(Color color) : m_color(color) {} + virtual void apply(PlatformGraphicsContext* context) { + context->setFillColor(m_color); + } + virtual OperationType type() { return SetFillColorOperation; } + virtual String parameters() { + return String::format("r: %d g: %d b: %d a: %d", + m_color.red(), + m_color.green(), + m_color.blue(), + m_color.alpha()); + } +private: + Color m_color; +}; + +class SetFillShader : public Operation { +public: + SetFillShader(SkShader* shader) : m_shader(shader) { + SkSafeRef(m_shader); + } + ~SetFillShader() { SkSafeUnref(m_shader); } + virtual void apply(PlatformGraphicsContext* context) { + context->setFillShader(m_shader); + } + virtual OperationType type() { return SetFillShaderOperation; } +private: + SkShader* m_shader; +}; + +class SetLineCap : public Operation { +public: + SetLineCap(LineCap cap) : m_cap(cap) {} + virtual void apply(PlatformGraphicsContext* context) { + context->setLineCap(m_cap); + } + virtual OperationType type() { return SetLineCapOperation; } +private: + LineCap m_cap; +}; + +class SetLineDash : public Operation { +public: + SetLineDash(const DashArray& dashes, float dashOffset) + : m_dashes(dashes), m_dashOffset(dashOffset) {} + virtual void apply(PlatformGraphicsContext* context) { + context->setLineDash(m_dashes, m_dashOffset); + } + virtual OperationType type() { return SetLineDashOperation; } +private: + DashArray m_dashes; + float m_dashOffset; +}; + +class SetLineJoin : public Operation { +public: + SetLineJoin(LineJoin join) : m_join(join) {} + virtual void apply(PlatformGraphicsContext* context) { + context->setLineJoin(m_join); + } + virtual OperationType type() { return SetLineJoinOperation; } +private: + LineJoin m_join; +}; + +class SetMiterLimit : public Operation { +public: + SetMiterLimit(float limit) : m_limit(limit) {} + virtual void apply(PlatformGraphicsContext* context) { + context->setMiterLimit(m_limit); + } + virtual OperationType type() { return SetMiterLimitOperation; } +private: + float m_limit; +}; + +class SetShadow : public Operation { +public: + SetShadow(int radius, int dx, int dy, SkColor c) + : m_radius(radius), m_dx(dx), m_dy(dy), m_color(c) {} + virtual void apply(PlatformGraphicsContext* context) { + context->setShadow(m_radius, m_dx, m_dy, m_color); + } + virtual OperationType type() { return SetShadowOperation; } +private: + int m_radius; + int m_dx; + int m_dy; + SkColor m_color; +}; + +class SetShouldAntialias : public Operation { +public: + SetShouldAntialias(bool useAA) : m_useAA(useAA) {} + virtual void apply(PlatformGraphicsContext* context) { + context->setShouldAntialias(m_useAA); + } + virtual OperationType type() { return SetShouldAntialiasOperation; } +private: + bool m_useAA; +}; + +class SetStrokeColor : public Operation { +public: + SetStrokeColor(const Color& c) : m_color(c) {} + virtual void apply(PlatformGraphicsContext* context) { + context->setStrokeColor(m_color); + } + virtual OperationType type() { return SetStrokeColorOperation; } +private: + Color m_color; +}; + +class SetStrokeShader : public Operation { +public: + SetStrokeShader(SkShader* strokeShader) : m_shader(strokeShader) { + SkSafeRef(m_shader); + } + ~SetStrokeShader() { SkSafeUnref(m_shader); } + virtual void apply(PlatformGraphicsContext* context) { + context->setStrokeShader(m_shader); + } + virtual OperationType type() { return SetStrokeShaderOperation; } +private: + SkShader* m_shader; +}; + +class SetStrokeStyle : public Operation { +public: + SetStrokeStyle(StrokeStyle style) : m_style(style) {} + virtual void apply(PlatformGraphicsContext* context) { + context->setStrokeStyle(m_style); + } + virtual OperationType type() { return SetStrokeStyleOperation; } +private: + StrokeStyle m_style; +}; + +class SetStrokeThickness : public Operation { +public: + SetStrokeThickness(float thickness) : m_thickness(thickness) {} + virtual void apply(PlatformGraphicsContext* context) { + context->setStrokeThickness(m_thickness); + } + virtual OperationType type() { return SetStrokeThicknessOperation; } +private: + float m_thickness; +}; + +//************************************** +// Paint setup +//************************************** + +class SetupPaintFill : public Operation { +public: + SetupPaintFill(SkPaint* paint) : m_paint(*paint) {} + virtual void apply(PlatformGraphicsContext* context) { + context->setupPaintFill(&m_paint); + } + virtual OperationType type() { return SetupPaintFillOperation; } +private: + SkPaint m_paint; +}; + +class SetupPaintShadow : public Operation { +public: + SetupPaintShadow(SkPaint* paint, SkPoint* offset) + : m_paint(*paint), m_offset(*offset) {} + virtual void apply(PlatformGraphicsContext* context) { + context->setupPaintShadow(&m_paint, &m_offset); + } + virtual OperationType type() { return SetupPaintShadowOperation; } +private: + SkPaint m_paint; + SkPoint m_offset; +}; + +class SetupPaintStroke : public Operation { +public: + SetupPaintStroke(SkPaint* paint, SkRect* rect, bool isHLine) + : m_paint(*paint), m_rect(*rect), m_isHLine(isHLine) {} + virtual void apply(PlatformGraphicsContext* context) { + context->setupPaintStroke(&m_paint, &m_rect, m_isHLine); + } + virtual OperationType type() { return SetupPaintStrokeOperation; } +private: + SkPaint m_paint; + SkRect m_rect; + bool m_isHLine; +}; + +//************************************** +// Matrix operations +//************************************** + +class ConcatCTM : public Operation { +public: + ConcatCTM(const AffineTransform& affine) : m_matrix(affine) {} + virtual void apply(PlatformGraphicsContext* context) { + context->concatCTM(m_matrix); + } + virtual OperationType type() { return ConcatCTMOperation; } +private: + AffineTransform m_matrix; +}; + +class Rotate : public Operation { +public: + Rotate(float angleInRadians) : m_angle(angleInRadians) {} + virtual void apply(PlatformGraphicsContext* context) { + context->rotate(m_angle); + } + virtual OperationType type() { return RotateOperation; } +private: + float m_angle; +}; + +class Scale : public Operation { +public: + Scale(const FloatSize& size) : m_scale(size) {} + virtual void apply(PlatformGraphicsContext* context) { + context->scale(m_scale); + } + virtual OperationType type() { return ScaleOperation; } +private: + FloatSize m_scale; +}; + +class Translate : public Operation { +public: + Translate(float x, float y) : m_x(x), m_y(y) {} + virtual void apply(PlatformGraphicsContext* context) { + context->translate(m_x, m_y); + } + virtual OperationType type() { return TranslateOperation; } +private: + float m_x; + float m_y; +}; + +//************************************** +// Clipping +//************************************** + +class InnerRoundedRectClip : public Operation { +public: + InnerRoundedRectClip(const IntRect& rect, int thickness) + : m_rect(rect), m_thickness(thickness) {} + virtual void apply(PlatformGraphicsContext* context) { + context->addInnerRoundedRectClip(m_rect, m_thickness); + } + virtual OperationType type() { return InnerRoundedRectClipOperation; } +private: + IntRect m_rect; + int m_thickness; +}; + +class Clip : public Operation { +public: + Clip(const FloatRect& rect) : m_rect(rect) {} + virtual void apply(PlatformGraphicsContext* context) { + context->clip(m_rect); + } + virtual OperationType type() { return ClipOperation; } +private: + const FloatRect m_rect; +}; + +class ClipPath : public Operation { +public: + ClipPath(const Path& path, bool clipout = false) + : m_path(path), m_clipOut(clipout), m_hasWindRule(false) {} + void setWindRule(WindRule rule) { m_windRule = rule; m_hasWindRule = true; } + virtual void apply(PlatformGraphicsContext* context) { + if (m_hasWindRule) { + context->clipPath(m_path, m_windRule); + return; + } + if (m_clipOut) + context->clipOut(m_path); + else + context->clip(m_path); + } + virtual OperationType type() { return ClipPathOperation; } +private: + const Path m_path; + bool m_clipOut; + WindRule m_windRule; + bool m_hasWindRule; +}; + +class ClipOut : public Operation { +public: + ClipOut(const IntRect& rect) : m_rect(rect) {} + virtual void apply(PlatformGraphicsContext* context) { + context->clipOut(m_rect); + } + virtual OperationType type() { return ClipOutOperation; } +private: + const IntRect m_rect; +}; + +class ClearRect : public Operation { +public: + ClearRect(const FloatRect& rect) : m_rect(rect) {} + virtual void apply(PlatformGraphicsContext* context) { + context->clearRect(m_rect); + } + virtual OperationType type() { return ClearRectOperation; } +private: + FloatRect m_rect; +}; + +//************************************** +// Drawing +//************************************** + +class DrawBitmapPattern : public Operation { +public: + DrawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix, + CompositeOperator op, const FloatRect& destRect) + : m_bitmap(bitmap), m_matrix(matrix), m_operator(op), m_destRect(destRect) {} + virtual void apply(PlatformGraphicsContext* context) { + context->drawBitmapPattern(m_bitmap, m_matrix, m_operator, m_destRect); + } + virtual OperationType type() { return DrawBitmapPatternOperation; } +private: + // TODO: use refcounted bitmap + const SkBitmap m_bitmap; + SkMatrix m_matrix; + CompositeOperator m_operator; + FloatRect m_destRect; +}; + +class DrawBitmapRect : public Operation { +public: + DrawBitmapRect(const SkBitmap& bitmap, const SkIRect& srcR, + const SkRect& dstR, CompositeOperator op) + : m_bitmap(bitmap), m_srcR(srcR), m_dstR(dstR), m_operator(op) {} + virtual void apply(PlatformGraphicsContext* context) { + context->drawBitmapRect(m_bitmap, &m_srcR, m_dstR, m_operator); + } + virtual OperationType type() { return DrawBitmapRectOperation; } + virtual String parameters() { + return String::format("%.2f, %.2f - %.2f x %.2f", + m_dstR.fLeft, m_dstR.fTop, + m_dstR.width(), m_dstR.height()); + } +private: + const SkBitmap& m_bitmap; + SkIRect m_srcR; + SkRect m_dstR; + CompositeOperator m_operator; +}; + +class DrawEllipse : public Operation { +public: + DrawEllipse(const IntRect& rect) : m_rect(rect) {} + virtual void apply(PlatformGraphicsContext* context) { + context->drawEllipse(m_rect); + } + virtual OperationType type() { return DrawEllipseOperation; } +private: + IntRect m_rect; +}; + +class DrawLine : public Operation { +public: + DrawLine(const IntPoint& point1, const IntPoint& point2) + : m_point1(point1), m_point2(point2) {} + virtual void apply(PlatformGraphicsContext* context) { + context->drawLine(m_point1, m_point2); + } + virtual OperationType type() { return DrawLineOperation; } +private: + IntPoint m_point1; + IntPoint m_point2; +}; + +class DrawLineForText : public Operation { +public: + DrawLineForText(const FloatPoint& pt, float width) + : m_point(pt), m_width(width) {} + virtual void apply(PlatformGraphicsContext* context) { + context->drawLineForText(m_point, m_width); + } + virtual OperationType type() { return DrawLineForTextOperation; } +private: + FloatPoint m_point; + float m_width; +}; + +class DrawLineForTextChecking : public Operation { +public: + DrawLineForTextChecking(const FloatPoint& pt, float width, + GraphicsContext::TextCheckingLineStyle lineStyle) + : m_point(pt), m_width(width), m_lineStyle(lineStyle) {} + virtual void apply(PlatformGraphicsContext* context) { + context->drawLineForTextChecking(m_point, m_width, m_lineStyle); + } + virtual OperationType type() { return DrawLineForTextCheckingOperation; } +private: + FloatPoint m_point; + float m_width; + GraphicsContext::TextCheckingLineStyle m_lineStyle; +}; + +class DrawRect : public Operation { +public: + DrawRect(const IntRect& rect) : m_rect(rect) {} + virtual void apply(PlatformGraphicsContext* context) { + context->drawRect(m_rect); + } + virtual OperationType type() { return DrawRectOperation; } +private: + IntRect m_rect; +}; + +class FillPath : public Operation { +public: + FillPath(const Path& pathToFill, WindRule fillRule) + : m_path(pathToFill), m_fillRule(fillRule) {} + virtual void apply(PlatformGraphicsContext* context) { + context->fillPath(m_path, m_fillRule); + } + virtual OperationType type() { return FillPathOperation; } +private: + Path m_path; + WindRule m_fillRule; +}; + +class FillRect : public Operation { +public: + FillRect(const FloatRect& rect) : m_rect(rect), m_hasColor(false) {} + void setColor(Color c) { m_color = c; m_hasColor = true; } + virtual void apply(PlatformGraphicsContext* context) { + if (m_hasColor) + context->fillRect(m_rect, m_color); + else + context->fillRect(m_rect); + } + virtual OperationType type() { return FillRectOperation; } +private: + FloatRect m_rect; + Color m_color; + bool m_hasColor; +}; + +class FillRoundedRect : public Operation { +public: + FillRoundedRect(const IntRect& rect, + const IntSize& topLeft, + const IntSize& topRight, + const IntSize& bottomLeft, + const IntSize& bottomRight, + const Color& color) + : m_rect(rect) + , m_topLeft(topLeft) + , m_topRight(topRight) + , m_bottomLeft(bottomLeft) + , m_bottomRight(bottomRight) + , m_color(color) + {} + virtual void apply(PlatformGraphicsContext* context) { + context->fillRoundedRect(m_rect, m_topLeft, m_topRight, + m_bottomLeft, m_bottomRight, + m_color); + } + virtual OperationType type() { return FillRoundedRectOperation; } +private: + IntRect m_rect; + IntSize m_topLeft; + IntSize m_topRight; + IntSize m_bottomLeft; + IntSize m_bottomRight; + Color m_color; +}; + +class StrokeArc : public Operation { +public: + StrokeArc(const IntRect& r, int startAngle, int angleSpan) + : m_rect(r) + , m_startAngle(startAngle) + , m_angleSpan(angleSpan) + {} + virtual void apply(PlatformGraphicsContext* context) { + context->strokeArc(m_rect, m_startAngle, m_angleSpan); + } + virtual OperationType type() { return StrokeArcOperation; } +private: + IntRect m_rect; + int m_startAngle; + int m_angleSpan; +}; + +class StrokePath : public Operation { +public: + StrokePath(const Path& path) : m_path(path) {} + virtual void apply(PlatformGraphicsContext* context) { + context->strokePath(m_path); + } + virtual OperationType type() { return StrokePathOperation; } +private: + Path m_path; +}; + + +class StrokeRect : public Operation { +public: + StrokeRect(const FloatRect& rect, float lineWidth) + : m_rect(rect), m_lineWidth(lineWidth) {} + virtual void apply(PlatformGraphicsContext* context) { + context->strokeRect(m_rect, m_lineWidth); + } + virtual OperationType type() { return StrokeRectOperation; } +private: + FloatRect m_rect; + float m_lineWidth; +}; + +//************************************** +// Text +//************************************** + +class DrawComplexText : public Operation { +public: + DrawComplexText(SkPicture* picture) : m_picture(picture) { + SkSafeRef(m_picture); + } + ~DrawComplexText() { SkSafeUnref(m_picture); } + virtual void apply(PlatformGraphicsContext* context) { + if (!context->getCanvas()) + return; + context->getCanvas()->drawPicture(*m_picture); + } + virtual OperationType type() { return DrawComplexTextOperation; } +private: + SkPicture* m_picture; +}; + +class DrawText : public Operation { +public: + DrawText(const Font* font, const SimpleFontData* simpleFont, + const GlyphBuffer& glyphBuffer, + int from, int numGlyphs, const FloatPoint& point) + : m_font(font), m_simpleFont(simpleFont) + , m_glyphBuffer(glyphBuffer), m_from(from) + , m_numGlyphs(numGlyphs), m_point(point) { + + SkPicture* picture = new SkPicture(); + SkCanvas* canvas = picture->beginRecording(0, 0, 0); + PlatformGraphicsContextSkia platformContext(canvas); + GraphicsContext graphicsContext(&platformContext); + m_font->drawGlyphs(&graphicsContext, m_simpleFont, + m_glyphBuffer, m_from, m_numGlyphs, m_point); + picture->endRecording(); + m_picture = picture; + } + ~DrawText() { SkSafeUnref(m_picture); } + virtual void apply(PlatformGraphicsContext* context) { + if (!context->getCanvas()) + return; + context->getCanvas()->drawPicture(*m_picture); + } + virtual OperationType type() { return DrawTextOperation; } +private: + SkPicture* m_picture; + const Font* m_font; + const SimpleFontData* m_simpleFont; + const GlyphBuffer m_glyphBuffer; + int m_from; + int m_numGlyphs; + const FloatPoint m_point; +}; + +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // GraphicsOperation_h diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp new file mode 100644 index 0000000..6118160 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp @@ -0,0 +1,63 @@ +#define LOG_TAG "GraphicsOperationCollection" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "GraphicsOperationCollection.h" + +#include "AndroidLog.h" +#include "GraphicsContext.h" +#include "PlatformGraphicsContext.h" +#include "PlatformGraphicsContextRecording.h" + +#if USE(ACCELERATED_COMPOSITING) + +namespace WebCore { + +GraphicsOperationCollection::GraphicsOperationCollection(const IntRect& drawArea) + : m_drawArea(drawArea) +{ +} + +GraphicsOperationCollection::~GraphicsOperationCollection() +{ + for (unsigned int i = 0; i < m_operations.size(); i++) + SkSafeUnref(m_operations[i]); +} + +void GraphicsOperationCollection::apply(PlatformGraphicsContext* context) +{ + ALOGD("\nApply GraphicsOperationCollection %x, %d operations", this, m_operations.size()); + for (unsigned int i = 0; i < m_operations.size(); i++) { + ALOGD("[%d] (%x) %s %s", i, this, m_operations[i]->name().latin1().data(), + m_operations[i]->parameters().latin1().data()); + m_operations[i]->apply(context); + } +} + +void GraphicsOperationCollection::append(GraphicsOperation::Operation* operation) +{ + m_operations.append(operation); +} + +bool GraphicsOperationCollection::isEmpty() +{ + return !m_operations.size(); +} + +AutoGraphicsOperationCollection::AutoGraphicsOperationCollection(const IntRect& area) +{ + m_graphicsOperationCollection = new GraphicsOperationCollection(area); + m_platformGraphicsContext = new PlatformGraphicsContextRecording(m_graphicsOperationCollection); + m_graphicsContext = new GraphicsContext(m_platformGraphicsContext); +} + +AutoGraphicsOperationCollection::~AutoGraphicsOperationCollection() +{ + SkSafeUnref(m_graphicsOperationCollection); + delete m_graphicsContext; + delete m_platformGraphicsContext; +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h new file mode 100644 index 0000000..9d7b530 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h @@ -0,0 +1,72 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GraphicsOperationCollection_h +#define GraphicsOperationCollection_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "Color.h" +#include "GraphicsOperation.h" +#include "IntRect.h" +#include "SkRefCnt.h" + +namespace WebCore { + +class PlatformGraphicsContext; + +class GraphicsOperationCollection : public SkRefCnt { +public: + GraphicsOperationCollection(const IntRect& drawArea); + ~GraphicsOperationCollection(); + + void apply(PlatformGraphicsContext* context); + void append(GraphicsOperation::Operation* operation); + + bool isEmpty(); + +private: + IntRect m_drawArea; + Vector<GraphicsOperation::Operation*> m_operations; +}; + +class AutoGraphicsOperationCollection { +public: + AutoGraphicsOperationCollection(const IntRect& area); + ~AutoGraphicsOperationCollection(); + GraphicsContext* context() { return m_graphicsContext; } + GraphicsOperationCollection* picture() { return m_graphicsOperationCollection; } + +private: + GraphicsOperationCollection* m_graphicsOperationCollection; + PlatformGraphicsContext* m_platformGraphicsContext; + GraphicsContext* m_graphicsContext; +}; + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // GraphicsOperationCollection_h diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp new file mode 100644 index 0000000..bb5d990 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp @@ -0,0 +1,456 @@ +/* + * Copyright 2006, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "PlatformGraphicsContext" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "PlatformGraphicsContext.h" + +#include "AndroidLog.h" +#include "SkBlurDrawLooper.h" +#include "SkBlurMaskFilter.h" +#include "SkColorPriv.h" +#include "SkDashPathEffect.h" +#include "SkPaint.h" +#include "SkShader.h" +#include "SkiaUtils.h" + +namespace WebCore { + +//************************************** +// Helper functions +//************************************** + +static int RoundToInt(float x) +{ + return (int)roundf(x); +} + +template <typename T> T* deepCopyPtr(const T* src) +{ + return src ? new T(*src) : 0; +} + +// Set a bitmap shader that mimics dashing by width-on, width-off. +// Returns false if it could not succeed (e.g. there was an existing shader) +static bool setBitmapDash(SkPaint* paint, int width) { + if (width <= 0 || paint->getShader()) + return false; + + SkColor c = paint->getColor(); + + SkBitmap bm; + bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 1); + bm.allocPixels(); + bm.lockPixels(); + + // set the ON pixel + *bm.getAddr32(0, 0) = SkPreMultiplyARGB(0xFF, SkColorGetR(c), + SkColorGetG(c), SkColorGetB(c)); + // set the OFF pixel + *bm.getAddr32(1, 0) = 0; + bm.unlockPixels(); + + SkMatrix matrix; + matrix.setScale(SkIntToScalar(width), SK_Scalar1); + + SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode, + SkShader::kClamp_TileMode); + s->setLocalMatrix(matrix); + + paint->setShader(s)->unref(); + return true; +} + +//************************************** +// State implementation +//************************************** + +PlatformGraphicsContext::State::State() + : pathEffect(0) + , miterLimit(4) + , alpha(1) + , strokeThickness(0) // Same as default in GraphicsContextPrivate.h + , lineCap(SkPaint::kDefault_Cap) + , lineJoin(SkPaint::kDefault_Join) + , mode(SkXfermode::kSrcOver_Mode) + , dashRatio(3) + , fillColor(SK_ColorBLACK) + , fillShader(0) + , strokeColor(SK_ColorBLACK) + , strokeShader(0) + , useAA(true) + , strokeStyle(SolidStroke) +{ +} + +PlatformGraphicsContext::State::State(const State& other) + : pathEffect(other.pathEffect) + , miterLimit(other.miterLimit) + , alpha(other.alpha) + , strokeThickness(other.strokeThickness) + , lineCap(other.lineCap) + , lineJoin(other.lineJoin) + , mode(other.mode) + , dashRatio(other.dashRatio) + , shadow(other.shadow) + , fillColor(other.fillColor) + , fillShader(other.fillShader) + , strokeColor(other.strokeColor) + , strokeShader(other.strokeShader) + , useAA(other.useAA) + , strokeStyle(other.strokeStyle) +{ + SkSafeRef(pathEffect); + SkSafeRef(fillShader); + SkSafeRef(strokeShader); +} + +PlatformGraphicsContext::State::~State() +{ + SkSafeUnref(pathEffect); + SkSafeUnref(fillShader); + SkSafeUnref(strokeShader); +} + +void PlatformGraphicsContext::State::setShadow(int radius, int dx, int dy, SkColor c) +{ + // Cut the radius in half, to visually match the effect seen in + // safari browser + shadow.blur = SkScalarHalf(SkIntToScalar(radius)); + shadow.dx = SkIntToScalar(dx); + shadow.dy = SkIntToScalar(dy); + shadow.color = c; +} + +bool PlatformGraphicsContext::State::setupShadowPaint(SkPaint* paint, SkPoint* offset, + bool shadowsIgnoreTransforms) +{ + paint->setAntiAlias(true); + paint->setDither(true); + paint->setXfermodeMode(mode); + paint->setColor(shadow.color); + offset->set(shadow.dx, shadow.dy); + + // Currently, only GraphicsContexts associated with the + // HTMLCanvasElement have shadows ignore transforms set. This + // allows us to distinguish between CSS and Canvas shadows which + // have different rendering specifications. + uint32_t flags = SkBlurMaskFilter::kHighQuality_BlurFlag; + if (shadowsIgnoreTransforms) { + offset->fY = -offset->fY; + flags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag; + } + + if (shadow.blur > 0) { + paint->setMaskFilter(SkBlurMaskFilter::Create(shadow.blur, + SkBlurMaskFilter::kNormal_BlurStyle))->unref(); + } + return SkColorGetA(shadow.color) && (shadow.blur || shadow.dx || shadow.dy); +} + +SkColor PlatformGraphicsContext::State::applyAlpha(SkColor c) const +{ + int s = RoundToInt(alpha * 256); + if (s >= 256) + return c; + if (s < 0) + return 0; + + int a = SkAlphaMul(SkColorGetA(c), s); + return (c & 0x00FFFFFF) | (a << 24); +} + +// Returns a new State with all of this object's inherited properties copied. +PlatformGraphicsContext::State PlatformGraphicsContext::State::cloneInheritedProperties() +{ + return PlatformGraphicsContext::State(*this); +} + +//************************************** +// PlatformGraphicsContext +//************************************** + +PlatformGraphicsContext::PlatformGraphicsContext() +{ + m_stateStack.append(State()); + m_state = &m_stateStack.last(); +} + +PlatformGraphicsContext::~PlatformGraphicsContext() +{ +} + +//************************************** +// State management +//************************************** + +void PlatformGraphicsContext::save() +{ + m_stateStack.append(m_state->cloneInheritedProperties()); + m_state = &m_stateStack.last(); +} + +void PlatformGraphicsContext::restore() +{ + m_stateStack.removeLast(); + m_state = &m_stateStack.last(); +} + +//************************************** +// State setters +//************************************** + +void PlatformGraphicsContext::setAlpha(float alpha) +{ + m_state->alpha = alpha; +} + +void PlatformGraphicsContext::setCompositeOperation(CompositeOperator op) +{ + m_state->mode = WebCoreCompositeToSkiaComposite(op); +} + +void PlatformGraphicsContext::setFillColor(const Color& c) +{ + m_state->fillColor = c.rgb(); + setFillShader(0); +} + +void PlatformGraphicsContext::setFillShader(SkShader* fillShader) +{ + if (fillShader) + m_state->fillColor = Color::black; + + if (fillShader != m_state->fillShader) { + SkSafeUnref(m_state->fillShader); + m_state->fillShader = fillShader; + SkSafeRef(m_state->fillShader); + } +} + +void PlatformGraphicsContext::setLineCap(LineCap cap) +{ + switch (cap) { + case ButtCap: + m_state->lineCap = SkPaint::kButt_Cap; + break; + case RoundCap: + m_state->lineCap = SkPaint::kRound_Cap; + break; + case SquareCap: + m_state->lineCap = SkPaint::kSquare_Cap; + break; + default: + ALOGD("PlatformGraphicsContextSkia::setLineCap: unknown LineCap %d\n", cap); + break; + } +} + +void PlatformGraphicsContext::setLineDash(const DashArray& dashes, float dashOffset) +{ + size_t dashLength = dashes.size(); + if (!dashLength) + return; + + size_t count = !(dashLength % 2) ? dashLength : dashLength * 2; + SkScalar* intervals = new SkScalar[count]; + + for (unsigned int i = 0; i < count; i++) + intervals[i] = SkFloatToScalar(dashes[i % dashLength]); + SkPathEffect **effectPtr = &m_state->pathEffect; + SkSafeUnref(*effectPtr); + *effectPtr = new SkDashPathEffect(intervals, count, SkFloatToScalar(dashOffset)); + + delete[] intervals; +} + +void PlatformGraphicsContext::setLineJoin(LineJoin join) +{ + switch (join) { + case MiterJoin: + m_state->lineJoin = SkPaint::kMiter_Join; + break; + case RoundJoin: + m_state->lineJoin = SkPaint::kRound_Join; + break; + case BevelJoin: + m_state->lineJoin = SkPaint::kBevel_Join; + break; + default: + ALOGD("PlatformGraphicsContextSkia::setLineJoin: unknown LineJoin %d\n", join); + break; + } +} + +void PlatformGraphicsContext::setMiterLimit(float limit) +{ + m_state->miterLimit = limit; +} + +void PlatformGraphicsContext::setShadow(int radius, int dx, int dy, SkColor c) +{ + m_state->setShadow(radius, dx, dy, c); +} + +void PlatformGraphicsContext::setShouldAntialias(bool useAA) +{ + m_state->useAA = useAA; +} + +void PlatformGraphicsContext::setStrokeColor(const Color& c) +{ + m_state->strokeColor = c.rgb(); + setStrokeShader(0); +} + +void PlatformGraphicsContext::setStrokeShader(SkShader* strokeShader) +{ + if (strokeShader) + m_state->strokeColor = Color::black; + + if (strokeShader != m_state->strokeShader) { + SkSafeUnref(m_state->strokeShader); + m_state->strokeShader = strokeShader; + SkSafeRef(m_state->strokeShader); + } +} + +void PlatformGraphicsContext::setStrokeStyle(StrokeStyle style) +{ + m_state->strokeStyle = style; +} + +void PlatformGraphicsContext::setStrokeThickness(float f) +{ + m_state->strokeThickness = f; +} + +//************************************** +// Paint setup +//************************************** + +void PlatformGraphicsContext::setupPaintCommon(SkPaint* paint) const +{ + paint->setAntiAlias(m_state->useAA); + paint->setDither(true); + paint->setXfermodeMode(m_state->mode); + if (SkColorGetA(m_state->shadow.color) > 0) { + + // Currently, only GraphicsContexts associated with the + // HTMLCanvasElement have shadows ignore transforms set. This + // allows us to distinguish between CSS and Canvas shadows which + // have different rendering specifications. + SkScalar dy = m_state->shadow.dy; + uint32_t flags = SkBlurDrawLooper::kHighQuality_BlurFlag; + if (shadowsIgnoreTransforms()) { + dy = -dy; + flags |= SkBlurDrawLooper::kIgnoreTransform_BlurFlag; + flags |= SkBlurDrawLooper::kOverrideColor_BlurFlag; + } + + SkDrawLooper* looper = new SkBlurDrawLooper(m_state->shadow.blur, + m_state->shadow.dx, + dy, + m_state->shadow.color, + flags); + paint->setLooper(looper)->unref(); + } + paint->setFilterBitmap(true); +} + +void PlatformGraphicsContext::setupPaintFill(SkPaint* paint) const +{ + this->setupPaintCommon(paint); + paint->setColor(m_state->applyAlpha(m_state->fillColor)); + paint->setShader(m_state->fillShader); +} + +bool PlatformGraphicsContext::setupPaintShadow(SkPaint* paint, SkPoint* offset) const +{ + return m_state->setupShadowPaint(paint, offset, shadowsIgnoreTransforms()); +} + +bool PlatformGraphicsContext::setupPaintStroke(SkPaint* paint, SkRect* rect, + bool isHLine) +{ + this->setupPaintCommon(paint); + paint->setColor(m_state->applyAlpha(m_state->strokeColor)); + paint->setShader(m_state->strokeShader); + + float width = m_state->strokeThickness; + + // This allows dashing and dotting to work properly for hairline strokes + // FIXME: Should we only do this for dashed and dotted strokes? + if (!width) + width = 1; + + paint->setStyle(SkPaint::kStroke_Style); + paint->setStrokeWidth(SkFloatToScalar(width)); + paint->setStrokeCap(m_state->lineCap); + paint->setStrokeJoin(m_state->lineJoin); + paint->setStrokeMiter(SkFloatToScalar(m_state->miterLimit)); + + if (rect && (RoundToInt(width) & 1)) + rect->inset(-SK_ScalarHalf, -SK_ScalarHalf); + + SkPathEffect* pe = m_state->pathEffect; + if (pe) { + paint->setPathEffect(pe); + return false; + } + switch (m_state->strokeStyle) { + case NoStroke: + case SolidStroke: + width = 0; + break; + case DashedStroke: + width = m_state->dashRatio * width; + break; + // No break + case DottedStroke: + break; + } + + if (width > 0) { + // Return true if we're basically a dotted dash of squares + bool justSqrs = RoundToInt(width) == RoundToInt(paint->getStrokeWidth()); + + if (justSqrs || !isHLine || !setBitmapDash(paint, width)) { +#if 0 + // this is slow enough that we just skip it for now + // see http://b/issue?id=4163023 + SkScalar intervals[] = { width, width }; + pe = new SkDashPathEffect(intervals, 2, 0); + paint->setPathEffect(pe)->unref(); +#endif + } + return justSqrs; + } + return false; +} + +} // WebCore diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h new file mode 100644 index 0000000..601de0f --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h @@ -0,0 +1,204 @@ +/* + * Copyright 2006, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef platform_graphics_context_h +#define platform_graphics_context_h + +#include "IntRect.h" +#include "GraphicsContext.h" +#include "RenderSkinAndroid.h" +#include "SkCanvas.h" +#include "SkPicture.h" +#include "SkTDArray.h" +#include <wtf/Vector.h> + +class SkCanvas; + +namespace WebCore { + +class PlatformGraphicsContext { +public: + PlatformGraphicsContext(); + virtual ~PlatformGraphicsContext(); + virtual bool isPaintingDisabled() = 0; + virtual SkCanvas* getCanvas() = 0; + + void setGraphicsContext(GraphicsContext* gc) { m_gc = gc; } + virtual bool deleteUs() const { return false; } + + typedef enum { PaintingContext, RecordingContext } ContextType; + virtual ContextType type() = 0; + + // State management + virtual void beginTransparencyLayer(float opacity) = 0; + virtual void endTransparencyLayer() = 0; + virtual void save(); + virtual void restore(); + + // State values + virtual void setAlpha(float alpha); + virtual void setCompositeOperation(CompositeOperator op); + virtual void setFillColor(const Color& c); + virtual void setFillShader(SkShader* fillShader); + virtual void setLineCap(LineCap cap); + virtual void setLineDash(const DashArray& dashes, float dashOffset); + virtual void setLineJoin(LineJoin join); + virtual void setMiterLimit(float limit); + virtual void setShadow(int radius, int dx, int dy, SkColor c); + virtual void setShouldAntialias(bool useAA); + virtual void setStrokeColor(const Color& c); + virtual void setStrokeShader(SkShader* strokeShader); + virtual void setStrokeStyle(StrokeStyle style); + virtual void setStrokeThickness(float f); + + // FIXME: These setupPaint* should be private, but + // they are used by FontAndroid currently + virtual void setupPaintFill(SkPaint* paint) const; + virtual bool setupPaintShadow(SkPaint* paint, SkPoint* offset) const; + // Sets up the paint for stroking. Returns true if the style is really + // just a dash of squares (the size of the paint's stroke-width. + virtual bool setupPaintStroke(SkPaint* paint, SkRect* rect, bool isHLine = false); + + // Matrix operations + virtual void concatCTM(const AffineTransform& affine) = 0; + virtual void rotate(float angleInRadians) = 0; + virtual void scale(const FloatSize& size) = 0; + virtual void translate(float x, float y) = 0; + virtual const SkMatrix& getTotalMatrix() = 0; + + // Clipping + virtual void addInnerRoundedRectClip(const IntRect& rect, int thickness) = 0; + virtual void canvasClip(const Path& path) = 0; + virtual void clip(const FloatRect& rect) = 0; + virtual void clip(const Path& path) = 0; + virtual void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias) = 0; + virtual void clipOut(const IntRect& r) = 0; + virtual void clipOut(const Path& p) = 0; + virtual void clipPath(const Path& pathToClip, WindRule clipRule) = 0; + + // Drawing + virtual void clearRect(const FloatRect& rect) = 0; + virtual void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix, + CompositeOperator compositeOp, const FloatRect& destRect) = 0; + virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, + const SkRect& dst, CompositeOperator op) = 0; + virtual void drawConvexPolygon(size_t numPoints, const FloatPoint* points, + bool shouldAntialias) = 0; + virtual void drawEllipse(const IntRect& rect) = 0; + virtual void drawFocusRing(const Vector<IntRect>& rects, int /* width */, + int /* offset */, const Color& color) = 0; + virtual void drawHighlightForText(const Font& font, const TextRun& run, + const FloatPoint& point, int h, + const Color& backgroundColor, ColorSpace colorSpace, + int from, int to, bool isActive) = 0; + virtual void drawLine(const IntPoint& point1, const IntPoint& point2) = 0; + virtual void drawLineForText(const FloatPoint& pt, float width) = 0; + virtual void drawLineForTextChecking(const FloatPoint& pt, float width, + GraphicsContext::TextCheckingLineStyle) = 0; + virtual void drawRect(const IntRect& rect) = 0; + virtual void fillPath(const Path& pathToFill, WindRule fillRule) = 0; + virtual void fillRect(const FloatRect& rect) = 0; + void fillRect(const FloatRect& rect, const Color& color, ColorSpace) { + fillRect(rect, color); + } + virtual void fillRect(const FloatRect& rect, const Color& color) = 0; + void fillRoundedRect(const IntRect& rect, const IntSize& topLeft, + const IntSize& topRight, const IntSize& bottomLeft, + const IntSize& bottomRight, const Color& color, + ColorSpace) { + fillRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight, color); + } + virtual void fillRoundedRect(const IntRect& rect, const IntSize& topLeft, + const IntSize& topRight, const IntSize& bottomLeft, + const IntSize& bottomRight, const Color& color) = 0; + virtual void strokeArc(const IntRect& r, int startAngle, int angleSpan) = 0; + virtual void strokePath(const Path& pathToStroke) = 0; + virtual void strokeRect(const FloatRect& rect, float lineWidth) = 0; + + virtual SkCanvas* recordingCanvas() = 0; + virtual void endRecording(int type = 0) = 0; + +protected: + + struct ShadowRec { + SkScalar blur; + SkScalar dx; + SkScalar dy; + SkColor color; // alpha>0 means valid shadow + ShadowRec(SkScalar b = 0, + SkScalar x = 0, + SkScalar y = 0, + SkColor c = 0) // by default, alpha=0, so no shadow + : blur(b), dx(x), dy(y), color(c) + {}; + }; + + class State { + public: + SkPathEffect* pathEffect; + float miterLimit; + float alpha; + float strokeThickness; + SkPaint::Cap lineCap; + SkPaint::Join lineJoin; + SkXfermode::Mode mode; + int dashRatio; // Ratio of the length of a dash to its width + ShadowRec shadow; + SkColor fillColor; + SkShader* fillShader; + SkColor strokeColor; + SkShader* strokeShader; + bool useAA; + StrokeStyle strokeStyle; + + State(); + State(const State& other); + ~State(); + + void setShadow(int radius, int dx, int dy, SkColor c); + bool setupShadowPaint(SkPaint* paint, SkPoint* offset, + bool shadowsIgnoreTransforms); + SkColor applyAlpha(SkColor c) const; + + State cloneInheritedProperties(); + private: + // Not supported. + void operator=(const State&); + + friend class PlatformGraphicsContextRecording; + friend class PlatformGraphicsContextSkia; + }; + + virtual bool shadowsIgnoreTransforms() const = 0; + void setupPaintCommon(SkPaint* paint) const; + GraphicsContext* m_gc; // Back-ptr to our parent + + struct State; + WTF::Vector<State> m_stateStack; + State* m_state; +}; + +} +#endif diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp new file mode 100644 index 0000000..d96124d --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp @@ -0,0 +1,373 @@ +#define LOG_TAG "PlatformGraphicsContextRecording" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "PlatformGraphicsContextRecording.h" + +#include "AndroidLog.h" +#include "Font.h" +#include "GraphicsContext.h" +#include "GraphicsOperationCollection.h" +#include "GraphicsOperation.h" + +namespace WebCore { + +//************************************** +// PlatformGraphicsContextRecording +//************************************** + +PlatformGraphicsContextRecording::PlatformGraphicsContextRecording(GraphicsOperationCollection* picture) + : PlatformGraphicsContext() + , mGraphicsOperationCollection(picture) + , mPicture(0) +{ +} + +bool PlatformGraphicsContextRecording::isPaintingDisabled() +{ + return !mGraphicsOperationCollection; +} + +SkCanvas* PlatformGraphicsContextRecording::recordingCanvas() +{ + SkSafeUnref(mPicture); + mPicture = new SkPicture(); + return mPicture->beginRecording(0, 0, 0); +} + +void PlatformGraphicsContextRecording::endRecording(int type) +{ + if (!mPicture) + return; + mPicture->endRecording(); + GraphicsOperation::DrawComplexText* text = new GraphicsOperation::DrawComplexText(mPicture); + mGraphicsOperationCollection->append(text); + mPicture = 0; +} + + +//************************************** +// State management +//************************************** + +void PlatformGraphicsContextRecording::beginTransparencyLayer(float opacity) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::BeginTransparencyLayer(opacity)); +} + +void PlatformGraphicsContextRecording::endTransparencyLayer() +{ + mGraphicsOperationCollection->append(new GraphicsOperation::EndTransparencyLayer()); +} + +void PlatformGraphicsContextRecording::save() +{ + PlatformGraphicsContext::save(); + mGraphicsOperationCollection->append(new GraphicsOperation::Save()); +} + +void PlatformGraphicsContextRecording::restore() +{ + PlatformGraphicsContext::restore(); + mGraphicsOperationCollection->append(new GraphicsOperation::Restore()); +} + +//************************************** +// State setters +//************************************** + +void PlatformGraphicsContextRecording::setAlpha(float alpha) +{ + PlatformGraphicsContext::setAlpha(alpha); + mGraphicsOperationCollection->append(new GraphicsOperation::SetAlpha(alpha)); +} + +void PlatformGraphicsContextRecording::setCompositeOperation(CompositeOperator op) +{ + PlatformGraphicsContext::setCompositeOperation(op); + mGraphicsOperationCollection->append(new GraphicsOperation::SetCompositeOperation(op)); +} + +void PlatformGraphicsContextRecording::setFillColor(const Color& c) +{ + PlatformGraphicsContext::setFillColor(c); + mGraphicsOperationCollection->append(new GraphicsOperation::SetFillColor(c)); +} + +void PlatformGraphicsContextRecording::setFillShader(SkShader* fillShader) +{ + PlatformGraphicsContext::setFillShader(fillShader); + mGraphicsOperationCollection->append(new GraphicsOperation::SetFillShader(fillShader)); +} + +void PlatformGraphicsContextRecording::setLineCap(LineCap cap) +{ + PlatformGraphicsContext::setLineCap(cap); + mGraphicsOperationCollection->append(new GraphicsOperation::SetLineCap(cap)); +} + +void PlatformGraphicsContextRecording::setLineDash(const DashArray& dashes, float dashOffset) +{ + PlatformGraphicsContext::setLineDash(dashes, dashOffset); + mGraphicsOperationCollection->append(new GraphicsOperation::SetLineDash(dashes, dashOffset)); +} + +void PlatformGraphicsContextRecording::setLineJoin(LineJoin join) +{ + PlatformGraphicsContext::setLineJoin(join); + mGraphicsOperationCollection->append(new GraphicsOperation::SetLineJoin(join)); +} + +void PlatformGraphicsContextRecording::setMiterLimit(float limit) +{ + PlatformGraphicsContext::setMiterLimit(limit); + mGraphicsOperationCollection->append(new GraphicsOperation::SetMiterLimit(limit)); +} + +void PlatformGraphicsContextRecording::setShadow(int radius, int dx, int dy, SkColor c) +{ + PlatformGraphicsContext::setShadow(radius, dx, dy, c); + mGraphicsOperationCollection->append(new GraphicsOperation::SetShadow(radius, dx, dy, c)); +} + +void PlatformGraphicsContextRecording::setShouldAntialias(bool useAA) +{ + m_state->useAA = useAA; + PlatformGraphicsContext::setShouldAntialias(useAA); + mGraphicsOperationCollection->append(new GraphicsOperation::SetShouldAntialias(useAA)); +} + +void PlatformGraphicsContextRecording::setStrokeColor(const Color& c) +{ + PlatformGraphicsContext::setStrokeColor(c); + mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeColor(c)); +} + +void PlatformGraphicsContextRecording::setStrokeShader(SkShader* strokeShader) +{ + PlatformGraphicsContext::setStrokeShader(strokeShader); + mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeShader(strokeShader)); +} + +void PlatformGraphicsContextRecording::setStrokeStyle(StrokeStyle style) +{ + PlatformGraphicsContext::setStrokeStyle(style); + mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeStyle(style)); +} + +void PlatformGraphicsContextRecording::setStrokeThickness(float f) +{ + PlatformGraphicsContext::setStrokeThickness(f); + mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeThickness(f)); +} + +//************************************** +// Matrix operations +//************************************** + +void PlatformGraphicsContextRecording::concatCTM(const AffineTransform& affine) +{ + mCurrentMatrix.preConcat(affine); + mGraphicsOperationCollection->append(new GraphicsOperation::ConcatCTM(affine)); +} + +void PlatformGraphicsContextRecording::rotate(float angleInRadians) +{ + float value = angleInRadians * (180.0f / 3.14159265f); + mCurrentMatrix.preRotate(SkFloatToScalar(value)); + mGraphicsOperationCollection->append(new GraphicsOperation::Rotate(angleInRadians)); +} + +void PlatformGraphicsContextRecording::scale(const FloatSize& size) +{ + mCurrentMatrix.preScale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height())); + mGraphicsOperationCollection->append(new GraphicsOperation::Scale(size)); +} + +void PlatformGraphicsContextRecording::translate(float x, float y) +{ + mCurrentMatrix.preTranslate(SkFloatToScalar(x), SkFloatToScalar(y)); + mGraphicsOperationCollection->append(new GraphicsOperation::Translate(x, y)); +} + +const SkMatrix& PlatformGraphicsContextRecording::getTotalMatrix() +{ + return mCurrentMatrix; +} + +//************************************** +// Clipping +//************************************** + +void PlatformGraphicsContextRecording::addInnerRoundedRectClip(const IntRect& rect, + int thickness) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::InnerRoundedRectClip(rect, thickness)); +} + +void PlatformGraphicsContextRecording::canvasClip(const Path& path) +{ + clip(path); +} + +void PlatformGraphicsContextRecording::clip(const FloatRect& rect) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::Clip(rect)); +} + +void PlatformGraphicsContextRecording::clip(const Path& path) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::ClipPath(path)); +} + +void PlatformGraphicsContextRecording::clipConvexPolygon(size_t numPoints, + const FloatPoint*, bool antialias) +{ + // TODO +} + +void PlatformGraphicsContextRecording::clipOut(const IntRect& r) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::ClipOut(r)); +} + +void PlatformGraphicsContextRecording::clipOut(const Path& path) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::ClipPath(path, true)); +} + +void PlatformGraphicsContextRecording::clipPath(const Path& pathToClip, WindRule clipRule) +{ + GraphicsOperation::ClipPath* operation = new GraphicsOperation::ClipPath(pathToClip); + operation->setWindRule(clipRule); + mGraphicsOperationCollection->append(operation); +} + +void PlatformGraphicsContextRecording::clearRect(const FloatRect& rect) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::ClearRect(rect)); +} + +//************************************** +// Drawing +//************************************** + +void PlatformGraphicsContextRecording::drawBitmapPattern( + const SkBitmap& bitmap, const SkMatrix& matrix, + CompositeOperator compositeOp, const FloatRect& destRect) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::DrawBitmapPattern(bitmap, matrix, compositeOp, destRect)); +} + +void PlatformGraphicsContextRecording::drawBitmapRect(const SkBitmap& bitmap, + const SkIRect* src, const SkRect& dst, + CompositeOperator op) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::DrawBitmapRect(bitmap, *src, dst, op)); +} + +void PlatformGraphicsContextRecording::drawConvexPolygon(size_t numPoints, + const FloatPoint* points, + bool shouldAntialias) +{ + // TODO +} + +void PlatformGraphicsContextRecording::drawEllipse(const IntRect& rect) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::DrawEllipse(rect)); +} + +void PlatformGraphicsContextRecording::drawFocusRing(const Vector<IntRect>& rects, + int /* width */, int /* offset */, + const Color& color) +{ + // TODO +} + +void PlatformGraphicsContextRecording::drawHighlightForText( + const Font& font, const TextRun& run, const FloatPoint& point, int h, + const Color& backgroundColor, ColorSpace colorSpace, int from, + int to, bool isActive) +{ + IntRect rect = (IntRect)font.selectionRectForText(run, point, h, from, to); + if (isActive) + fillRect(rect, backgroundColor); + else { + int x = rect.x(), y = rect.y(), w = rect.width(), h = rect.height(); + const int t = 3, t2 = t * 2; + + fillRect(IntRect(x, y, w, t), backgroundColor); + fillRect(IntRect(x, y+h-t, w, t), backgroundColor); + fillRect(IntRect(x, y+t, t, h-t2), backgroundColor); + fillRect(IntRect(x+w-t, y+t, t, h-t2), backgroundColor); + } +} + +void PlatformGraphicsContextRecording::drawLine(const IntPoint& point1, + const IntPoint& point2) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::DrawLine(point1, point2)); +} + +void PlatformGraphicsContextRecording::drawLineForText(const FloatPoint& pt, float width) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::DrawLineForText(pt, width)); +} + +void PlatformGraphicsContextRecording::drawLineForTextChecking(const FloatPoint& pt, + float width, GraphicsContext::TextCheckingLineStyle lineStyle) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::DrawLineForTextChecking(pt, width, lineStyle)); +} + +void PlatformGraphicsContextRecording::drawRect(const IntRect& rect) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::DrawRect(rect)); +} + +void PlatformGraphicsContextRecording::fillPath(const Path& pathToFill, WindRule fillRule) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::FillPath(pathToFill, fillRule)); +} + +void PlatformGraphicsContextRecording::fillRect(const FloatRect& rect) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::FillRect(rect)); +} + +void PlatformGraphicsContextRecording::fillRect(const FloatRect& rect, + const Color& color) +{ + GraphicsOperation::FillRect* operation = new GraphicsOperation::FillRect(rect); + operation->setColor(color); + mGraphicsOperationCollection->append(operation); +} + +void PlatformGraphicsContextRecording::fillRoundedRect( + const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, + const IntSize& bottomLeft, const IntSize& bottomRight, + const Color& color) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::FillRoundedRect(rect, topLeft, + topRight, bottomLeft, bottomRight, color)); +} + +void PlatformGraphicsContextRecording::strokeArc(const IntRect& r, int startAngle, + int angleSpan) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::StrokeArc(r, startAngle, angleSpan)); +} + +void PlatformGraphicsContextRecording::strokePath(const Path& pathToStroke) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::StrokePath(pathToStroke)); +} + +void PlatformGraphicsContextRecording::strokeRect(const FloatRect& rect, float lineWidth) +{ + mGraphicsOperationCollection->append(new GraphicsOperation::StrokeRect(rect, lineWidth)); +} + + +} // WebCore diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h new file mode 100644 index 0000000..ebb0075 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h @@ -0,0 +1,128 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef platform_graphics_context_recording_h +#define platform_graphics_context_recording_h + +#include "PlatformGraphicsContext.h" + +namespace WebCore { +class GraphicsOperationCollection; + +class PlatformGraphicsContextRecording : public PlatformGraphicsContext { +public: + PlatformGraphicsContextRecording(GraphicsOperationCollection* picture); + virtual ~PlatformGraphicsContextRecording() {} + virtual bool isPaintingDisabled(); + virtual SkCanvas* getCanvas() { return 0; } + + GraphicsOperationCollection* mGraphicsOperationCollection; + SkMatrix mCurrentMatrix; + + virtual SkCanvas* recordingCanvas(); + virtual void endRecording(int type = 0); + + virtual ContextType type() { return RecordingContext; } + + // State management + virtual void beginTransparencyLayer(float opacity); + virtual void endTransparencyLayer(); + virtual void save(); + virtual void restore(); + + // State values + virtual void setAlpha(float alpha); + virtual void setCompositeOperation(CompositeOperator op); + virtual void setFillColor(const Color& c); + virtual void setFillShader(SkShader* fillShader); + virtual void setLineCap(LineCap cap); + virtual void setLineDash(const DashArray& dashes, float dashOffset); + virtual void setLineJoin(LineJoin join); + virtual void setMiterLimit(float limit); + virtual void setShadow(int radius, int dx, int dy, SkColor c); + virtual void setShouldAntialias(bool useAA); + virtual void setStrokeColor(const Color& c); + virtual void setStrokeShader(SkShader* strokeShader); + virtual void setStrokeStyle(StrokeStyle style); + virtual void setStrokeThickness(float f); + + // Matrix operations + virtual void concatCTM(const AffineTransform& affine); + virtual void rotate(float angleInRadians); + virtual void scale(const FloatSize& size); + virtual void translate(float x, float y); + virtual const SkMatrix& getTotalMatrix(); + + // Clipping + virtual void addInnerRoundedRectClip(const IntRect& rect, int thickness); + virtual void canvasClip(const Path& path); + virtual void clip(const FloatRect& rect); + virtual void clip(const Path& path); + virtual void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias); + virtual void clipOut(const IntRect& r); + virtual void clipOut(const Path& p); + virtual void clipPath(const Path& pathToClip, WindRule clipRule); + + // Drawing + virtual void clearRect(const FloatRect& rect); + virtual void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix, + CompositeOperator compositeOp, const FloatRect& destRect); + virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, + const SkRect& dst, CompositeOperator op); + virtual void drawConvexPolygon(size_t numPoints, const FloatPoint* points, + bool shouldAntialias); + virtual void drawEllipse(const IntRect& rect); + virtual void drawFocusRing(const Vector<IntRect>& rects, int /* width */, + int /* offset */, const Color& color); + virtual void drawHighlightForText(const Font& font, const TextRun& run, + const FloatPoint& point, int h, + const Color& backgroundColor, ColorSpace colorSpace, + int from, int to, bool isActive); + virtual void drawLine(const IntPoint& point1, const IntPoint& point2); + virtual void drawLineForText(const FloatPoint& pt, float width); + virtual void drawLineForTextChecking(const FloatPoint& pt, float width, + GraphicsContext::TextCheckingLineStyle); + virtual void drawRect(const IntRect& rect); + virtual void fillPath(const Path& pathToFill, WindRule fillRule); + virtual void fillRect(const FloatRect& rect); + virtual void fillRect(const FloatRect& rect, const Color& color); + virtual void fillRoundedRect(const IntRect& rect, const IntSize& topLeft, + const IntSize& topRight, const IntSize& bottomLeft, + const IntSize& bottomRight, const Color& color); + virtual void strokeArc(const IntRect& r, int startAngle, int angleSpan); + virtual void strokePath(const Path& pathToStroke); + virtual void strokeRect(const FloatRect& rect, float lineWidth); + +private: + + virtual bool shadowsIgnoreTransforms() const { + return false; + } + + SkPicture* mPicture; +}; + +} +#endif diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp new file mode 100644 index 0000000..9b32726 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp @@ -0,0 +1,606 @@ +#define LOG_TAG "PlatformGraphicsContextSkia" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "PlatformGraphicsContextSkia.h" + +#include "AndroidLog.h" +#include "Font.h" +#include "GraphicsContext.h" +#include "SkCanvas.h" +#include "SkCornerPathEffect.h" +#include "SkPaint.h" +#include "SkShader.h" +#include "SkiaUtils.h" + +namespace WebCore { + +// These are the flags we need when we call saveLayer for transparency. +// Since it does not appear that webkit intends this to also save/restore +// the matrix or clip, I do not give those flags (for performance) +#define TRANSPARENCY_SAVEFLAGS \ + (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | \ + SkCanvas::kFullColorLayer_SaveFlag) + +//************************************** +// Helper functions +//************************************** + +static void setrectForUnderline(SkRect* r, float lineThickness, + const FloatPoint& point, int yOffset, float width) +{ +#if 0 + if (lineThickness < 1) // Do we really need/want this? + lineThickness = 1; +#endif + r->fLeft = point.x(); + r->fTop = point.y() + yOffset; + r->fRight = r->fLeft + width; + r->fBottom = r->fTop + lineThickness; +} + +static inline int fastMod(int value, int max) +{ + int sign = SkExtractSign(value); + + value = SkApplySign(value, sign); + if (value >= max) + value %= max; + return SkApplySign(value, sign); +} + +static inline void fixPaintForBitmapsThatMaySeam(SkPaint* paint) { + /* Bitmaps may be drawn to seem next to other images. If we are drawn + zoomed, or at fractional coordinates, we may see cracks/edges if + we antialias, because that will cause us to draw the same pixels + more than once (e.g. from the left and right bitmaps that share + an edge). + + Disabling antialiasing fixes this, and since so far we are never + rotated at non-multiple-of-90 angles, this seems to do no harm + */ + paint->setAntiAlias(false); +} + +//************************************** +// PlatformGraphicsContextSkia +//************************************** + +PlatformGraphicsContextSkia::PlatformGraphicsContextSkia(SkCanvas* canvas, + bool takeCanvasOwnership) + : PlatformGraphicsContext() + , mCanvas(canvas) + , m_deleteCanvas(takeCanvasOwnership) +{ + m_gc = 0; +} + +PlatformGraphicsContextSkia::~PlatformGraphicsContextSkia() +{ + if (m_deleteCanvas) + delete mCanvas; +} + +bool PlatformGraphicsContextSkia::isPaintingDisabled() +{ + return !mCanvas; +} + +//************************************** +// State management +//************************************** + +void PlatformGraphicsContextSkia::beginTransparencyLayer(float opacity) +{ + SkCanvas* canvas = mCanvas; + canvas->saveLayerAlpha(0, (int)(opacity * 255), TRANSPARENCY_SAVEFLAGS); +} + +void PlatformGraphicsContextSkia::endTransparencyLayer() +{ + if (!mCanvas) + return; + mCanvas->restore(); +} + +void PlatformGraphicsContextSkia::save() +{ + PlatformGraphicsContext::save(); + // Save our native canvas. + mCanvas->save(); +} + +void PlatformGraphicsContextSkia::restore() +{ + PlatformGraphicsContext::restore(); + // Restore our native canvas. + mCanvas->restore(); +} + +//************************************** +// Matrix operations +//************************************** + +void PlatformGraphicsContextSkia::concatCTM(const AffineTransform& affine) +{ + mCanvas->concat(affine); +} + +void PlatformGraphicsContextSkia::rotate(float angleInRadians) +{ + float value = angleInRadians * (180.0f / 3.14159265f); + mCanvas->rotate(SkFloatToScalar(value)); +} + +void PlatformGraphicsContextSkia::scale(const FloatSize& size) +{ + mCanvas->scale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height())); +} + +void PlatformGraphicsContextSkia::translate(float x, float y) +{ + mCanvas->translate(SkFloatToScalar(x), SkFloatToScalar(y)); +} + +const SkMatrix& PlatformGraphicsContextSkia::getTotalMatrix() +{ + return mCanvas->getTotalMatrix(); +} + +//************************************** +// Clipping +//************************************** + +void PlatformGraphicsContextSkia::addInnerRoundedRectClip(const IntRect& rect, + int thickness) +{ + SkPath path; + SkRect r(rect); + + path.addOval(r, SkPath::kCW_Direction); + // Only perform the inset if we won't invert r + if (2 * thickness < rect.width() && 2 * thickness < rect.height()) { + // Adding one to the thickness doesn't make the border too thick as + // it's painted over afterwards. But without this adjustment the + // border appears a little anemic after anti-aliasing. + r.inset(SkIntToScalar(thickness + 1), SkIntToScalar(thickness + 1)); + path.addOval(r, SkPath::kCCW_Direction); + } + mCanvas->clipPath(path, SkRegion::kIntersect_Op, true); +} + +void PlatformGraphicsContextSkia::canvasClip(const Path& path) +{ + clip(path); +} + +void PlatformGraphicsContextSkia::clip(const FloatRect& rect) +{ + mCanvas->clipRect(rect); +} + +void PlatformGraphicsContextSkia::clip(const Path& path) +{ + mCanvas->clipPath(*path.platformPath(), SkRegion::kIntersect_Op, true); +} + +void PlatformGraphicsContextSkia::clipConvexPolygon(size_t numPoints, + const FloatPoint*, bool antialias) +{ + if (numPoints <= 1) + return; + + // This is only used if HAVE_PATH_BASED_BORDER_RADIUS_DRAWING is defined + // in RenderObject.h which it isn't for us. TODO: Support that :) +} + +void PlatformGraphicsContextSkia::clipOut(const IntRect& r) +{ + mCanvas->clipRect(r, SkRegion::kDifference_Op); +} + +void PlatformGraphicsContextSkia::clipOut(const Path& path) +{ + mCanvas->clipPath(*path.platformPath(), SkRegion::kDifference_Op); +} + +void PlatformGraphicsContextSkia::clipPath(const Path& pathToClip, WindRule clipRule) +{ + SkPath path = *pathToClip.platformPath(); + path.setFillType(clipRule == RULE_EVENODD + ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType); + mCanvas->clipPath(path); +} +void PlatformGraphicsContextSkia::clearRect(const FloatRect& rect) +{ + SkPaint paint; + + setupPaintFill(&paint); + paint.setXfermodeMode(SkXfermode::kClear_Mode); + + mCanvas->drawRect(rect, paint); +} + +//************************************** +// Drawing +//************************************** + +void PlatformGraphicsContextSkia::drawBitmapPattern( + const SkBitmap& bitmap, const SkMatrix& matrix, + CompositeOperator compositeOp, const FloatRect& destRect) +{ + SkShader* shader = SkShader::CreateBitmapShader(bitmap, + SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode); + shader->setLocalMatrix(matrix); + SkPaint paint; + setupPaintFill(&paint); + paint.setShader(shader); + paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp)); + fixPaintForBitmapsThatMaySeam(&paint); + mCanvas->drawRect(destRect, paint); +} + +void PlatformGraphicsContextSkia::drawBitmapRect(const SkBitmap& bitmap, + const SkIRect* src, const SkRect& dst, + CompositeOperator op) +{ + SkPaint paint; + setupPaintFill(&paint); + paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(op)); + fixPaintForBitmapsThatMaySeam(&paint); + + mCanvas->drawBitmapRect(bitmap, src, dst, &paint); +} + +void PlatformGraphicsContextSkia::drawConvexPolygon(size_t numPoints, + const FloatPoint* points, + bool shouldAntialias) +{ + if (numPoints <= 1) + return; + + SkPaint paint; + SkPath path; + + path.incReserve(numPoints); + path.moveTo(SkFloatToScalar(points[0].x()), SkFloatToScalar(points[0].y())); + for (size_t i = 1; i < numPoints; i++) + path.lineTo(SkFloatToScalar(points[i].x()), SkFloatToScalar(points[i].y())); + + if (mCanvas->quickReject(path, shouldAntialias ? + SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType)) { + return; + } + + if (m_state->fillColor & 0xFF000000) { + setupPaintFill(&paint); + paint.setAntiAlias(shouldAntialias); + mCanvas->drawPath(path, paint); + } + + if (m_state->strokeStyle != NoStroke) { + paint.reset(); + setupPaintStroke(&paint, 0); + paint.setAntiAlias(shouldAntialias); + mCanvas->drawPath(path, paint); + } +} + +void PlatformGraphicsContextSkia::drawEllipse(const IntRect& rect) +{ + SkPaint paint; + SkRect oval(rect); + + if (m_state->fillColor & 0xFF000000) { + setupPaintFill(&paint); + mCanvas->drawOval(oval, paint); + } + if (m_state->strokeStyle != NoStroke) { + paint.reset(); + setupPaintStroke(&paint, &oval); + mCanvas->drawOval(oval, paint); + } +} + +void PlatformGraphicsContextSkia::drawFocusRing(const Vector<IntRect>& rects, + int /* width */, int /* offset */, + const Color& color) +{ + unsigned rectCount = rects.size(); + if (!rectCount) + return; + + SkRegion focusRingRegion; + const SkScalar focusRingOutset = WebCoreFloatToSkScalar(0.8); + for (unsigned i = 0; i < rectCount; i++) { + SkIRect r = rects[i]; + r.inset(-focusRingOutset, -focusRingOutset); + focusRingRegion.op(r, SkRegion::kUnion_Op); + } + + SkPath path; + SkPaint paint; + paint.setAntiAlias(true); + paint.setStyle(SkPaint::kStroke_Style); + + paint.setColor(color.rgb()); + paint.setStrokeWidth(focusRingOutset * 2); + paint.setPathEffect(new SkCornerPathEffect(focusRingOutset * 2))->unref(); + focusRingRegion.getBoundaryPath(&path); + mCanvas->drawPath(path, paint); +} + +void PlatformGraphicsContextSkia::drawHighlightForText( + const Font& font, const TextRun& run, const FloatPoint& point, int h, + const Color& backgroundColor, ColorSpace colorSpace, int from, + int to, bool isActive) +{ + IntRect rect = (IntRect)font.selectionRectForText(run, point, h, from, to); + if (isActive) + fillRect(rect, backgroundColor); + else { + int x = rect.x(), y = rect.y(), w = rect.width(), h = rect.height(); + const int t = 3, t2 = t * 2; + + fillRect(IntRect(x, y, w, t), backgroundColor); + fillRect(IntRect(x, y+h-t, w, t), backgroundColor); + fillRect(IntRect(x, y+t, t, h-t2), backgroundColor); + fillRect(IntRect(x+w-t, y+t, t, h-t2), backgroundColor); + } +} + +void PlatformGraphicsContextSkia::drawLine(const IntPoint& point1, + const IntPoint& point2) +{ + StrokeStyle style = m_state->strokeStyle; + if (style == NoStroke) + return; + + SkPaint paint; + SkCanvas* canvas = mCanvas; + const int idx = SkAbs32(point2.x() - point1.x()); + const int idy = SkAbs32(point2.y() - point1.y()); + + // Special-case horizontal and vertical lines that are really just dots + if (setupPaintStroke(&paint, 0, !idy) && (!idx || !idy)) { + const SkScalar diameter = paint.getStrokeWidth(); + const SkScalar radius = SkScalarHalf(diameter); + SkScalar x = SkIntToScalar(SkMin32(point1.x(), point2.x())); + SkScalar y = SkIntToScalar(SkMin32(point1.y(), point2.y())); + SkScalar dx, dy; + int count; + SkRect bounds; + + if (!idy) { // Horizontal + bounds.set(x, y - radius, x + SkIntToScalar(idx), y + radius); + x += radius; + dx = diameter * 2; + dy = 0; + count = idx; + } else { // Vertical + bounds.set(x - radius, y, x + radius, y + SkIntToScalar(idy)); + y += radius; + dx = 0; + dy = diameter * 2; + count = idy; + } + + // The actual count is the number of ONs we hit alternating + // ON(diameter), OFF(diameter), ... + { + SkScalar width = SkScalarDiv(SkIntToScalar(count), diameter); + // Now compute the number of cells (ON and OFF) + count = SkScalarRound(width); + // Now compute the number of ONs + count = (count + 1) >> 1; + } + + SkAutoMalloc storage(count * sizeof(SkPoint)); + SkPoint* verts = (SkPoint*)storage.get(); + // Now build the array of vertices to past to drawPoints + for (int i = 0; i < count; i++) { + verts[i].set(x, y); + x += dx; + y += dy; + } + + paint.setStyle(SkPaint::kFill_Style); + paint.setPathEffect(0); + + // Clipping to bounds is not required for correctness, but it does + // allow us to reject the entire array of points if we are completely + // offscreen. This is common in a webpage for android, where most of + // the content is clipped out. If drawPoints took an (optional) bounds + // parameter, that might even be better, as we would *just* use it for + // culling, and not both wacking the canvas' save/restore stack. + canvas->save(SkCanvas::kClip_SaveFlag); + canvas->clipRect(bounds); + canvas->drawPoints(SkCanvas::kPoints_PointMode, count, verts, paint); + canvas->restore(); + } else { + SkPoint pts[2] = { point1, point2 }; + canvas->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint); + } +} + +void PlatformGraphicsContextSkia::drawLineForText(const FloatPoint& pt, float width) +{ + SkRect r; + setrectForUnderline(&r, m_state->strokeThickness, pt, 0, width); + + SkPaint paint; + paint.setAntiAlias(true); + paint.setColor(m_state->strokeColor); + + mCanvas->drawRect(r, paint); +} + +void PlatformGraphicsContextSkia::drawLineForTextChecking(const FloatPoint& pt, + float width, GraphicsContext::TextCheckingLineStyle) +{ + // TODO: Should we draw different based on TextCheckingLineStyle? + SkRect r; + setrectForUnderline(&r, m_state->strokeThickness, pt, 0, width); + + SkPaint paint; + paint.setAntiAlias(true); + paint.setColor(SK_ColorRED); // Is this specified somewhere? + + mCanvas->drawRect(r, paint); +} + +void PlatformGraphicsContextSkia::drawRect(const IntRect& rect) +{ + SkPaint paint; + SkRect r(rect); + + if (m_state->fillColor & 0xFF000000) { + setupPaintFill(&paint); + mCanvas->drawRect(r, paint); + } + + // According to GraphicsContext.h, stroking inside drawRect always means + // a stroke of 1 inside the rect. + if (m_state->strokeStyle != NoStroke && (m_state->strokeColor & 0xFF000000)) { + paint.reset(); + setupPaintStroke(&paint, &r); + paint.setPathEffect(0); // No dashing please + paint.setStrokeWidth(SK_Scalar1); // Always just 1.0 width + r.inset(SK_ScalarHalf, SK_ScalarHalf); // Ensure we're "inside" + mCanvas->drawRect(r, paint); + } +} + +void PlatformGraphicsContextSkia::fillPath(const Path& pathToFill, WindRule fillRule) +{ + SkPath* path = pathToFill.platformPath(); + if (!path) + return; + + switch (fillRule) { + case RULE_NONZERO: + path->setFillType(SkPath::kWinding_FillType); + break; + case RULE_EVENODD: + path->setFillType(SkPath::kEvenOdd_FillType); + break; + } + + SkPaint paint; + setupPaintFill(&paint); + + mCanvas->drawPath(*path, paint); +} + +void PlatformGraphicsContextSkia::fillRect(const FloatRect& rect) +{ + SkPaint paint; + setupPaintFill(&paint); + mCanvas->drawRect(rect, paint); +} + +void PlatformGraphicsContextSkia::fillRect(const FloatRect& rect, + const Color& color) +{ + if (color.rgb() & 0xFF000000) { + SkPaint paint; + + setupPaintCommon(&paint); + paint.setColor(color.rgb()); // Punch in the specified color + paint.setShader(0); // In case we had one set + + // Sometimes we record and draw portions of the page, using clips + // for each portion. The problem with this is that webkit, sometimes, + // sees that we're only recording a portion, and they adjust some of + // their rectangle coordinates accordingly (e.g. + // RenderBoxModelObject::paintFillLayerExtended() which calls + // rect.intersect(paintInfo.rect) and then draws the bg with that + // rect. The result is that we end up drawing rects that are meant to + // seam together (one for each portion), but if the rects have + // fractional coordinates (e.g. we are zoomed by a fractional amount) + // we will double-draw those edges, resulting in visual cracks or + // artifacts. + + // The fix seems to be to just turn off antialasing for rects (this + // entry-point in GraphicsContext seems to have been sufficient, + // though perhaps we'll find we need to do this as well in fillRect(r) + // as well.) Currently setupPaintCommon() enables antialiasing. + + // Since we never show the page rotated at a funny angle, disabling + // antialiasing seems to have no real down-side, and it does fix the + // bug when we're zoomed (and drawing portions that need to seam). + paint.setAntiAlias(false); + + mCanvas->drawRect(rect, paint); + } +} + +void PlatformGraphicsContextSkia::fillRoundedRect( + const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, + const IntSize& bottomLeft, const IntSize& bottomRight, + const Color& color) +{ + SkPaint paint; + SkPath path; + SkScalar radii[8]; + + radii[0] = SkIntToScalar(topLeft.width()); + radii[1] = SkIntToScalar(topLeft.height()); + radii[2] = SkIntToScalar(topRight.width()); + radii[3] = SkIntToScalar(topRight.height()); + radii[4] = SkIntToScalar(bottomRight.width()); + radii[5] = SkIntToScalar(bottomRight.height()); + radii[6] = SkIntToScalar(bottomLeft.width()); + radii[7] = SkIntToScalar(bottomLeft.height()); + path.addRoundRect(rect, radii); + + setupPaintFill(&paint); + paint.setColor(color.rgb()); + mCanvas->drawPath(path, paint); +} + +void PlatformGraphicsContextSkia::strokeArc(const IntRect& r, int startAngle, + int angleSpan) +{ + SkPath path; + SkPaint paint; + SkRect oval(r); + + if (m_state->strokeStyle == NoStroke) { + setupPaintFill(&paint); // We want the fill color + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeWidth(SkFloatToScalar(m_state->strokeThickness)); + } else + setupPaintStroke(&paint, 0); + + // We do this before converting to scalar, so we don't overflow SkFixed + startAngle = fastMod(startAngle, 360); + angleSpan = fastMod(angleSpan, 360); + + path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan)); + mCanvas->drawPath(path, paint); +} + +void PlatformGraphicsContextSkia::strokePath(const Path& pathToStroke) +{ + const SkPath* path = pathToStroke.platformPath(); + if (!path) + return; + + SkPaint paint; + setupPaintStroke(&paint, 0); + + mCanvas->drawPath(*path, paint); +} + +void PlatformGraphicsContextSkia::strokeRect(const FloatRect& rect, float lineWidth) +{ + SkPaint paint; + + setupPaintStroke(&paint, 0); + paint.setStrokeWidth(SkFloatToScalar(lineWidth)); + mCanvas->drawRect(rect, paint); +} + +} // WebCore diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h new file mode 100644 index 0000000..724e20b --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h @@ -0,0 +1,115 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef platform_graphics_context_skia_h +#define platform_graphics_context_skia_h + +#include "PlatformGraphicsContext.h" + +namespace WebCore { + +class PlatformGraphicsContextSkia : public PlatformGraphicsContext { +public: + PlatformGraphicsContextSkia(SkCanvas* canvas, bool takeCanvasOwnership = false); + virtual ~PlatformGraphicsContextSkia(); + virtual bool isPaintingDisabled(); + virtual SkCanvas* getCanvas() { return mCanvas; } + + virtual ContextType type() { return PaintingContext; } + virtual SkCanvas* recordingCanvas() { return mCanvas; } + virtual void endRecording(int type = 0) {} + + // FIXME: This is used by ImageBufferAndroid, which should really be + // managing the canvas lifecycle itself + + virtual bool deleteUs() const { return m_deleteCanvas; } + + // State management + virtual void beginTransparencyLayer(float opacity); + virtual void endTransparencyLayer(); + virtual void save(); + virtual void restore(); + + // Matrix operations + virtual void concatCTM(const AffineTransform& affine); + virtual void rotate(float angleInRadians); + virtual void scale(const FloatSize& size); + virtual void translate(float x, float y); + virtual const SkMatrix& getTotalMatrix(); + + // Clipping + virtual void addInnerRoundedRectClip(const IntRect& rect, int thickness); + virtual void canvasClip(const Path& path); + virtual void clip(const FloatRect& rect); + virtual void clip(const Path& path); + virtual void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias); + virtual void clipOut(const IntRect& r); + virtual void clipOut(const Path& p); + virtual void clipPath(const Path& pathToClip, WindRule clipRule); + + // Drawing + virtual void clearRect(const FloatRect& rect); + virtual void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix, + CompositeOperator compositeOp, const FloatRect& destRect); + virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, + const SkRect& dst, CompositeOperator op); + virtual void drawConvexPolygon(size_t numPoints, const FloatPoint* points, + bool shouldAntialias); + virtual void drawEllipse(const IntRect& rect); + virtual void drawFocusRing(const Vector<IntRect>& rects, int /* width */, + int /* offset */, const Color& color); + virtual void drawHighlightForText(const Font& font, const TextRun& run, + const FloatPoint& point, int h, + const Color& backgroundColor, ColorSpace colorSpace, + int from, int to, bool isActive); + virtual void drawLine(const IntPoint& point1, const IntPoint& point2); + virtual void drawLineForText(const FloatPoint& pt, float width); + virtual void drawLineForTextChecking(const FloatPoint& pt, float width, + GraphicsContext::TextCheckingLineStyle); + virtual void drawRect(const IntRect& rect); + virtual void fillPath(const Path& pathToFill, WindRule fillRule); + virtual void fillRect(const FloatRect& rect); + virtual void fillRect(const FloatRect& rect, const Color& color); + virtual void fillRoundedRect(const IntRect& rect, const IntSize& topLeft, + const IntSize& topRight, const IntSize& bottomLeft, + const IntSize& bottomRight, const Color& color); + virtual void strokeArc(const IntRect& r, int startAngle, int angleSpan); + virtual void strokePath(const Path& pathToStroke); + virtual void strokeRect(const FloatRect& rect, float lineWidth); + +private: + + // shadowsIgnoreTransforms is only true for canvas's ImageBuffer, which will + // have a GraphicsContext + virtual bool shadowsIgnoreTransforms() const { + return m_gc && m_gc->shadowsIgnoreTransforms(); + } + + SkCanvas* mCanvas; + bool m_deleteCanvas; +}; + +} +#endif diff --git a/Source/WebCore/platform/graphics/android/android_graphics.h b/Source/WebCore/platform/graphics/android/context/android_graphics.h index 7faa781..7faa781 100644 --- a/Source/WebCore/platform/graphics/android/android_graphics.h +++ b/Source/WebCore/platform/graphics/android/context/android_graphics.h diff --git a/Source/WebCore/platform/graphics/android/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp index c8b9488..3146612 100644 --- a/Source/WebCore/platform/graphics/android/FontAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp @@ -27,6 +27,8 @@ #include "config.h" #include "EmojiFont.h" +#include "GraphicsOperationCollection.h" +#include "GraphicsOperation.h" #include "Font.h" #include "FontData.h" #include "FontFallbackList.h" @@ -196,7 +198,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, SkAutoSTMalloc<32, SkPoint> storage(numGlyphs), storage2(numGlyphs), storage3(numGlyphs); SkPoint* pos = storage.get(); - SkCanvas* canvas = gc->platformContext()->mCanvas; + SkCanvas* canvas = gc->platformContext()->recordingCanvas(); /* We need an array of [x,y,x,y,x,y,...], but webkit is giving us point.xy + [width, height, width, height, ...], so we have to convert @@ -254,6 +256,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, if (font->platformData().orientation() == Vertical) canvas->restore(); } + gc->platformContext()->endRecording(); } void Font::drawEmphasisMarksForComplexText(WebCore::GraphicsContext*, WebCore::TextRun const&, WTF::AtomicString const&, WebCore::FloatPoint const&, int, int) const @@ -1054,7 +1057,8 @@ void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, if (stroke) setupStroke(&strokePaint, gc, primaryFont()); - SkCanvas* canvas = gc->platformContext()->mCanvas; + SkCanvas* canvas = gc->platformContext()->recordingCanvas(); + bool haveMultipleLayers = isCanvasMultiLayered(canvas); TextRunWalker walker(run, point.x(), point.y(), this); walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); @@ -1074,6 +1078,8 @@ void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, walker.positions(), strokePaint); } } + + gc->platformContext()->endRecording(); } float Font::floatWidthForComplexText(const TextRun& run, diff --git a/Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontCacheAndroid.cpp index 5696a46..5696a46 100644 --- a/Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/fonts/FontCacheAndroid.cpp diff --git a/Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.cpp index 693386e..693386e 100644 --- a/Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp +++ b/Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.cpp diff --git a/Source/WebCore/platform/graphics/android/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.h index 47e5e71..47e5e71 100644 --- a/Source/WebCore/platform/graphics/android/FontCustomPlatformData.h +++ b/Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.h diff --git a/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontDataAndroid.cpp index c6dd174..88822df 100644 --- a/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/fonts/FontDataAndroid.cpp @@ -56,8 +56,12 @@ void SimpleFontData::platformInit() m_fontMetrics.setAscent(a); m_fontMetrics.setDescent(d); m_fontMetrics.setXHeight(SkScalarToFloat(-skiaFontMetrics.fAscent) * 0.56f); // hack I stole from the window's port - m_fontMetrics.setLineSpacing(a + d); - m_fontMetrics.setLineGap(SkScalarToFloat(skiaFontMetrics.fLeading)); + float lineGap = SkScalarToFloat(skiaFontMetrics.fLeading); + if (platformData().orientation() == Vertical && lineGap == 0) { + lineGap = skiaFontMetrics.fAvgCharWidth * 0.56f; + } + m_fontMetrics.setLineGap(lineGap); + m_fontMetrics.setLineSpacing(a + d + lineGap); if (platformData().orientation() == Vertical && !isTextOrientationFallback()) { static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a'); diff --git a/Source/WebCore/platform/graphics/android/FontPlatformData.h b/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h index 1e46971..1e46971 100644 --- a/Source/WebCore/platform/graphics/android/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h diff --git a/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp index fc254c0..fc254c0 100644 --- a/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp diff --git a/Source/WebCore/platform/graphics/android/GlyphMapAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/GlyphMapAndroid.cpp index a327b79..b9798e6 100644 --- a/Source/WebCore/platform/graphics/android/GlyphMapAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/fonts/GlyphMapAndroid.cpp @@ -44,12 +44,12 @@ namespace WebCore { #define NO_BREAK_SPACE_UNICHAR 0xA0 -static int substituteWithVerticalGlyphs(const FontPlatformData& platformData, uint16_t* glyphs, unsigned bufferLength) +static HB_Error substituteWithVerticalGlyphs(const FontPlatformData& platformData, uint16_t* glyphs, unsigned bufferLength) { HB_FaceRec_* hbFace = platformData.harfbuzzFace(); if (!hbFace->gsub) { // if there is no GSUB table, treat it as not covered - return 0Xffff; + return static_cast<HB_Error>(0Xffff); } HB_Buffer buffer; @@ -60,13 +60,19 @@ static int substituteWithVerticalGlyphs(const FontPlatformData& platformData, ui HB_UShort scriptIndex; HB_UShort featureIndex; - HB_GSUB_Select_Script(hbFace->gsub, HB_MAKE_TAG('D', 'F', 'L', 'T'), &scriptIndex); + HB_Error error = HB_GSUB_Select_Script(hbFace->gsub, HB_MAKE_TAG('D', 'F', 'L', 'T'), &scriptIndex); + if (error) { + if (error != HB_Err_Not_Covered) + return error; + scriptIndex = HB_Script_Common; // Set script to common script. + } + HB_GSUB_Select_Feature(hbFace->gsub, HB_MAKE_TAG('v', 'e', 'r', 't'), scriptIndex, 0xffff, &featureIndex); HB_GSUB_Add_Feature(hbFace->gsub, featureIndex, 1); HB_GSUB_Select_Feature(hbFace->gsub, HB_MAKE_TAG('v', 'r', 't', '2'), scriptIndex, 0xffff, &featureIndex); HB_GSUB_Add_Feature(hbFace->gsub, featureIndex, 1); - int error = HB_GSUB_Apply_String(hbFace->gsub, buffer); + error = HB_GSUB_Apply_String(hbFace->gsub, buffer); if (!error) { for (unsigned i = 0; i < bufferLength; ++i) glyphs[i] = static_cast<Glyph>(buffer->out_string[i].gindex); @@ -74,6 +80,14 @@ static int substituteWithVerticalGlyphs(const FontPlatformData& platformData, ui return error; } +static void convertToVerticalForms(UChar* src, UChar* dest, unsigned bufferLength) { + for (unsigned i = 0; i < bufferLength; ++i) { + dest[i] = VerticalTextMap::getVerticalForm(src[i]); + if (!dest[i]) + dest[i] = src[i]; + } +} + bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) { if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) { @@ -92,11 +106,7 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b if (fontData->platformData().orientation() == Vertical && !fontData->hasVerticalGlyphs()) { // Convert to vertical form if there is no vertical glyphs. - for (unsigned i = 0; i < bufferLength; ++i) { - vTextBuffer[i] = VerticalTextMap::getVerticalForm(buffer[i]); - if (!vTextBuffer[i]) - vTextBuffer[i] = buffer[i]; - } + convertToVerticalForms(buffer, vTextBuffer, bufferLength); textBuffer = vTextBuffer; } @@ -111,11 +121,22 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b for (unsigned i = 0; i < bufferLength; ++i) { if (!Font::isCJKIdeograph(textBuffer[i])) { lookVariants = true; - continue; + break; + } + } + if (lookVariants) { + if (substituteWithVerticalGlyphs(fontData->platformData(), glyphs, bufferLength)) { + // Convert text to vertical forms if substituteWithVerticalGlyphs() fails to access vert tables. + convertToVerticalForms(buffer, vTextBuffer, bufferLength); + textBuffer = vTextBuffer; + + unsigned count = paint.textToGlyphs(textBuffer, bufferLength << 1, glyphs); + if (count != length) { + SkDebugf("%s count != length\n", __FUNCTION__); + return false; + } } } - if (lookVariants) - substituteWithVerticalGlyphs(fontData->platformData(), glyphs, bufferLength); } unsigned allGlyphs = 0; // track if any of the glyphIDs are non-zero diff --git a/Source/WebCore/platform/graphics/android/HarfbuzzSkia.cpp b/Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.cpp index 7c3a6b4..7c3a6b4 100644 --- a/Source/WebCore/platform/graphics/android/HarfbuzzSkia.cpp +++ b/Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.cpp diff --git a/Source/WebCore/platform/graphics/android/HarfbuzzSkia.h b/Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.h index d26bbe2..d26bbe2 100644 --- a/Source/WebCore/platform/graphics/android/HarfbuzzSkia.h +++ b/Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.h diff --git a/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp b/Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.cpp index 42aa385..42aa385 100644 --- a/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp +++ b/Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.cpp diff --git a/Source/WebCore/platform/graphics/android/VerticalTextMap.h b/Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.h index 2955589..2955589 100644 --- a/Source/WebCore/platform/graphics/android/VerticalTextMap.h +++ b/Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.h diff --git a/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp b/Source/WebCore/platform/graphics/android/layers/AndroidAnimation.cpp index 0ef84b9..0ef84b9 100644 --- a/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp +++ b/Source/WebCore/platform/graphics/android/layers/AndroidAnimation.cpp diff --git a/Source/WebCore/platform/graphics/android/AndroidAnimation.h b/Source/WebCore/platform/graphics/android/layers/AndroidAnimation.h index dca769f..dca769f 100644 --- a/Source/WebCore/platform/graphics/android/AndroidAnimation.h +++ b/Source/WebCore/platform/graphics/android/layers/AndroidAnimation.h diff --git a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp new file mode 100644 index 0000000..ce520b4 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp @@ -0,0 +1,69 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "BaseLayerAndroid" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "BaseLayerAndroid.h" + +#include "AndroidLog.h" +#include "GLWebViewState.h" +#include "LayerContent.h" + +namespace WebCore { + +// Note: this must match the use of ID 0 specifying the base layer in DrawExtra +#define BASE_UNIQUE_ID 0 + +BaseLayerAndroid::BaseLayerAndroid(LayerContent* content) + : LayerAndroid((RenderLayer*)0) + , m_color(Color::white) +{ + setContent(content); + setSize(content->width(), content->height()); + m_uniqueId = BASE_UNIQUE_ID; +} + +void BaseLayerAndroid::getLocalTransform(SkMatrix* matrix) const +{ + // base layer doesn't use size in transform calculation + matrix->preConcat(getMatrix()); +} + +IFrameLayerAndroid* BaseLayerAndroid::updatePosition(SkRect viewport, + IFrameLayerAndroid* parentIframeLayer) +{ + if (viewport.fRight > getWidth() || viewport.fBottom > getHeight()) { + // To handle the viewport expanding past the layer's size with HW accel, + // expand the size of the layer, so that tiles will cover the viewport. + setSize(std::max(viewport.fRight, getWidth()), + std::max(viewport.fBottom, getHeight())); + } + + return LayerAndroid::updatePosition(viewport, parentIframeLayer); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h new file mode 100644 index 0000000..f4cf9f3 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h @@ -0,0 +1,61 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BaseLayerAndroid_h +#define BaseLayerAndroid_h + +#include "Color.h" +#include "LayerAndroid.h" + +namespace WebCore { + +class RenderLayerCompositor; + +class BaseLayerAndroid : public LayerAndroid { + +public: + BaseLayerAndroid(LayerContent* content); + + virtual ~BaseLayerAndroid() {}; + + virtual SubclassType subclassType() { return LayerAndroid::BaseLayer; } + virtual bool needsTexture() { return true; } + + void setBackgroundColor(Color& color) { m_color = color; } + Color getBackgroundColor() { return m_color; } + + virtual void getLocalTransform(SkMatrix* matrix) const; + virtual const TransformationMatrix* drawTransform() const { return 0; } + + virtual IFrameLayerAndroid* updatePosition(SkRect viewport, + IFrameLayerAndroid* parentIframeLayer); +private: + // TODO: move to SurfaceCollection. + Color m_color; +}; + +} // namespace WebCore + +#endif //BaseLayerAndroid_h diff --git a/Source/WebCore/platform/graphics/android/layers/CanvasLayer.cpp b/Source/WebCore/platform/graphics/android/layers/CanvasLayer.cpp new file mode 100644 index 0000000..1813903 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/CanvasLayer.cpp @@ -0,0 +1,220 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "CanvasLayer" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "CanvasLayer.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "CanvasTexture.h" +#include "DrawQuadData.h" +#include "Image.h" +#include "ImageBuffer.h" +#include "RenderLayerCompositor.h" +#include "SkBitmap.h" +#include "SkBitmapRef.h" +#include "SkCanvas.h" +#include "TilesManager.h" + +namespace WebCore { + +CanvasLayer::CanvasLayer(RenderLayer* owner, HTMLCanvasElement* canvas) + : LayerAndroid(owner) + , m_canvas(canvas) + , m_dirtyCanvas() + , m_bitmap(0) +{ + init(); + m_canvas->addObserver(this); +} + +CanvasLayer::CanvasLayer(const CanvasLayer& layer) + : LayerAndroid(layer) + , m_canvas(0) + , m_bitmap(0) +{ + init(); + if (!layer.m_canvas) { + // The canvas has already been destroyed - this shouldn't happen + ALOGW("Creating a CanvasLayer for a destroyed canvas!"); + m_contentRect = IntRect(); + m_offsetFromRenderer = IntSize(); + m_texture->setHwAccelerated(false); + return; + } + // We are making a copy for the UI, sync the interesting bits + m_contentRect = layer.contentRect(); + m_offsetFromRenderer = layer.offsetFromRenderer(); + bool previousState = m_texture->hasValidTexture(); + if (!previousState && layer.m_dirtyCanvas.isEmpty()) { + // We were previously in software and don't have anything new to draw, + // so stay in software + m_bitmap = layer.bitmap(); + SkSafeRef(m_bitmap); + } else { + // Attempt to upload to a surface texture + if (!m_texture->uploadImageBuffer(layer.m_canvas->buffer())) { + // Blargh, no surface texture or ImageBuffer - fall back to software + m_bitmap = layer.bitmap(); + SkSafeRef(m_bitmap); + // Merge the canvas invals with the layer's invals to repaint the needed + // tiles. + SkRegion::Iterator iter(layer.m_dirtyCanvas); + const IntPoint& offset = m_contentRect.location(); + for (; !iter.done(); iter.next()) { + SkIRect diff = iter.rect(); + diff.fLeft += offset.x(); + diff.fRight += offset.x(); + diff.fTop += offset.y(); + diff.fBottom += offset.y(); + m_dirtyRegion.op(diff, SkRegion::kUnion_Op); + } + } + if (previousState != m_texture->hasValidTexture()) { + // Need to do a full inval of the canvas content as we are mode switching + m_dirtyRegion.op(m_contentRect.x(), m_contentRect.y(), + m_contentRect.maxX(), m_contentRect.maxY(), SkRegion::kUnion_Op); + } + } +} + +CanvasLayer::~CanvasLayer() +{ + if (m_canvas) + m_canvas->removeObserver(this); + SkSafeUnref(m_bitmap); +} + +void CanvasLayer::init() +{ + m_texture = CanvasTexture::getCanvasTexture(this); +} + +void CanvasLayer::canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect) +{ + if (!m_texture->hasValidTexture()) { + // We only need to track invals if we aren't using a SurfaceTexture. + // If we drop out of hwa, we will do a full inval anyway + SkIRect irect = SkIRect::MakeXYWH(changedRect.x(), changedRect.y(), + changedRect.width(), changedRect.height()); + m_dirtyCanvas.op(irect, SkRegion::kUnion_Op); + } + owningLayer()->compositor()->scheduleLayerFlush(); +} + +void CanvasLayer::canvasResized(HTMLCanvasElement*) +{ + const IntSize& size = m_canvas->size(); + m_dirtyCanvas.setRect(0, 0, size.width(), size.height()); + // If we are smaller than one tile, don't bother using a surface texture + if (size.width() <= TilesManager::tileWidth() + && size.height() <= TilesManager::tileHeight()) + m_texture->setSize(IntSize()); + else + m_texture->setSize(size); +} + +void CanvasLayer::canvasDestroyed(HTMLCanvasElement*) +{ + m_canvas = 0; +} + +void CanvasLayer::clearDirtyRegion() +{ + LayerAndroid::clearDirtyRegion(); + m_dirtyCanvas.setEmpty(); + if (m_canvas) + m_canvas->clearDirtyRect(); +} + +SkBitmapRef* CanvasLayer::bitmap() const +{ + if (!m_canvas || !m_canvas->buffer()) + return 0; + return m_canvas->copiedImage()->nativeImageForCurrentFrame(); +} + +IntRect CanvasLayer::contentRect() const +{ + if (!m_canvas + || !m_canvas->renderer() + || !m_canvas->renderer()->style() + || !m_canvas->inDocument() + || m_canvas->renderer()->style()->visibility() != VISIBLE) + return IntRect(); + return m_canvas->renderBox()->contentBoxRect(); +} + +IntSize CanvasLayer::offsetFromRenderer() const +{ + return m_canvas->renderBox()->layer()->backing()->graphicsLayer()->offsetFromRenderer(); +} + +bool CanvasLayer::needsTexture() +{ + return m_bitmap || LayerAndroid::needsTexture(); +} + +void CanvasLayer::contentDraw(SkCanvas* canvas, PaintStyle style) +{ + LayerAndroid::contentDraw(canvas, style); + if (!m_bitmap) + return; + SkBitmap& bitmap = m_bitmap->bitmap(); + SkRect dst = SkRect::MakeXYWH(m_contentRect.x() - m_offsetFromRenderer.width(), + m_contentRect.y() - m_offsetFromRenderer.height(), + m_contentRect.width(), m_contentRect.height()); + canvas->drawBitmapRect(bitmap, 0, dst, 0); +} + +bool CanvasLayer::drawGL(bool layerTilesDisabled) +{ + bool ret = LayerAndroid::drawGL(layerTilesDisabled); + m_texture->requireTexture(); + if (!m_bitmap && m_texture->updateTexImage()) { + SkRect rect = SkRect::MakeXYWH(m_contentRect.x() - m_offsetFromRenderer.width(), + m_contentRect.y() - m_offsetFromRenderer.height(), + m_contentRect.width(), m_contentRect.height()); + TextureQuadData data(m_texture->texture(), GL_TEXTURE_EXTERNAL_OES, + GL_LINEAR, LayerQuad, &m_drawTransform, &rect); + TilesManager::instance()->shader()->drawQuad(&data); + } + return ret; +} + +LayerAndroid::InvalidateFlags CanvasLayer::onSetHwAccelerated(bool hwAccelerated) +{ + if (m_texture->setHwAccelerated(hwAccelerated)) + return LayerAndroid::InvalidateLayers; + return LayerAndroid::InvalidateNone; +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/CanvasLayer.h b/Source/WebCore/platform/graphics/android/layers/CanvasLayer.h new file mode 100644 index 0000000..532dbf2 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/CanvasLayer.h @@ -0,0 +1,81 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CanvasLayer_h +#define CanvasLayer_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "HTMLCanvasElement.h" +#include "ImageData.h" +#include "LayerAndroid.h" +#include "RenderLayer.h" + +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CanvasTexture; + +class CanvasLayer : public LayerAndroid, private CanvasObserver { +public: + CanvasLayer(RenderLayer* owner, HTMLCanvasElement* canvas); + CanvasLayer(const CanvasLayer& layer); + virtual ~CanvasLayer(); + + virtual LayerAndroid* copy() const { return new CanvasLayer(*this); } + virtual SubclassType subclassType() { return LayerAndroid::CanvasLayer; } + virtual void clearDirtyRegion(); + + virtual bool drawGL(bool layerTilesDisabled); + virtual void contentDraw(SkCanvas* canvas, PaintStyle style); + virtual bool needsTexture(); + +protected: + virtual InvalidateFlags onSetHwAccelerated(bool hwAccelerated); + +private: + virtual void canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect); + virtual void canvasResized(HTMLCanvasElement*); + virtual void canvasDestroyed(HTMLCanvasElement*); + + void init(); + SkBitmapRef* bitmap() const; + IntRect contentRect() const; + IntSize offsetFromRenderer() const; + + HTMLCanvasElement* m_canvas; + IntRect m_contentRect; + IntSize m_offsetFromRenderer; + SkRegion m_dirtyCanvas; + SkBitmapRef* m_bitmap; + RefPtr<CanvasTexture> m_texture; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // CanvasLayer_h diff --git a/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp new file mode 100644 index 0000000..e4b2bc6 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp @@ -0,0 +1,225 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "CanvasTexture" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "CanvasTexture.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "android_graphics.h" +#include "AndroidLog.h" +#include "GLUtils.h" +#include "Image.h" +#include "ImageBuffer.h" +#include "SkBitmap.h" +#include "SkBitmapRef.h" +#include "SkDevice.h" +#include "SkPixelRef.h" + +#include <android/native_window.h> +#include <gui/SurfaceTexture.h> +#include <gui/SurfaceTextureClient.h> + +namespace WebCore { + +static int s_maxTextureSize = 0; +static HashMap<int, CanvasTexture*> s_textures; +static android::Mutex s_texturesLock; + +/******************************************** + * Called by both threads + ********************************************/ + +PassRefPtr<CanvasTexture> CanvasTexture::getCanvasTexture(CanvasLayer* layer) +{ + android::Mutex::Autolock lock(s_texturesLock); + RefPtr<CanvasTexture> texture = s_textures.get(layer->uniqueId()); + if (texture.get()) + return texture.release(); + return adoptRef(new CanvasTexture(layer->uniqueId())); +} + +bool CanvasTexture::setHwAccelerated(bool hwAccelerated) +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (m_useHwAcceleration == hwAccelerated) + return false; + m_useHwAcceleration = hwAccelerated; + if (!m_ANW.get()) + return false; + destroySurfaceTextureLocked(); + return true; +} + +/******************************************** + * Called by WebKit thread + ********************************************/ + +void CanvasTexture::setSize(const IntSize& size) +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (m_size == size) + return; + m_size = size; + if (m_ANW.get()) { + if (useSurfaceTexture()) { + int result = native_window_set_buffers_dimensions(m_ANW.get(), + m_size.width(), m_size.height()); + GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result); + if (result != NO_ERROR) + m_useHwAcceleration = false; // On error, drop out of HWA + } + if (!useSurfaceTexture()) + destroySurfaceTextureLocked(); + } +} + +SurfaceTextureClient* CanvasTexture::nativeWindow() +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (m_ANW.get()) + return m_ANW.get(); + if (!m_texture) + return 0; + if (!useSurfaceTexture()) + return 0; + m_surfaceTexture = new android::SurfaceTexture(m_texture, false); + m_ANW = new android::SurfaceTextureClient(m_surfaceTexture); + int result = native_window_set_buffers_format(m_ANW.get(), HAL_PIXEL_FORMAT_RGBA_8888); + GLUtils::checkSurfaceTextureError("native_window_set_buffers_format", result); + if (result == NO_ERROR) { + result = native_window_set_buffers_dimensions(m_ANW.get(), + m_size.width(), m_size.height()); + GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result); + } + if (result != NO_ERROR) { + m_useHwAcceleration = false; + destroySurfaceTextureLocked(); + return 0; + } + return m_ANW.get(); +} + +bool CanvasTexture::uploadImageBuffer(ImageBuffer* imageBuffer) +{ + m_hasValidTexture = false; + SurfaceTextureClient* anw = nativeWindow(); + if (!anw) + return false; + // Size mismatch, early abort (will fall back to software) + if (imageBuffer->size() != m_size) + return false; + GraphicsContext* gc = imageBuffer ? imageBuffer->context() : 0; + if (!gc) + return false; + const SkBitmap& bitmap = android_gc2canvas(gc)->getDevice()->accessBitmap(false); + if (!GLUtils::updateSharedSurfaceTextureWithBitmap(anw, bitmap)) + return false; + m_hasValidTexture = true; + return true; +} + +/******************************************** + * Called by UI thread WITH GL context + ********************************************/ + +CanvasTexture::~CanvasTexture() +{ + if (m_layerId) { + s_texturesLock.lock(); + s_textures.remove(m_layerId); + s_texturesLock.unlock(); + } + if (m_texture) + GLUtils::deleteTexture(&m_texture); +} + +void CanvasTexture::requireTexture() +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (!m_texture) + glGenTextures(1, &m_texture); + if (!s_maxTextureSize) + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &s_maxTextureSize); +} + +bool CanvasTexture::updateTexImage() +{ + android::Mutex::Autolock lock(m_surfaceLock); + if (!m_surfaceTexture.get()) + return false; + status_t result = m_surfaceTexture->updateTexImage(); + if (result != OK) { + ALOGE("unexpected error: updateTexImage return %d", result); + return false; + } + return true; +} + +/******************************************** + * Called by both threads + ********************************************/ + +void CanvasTexture::destroySurfaceTextureLocked() +{ + if (m_ANW.get()) { + m_ANW.clear(); + m_surfaceTexture->abandon(); + m_surfaceTexture.clear(); + } +} + +/******************************************** + * Called by WebKit thread + ********************************************/ + +CanvasTexture::CanvasTexture(int layerId) + : m_size() + , m_layerId(layerId) + , m_texture(0) + , m_surfaceTexture(0) + , m_ANW(0) + , m_hasValidTexture(false) + , m_useHwAcceleration(true) +{ + s_textures.add(m_layerId, this); +} + +// TODO: Have a global limit as well as a way to react to low memory situations +bool CanvasTexture::useSurfaceTexture() +{ + if (!m_useHwAcceleration) + return false; + if (m_size.isEmpty()) + return false; + return (m_size.width() < s_maxTextureSize) && (m_size.height() < s_maxTextureSize); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/layers/CanvasTexture.h b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.h new file mode 100644 index 0000000..98962a0 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.h @@ -0,0 +1,95 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CanvasTexture_h +#define CanvasTexture_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "CanvasLayer.h" + +#include <wtf/RefPtr.h> +#include <utils/threads.h> + +namespace android { +class SurfaceTexture; +class SurfaceTextureClient; +} + +namespace WebCore { + +class CanvasTexture : public ThreadSafeRefCounted<CanvasTexture> { + +public: + /******************************************** + * Called by both threads + ********************************************/ + static PassRefPtr<CanvasTexture> getCanvasTexture(CanvasLayer* layer); + bool setHwAccelerated(bool hwAccelerated); + + /******************************************** + * Called by WebKit thread + ********************************************/ + void setSize(const IntSize& size); + SurfaceTextureClient* nativeWindow(); + bool uploadImageBuffer(ImageBuffer* imageBuffer); + bool hasValidTexture() { return m_hasValidTexture; } + + /******************************************** + * Called by UI thread WITH GL context + ********************************************/ + virtual ~CanvasTexture(); + void requireTexture(); + GLuint texture() { requireTexture(); return m_texture; } + bool updateTexImage(); + +private: + /******************************************** + * Called by both threads + ********************************************/ + void destroySurfaceTextureLocked(); + + /******************************************** + * Called by WebKit thread + ********************************************/ + CanvasTexture(int layerId); + bool useSurfaceTexture(); + + IntSize m_size; + int m_layerId; + GLuint m_texture; + android::Mutex m_surfaceLock; + sp<android::SurfaceTexture> m_surfaceTexture; + sp<android::SurfaceTextureClient> m_ANW; + bool m_hasValidTexture; + bool m_useHwAcceleration; + +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // CanvasTexture_h diff --git a/Source/WebCore/platform/graphics/android/DumpLayer.cpp b/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp index 5551965..5551965 100644 --- a/Source/WebCore/platform/graphics/android/DumpLayer.cpp +++ b/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp diff --git a/Source/WebCore/platform/graphics/android/DumpLayer.h b/Source/WebCore/platform/graphics/android/layers/DumpLayer.h index 5b30952..5b30952 100644 --- a/Source/WebCore/platform/graphics/android/DumpLayer.h +++ b/Source/WebCore/platform/graphics/android/layers/DumpLayer.h diff --git a/Source/WebCore/platform/graphics/android/FixedPositioning.cpp b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp index 989eebd..c7909c4 100644 --- a/Source/WebCore/platform/graphics/android/FixedPositioning.cpp +++ b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp @@ -8,6 +8,7 @@ #include "DumpLayer.h" #include "IFrameLayerAndroid.h" #include "TilesManager.h" +#include "SkCanvas.h" #if USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/FixedPositioning.h b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h index 973113b..973113b 100644 --- a/Source/WebCore/platform/graphics/android/FixedPositioning.h +++ b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h diff --git a/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.cpp index dadb13d..dadb13d 100644 --- a/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.cpp diff --git a/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.h index 64b2d06..64b2d06 100644 --- a/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.h diff --git a/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp index 3532542..3532542 100644 --- a/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp diff --git a/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h index e12188a..e12188a 100644 --- a/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h diff --git a/Source/WebCore/platform/graphics/android/Layer.cpp b/Source/WebCore/platform/graphics/android/layers/Layer.cpp index 7453a24..48e36fc 100644 --- a/Source/WebCore/platform/graphics/android/Layer.cpp +++ b/Source/WebCore/platform/graphics/android/layers/Layer.cpp @@ -1,5 +1,10 @@ +#define LOG_TAG "Layer" +#define LOG_NDEBUG 1 + #include "config.h" #include "Layer.h" + +#include "AndroidLog.h" #include "SkCanvas.h" //#define DEBUG_DRAW_LAYER_BOUNDS diff --git a/Source/WebCore/platform/graphics/android/Layer.h b/Source/WebCore/platform/graphics/android/layers/Layer.h index e872278..d87c699 100644 --- a/Source/WebCore/platform/graphics/android/Layer.h +++ b/Source/WebCore/platform/graphics/android/layers/Layer.h @@ -120,7 +120,7 @@ public: This does not include the childrenMatrix, since that is only applied after this layer draws (but before its children draw). */ - void getLocalTransform(SkMatrix* matrix) const; + virtual void getLocalTransform(SkMatrix* matrix) const; /** Return, in matrix, the concatenation of transforms that are applied from this layer's root parent to the layer itself. @@ -157,6 +157,9 @@ protected: bool m_hasOverflowChildren; + // invalidation region + SkRegion m_dirtyRegion; +private: bool isAncestor(const Layer*) const; Layer* fParent; @@ -173,9 +176,6 @@ protected: SkTDArray<Layer*> m_children; - // invalidation region - SkRegion m_dirtyRegion; - WebCore::GLWebViewState* m_state; typedef SkRefCnt INHERITED; diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp index 946d2a3..a02759d 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp @@ -13,10 +13,10 @@ #include "DumpLayer.h" #include "FixedPositioning.h" #include "GLUtils.h" +#include "GLWebViewState.h" #include "ImagesManager.h" #include "InspectorCanvas.h" #include "LayerContent.h" -#include "LayerGroup.h" #include "MediaLayer.h" #include "ParseCanvas.h" #include "PictureLayerContent.h" @@ -24,6 +24,7 @@ #include "SkDrawFilter.h" #include "SkPaint.h" #include "SkPicture.h" +#include "Surface.h" #include "TilesManager.h" #include <wtf/CurrentTime.h> @@ -33,8 +34,8 @@ #define DISABLE_LAYER_MERGE #undef DISABLE_LAYER_MERGE -#define LAYER_GROUPING_DEBUG -#undef LAYER_GROUPING_DEBUG +#define LAYER_MERGING_DEBUG +#undef LAYER_MERGING_DEBUG namespace WebCore { @@ -54,6 +55,7 @@ private: /////////////////////////////////////////////////////////////////////////////// LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), + m_uniqueId(++gUniqueId), m_haveClip(false), m_backfaceVisibility(true), m_visible(true), @@ -62,7 +64,6 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), m_isPositionAbsolute(false), m_fixedPosition(0), m_zValue(0), - m_uniqueId(++gUniqueId), m_content(0), m_imageCRC(0), m_scale(1), @@ -70,7 +71,7 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), m_owningLayer(owner), m_type(LayerAndroid::WebCoreLayer), m_intrinsicallyComposited(true), - m_layerGroup(0) + m_surface(0) { m_backgroundColor = 0; @@ -83,15 +84,15 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), } LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), + m_uniqueId(layer.m_uniqueId), m_haveClip(layer.m_haveClip), m_isPositionAbsolute(layer.m_isPositionAbsolute), m_fixedPosition(0), m_zValue(layer.m_zValue), - m_uniqueId(layer.m_uniqueId), m_owningLayer(layer.m_owningLayer), m_type(LayerAndroid::UILayer), m_intrinsicallyComposited(layer.m_intrinsicallyComposited), - m_layerGroup(0) + m_surface(0) { m_imageCRC = layer.m_imageCRC; if (m_imageCRC) @@ -169,28 +170,6 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), #endif } -LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(), - m_haveClip(false), - m_fixedPosition(0), - m_zValue(0), - m_uniqueId(++gUniqueId), - m_imageCRC(0), - m_scale(1), - m_lastComputeTextureSize(0), - m_owningLayer(0), - m_type(LayerAndroid::NavCacheLayer), - m_intrinsicallyComposited(true), - m_layerGroup(0) -{ - m_backgroundColor = 0; - m_content = new PictureLayerContent(picture); - m_dirtyRegion.setEmpty(); -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("LayerAndroid - from picture"); - ClassTracker::instance()->add(this); -#endif -} - LayerAndroid::~LayerAndroid() { if (m_imageCRC) @@ -199,7 +178,7 @@ LayerAndroid::~LayerAndroid() delete m_fixedPosition; SkSafeUnref(m_content); - // Don't unref m_layerGroup, owned by BaseLayerAndroid + // Don't unref m_surface, owned by BaseLayerAndroid m_animations.clear(); #ifdef DEBUG_COUNT ClassTracker::instance()->remove(this); @@ -207,8 +186,6 @@ LayerAndroid::~LayerAndroid() ClassTracker::instance()->decrement("LayerAndroid"); else if (m_type == LayerAndroid::UILayer) ClassTracker::instance()->decrement("LayerAndroid - recopy (UI)"); - else if (m_type == LayerAndroid::NavCacheLayer) - ClassTracker::instance()->decrement("LayerAndroid - from picture"); #endif } @@ -277,7 +254,7 @@ void LayerAndroid::addDirtyArea() area.intersect(clip); IntRect dirtyArea(area.x(), area.y(), area.width(), area.height()); - m_state->addDirtyArea(dirtyArea); + state()->addDirtyArea(dirtyArea); } void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> prpAnim) @@ -434,7 +411,6 @@ void LayerAndroid::updatePositions() void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentMatrix, const FloatRect& clipping, float opacity, float scale) { - m_atomicSync.lock(); IntSize layerSize(getSize().width(), getSize().height()); FloatPoint anchorPoint(getAnchorPoint().fX, getAnchorPoint().fY); FloatPoint position(getPosition().fX - m_offset.x(), getPosition().fY - m_offset.y()); @@ -451,7 +427,6 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM -originY, -anchorPointZ()); - m_atomicSync.unlock(); setDrawTransform(localMatrix); if (m_drawTransform.isIdentityOrTranslation()) { // adjust the translation coordinates of the draw transform matrix so @@ -483,6 +458,9 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM } else { setDrawClip(clipping); } + ALOGV("%s - %d %f %f %f %f", + subclassType() == BaseLayer ? "BASE" : "nonbase", + m_haveClip, m_clippingRect.x(), m_clippingRect.y(), m_clippingRect.width(), m_clippingRect.height()); if (!m_backfaceVisibility && m_drawTransform.inverse().m33() < 0) { @@ -630,65 +608,21 @@ void LayerAndroid::mergeInvalsInto(LayerAndroid* replacementTree) replacementLayer->markAsDirty(m_dirtyRegion); } -bool LayerAndroid::updateWithTree(LayerAndroid* newTree) -{ -// Disable fast update for now -#if (0) - bool needsRepaint = false; - int count = this->countChildren(); - for (int i = 0; i < count; i++) - needsRepaint |= this->getChild(i)->updateWithTree(newTree); - - if (newTree) { - LayerAndroid* newLayer = newTree->findById(uniqueId()); - needsRepaint |= updateWithLayer(newLayer); - } - return needsRepaint; -#else - return true; -#endif -} - -// Return true to indicate to WebViewCore that the updates -// are too complicated to be fully handled and we need a full -// call to webkit (e.g. handle repaints) -bool LayerAndroid::updateWithLayer(LayerAndroid* layer) -{ - if (!layer) - return true; - - android::AutoMutex lock(m_atomicSync); - m_position = layer->m_position; - m_anchorPoint = layer->m_anchorPoint; - m_size = layer->m_size; - m_opacity = layer->m_opacity; - m_transform = layer->m_transform; - - if (m_imageCRC != layer->m_imageCRC) - m_visible = false; - - if ((m_content != layer->m_content) - || (m_imageCRC != layer->m_imageCRC)) - return true; - - return false; -} - static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b) { return a->zValue() > b->zValue(); } -bool LayerAndroid::canJoinGroup(LayerGroup* group) +bool LayerAndroid::canJoinSurface(Surface* surface) { -#if DISABLE_LAYER_MERGE +#ifdef DISABLE_LAYER_MERGE return false; #else - // returns true if the layer can be merged onto the layergroup - if (!group) + // returns true if the layer can be merged onto the surface (group of layers) + if (!surface) return false; - LayerAndroid* lastLayer = group->getFirstLayer(); + LayerAndroid* lastLayer = surface->getFirstLayer(); // isolate non-tiled layers // TODO: remove this check so that multiple tiled layers with a invisible @@ -710,9 +644,9 @@ bool LayerAndroid::canJoinGroup(LayerGroup* group) || !lastLayer->m_drawTransform.isIdentityOrTranslation()) return false; - // currently, we don't group zoomable with non-zoomable layers (unless the - // group or the layer doesn't need a texture) - if (group->needsTexture() && needsTexture() && m_content->hasText() != group->hasText()) + // currently, we don't surface zoomable with non-zoomable layers (unless the + // surface or the layer doesn't need a texture) + if (surface->needsTexture() && needsTexture() && m_content->hasText() != surface->hasText()) return false; // TODO: compare other layer properties - fixed? overscroll? transformed? @@ -720,31 +654,31 @@ bool LayerAndroid::canJoinGroup(LayerGroup* group) #endif } -void LayerAndroid::assignGroups(LayerMergeState* mergeState) +void LayerAndroid::assignSurfaces(LayerMergeState* mergeState) { // recurse through layers in draw order, and merge layers when able - bool needNewGroup = !mergeState->currentLayerGroup + bool needNewSurface = !mergeState->currentSurface || mergeState->nonMergeNestedLevel > 0 - || !canJoinGroup(mergeState->currentLayerGroup); + || !canJoinSurface(mergeState->currentSurface); - if (needNewGroup) { - mergeState->currentLayerGroup = new LayerGroup(); - mergeState->groupList->append(mergeState->currentLayerGroup); + if (needNewSurface) { + mergeState->currentSurface = new Surface(); + mergeState->surfaceList->append(mergeState->currentSurface); } -#ifdef LAYER_GROUPING_DEBUG - ALOGD("%*slayer %p(%d) rl %p %s group %p, fixed %d, anim %d, intCom %d, haveClip %d scroll %d", +#ifdef LAYER_MERGING_DEBUG + ALOGD("%*slayer %p(%d) rl %p %s surface %p, fixed %d, anim %d, intCom %d, haveClip %d scroll %d", 4*mergeState->depth, "", this, m_uniqueId, m_owningLayer, - needNewGroup ? "NEW" : "joins", mergeState->currentLayerGroup, + needNewSurface ? "NEW" : "joins", mergeState->currentSurface, isPositionFixed(), m_animations.size() != 0, m_intrinsicallyComposited, m_haveClip, contentIsScrollable()); #endif - mergeState->currentLayerGroup->addLayer(this, m_drawTransform); - m_layerGroup = mergeState->currentLayerGroup; + mergeState->currentSurface->addLayer(this, m_drawTransform); + m_surface = mergeState->currentSurface; if (m_haveClip || contentIsScrollable() || isPositionFixed()) { // disable layer merging within the children of these layer types @@ -752,7 +686,7 @@ void LayerAndroid::assignGroups(LayerMergeState* mergeState) } - // pass the layergroup through children in drawing order, so that they may + // pass the surface through children in drawing order, so that they may // attach themselves (and paint on it) if possible, or ignore it and create // a new one if not int count = this->countChildren(); @@ -765,7 +699,7 @@ void LayerAndroid::assignGroups(LayerMergeState* mergeState) // sort for the transparency std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); for (int i = 0; i < count; i++) - sublayers[i]->assignGroups(mergeState); + sublayers[i]->assignSurfaces(mergeState); mergeState->depth--; } @@ -773,8 +707,8 @@ void LayerAndroid::assignGroups(LayerMergeState* mergeState) // re-enable joining mergeState->nonMergeNestedLevel--; - // disallow layers painting after to join with this group - mergeState->currentLayerGroup = 0; + // disallow layers painting after to join with this surface + mergeState->currentSurface = 0; } } @@ -791,6 +725,16 @@ void LayerAndroid::clearDirtyRegion() m_dirtyRegion.setEmpty(); } +int LayerAndroid::setHwAccelerated(bool hwAccelerated) +{ + int flags = InvalidateNone; + int count = this->countChildren(); + for (int i = 0; i < count; i++) + flags |= this->getChild(i)->setHwAccelerated(hwAccelerated); + + return flags | onSetHwAccelerated(hwAccelerated); +} + IntRect LayerAndroid::unclippedArea() { IntRect area; @@ -867,7 +811,7 @@ bool LayerAndroid::drawGL(bool layerTilesDisabled) ImagesManager::instance()->releaseImage(m_imageCRC); } - m_state->glExtras()->drawGL(this); + state()->glExtras()->drawGL(this); bool askScreenUpdate = false; m_atomicSync.lock(); @@ -920,10 +864,10 @@ void LayerAndroid::contentDraw(SkCanvas* canvas, PaintStyle style) canvas->drawLine(0, 0, w, h, paint); canvas->drawLine(0, h, w, 0, paint); - canvas->drawLine(0, 0, 0, h, paint); - canvas->drawLine(0, h, w, h, paint); - canvas->drawLine(w, h, w, 0, paint); - canvas->drawLine(w, 0, 0, 0, paint); + canvas->drawLine(0, 0, 0, h-1, paint); + canvas->drawLine(0, h-1, w-1, h-1, paint); + canvas->drawLine(w-1, h-1, w-1, 0, paint); + canvas->drawLine(w-1, 0, 0, 0, paint); } if (m_fixedPosition) @@ -940,7 +884,8 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity, return; } - if (masksToBounds() || !m_content) + // only continue drawing if layer is drawable + if (!m_content && !m_imageCRC) return; // we just have this save/restore for opacity... diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h index 7436676..9a803a9 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h @@ -25,6 +25,7 @@ #include "GraphicsLayerClient.h" #include "ImageTexture.h" #include "Layer.h" +#include "PlatformString.h" #include "RefPtr.h" #include "SkBitmap.h" #include "SkColor.h" @@ -32,6 +33,7 @@ #include "SkStream.h" #include "TransformationMatrix.h" +#include <utils/threads.h> #include <wtf/HashMap.h> #ifndef BZERO_DEFINED @@ -49,8 +51,8 @@ class SkPicture; namespace WebCore { class LayerAndroid; class LayerContent; -class LayerGroup; class ImageTexture; +class Surface; } namespace android { @@ -65,13 +67,11 @@ using namespace android; namespace WebCore { class AndroidAnimation; -class BaseTileTexture; class FixedPositioning; class GLWebViewState; class IFrameLayerAndroid; class LayerMergeState; class RenderLayer; -class TiledPage; class PaintedSurface; class TexturesResult { @@ -91,9 +91,11 @@ public: class TEST_EXPORT LayerAndroid : public Layer { public: - typedef enum { UndefinedLayer, WebCoreLayer, UILayer, NavCacheLayer } LayerType; + typedef enum { UndefinedLayer, WebCoreLayer, UILayer } LayerType; typedef enum { StandardLayer, ScrollableLayer, - IFrameLayer, IFrameContentLayer } SubclassType; + IFrameLayer, IFrameContentLayer, + CanvasLayer, BaseLayer } SubclassType; + typedef enum { InvalidateNone = 0, InvalidateLayers } InvalidateFlags; String subclassName() { @@ -106,17 +108,18 @@ public: return "IFrameLayer"; case LayerAndroid::IFrameContentLayer: return "IFrameContentLayer"; + case LayerAndroid::CanvasLayer: + return "CanvasLayer"; + case LayerAndroid::BaseLayer: + return "BaseLayer"; } return "Undefined"; } LayerAndroid(RenderLayer* owner); LayerAndroid(const LayerAndroid& layer); - LayerAndroid(SkPicture*); virtual ~LayerAndroid(); - virtual TiledPage* page() { return 0; } - void setBackfaceVisibility(bool value) { m_backfaceVisibility = value; } void setTransform(const TransformationMatrix& matrix) { m_transform = matrix; } FloatPoint translation() const; @@ -156,7 +159,7 @@ public: void setAnchorPointZ(float z) { m_anchorPointZ = z; } float anchorPointZ() { return m_anchorPointZ; } void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = transform; } - const TransformationMatrix* drawTransform() const { return &m_drawTransform; } + virtual const TransformationMatrix* drawTransform() const { return &m_drawTransform; } void setChildrenTransform(const TransformationMatrix& t) { m_childrenTransform = t; } void setDrawClip(const FloatRect& rect) { m_clippingRect = rect; } const FloatRect& drawClip() { return m_clippingRect; } @@ -230,7 +233,7 @@ public: virtual LayerAndroid* copy() const { return new LayerAndroid(*this); } - void clearDirtyRegion(); + virtual void clearDirtyRegion(); virtual void contentDraw(SkCanvas* canvas, PaintStyle style); @@ -254,12 +257,6 @@ public: friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream); friend void android::cleanupImageRefs(LayerAndroid* layer); - // Update layers using another tree. Only works for basic properties - // such as the position, the transform. Return true if anything more - // complex is needed. - bool updateWithTree(LayerAndroid*); - virtual bool updateWithLayer(LayerAndroid*); - LayerType type() { return m_type; } virtual SubclassType subclassType() { return LayerAndroid::StandardLayer; } @@ -271,16 +268,20 @@ public: SkRegion* getInvalRegion() { return &m_dirtyRegion; } void mergeInvalsInto(LayerAndroid* replacementTree); - bool canJoinGroup(LayerGroup* group); - void assignGroups(LayerMergeState* mergeState); - LayerGroup* group() { return m_layerGroup; } + bool canJoinSurface(Surface* surface); + void assignSurfaces(LayerMergeState* mergeState); + Surface* surface() { return m_surface; } void setIntrinsicallyComposited(bool intCom) { m_intrinsicallyComposited = intCom; } + int setHwAccelerated(bool hwAccelerated); + protected: virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style); + virtual InvalidateFlags onSetHwAccelerated(bool hwAccelerated) { return InvalidateNone; } IntPoint m_offset; TransformationMatrix m_drawTransform; + int m_uniqueId; private: #if DUMP_NAV_CACHE @@ -324,8 +325,6 @@ private: FloatRect m_clippingRect; - int m_uniqueId; - // Note that m_content and m_imageCRC are mutually exclusive; // m_content is used when WebKit is asked to paint the layer's // content, while m_imageCRC references an image that we directly @@ -356,7 +355,7 @@ private: bool m_intrinsicallyComposited; - LayerGroup* m_layerGroup; + Surface* m_surface; typedef Layer INHERITED; }; diff --git a/Source/WebCore/platform/graphics/android/LayerContent.h b/Source/WebCore/platform/graphics/android/layers/LayerContent.h index 32108ec..97bc32a 100644 --- a/Source/WebCore/platform/graphics/android/LayerContent.h +++ b/Source/WebCore/platform/graphics/android/layers/LayerContent.h @@ -27,6 +27,7 @@ #define LayerContent_h #include "SkRefCnt.h" +#include <utils/threads.h> class SkCanvas; class SkPicture; @@ -44,6 +45,10 @@ public: virtual void draw(SkCanvas* canvas) = 0; virtual void serialize(SkWStream* stream) = 0; + +protected: + // used to prevent parallel draws, as both SkPicture and PictureSet don't support them + android::Mutex m_drawLock; }; } // WebCore diff --git a/Source/WebCore/platform/graphics/android/MediaLayer.cpp b/Source/WebCore/platform/graphics/android/layers/MediaLayer.cpp index de1db17..6227ea4 100644 --- a/Source/WebCore/platform/graphics/android/MediaLayer.cpp +++ b/Source/WebCore/platform/graphics/android/layers/MediaLayer.cpp @@ -28,9 +28,9 @@ namespace WebCore { -MediaLayer::MediaLayer(jobject webViewRef) : LayerAndroid((RenderLayer*) NULL) +MediaLayer::MediaLayer(jobject webViewRef, jobject webViewCoreRef) : LayerAndroid((RenderLayer*) NULL) { - m_mediaTexture = new MediaTexture(webViewRef); + m_mediaTexture = new MediaTexture(webViewRef, webViewCoreRef); m_mediaTexture->incStrong(this); m_isCopy = false; diff --git a/Source/WebCore/platform/graphics/android/MediaLayer.h b/Source/WebCore/platform/graphics/android/layers/MediaLayer.h index 907c53c..2f39d74 100644 --- a/Source/WebCore/platform/graphics/android/MediaLayer.h +++ b/Source/WebCore/platform/graphics/android/layers/MediaLayer.h @@ -32,7 +32,7 @@ namespace WebCore { class MediaLayer : public LayerAndroid { public: - MediaLayer(jobject webViewRef); + MediaLayer(jobject webViewRef, jobject webViewCoreRef); MediaLayer(const MediaLayer& layer); virtual ~MediaLayer(); diff --git a/Source/WebCore/platform/graphics/android/MediaListener.h b/Source/WebCore/platform/graphics/android/layers/MediaListener.h index 2dfc08b..2dfc08b 100644 --- a/Source/WebCore/platform/graphics/android/MediaListener.h +++ b/Source/WebCore/platform/graphics/android/layers/MediaListener.h diff --git a/Source/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h b/Source/WebCore/platform/graphics/android/layers/MediaPlayerPrivateAndroid.h index 535e7ae..535e7ae 100644 --- a/Source/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h +++ b/Source/WebCore/platform/graphics/android/layers/MediaPlayerPrivateAndroid.h diff --git a/Source/WebCore/platform/graphics/android/MediaTexture.cpp b/Source/WebCore/platform/graphics/android/layers/MediaTexture.cpp index 789ca03..dffe6c2 100644 --- a/Source/WebCore/platform/graphics/android/MediaTexture.cpp +++ b/Source/WebCore/platform/graphics/android/layers/MediaTexture.cpp @@ -21,6 +21,7 @@ #include "MediaTexture.h" #include "AndroidLog.h" +#include "DrawQuadData.h" #include "TilesManager.h" #include "GLUtils.h" #include "MediaListener.h" @@ -41,14 +42,11 @@ namespace WebCore { -MediaTexture::MediaTexture(jobject webViewRef) : android::LightRefBase<MediaTexture>() +MediaTexture::MediaTexture(jobject webViewRef, jobject webViewCoreRef) : android::LightRefBase<MediaTexture>() { - if (webViewRef) { - JNIEnv* env = JSC::Bindings::getJNIEnv(); - m_weakWebViewRef = env->NewWeakGlobalRef(webViewRef); - } else { - m_weakWebViewRef = 0; - } + JNIEnv* env = JSC::Bindings::getJNIEnv(); + m_weakWebViewRef = env->NewWeakGlobalRef(webViewRef); + m_weakWebViewCoreRef = env->NewWeakGlobalRef(webViewCoreRef); m_contentTexture = 0; m_isContentInverted = false; @@ -63,10 +61,9 @@ MediaTexture::~MediaTexture() deleteTexture(m_videoTextures[i], true); } - if (m_weakWebViewRef) { - JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->DeleteWeakGlobalRef(m_weakWebViewRef); - } + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->DeleteWeakGlobalRef(m_weakWebViewRef); + env->DeleteWeakGlobalRef(m_weakWebViewCoreRef); } bool MediaTexture::isContentInverted() @@ -98,16 +95,16 @@ void MediaTexture::initNativeWindowIfNeeded() m_contentTexture = createTexture(); // send a message to the WebKit thread to notify the plugin that it can draw - if (m_weakWebViewRef) { + if (m_weakWebViewCoreRef) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - jobject localWebViewRef = env->NewLocalRef(m_weakWebViewRef); - if (localWebViewRef) { - jclass wvClass = env->GetObjectClass(localWebViewRef); + jobject localWebViewCoreRef = env->NewLocalRef(m_weakWebViewCoreRef); + if (localWebViewCoreRef) { + jclass wvClass = env->GetObjectClass(localWebViewCoreRef); jmethodID sendPluginDrawMsg = env->GetMethodID(wvClass, "sendPluginDrawMsg", "()V"); - env->CallVoidMethod(localWebViewRef, sendPluginDrawMsg); + env->CallVoidMethod(localWebViewCoreRef, sendPluginDrawMsg); env->DeleteLocalRef(wvClass); - env->DeleteLocalRef(localWebViewRef); + env->DeleteLocalRef(localWebViewCoreRef); } checkException(env); } @@ -180,11 +177,10 @@ void MediaTexture::draw(const TransformationMatrix& contentMatrix, PIXEL_FORMAT_RGB_888 == f || PIXEL_FORMAT_RGB_565 == f); - TilesManager::instance()->shader()->drawLayerQuad(contentMatrix, - mediaBounds, - m_contentTexture->textureId, - 1.0f, forceAlphaBlending, - GL_TEXTURE_EXTERNAL_OES); + TextureQuadData data(m_contentTexture->textureId, GL_TEXTURE_EXTERNAL_OES, + GL_LINEAR, LayerQuad, &contentMatrix, &mediaBounds, + 1.0f, forceAlphaBlending); + TilesManager::instance()->shader()->drawQuad(&data); } ANativeWindow* MediaTexture::requestNativeWindowForVideo() diff --git a/Source/WebCore/platform/graphics/android/MediaTexture.h b/Source/WebCore/platform/graphics/android/layers/MediaTexture.h index 97bb530..9ea7be2 100644 --- a/Source/WebCore/platform/graphics/android/MediaTexture.h +++ b/Source/WebCore/platform/graphics/android/layers/MediaTexture.h @@ -40,7 +40,7 @@ class MediaListener; class MediaTexture : public android::LightRefBase<MediaTexture> { public: - MediaTexture(jobject webViewRef); + MediaTexture(jobject webViewRef, jobject webViewCoreRef); ~MediaTexture(); bool isContentInverted(); @@ -83,6 +83,7 @@ private: sp<ANativeWindow> m_newWindow; jobject m_weakWebViewRef; + jobject m_weakWebViewCoreRef; android::Mutex m_mediaLock; android::Condition m_newMediaRequestCond; diff --git a/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp index cf2e569..4398146 100644 --- a/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp +++ b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp @@ -90,6 +90,9 @@ void PictureLayerContent::draw(SkCanvas* canvas) if (!m_picture) return; + android::Mutex::Autolock lock(m_drawLock); + SkRect r = SkRect::MakeWH(width(), height()); + canvas->clipRect(r); canvas->drawPicture(*m_picture); } diff --git a/Source/WebCore/platform/graphics/android/PictureLayerContent.h b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h index 94bdfac..94bdfac 100644 --- a/Source/WebCore/platform/graphics/android/PictureLayerContent.h +++ b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h diff --git a/Source/WebCore/platform/graphics/android/PictureSetLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PictureSetLayerContent.cpp index bc024eb..8b72b0a 100644 --- a/Source/WebCore/platform/graphics/android/PictureSetLayerContent.cpp +++ b/Source/WebCore/platform/graphics/android/layers/PictureSetLayerContent.cpp @@ -1,6 +1,7 @@ #include "config.h" #include "PictureSetLayerContent.h" +#include "SkCanvas.h" #include "SkPicture.h" namespace WebCore { @@ -17,8 +18,13 @@ PictureSetLayerContent::~PictureSetLayerContent() void PictureSetLayerContent::draw(SkCanvas* canvas) { - if (!m_pictureSet.isEmpty()) - m_pictureSet.draw(canvas); + if (m_pictureSet.isEmpty()) + return; + + android::Mutex::Autolock lock(m_drawLock); + SkRect r = SkRect::MakeWH(width(), height()); + canvas->clipRect(r); + m_pictureSet.draw(canvas); } void PictureSetLayerContent::serialize(SkWStream* stream) diff --git a/Source/WebCore/platform/graphics/android/PictureSetLayerContent.h b/Source/WebCore/platform/graphics/android/layers/PictureSetLayerContent.h index 61fc3f4..61fc3f4 100644 --- a/Source/WebCore/platform/graphics/android/PictureSetLayerContent.h +++ b/Source/WebCore/platform/graphics/android/layers/PictureSetLayerContent.h diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.cpp index f28c31d..f28c31d 100644 --- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.cpp diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.h index 1f289e6..52f5e7e 100644 --- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.h @@ -43,8 +43,6 @@ public: virtual LayerAndroid* copy() const { return new ScrollableLayerAndroid(*this); } virtual SubclassType subclassType() { return LayerAndroid::ScrollableLayer; } - virtual bool updateWithLayer(LayerAndroid*) { return true; } - // Scrolls to the given position in the layer. // Returns whether or not any scrolling was required. virtual bool scrollTo(int x, int y); diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.cpp index 756bf28..39bbec6 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.cpp @@ -30,6 +30,8 @@ #include "VideoLayerAndroid.h" #include "AndroidLog.h" +#include "DrawQuadData.h" +#include "ShaderProgram.h" #include "TilesManager.h" #include <GLES2/gl2.h> #include <gui/SurfaceTexture.h> @@ -74,8 +76,9 @@ void VideoLayerAndroid::showPreparingAnimation(const SkRect& rect, ShaderProgram* shader = TilesManager::instance()->shader(); VideoLayerManager* manager = TilesManager::instance()->videoLayerManager(); // Paint the video content's background. - shader->drawLayerQuad(m_drawTransform, rect, 0, 1, true, GL_TEXTURE_2D, - Color(128, 128, 128, 255)); + PureColorQuadData backGroundQuadData(Color(128, 128, 128, 255), LayerQuad, + &m_drawTransform, &rect); + shader->drawQuad(&backGroundQuadData); TransformationMatrix addReverseRotation; TransformationMatrix addRotation = m_drawTransform; @@ -87,14 +90,18 @@ void VideoLayerAndroid::showPreparingAnimation(const SkRect& rect, addRotation.translate(-halfButtonSize, -halfButtonSize); SkRect size = SkRect::MakeWH(innerRect.width(), innerRect.height()); - shader->drawLayerQuad(addRotation, size, - manager->getSpinnerOuterTextureId(), 1, true); + + TextureQuadData spinnerQuadData(manager->getSpinnerOuterTextureId(), + GL_TEXTURE_2D, GL_LINEAR, + LayerQuad, &addRotation, &size); + shader->drawQuad(&spinnerQuadData); addReverseRotation.rotate(-m_rotateDegree); addReverseRotation.translate(-halfButtonSize, -halfButtonSize); - shader->drawLayerQuad(addReverseRotation, size, - manager->getSpinnerInnerTextureId(), 1, true); + spinnerQuadData.updateTextureId(manager->getSpinnerInnerTextureId()); + spinnerQuadData.updateDrawMatrix(&addReverseRotation); + shader->drawQuad(&spinnerQuadData); m_rotateDegree += ROTATESTEP; } @@ -129,11 +136,13 @@ bool VideoLayerAndroid::drawGL(bool layerTilesDisabled) // Calculate the video rect based on the aspect ratio and the element rect. SkRect videoRect = calVideoRect(rect); + PureColorQuadData pureColorQuadData(Color(0, 0, 0, 255), LayerQuad, + &m_drawTransform, &rect); + if (videoRect != rect) { // Paint the whole video element with black color when video content // can't cover the whole area. - shader->drawLayerQuad(m_drawTransform, rect, 0, 1, true, GL_TEXTURE_2D, - Color(0, 0, 0, 255)); + shader->drawQuad(&pureColorQuadData); } // Inner rect is for the progressing / play / pause animation. @@ -148,7 +157,8 @@ bool VideoLayerAndroid::drawGL(bool layerTilesDisabled) // When we are drawing the animation of the play/pause button in the // middle of the video, we need to ask for redraw. bool needRedraw = false; - + TextureQuadData iconQuadData(0, GL_TEXTURE_2D, GL_LINEAR, LayerQuad, + &m_drawTransform, &innerRect); // Draw the poster image, the progressing image or the Video depending // on the player's state. if (m_playerState == PREPARING) { @@ -169,11 +179,11 @@ bool VideoLayerAndroid::drawGL(bool layerTilesDisabled) if (scale) { innerRect.inset(manager->getButtonSize() / 4 * scale, manager->getButtonSize() / 4 * scale); - shader->drawLayerQuad(m_drawTransform, innerRect, - manager->getPlayTextureId(), scale, true); + iconQuadData.updateTextureId(manager->getPlayTextureId()); + iconQuadData.updateOpacity(scale); + shader->drawQuad(&iconQuadData); needRedraw = true; } - } else { GLuint textureId = manager->getTextureId(uniqueId()); GLfloat* matrix = manager->getMatrix(uniqueId()); @@ -183,10 +193,12 @@ bool VideoLayerAndroid::drawGL(bool layerTilesDisabled) videoRect, textureId); } else { // Show the static poster b/c there is no screen shot available. - shader->drawLayerQuad(m_drawTransform, rect, 0, 1, true, GL_TEXTURE_2D, - Color(128, 128, 128, 255)); - shader->drawLayerQuad(m_drawTransform, innerRect, - manager->getPosterTextureId(), 1, true); + pureColorQuadData.updateColor(Color(128, 128, 128, 255)); + shader->drawQuad(&pureColorQuadData); + + iconQuadData.updateTextureId(manager->getPosterTextureId()); + iconQuadData.updateOpacity(1.0); + shader->drawQuad(&iconQuadData); } // Use the scale to control the fading and the sizing during animation. @@ -194,8 +206,9 @@ bool VideoLayerAndroid::drawGL(bool layerTilesDisabled) if (scale) { innerRect.inset(manager->getButtonSize() / 4 * scale, manager->getButtonSize() / 4 * scale); - shader->drawLayerQuad(m_drawTransform, innerRect, - manager->getPauseTextureId(), scale, true); + iconQuadData.updateTextureId(manager->getPauseTextureId()); + iconQuadData.updateOpacity(scale); + shader->drawQuad(&iconQuadData); needRedraw = true; } diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.h index 29b1bdc..dd88a85 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.h @@ -30,7 +30,6 @@ #include "GLUtils.h" #include "LayerAndroid.h" -#include "ShaderProgram.h" #include <jni.h> namespace android { diff --git a/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp index 6501f98..6501f98 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp +++ b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp diff --git a/Source/WebCore/platform/graphics/android/VideoLayerManager.h b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h index c8e420e..6c02534 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerManager.h +++ b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h @@ -30,6 +30,7 @@ #include "IntRect.h" #include <wtf/HashMap.h> #include <wtf/Vector.h> +#include <utils/threads.h> #if USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp index 6dd16e1..8bb1755 100644 --- a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp @@ -40,12 +40,14 @@ #include "SkCanvas.h" #include "SkDevice.h" #include "SkPicture.h" +#include "SkTypeface.h" +#include "Tile.h" #include "TilesManager.h" #include <wtf/text/CString.h> #define UPDATE_COUNT_MASK 0xFF // displayed count wraps at 256 -#define UPDATE_COUNT_ALPHA_MASK 0x3F // alpha wraps at 64 +#define UPDATE_COUNT_ALPHA_MASK 0x1F // alpha wraps at 32 namespace WebCore { @@ -70,40 +72,24 @@ void BaseRenderer::swapRendererIfNeeded(BaseRenderer*& renderer) } void BaseRenderer::drawTileInfo(SkCanvas* canvas, - const TileRenderInfo& renderInfo, int updateCount) + const TileRenderInfo& renderInfo, int updateCount, double renderDuration) { + static SkTypeface* s_typeface = 0; + if (!s_typeface) + s_typeface = SkTypeface::CreateFromName("", SkTypeface::kBold); SkPaint paint; + paint.setTextSize(17); char str[256]; - snprintf(str, 256, "(%d,%d) %.2f, tl%x p%x c%d", renderInfo.x, renderInfo.y, - renderInfo.scale, this, renderInfo.tilePainter, updateCount); - paint.setARGB(255, 0, 0, 0); - canvas->drawText(str, strlen(str), 0, 10, paint); + snprintf(str, 256, " (%d,%d) %.2fx %d %.1fms", renderInfo.x, renderInfo.y, + renderInfo.scale, updateCount, renderDuration); + paint.setARGB(128, 255, 255, 255); + canvas->drawRectCoords(0, 0, renderInfo.tileSize.fWidth, 17, paint); paint.setARGB(255, 255, 0, 0); - canvas->drawText(str, strlen(str), 0, 11, paint); - - int tagCount = 0; - const String* tags = getPerformanceTags(tagCount); - - float total = 0; - for (int i = 0; i < tagCount; i++) { - float tagDuration = m_perfMon.getAverageDuration(tags[i]); - total += tagDuration; - snprintf(str, 256, "%s: %.2f", tags[i].utf8().data(), tagDuration); - paint.setARGB(255, 0, 0, 0); - int textY = (i * 12) + 25; - canvas->drawText(str, strlen(str), 0, textY, paint); - paint.setARGB(255, 255, 0, 0); - canvas->drawText(str, strlen(str), 0, textY + 1, paint); - } - snprintf(str, 256, "total: %.2f", total); - paint.setARGB(255, 0, 0, 0); - int textY = (tagCount * 12) + 30; - canvas->drawText(str, strlen(str), 0, textY, paint); - paint.setARGB(255, 255, 0, 0); - canvas->drawText(str, strlen(str), 0, textY + 1, paint); + paint.setTypeface(s_typeface); + canvas->drawText(str, strlen(str), 20, 15, paint); } -void BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo) +void BaseRenderer::renderTiledContent(TileRenderInfo& renderInfo) { const bool visualIndicator = TilesManager::instance()->getShowVisualIndicator(); const SkSize& tileSize = renderInfo.tileSize; @@ -117,41 +103,38 @@ void BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo) return; } - if (visualIndicator) + double before; + if (visualIndicator) { canvas.save(); + before = currentTimeMS(); + } setupPartialInval(renderInfo, &canvas); canvas.translate(-renderInfo.x * tileSize.width(), -renderInfo.y * tileSize.height()); canvas.scale(renderInfo.scale, renderInfo.scale); - renderInfo.tilePainter->paint(renderInfo.baseTile, &canvas); + renderInfo.tilePainter->paint(&canvas); + if (renderInfo.baseTile && renderInfo.baseTile->backTexture()) + checkForPureColor(renderInfo, &canvas); + else + renderInfo.isPureColor = false; if (visualIndicator) { + double after = currentTimeMS(); canvas.restore(); unsigned int updateCount = renderInfo.tilePainter->getUpdateCount() & UPDATE_COUNT_MASK; const int color = updateCount & UPDATE_COUNT_ALPHA_MASK; // only color the invalidated area - SkPaint invalPaint; - invalPaint.setARGB(color, 0, 255, 0); + SkPaint paint; + paint.setARGB(color, 0, 255, 0); if (renderInfo.invalRect) - canvas.drawIRect(*renderInfo.invalRect, invalPaint); + canvas.drawIRect(*renderInfo.invalRect, paint); else { SkIRect rect; rect.set(0, 0, tileSize.width(), tileSize.height()); - canvas.drawIRect(rect, invalPaint); + canvas.drawIRect(rect, paint); } - // paint the tile boundaries - SkPaint paint; - paint.setARGB(128, 255, 0, 0); - paint.setStrokeWidth(3); - canvas.drawLine(0, 0, tileSize.width(), tileSize.height(), paint); - paint.setARGB(128, 0, 255, 0); - canvas.drawLine(0, tileSize.height(), tileSize.width(), 0, paint); - paint.setARGB(128, 0, 0, 255); - canvas.drawLine(0, 0, tileSize.width(), 0, paint); - canvas.drawLine(tileSize.width(), 0, tileSize.width(), tileSize.height(), paint); - if (renderInfo.invalRect) { // if partial inval... int x = renderInfo.invalRect->fLeft; @@ -163,9 +146,16 @@ void BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo) canvas.drawLine(x, y, x + w, y + h, paint); canvas.drawLine(x, y + h, x + w, y, paint); } + drawTileInfo(&canvas, renderInfo, updateCount, after - before); - if (renderInfo.measurePerf) - drawTileInfo(&canvas, renderInfo, updateCount); + // paint the tile boundaries + paint.setARGB(64, 255, 0, 0); + paint.setStrokeWidth(3); + canvas.drawLine(0, 0, tileSize.width(), tileSize.height(), paint); + paint.setARGB(64, 0, 255, 0); + canvas.drawLine(0, tileSize.height(), tileSize.width(), 0, paint); + paint.setARGB(128, 0, 0, 255); + canvas.drawLine(tileSize.width(), 0, tileSize.width(), tileSize.height(), paint); } renderingComplete(renderInfo, &canvas); } diff --git a/Source/WebCore/platform/graphics/android/BaseRenderer.h b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h index 2defcc3..f225871 100644 --- a/Source/WebCore/platform/graphics/android/BaseRenderer.h +++ b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h @@ -28,8 +28,9 @@ #if USE(ACCELERATED_COMPOSITING) -#include "PerformanceMonitor.h" +#include "Color.h" #include "SkRect.h" +#include <wtf/text/StringHash.h> class SkCanvas; class SkDevice; @@ -38,7 +39,7 @@ namespace WebCore { class TextureInfo; class TilePainter; -class BaseTile; +class Tile; struct TileRenderInfo { // coordinates of the tile @@ -58,13 +59,13 @@ struct TileRenderInfo { TilePainter* tilePainter; // the base tile calling us - BaseTile* baseTile; + Tile* baseTile; // info about the texture that we are to render into TextureInfo* textureInfo; - // specifies whether or not to measure the rendering performance - bool measurePerf; + bool isPureColor; + Color pureColor; }; /** @@ -76,7 +77,7 @@ public: BaseRenderer(RendererType type) : m_type(type) {} virtual ~BaseRenderer() {} - void renderTiledContent(const TileRenderInfo& renderInfo); + void renderTiledContent(TileRenderInfo& renderInfo); RendererType getType() { return m_type; } @@ -90,14 +91,10 @@ protected: virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; virtual void setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas) {} virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; + virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) = 0; void drawTileInfo(SkCanvas* canvas, const TileRenderInfo& renderInfo, - int updateCount); - - virtual const String* getPerformanceTags(int& tagCount) = 0; - - // Performance tracking - PerformanceMonitor m_perfMon; + int updateCount, double renderDuration); private: RendererType m_type; diff --git a/Source/WebCore/platform/graphics/android/rendering/DrawQuadData.h b/Source/WebCore/platform/graphics/android/rendering/DrawQuadData.h new file mode 100644 index 0000000..687808d --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/DrawQuadData.h @@ -0,0 +1,172 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DrawQuadData_h +#define DrawQuadData_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "Color.h" +#include "SkRect.h" +#include <GLES2/gl2.h> + +namespace WebCore { + +class TransformationMatrix; + +enum DrawQuadType { + BaseQuad, + LayerQuad, + Blit // 1:1 straight pixel blit +}; + +// Both PureColorQuadData and TextureQuadData share the data from DrawQuadData. +class DrawQuadData { +public: + DrawQuadData(DrawQuadType type = BaseQuad, + const TransformationMatrix* drawMatrix = 0, + const SkRect* geometry = 0, + float opacity = 1.0f, + bool forceBlending = true) + : m_type(type) + , m_drawMatrix(drawMatrix) + , m_geometry(geometry) + , m_opacity(opacity) + , m_forceBlending(forceBlending) + { + } + + DrawQuadData(const DrawQuadData& data) + : m_type(data.m_type) + , m_drawMatrix(data.m_drawMatrix) + , m_geometry(data.m_geometry) + , m_opacity(data.m_opacity) + , m_forceBlending(data.m_forceBlending) + { + } + + virtual ~DrawQuadData() {}; + + DrawQuadType type() const { return m_type; } + const TransformationMatrix* drawMatrix() const { return m_drawMatrix; } + const SkRect* geometry() const { return m_geometry; } + float opacity() const { return m_opacity; } + bool forceBlending() const { return m_forceBlending; } + + void updateDrawMatrix(TransformationMatrix* matrix) { m_drawMatrix = matrix; } + void updateGeometry(SkRect* rect) { m_geometry = rect; } + void updateOpacity(float opacity) { m_opacity = opacity; } + + virtual bool pureColor() const { return false; } + + virtual Color quadColor() const { return Color(); } + + virtual int textureId() const { return 0; } + virtual GLint textureFilter() const { return 0; } + virtual GLenum textureTarget() const { return 0; } + +private: + DrawQuadType m_type; + const TransformationMatrix* m_drawMatrix; + const SkRect* m_geometry; + float m_opacity; + bool m_forceBlending; +}; + +class PureColorQuadData : public DrawQuadData { +public: + PureColorQuadData(Color color, + DrawQuadType type = BaseQuad, + const TransformationMatrix* drawMatrix = 0, + const SkRect* geometry = 0, + float opacity = 1.0f, + bool forceBlending = true) + : DrawQuadData(type, drawMatrix, geometry, opacity, forceBlending) + { + m_quadColor = color; + } + + PureColorQuadData(const DrawQuadData& data, Color color) + : DrawQuadData(data) + { + m_quadColor = color; + } + + virtual ~PureColorQuadData() {}; + virtual bool pureColor() const { return true; } + virtual Color quadColor() const { return m_quadColor; } + void updateColor(const Color& color) { m_quadColor = color; } + +private: + Color m_quadColor; +}; + +class TextureQuadData : public DrawQuadData { +public: + TextureQuadData(int textureId, + GLenum textureTarget = GL_TEXTURE_2D, + GLint textureFilter = GL_LINEAR, + DrawQuadType type = BaseQuad, + const TransformationMatrix* drawMatrix = 0, + const SkRect* geometry = 0, + float opacity = 1.0f, + bool forceBlending = true) + : DrawQuadData(type, drawMatrix, geometry, opacity, forceBlending) + { + m_textureId = textureId; + m_textureTarget = textureTarget; + m_textureFilter = textureFilter; + } + + TextureQuadData(const DrawQuadData& data, + int textureId, + GLenum textureTarget = GL_TEXTURE_2D, + GLint textureFilter = GL_LINEAR) + : DrawQuadData(data) + { + m_textureId = textureId; + m_textureTarget = textureTarget; + m_textureFilter = textureFilter; + } + + virtual ~TextureQuadData() {}; + virtual bool pureColor() const { return false; } + + virtual int textureId() const { return m_textureId; } + virtual GLint textureFilter() const { return m_textureFilter; } + virtual GLenum textureTarget() const { return m_textureTarget; } + + void updateTextureId(int newId) { m_textureId = newId; } + +private: + int m_textureId; + GLint m_textureFilter; + GLenum m_textureTarget; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // DrawQuadData_h diff --git a/Source/WebCore/platform/graphics/android/GLExtras.cpp b/Source/WebCore/platform/graphics/android/rendering/GLExtras.cpp index 1676489..6498ecf 100644 --- a/Source/WebCore/platform/graphics/android/GLExtras.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/GLExtras.cpp @@ -30,8 +30,10 @@ #include "AndroidLog.h" #include "DrawExtra.h" +#include "DrawQuadData.h" #include "GLExtras.h" #include "IntRect.h" +#include "SkPath.h" #include "TilesManager.h" #include "android_graphics.h" @@ -61,11 +63,10 @@ void GLExtras::drawRing(SkRect& srcRect, Color color, const TransformationMatrix // double applied Color colorWithoutAlpha(0xFF000000 | color.rgb()); float alpha = color.alpha() / (float) 255; - if (drawMat) { - TilesManager::instance()->shader()->drawLayerQuad(*drawMat, srcRect, 0, - alpha, false, 0, colorWithoutAlpha); - } else - TilesManager::instance()->shader()->drawQuad(srcRect, 0, alpha, colorWithoutAlpha); + + PureColorQuadData data(colorWithoutAlpha, drawMat ? LayerQuad : BaseQuad, + drawMat, &srcRect, alpha, false); + TilesManager::instance()->shader()->drawQuad(&data); } void GLExtras::drawRegion(const SkRegion& region, bool fill, bool drawBorder, diff --git a/Source/WebCore/platform/graphics/android/GLExtras.h b/Source/WebCore/platform/graphics/android/rendering/GLExtras.h index 59a7c3c..59a7c3c 100644 --- a/Source/WebCore/platform/graphics/android/GLExtras.h +++ b/Source/WebCore/platform/graphics/android/rendering/GLExtras.h diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp index ecd6bce..9435065 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp @@ -31,10 +31,14 @@ #if USE(ACCELERATED_COMPOSITING) -#include "ShaderProgram.h" +#include "AndroidLog.h" +#include "BaseRenderer.h" +#include "TextureInfo.h" +#include "Tile.h" #include "TilesManager.h" +#include "TransferQueue.h" -#include <AndroidLog.h> +#include <android/native_window.h> #include <gui/SurfaceTexture.h> #include <wtf/CurrentTime.h> @@ -384,7 +388,7 @@ GLuint GLUtils::createSampleTexture() return texture; } -GLuint GLUtils::createBaseTileGLTexture(int width, int height) +GLuint GLUtils::createTileGLTexture(int width, int height) { GLuint texture; glGenTextures(1, &texture); @@ -412,7 +416,7 @@ GLuint GLUtils::createBaseTileGLTexture(int width, int height) bool GLUtils::isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor) { - // If the bitmap is the pure color, skip the transfer step, and update the BaseTile Info. + // 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. pureColor = Color(Color::transparent); @@ -455,25 +459,23 @@ bool GLUtils::skipTransferForPureColor(const TileRenderInfo* renderInfo, const SkBitmap& bitmap) { bool skipTransfer = false; - BaseTile* tilePtr = renderInfo->baseTile; + Tile* tilePtr = renderInfo->baseTile; // TODO: use pure color for partial invals as well if (renderInfo->invalRect) return false; if (tilePtr) { - BaseTileTexture* tileTexture = tilePtr->backTexture(); + TileTexture* tileTexture = tilePtr->backTexture(); // Check the bitmap, and make everything ready here. - Color pureColor; - if (tileTexture && isPureColorBitmap(bitmap, pureColor)) { + if (tileTexture && renderInfo->isPureColor) { // update basetile's info // Note that we are skipping the whole TransferQueue. renderInfo->textureInfo->m_width = bitmap.width(); renderInfo->textureInfo->m_height = bitmap.height(); renderInfo->textureInfo->m_internalFormat = GL_RGBA; - TilesManager::instance()->transferQueue()->addItemInPureColorQueue(renderInfo, - pureColor); + TilesManager::instance()->transferQueue()->addItemInPureColorQueue(renderInfo); skipTransfer = true; } @@ -493,14 +495,14 @@ void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo, return; if (requiredSize.equals(textureInfo->m_width, textureInfo->m_height)) - GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, bitmap); + GLUtils::updateQueueWithBitmap(renderInfo, bitmap); else { if (!requiredSize.equals(bitmap.width(), bitmap.height())) { ALOGV("The bitmap size (%d,%d) does not equal the texture size (%d,%d)", bitmap.width(), bitmap.height(), requiredSize.width(), requiredSize.height()); } - GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, bitmap); + GLUtils::updateQueueWithBitmap(renderInfo, bitmap); textureInfo->m_width = bitmap.width(); textureInfo->m_height = bitmap.height(); @@ -508,7 +510,7 @@ void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo, } } -void GLUtils::updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap) +void GLUtils::updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap) { if (!renderInfo || !renderInfo->textureInfo @@ -518,6 +520,42 @@ void GLUtils::updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* renderI TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, bitmap); } +bool GLUtils::updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap) +{ + SkAutoLockPixels alp(bitmap); + if (!bitmap.getPixels()) + return false; + ANativeWindow_Buffer buffer; + if (ANativeWindow_lock(anw, &buffer, 0)) + return false; + if (buffer.width < bitmap.width() || buffer.height < bitmap.height()) { + ALOGW("bitmap (%dx%d) too large for buffer (%dx%d)!", + bitmap.width(), bitmap.height(), + buffer.width, buffer.height); + ANativeWindow_unlockAndPost(anw); + return false; + } + uint8_t* img = (uint8_t*)buffer.bits; + int row; + int bpp = 4; // Now we only deal with RGBA8888 format. + bitmap.lockPixels(); + uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels()); + + if (buffer.stride != bitmap.width()) + // Copied line by line since we need to handle the offsets and stride. + for (row = 0 ; row < bitmap.height(); row ++) { + uint8_t* dst = &(img[buffer.stride * row * bpp]); + uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]); + memcpy(dst, src, bpp * bitmap.width()); + } + else + memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height()); + + bitmap.unlockPixels(); + ANativeWindow_unlockAndPost(anw); + return true; +} + void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -540,16 +578,6 @@ void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GL } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - - // The following is a workaround -- remove when EGLImage texture upload is fixed. - GLuint fboID; - glGenFramebuffers(1, &fboID); - glBindFramebuffer(GL_FRAMEBUFFER, fboID); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); - glCheckFramebufferStatus(GL_FRAMEBUFFER); // should return GL_FRAMEBUFFER_COMPLETE - - glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the standard FBO - glDeleteFramebuffers(1, &fboID); } void GLUtils::updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, @@ -609,6 +637,23 @@ void GLUtils::convertToTransformationMatrix(const float* matrix, TransformationM matrix[12], matrix[13], matrix[14], matrix[15]); } +void GLUtils::clearBackgroundIfOpaque(const Color* backgroundColor) +{ + if (!backgroundColor->hasAlpha()) { + if (TilesManager::instance()->invertedScreen()) { + float color = 1.0 - ((((float) backgroundColor->red() / 255.0) + + ((float) backgroundColor->green() / 255.0) + + ((float) backgroundColor->blue() / 255.0)) / 3.0); + glClearColor(color, color, color, 1); + } else { + glClearColor((float)backgroundColor->red() / 255.0, + (float)backgroundColor->green() / 255.0, + (float)backgroundColor->blue() / 255.0, 1); + } + glClear(GL_COLOR_BUFFER_BIT); + } +} + } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/GLUtils.h b/Source/WebCore/platform/graphics/android/rendering/GLUtils.h index e001aee..d4a2e84 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.h +++ b/Source/WebCore/platform/graphics/android/rendering/GLUtils.h @@ -31,8 +31,6 @@ #include "Color.h" #include "SkBitmap.h" #include "SkMatrix.h" -#include "SkSize.h" -#include "TextureInfo.h" #include "TransformationMatrix.h" #include <EGL/egl.h> #include <EGL/eglext.h> @@ -47,6 +45,8 @@ class SurfaceTexture; namespace WebCore { +class TileRenderInfo; + class GLUtils { public: @@ -71,7 +71,7 @@ public: static void deleteTexture(GLuint* texture); static GLuint createSampleColorTexture(int r, int g, int b); static GLuint createSampleTexture(); - static GLuint createBaseTileGLTexture(int width, int height); + static GLuint createTileGLTexture(int width, int height); static void createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter = GL_LINEAR); static void updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, const IntRect&, GLint filter = GL_LINEAR); @@ -79,12 +79,14 @@ public: static void createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter = GL_LINEAR); static void paintTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); - static void updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* , const SkBitmap& bitmap); + static void updateQueueWithBitmap(const TileRenderInfo* , const SkBitmap& bitmap); + static bool updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap); static void convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix); static bool isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor); static bool skipTransferForPureColor(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); + static void clearBackgroundIfOpaque(const Color* backgroundColor); static bool allowGLLog(); static double m_previousLogTime; static int m_currentLogCounter; diff --git a/Source/WebCore/platform/graphics/android/GaneshContext.cpp b/Source/WebCore/platform/graphics/android/rendering/GaneshContext.cpp index 620fccf..5c4b453 100644 --- a/Source/WebCore/platform/graphics/android/GaneshContext.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/GaneshContext.cpp @@ -31,6 +31,9 @@ #include "AndroidLog.h" #include "GLUtils.h" +#include "TextureInfo.h" +#include "TilesManager.h" +#include "TransferQueue.h" #include "android/native_window.h" @@ -40,7 +43,7 @@ namespace WebCore { GaneshContext::GaneshContext() : m_grContext(0) - , m_baseTileDeviceSurface(0) + , m_tileDeviceSurface(0) , m_surfaceConfig(0) , m_surfaceContext(EGL_NO_CONTEXT) { @@ -57,9 +60,8 @@ GaneshContext* GaneshContext::instance() GrContext* GaneshContext::getGrContext() { - if (!m_grContext) { - m_grContext = GrContext::Create(kOpenGL_Shaders_GrEngine, NULL); - } + if (!m_grContext) + m_grContext = GrContext::Create(kOpenGL_Shaders_GrEngine, 0); return m_grContext; } @@ -69,7 +71,7 @@ void GaneshContext::flush() m_grContext->flush(); } -SkDevice* GaneshContext::getDeviceForBaseTile(const TileRenderInfo& renderInfo) +SkDevice* GaneshContext::getDeviceForTile(const TileRenderInfo& renderInfo) { // Ganesh should be the only code in the rendering thread that is using GL // and setting the EGLContext. If this is not the case then we need to @@ -85,9 +87,8 @@ SkDevice* GaneshContext::getDeviceForBaseTile(const TileRenderInfo& renderInfo) if (!m_surfaceContext) { - if(eglGetCurrentContext() != EGL_NO_CONTEXT) { + if(eglGetCurrentContext() != EGL_NO_CONTEXT) ALOGV("ERROR: should not have a context yet"); - } display = eglGetDisplay(EGL_DEFAULT_DISPLAY); GLUtils::checkEglError("eglGetDisplay"); @@ -146,7 +147,7 @@ SkDevice* GaneshContext::getDeviceForBaseTile(const TileRenderInfo& renderInfo) GLUtils::checkEglError("eglMakeCurrent", returnValue); ALOGV("eglMakeCurrent"); - if (!m_baseTileDeviceSurface) { + if (!m_tileDeviceSurface) { GrPlatformRenderTargetDesc renderTargetDesc; renderTargetDesc.fWidth = TilesManager::tileWidth(); @@ -159,19 +160,19 @@ SkDevice* GaneshContext::getDeviceForBaseTile(const TileRenderInfo& renderInfo) GrContext* grContext = getGrContext(); GrRenderTarget* renderTarget = grContext->createPlatformRenderTarget(renderTargetDesc); - m_baseTileDeviceSurface = new SkGpuDevice(grContext, renderTarget); + m_tileDeviceSurface = new SkGpuDevice(grContext, renderTarget); renderTarget->unref(); - ALOGV("generated device %p", m_baseTileDeviceSurface); + ALOGV("generated device %p", m_tileDeviceSurface); } - GLUtils::checkGlError("getDeviceForBaseTile"); + GLUtils::checkGlError("getDeviceForTile"); // We must reset the Ganesh context only after we are sure we have // re-established our EGLContext as the current context. - if (m_baseTileDeviceSurface && contextNeedsReset) + if (m_tileDeviceSurface && contextNeedsReset) getGrContext()->resetContext(); - return m_baseTileDeviceSurface; + return m_tileDeviceSurface; } diff --git a/Source/WebCore/platform/graphics/android/GaneshContext.h b/Source/WebCore/platform/graphics/android/rendering/GaneshContext.h index def35e5..57e8e19 100644 --- a/Source/WebCore/platform/graphics/android/GaneshContext.h +++ b/Source/WebCore/platform/graphics/android/rendering/GaneshContext.h @@ -31,7 +31,7 @@ #include "BaseRenderer.h" #include "GrContext.h" #include "SkGpuDevice.h" -#include "TilesManager.h" +#include <EGL/egl.h> namespace WebCore { @@ -39,7 +39,7 @@ class GaneshContext { public: static GaneshContext* instance(); - SkDevice* getDeviceForBaseTile(const TileRenderInfo& renderInfo); + SkDevice* getDeviceForTile(const TileRenderInfo& renderInfo); void flush(); @@ -50,7 +50,7 @@ private: GrContext* getGrContext(); GrContext* m_grContext; - SkGpuDevice* m_baseTileDeviceSurface; + SkGpuDevice* m_tileDeviceSurface; EGLConfig m_surfaceConfig; EGLContext m_surfaceContext; diff --git a/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp index 74b008c..208adb6 100644 --- a/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp @@ -36,19 +36,10 @@ #include "SkCanvas.h" #include "SkGpuDevice.h" #include "TilesManager.h" +#include "TransferQueue.h" namespace WebCore { -static const String TAG_CREATE_FBO = "create_fbo"; -static const String TAG_DRAW_PICTURE = "draw_picture"; -static const String TAG_UPDATE_TEXTURE = "update_texture"; -#define TAG_COUNT 3 -static const String TAGS[] = { - TAG_CREATE_FBO, - TAG_DRAW_PICTURE, - TAG_UPDATE_TEXTURE, -}; - GaneshRenderer::GaneshRenderer() : BaseRenderer(BaseRenderer::Ganesh) { #ifdef DEBUG_COUNT @@ -65,9 +56,6 @@ GaneshRenderer::~GaneshRenderer() void GaneshRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) { - if (renderInfo.measurePerf) - m_perfMon.start(TAG_CREATE_FBO); - GaneshContext* ganesh = GaneshContext::instance(); TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); @@ -84,7 +72,7 @@ void GaneshRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can SkDevice* device = NULL; if (renderInfo.tileSize.width() == TilesManager::tileWidth() && renderInfo.tileSize.height() == TilesManager::tileHeight()) { - device = ganesh->getDeviceForBaseTile(renderInfo); + device = ganesh->getDeviceForTile(renderInfo); } else { // TODO support arbitrary sizes for layers ALOGV("ERROR: expected (%d,%d) actual (%d,%d)", @@ -92,11 +80,6 @@ void GaneshRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can renderInfo.tileSize.width(), renderInfo.tileSize.height()); } - if (renderInfo.measurePerf) { - m_perfMon.stop(TAG_CREATE_FBO); - m_perfMon.start(TAG_DRAW_PICTURE); - } - // set the GPU device to the canvas canvas->setDevice(device); } @@ -113,11 +96,6 @@ void GaneshRenderer::setupPartialInval(const TileRenderInfo& renderInfo, SkCanva void GaneshRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) { - if (renderInfo.measurePerf) { - m_perfMon.stop(TAG_DRAW_PICTURE); - m_perfMon.start(TAG_UPDATE_TEXTURE); - } - ALOGV("rendered to tile (%d,%d)", renderInfo.x, renderInfo.y); GaneshContext::instance()->flush(); @@ -128,15 +106,6 @@ void GaneshRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanva eglSwapBuffers(eglGetCurrentDisplay(), tileQueue->m_eglSurface); tileQueue->addItemInTransferQueue(&renderInfo, GpuUpload, 0); tileQueue->unlockQueue(); - - if (renderInfo.measurePerf) - m_perfMon.stop(TAG_UPDATE_TEXTURE); -} - -const String* GaneshRenderer::getPerformanceTags(int& tagCount) -{ - tagCount = TAG_COUNT; - return TAGS; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/GaneshRenderer.h b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h index 0e1d41e..d7eda24 100644 --- a/Source/WebCore/platform/graphics/android/GaneshRenderer.h +++ b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h @@ -49,7 +49,9 @@ protected: virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas); virtual void setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas); virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas); - virtual const String* getPerformanceTags(int& tagCount); + virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) { + renderInfo.isPureColor = false; + } }; diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.cpp b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp index e42d075..6e4a82c 100644 --- a/Source/WebCore/platform/graphics/android/ImageTexture.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp @@ -30,12 +30,13 @@ #include "ImageTexture.h" #include "AndroidLog.h" +#include "ClassTracker.h" #include "ImagesManager.h" #include "LayerAndroid.h" #include "SkDevice.h" #include "SkPicture.h" +#include "TileGrid.h" #include "TilesManager.h" -#include "TiledTexture.h" namespace WebCore { @@ -71,7 +72,7 @@ unsigned computeCrc(uint8_t* buffer, size_t size) ImageTexture::ImageTexture(SkBitmap* bmp, unsigned crc) : m_image(bmp) - , m_texture(0) + , m_tileGrid(0) , m_layer(0) , m_picture(0) , m_crc(crc) @@ -84,7 +85,7 @@ ImageTexture::ImageTexture(SkBitmap* bmp, unsigned crc) // NOTE: This constructor is called on the webcore thread - // Create a picture containing the image (needed for TiledTexture) + // Create a picture containing the image (needed for TileGrid) m_picture = new SkPicture(); SkCanvas* pcanvas = m_picture->beginRecording(m_image->width(), m_image->height()); pcanvas->clear(SkColorSetARGBInline(0, 0, 0, 0)); @@ -98,7 +99,7 @@ ImageTexture::~ImageTexture() ClassTracker::instance()->decrement("ImageTexture"); #endif delete m_image; - delete m_texture; + delete m_tileGrid; SkSafeUnref(m_picture); } @@ -144,13 +145,13 @@ int ImageTexture::nbTextures() { if (!hasContentToShow()) return 0; - if (!m_texture) + if (!m_tileGrid) return 0; // TODO: take in account the visible clip (need to maintain // a list of the clients layer, etc.) IntRect visibleArea(0, 0, m_image->width(), m_image->height()); - int nbTextures = m_texture->nbTextures(visibleArea, 1.0); + int nbTextures = m_tileGrid->nbTextures(visibleArea, 1.0); ALOGV("ImageTexture %p, %d x %d needs %d textures", this, m_image->width(), m_image->height(), nbTextures); @@ -172,20 +173,21 @@ bool ImageTexture::prepareGL(GLWebViewState* state) if (!hasContentToShow()) return false; - if (!m_texture && m_picture) { - m_texture = new TiledTexture(); + if (!m_tileGrid && m_picture) { + bool isBaseSurface = false; + m_tileGrid = new TileGrid(isBaseSurface); SkRegion region; region.setRect(0, 0, m_image->width(), m_image->height()); - m_texture->markAsDirty(region); + m_tileGrid->markAsDirty(region); } - if (!m_texture) + if (!m_tileGrid) return false; - IntRect visibleArea(0, 0, m_image->width(), m_image->height()); - m_texture->prepareGL(state, 1.0, visibleArea, this); - if (m_texture->isReady()) { - m_texture->swapTiles(); + IntRect unclippedArea(0, 0, m_image->width(), m_image->height()); + m_tileGrid->prepareGL(state, 1.0, unclippedArea, unclippedArea, this); + if (m_tileGrid->isReady()) { + m_tileGrid->swapTiles(); return false; } return true; @@ -196,8 +198,6 @@ const TransformationMatrix* ImageTexture::transform() if (!m_layer) return 0; - FloatPoint p(0, 0); - p = m_layer->drawTransform()->mapPoint(p); IntRect layerArea = m_layer->unclippedArea(); float scaleW = static_cast<float>(layerArea.width()) / static_cast<float>(m_image->width()); float scaleH = static_cast<float>(layerArea.height()) / static_cast<float>(m_image->height()); @@ -215,14 +215,14 @@ float ImageTexture::opacity() return m_layer->drawOpacity(); } -bool ImageTexture::paint(BaseTile* tile, SkCanvas* canvas) +bool ImageTexture::paint(SkCanvas* canvas) { if (!m_picture) { ALOGV("IT %p COULDNT PAINT, NO PICTURE", this); return false; } - ALOGV("IT %p painting tile %d, %d with picture %p", this, tile->x(), tile->y(), m_picture); + ALOGV("IT %p painting with picture %p", this, m_picture); canvas->drawPicture(*m_picture); return true; @@ -235,12 +235,12 @@ void ImageTexture::drawGL(LayerAndroid* layer, float opacity) if (!hasContentToShow()) return; - // TiledTexture::draw() will call us back to know the + // TileGrid::draw() will call us back to know the // transform and opacity, so we need to set m_layer m_layer = layer; - if (m_texture) { + if (m_tileGrid) { IntRect visibleArea = m_layer->visibleArea(); - m_texture->drawGL(visibleArea, opacity, transform()); + m_tileGrid->drawGL(visibleArea, opacity, transform()); } m_layer = 0; } diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.h b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.h index 91c8a29..fccbb78 100644 --- a/Source/WebCore/platform/graphics/android/ImageTexture.h +++ b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.h @@ -31,13 +31,14 @@ #include "SkBitmapRef.h" #include "SkPicture.h" #include "SkRefCnt.h" -#include "LayerAndroid.h" +#include "TilePainter.h" namespace WebCore { +class GLWebViewState; class LayerAndroid; class TexturesResult; -class TiledTexture; +class TileGrid; ///////////////////////////////////////////////////////////////////////////////// // Image sharing codepath for layers @@ -63,7 +64,7 @@ class TiledTexture; // ImageTexture at draw time. // // ImageTexture recopy the original SkBitmap so that they can safely be used -// on a different thread; it uses TiledTexture to allocate and paint the image, +// on a different thread; it uses TileGrid to allocate and paint the image, // so that we can share the same textures and limits as the rest of the layers. // ///////////////////////////////////////////////////////////////////////////////// @@ -84,8 +85,8 @@ public: static unsigned computeCRC(const SkBitmap* bitmap); bool equalsCRC(unsigned crc); - // methods used by TiledTexture - virtual bool paint(BaseTile* tile, SkCanvas* canvas); + // methods used by TileGrid + virtual bool paint(SkCanvas* canvas); virtual float opacity(); int nbTextures(); @@ -97,7 +98,7 @@ private: SkBitmapRef* m_imageRef; SkBitmap* m_image; - TiledTexture* m_texture; + TileGrid* m_tileGrid; LayerAndroid* m_layer; SkPicture* m_picture; TransformationMatrix m_layerMatrix; diff --git a/Source/WebCore/platform/graphics/android/ImagesManager.cpp b/Source/WebCore/platform/graphics/android/rendering/ImagesManager.cpp index 8452503..8452503 100644 --- a/Source/WebCore/platform/graphics/android/ImagesManager.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/ImagesManager.cpp diff --git a/Source/WebCore/platform/graphics/android/ImagesManager.h b/Source/WebCore/platform/graphics/android/rendering/ImagesManager.h index b915a46..b915a46 100644 --- a/Source/WebCore/platform/graphics/android/ImagesManager.h +++ b/Source/WebCore/platform/graphics/android/rendering/ImagesManager.h diff --git a/Source/WebCore/platform/graphics/android/InspectorCanvas.cpp b/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.cpp index f9edb74..f9edb74 100644 --- a/Source/WebCore/platform/graphics/android/InspectorCanvas.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.cpp diff --git a/Source/WebCore/platform/graphics/android/InspectorCanvas.h b/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.h index 415a579..415a579 100644 --- a/Source/WebCore/platform/graphics/android/InspectorCanvas.h +++ b/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.h diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp index 1fcb765..fcd9d3b 100644 --- a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp @@ -23,20 +23,27 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "PaintTileOperation" +#define LOG_NDEBUG 1 + #include "config.h" #include "PaintTileOperation.h" + +#include "AndroidLog.h" +#include "GLWebViewState.h" #include "ImageTexture.h" #include "ImagesManager.h" #include "LayerAndroid.h" -#include "TiledPage.h" #include "TilesManager.h" namespace WebCore { -PaintTileOperation::PaintTileOperation(BaseTile* tile, TilePainter* painter) - : QueuedOperation(tile->page()) - , m_tile(tile) +PaintTileOperation::PaintTileOperation(Tile* tile, TilePainter* painter, + GLWebViewState* state, bool isLowResPrefetch) + : m_tile(tile) , m_painter(painter) + , m_state(state) + , m_isLowResPrefetch(isLowResPrefetch) { if (m_tile) m_tile->setRepaintPending(true); @@ -66,6 +73,8 @@ bool PaintTileOperation::operator==(const QueuedOperation* operation) void PaintTileOperation::run() { + TRACE_METHOD(); + if (m_tile) { m_tile->paintBitmap(m_painter); m_tile->setRepaintPending(false); @@ -80,14 +89,9 @@ int PaintTileOperation::priority() int priority = 200000; - // if scrolling, prioritize the prefetch page, otherwise deprioritize - TiledPage* page = m_tile->page(); - if (page && page->isPrefetchPage()) { - if (page->glWebViewState()->isScrolling()) - priority = 0; - else - priority = 400000; - } + // prioritize low res while scrolling + if (m_isLowResPrefetch) + priority = m_state->isScrolling() ? 0 : 400000; // prioritize higher draw count unsigned long long currentDraw = TilesManager::instance()->getDrawGLCount(); @@ -100,7 +104,7 @@ int PaintTileOperation::priority() // for base tiles, prioritize based on position if (!m_tile->isLayerTile()) { - bool goingDown = m_tile->page()->scrollingDown(); + bool goingDown = m_state->goingDown(); priority += m_tile->x(); if (goingDown) diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.h b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h index 05825e2..1d376bf 100644 --- a/Source/WebCore/platform/graphics/android/PaintTileOperation.h +++ b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h @@ -26,7 +26,7 @@ #ifndef PaintTileSetOperation_h #define PaintTileSetOperation_h -#include "BaseTile.h" +#include "Tile.h" #include "QueuedOperation.h" #include "SkRefCnt.h" @@ -38,7 +38,8 @@ class ImageTexture; class PaintTileOperation : public QueuedOperation { public: - PaintTileOperation(BaseTile* tile, TilePainter* painter); + PaintTileOperation(Tile* tile, TilePainter* painter, + GLWebViewState* state, bool isLowResPrefetch); virtual ~PaintTileOperation(); virtual bool operator==(const QueuedOperation* operation); virtual void run(); @@ -48,8 +49,10 @@ public: float scale() { return m_tile->scale(); } private: - BaseTile* m_tile; + Tile* m_tile; TilePainter* m_painter; + GLWebViewState* m_state; + bool m_isLowResPrefetch; }; class ScaleFilter : public OperationFilter { diff --git a/Source/WebCore/platform/graphics/android/QueuedOperation.h b/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h index 2f36547..f98efcd 100644 --- a/Source/WebCore/platform/graphics/android/QueuedOperation.h +++ b/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h @@ -28,19 +28,12 @@ namespace WebCore { -class TiledPage; - class QueuedOperation { public: - QueuedOperation(TiledPage* page) - : m_page(page) {} virtual ~QueuedOperation() {} virtual void run() = 0; virtual bool operator==(const QueuedOperation* operation) = 0; - virtual int priority() { return -1; } - TiledPage* page() const { return m_page; } -private: - TiledPage* m_page; + virtual int priority() = 0; }; class OperationFilter { @@ -49,19 +42,6 @@ public: virtual bool check(QueuedOperation* operation) = 0; }; -class PageFilter : public OperationFilter { -public: - PageFilter(TiledPage* page) : m_page(page) {} - virtual bool check(QueuedOperation* operation) - { - if (operation->page() == m_page) - return true; - return false; - } -private: - TiledPage* m_page; -}; - } #endif // QueuedOperation_h diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp index 44f2a7d..b880eef 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp @@ -23,30 +23,25 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "RasterRenderer" +#define LOG_NDEBUG 1 + #include "config.h" #include "RasterRenderer.h" #if USE(ACCELERATED_COMPOSITING) +#include "AndroidLog.h" #include "GLUtils.h" #include "SkBitmap.h" #include "SkBitmapRef.h" #include "SkCanvas.h" #include "SkDevice.h" +#include "Tile.h" #include "TilesManager.h" namespace WebCore { -static const String TAG_CREATE_BITMAP = "create_bitmap"; -static const String TAG_DRAW_PICTURE = "draw_picture"; -static const String TAG_UPDATE_TEXTURE = "update_texture"; -#define TAG_COUNT 3 -static const String TAGS[] = { - TAG_CREATE_BITMAP, - TAG_DRAW_PICTURE, - TAG_UPDATE_TEXTURE, -}; - SkBitmap* RasterRenderer::g_bitmap = 0; RasterRenderer::RasterRenderer() : BaseRenderer(BaseRenderer::Raster) @@ -72,24 +67,24 @@ RasterRenderer::~RasterRenderer() void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) { - if (renderInfo.measurePerf) - m_perfMon.start(TAG_CREATE_BITMAP); - if (renderInfo.baseTile->isLayerTile()) { g_bitmap->setIsOpaque(false); g_bitmap->eraseARGB(0, 0, 0, 0); } else { - g_bitmap->setIsOpaque(true); - g_bitmap->eraseARGB(255, 255, 255, 255); + Color defaultBackground = Color::white; + Color* background = renderInfo.tilePainter->background(); + if (!background) { + ALOGV("No background color for base layer!"); + 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()); } SkDevice* device = new SkDevice(*g_bitmap); - if (renderInfo.measurePerf) { - m_perfMon.stop(TAG_CREATE_BITMAP); - m_perfMon.start(TAG_DRAW_PICTURE); - } - canvas->setDevice(device); device->unref(); @@ -106,23 +101,13 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can void RasterRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) { - if (renderInfo.measurePerf) { - m_perfMon.stop(TAG_DRAW_PICTURE); - m_perfMon.start(TAG_UPDATE_TEXTURE); - } - const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); - GLUtils::paintTextureWithBitmap(&renderInfo, bitmap); - - if (renderInfo.measurePerf) - m_perfMon.stop(TAG_UPDATE_TEXTURE); } -const String* RasterRenderer::getPerformanceTags(int& tagCount) +void RasterRenderer::checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) { - tagCount = TAG_COUNT; - return TAGS; + renderInfo.isPureColor = GLUtils::isPureColorBitmap(*g_bitmap, renderInfo.pureColor); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.h b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h index 96b3f58..39e00f2 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.h +++ b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h @@ -49,7 +49,7 @@ protected: virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas); virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas); - virtual const String* getPerformanceTags(int& tagCount); + virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas); private: static SkBitmap* g_bitmap; diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp index 33829e3..b1fe2f4 100644 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp @@ -32,6 +32,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "AndroidLog.h" +#include "DrawQuadData.h" #include "FloatPoint3D.h" #include "GLUtils.h" #include "TilesManager.h" @@ -39,6 +40,8 @@ #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> +#define EPSILON 0.00001f + namespace WebCore { static const char gVertexShader[] = @@ -384,7 +387,22 @@ void ShaderProgram::setupDrawing(const IntRect& viewRect, const SkRect& visibleR TransformationMatrix orthoScale; orthoScale.scale3d(orthoScaleX, orthoScaleY, 1.0); - m_projectionMatrix = ortho * orthoScale; + m_visibleRectProjectionMatrix = ortho * orthoScale; + + ALOGV("set m_clipProjectionMatrix, %d, %d, %d, %d", + screenClip.x(), screenClip.y(), screenClip.x() + screenClip.width(), + screenClip.y() + screenClip.height()); + + // In order to incorporate the animation delta X and Y, using the clip as + // the GL viewport can save all the trouble of re-position from webViewRect + // to final position. + GLUtils::setOrthographicMatrix(m_clipProjectionMatrix, screenClip.x(), screenClip.y(), + screenClip.x() + screenClip.width(), + screenClip.y() + screenClip.height(), -1000, 1000); + + glViewport(screenClip.x(), m_targetHeight - screenClip.y() - screenClip.height() , + screenClip.width(), screenClip.height()); + m_viewport = visibleRect; m_currentScale = scale; @@ -401,10 +419,10 @@ void ShaderProgram::setupDrawing(const IntRect& viewRect, const SkRect& visibleR TransformationMatrix viewScale; viewScale.scale3d(m_viewRect.width() * 0.5f, m_viewRect.height() * 0.5f, 1); - m_documentToScreenMatrix = viewScale * viewTranslate * m_projectionMatrix; + m_documentToScreenMatrix = viewScale * viewTranslate * m_visibleRectProjectionMatrix; viewTranslate.scale3d(1, -1, 1); - m_documentToInvScreenMatrix = viewScale * viewTranslate * m_projectionMatrix; + m_documentToInvScreenMatrix = viewScale * viewTranslate * m_visibleRectProjectionMatrix; IntRect rect(0, 0, m_webViewRect.width(), m_webViewRect.height()); m_documentViewport = m_documentToScreenMatrix.inverse().mapRect(rect); @@ -421,24 +439,10 @@ void ShaderProgram::setupDrawing(const IntRect& viewRect, const SkRect& visibleR m_screenClip.setSize(IntSize(ceilf(tclip.width()), ceilf(tclip.height()))); resetBlending(); -} -// Calculate the matrix given the geometry. -void ShaderProgram::setProjectionMatrix(const SkRect& geometry, GLfloat* mtxPtr) -{ - TransformationMatrix translate; - translate.translate3d(geometry.fLeft, geometry.fTop, 0.0); - TransformationMatrix scale; - scale.scale3d(geometry.width(), geometry.height(), 1.0); - - TransformationMatrix total; - if (!m_alphaLayer) - total = m_projectionMatrix * m_repositionMatrix * m_webViewMatrix - * translate * scale; - else - total = m_projectionMatrix * translate * scale; - - GLUtils::toGLMatrix(mtxPtr, total); + // Set up m_clipProjectionMatrix, m_currentScale and m_webViewMatrix before + // calling this function. + setupSurfaceProjectionMatrix(); } // Calculate the right color value sent into the shader considering the (0,1) @@ -482,33 +486,6 @@ ShaderType ShaderProgram::getTextureShaderType(GLenum textureTarget) return type; } -void ShaderProgram::drawQuad(const SkRect& geometry, int textureId, float opacity, - Color pureColor, GLenum textureTarget, GLint texFilter) -{ - ShaderType type = UndefinedShader; - if (!textureId) { - pureColor = shaderColor(pureColor, opacity); - if (pureColor.rgb() == Color::transparent && opacity < 1.0) - return; - type = PureColor; - } else - type = getTextureShaderType(textureTarget); - - if (type != UndefinedShader) { - // The matrix is either for the transfer queue or the tiles - GLfloat* finalMatrix = m_transferProjMtx; - GLfloat projectionMatrix[16]; - if (!geometry.isEmpty()) { - setProjectionMatrix(geometry, projectionMatrix); - finalMatrix = projectionMatrix; - } - setBlendingState(opacity < 1.0); - drawQuadInternal(type, finalMatrix, textureId, opacity, textureTarget, - texFilter, pureColor); - } - GLUtils::checkGlError("drawQuad"); -} - // This function transform a clip rect extracted from the current layer // into a clip rect in screen coordinates -- used by the clipping rects FloatRect ShaderProgram::rectInScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size) @@ -559,6 +536,9 @@ void ShaderProgram::clip(const FloatRect& clip) if (clip == m_clipRect) return; + ALOGV("--clipping rect %f %f, %f x %f", + clip.x(), clip.y(), clip.width(), clip.height()); + // we should only call glScissor in this function, so that we can easily // track the current clipping rect. @@ -600,7 +580,7 @@ float ShaderProgram::zValue(const TransformationMatrix& drawMatrix, float w, flo { TransformationMatrix modifiedDrawMatrix = drawMatrix; modifiedDrawMatrix.scale3d(w, h, 1); - TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix; + TransformationMatrix renderMatrix = m_visibleRectProjectionMatrix * modifiedDrawMatrix; FloatPoint3D point(0.5, 0.5, 0.0); FloatPoint3D result = renderMatrix.mapPoint(point); return result.z(); @@ -639,44 +619,81 @@ void ShaderProgram::drawQuadInternal(ShaderType type, const GLfloat* matrix, glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } -void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix, - const SkRect& geometry, int textureId, - float opacity, bool forceBlending, - GLenum textureTarget, - Color pureColor) +// Put the common matrix computation at higher level to avoid redundancy. +void ShaderProgram::setupSurfaceProjectionMatrix() { - TransformationMatrix modifiedDrawMatrix = drawMatrix; - // move the drawing depending on where the texture is on the layer - modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop); - modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1); + TransformationMatrix scaleMatrix; + scaleMatrix.scale3d(m_currentScale, m_currentScale, 1); + m_surfaceProjectionMatrix = m_clipProjectionMatrix * m_webViewMatrix * scaleMatrix; +} +// Calculate the matrix given the geometry. +GLfloat* ShaderProgram::getTileProjectionMatrix(const DrawQuadData* data) +{ + DrawQuadType type = data->type(); + if (type == Blit) + return m_transferProjMtx; + + const TransformationMatrix* matrix = data->drawMatrix(); + const SkRect* geometry = data->geometry(); + + // This modifiedDrawMatrix tranform (0,0)(1x1) to the final rect in screen + // coordinate, before applying the m_webViewMatrix. + // It first scale and translate the vertex array from (0,0)(1x1) to real + // tile position and size. Then apply the transform from the layer's. + // Finally scale to the currentScale to support zooming. + // Note the geometry contains the tile zoom scale, so visually we will see + // the tiles scale at a ratio as (m_currentScale/tile's scale). + TransformationMatrix modifiedDrawMatrix; + if (type == LayerQuad) + modifiedDrawMatrix = *matrix; + modifiedDrawMatrix.translate(geometry->fLeft, geometry->fTop); + modifiedDrawMatrix.scale3d(geometry->width(), geometry->height(), 1); + + // Even when we are on a alpha layer or not, we need to respect the + // m_webViewMatrix, it may contain the layout offset. Normally it is + // identity. TransformationMatrix renderMatrix; - if (!m_alphaLayer) - renderMatrix = m_projectionMatrix * m_repositionMatrix - * m_webViewMatrix * modifiedDrawMatrix; - else - renderMatrix = m_projectionMatrix * modifiedDrawMatrix; + renderMatrix = m_surfaceProjectionMatrix * modifiedDrawMatrix; - GLfloat projectionMatrix[16]; - GLUtils::toGLMatrix(projectionMatrix, renderMatrix); +#if DEBUG_MATRIX + debugMatrixInfo(m_currentScale, m_clipProjectionMatrix, m_webViewMatrix, + modifiedDrawMatrix, matrix); +#endif + + GLUtils::toGLMatrix(m_tileProjMatrix, renderMatrix); + return m_tileProjMatrix; +} + +void ShaderProgram::drawQuad(const DrawQuadData* data) +{ + GLfloat* matrix = getTileProjectionMatrix(data); + + float opacity = data->opacity(); + bool forceBlending = data->forceBlending(); bool enableBlending = forceBlending || opacity < 1.0; - ShaderType type = UndefinedShader; - if (!textureId) { - pureColor = shaderColor(pureColor, opacity); - if (pureColor.rgb() == Color::transparent && enableBlending) + ShaderType shaderType = UndefinedShader; + int textureId = 0; + GLint textureFilter = 0; + GLenum textureTarget = 0; + + Color quadColor = data->quadColor(); + if (data->pureColor()) { + shaderType = PureColor; + quadColor = shaderColor(quadColor, opacity); + enableBlending = enableBlending || quadColor.hasAlpha(); + if (!quadColor.alpha() && enableBlending) return; - type = PureColor; - } else - type = getTextureShaderType(textureTarget); - - if (type != UndefinedShader) { - setBlendingState(enableBlending); - drawQuadInternal(type, projectionMatrix, textureId, opacity, - textureTarget, GL_LINEAR, pureColor); + } else { + textureId = data->textureId(); + textureFilter = data->textureFilter(); + textureTarget = data->textureTarget(); + shaderType = getTextureShaderType(textureTarget); } - - GLUtils::checkGlError("drawLayerQuad"); + setBlendingState(enableBlending); + drawQuadInternal(shaderType, matrix, textureId, opacity, + textureTarget, textureFilter, quadColor); } void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix, @@ -685,11 +702,14 @@ void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix, { // switch to our custom yuv video rendering program glUseProgram(m_handleArray[Video].programHandle); - - TransformationMatrix modifiedDrawMatrix = drawMatrix; + // TODO: Merge drawVideoLayerQuad into drawQuad. + TransformationMatrix modifiedDrawMatrix; + modifiedDrawMatrix.scale3d(m_currentScale, m_currentScale, 1); + modifiedDrawMatrix.multiply(drawMatrix); modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop); modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1); - TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix; + TransformationMatrix renderMatrix = + m_clipProjectionMatrix * m_webViewMatrix * modifiedDrawMatrix; GLfloat projectionMatrix[16]; GLUtils::toGLMatrix(projectionMatrix, renderMatrix); @@ -711,44 +731,91 @@ void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix, glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } -void ShaderProgram::setWebViewMatrix(const float* matrix, bool alphaLayer) +void ShaderProgram::setGLDrawInfo(const android::uirenderer::DrawGlInfo* info) { - GLUtils::convertToTransformationMatrix(matrix, m_webViewMatrix); - m_alphaLayer = alphaLayer; + GLUtils::convertToTransformationMatrix(info->transform, m_webViewMatrix); + m_alphaLayer = info->isLayer; + m_targetHeight = info->height; } -void ShaderProgram::calculateAnimationDelta() +// This function is called per tileGrid to minimize the computation overhead. +// The ortho projection and glViewport will map 1:1, so we don't need to +// worry about them here. Basically, if the current zoom scale / tile's scale +// plus the webview and layer transformation ends up at scale factor 1.0, +// then we can use point sampling. +bool ShaderProgram::usePointSampling(float tileScale, + const TransformationMatrix* layerTransform) { - // The matrix contains the scrolling info, so this rect is starting from - // the m_viewport. - // So we just need to map the webview's visible rect using the matrix, - // calculate the difference b/t transformed rect and the webViewRect, - // then we can get the delta x , y caused by the animation. - // Note that the Y is for reporting back to GL viewport, so it is inverted. - // When it is alpha animation, then we rely on the framework implementation - // such that there is no matrix applied in native webkit. - if (!m_alphaLayer) { - FloatRect rect(m_viewport.fLeft * m_currentScale, - m_viewport.fTop * m_currentScale, - m_webViewRect.width(), - m_webViewRect.height()); - rect = m_webViewMatrix.mapRect(rect); - m_animationDelta.setX(rect.x() - m_webViewRect.x() ); - m_animationDelta.setY(rect.y() + rect.height() - m_webViewRect.y() - - m_webViewRect.height() - m_titleBarHeight); - - m_repositionMatrix.makeIdentity(); - m_repositionMatrix.translate3d(-m_webViewRect.x(), -m_webViewRect.y() - m_titleBarHeight, 0); - m_repositionMatrix.translate3d(m_viewport.fLeft * m_currentScale, m_viewport.fTop * m_currentScale, 0); - m_repositionMatrix.translate3d(-m_animationDelta.x(), -m_animationDelta.y(), 0); - } else { - m_animationDelta.setX(0); - m_animationDelta.setY(0); - m_repositionMatrix.makeIdentity(); + const float testSize = 1.0; + FloatRect rect(0, 0, testSize, testSize); + TransformationMatrix matrix; + matrix.scale3d(m_currentScale, m_currentScale, 1); + if (layerTransform) + matrix.multiply(*layerTransform); + matrix.scale3d(1.0 / tileScale, 1.0 / tileScale, 1); + + matrix = m_webViewMatrix * matrix; + + rect = matrix.mapRect(rect); + + float deltaWidth = abs(rect.width() - testSize); + float deltaHeight = abs(rect.height() - testSize); + + if (deltaWidth < EPSILON && deltaHeight < EPSILON) { + ALOGV("Point sampling : deltaWidth is %f, deltaHeight is %f", deltaWidth, deltaHeight); + return true; } + return false; +} + +#if DEBUG_MATRIX +FloatRect ShaderProgram::debugMatrixTransform(const TransformationMatrix& matrix, + const char* matrixName) +{ + FloatRect rect(0.0, 0.0, 1.0, 1.0); + rect = matrix.mapRect(rect); + ALOGV("After %s matrix:\n %f, %f rect.width() %f rect.height() %f", + matrixName, rect.x(), rect.y(), rect.width(), rect.height()); + return rect; } -} // namespace WebCore +void ShaderProgram::debugMatrixInfo(float currentScale, + const TransformationMatrix& clipProjectionMatrix, + const TransformationMatrix& webViewMatrix, + const TransformationMatrix& modifiedDrawMatrix, + const TransformationMatrix* layerMatrix) +{ + int viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + ALOGV("viewport %d, %d, %d, %d , currentScale %f", + viewport[0], viewport[1], viewport[2], viewport[3], currentScale); + IntRect currentGLViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + + TransformationMatrix scaleMatrix; + scaleMatrix.scale3d(currentScale, currentScale, 1.0); + + if (layerMatrix) + debugMatrixTransform(*layerMatrix, "layerMatrix"); + + TransformationMatrix debugMatrix = scaleMatrix * modifiedDrawMatrix; + debugMatrixTransform(debugMatrix, "scaleMatrix * modifiedDrawMatrix"); + + debugMatrix = webViewMatrix * debugMatrix; + debugMatrixTransform(debugMatrix, "webViewMatrix * scaleMatrix * modifiedDrawMatrix"); + + debugMatrix = clipProjectionMatrix * debugMatrix; + FloatRect finalRect = + debugMatrixTransform(debugMatrix, "all Matrix"); + // After projection, we will be in a (-1, 1) range and now we can map it back + // to the (x,y) -> (x+width, y+height) + ALOGV("final convert to screen coord x, y %f, %f width %f height %f , ", + (finalRect.x() + 1) / 2 * currentGLViewport.width() + currentGLViewport.x(), + (finalRect.y() + 1) / 2 * currentGLViewport.height() + currentGLViewport.y(), + finalRect.width() * currentGLViewport.width() / 2, + finalRect.height() * currentGLViewport.height() / 2); +} +#endif // DEBUG_MATRIX +} // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.h b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h index 98d45b5..cfdccda 100644 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.h +++ b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h @@ -24,12 +24,18 @@ #include "IntRect.h" #include "SkRect.h" #include "TransformationMatrix.h" +#include "private/hwui/DrawGlInfo.h" #include <GLES2/gl2.h> #define MAX_CONTRAST 5 +#define DEBUG_MATRIX 0 namespace WebCore { +class DrawQuadData; +class PureColorQuadData; +class TextureQuadData; + enum ShaderType { UndefinedShader = -1, PureColor, @@ -45,14 +51,14 @@ enum ShaderType { struct ShaderHandles { ShaderHandles() - : alphaHandle(-1) - , contrastHandle(-1) - , positionHandle(-1) - , programHandle(-1) - , projMtxHandle(-1) - , pureColorHandle(-1) - , texSamplerHandle(-1) - , videoMtxHandle(-1) + : alphaHandle(-1) + , contrastHandle(-1) + , positionHandle(-1) + , programHandle(-1) + , projMtxHandle(-1) + , pureColorHandle(-1) + , texSamplerHandle(-1) + , videoMtxHandle(-1) { } @@ -82,16 +88,16 @@ struct ShaderHandles { struct ShaderResource { ShaderResource() - : program(-1) - , vertexShader(-1) - , fragmentShader(-1) + : program(-1) + , vertexShader(-1) + , fragmentShader(-1) { }; ShaderResource(GLuint prog, GLuint vertex, GLuint fragment) - : program(prog) - , vertexShader(vertex) - , fragmentShader(fragment) + : program(prog) + , vertexShader(vertex) + , fragmentShader(fragment) { }; @@ -118,14 +124,7 @@ public: // Surface texture in GL_TEXTURE_EXTERNAL_OES target. // 3) textureId == 0 // No texture needed, just a pureColor quad. - void drawQuad(const SkRect& geometry, int textureId, float opacity, Color pureColor = Color(), - GLenum textureTarget = GL_TEXTURE_2D, - GLint texFilter = GL_LINEAR); - void drawLayerQuad(const TransformationMatrix& drawMatrix, - const SkRect& geometry, int textureId, float opacity, - bool forceBlending = false, - GLenum textureTarget = GL_TEXTURE_2D, - Color pureColor = Color()); + void drawQuad(const DrawQuadData* data); void drawVideoLayerQuad(const TransformationMatrix& drawMatrix, float* textureMatrix, SkRect& geometry, int textureId); FloatRect rectInScreenCoord(const TransformationMatrix& drawMatrix, @@ -153,24 +152,15 @@ public: contrast = MAX_CONTRAST; m_contrast = contrast; } - void setWebViewMatrix(const float* matrix, bool alphaLayer); - - // This delta is the delta from the layout pos and the current animation pos. - // Basically, in terms of layout, the webview is still in the original layout - // pos, as without animation. Such that the viewport and visible rect etc are - // still in that pos, too, except the clipping info. - // Our rendering approach is after applying all the matrix, webView is - // rendered as if it was at the original layout pos, but then offset the - // glViewport to match the animation. - void calculateAnimationDelta(); - int getAnimationDeltaX() { return m_animationDelta.x(); } - int getAnimationDeltaY() { return m_animationDelta.y(); } + void setGLDrawInfo(const android::uirenderer::DrawGlInfo* info); + bool needsInit() { return m_needsInit; } + bool usePointSampling(float tileScale, const TransformationMatrix* layerTransform); private: GLuint loadShader(GLenum shaderType, const char* pSource); GLint createProgram(const char* vertexSource, const char* fragmentSource); - void setProjectionMatrix(const SkRect& geometry, GLfloat* mtxPtr); + GLfloat* getTileProjectionMatrix(const DrawQuadData* data); void setBlendingState(bool enableBlending); void drawQuadInternal(ShaderType type, const GLfloat* matrix, int textureId, float opacity, GLenum textureTarget, GLenum filter, @@ -178,10 +168,21 @@ private: Color shaderColor(Color pureColor, float opacity); ShaderType getTextureShaderType(GLenum textureTarget); void resetBlending(); + void setupSurfaceProjectionMatrix(); +#if DEBUG_MATRIX + FloatRect debugMatrixTransform(const TransformationMatrix& matrix, const char* matrixName); + void debugMatrixInfo(float currentScale, + const TransformationMatrix& clipProjectionMatrix, + const TransformationMatrix& webViewMatrix, + const TransformationMatrix& modifiedDrawMatrix, + const TransformationMatrix* layerMatrix); +#endif // DEBUG_MATRIX bool m_blendingEnabled; - TransformationMatrix m_projectionMatrix; + TransformationMatrix m_surfaceProjectionMatrix; + TransformationMatrix m_clipProjectionMatrix; + TransformationMatrix m_visibleRectProjectionMatrix; GLuint m_textureBuffer[1]; TransformationMatrix m_documentToScreenMatrix; @@ -191,28 +192,20 @@ private: FloatRect m_clipRect; IntRect m_screenClip; int m_titleBarHeight; + // This is the layout position in screen coordinate and didn't contain the + // animation offset. IntRect m_webViewRect; FloatRect m_documentViewport; float m_contrast; + // The height of the render target, either FBO or screen. + int m_targetHeight; bool m_alphaLayer; TransformationMatrix m_webViewMatrix; float m_currentScale; - // After the webViewTranform, we need to reposition the rect to match our viewport. - // Basically, the webViewTransformMatrix should apply on the screen resolution. - // So we start by doing the scale and translate to get each tile into screen coordinates. - // After applying the webViewTransformMatrix, b/c the way it currently set up - // for scroll and titlebar, we need to offset both of them. - // Finally, map everything back to (-1, 1) by using the m_projectionMatrix. - // TODO: Given that m_webViewMatrix contains most of the tranformation - // information, we should be able to get rid of some parameter we got from - // Java side and simplify our code. - TransformationMatrix m_repositionMatrix; - IntPoint m_animationDelta; - // Put all the uniform location (handle) info into an array, and group them // by the shader's type, this can help to clean up the interface. // TODO: use the type and data comparison to skip GL call if possible. @@ -226,6 +219,8 @@ private: // (-1,1) GLfloat m_transferProjMtx[16]; + GLfloat m_tileProjMatrix[16]; + Vector<ShaderResource> m_resources; }; diff --git a/Source/WebCore/platform/graphics/android/LayerGroup.cpp b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp index f360919..a9ebd1e 100644 --- a/Source/WebCore/platform/graphics/android/LayerGroup.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp @@ -23,80 +23,83 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define LOG_TAG "LayerGroup" +#define LOG_TAG "Surface" #define LOG_NDEBUG 1 #include "config.h" -#include "LayerGroup.h" +#include "Surface.h" #include "AndroidLog.h" +#include "BaseLayerAndroid.h" #include "ClassTracker.h" #include "LayerAndroid.h" -#include "TiledTexture.h" +#include "GLWebViewState.h" +#include "SkCanvas.h" +#include "SurfaceBacking.h" #include "TilesManager.h" -// LayerGroups with an area larger than 2048*2048 should never be unclipped +// Surfaces with an area larger than 2048*2048 should never be unclipped #define MAX_UNCLIPPED_AREA 4194304 namespace WebCore { -LayerGroup::LayerGroup() - : m_dualTiledTexture(0) +Surface::Surface() + : m_surfaceBacking(0) , m_needsTexture(false) , m_hasText(false) { #ifdef DEBUG_COUNT - ClassTracker::instance()->increment("LayerGroup"); + ClassTracker::instance()->increment("Surface"); #endif } -LayerGroup::~LayerGroup() +Surface::~Surface() { for (unsigned int i = 0; i < m_layers.size(); i++) SkSafeUnref(m_layers[i]); - if (m_dualTiledTexture) - SkSafeUnref(m_dualTiledTexture); + if (m_surfaceBacking) + SkSafeUnref(m_surfaceBacking); #ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("LayerGroup"); + ClassTracker::instance()->decrement("Surface"); #endif } -bool LayerGroup::tryUpdateLayerGroup(LayerGroup* oldLayerGroup) +bool Surface::tryUpdateSurface(Surface* oldSurface) { - if (!needsTexture() || !oldLayerGroup->needsTexture()) + if (!needsTexture() || !oldSurface->needsTexture()) return false; - // merge layer group based on first layer ID - if (getFirstLayer()->uniqueId() != oldLayerGroup->getFirstLayer()->uniqueId()) + // merge surfaces based on first layer ID + if (getFirstLayer()->uniqueId() != oldSurface->getFirstLayer()->uniqueId()) return false; - m_dualTiledTexture = oldLayerGroup->m_dualTiledTexture; - SkSafeRef(m_dualTiledTexture); + m_surfaceBacking = oldSurface->m_surfaceBacking; + SkSafeRef(m_surfaceBacking); - ALOGV("%p taking old DTT %p from group %p, nt %d", - this, m_dualTiledTexture, oldLayerGroup, oldLayerGroup->needsTexture()); + ALOGV("%p taking old SurfBack %p from surface %p, nt %d", + this, m_surfaceBacking, oldSurface, oldSurface->needsTexture()); - if (!m_dualTiledTexture) { - // no DTT to inval, so don't worry about it. + if (!m_surfaceBacking) { + // no SurfBack to inval, so don't worry about it. return true; } - if (singleLayer() && oldLayerGroup->singleLayer()) { + if (singleLayer() && oldSurface->singleLayer()) { // both are single matching layers, simply apply inval SkRegion* layerInval = getFirstLayer()->getInvalRegion(); - m_dualTiledTexture->markAsDirty(*layerInval); + m_surfaceBacking->markAsDirty(*layerInval); } else { SkRegion invalRegion; - bool fullInval = m_layers.size() != oldLayerGroup->m_layers.size(); + bool fullInval = m_layers.size() != oldSurface->m_layers.size(); if (!fullInval) { for (unsigned int i = 0; i < m_layers.size(); i++) { - if (m_layers[i]->uniqueId() != oldLayerGroup->m_layers[i]->uniqueId()) { + if (m_layers[i]->uniqueId() != oldSurface->m_layers[i]->uniqueId()) { // layer list has changed, fully invalidate // TODO: partially invalidate based on layer size/position fullInval = true; break; } else if (!m_layers[i]->getInvalRegion()->isEmpty()) { - // merge layer inval - translate the layer's inval region into group coordinates + // merge layer inval - translate the layer's inval region into surface coordinates SkPoint pos = m_layers[i]->getPosition(); m_layers[i]->getInvalRegion()->translate(pos.fX, pos.fY); invalRegion.op(*(m_layers[i]->getInvalRegion()), SkRegion::kUnion_Op); @@ -108,12 +111,12 @@ bool LayerGroup::tryUpdateLayerGroup(LayerGroup* oldLayerGroup) if (fullInval) invalRegion.setRect(-1e8, -1e8, 2e8, 2e8); - m_dualTiledTexture->markAsDirty(invalRegion); + m_surfaceBacking->markAsDirty(invalRegion); } return true; } -void LayerGroup::addLayer(LayerAndroid* layer, const TransformationMatrix& transform) +void Surface::addLayer(LayerAndroid* layer, const TransformationMatrix& transform) { m_layers.append(layer); SkSafeRef(layer); @@ -133,14 +136,17 @@ void LayerGroup::addLayer(LayerAndroid* layer, const TransformationMatrix& trans m_unclippedArea = rect; } else m_unclippedArea.unite(rect); - ALOGV("LG %p adding LA %p, size %d, %d %dx%d, now LG size %d,%d %dx%d", + ALOGV("Surf %p adding LA %p, size %d, %d %dx%d, now Surf size %d,%d %dx%d", this, layer, rect.x(), rect.y(), rect.width(), rect.height(), m_unclippedArea.x(), m_unclippedArea.y(), m_unclippedArea.width(), m_unclippedArea.height()); } + + if (isBase()) + m_background = static_cast<BaseLayerAndroid*>(layer)->getBackgroundColor(); } -IntRect LayerGroup::visibleArea() +IntRect Surface::visibleArea() { if (singleLayer()) return getFirstLayer()->visibleArea(); @@ -156,78 +162,114 @@ IntRect LayerGroup::visibleArea() return rect; } -void LayerGroup::prepareGL(bool layerTilesDisabled) +IntRect Surface::unclippedArea() +{ + if (singleLayer()) + return getFirstLayer()->unclippedArea(); + return m_unclippedArea; +} + +bool Surface::useAggressiveRendering() +{ + // When the background is semi-opaque, 0 < alpha < 255, we had to turn off + // low res to avoid artifacts from double drawing. + // TODO: avoid double drawing for low res tiles. + return isBase() + && (!m_background.alpha() + || !m_background.hasAlpha()); +} + +void Surface::prepareGL(bool layerTilesDisabled) { - if (!m_dualTiledTexture) { - ALOGV("prepareGL on LG %p, no DTT, needsTexture? %d", - this, m_dualTiledTexture, needsTexture()); + bool tilesDisabled = layerTilesDisabled && !isBase(); + if (!m_surfaceBacking) { + ALOGV("prepareGL on Surf %p, no SurfBack, needsTexture? %d", + this, m_surfaceBacking, needsTexture()); - if (needsTexture()) - m_dualTiledTexture = new DualTiledTexture(); - else + if (!needsTexture()) return; + + m_surfaceBacking = new SurfaceBacking(isBase()); } - if (layerTilesDisabled) { - m_dualTiledTexture->discardTextures(); + if (tilesDisabled) { + m_surfaceBacking->discardTextures(); } else { bool allowZoom = hasText(); // only allow for scale > 1 if painting vectors IntRect prepareArea = computePrepareArea(); + IntRect fullArea = unclippedArea(); - ALOGV("prepareGL on LG %p with DTT %p, %d layers", - this, m_dualTiledTexture, m_layers.size()); - m_dualTiledTexture->prepareGL(getFirstLayer()->state(), allowZoom, - prepareArea, this); + ALOGV("prepareGL on Surf %p with SurfBack %p, %d layers", + this, m_surfaceBacking, m_layers.size()); + + m_surfaceBacking->prepareGL(getFirstLayer()->state(), allowZoom, + prepareArea, fullArea, + this, useAggressiveRendering()); } } -bool LayerGroup::drawGL(bool layerTilesDisabled) +bool Surface::drawGL(bool layerTilesDisabled) { + bool tilesDisabled = layerTilesDisabled && !isBase(); if (!getFirstLayer()->visible()) return false; - FloatRect drawClip = getFirstLayer()->drawClip(); - FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(drawClip); - TilesManager::instance()->shader()->clip(clippingRect); + if (!isBase()) { + // TODO: why are clipping regions wrong for base layer? + FloatRect drawClip = getFirstLayer()->drawClip(); + FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(drawClip); + TilesManager::instance()->shader()->clip(clippingRect); + } bool askRedraw = false; - if (m_dualTiledTexture && !layerTilesDisabled) { - ALOGV("drawGL on LG %p with DTT %p", this, m_dualTiledTexture); + if (m_surfaceBacking && !tilesDisabled) { + ALOGV("drawGL on Surf %p with SurfBack %p", this, m_surfaceBacking); + // TODO: why this visibleArea is different from visibleRect at zooming for base? IntRect drawArea = visibleArea(); - askRedraw |= m_dualTiledTexture->drawGL(drawArea, opacity(), drawTransform()); + m_surfaceBacking->drawGL(drawArea, opacity(), drawTransform(), + useAggressiveRendering(), background()); } // draw member layers (draws image textures, glextras) for (unsigned int i = 0; i < m_layers.size(); i++) - askRedraw |= m_layers[i]->drawGL(layerTilesDisabled); + askRedraw |= m_layers[i]->drawGL(tilesDisabled); return askRedraw; } -void LayerGroup::swapTiles() +void Surface::swapTiles() { - if (!m_dualTiledTexture) + if (!m_surfaceBacking) return; - m_dualTiledTexture->swapTiles(); + m_surfaceBacking->swapTiles(); +} + +bool Surface::isReady() +{ + if (!m_surfaceBacking) + return true; + + return m_surfaceBacking->isReady(); } -bool LayerGroup::isReady() +bool Surface::isMissingContent() { - if (!m_dualTiledTexture) + if (!m_surfaceBacking) return true; - return m_dualTiledTexture->isReady(); + return m_surfaceBacking->isMissingContent(); } -IntRect LayerGroup::computePrepareArea() { +IntRect Surface::computePrepareArea() { IntRect area; if (!getFirstLayer()->contentIsScrollable() + && !isBase() && getFirstLayer()->state()->layersRenderingMode() == GLWebViewState::kAllTextures) { - area = singleLayer() ? getFirstLayer()->unclippedArea() : m_unclippedArea; + area = unclippedArea(); double total = ((double) area.width()) * ((double) area.height()); if (total > MAX_UNCLIPPED_AREA) @@ -239,18 +281,36 @@ IntRect LayerGroup::computePrepareArea() { return area; } -void LayerGroup::computeTexturesAmount(TexturesResult* result) +void Surface::computeTexturesAmount(TexturesResult* result) { - if (!m_dualTiledTexture) + if (!m_surfaceBacking || isBase()) return; - m_dualTiledTexture->computeTexturesAmount(result, getFirstLayer()); + m_surfaceBacking->computeTexturesAmount(result, getFirstLayer()); +} + +bool Surface::isBase() +{ + // base layer surface + // - doesn't use layer tiles (disables blending, doesn't compute textures amount) + // - ignores clip rects + // - only prepares clippedArea + return getFirstLayer()->subclassType() == LayerAndroid::BaseLayer; } -bool LayerGroup::paint(BaseTile* tile, SkCanvas* canvas) +bool Surface::paint(SkCanvas* canvas) { if (singleLayer()) { getFirstLayer()->contentDraw(canvas, Layer::UnmergedLayers); + + // TODO: double buffer by disabling SurfaceCollection swaps and position + // updates until painting complete + + // In single surface mode, draw layer content onto the base layer + if (isBase() + && getFirstLayer()->countChildren() + && getFirstLayer()->state()->layersRenderingMode() > GLWebViewState::kClippedTextures) + getFirstLayer()->getChild(0)->drawCanvas(canvas, true, Layer::FlattenedLayers); } else { SkAutoCanvasRestore acr(canvas, true); SkMatrix matrix; @@ -270,18 +330,25 @@ bool LayerGroup::paint(BaseTile* tile, SkCanvas* canvas) return true; } -float LayerGroup::opacity() +float Surface::opacity() { if (singleLayer()) - return getFirstLayer()->getOpacity(); + return getFirstLayer()->drawOpacity(); return 1.0; } -const TransformationMatrix* LayerGroup::drawTransform() +Color* Surface::background() +{ + if (!isBase() || !m_background.isValid()) + return 0; + return &m_background; +} + +const TransformationMatrix* Surface::drawTransform() { - // single layer groups query the layer's draw transform, while multi-layer - // groups copy the draw transform once, during initialization - // TODO: support fixed multi-layer groups by querying the changing drawTransform + // single layer surfaces query the layer's draw transform, while multi-layer + // surfaces copy the draw transform once, during initialization + // TODO: support fixed multi-layer surfaces by querying the changing drawTransform if (singleLayer()) return getFirstLayer()->drawTransform(); diff --git a/Source/WebCore/platform/graphics/android/LayerGroup.h b/Source/WebCore/platform/graphics/android/rendering/Surface.h index 90001a5..0fced47 100644 --- a/Source/WebCore/platform/graphics/android/LayerGroup.h +++ b/Source/WebCore/platform/graphics/android/rendering/Surface.h @@ -23,9 +23,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef LayerGroup_h -#define LayerGroup_h +#ifndef Surface_h +#define Surface_h +#include "Color.h" #include "IntRect.h" #include "TilePainter.h" #include "Vector.h" @@ -35,62 +36,70 @@ class SkRegion; namespace WebCore { -class BaseTile; -class DualTiledTexture; -class TexturesResult; +class Tile; +class SurfaceBacking; class LayerAndroid; +class TexturesResult; -class LayerGroup : public TilePainter { +class Surface : public TilePainter { public: - LayerGroup(); - virtual ~LayerGroup(); - - bool tryUpdateLayerGroup(LayerGroup* oldLayerGroup); + Surface(); + virtual ~Surface(); + bool tryUpdateSurface(Surface* oldSurface); void addLayer(LayerAndroid* layer, const TransformationMatrix& transform); - IntRect visibleArea(); void prepareGL(bool layerTilesDisabled); bool drawGL(bool layerTilesDisabled); void swapTiles(); bool isReady(); + bool isMissingContent(); - IntRect computePrepareArea(); void computeTexturesAmount(TexturesResult* result); - LayerAndroid* getFirstLayer() { return m_layers[0]; } - bool singleLayer() { return m_layers.size() == 1; } + LayerAndroid* getFirstLayer() const { return m_layers[0]; } bool needsTexture() { return m_needsTexture; } bool hasText() { return m_hasText; } + bool isBase(); // TilePainter methods - virtual bool paint(BaseTile* tile, SkCanvas* canvas); + virtual bool paint(SkCanvas* canvas); virtual float opacity(); + virtual Color* background(); + private: + IntRect computePrepareArea(); + IntRect visibleArea(); + IntRect unclippedArea(); + bool singleLayer() { return m_layers.size() == 1; } + bool useAggressiveRendering(); + const TransformationMatrix* drawTransform(); IntRect m_unclippedArea; TransformationMatrix m_drawTransform; - DualTiledTexture* m_dualTiledTexture; + SurfaceBacking* m_surfaceBacking; bool m_needsTexture; bool m_hasText; Vector<LayerAndroid*> m_layers; + + Color m_background; }; class LayerMergeState { public: - LayerMergeState(Vector<LayerGroup*>* const allGroups) - : groupList(allGroups) - , currentLayerGroup(0) + LayerMergeState(Vector<Surface*>* const allGroups) + : surfaceList(allGroups) + , currentSurface(0) , nonMergeNestedLevel(-1) // start at -1 to ignore first LayerAndroid's clipping , depth(0) {} // vector storing all generated layer groups - Vector<LayerGroup*>* const groupList; + Vector<Surface*>* const surfaceList; // currently merging group. if cleared, no more layers may join - LayerGroup* currentLayerGroup; + Surface* currentSurface; // records depth within non-mergeable parents (clipping, fixed, scrolling) // and disable merging therein. @@ -102,4 +111,4 @@ public: } // namespace WebCore -#endif //#define LayerGroup_h +#endif //#define Surface_h diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp new file mode 100644 index 0000000..f43472e --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp @@ -0,0 +1,196 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "SurfaceBacking" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "SurfaceBacking.h" + +#include "AndroidLog.h" +#include "Color.h" +#include "GLWebViewState.h" +#include "LayerAndroid.h" + +#define LOW_RES_PREFETCH_SCALE_MODIFIER 0.3f + +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; +} + +SurfaceBacking::~SurfaceBacking() +{ + delete m_frontTileGrid; + delete m_backTileGrid; + delete m_lowResTileGrid; +} + +void SurfaceBacking::prepareGL(GLWebViewState* state, bool allowZoom, + const IntRect& prepareArea, const IntRect& unclippedArea, + TilePainter* painter, bool aggressiveRendering) +{ + float scale = state->scale(); + if (scale > 1 && !allowZoom) + scale = 1; + + if (m_scale == -1) { + m_scale = scale; + m_futureScale = scale; + } + + if (m_futureScale != scale) { + m_futureScale = scale; + m_zoomUpdateTime = WTF::currentTime() + SurfaceBacking::s_zoomUpdateDelay; + m_zooming = true; + + // release back TileGrid's TileTextures, so they can be reused immediately + m_backTileGrid->discardTextures(); + } + + int prepareRegionFlags = TileGrid::StandardRegion; + if (aggressiveRendering) + prepareRegionFlags |= TileGrid::ExpandedRegion; + + ALOGV("Prepare SurfBack %p, scale %.2f, m_scale %.2f, futScale: %.2f, zooming: %d, f %p, b %p", + this, scale, m_scale, m_futureScale, m_zooming, + m_frontTileGrid, m_backTileGrid); + + if (m_zooming && (m_zoomUpdateTime < WTF::currentTime())) { + // prepare the visible portions of the back tile grid at the futureScale + m_backTileGrid->prepareGL(state, m_futureScale, + prepareArea, unclippedArea, painter, + TileGrid::StandardRegion, false); + + if (m_backTileGrid->isReady()) { + // zooming completed, swap the TileGrids and new front tiles + swapTileGrids(); + + m_frontTileGrid->swapTiles(); + m_backTileGrid->discardTextures(); + m_lowResTileGrid->discardTextures(); + + m_scale = m_futureScale; + m_zooming = false; + + // clear the StandardRegion flag, to prevent preparing it twice - + // the new frontTileGrid has already had its StandardRegion prepared + prepareRegionFlags &= ~TileGrid::StandardRegion; + } + } + + if (!m_zooming) { + if (prepareRegionFlags) { + // if the front grid hasn't already prepared, or needs to prepare + // expanded bounds do so now + m_frontTileGrid->prepareGL(state, m_scale, + prepareArea, unclippedArea, painter, prepareRegionFlags, false); + } + if (aggressiveRendering) { + // prepare low res content + float lowResPrefetchScale = m_scale * LOW_RES_PREFETCH_SCALE_MODIFIER; + m_lowResTileGrid->prepareGL(state, lowResPrefetchScale, + prepareArea, unclippedArea, painter, + TileGrid::StandardRegion | TileGrid::ExpandedRegion, true); + m_lowResTileGrid->swapTiles(); + } + } +} + +void SurfaceBacking::drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform, + bool aggressiveRendering, const Color* background) +{ + // draw low res prefetch page if zooming or front texture missing content + if (aggressiveRendering && isMissingContent()) + m_lowResTileGrid->drawGL(visibleArea, opacity, transform); + + m_frontTileGrid->drawGL(visibleArea, opacity, transform, background); +} + +void SurfaceBacking::markAsDirty(const SkRegion& dirtyArea) +{ + m_backTileGrid->markAsDirty(dirtyArea); + m_frontTileGrid->markAsDirty(dirtyArea); + m_lowResTileGrid->markAsDirty(dirtyArea); +} + +void SurfaceBacking::swapTiles() +{ + m_backTileGrid->swapTiles(); + m_frontTileGrid->swapTiles(); + m_lowResTileGrid->swapTiles(); +} + +void SurfaceBacking::computeTexturesAmount(TexturesResult* result, LayerAndroid* layer) +{ + // TODO: shouldn't use layer, as this SB may paint multiple layers + if (!layer) + return; + + IntRect unclippedArea = layer->unclippedArea(); + IntRect clippedVisibleArea = layer->visibleArea(); + + // get two numbers here: + // - textures needed for a clipped area + // - textures needed for an un-clipped area + TileGrid* tileGrid = m_zooming ? m_backTileGrid : m_frontTileGrid; + int nbTexturesUnclipped = tileGrid->nbTextures(unclippedArea, m_scale); + int nbTexturesClipped = tileGrid->nbTextures(clippedVisibleArea, m_scale); + + // Set kFixedLayers level + if (layer->isPositionFixed()) + result->fixed += nbTexturesClipped; + + // Set kScrollableAndFixedLayers level + if (layer->contentIsScrollable() + || layer->isPositionFixed()) + result->scrollable += nbTexturesClipped; + + // Set kClippedTextures level + result->clipped += nbTexturesClipped; + + // Set kAllTextures level + if (layer->contentIsScrollable()) + result->full += nbTexturesClipped; + else + result->full += nbTexturesUnclipped; +} + +void SurfaceBacking::swapTileGrids() +{ + TileGrid* temp = m_frontTileGrid; + m_frontTileGrid = m_backTileGrid; + m_backTileGrid = temp; +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h new file mode 100644 index 0000000..61e3336 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h @@ -0,0 +1,93 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SurfaceBacking_h +#define SurfaceBacking_h + +#include "SkRefCnt.h" +#include "TileGrid.h" + +namespace WebCore { + +class LayerAndroid; +class TexturesResult; +class TilePainter; + +class SurfaceBacking : public SkRefCnt { +// TODO: investigate webkit threadsafe ref counting +public: + SurfaceBacking(bool isBaseSurface); + ~SurfaceBacking(); + void prepareGL(GLWebViewState* state, bool allowZoom, + const IntRect& prepareArea, const IntRect& unclippedArea, + TilePainter* painter, bool aggressiveRendering); + void swapTiles(); + void drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform, bool aggressiveRendering, + const Color* background); + void markAsDirty(const SkRegion& dirtyArea); + void computeTexturesAmount(TexturesResult* result, LayerAndroid* layer); + void discardTextures() + { + m_frontTileGrid->discardTextures(); + m_backTileGrid->discardTextures(); + } + bool isReady() + { + return !m_zooming && m_frontTileGrid->isReady() && m_scale > 0; + } + + bool isMissingContent() + { + return m_zooming || m_frontTileGrid->isMissingContent(); + } + + int nbTextures(IntRect& area, float scale) + { + // TODO: consider the zooming case for the backTileGrid + if (!m_frontTileGrid) + return 0; + return m_frontTileGrid->nbTextures(area, scale); + } + +private: + void swapTileGrids(); + + // Delay before we schedule a new tile at the new scale factor + static const double s_zoomUpdateDelay = 0.2; // 200 ms + + TileGrid* m_frontTileGrid; + TileGrid* m_backTileGrid; + TileGrid* m_lowResTileGrid; + + float m_scale; + float m_futureScale; + double m_zoomUpdateTime; + bool m_zooming; +}; + +} // namespace WebCore + +#endif // SurfaceBacking_h diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp new file mode 100644 index 0000000..24e196b --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp @@ -0,0 +1,242 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "SurfaceCollection" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "SurfaceCollection.h" + +#include "AndroidLog.h" +#include "BaseLayerAndroid.h" +#include "ClassTracker.h" +#include "GLWebViewState.h" +#include "LayerAndroid.h" +#include "Surface.h" +#include "ScrollableLayerAndroid.h" +#include "TilesManager.h" + +namespace WebCore { + +//////////////////////////////////////////////////////////////////////////////// +// TILED PAINTING / SURFACES // +//////////////////////////////////////////////////////////////////////////////// + +SurfaceCollection::SurfaceCollection(LayerAndroid* layer) + : m_compositedRoot(layer) +{ + // layer must be non-null. + SkSafeRef(m_compositedRoot); + + // calculate draw transforms and z values + SkRect visibleRect = SkRect::MakeLTRB(0, 0, 1, 1); + m_compositedRoot->updateLayerPositions(visibleRect); + // TODO: updateGLPositionsAndScale? + + // allocate surfaces for layers, merging where possible + ALOGV("new tree, allocating surfaces for tree %p", m_baseLayer); + + LayerMergeState layerMergeState(&m_surfaces); + m_compositedRoot->assignSurfaces(&layerMergeState); + + // set the layersurfaces' update count, to be drawn on painted tiles + unsigned int updateCount = TilesManager::instance()->incWebkitContentUpdates(); + for (unsigned int i = 0; i < m_surfaces.size(); i++) + m_surfaces[i]->setUpdateCount(updateCount); + +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("SurfaceCollection"); +#endif +} + +SurfaceCollection::~SurfaceCollection() +{ + SkSafeUnref(m_compositedRoot); + for (unsigned int i = 0; i < m_surfaces.size(); i++) + SkSafeUnref(m_surfaces[i]); + m_surfaces.clear(); + +#ifdef DEBUG_COUNT + ClassTracker::instance()->decrement("SurfaceCollection"); +#endif +} + +void SurfaceCollection::prepareGL(const SkRect& visibleRect) +{ + updateLayerPositions(visibleRect); + bool layerTilesDisabled = m_compositedRoot->state()->layersRenderingMode() + > GLWebViewState::kClippedTextures; + for (unsigned int i = 0; i < m_surfaces.size(); i++) + m_surfaces[i]->prepareGL(layerTilesDisabled); +} + +static inline bool compareSurfaceZ(const Surface* a, const Surface* b) +{ + const LayerAndroid* la = a->getFirstLayer(); + const LayerAndroid* lb = b->getFirstLayer(); + + // swap drawing order if zValue suggests it AND the layers are in the same stacking context + return (la->zValue() > lb->zValue()) && (la->getParent() == lb->getParent()); +} + +bool SurfaceCollection::drawGL(const SkRect& visibleRect) +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->show(); +#endif + + bool needsRedraw = false; + updateLayerPositions(visibleRect); + bool layerTilesDisabled = m_compositedRoot->state()->layersRenderingMode() + > GLWebViewState::kClippedTextures; + + // create a duplicate vector of surfaces, sorted by z value + Vector <Surface*> surfaces; + for (unsigned int i = 0; i < m_surfaces.size(); i++) + surfaces.append(m_surfaces[i]); + std::stable_sort(surfaces.begin()+1, surfaces.end(), compareSurfaceZ); + + // draw the sorted vector + for (unsigned int i = 0; i < m_surfaces.size(); i++) + needsRedraw |= surfaces[i]->drawGL(layerTilesDisabled); + + return needsRedraw; +} + +Color SurfaceCollection::getBackgroundColor() +{ + return static_cast<BaseLayerAndroid*>(m_compositedRoot)->getBackgroundColor(); +} + +void SurfaceCollection::swapTiles() +{ + for (unsigned int i = 0; i < m_surfaces.size(); i++) + m_surfaces[i]->swapTiles(); +} + +bool SurfaceCollection::isReady() +{ + // Override layer readiness check for single surface mode + if (m_compositedRoot->state()->layersRenderingMode() > GLWebViewState::kClippedTextures) { + // TODO: single surface mode should be properly double buffered + return true; + } + + for (unsigned int i = 0; i < m_surfaces.size(); i++) { + if (!m_surfaces[i]->isReady()) { + ALOGV("layer surface %p isn't ready", m_surfaces[i]); + return false; + } + } + return true; +} + +bool SurfaceCollection::isMissingBackgroundContent() +{ + if (!m_compositedRoot) + return true; + + // return true when the first surface is missing content (indicating the + // entire viewport isn't covered) + return m_surfaces[0]->isMissingContent(); +} + +void SurfaceCollection::computeTexturesAmount(TexturesResult* result) +{ + for (unsigned int i = 0; i < m_surfaces.size(); i++) + m_surfaces[i]->computeTexturesAmount(result); +} + +//////////////////////////////////////////////////////////////////////////////// +// RECURSIVE ANIMATION / INVALS / LAYERS // +//////////////////////////////////////////////////////////////////////////////// + +void SurfaceCollection::setIsPainting(SurfaceCollection* drawingSurface) +{ + if (!drawingSurface) + return; + + for (unsigned int i = 0; i < m_surfaces.size(); i++) { + Surface* newSurface = m_surfaces[i]; + if (!newSurface->needsTexture()) + continue; + + for (unsigned int j = 0; j < drawingSurface->m_surfaces.size(); j++) { + Surface* oldSurface = drawingSurface->m_surfaces[j]; + if (newSurface->tryUpdateSurface(oldSurface)) + break; + } + } +} + +void SurfaceCollection::setIsDrawing() +{ + m_compositedRoot->initAnimations(); +} + +void SurfaceCollection::mergeInvalsInto(SurfaceCollection* replacementSurface) +{ + m_compositedRoot->mergeInvalsInto(replacementSurface->m_compositedRoot); +} + +void SurfaceCollection::evaluateAnimations(double currentTime) +{ + m_compositedRoot->evaluateAnimations(currentTime); +} + +bool SurfaceCollection::hasCompositedLayers() +{ + return m_compositedRoot->countChildren(); +} + +bool SurfaceCollection::hasCompositedAnimations() +{ + return m_compositedRoot->hasAnimations(); +} + +void SurfaceCollection::updateScrollableLayer(int layerId, int x, int y) +{ + LayerAndroid* layer = m_compositedRoot->findById(layerId); + if (layer && layer->contentIsScrollable()) + static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y); +} + +void SurfaceCollection::updateLayerPositions(const SkRect& visibleRect) +{ + TransformationMatrix ident; + m_compositedRoot->updateLayerPositions(visibleRect); + FloatRect clip(0, 0, 1e10, 1e10); + m_compositedRoot->updateGLPositionsAndScale( + ident, clip, 1, m_compositedRoot->state()->scale()); + +#ifdef DEBUG + m_compositedRoot->showLayer(0); + ALOGV("We have %d layers, %d textured", + m_compositedRoot->nbLayers(), + m_compositedRoot->nbTexturedLayers()); +#endif +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollection.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h index 921929b..7dfe140 100644 --- a/Source/WebCore/platform/graphics/android/SurfaceCollection.h +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h @@ -26,33 +26,35 @@ #ifndef SurfaceCollection_h #define SurfaceCollection_h -#include "SkRefCnt.h" +#include "Color.h" #include "SkRect.h" -#include "Vector.h" +#include "SkRefCnt.h" + +#include <wtf/Vector.h> class SkCanvas; class SkRegion; namespace WebCore { -class BaseLayerAndroid; class LayerAndroid; -class LayerGroup; +class Surface; class TexturesResult; class SurfaceCollection : public SkRefCnt { // TODO: investigate webkit threadsafe ref counting public: - SurfaceCollection(BaseLayerAndroid* baseLayer); + SurfaceCollection(LayerAndroid* compositedRoot); virtual ~SurfaceCollection(); // Tiled painting methods (executed on groups) - void prepareGL(const SkRect& visibleRect, float scale, double currentTime); - bool drawGL(const SkRect& visibleRect, float scale); + void prepareGL(const SkRect& visibleRect); + bool drawGL(const SkRect& visibleRect); + Color getBackgroundColor(); void swapTiles(); bool isReady(); + bool isMissingBackgroundContent(); void computeTexturesAmount(TexturesResult* result); - void drawCanvas(SkCanvas* canvas, bool drawLayers); // Recursive tree methods (animations, invals, etc) void setIsPainting(SurfaceCollection* drawingSurfaceCollection); @@ -62,14 +64,12 @@ public: bool hasCompositedLayers(); bool hasCompositedAnimations(); - int baseContentWidth(); - int baseContentHeight(); void updateScrollableLayer(int layerId, int x, int y); private: - BaseLayerAndroid* m_baseLayer; + void updateLayerPositions(const SkRect& visibleRect); LayerAndroid* m_compositedRoot; - Vector<LayerGroup*> m_layerGroups; + WTF::Vector<Surface*> m_surfaces; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp index 633651d..52a8e44 100644 --- a/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp @@ -30,16 +30,14 @@ #include "SurfaceCollectionManager.h" #include "AndroidLog.h" -#include "BaseLayerAndroid.h" -#include "LayerGroup.h" +#include "private/hwui/DrawGlInfo.h" #include "TilesManager.h" #include "SurfaceCollection.h" namespace WebCore { -SurfaceCollectionManager::SurfaceCollectionManager(GLWebViewState* state) - : m_state(state) - , m_drawingCollection(0) +SurfaceCollectionManager::SurfaceCollectionManager() + : m_drawingCollection(0) , m_paintingCollection(0) , m_queuedCollection(0) , m_fastSwapMode(false) @@ -60,8 +58,6 @@ void SurfaceCollectionManager::swap() // swap can't be called unless painting just finished ASSERT(m_paintingCollection); - android::Mutex::Autolock lock(m_paintSwapLock); - ALOGV("SWAPPING, D %p, P %p, Q %p", m_drawingCollection, m_paintingCollection, m_queuedCollection); @@ -91,8 +87,6 @@ void SurfaceCollectionManager::swap() // clear all of the content in the three collections held by the collection manager void SurfaceCollectionManager::clearCollections() { - ALOGV("SurfaceCollectionManager %p removing PS from state %p", this, m_state); - SkSafeUnref(m_drawingCollection); m_drawingCollection = 0; SkSafeUnref(m_paintingCollection); @@ -107,15 +101,9 @@ void SurfaceCollectionManager::clearCollections() bool SurfaceCollectionManager::updateWithSurfaceCollection(SurfaceCollection* newCollection, bool brandNew) { - ALOGV("updateWithSurfaceCollection - %p, has children %d, has animations %d", - newCollection, newCollection->hasCompositedLayers(), - newCollection->hasCompositedAnimations()); - // can't have a queued collection unless have a painting collection too ASSERT(m_paintingCollection || !m_queuedCollection); - android::Mutex::Autolock lock(m_paintSwapLock); - if (!newCollection || brandNew) { clearCollections(); if (brandNew) { @@ -125,6 +113,10 @@ bool SurfaceCollectionManager::updateWithSurfaceCollection(SurfaceCollection* ne return false; } + ALOGV("updateWithSurfaceCollection - %p, has children %d, has animations %d", + newCollection, newCollection->hasCompositedLayers(), + newCollection->hasCompositedAnimations()); + if (m_queuedCollection || m_paintingCollection) { // currently painting, so defer this new collection if (m_queuedCollection) { @@ -161,25 +153,25 @@ void SurfaceCollectionManager::updateScrollableLayer(int layerId, int x, int y) m_drawingCollection->updateScrollableLayer(layerId, x, y); } -bool SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, +int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, SkRect& visibleRect, float scale, bool enterFastSwapMode, bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr, - TexturesResult* texturesResultPtr) + TexturesResult* texturesResultPtr, bool shouldDraw) { m_fastSwapMode |= enterFastSwapMode; - ALOGV("drawGL, D %p, P %p, Q %p, fastSwap %d", - m_drawingCollection, m_paintingCollection, m_queuedCollection, m_fastSwapMode); + ALOGV("drawGL, D %p, P %p, Q %p, fastSwap %d shouldDraw %d", + m_drawingCollection, m_paintingCollection, + m_queuedCollection, m_fastSwapMode, shouldDraw); - bool ret = false; bool didCollectionSwap = false; if (m_paintingCollection) { ALOGV("preparing painting collection %p", m_paintingCollection); m_paintingCollection->evaluateAnimations(currentTime); - m_paintingCollection->prepareGL(visibleRect, scale, currentTime); + m_paintingCollection->prepareGL(visibleRect); m_paintingCollection->computeTexturesAmount(texturesResultPtr); if (!TilesManager::instance()->useDoubleBuffering() || m_paintingCollection->isReady()) { @@ -194,10 +186,38 @@ bool SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, } } else if (m_drawingCollection) { ALOGV("preparing drawing collection %p", m_drawingCollection); - m_drawingCollection->prepareGL(visibleRect, scale, currentTime); + m_drawingCollection->prepareGL(visibleRect); m_drawingCollection->computeTexturesAmount(texturesResultPtr); } + // ask for kStatusInvoke while painting, kStatusDraw if we have content to be redrawn next frame + // returning 0 indicates all painting complete, no framework inval needed. + int returnFlags = 0; + + if (m_paintingCollection) + returnFlags |= uirenderer::DrawGlInfo::kStatusInvoke; + + if (!shouldDraw) { + if (didCollectionSwap + || (!m_paintingCollection + && m_drawingCollection + && m_drawingCollection->isReady())) { + // either a swap just occurred, or there is no more work to be done: do a full draw + m_drawingCollection->swapTiles(); + returnFlags |= uirenderer::DrawGlInfo::kStatusDraw; + } else { + // current collection not ready - invoke functor in process mode + // until either drawing or painting collection is ready + returnFlags |= uirenderer::DrawGlInfo::kStatusInvoke; + } + + return returnFlags; + } + + // =========================================================================== + // Don't have a drawing collection, draw white background + Color background = Color::white; + bool drawBackground = true; if (m_drawingCollection) { bool drawingReady = didCollectionSwap || m_drawingCollection->isReady(); @@ -213,60 +233,32 @@ bool SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, m_fastSwapMode = false; } else { // drawing isn't ready, must redraw - ret = true; + returnFlags |= uirenderer::DrawGlInfo::kStatusInvoke; } m_drawingCollection->evaluateAnimations(currentTime); + ALOGV("drawing collection %p", m_drawingCollection); - ret |= m_drawingCollection->drawGL(visibleRect, scale); - } else { - // Dont have a drawing collection, draw white background - Color defaultBackground = Color::white; - m_state->drawBackground(defaultBackground); + background = m_drawingCollection->getBackgroundColor(); + drawBackground = m_drawingCollection->isMissingBackgroundContent(); + } else if (m_paintingCollection) { + // Use paintingCollection background color while tiles are not done painting. + background = m_paintingCollection->getBackgroundColor(); } - if (m_paintingCollection) { - ALOGV("still have painting collection %p", m_paintingCollection); - return true; + // Start doing the actual GL drawing. + if (drawBackground) { + ALOGV("background is %x", background.rgb()); + // If background is opaque, we can safely and efficiently clear it here. + // Otherwise, we have to calculate all the missing tiles and blend the background. + GLUtils::clearBackgroundIfOpaque(&background); } - return ret; -} - -// draw for base tile - called on TextureGeneration thread -void SurfaceCollectionManager::drawCanvas(SkCanvas* canvas, bool drawLayers) -{ - SurfaceCollection* paintingCollection = 0; - m_paintSwapLock.lock(); - paintingCollection = m_paintingCollection ? m_paintingCollection : m_drawingCollection; - SkSafeRef(paintingCollection); - m_paintSwapLock.unlock(); - - if (!paintingCollection) - return; - - paintingCollection->drawCanvas(canvas, drawLayers); + if (m_drawingCollection && m_drawingCollection->drawGL(visibleRect)) + returnFlags |= uirenderer::DrawGlInfo::kStatusDraw; - SkSafeUnref(paintingCollection); -} - -// TODO: refactor this functionality elsewhere -int SurfaceCollectionManager::baseContentWidth() -{ - if (m_paintingCollection) - return m_paintingCollection->baseContentWidth(); - else if (m_drawingCollection) - return m_drawingCollection->baseContentWidth(); - return 0; -} - -int SurfaceCollectionManager::baseContentHeight() -{ - if (m_paintingCollection) - return m_paintingCollection->baseContentHeight(); - else if (m_drawingCollection) - return m_drawingCollection->baseContentHeight(); - return 0; + ALOGV("returnFlags %d, m_paintingCollection %d ", returnFlags, m_paintingCollection); + return returnFlags; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.h index 76e5e9e..125bf02 100644 --- a/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.h +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.h @@ -41,7 +41,7 @@ class SurfaceCollection; class TEST_EXPORT SurfaceCollectionManager { public: - SurfaceCollectionManager(GLWebViewState* state); + SurfaceCollectionManager(); ~SurfaceCollectionManager(); @@ -49,24 +49,15 @@ public: void updateScrollableLayer(int layerId, int x, int y); - bool drawGL(double currentTime, IntRect& viewRect, + int drawGL(double currentTime, IntRect& viewRect, SkRect& visibleRect, float scale, bool enterFastSwapMode, bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr, - TexturesResult* texturesResultPtr); - - void drawCanvas(SkCanvas* canvas, bool drawLayers); - - int baseContentWidth(); - int baseContentHeight(); + TexturesResult* texturesResultPtr, bool shouldDraw); private: void swap(); void clearCollections(); - android::Mutex m_paintSwapLock; - - GLWebViewState* m_state; - SurfaceCollection* m_drawingCollection; SurfaceCollection* m_paintingCollection; SurfaceCollection* m_queuedCollection; diff --git a/Source/WebCore/platform/graphics/android/TextureInfo.cpp b/Source/WebCore/platform/graphics/android/rendering/TextureInfo.cpp index f5c8b02..f5c8b02 100644 --- a/Source/WebCore/platform/graphics/android/TextureInfo.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TextureInfo.cpp diff --git a/Source/WebCore/platform/graphics/android/TextureInfo.h b/Source/WebCore/platform/graphics/android/rendering/TextureInfo.h index 4684df2..7d182c3 100644 --- a/Source/WebCore/platform/graphics/android/TextureInfo.h +++ b/Source/WebCore/platform/graphics/android/rendering/TextureInfo.h @@ -31,7 +31,6 @@ #include <jni.h> #include <ui/GraphicBuffer.h> #include <utils/RefBase.h> -#include "BaseTile.h" using android::sp; namespace android { diff --git a/Source/WebCore/platform/graphics/android/TextureOwner.h b/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h index 5434dbf..b12d8b7 100644 --- a/Source/WebCore/platform/graphics/android/TextureOwner.h +++ b/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h @@ -31,17 +31,13 @@ class Layer; namespace WebCore { -class TiledPage; -class BaseTileTexture; +class TileTexture; class GLWebViewState; class TextureOwner { public: virtual ~TextureOwner() { } - virtual bool removeTexture(BaseTileTexture* texture) = 0; - virtual TiledPage* page() = 0; - virtual GLWebViewState* state() = 0; - virtual bool samePageAs(Layer* root) { return false; } + virtual bool removeTexture(TileTexture* texture) = 0; virtual bool isRepaintPending() = 0; virtual unsigned long long drawCount() = 0; }; diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp index 81a404f..f884e52 100644 --- a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp @@ -35,6 +35,7 @@ #include "GLUtils.h" #include "PaintTileOperation.h" #include "TilesManager.h" +#include "TransferQueue.h" namespace WebCore { @@ -47,21 +48,6 @@ void TexturesGenerator::scheduleOperation(QueuedOperation* operation) mRequestedOperationsCond.signal(); } -void TexturesGenerator::removeOperationsForPage(TiledPage* page) -{ - removeOperationsForFilter(new PageFilter(page)); -} - -void TexturesGenerator::removePaintOperationsForPage(TiledPage* page, bool waitForRunning) -{ - removeOperationsForFilter(new PageFilter(page), waitForRunning); -} - -void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) -{ - removeOperationsForFilter(filter, true); -} - void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool waitForRunning) { if (!filter) @@ -91,7 +77,7 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool // The solution is use this as a flag to tell Tex Gen thread that // UI thread is waiting now, Tex Gen thread should not wait for the // queue any more. - TilesManager::instance()->transferQueue()->interruptTransferQueue(true); + m_tilesManager->transferQueue()->interruptTransferQueue(true); } delete filter; @@ -109,7 +95,6 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool status_t TexturesGenerator::readyToRun() { - TilesManager::instance()->markGeneratorAsReady(); ALOGV("Thread ready to run"); return NO_ERROR; } @@ -180,7 +165,7 @@ bool TexturesGenerator::threadLoop() stop = true; if (m_waitForCompletion) { m_waitForCompletion = false; - TilesManager::instance()->transferQueue()->interruptTransferQueue(false); + m_tilesManager->transferQueue()->interruptTransferQueue(false); mRequestedOperationsCond.signal(); } mRequestedOperationsLock.unlock(); diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.h b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h index 2e3b6b4..08f69ae 100644 --- a/Source/WebCore/platform/graphics/android/TexturesGenerator.h +++ b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h @@ -29,40 +29,39 @@ #if USE(ACCELERATED_COMPOSITING) #include "QueuedOperation.h" -#include "TiledPage.h" #include "TilePainter.h" +#include <wtf/Vector.h> + #include <utils/threads.h> namespace WebCore { using namespace android; -class BaseLayerAndroid; -class LayerAndroid; +class TilesManager; class TexturesGenerator : public Thread { public: - TexturesGenerator() : Thread(false) + TexturesGenerator(TilesManager* instance) : Thread(false) , m_waitForCompletion(false) - , m_currentOperation(0) { } + , m_currentOperation(0) + , m_tilesManager(instance) { } virtual ~TexturesGenerator() { } virtual status_t readyToRun(); - void removeOperationsForPage(TiledPage* page); - void removePaintOperationsForPage(TiledPage* page, bool waitForRunning); - void removeOperationsForFilter(OperationFilter* filter); - void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning); + void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning = true); void scheduleOperation(QueuedOperation* operation); private: QueuedOperation* popNext(); virtual bool threadLoop(); - Vector<QueuedOperation*> mRequestedOperations; + WTF::Vector<QueuedOperation*> mRequestedOperations; android::Mutex mRequestedOperationsLock; android::Condition mRequestedOperationsCond; bool m_waitForCompletion; QueuedOperation* m_currentOperation; + TilesManager* m_tilesManager; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/rendering/Tile.cpp index d15feeb..f2aa9a0 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/Tile.cpp @@ -23,11 +23,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define LOG_TAG "BaseTile" +#define LOG_TAG "Tile" #define LOG_NDEBUG 1 #include "config.h" -#include "BaseTile.h" +#include "Tile.h" #if USE(ACCELERATED_COMPOSITING) @@ -35,6 +35,7 @@ #include "GLUtils.h" #include "RasterRenderer.h" #include "TextureInfo.h" +#include "TileTexture.h" #include "TilesManager.h" // If the dirty portion of a tile exceeds this ratio, fully repaint. @@ -46,29 +47,26 @@ namespace WebCore { -BaseTile::BaseTile(bool isLayerTile) - : m_glWebViewState(0) - , m_x(-1) +Tile::Tile(bool isLayerTile) + : m_x(-1) , m_y(-1) - , m_page(0) , m_frontTexture(0) , m_backTexture(0) , m_scale(1) , m_dirty(true) , m_repaintPending(false) , m_fullRepaint(true) - , m_isTexturePainted(false) , m_isLayerTile(isLayerTile) , m_drawCount(0) , m_state(Unpainted) { #ifdef DEBUG_COUNT - ClassTracker::instance()->increment("BaseTile"); + ClassTracker::instance()->increment("Tile"); #endif m_renderer = BaseRenderer::createRenderer(); } -BaseTile::~BaseTile() +Tile::~Tile() { if (m_backTexture) m_backTexture->release(this); @@ -78,13 +76,13 @@ BaseTile::~BaseTile() delete m_renderer; #ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("BaseTile"); + ClassTracker::instance()->decrement("Tile"); #endif } // All the following functions must be called from the main GL thread. -void BaseTile::setContents(int x, int y, float scale) +void Tile::setContents(int x, int y, float scale, bool isExpandedPrefetchTile) { // TODO: investigate whether below check/discard is necessary if ((m_x != x) @@ -99,11 +97,13 @@ void BaseTile::setContents(int x, int y, float scale) m_y = y; m_scale = scale; m_drawCount = TilesManager::instance()->getDrawGLCount(); + if (isExpandedPrefetchTile) + m_drawCount--; // deprioritize expanded painting region } -void BaseTile::reserveTexture() +void Tile::reserveTexture() { - BaseTileTexture* texture = TilesManager::instance()->getAvailableTexture(this); + TileTexture* texture = TilesManager::instance()->getAvailableTexture(this); android::AutoMutex lock(m_atomicSync); if (texture && m_backTexture != texture) { @@ -120,10 +120,10 @@ void BaseTile::reserveTexture() } } -bool BaseTile::removeTexture(BaseTileTexture* texture) +bool Tile::removeTexture(TileTexture* texture) { - ALOGV("%p removeTexture %p, back %p front %p... page %p", - this, texture, m_backTexture, m_frontTexture, m_page); + ALOGV("%p removeTexture %p, back %p front %p", + this, texture, m_backTexture, m_frontTexture); // We update atomically, so paintBitmap() can see the correct value android::AutoMutex lock(m_atomicSync); if (m_frontTexture == texture) { @@ -146,7 +146,7 @@ bool BaseTile::removeTexture(BaseTileTexture* texture) return true; } -void BaseTile::markAsDirty(const SkRegion& dirtyArea) +void Tile::markAsDirty(const SkRegion& dirtyArea) { if (dirtyArea.isEmpty()) return; @@ -156,17 +156,11 @@ void BaseTile::markAsDirty(const SkRegion& dirtyArea) // Check if we actually intersect with the area bool intersect = false; SkRegion::Iterator cliperator(dirtyArea); - int tileWidth = TilesManager::instance()->tileWidth(); - int tileHeight = TilesManager::instance()->tileHeight(); - if (m_isLayerTile) { - tileWidth = TilesManager::instance()->layerTileWidth(); - tileHeight = TilesManager::instance()->layerTileHeight(); - } SkRect realTileRect; SkRect dirtyRect; while (!cliperator.done()) { dirtyRect.set(cliperator.rect()); - if (intersectWithRect(m_x, m_y, tileWidth, tileHeight, + if (intersectWithRect(m_x, m_y, TilesManager::tileWidth(), TilesManager::tileHeight(), m_scale, dirtyRect, realTileRect)) { intersect = true; break; @@ -186,8 +180,8 @@ void BaseTile::markAsDirty(const SkRegion& dirtyArea) } else if (m_state != Unpainted) { // TODO: fix it so that they can paint while deferring the markAsDirty // call (or block updates) - ALOGV("Warning: tried to mark tile %p at %d, %d islayertile %d as dirty, state %d, page %p", - this, m_x, m_y, isLayerTile(), m_state, m_page); + ALOGV("Warning: tried to mark tile %p at %d, %d islayertile %d as dirty, state %d", + this, m_x, m_y, isLayerTile(), m_state); // prefetch tiles can be marked dirty while in the process of painting, // due to not using an update lock. force them to fail validate step. @@ -195,51 +189,46 @@ void BaseTile::markAsDirty(const SkRegion& dirtyArea) } } -bool BaseTile::isDirty() +bool Tile::isDirty() { android::AutoMutex lock(m_atomicSync); return m_dirty; } -bool BaseTile::isRepaintPending() +bool Tile::isRepaintPending() { android::AutoMutex lock(m_atomicSync); return m_repaintPending; } -void BaseTile::setRepaintPending(bool pending) +void Tile::setRepaintPending(bool pending) { android::AutoMutex lock(m_atomicSync); m_repaintPending = pending; } -void BaseTile::drawGL(float opacity, const SkRect& rect, float scale, - const TransformationMatrix* transform) +bool Tile::drawGL(float opacity, const SkRect& rect, float scale, + const TransformationMatrix* transform, + bool forceBlending, bool usePointSampling) { if (m_x < 0 || m_y < 0 || m_scale != scale) - return; + return false; // No need to mutex protect reads of m_backTexture as it is only written to by // the consumer thread. if (!m_frontTexture) - return; - - // Early return if set to un-usable in purpose! - m_atomicSync.lock(); - bool isTexturePainted = m_isTexturePainted; - m_atomicSync.unlock(); - - if (!isTexturePainted) - return; + return false; - m_frontTexture->drawGL(isLayerTile(), rect, opacity, transform); + m_frontTexture->drawGL(isLayerTile(), rect, opacity, transform, + forceBlending, usePointSampling); + return true; } -bool BaseTile::isTileReady() +bool Tile::isTileReady() { // Return true if the tile's most recently drawn texture is up to date android::AutoMutex lock(m_atomicSync); - BaseTileTexture * texture = (m_state == ReadyToSwap) ? m_backTexture : m_frontTexture; + TileTexture * texture = (m_state == ReadyToSwap) ? m_backTexture : m_frontTexture; if (!texture) return false; @@ -256,9 +245,9 @@ bool BaseTile::isTileReady() return true; } -bool BaseTile::intersectWithRect(int x, int y, int tileWidth, int tileHeight, - float scale, const SkRect& dirtyRect, - SkRect& realTileRect) +bool Tile::intersectWithRect(int x, int y, int tileWidth, int tileHeight, + float scale, const SkRect& dirtyRect, + SkRect& realTileRect) { // compute the rect to corresponds to pixels realTileRect.fLeft = x * tileWidth; @@ -276,7 +265,7 @@ bool BaseTile::intersectWithRect(int x, int y, int tileWidth, int tileHeight, return true; } -bool BaseTile::isTileVisible(const IntRect& viewTileBounds) +bool Tile::isTileVisible(const IntRect& viewTileBounds) { return (m_x >= viewTileBounds.x() && m_x < viewTileBounds.x() + viewTileBounds.width() @@ -285,14 +274,14 @@ bool BaseTile::isTileVisible(const IntRect& viewTileBounds) } // This is called from the texture generation thread -void BaseTile::paintBitmap(TilePainter* painter) +void Tile::paintBitmap(TilePainter* painter) { // We acquire the values below atomically. This ensures that we are reading // values correctly across cores. Further, once we have these values they // can be updated by other threads without consequence. m_atomicSync.lock(); bool dirty = m_dirty; - BaseTileTexture* texture = m_backTexture; + TileTexture* texture = m_backTexture; SkRegion dirtyArea = m_dirtyArea; float scale = m_scale; const int x = m_x; @@ -311,7 +300,7 @@ void BaseTile::paintBitmap(TilePainter* painter) m_atomicSync.unlock(); // at this point we can safely check the ownership (if the texture got - // transferred to another BaseTile under us) + // transferred to another Tile under us) if (texture->owner() != this) { return; } @@ -391,7 +380,6 @@ void BaseTile::paintBitmap(TilePainter* painter) if (!fullRepaint) { renderInfo.invalRect = &totalRect; - renderInfo.measurePerf = false; m_renderer->renderTiledContent(renderInfo); } } @@ -399,15 +387,12 @@ void BaseTile::paintBitmap(TilePainter* painter) // Do a full repaint if needed if (fullRepaint) { renderInfo.invalRect = 0; - renderInfo.measurePerf = TilesManager::instance()->getShowVisualIndicator(); m_renderer->renderTiledContent(renderInfo); } m_atomicSync.lock(); if (texture == m_backTexture) { - m_isTexturePainted = true; - // set the fullrepaint flags m_fullRepaint = false; @@ -437,7 +422,7 @@ void BaseTile::paintBitmap(TilePainter* painter) m_atomicSync.unlock(); } -void BaseTile::discardTextures() { +void Tile::discardTextures() { android::AutoMutex lock(m_atomicSync); ALOGV("%p discarding bt %p, ft %p", this, m_backTexture, m_frontTexture); @@ -456,7 +441,7 @@ void BaseTile::discardTextures() { m_state = Unpainted; } -void BaseTile::discardBackTexture() { +void Tile::discardBackTexture() { android::AutoMutex lock(m_atomicSync); if (m_backTexture) { m_backTexture->release(this); @@ -466,7 +451,7 @@ void BaseTile::discardBackTexture() { m_dirty = true; } -bool BaseTile::swapTexturesIfNeeded() { +bool Tile::swapTexturesIfNeeded() { android::AutoMutex lock(m_atomicSync); if (m_state == ReadyToSwap) { // discard old texture and swap the new one in its place @@ -484,7 +469,7 @@ bool BaseTile::swapTexturesIfNeeded() { return false; } -void BaseTile::backTextureTransfer() { +void Tile::backTextureTransfer() { android::AutoMutex lock(m_atomicSync); if (m_state == PaintingStarted) m_state = TransferredUnvalidated; @@ -497,7 +482,7 @@ void BaseTile::backTextureTransfer() { } } -void BaseTile::backTextureTransferFail() { +void Tile::backTextureTransferFail() { // transfer failed for some reason, mark dirty so it will (repaint and) be // retransferred. android::AutoMutex lock(m_atomicSync); @@ -506,7 +491,7 @@ void BaseTile::backTextureTransferFail() { // whether validatePaint is called before or after, it won't do anything } -void BaseTile::validatePaint() { +void Tile::validatePaint() { // ONLY CALL while m_atomicSync is locked (at the end of paintBitmap()) if (!m_dirty) { @@ -527,11 +512,6 @@ void BaseTile::validatePaint() { // paintBitmap() may have cleared m_dirty) m_dirty = true; } - - if (m_deferredDirty) { - ALOGV("Note: deferred dirty flag set, possibly a missed paint on tile %p", this); - m_deferredDirty = false; - } } else { ALOGV("Note: paint was unsuccessful."); m_state = Unpainted; diff --git a/Source/WebCore/platform/graphics/android/BaseTile.h b/Source/WebCore/platform/graphics/android/rendering/Tile.h index ab16dc9..fa06892 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.h +++ b/Source/WebCore/platform/graphics/android/rendering/Tile.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BaseTile_h -#define BaseTile_h +#ifndef Tile_h +#define Tile_h #if USE(ACCELERATED_COMPOSITING) @@ -39,8 +39,7 @@ namespace WebCore { class TextureInfo; -class TiledPage; -class BaseTileTexture; +class TileTexture; class GLWebViewState; /** @@ -59,7 +58,7 @@ class GLWebViewState; * 5. The tile is destroyed when the user navigates to a new page. * */ -class BaseTile : public TextureOwner { +class Tile : public TextureOwner { public: // eventually, m_dirty might be rolled into the state machine, but note @@ -89,20 +88,21 @@ public: UpToDate = 5, }; - BaseTile(bool isLayerTile = false); - ~BaseTile(); + Tile(bool isLayerTile = false); + ~Tile(); bool isLayerTile() { return m_isLayerTile; } - void setContents(int x, int y, float scale); - void setPage(TiledPage* page) { m_page = page; } + void setContents(int x, int y, float scale, bool isExpandedPrefetchTile); void reserveTexture(); bool isTileReady(); - void drawGL(float opacity, const SkRect& rect, float scale, - const TransformationMatrix* transform); + // Return false when real draw didn't happen for any reason. + bool drawGL(float opacity, const SkRect& rect, float scale, + const TransformationMatrix* transform, + bool forceBlending = false, bool usePointSampling = false); // the only thread-safe function called by the background thread void paintBitmap(TilePainter* painter); @@ -114,15 +114,15 @@ public: void markAsDirty(const SkRegion& dirtyArea); bool isDirty(); - bool isRepaintPending(); + virtual bool isRepaintPending(); void setRepaintPending(bool pending); float scale() const { return m_scale; } TextureState textureState() const { return m_state; } int x() const { return m_x; } int y() const { return m_y; } - BaseTileTexture* frontTexture() { return m_frontTexture; } - BaseTileTexture* backTexture() { return m_backTexture; } + TileTexture* frontTexture() { return m_frontTexture; } + TileTexture* backTexture() { return m_backTexture; } // only used for prioritization - the higher, the more relevant the tile is unsigned long long drawCount() { return m_drawCount; } @@ -132,36 +132,25 @@ public: void backTextureTransfer(); void backTextureTransferFail(); - void setGLWebViewState(GLWebViewState* state) { m_glWebViewState = state; } - // TextureOwner implementation - virtual bool removeTexture(BaseTileTexture* texture); - virtual TiledPage* page() { return m_page; } - virtual GLWebViewState* state() { return m_glWebViewState; } + virtual bool removeTexture(TileTexture* texture); private: void validatePaint(); - GLWebViewState* m_glWebViewState; - int m_x; int m_y; - TiledPage* m_page; - // The remaining variables can be updated throughout the lifetime of the object - BaseTileTexture* m_frontTexture; - BaseTileTexture* m_backTexture; + TileTexture* m_frontTexture; + TileTexture* m_backTexture; float m_scale; // used to signal that the that the tile is out-of-date and needs to be // redrawn in the backTexture bool m_dirty; - // currently only for debugging, to be used for tracking down dropped repaints - bool m_deferredDirty; - // used to signal that a repaint is pending bool m_repaintPending; @@ -169,9 +158,6 @@ private: SkRegion m_dirtyArea; bool m_fullRepaint; - // flag used to know if we have a texture that was painted at least once - bool m_isTexturePainted; - // This mutex serves two purposes. (1) It ensures that certain operations // happen atomically and (2) it makes sure those operations are synchronized // across all threads and cores. @@ -199,4 +185,4 @@ private: } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) -#endif // BaseTile_h +#endif // Tile_h diff --git a/Source/WebCore/platform/graphics/android/rendering/TileGrid.cpp b/Source/WebCore/platform/graphics/android/rendering/TileGrid.cpp new file mode 100644 index 0000000..e3aa2a9 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TileGrid.cpp @@ -0,0 +1,383 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "TileGrid" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "TileGrid.h" + +#include "AndroidLog.h" +#include "DrawQuadData.h" +#include "GLWebViewState.h" +#include "PaintTileOperation.h" +#include "Tile.h" +#include "TilesManager.h" + +#include <wtf/CurrentTime.h> + +#define EXPANDED_BOUNDS_INFLATE 1 +#define EXPANDED_PREFETCH_BOUNDS_Y_INFLATE 1 + +namespace WebCore { + +TileGrid::TileGrid(bool isBaseSurface) + : m_prevTileY(0) + , m_scale(1) + , m_isBaseSurface(isBaseSurface) +{ + m_dirtyRegion.setEmpty(); +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("TileGrid"); +#endif +} + +TileGrid::~TileGrid() +{ +#ifdef DEBUG_COUNT + ClassTracker::instance()->decrement("TileGrid"); +#endif + removeTiles(); +} + +bool TileGrid::isReady() +{ + bool tilesAllReady = true; + bool tilesVisible = false; + for (unsigned int i = 0; i < m_tiles.size(); i++) { + Tile* tile = m_tiles[i]; + if (tile->isTileVisible(m_area)) { + tilesVisible = true; + if (!tile->isTileReady()) { + tilesAllReady = false; + break; + } + } + } + // For now, if no textures are available, consider ourselves as ready + // in order to unblock the zooming process. + // FIXME: have a better system -- maybe keeping the last scale factor + // able to fully render everything + ALOGV("TG %p, ready %d, visible %d, texturesRemain %d", + this, tilesAllReady, tilesVisible, + TilesManager::instance()->layerTexturesRemain()); + + return !TilesManager::instance()->layerTexturesRemain() + || !tilesVisible || tilesAllReady; +} + +bool TileGrid::isMissingContent() +{ + for (unsigned int i = 0; i < m_tiles.size(); i++) + if (m_tiles[i]->isTileVisible(m_area) && !m_tiles[i]->frontTexture()) + return true; + return false; +} + +void TileGrid::swapTiles() +{ + int swaps = 0; + for (unsigned int i = 0; i < m_tiles.size(); i++) + if (m_tiles[i]->swapTexturesIfNeeded()) + swaps++; + ALOGV("TG %p swapping, swaps = %d", this, swaps); +} + +IntRect TileGrid::computeTilesArea(const IntRect& contentArea, float scale) +{ + IntRect computedArea; + IntRect area(contentArea.x() * scale, + contentArea.y() * scale, + ceilf(contentArea.width() * scale), + ceilf(contentArea.height() * scale)); + + ALOGV("TG %p prepare, scale %f, area %d x %d", this, scale, area.width(), area.height()); + + if (area.width() == 0 && area.height() == 0) { + computedArea.setWidth(0); + computedArea.setHeight(0); + return computedArea; + } + + int tileWidth = TilesManager::tileWidth(); + int tileHeight = TilesManager::tileHeight(); + + computedArea.setX(area.x() / tileWidth); + computedArea.setY(area.y() / tileHeight); + float right = (area.x() + area.width()) / (float) tileWidth; + float bottom = (area.y() + area.height()) / (float) tileHeight; + computedArea.setWidth(ceilf(right) - computedArea.x()); + computedArea.setHeight(ceilf(bottom) - computedArea.y()); + return computedArea; +} + +void TileGrid::prepareGL(GLWebViewState* state, float scale, + const IntRect& prepareArea, const IntRect& unclippedArea, + TilePainter* painter, int regionFlags, bool isLowResPrefetch) +{ + // first, how many tiles do we need + m_area = computeTilesArea(prepareArea, scale); + if (m_area.isEmpty()) + return; + + ALOGV("prepare TileGrid %p with scale %.2f, prepareArea " + " %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles", + this, scale, + prepareArea.x(), prepareArea.y(), + prepareArea.width(), prepareArea.height(), + m_area.x(), m_area.y(), + m_area.width(), m_area.height()); + + bool goingDown = m_prevTileY < m_area.y(); + m_prevTileY = m_area.y(); + + TilesManager* tilesManager = TilesManager::instance(); + if (scale != m_scale) + tilesManager->removeOperationsForFilter(new ScaleFilter(painter, m_scale)); + + m_scale = scale; + + // apply dirty region to affected tiles + if (!m_dirtyRegion.isEmpty()) { + for (unsigned int i = 0; i < m_tiles.size(); i++) + m_tiles[i]->markAsDirty(m_dirtyRegion); + + // log inval region for the base surface + if (m_isBaseSurface && tilesManager->getProfiler()->enabled()) { + SkRegion::Iterator iterator(m_dirtyRegion); + while (!iterator.done()) { + SkIRect r = iterator.rect(); + tilesManager->getProfiler()->nextInval(r, scale); + iterator.next(); + } + } + m_dirtyRegion.setEmpty(); + } + + if (regionFlags & StandardRegion) { + for (int i = 0; i < m_area.width(); i++) { + if (goingDown) { + for (int j = 0; j < m_area.height(); j++) + prepareTile(m_area.x() + i, m_area.y() + j, + painter, state, isLowResPrefetch, false); + } else { + for (int j = m_area.height() - 1; j >= 0; j--) + prepareTile(m_area.x() + i, m_area.y() + j, + painter, state, isLowResPrefetch, false); + } + } + } + + if (regionFlags & ExpandedRegion) { + IntRect fullArea = computeTilesArea(unclippedArea, scale); + IntRect expandedArea = m_area; + + // on systems reporting highEndGfx=true and useMinimalMemory not set, use expanded bounds + if (tilesManager->highEndGfx() && !tilesManager->useMinimalMemory()) + expandedArea.inflate(EXPANDED_BOUNDS_INFLATE); + + if (isLowResPrefetch) + expandedArea.inflateY(EXPANDED_PREFETCH_BOUNDS_Y_INFLATE); + + // clip painting area to content + expandedArea.intersect(fullArea); + + for (int i = expandedArea.x(); i < expandedArea.maxX(); i++) + for (int j = expandedArea.y(); j < expandedArea.maxY(); j++) + if (!m_area.contains(i, j)) + prepareTile(i, j, painter, state, isLowResPrefetch, true); + } +} + +void TileGrid::markAsDirty(const SkRegion& invalRegion) +{ + ALOGV("TG %p markAsDirty, current region empty %d, new empty %d", + this, m_dirtyRegion.isEmpty(), invalRegion.isEmpty()); + m_dirtyRegion.op(invalRegion, SkRegion::kUnion_Op); +} + +void TileGrid::prepareTile(int x, int y, TilePainter* painter, + GLWebViewState* state, bool isLowResPrefetch, bool isExpandPrefetch) +{ + Tile* tile = getTile(x, y); + if (!tile) { + bool isLayerTile = !m_isBaseSurface; + tile = new Tile(isLayerTile); + m_tiles.append(tile); + } + + ALOGV("preparing tile %p at %d, %d, painter is %p", tile, x, y, painter); + + tile->setContents(x, y, m_scale, isExpandPrefetch); + + // TODO: move below (which is largely the same for layers / tiled page) into + // prepareGL() function + + if (tile->isDirty() || !tile->frontTexture()) + tile->reserveTexture(); + + if (tile->backTexture() && tile->isDirty() && !tile->isRepaintPending()) { + ALOGV("painting TG %p's tile %d %d for LG %p", this, x, y, painter); + PaintTileOperation *operation = new PaintTileOperation(tile, painter, + state, isLowResPrefetch); + TilesManager::instance()->scheduleOperation(operation); + } +} + +Tile* TileGrid::getTile(int x, int y) +{ + for (unsigned int i = 0; i <m_tiles.size(); i++) { + Tile* tile = m_tiles[i]; + if (tile->x() == x && tile->y() == y) + return tile; + } + return 0; +} + +int TileGrid::nbTextures(IntRect& area, float scale) +{ + IntRect tileBounds = computeTilesArea(area, scale); + int numberTextures = tileBounds.width() * tileBounds.height(); + + // add the number of dirty tiles in the bounds, as they take up double + // textures for double buffering + for (unsigned int i = 0; i <m_tiles.size(); i++) { + Tile* tile = m_tiles[i]; + if (tile->isDirty() + && tile->x() >= tileBounds.x() && tile->x() <= tileBounds.maxX() + && tile->y() >= tileBounds.y() && tile->y() <= tileBounds.maxY()) + numberTextures++; + } + return numberTextures; +} + +void TileGrid::drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform, + const Color* background) +{ + m_area = computeTilesArea(visibleArea, m_scale); + if (m_area.width() == 0 || m_area.height() == 0) + return; + + float invScale = 1.0 / m_scale; + const float tileWidth = TilesManager::tileWidth() * invScale; + const float tileHeight = TilesManager::tileHeight() * invScale; + + int drawn = 0; + + SkRegion missingRegion; + bool semiOpaqueBaseSurface = + background ? (background->hasAlpha() && background->alpha() > 0) : false; + if (semiOpaqueBaseSurface) { + SkIRect totalArea = SkIRect::MakeXYWH(m_area.x(), m_area.y(), + m_area.width(), m_area.height()); + missingRegion = SkRegion(totalArea); + } + + bool usePointSampling = + TilesManager::instance()->shader()->usePointSampling(m_scale, transform); + + for (unsigned int i = 0; i < m_tiles.size(); i++) { + Tile* tile = m_tiles[i]; + + bool tileInView = tile->isTileVisible(m_area); + if (tileInView) { + SkRect rect; + rect.fLeft = tile->x() * tileWidth; + rect.fTop = tile->y() * tileHeight; + rect.fRight = rect.fLeft + tileWidth; + rect.fBottom = rect.fTop + tileHeight; + ALOGV("tile %p (layer tile: %d) %d,%d at scale %.2f vs %.2f [ready: %d] dirty: %d", + tile, tile->isLayerTile(), tile->x(), tile->y(), + tile->scale(), m_scale, tile->isTileReady(), tile->isDirty()); + + bool forceBaseBlending = background ? background->hasAlpha() : false; + bool success = tile->drawGL(opacity, rect, m_scale, transform, + forceBaseBlending, usePointSampling); + if (semiOpaqueBaseSurface && success) { + // Cut the successful drawn tile area from the missing region. + missingRegion.op(SkIRect::MakeXYWH(tile->x(), tile->y(), 1, 1), + SkRegion::kDifference_Op); + } + if (tile->frontTexture()) + drawn++; + } + + // log tile information for base, high res tiles + if (m_isBaseSurface && background) + TilesManager::instance()->getProfiler()->nextTile(tile, invScale, tileInView); + } + + // Draw missing Regions with blend turned on + if (semiOpaqueBaseSurface) + drawMissingRegion(missingRegion, opacity, background); + + ALOGV("TG %p drew %d tiles, scale %f", + this, drawn, m_scale); +} + +void TileGrid::drawMissingRegion(const SkRegion& region, float opacity, + const Color* background) +{ + SkRegion::Iterator iterator(region); + const float tileWidth = TilesManager::tileWidth() / m_scale; + const float tileHeight = TilesManager::tileHeight() / m_scale; + while (!iterator.done()) { + SkIRect r = iterator.rect(); + SkRect rect; + rect.fLeft = r.x() * tileWidth; + rect.fTop = r.y() * tileHeight; + rect.fRight = rect.fLeft + tileWidth * r.width(); + rect.fBottom = rect.fTop + tileHeight * r.height(); + ALOGV("draw tile x y, %d %d (%d %d) opacity %f", r.x(), r.y(), + r.width(), r.height(), opacity); + // Skia is using pre-multiplied color. + Color postAlpha = Color(background->red() * background->alpha() / 255, + background->green() * background->alpha() / 255, + background->blue() * background->alpha() / 255, + background->alpha() ); + + PureColorQuadData backGroundData(postAlpha, BaseQuad, 0, &rect, opacity); + TilesManager::instance()->shader()->drawQuad(&backGroundData); + iterator.next(); + } +} + +void TileGrid::removeTiles() +{ + for (unsigned int i = 0; i < m_tiles.size(); i++) { + delete m_tiles[i]; + } + m_tiles.clear(); +} + +void TileGrid::discardTextures() +{ + ALOGV("TG %p discarding textures", this); + for (unsigned int i = 0; i < m_tiles.size(); i++) + m_tiles[i]->discardTextures(); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/TileGrid.h b/Source/WebCore/platform/graphics/android/rendering/TileGrid.h new file mode 100644 index 0000000..2483e0e --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TileGrid.h @@ -0,0 +1,89 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TileGrid_h +#define TileGrid_h + +#include "IntRect.h" +#include "SkRegion.h" + +#include <wtf/Vector.h> + +namespace WebCore { + +class Color; +class GLWebViewState; +class Tile; +class TilePainter; +class TransformationMatrix; + +class TileGrid { +public: + enum PrepareRegionFlags { EmptyRegion = 0x0, StandardRegion = 0x1, ExpandedRegion = 0x2 }; + + TileGrid(bool isBaseSurface); + virtual ~TileGrid(); + + static IntRect computeTilesArea(const IntRect& contentArea, float scale); + + void prepareGL(GLWebViewState* state, float scale, + const IntRect& prepareArea, const IntRect& unclippedArea, + TilePainter* painter, int regionFlags = StandardRegion, + bool isLowResPrefetch = false); + void swapTiles(); + void drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform, const Color* background = 0); + + void prepareTile(int x, int y, TilePainter* painter, + GLWebViewState* state, bool isLowResPrefetch, bool isExpandPrefetch); + void markAsDirty(const SkRegion& dirtyArea); + + Tile* getTile(int x, int y); + + void removeTiles(); + void discardTextures(); + + bool isReady(); + bool isMissingContent(); + + int nbTextures(IntRect& area, float scale); + +private: + void drawMissingRegion(const SkRegion& region, float opacity, const Color* tileBackground); + WTF::Vector<Tile*> m_tiles; + + IntRect m_area; + + SkRegion m_dirtyRegion; + + int m_prevTileY; + float m_scale; + + bool m_isBaseSurface; +}; + +} // namespace WebCore + +#endif // TileGrid_h diff --git a/Source/WebCore/platform/graphics/android/TilePainter.h b/Source/WebCore/platform/graphics/android/rendering/TilePainter.h index 34e877e..53dfadc 100644 --- a/Source/WebCore/platform/graphics/android/TilePainter.h +++ b/Source/WebCore/platform/graphics/android/rendering/TilePainter.h @@ -33,16 +33,17 @@ class SkCanvas; namespace WebCore { -class BaseTile; +class Color; class TilePainter : public SkRefCnt { // TODO: investigate webkit threadsafe ref counting public: virtual ~TilePainter() { } - virtual bool paint(BaseTile* tile, SkCanvas* canvas) = 0; + virtual bool paint(SkCanvas* canvas) = 0; virtual float opacity() { return 1.0; } enum SurfaceType { Painted, Image }; virtual SurfaceType type() { return Painted; } + virtual Color* background() { return 0; } unsigned int getUpdateCount() { return m_updateCount; } void setUpdateCount(unsigned int updateCount) { m_updateCount = updateCount; } diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp b/Source/WebCore/platform/graphics/android/rendering/TileTexture.cpp index ec1fac2..3dceda9 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TileTexture.cpp @@ -23,21 +23,24 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define LOG_TAG "BaseTileTexture" +#define LOG_TAG "TileTexture" #define LOG_NDEBUG 1 #include "config.h" -#include "BaseTileTexture.h" +#include "TileTexture.h" #include "AndroidLog.h" -#include "BaseTile.h" +#include "Tile.h" #include "ClassTracker.h" +#include "DrawQuadData.h" #include "GLUtils.h" +#include "GLWebViewState.h" +#include "TextureOwner.h" #include "TilesManager.h" namespace WebCore { -BaseTileTexture::BaseTileTexture(uint32_t w, uint32_t h) +TileTexture::TileTexture(uint32_t w, uint32_t h) : m_owner(0) , m_isPureColor(false) { @@ -45,24 +48,24 @@ BaseTileTexture::BaseTileTexture(uint32_t w, uint32_t h) m_ownTextureId = 0; #ifdef DEBUG_COUNT - ClassTracker::instance()->increment("BaseTileTexture"); + ClassTracker::instance()->increment("TileTexture"); #endif } -BaseTileTexture::~BaseTileTexture() +TileTexture::~TileTexture() { #ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("BaseTileTexture"); + ClassTracker::instance()->decrement("TileTexture"); #endif } -void BaseTileTexture::requireGLTexture() +void TileTexture::requireGLTexture() { if (!m_ownTextureId) - m_ownTextureId = GLUtils::createBaseTileGLTexture(m_size.width(), m_size.height()); + m_ownTextureId = GLUtils::createTileGLTexture(m_size.width(), m_size.height()); } -void BaseTileTexture::discardGLTexture() +void TileTexture::discardGLTexture() { if (m_ownTextureId) GLUtils::deleteTexture(&m_ownTextureId); @@ -74,15 +77,15 @@ void BaseTileTexture::discardGLTexture() } } -bool BaseTileTexture::acquire(TextureOwner* owner, bool force) +bool TileTexture::acquire(TextureOwner* owner) { if (m_owner == owner) return true; - return setOwner(owner, force); + return setOwner(owner); } -bool BaseTileTexture::setOwner(TextureOwner* owner, bool force) +bool TileTexture::setOwner(TextureOwner* owner) { bool proceed = true; if (m_owner && m_owner != owner) @@ -96,7 +99,7 @@ bool BaseTileTexture::setOwner(TextureOwner* owner, bool force) return false; } -bool BaseTileTexture::release(TextureOwner* owner) +bool TileTexture::release(TextureOwner* owner) { ALOGV("texture %p releasing tile %p, m_owner %p", this, owner, m_owner); if (m_owner != owner) @@ -106,32 +109,39 @@ bool BaseTileTexture::release(TextureOwner* owner) return true; } -void BaseTileTexture::transferComplete() +void TileTexture::transferComplete() { if (m_owner) { - BaseTile* owner = static_cast<BaseTile*>(m_owner); + Tile* owner = static_cast<Tile*>(m_owner); owner->backTextureTransfer(); } else ALOGE("ERROR: owner missing after transfer of texture %p", this); } -void BaseTileTexture::drawGL(bool isLayer, const SkRect& rect, float opacity, - const TransformationMatrix* transform) +void TileTexture::drawGL(bool isLayer, const SkRect& rect, float opacity, + const TransformationMatrix* transform, + bool forceBlending, bool usePointSampling) { ShaderProgram* shader = TilesManager::instance()->shader(); - if (isLayer && transform) { - if (isPureColor()) { - shader->drawLayerQuad(*transform, rect, 0, opacity, - true, GL_TEXTURE_2D, pureColor()); - } else { - shader->drawLayerQuad(*transform, rect, m_ownTextureId, - opacity, true); - } + + if (isLayer && !transform) { + ALOGE("ERROR: Missing tranform for layers!"); + return; + } + + // For base layer, we just follow the forceBlending, otherwise, blending is + // always turned on. + // TODO: Don't blend tiles if they are fully opaque. + bool useBlending = forceBlending || isLayer; + DrawQuadData commonData(isLayer ? LayerQuad : BaseQuad, transform, &rect, + opacity, useBlending); + if (isPureColor()) { + PureColorQuadData data(commonData, pureColor()); + shader->drawQuad(&data); } else { - if (isPureColor()) - shader->drawQuad(rect, 0, opacity, pureColor()); - else - shader->drawQuad(rect, m_ownTextureId, opacity); + GLint filter = usePointSampling ? GL_NEAREST : GL_LINEAR; + TextureQuadData data(commonData, m_ownTextureId, GL_TEXTURE_2D, filter); + shader->drawQuad(&data); } } diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.h b/Source/WebCore/platform/graphics/android/rendering/TileTexture.h index 321ca31..a624c1d 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.h +++ b/Source/WebCore/platform/graphics/android/rendering/TileTexture.h @@ -23,45 +23,45 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BaseTileTexture_h -#define BaseTileTexture_h +#ifndef TileTexture_h +#define TileTexture_h -#include "GLWebViewState.h" #include "TextureInfo.h" -#include "TextureOwner.h" -#include "TilePainter.h" +#include "Color.h" +#include "SkBitmap.h" +#include "SkRect.h" +#include "SkSize.h" + #include <GLES2/gl2.h> -#include <SkBitmap.h> class SkCanvas; namespace WebCore { -class BaseTile; +class TextureOwner; +class Tile; +class TransformationMatrix; -class BaseTileTexture { +class TileTexture { public: // This object is to be constructed on the consumer's thread and must have // a width and height greater than 0. - BaseTileTexture(uint32_t w, uint32_t h); - virtual ~BaseTileTexture(); + TileTexture(uint32_t w, uint32_t h); + virtual ~TileTexture(); // allows consumer thread to assign ownership of the texture to the tile. It // returns false if ownership cannot be transferred because the tile is busy - bool acquire(TextureOwner* owner, bool force = false); + bool acquire(TextureOwner* owner); bool release(TextureOwner* owner); // set the texture owner if not busy. Return false if busy, true otherwise. - bool setOwner(TextureOwner* owner, bool force = false); + bool setOwner(TextureOwner* owner); // private member accessor functions TextureOwner* owner() { return m_owner; } // only used by the consumer thread const SkSize& getSize() const { return m_size; } - bool readyFor(BaseTile* baseTile); - float scale(); - // OpenGL ID of backing texture, 0 when not allocated GLuint m_ownTextureId; // these are used for dynamically (de)allocating backing graphics memory @@ -80,13 +80,13 @@ public: Color pureColor() { return m_pureColor; } void drawGL(bool isLayer, const SkRect& rect, float opacity, - const TransformationMatrix* transform); + const TransformationMatrix* transform, bool forceBlending = false, + bool usePointSampling = false); private: TextureInfo m_ownTextureInfo; SkSize m_size; - SkBitmap::Config m_config; - // BaseTile owning the texture, only modified by UI thread + // Tile owning the texture, only modified by UI thread TextureOwner* m_owner; // When the whole tile is single color, skip the transfer queue and draw @@ -97,4 +97,4 @@ private: } // namespace WebCore -#endif // BaseTileTexture_h +#endif // TileTexture_h diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp index 37a7301..f46562a 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp @@ -32,10 +32,14 @@ #if USE(ACCELERATED_COMPOSITING) #include "AndroidLog.h" -#include "BaseTile.h" +#include "GLWebViewState.h" #include "SkCanvas.h" #include "SkDevice.h" #include "SkPaint.h" +#include "Tile.h" +#include "TileTexture.h" +#include "TransferQueue.h" + #include <android/native_window.h> #include <cutils/atomic.h> #include <gui/SurfaceTexture.h> @@ -56,8 +60,6 @@ #define MAX_TEXTURE_ALLOCATION ((6+TILE_PREFETCH_DISTANCE*2)*(5+TILE_PREFETCH_DISTANCE*2)*4) #define TILE_WIDTH 256 #define TILE_HEIGHT 256 -#define LAYER_TILE_WIDTH 256 -#define LAYER_TILE_HEIGHT 256 #define BYTES_PER_PIXEL 4 // 8888 config @@ -86,7 +88,6 @@ TilesManager::TilesManager() , m_generatorReady(false) , m_showVisualIndicator(false) , m_invertedScreen(false) - , m_invertedScreenSwitch(false) , m_useMinimalMemory(true) , m_useDoubleBuffering(true) , m_contentUpdates(0) @@ -101,7 +102,7 @@ TilesManager::TilesManager() m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); - m_pixmapsGenerationThread = new TexturesGenerator(); + m_pixmapsGenerationThread = new TexturesGenerator(this); m_pixmapsGenerationThread->run("TexturesGenerator"); } @@ -111,12 +112,12 @@ void TilesManager::allocateTiles() ALOGV("%d tiles to allocate (%d textures planned)", nbTexturesToAllocate, m_maxTextureCount); int nbTexturesAllocated = 0; for (int i = 0; i < nbTexturesToAllocate; i++) { - BaseTileTexture* texture = new BaseTileTexture( + TileTexture* texture = new TileTexture( tileWidth(), tileHeight()); // the atomic load ensures that the texture has been fully initialized // before we pass a pointer for other threads to operate on - BaseTileTexture* loadedTexture = - reinterpret_cast<BaseTileTexture*>( + TileTexture* loadedTexture = + reinterpret_cast<TileTexture*>( android_atomic_acquire_load(reinterpret_cast<int32_t*>(&texture))); m_textures.append(loadedTexture); nbTexturesAllocated++; @@ -127,12 +128,12 @@ void TilesManager::allocateTiles() nbLayersTexturesToAllocate, m_maxLayerTextureCount); int nbLayersTexturesAllocated = 0; for (int i = 0; i < nbLayersTexturesToAllocate; i++) { - BaseTileTexture* texture = new BaseTileTexture( - layerTileWidth(), layerTileHeight()); + TileTexture* texture = new TileTexture( + tileWidth(), tileHeight()); // the atomic load ensures that the texture has been fully initialized // before we pass a pointer for other threads to operate on - BaseTileTexture* loadedTexture = - reinterpret_cast<BaseTileTexture*>( + TileTexture* loadedTexture = + reinterpret_cast<TileTexture*>( android_atomic_acquire_load(reinterpret_cast<int32_t*>(&texture))); m_tilesTextures.append(loadedTexture); nbLayersTexturesAllocated++; @@ -141,7 +142,7 @@ void TilesManager::allocateTiles() nbTexturesAllocated, m_textures.size(), m_textures.size() * TILE_WIDTH * TILE_HEIGHT * 4 / 1024 / 1024, nbLayersTexturesAllocated, m_tilesTextures.size(), - m_tilesTextures.size() * LAYER_TILE_WIDTH * LAYER_TILE_HEIGHT * 4 / 1024 / 1024); + m_tilesTextures.size() * tileWidth() * tileHeight() * 4 / 1024 / 1024); } void TilesManager::discardTextures(bool allTextures, bool glTextures) @@ -163,7 +164,7 @@ void TilesManager::discardTextures(bool allTextures, bool glTextures) } void TilesManager::discardTexturesVector(unsigned long long sparedDrawCount, - WTF::Vector<BaseTileTexture*>& textures, + WTF::Vector<TileTexture*>& textures, bool deallocateGLTextures) { const unsigned int max = textures.size(); @@ -178,14 +179,14 @@ void TilesManager::discardTexturesVector(unsigned long long sparedDrawCount, discardedIndex.append(i); } else if (owner) { // simply detach textures from owner - static_cast<BaseTile*>(owner)->discardTextures(); + static_cast<Tile*>(owner)->discardTextures(); } dealloc++; } } bool base = textures == m_textures; - // Clean up the vector of BaseTileTextures and reset the max texture count. + // Clean up the vector of TileTextures and reset the max texture count. if (discardedIndex.size()) { android::Mutex::Autolock lock(m_texturesLock); for (int i = discardedIndex.size() - 1; i >= 0; i--) @@ -211,13 +212,13 @@ void TilesManager::gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextur { *nbTextures = m_textures.size(); for (unsigned int i = 0; i < m_textures.size(); i++) { - BaseTileTexture* texture = m_textures[i]; + TileTexture* texture = m_textures[i]; if (texture->m_ownTextureId) *nbAllocatedTextures += 1; } *nbLayerTextures = m_tilesTextures.size(); for (unsigned int i = 0; i < m_tilesTextures.size(); i++) { - BaseTileTexture* texture = m_tilesTextures[i]; + TileTexture* texture = m_tilesTextures[i]; if (texture->m_ownTextureId) *nbAllocatedLayerTextures += 1; } @@ -228,19 +229,18 @@ void TilesManager::printTextures() #ifdef DEBUG ALOGV("++++++"); for (unsigned int i = 0; i < m_textures.size(); i++) { - BaseTileTexture* texture = m_textures[i]; - BaseTile* o = 0; + TileTexture* texture = m_textures[i]; + Tile* o = 0; if (texture->owner()) - o = (BaseTile*) texture->owner(); + o = (Tile*) texture->owner(); int x = -1; int y = -1; if (o) { x = o->x(); y = o->y(); } - ALOGV("[%d] texture %x owner: %x (%d, %d) page: %x scale: %.2f", - i, texture, - o, x, y, o ? o->page() : 0, o ? o->scale() : 0); + ALOGV("[%d] texture %x owner: %x (%d, %d) scale: %.2f", + i, texture, o, x, y, o ? o->scale() : 0); } ALOGV("------"); #endif // DEBUG @@ -250,37 +250,26 @@ void TilesManager::gatherTextures() { android::Mutex::Autolock lock(m_texturesLock); m_availableTextures = m_textures; -} - -void TilesManager::gatherLayerTextures() -{ - android::Mutex::Autolock lock(m_texturesLock); m_availableTilesTextures = m_tilesTextures; m_layerTexturesRemain = true; } -BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) +TileTexture* TilesManager::getAvailableTexture(Tile* owner) { android::Mutex::Autolock lock(m_texturesLock); + WTF::Vector<TileTexture*>* availableTexturePool; + if (owner->isLayerTile()) + availableTexturePool = &m_availableTilesTextures; + else + availableTexturePool = &m_availableTextures; + // Sanity check that the tile does not already own a texture if (owner->backTexture() && owner->backTexture()->owner() == owner) { - ALOGV("same owner (%d, %d), getAvailableBackTexture(%x) => texture %x", - owner->x(), owner->y(), owner, owner->backTexture()); - if (owner->isLayerTile()) - m_availableTilesTextures.remove(m_availableTilesTextures.find(owner->backTexture())); - else - m_availableTextures.remove(m_availableTextures.find(owner->backTexture())); + availableTexturePool->remove(availableTexturePool->find(owner->backTexture())); return owner->backTexture(); } - WTF::Vector<BaseTileTexture*>* availableTexturePool; - if (owner->isLayerTile()) { - availableTexturePool = &m_availableTilesTextures; - } else { - availableTexturePool = &m_availableTextures; - } - // The heuristic for selecting a texture is as follows: // 1. Skip textures currently being painted, they can't be painted while // busy anyway @@ -289,12 +278,12 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) // 4. Otherwise, use the least recently prepared tile, but ignoring tiles // drawn in the last frame to avoid flickering - BaseTileTexture* farthestTexture = 0; + TileTexture* farthestTexture = 0; unsigned long long oldestDrawCount = getDrawGLCount() - 1; const unsigned int max = availableTexturePool->size(); for (unsigned int i = 0; i < max; i++) { - BaseTileTexture* texture = (*availableTexturePool)[i]; - BaseTile* currentOwner = static_cast<BaseTile*>(texture->owner()); + TileTexture* texture = (*availableTexturePool)[i]; + Tile* currentOwner = static_cast<Tile*>(texture->owner()); if (!currentOwner) { // unused texture! take it! farthestTexture = texture; @@ -315,7 +304,7 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) } if (farthestTexture) { - BaseTile* previousOwner = static_cast<BaseTile*>(farthestTexture->owner()); + Tile* previousOwner = static_cast<Tile*>(farthestTexture->owner()); if (farthestTexture->acquire(owner)) { if (previousOwner) { previousOwner->removeTexture(farthestTexture); @@ -420,8 +409,9 @@ void TilesManager::setMaxLayerTextureCount(int max) TransferQueue* TilesManager::transferQueue() { - // To minimize the memory usage, transfer queue can be set to minimal size - // if required. + // m_queue will be created on the UI thread, although it may + // be accessed from the TexturesGenerator. However, that can only happen after + // a previous transferQueue() call due to a prepare. if (!m_queue) m_queue = new TransferQueue(m_useMinimalMemory); return m_queue; @@ -437,24 +427,11 @@ float TilesManager::tileHeight() return TILE_HEIGHT; } -float TilesManager::layerTileWidth() -{ - return LAYER_TILE_WIDTH; -} - -float TilesManager::layerTileHeight() -{ - return LAYER_TILE_HEIGHT; -} - TilesManager* TilesManager::instance() { if (!gInstance) { gInstance = new TilesManager(); ALOGV("instance(), new gInstance is %x", gInstance); - ALOGV("Waiting for the generator..."); - gInstance->waitForGenerator(); - ALOGV("Generator ready!"); } return gInstance; } diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/rendering/TilesManager.h index aafdfb6..92c56d3 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.h +++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.h @@ -28,24 +28,24 @@ #if USE(ACCELERATED_COMPOSITING) -#include "BaseTile.h" -#include "BaseTileTexture.h" -#include "ImageTexture.h" #include "LayerAndroid.h" #include "ShaderProgram.h" -#include "SkBitmapRef.h" #include "TexturesGenerator.h" -#include "TiledPage.h" #include "TilesProfiler.h" -#include "TransferQueue.h" #include "VideoLayerManager.h" #include <utils/threads.h> #include <wtf/HashMap.h> namespace WebCore { +class OperationFilter; +class Tile; +class TileTexture; +class TransferQueue; + class TilesManager { public: + // May only be called from the UI thread static TilesManager* instance(); static GLint getMaxTextureSize(); static int getMaxTextureAllocation(); @@ -60,16 +60,6 @@ public: m_pixmapsGenerationThread->removeOperationsForFilter(filter, waitForRunning); } - void removeOperationsForPage(TiledPage* page) - { - m_pixmapsGenerationThread->removeOperationsForPage(page); - } - - void removePaintOperationsForPage(TiledPage* page, bool waitForCompletion) - { - m_pixmapsGenerationThread->removePaintOperationsForPage(page, waitForCompletion); - } - void scheduleOperation(QueuedOperation* operation) { m_pixmapsGenerationThread->scheduleOperation(operation); @@ -79,27 +69,15 @@ public: TransferQueue* transferQueue(); VideoLayerManager* videoLayerManager() { return &m_videoLayerManager; } - void gatherLayerTextures(); void gatherTextures(); bool layerTexturesRemain() { return m_layerTexturesRemain; } void gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures, int* nbLayerTextures, int* nbAllocatedLayerTextures); - BaseTileTexture* getAvailableTexture(BaseTile* owner); - - void markGeneratorAsReady() - { - { - android::Mutex::Autolock lock(m_generatorLock); - m_generatorReady = true; - } - m_generatorReadyCond.signal(); - } + TileTexture* getAvailableTexture(Tile* owner); void printTextures(); - void resetTextureUsage(TiledPage* page); - // m_highEndGfx is written/read only on UI thread, no need for a lock. void setHighEndGfx(bool highEnd); bool highEndGfx(); @@ -110,8 +88,6 @@ public: void setMaxLayerTextureCount(int max); static float tileWidth(); static float tileHeight(); - static float layerTileWidth(); - static float layerTileHeight(); void allocateTiles(); @@ -138,23 +114,11 @@ public: return m_invertedScreen; } - bool invertedScreenSwitch() - { - return m_invertedScreenSwitch; - } - void setInvertedScreen(bool invert) { - if (m_invertedScreen != invert) - m_invertedScreenSwitch = true; m_invertedScreen = invert; } - void setInvertedScreenSwitch(bool invertedSwitch) - { - m_invertedScreenSwitch = invertedSwitch; - } - void setInvertedScreenContrast(float contrast) { m_shader.setContrast(contrast); @@ -196,22 +160,15 @@ public: private: TilesManager(); - void waitForGenerator() - { - android::Mutex::Autolock lock(m_generatorLock); - while (!m_generatorReady) - m_generatorReadyCond.wait(m_generatorLock); - } - void discardTexturesVector(unsigned long long sparedDrawCount, - WTF::Vector<BaseTileTexture*>& textures, + WTF::Vector<TileTexture*>& textures, bool deallocateGLTextures); - Vector<BaseTileTexture*> m_textures; - Vector<BaseTileTexture*> m_availableTextures; + WTF::Vector<TileTexture*> m_textures; + WTF::Vector<TileTexture*> m_availableTextures; - Vector<BaseTileTexture*> m_tilesTextures; - Vector<BaseTileTexture*> m_availableTilesTextures; + WTF::Vector<TileTexture*> m_tilesTextures; + WTF::Vector<TileTexture*> m_availableTilesTextures; bool m_layerTexturesRemain; bool m_highEndGfx; @@ -222,7 +179,6 @@ private: bool m_showVisualIndicator; bool m_invertedScreen; - bool m_invertedScreenSwitch; bool m_useMinimalMemory; @@ -233,8 +189,6 @@ private: sp<TexturesGenerator> m_pixmapsGenerationThread; android::Mutex m_texturesLock; - android::Mutex m_generatorLock; - android::Condition m_generatorReadyCond; static TilesManager* gInstance; diff --git a/Source/WebCore/platform/graphics/android/TilesProfiler.cpp b/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.cpp index a113514..4f0c6b5 100644 --- a/Source/WebCore/platform/graphics/android/TilesProfiler.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.cpp @@ -32,6 +32,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "AndroidLog.h" +#include "Tile.h" #include "TilesManager.h" #include <wtf/CurrentTime.h> @@ -92,14 +93,14 @@ void TilesProfiler::nextFrame(int left, int top, int right, int bottom, float sc scale, true, (int)(timeDelta * 1000))); } -void TilesProfiler::nextTile(BaseTile& tile, float scale, bool inView) +void TilesProfiler::nextTile(Tile* tile, float scale, bool inView) { if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES) || (m_records.size() == 0)) return; - bool isReady = tile.isTileReady(); - int left = tile.x() * TilesManager::tileWidth(); - int top = tile.y() * TilesManager::tileWidth(); + bool isReady = tile->isTileReady(); + int left = tile->x() * TilesManager::tileWidth(); + int top = tile->y() * TilesManager::tileWidth(); int right = left + TilesManager::tileWidth(); int bottom = top + TilesManager::tileWidth(); @@ -111,20 +112,20 @@ void TilesProfiler::nextTile(BaseTile& tile, float scale, bool inView) } m_records.last().append(TileProfileRecord( left, top, right, bottom, - scale, isReady, (int)tile.drawCount())); + scale, isReady, (int)tile->drawCount())); ALOGV("adding tile %d %d %d %d, scale %f", left, top, right, bottom, scale); } -void TilesProfiler::nextInval(const IntRect& rect, float scale) +void TilesProfiler::nextInval(const SkIRect& rect, float scale) { if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES) || (m_records.size() == 0)) return; m_records.last().append(TileProfileRecord( rect.x(), rect.y(), - rect.maxX(), rect.maxY(), scale, false, INVAL_CODE)); + rect.right(), rect.bottom(), scale, false, INVAL_CODE)); ALOGV("adding inval region %d %d %d %d, scale %f", rect.x(), rect.y(), - rect.maxX(), rect.maxY(), scale); + rect.right(), rect.bottom(), scale); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TilesProfiler.h b/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.h index 286d350..b39ae2f 100644 --- a/Source/WebCore/platform/graphics/android/TilesProfiler.h +++ b/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.h @@ -28,12 +28,14 @@ #if USE(ACCELERATED_COMPOSITING) -#include "BaseTile.h" #include "IntRect.h" -#include "Vector.h" +#include "SkRect.h" +#include <wtf/Vector.h> namespace WebCore { +class Tile; + struct TileProfileRecord { TileProfileRecord(int left, int top, int right, int bottom, float scale, int isReady, int level) { this->left = left; @@ -58,8 +60,8 @@ public: float stop(); void clear(); void nextFrame(int left, int top, int right, int bottom, float scale); - void nextTile(BaseTile& tile, float scale, bool inView); - void nextInval(const IntRect& rect, float scale); + void nextTile(Tile* tile, float scale, bool inView); + void nextInval(const SkIRect& rect, float scale); int numFrames() { return m_records.size(); }; @@ -72,11 +74,13 @@ public: return &m_records[frame][tile]; } + bool enabled() { return m_enabled; } + private: bool m_enabled; unsigned int m_goodTiles; unsigned int m_badTiles; - Vector<Vector<TileProfileRecord> > m_records; + WTF::Vector<WTF::Vector<TileProfileRecord> > m_records; double m_time; }; diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp index ac45112..5ede167 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp @@ -32,8 +32,10 @@ #if USE(ACCELERATED_COMPOSITING) #include "AndroidLog.h" -#include "BaseTile.h" +#include "DrawQuadData.h" #include "GLUtils.h" +#include "Tile.h" +#include "TileTexture.h" #include "TilesManager.h" #include <android/native_window.h> #include <gui/SurfaceTexture.h> @@ -96,12 +98,15 @@ void TransferQueue::initGLResources(int width, int height) android::Mutex::Autolock lock(m_transferQueueItemLocks); if (!m_sharedSurfaceTextureId) { glGenTextures(1, &m_sharedSurfaceTextureId); + sp<BufferQueue> bufferQueue(new BufferQueue(true)); m_sharedSurfaceTexture = #if GPU_UPLOAD_WITHOUT_DRAW new android::SurfaceTexture(m_sharedSurfaceTextureId, true, - GL_TEXTURE_2D, false); + GL_TEXTURE_2D, false, bufferQueue); #else - new android::SurfaceTexture(m_sharedSurfaceTextureId); + new android::SurfaceTexture(m_sharedSurfaceTextureId, true, + GL_TEXTURE_EXTERNAL_OES, true, + bufferQueue); #endif m_ANW = new android::SurfaceTextureClient(m_sharedSurfaceTexture); m_sharedSurfaceTexture->setSynchronousMode(true); @@ -109,7 +114,7 @@ void TransferQueue::initGLResources(int width, int height) int extraBuffersNeeded = 0; m_ANW->query(m_ANW.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &extraBuffersNeeded); - m_sharedSurfaceTexture->setBufferCount(m_transferQueueSize + extraBuffersNeeded); + bufferQueue->setBufferCount(m_transferQueueSize + extraBuffersNeeded); int result = native_window_set_buffers_geometry(m_ANW.get(), width, height, HAL_PIXEL_FORMAT_RGBA_8888); @@ -124,28 +129,28 @@ void TransferQueue::initGLResources(int width, int height) } // When bliting, if the item from the transfer queue is mismatching b/t the -// BaseTile and the content, then the item is considered as obsolete, and +// Tile and the content, then the item is considered as obsolete, and // the content is discarded. bool TransferQueue::checkObsolete(const TileTransferData* data) { - BaseTile* baseTilePtr = data->savedBaseTilePtr; + Tile* baseTilePtr = data->savedTilePtr; if (!baseTilePtr) { - ALOGV("Invalid savedBaseTilePtr , such that the tile is obsolete"); + ALOGV("Invalid savedTilePtr , such that the tile is obsolete"); return true; } - BaseTileTexture* baseTileTexture = baseTilePtr->backTexture(); - if (!baseTileTexture || baseTileTexture != data->savedBaseTileTexturePtr) { + TileTexture* baseTileTexture = baseTilePtr->backTexture(); + if (!baseTileTexture || baseTileTexture != data->savedTileTexturePtr) { ALOGV("Invalid baseTileTexture %p (vs expected %p), such that the tile is obsolete", - baseTileTexture, data->savedBaseTileTexturePtr); + baseTileTexture, data->savedTileTexturePtr); return true; } return false; } -void TransferQueue::blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, - BaseTileTexture* frontTex, +void TransferQueue::blitTileFromQueue(GLuint fboID, TileTexture* destTex, + TileTexture* frontTex, GLuint srcTexId, GLenum srcTexTarget, int index) { @@ -198,14 +203,14 @@ void TransferQueue::blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { ALOGV("Error: glCheckFramebufferStatus failed"); - glBindFramebuffer(GL_FRAMEBUFFER, 0); return; } // Use empty rect to set up the special matrix to draw. SkRect rect = SkRect::MakeEmpty(); - TilesManager::instance()->shader()->drawQuad(rect, srcTexId, 1.0, - srcTexTarget, GL_NEAREST); + + TextureQuadData data(srcTexId, GL_NEAREST, srcTexTarget, Blit, 0, 0, 1.0, false); + TilesManager::instance()->shader()->drawQuad(&data); // To workaround a sync issue on some platforms, we should insert the sync // here while in the current FBO. @@ -327,10 +332,10 @@ void TransferQueue::updatePureColorTiles() for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) { TileTransferData* data = &m_pureColorTileQueue[i]; if (data->status == pendingBlit) { - BaseTileTexture* destTexture = 0; - bool obsoleteBaseTile = checkObsolete(data); - if (!obsoleteBaseTile) { - destTexture = data->savedBaseTilePtr->backTexture(); + TileTexture* destTexture = 0; + bool obsoleteTile = checkObsolete(data); + if (!obsoleteTile) { + destTexture = data->savedTilePtr->backTexture(); destTexture->setPureColor(data->pureColor); destTexture->transferComplete(); } @@ -342,8 +347,8 @@ void TransferQueue::updatePureColorTiles() m_pureColorTileQueue.clear(); } -// Call on UI thread to copy from the shared Surface Texture to the BaseTile's texture. -void TransferQueue::updateDirtyBaseTiles() +// Call on UI thread to copy from the shared Surface Texture to the Tile's texture. +void TransferQueue::updateDirtyTiles() { android::Mutex::Autolock lock(m_transferQueueItemLocks); @@ -355,22 +360,22 @@ void TransferQueue::updateDirtyBaseTiles() updatePureColorTiles(); // Start from the oldest item, we call the updateTexImage to retrive - // the texture and blit that into each BaseTile's texture. + // the texture and blit that into each Tile's texture. const int nextItemIndex = getNextTransferQueueIndex(); int index = nextItemIndex; bool usedFboForUpload = false; for (int k = 0; k < m_transferQueueSize ; k++) { if (m_transferQueue[index].status == pendingBlit) { - bool obsoleteBaseTile = checkObsolete(&m_transferQueue[index]); + bool obsoleteTile = checkObsolete(&m_transferQueue[index]); // Save the needed info, update the Surf Tex, clean up the item in // the queue. Then either move on to next item or copy the content. - BaseTileTexture* destTexture = 0; - BaseTileTexture* frontTexture = 0; - if (!obsoleteBaseTile) { - destTexture = m_transferQueue[index].savedBaseTilePtr->backTexture(); + TileTexture* destTexture = 0; + TileTexture* frontTexture = 0; + if (!obsoleteTile) { + destTexture = m_transferQueue[index].savedTilePtr->backTexture(); // while destTexture is guaranteed to not be null, frontTexture // might be (first transfer) - frontTexture = m_transferQueue[index].savedBaseTilePtr->frontTexture(); + frontTexture = m_transferQueue[index].savedTilePtr->frontTexture(); } if (m_transferQueue[index].uploadType == GpuUpload) { @@ -378,9 +383,9 @@ void TransferQueue::updateDirtyBaseTiles() if (result != OK) ALOGE("unexpected error: updateTexImage return %d", result); } - m_transferQueue[index].savedBaseTilePtr = 0; + m_transferQueue[index].savedTilePtr = 0; m_transferQueue[index].status = emptyItem; - if (obsoleteBaseTile) { + if (obsoleteTile) { ALOGV("Warning: the texture is obsolete for this baseTile"); index = (index + 1) % m_transferQueueSize; continue; @@ -409,7 +414,7 @@ void TransferQueue::updateDirtyBaseTiles() destTexture->transferComplete(); ALOGV("Blit tile x, y %d %d with dest texture %p to destTexture->m_ownTextureId %d", - m_transferQueue[index].savedBaseTilePtr, + m_transferQueue[index].savedTilePtr, destTexture, destTexture->m_ownTextureId); } @@ -420,9 +425,8 @@ void TransferQueue::updateDirtyBaseTiles() // dynamic switch possible. Moving this out from the loop can save some // milli-seconds. if (usedFboForUpload) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the standard FBO restoreGLState(); - GLUtils::checkGlError("updateDirtyBaseTiles"); + GLUtils::checkGlError("updateDirtyTiles"); } m_emptyItemCount = m_transferQueueSize; @@ -435,7 +439,7 @@ void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo, if (!tryUpdateQueueWithBitmap(renderInfo, bitmap)) { // failed placing bitmap in queue, discard tile's texture so it will be // re-enqueued (and repainted) - BaseTile* tile = renderInfo->baseTile; + Tile* tile = renderInfo->baseTile; if (tile) tile->backTextureTransferFail(); } @@ -463,33 +467,8 @@ bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, return false; } - ANativeWindow_Buffer buffer; - if (ANativeWindow_lock(m_ANW.get(), &buffer, 0)) + if (!GLUtils::updateSharedSurfaceTextureWithBitmap(m_ANW.get(), bitmap)) return false; - - uint8_t* img = (uint8_t*)buffer.bits; - int row; - int bpp = 4; // Now we only deal with RGBA8888 format. - int width = TilesManager::instance()->tileWidth(); - int height = TilesManager::instance()->tileHeight(); - if (bitmap.width() == width && bitmap.height() == height) { - bitmap.lockPixels(); - uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels()); - - if (buffer.stride != bitmap.width()) - // Copied line by line since we need to handle the offsets and stride. - for (row = 0 ; row < bitmap.height(); row ++) { - uint8_t* dst = &(img[buffer.stride * row * bpp]); - uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]); - memcpy(dst, src, bpp * bitmap.width()); - } - else - memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height()); - - bitmap.unlockPixels(); - } - - ANativeWindow_unlockAndPost(m_ANW.get()); } // b) After update the Surface Texture, now udpate the transfer queue info. @@ -500,14 +479,14 @@ bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, return true; } -void TransferQueue::addItemInPureColorQueue(const TileRenderInfo* renderInfo, Color color) +void TransferQueue::addItemInPureColorQueue(const TileRenderInfo* renderInfo) { // The pure color tiles' queue will be read from UI thread and written in // Tex Gen thread, thus we need to have a lock here. android::Mutex::Autolock lock(m_transferQueueItemLocks); TileTransferData data; addItemCommon(renderInfo, GpuUpload, &data); - data.pureColor = color; + data.pureColor = renderInfo->pureColor; m_pureColorTileQueue.append(data); } @@ -517,8 +496,8 @@ void TransferQueue::addItemCommon(const TileRenderInfo* renderInfo, TextureUploadType type, TileTransferData* data) { - data->savedBaseTileTexturePtr = renderInfo->baseTile->backTexture(); - data->savedBaseTilePtr = renderInfo->baseTile; + data->savedTileTexturePtr = renderInfo->baseTile->backTexture(); + data->savedTilePtr = renderInfo->baseTile; data->status = pendingBlit; data->uploadType = type; @@ -541,7 +520,7 @@ void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo, m_transferQueueIndex = (m_transferQueueIndex + 1) % m_transferQueueSize; int index = m_transferQueueIndex; - if (m_transferQueue[index].savedBaseTilePtr + if (m_transferQueue[index].savedTilePtr || m_transferQueue[index].status != emptyItem) { ALOGV("ERROR update a tile which is dirty already @ index %d", index); } @@ -575,7 +554,7 @@ void TransferQueue::setTextureUploadType(TextureUploadType type) } // Note: this need to be called within the lock and on the UI thread. -// Only called by updateDirtyBaseTiles() and emptyQueue() for now +// Only called by updateDirtyTiles() and emptyQueue() for now void TransferQueue::cleanupPendingDiscard() { int index = getNextTransferQueueIndex(); @@ -593,8 +572,8 @@ void TransferQueue::cleanupPendingDiscard() // since tiles in the queue may be from another webview, remove // their textures so that they will be repainted / retransferred - BaseTile* tile = m_transferQueue[index].savedBaseTilePtr; - BaseTileTexture* texture = m_transferQueue[index].savedBaseTileTexturePtr; + Tile* tile = m_transferQueue[index].savedTilePtr; + TileTexture* texture = m_transferQueue[index].savedTileTexturePtr; if (tile && texture && texture->owner() == tile) { // since tile destruction removes textures on the UI thread, the // texture->owner ptr guarantees the tile is valid @@ -602,8 +581,8 @@ void TransferQueue::cleanupPendingDiscard() ALOGV("transfer queue discarded tile %p, removed texture", tile); } - m_transferQueue[index].savedBaseTilePtr = 0; - m_transferQueue[index].savedBaseTileTexturePtr = 0; + m_transferQueue[index].savedTilePtr = 0; + m_transferQueue[index].savedTileTexturePtr = 0; m_transferQueue[index].status = emptyItem; } index = (index + 1) % m_transferQueueSize; @@ -612,6 +591,7 @@ void TransferQueue::cleanupPendingDiscard() void TransferQueue::saveGLState() { + glGetIntegerv(GL_FRAMEBUFFER_BINDING, m_GLStateBeforeBlit.bufferId); glGetIntegerv(GL_VIEWPORT, m_GLStateBeforeBlit.viewport); glGetBooleanv(GL_SCISSOR_TEST, m_GLStateBeforeBlit.scissor); glGetBooleanv(GL_DEPTH_TEST, m_GLStateBeforeBlit.depth); @@ -635,6 +615,7 @@ void TransferQueue::setGLStateForCopy(int width, int height) void TransferQueue::restoreGLState() { + glBindFramebuffer(GL_FRAMEBUFFER, m_GLStateBeforeBlit.bufferId[0]); glViewport(m_GLStateBeforeBlit.viewport[0], m_GLStateBeforeBlit.viewport[1], m_GLStateBeforeBlit.viewport[2], diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.h b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h index b864085..d1024a4 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.h +++ b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h @@ -28,15 +28,19 @@ #if USE(ACCELERATED_COMPOSITING) -#include "BaseTile.h" -#include "BaseTileTexture.h" +#include "GLUtils.h" #include "ShaderProgram.h" -#include "TiledPage.h" -#include <EGL/eglext.h> +#include "SkBitmap.h" +#include <utils/StrongPointer.h> +#include <utils/threads.h> namespace WebCore { +class Tile; +class TileTexture; + struct GLState { + GLint bufferId[1]; GLint viewport[4]; GLboolean scissor[1]; GLboolean depth[1]; @@ -44,7 +48,7 @@ struct GLState { }; -// While in the queue, the BaseTile can be re-used, the updated bitmap +// While in the queue, the Tile can be re-used, the updated bitmap // can be discarded. In order to track this obsolete base tiles, we save // the Tile's Info to make the comparison. // At the time of base tile's dtor or webview destroy, we want to discard @@ -70,8 +74,8 @@ class TileTransferData { public: TileTransferData() : status(emptyItem) - , savedBaseTilePtr(0) - , savedBaseTileTexturePtr(0) + , savedTilePtr(0) + , savedTileTexturePtr(0) , uploadType(DEFAULT_UPLOAD_TYPE) , bitmap(0) , m_syncKHR(EGL_NO_SYNC_KHR) @@ -85,8 +89,8 @@ public: } TransferItemStatus status; - BaseTile* savedBaseTilePtr; - BaseTileTexture* savedBaseTileTexturePtr; + Tile* savedTilePtr; + TileTexture* savedTileTexturePtr; IntRect invalRect; TextureUploadType uploadType; // This is only useful in Cpu upload code path, so it will be dynamically @@ -114,7 +118,7 @@ public: // This will be called by the browser through nativeSetProperty void setTextureUploadType(TextureUploadType type); void cleanupGLResources(); - void updateDirtyBaseTiles(); + void updateDirtyTiles(); void initGLResources(int width, int height); @@ -134,7 +138,7 @@ public: void lockQueue() { m_transferQueueItemLocks.lock(); } void unlockQueue() { m_transferQueueItemLocks.unlock(); } - void addItemInPureColorQueue(const TileRenderInfo* renderInfo, Color color); + void addItemInPureColorQueue(const TileRenderInfo* renderInfo); void setPendingDiscardWithLock(); void emptyQueue(); @@ -144,7 +148,7 @@ public: // a lock to protect its access TileTransferData* m_transferQueue; - sp<ANativeWindow> m_ANW; + android::sp<ANativeWindow> m_ANW; // EGL wrapper around m_ANW for use by the GaneshRenderer EGLSurface m_eglSurface; @@ -171,8 +175,8 @@ private: // pendingDiscard items. void cleanupPendingDiscard(); - void blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, - BaseTileTexture* frontTex, + void blitTileFromQueue(GLuint fboID, TileTexture* destTex, + TileTexture* frontTex, GLuint srcTexId, GLenum srcTexTarget, int index); @@ -192,7 +196,7 @@ private: bool m_hasGLContext; GLState m_GLStateBeforeBlit; - sp<android::SurfaceTexture> m_sharedSurfaceTexture; + android::sp<android::SurfaceTexture> m_sharedSurfaceTexture; int m_emptyItemCount; diff --git a/Source/WebCore/platform/graphics/android/ClassTracker.cpp b/Source/WebCore/platform/graphics/android/utils/ClassTracker.cpp index 98e33d9..98e33d9 100644 --- a/Source/WebCore/platform/graphics/android/ClassTracker.cpp +++ b/Source/WebCore/platform/graphics/android/utils/ClassTracker.cpp diff --git a/Source/WebCore/platform/graphics/android/ClassTracker.h b/Source/WebCore/platform/graphics/android/utils/ClassTracker.h index d169883..d169883 100644 --- a/Source/WebCore/platform/graphics/android/ClassTracker.h +++ b/Source/WebCore/platform/graphics/android/utils/ClassTracker.h diff --git a/Source/WebCore/platform/graphics/android/TestExport.h b/Source/WebCore/platform/graphics/android/utils/TestExport.h index 15d7cc3..15d7cc3 100644 --- a/Source/WebCore/platform/graphics/android/TestExport.h +++ b/Source/WebCore/platform/graphics/android/utils/TestExport.h diff --git a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp index dc22fca..ec04035 100644 --- a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp +++ b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp @@ -180,9 +180,9 @@ static void ensureSessionIsInitialized(SoupSession* session) g_object_set_data(G_OBJECT(session), "webkit-init", reinterpret_cast<void*>(0xdeadbeef)); } -void ResourceHandle::prepareForURL(const KURL &url) +void ResourceHandle::prepareForURL(const KURL& url) { - GOwnPtr<SoupURI> soupURI(soup_uri_new(url.prettyURL().utf8().data())); + GOwnPtr<SoupURI> soupURI(soup_uri_new(url.string().utf8().data())); if (!soupURI) return; soup_session_prepare_for_uri(ResourceHandle::defaultSession(), soupURI.get()); diff --git a/Source/WebCore/platform/qt/KURLQt.cpp b/Source/WebCore/platform/qt/KURLQt.cpp index f6d2a86..674a933 100644 --- a/Source/WebCore/platform/qt/KURLQt.cpp +++ b/Source/WebCore/platform/qt/KURLQt.cpp @@ -50,4 +50,3 @@ String KURL::fileSystemPath() const } } - diff --git a/Source/WebCore/platform/win/ClipboardWin.cpp b/Source/WebCore/platform/win/ClipboardWin.cpp index 0b5a3d3..2e56cbc 100644 --- a/Source/WebCore/platform/win/ClipboardWin.cpp +++ b/Source/WebCore/platform/win/ClipboardWin.cpp @@ -191,7 +191,7 @@ static HGLOBAL createGlobalHDropContent(const KURL& url, String& fileName, Share WCHAR filePath[MAX_PATH]; if (url.isLocalFile()) { - String localPath = url.path(); + String localPath = decodeURLEscapeSequences(url.path()); // windows does not enjoy a leading slash on paths if (localPath[0] == '/') localPath = localPath.substring(1); diff --git a/Source/WebCore/plugins/android/PluginViewAndroid.cpp b/Source/WebCore/plugins/android/PluginViewAndroid.cpp index 315d8a4..fdf6e03 100644 --- a/Source/WebCore/plugins/android/PluginViewAndroid.cpp +++ b/Source/WebCore/plugins/android/PluginViewAndroid.cpp @@ -690,7 +690,10 @@ void PluginView::paint(GraphicsContext* context, const IntRect& rect) notification of its global position change. */ updatePluginWidget(); - m_window->setSurfaceClip(context->platformContext()->mCanvas->getTotalClip().getBounds()); + SkCanvas* canvas = context->platformContext()->getCanvas(); + if (!canvas) + return; + m_window->setSurfaceClip(canvas->getTotalClip().getBounds()); } else { m_window->inval(rect, false); context->save(); diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp index a90bf69..a3bd41a 100644 --- a/Source/WebCore/rendering/RenderBlock.cpp +++ b/Source/WebCore/rendering/RenderBlock.cpp @@ -191,7 +191,7 @@ void RenderBlock::destroy() childBox->remove(); } } - } else if (isInline() && parent()) + } else if (parent()) parent()->dirtyLinesFromChangedChild(this); } @@ -420,14 +420,18 @@ void RenderBlock::addChildToAnonymousColumnBlocks(RenderObject* newChild, Render RenderBlock* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBlock) { + RenderBlock* firstChildIgnoringAnonymousWrappers = 0; for (RenderObject* curr = this; curr; curr = curr->parent()) { if (!curr->isRenderBlock() || curr->isFloatingOrPositioned() || curr->isTableCell() || curr->isRoot() || curr->isRenderView() || curr->hasOverflowClip() || curr->isInlineBlockOrInlineTable()) return 0; RenderBlock* currBlock = toRenderBlock(curr); + if (!currBlock->createsAnonymousWrapper()) + firstChildIgnoringAnonymousWrappers = currBlock; + if (currBlock->style()->specifiesColumns() && (allowAnonymousColumnBlock || !currBlock->isAnonymousColumnsBlock())) - return currBlock; + return firstChildIgnoringAnonymousWrappers; if (currBlock->isAnonymousColumnSpanBlock()) return 0; @@ -443,6 +447,8 @@ RenderBlock* RenderBlock::clone() const else { cloneBlock = new (renderArena()) RenderBlock(node()); cloneBlock->setStyle(style()); + if (!childrenInline() && cloneBlock->firstChild() && cloneBlock->firstChild()->isInline()) + cloneBlock->makeChildrenNonInline(); } cloneBlock->setChildrenInline(childrenInline()); return cloneBlock; @@ -657,12 +663,21 @@ RenderBlock* RenderBlock::columnsBlockForSpanningElement(RenderObject* newChild) // cross the streams and have to cope with both types of continuations mixed together). // This function currently supports (1) and (2). RenderBlock* columnsBlockAncestor = 0; - if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isFloatingOrPositioned() - && !newChild->isInline() && !isAnonymousColumnSpanBlock()) { - if (style()->specifiesColumns()) - columnsBlockAncestor = this; - else if (parent() && parent()->isRenderBlock()) - columnsBlockAncestor = toRenderBlock(parent())->containingColumnsBlock(false); + if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isBeforeOrAfterContent() + && !newChild->isFloatingOrPositioned() && !newChild->isInline() && !isAnonymousColumnSpanBlock()) { + columnsBlockAncestor = containingColumnsBlock(false); + if (columnsBlockAncestor) { + // Make sure that none of the parent ancestors have a continuation. + // If yes, we do not want split the block into continuations. + RenderObject* curr = this; + while (curr && curr != columnsBlockAncestor) { + if (curr->isRenderBlock() && toRenderBlock(curr)->continuation()) { + columnsBlockAncestor = 0; + break; + } + curr = curr->parent(); + } + } } return columnsBlockAncestor; } diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp index fb1dd2c..9c40d5b 100644 --- a/Source/WebCore/rendering/RenderBox.cpp +++ b/Source/WebCore/rendering/RenderBox.cpp @@ -3260,7 +3260,7 @@ bool RenderBox::shrinkToAvoidFloats() const bool RenderBox::avoidsFloats() const { - return isReplaced() || hasOverflowClip() || isHR() || isLegend() || isWritingModeRoot(); + return isReplaced() || hasOverflowClip() || isHR() || isLegend() || isWritingModeRoot() || isDeprecatedFlexItem(); } void RenderBox::addShadowOverflow() diff --git a/Source/WebCore/rendering/RenderBox.h b/Source/WebCore/rendering/RenderBox.h index 1bee989..a5dc1b2 100644 --- a/Source/WebCore/rendering/RenderBox.h +++ b/Source/WebCore/rendering/RenderBox.h @@ -378,6 +378,8 @@ public: virtual void markForPaginationRelayoutIfNeeded() { } bool isWritingModeRoot() const { return !parent() || parent()->style()->writingMode() != style()->writingMode(); } + + bool isDeprecatedFlexItem() const { return !isInline() && !isFloatingOrPositioned() && parent() && parent()->isFlexibleBox(); } virtual int lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; diff --git a/Source/WebCore/rendering/RenderFileUploadControl.cpp b/Source/WebCore/rendering/RenderFileUploadControl.cpp index 8056662..109d219 100644 --- a/Source/WebCore/rendering/RenderFileUploadControl.cpp +++ b/Source/WebCore/rendering/RenderFileUploadControl.cpp @@ -122,6 +122,13 @@ String RenderFileUploadControl::acceptTypes() return static_cast<HTMLInputElement*>(node())->accept(); } +#if ENABLE(MEDIA_CAPTURE) +String RenderFileUploadControl::capture() +{ + return static_cast<HTMLInputElement*>(node())->capture(); +} +#endif + void RenderFileUploadControl::chooseIconForFiles(FileChooser* chooser, const Vector<String>& filenames) { if (Chrome* chromePointer = chrome()) diff --git a/Source/WebCore/rendering/RenderFileUploadControl.h b/Source/WebCore/rendering/RenderFileUploadControl.h index e9fb7f0..b57260d 100644 --- a/Source/WebCore/rendering/RenderFileUploadControl.h +++ b/Source/WebCore/rendering/RenderFileUploadControl.h @@ -68,6 +68,9 @@ private: #endif String acceptTypes(); void chooseIconForFiles(FileChooser*, const Vector<String>&); +#if ENABLE(MEDIA_CAPTURE) + String capture(); +#endif Chrome* chrome() const; int maxFilenameWidth() const; diff --git a/Source/WebCore/rendering/RenderFlexibleBox.cpp b/Source/WebCore/rendering/RenderFlexibleBox.cpp index dc5c171..99c7e0b 100644 --- a/Source/WebCore/rendering/RenderFlexibleBox.cpp +++ b/Source/WebCore/rendering/RenderFlexibleBox.cpp @@ -43,30 +43,30 @@ namespace WebCore { class FlexBoxIterator { public: FlexBoxIterator(RenderFlexibleBox* parent) + : m_box(parent) + , m_lastOrdinal(1) { - box = parent; - if (box->style()->boxOrient() == HORIZONTAL && !box->style()->isLeftToRightDirection()) - forward = box->style()->boxDirection() != BNORMAL; + if (m_box->style()->boxOrient() == HORIZONTAL && !m_box->style()->isLeftToRightDirection()) + m_forward = m_box->style()->boxDirection() != BNORMAL; else - forward = box->style()->boxDirection() == BNORMAL; - lastOrdinal = 1; - if (!forward) { + m_forward = m_box->style()->boxDirection() == BNORMAL; + if (!m_forward) { // No choice, since we're going backwards, we have to find out the highest ordinal up front. - RenderBox* child = box->firstChildBox(); + RenderBox* child = m_box->firstChildBox(); while (child) { - if (child->style()->boxOrdinalGroup() > lastOrdinal) - lastOrdinal = child->style()->boxOrdinalGroup(); + if (child->style()->boxOrdinalGroup() > m_lastOrdinal) + m_lastOrdinal = child->style()->boxOrdinalGroup(); child = child->nextSiblingBox(); } } - + reset(); } void reset() { - current = 0; - currentOrdinal = forward ? 0 : lastOrdinal+1; + m_currentChild = 0; + m_currentOrdinal = m_forward ? 0 : m_lastOrdinal + 1; } RenderBox* first() @@ -74,42 +74,42 @@ public: reset(); return next(); } - + RenderBox* next() { - do { - if (!current) { - if (forward) { - currentOrdinal++; - if (currentOrdinal > lastOrdinal) + do { + if (!m_currentChild) { + if (m_forward) { + ++m_currentOrdinal; + if (m_currentOrdinal > m_lastOrdinal) return 0; - current = box->firstChildBox(); + m_currentChild = m_box->firstChildBox(); } else { - currentOrdinal--; - if (currentOrdinal == 0) + --m_currentOrdinal; + if (!m_currentOrdinal) return 0; - current = box->lastChildBox(); + m_currentChild = m_box->lastChildBox(); } } else - current = forward ? current->nextSiblingBox() : current->previousSiblingBox(); - if (current && current->style()->boxOrdinalGroup() > lastOrdinal) - lastOrdinal = current->style()->boxOrdinalGroup(); - } while (!current || current->style()->boxOrdinalGroup() != currentOrdinal || - current->style()->visibility() == COLLAPSE); - return current; + m_currentChild = m_forward ? m_currentChild->nextSiblingBox() : m_currentChild->previousSiblingBox(); + if (m_currentChild && m_currentChild->style()->boxOrdinalGroup() > m_lastOrdinal) + m_lastOrdinal = m_currentChild->style()->boxOrdinalGroup(); + } while (!m_currentChild || (!m_currentChild->isAnonymous() + && (m_currentChild->style()->boxOrdinalGroup() != m_currentOrdinal || m_currentChild->style()->visibility() == COLLAPSE))); + return m_currentChild; } private: - RenderFlexibleBox* box; - RenderBox* current; - bool forward; - unsigned int currentOrdinal; - unsigned int lastOrdinal; + RenderFlexibleBox* m_box; + RenderBox* m_currentChild; + bool m_forward; + unsigned int m_currentOrdinal; + unsigned int m_lastOrdinal; }; - + RenderFlexibleBox::RenderFlexibleBox(Node* node) -:RenderBlock(node) + : RenderBlock(node) { setChildrenInline(false); // All of our children must be block-level m_flexingChildren = m_stretchingChildren = false; @@ -119,54 +119,48 @@ RenderFlexibleBox::~RenderFlexibleBox() { } +static int marginWidthForChild(RenderBox* child) +{ + // A margin basically has three types: fixed, percentage, and auto (variable). + // Auto and percentage margins simply become 0 when computing min/max width. + // Fixed margins can be added in as is. + Length marginLeft = child->style()->marginLeft(); + Length marginRight = child->style()->marginRight(); + int margin = 0; + if (marginLeft.isFixed()) + margin += marginLeft.value(); + if (marginRight.isFixed()) + margin += marginRight.value(); + return margin; +} + void RenderFlexibleBox::calcHorizontalPrefWidths() { for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { - // positioned children don't affect the minmaxwidth + // Positioned children and collapsed children don't affect the min/max width. if (child->isPositioned() || child->style()->visibility() == COLLAPSE) continue; - // A margin basically has three types: fixed, percentage, and auto (variable). - // Auto and percentage margins simply become 0 when computing min/max width. - // Fixed margins can be added in as is. - Length ml = child->style()->marginLeft(); - Length mr = child->style()->marginRight(); - int margin = 0, marginLeft = 0, marginRight = 0; - if (ml.isFixed()) - marginLeft += ml.value(); - if (mr.isFixed()) - marginRight += mr.value(); - margin = marginLeft + marginRight; - + int margin = marginWidthForChild(child); m_minPreferredLogicalWidth += child->minPreferredLogicalWidth() + margin; m_maxPreferredLogicalWidth += child->maxPreferredLogicalWidth() + margin; - } + } } void RenderFlexibleBox::calcVerticalPrefWidths() { for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { - // Positioned children and collapsed children don't affect the min/max width + // Positioned children and collapsed children don't affect the min/max width. if (child->isPositioned() || child->style()->visibility() == COLLAPSE) continue; - // A margin basically has three types: fixed, percentage, and auto (variable). - // Auto/percentage margins simply become 0 when computing min/max width. - // Fixed margins can be added in as is. - Length ml = child->style()->marginLeft(); - Length mr = child->style()->marginRight(); - int margin = 0; - if (ml.isFixed()) - margin += ml.value(); - if (mr.isFixed()) - margin += mr.value(); - - int w = child->minPreferredLogicalWidth() + margin; - m_minPreferredLogicalWidth = max(w, m_minPreferredLogicalWidth); - - w = child->maxPreferredLogicalWidth() + margin; - m_maxPreferredLogicalWidth = max(w, m_maxPreferredLogicalWidth); - } + int margin = marginWidthForChild(child); + int width = child->minPreferredLogicalWidth() + margin; + m_minPreferredLogicalWidth = max(width, m_minPreferredLogicalWidth); + + width = child->maxPreferredLogicalWidth() + margin; + m_maxPreferredLogicalWidth = max(width, m_maxPreferredLogicalWidth); + } } void RenderFlexibleBox::computePreferredLogicalWidths() @@ -197,7 +191,7 @@ void RenderFlexibleBox::computePreferredLogicalWidths() m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value())); m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value())); } - + if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) { m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->maxWidth().value())); m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->maxWidth().value())); @@ -222,10 +216,10 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int /*pageHeight FIXM int previousWidth = width(); int previousHeight = height(); - + computeLogicalWidth(); computeLogicalHeight(); - + m_overflow.clear(); if (previousWidth != width() || previousHeight != height() || @@ -280,7 +274,7 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int /*pageHeight FIXM setMaxMarginBeforeValues(pos, neg); setMaxMarginAfterValues(0, 0); } - + computeOverflow(oldClientAfterEdge); statePusher.pop(); @@ -297,15 +291,14 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int /*pageHeight FIXM // Repaint with our new bounds if they are different from our old bounds. repainter.repaintAfterLayout(); - + setNeedsLayout(false); } // The first walk over our kids is to find out if we have any flexible children. static void gatherFlexChildrenInfo(FlexBoxIterator& iterator, bool relayoutChildren, unsigned int& highestFlexGroup, unsigned int& lowestFlexGroup, bool& haveFlex) { - RenderBox* child = iterator.first(); - while (child) { + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { // Check to see if this child flexes. if (!child->isPositioned() && child->style()->boxFlex() > 0.0f) { // We always have to lay out flexible objects again, since the flex distribution @@ -322,7 +315,6 @@ static void gatherFlexChildrenInfo(FlexBoxIterator& iterator, bool relayoutChild if (flexGroup > highestFlexGroup) highestFlexGroup = flexGroup; } - child = iterator.next(); } } @@ -343,8 +335,6 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) bool haveFlex = false; gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex); - RenderBox* child; - RenderBlock::startDelayUpdateScrollInfo(); // We do 2 passes. The first pass is simply to lay everyone out at @@ -354,31 +344,28 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) setHeight(yPos); xPos = borderLeft() + paddingLeft(); - + // Our first pass is done without flexing. We simply lay the children // out within the box. We have to do a layout first in order to determine // our box's intrinsic height. int maxAscent = 0, maxDescent = 0; - child = iterator.first(); - while (child) { + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { // make sure we relayout children if we need it. if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))) child->setChildNeedsLayout(true, false); - - if (child->isPositioned()) { - child = iterator.next(); + + if (child->isPositioned()) continue; - } - + // Compute the child's vertical margins. child->computeBlockDirectionMargins(this); - + if (!child->needsLayout()) child->markForPaginationRelayoutIfNeeded(); // Now do the layout. child->layoutIfNeeded(); - + // Update our height and overflow height. if (style()->boxAlign() == BBASELINE) { int ascent = child->firstLineBoxBaseline(); @@ -386,38 +373,35 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) ascent = child->height() + child->marginBottom(); ascent += child->marginTop(); int descent = (child->marginTop() + child->height() + child->marginBottom()) - ascent; - + // Update our maximum ascent. maxAscent = max(maxAscent, ascent); - + // Update our maximum descent. maxDescent = max(maxDescent, descent); - + // Now update our height. setHeight(max(yPos + maxAscent + maxDescent, height())); } else setHeight(max(height(), yPos + child->marginTop() + child->height() + child->marginBottom())); - - child = iterator.next(); } - + if (!iterator.first() && hasLineIfEmpty()) setHeight(height() + lineHeight(true, style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes)); - + setHeight(height() + toAdd); - + oldHeight = height(); computeLogicalHeight(); relayoutChildren = false; if (oldHeight != height()) heightSpecified = true; - + // Now that our height is actually known, we can place our boxes. m_stretchingChildren = (style()->boxAlign() == BSTRETCH); - child = iterator.first(); - while (child) { + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { if (child->isPositioned()) { child->containingBlock()->insertPositionedObject(child); RenderLayer* childLayer = child->layer(); @@ -427,10 +411,9 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode())) child->setChildNeedsLayout(true, false); } - child = iterator.next(); continue; } - + // We need to see if this child's height has changed, since we make block elements // fill the height of a containing box by default. // Now do a layout. @@ -438,18 +421,18 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) child->computeLogicalHeight(); if (oldChildHeight != child->height()) child->setChildNeedsLayout(true, false); - + if (!child->needsLayout()) child->markForPaginationRelayoutIfNeeded(); child->layoutIfNeeded(); - + // We can place the child now, using our value of box-align. xPos += child->marginLeft(); int childY = yPos; switch (style()->boxAlign()) { case BCENTER: - childY += child->marginTop() + max(0, (contentHeight() - (child->height() + child->marginTop() + child->marginBottom()))/2); + childY += child->marginTop() + max(0, (contentHeight() - (child->height() + child->marginTop() + child->marginBottom())) / 2); break; case BBASELINE: { int ascent = child->firstLineBoxBaseline(); @@ -468,14 +451,12 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) } placeChild(child, xPos, childY); - + xPos += child->width() + child->marginRight(); - - child = iterator.next(); } remainingSpace = borderLeft() + paddingLeft() + contentWidth() - xPos; - + m_stretchingChildren = false; if (m_flexingChildren) haveFlex = false; // We're done. @@ -500,24 +481,20 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) // forces a totalFlex recomputation). int groupRemainingSpaceAtBeginning = groupRemainingSpace; float totalFlex = 0.0f; - child = iterator.first(); - while (child) { + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { if (allowedChildFlex(child, expanding, i)) totalFlex += child->style()->boxFlex(); - child = iterator.next(); } - child = iterator.first(); int spaceAvailableThisPass = groupRemainingSpace; - while (child) { + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { int allowedFlex = allowedChildFlex(child, expanding, i); if (allowedFlex) { int projectedFlex = (allowedFlex == INT_MAX) ? allowedFlex : (int)(allowedFlex * (totalFlex / child->style()->boxFlex())); spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex); } - child = iterator.next(); } - // The flex groups may not have any flexible objects this time around. + // The flex groups may not have any flexible objects this time around. if (!spaceAvailableThisPass || totalFlex == 0.0f) { // If we just couldn't grow/shrink any more, then it's time to transition to the next flex group. groupRemainingSpace = 0; @@ -525,8 +502,7 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) } // Now distribute the space to objects. - child = iterator.first(); - while (child && spaceAvailableThisPass && totalFlex) { + for (RenderBox* child = iterator.first(); child && spaceAvailableThisPass && totalFlex; child = iterator.next()) { if (allowedChildFlex(child, expanding, i)) { int spaceAdd = (int)(spaceAvailableThisPass * (child->style()->boxFlex()/totalFlex)); if (spaceAdd) { @@ -538,16 +514,14 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) spaceAvailableThisPass -= spaceAdd; remainingSpace -= spaceAdd; groupRemainingSpace -= spaceAdd; - + totalFlex -= child->style()->boxFlex(); } - child = iterator.next(); } if (groupRemainingSpace == groupRemainingSpaceAtBeginning) { - // this is not advancing, avoid getting stuck by distributing the remaining pixels - child = iterator.first(); + // This is not advancing, avoid getting stuck by distributing the remaining pixels. int spaceAdd = groupRemainingSpace > 0 ? 1 : -1; - while (child && groupRemainingSpace) { + for (RenderBox* child = iterator.first(); child && groupRemainingSpace; child = iterator.next()) { if (allowedChildFlex(child, expanding, i)) { child->setOverrideSize(child->overrideWidth() + spaceAdd); m_flexingChildren = true; @@ -555,7 +529,6 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) remainingSpace -= spaceAdd; groupRemainingSpace -= spaceAdd; } - child = iterator.next(); } } } while (groupRemainingSpace); @@ -578,59 +551,47 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) if (style()->boxPack() == BJUSTIFY) { // Determine the total number of children. int totalChildren = 0; - child = iterator.first(); - while (child) { - if (child->isPositioned()) { - child = iterator.next(); + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { + if (child->isPositioned()) continue; - } - totalChildren++; - child = iterator.next(); + ++totalChildren; } // Iterate over the children and space them out according to the // justification level. if (totalChildren > 1) { - totalChildren--; + --totalChildren; bool firstChild = true; - child = iterator.first(); - while (child) { - if (child->isPositioned()) { - child = iterator.next(); + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { + if (child->isPositioned()) continue; - } if (firstChild) { firstChild = false; - child = iterator.next(); continue; } offset += remainingSpace/totalChildren; remainingSpace -= (remainingSpace/totalChildren); - totalChildren--; + --totalChildren; - placeChild(child, child->x()+offset, child->y()); - child = iterator.next(); + placeChild(child, child->x() + offset, child->y()); } } } else { if (style()->boxPack() == BCENTER) - offset += remainingSpace/2; + offset += remainingSpace / 2; else // END for LTR, START for RTL offset += remainingSpace; - child = iterator.first(); - while (child) { - if (child->isPositioned()) { - child = iterator.next(); + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { + if (child->isPositioned()) continue; - } - placeChild(child, child->x()+offset, child->y()); - child = iterator.next(); + + placeChild(child, child->x() + offset, child->y()); } } } - + // So that the computeLogicalHeight in layoutBlock() knows to relayout positioned objects because of // a height change, we revert our height back to the intrinsic height before returning. if (heightSpecified) @@ -655,8 +616,6 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) bool haveFlex = false; gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex); - RenderBox* child; - // We confine the line clamp ugliness to vertical flexible boxes (thus keeping it out of // mainstream block layout); this is not really part of the XUL box model. bool haveLineClamp = !style()->lineClamp().isNone(); @@ -673,12 +632,11 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) setHeight(borderTop() + paddingTop()); int minHeight = height() + toAdd; - child = iterator.first(); - while (child) { - // make sure we relayout children if we need it. + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { + // Make sure we relayout children if we need it. if (!haveLineClamp && (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())))) child->setChildNeedsLayout(true, false); - + if (child->isPositioned()) { child->containingBlock()->insertPositionedObject(child); RenderLayer* childLayer = child->layer(); @@ -688,28 +646,27 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode())) child->setChildNeedsLayout(true, false); } - child = iterator.next(); continue; - } - + } + // Compute the child's vertical margins. child->computeBlockDirectionMargins(this); - + // Add in the child's marginTop to our height. setHeight(height() + child->marginTop()); - + if (!child->needsLayout()) child->markForPaginationRelayoutIfNeeded(); // Now do a layout. child->layoutIfNeeded(); - + // We can place the child now, using our value of box-align. int childX = borderLeft() + paddingLeft(); switch (style()->boxAlign()) { case BCENTER: case BBASELINE: // Baseline just maps to center for vertical boxes - childX += child->marginLeft() + max(0, (contentWidth() - (child->width() + child->marginLeft() + child->marginRight()))/2); + childX += child->marginLeft() + max(0, (contentWidth() - (child->width() + child->marginLeft() + child->marginRight())) / 2); break; case BEND: if (!style()->isLeftToRightDirection()) @@ -724,19 +681,17 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) childX += contentWidth() - child->marginRight() - child->width(); break; } - + // Place the child. placeChild(child, childX, height()); setHeight(height() + child->height() + child->marginBottom()); - - child = iterator.next(); } yPos = height(); - + if (!iterator.first() && hasLineIfEmpty()) setHeight(height() + lineHeight(true, style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes)); - + setHeight(height() + toAdd); // Negative margins can cause our height to shrink below our minimal height (border/padding). @@ -751,7 +706,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) heightSpecified = true; remainingSpace = borderTop() + paddingTop() + contentHeight() - yPos; - + if (m_flexingChildren) haveFlex = false; // We're done. else if (haveFlex) { @@ -775,33 +730,28 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) // forces a totalFlex recomputation). int groupRemainingSpaceAtBeginning = groupRemainingSpace; float totalFlex = 0.0f; - child = iterator.first(); - while (child) { + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { if (allowedChildFlex(child, expanding, i)) totalFlex += child->style()->boxFlex(); - child = iterator.next(); } - child = iterator.first(); int spaceAvailableThisPass = groupRemainingSpace; - while (child) { + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { int allowedFlex = allowedChildFlex(child, expanding, i); if (allowedFlex) { int projectedFlex = (allowedFlex == INT_MAX) ? allowedFlex : (int)(allowedFlex * (totalFlex / child->style()->boxFlex())); spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex); } - child = iterator.next(); } - // The flex groups may not have any flexible objects this time around. + // The flex groups may not have any flexible objects this time around. if (!spaceAvailableThisPass || totalFlex == 0.0f) { // If we just couldn't grow/shrink any more, then it's time to transition to the next flex group. groupRemainingSpace = 0; continue; } - + // Now distribute the space to objects. - child = iterator.first(); - while (child && spaceAvailableThisPass && totalFlex) { + for (RenderBox* child = iterator.first(); child && spaceAvailableThisPass && totalFlex; child = iterator.next()) { if (allowedChildFlex(child, expanding, i)) { int spaceAdd = (int)(spaceAvailableThisPass * (child->style()->boxFlex()/totalFlex)); if (spaceAdd) { @@ -813,16 +763,14 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) spaceAvailableThisPass -= spaceAdd; remainingSpace -= spaceAdd; groupRemainingSpace -= spaceAdd; - + totalFlex -= child->style()->boxFlex(); } - child = iterator.next(); } if (groupRemainingSpace == groupRemainingSpaceAtBeginning) { - // this is not advancing, avoid getting stuck by distributing the remaining pixels - child = iterator.first(); + // This is not advancing, avoid getting stuck by distributing the remaining pixels. int spaceAdd = groupRemainingSpace > 0 ? 1 : -1; - while (child && groupRemainingSpace) { + for (RenderBox* child = iterator.first(); child && groupRemainingSpace; child = iterator.next()) { if (allowedChildFlex(child, expanding, i)) { child->setOverrideSize(child->overrideHeight() + spaceAdd); m_flexingChildren = true; @@ -830,7 +778,6 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) remainingSpace -= spaceAdd; groupRemainingSpace -= spaceAdd; } - child = iterator.next(); } } } while (groupRemainingSpace); @@ -839,7 +786,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) // We didn't find any children that could grow. if (haveFlex && !m_flexingChildren) haveFlex = false; - } + } } while (haveFlex); RenderBlock::finishDelayUpdateScrollInfo(); @@ -850,54 +797,42 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) if (style()->boxPack() == BJUSTIFY) { // Determine the total number of children. int totalChildren = 0; - child = iterator.first(); - while (child) { - if (child->isPositioned()) { - child = iterator.next(); + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { + if (child->isPositioned()) continue; - } - totalChildren++; - child = iterator.next(); + + ++totalChildren; } - + // Iterate over the children and space them out according to the // justification level. if (totalChildren > 1) { - totalChildren--; + --totalChildren; bool firstChild = true; - child = iterator.first(); - while (child) { - if (child->isPositioned()) { - child = iterator.next(); + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { + if (child->isPositioned()) continue; - } - + if (firstChild) { firstChild = false; - child = iterator.next(); continue; } offset += remainingSpace/totalChildren; remainingSpace -= (remainingSpace/totalChildren); - totalChildren--; - placeChild(child, child->x(), child->y()+offset); - child = iterator.next(); + --totalChildren; + placeChild(child, child->x(), child->y() + offset); } } } else { if (style()->boxPack() == BCENTER) - offset += remainingSpace/2; + offset += remainingSpace / 2; else // END offset += remainingSpace; - child = iterator.first(); - while (child) { - if (child->isPositioned()) { - child = iterator.next(); + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { + if (child->isPositioned()) continue; - } - placeChild(child, child->x(), child->y()+offset); - child = iterator.next(); + placeChild(child, child->x(), child->y() + offset); } } } @@ -905,7 +840,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) // So that the computeLogicalHeight in layoutBlock() knows to relayout positioned objects because of // a height change, we revert our height back to the intrinsic height before returning. if (heightSpecified) - setHeight(oldHeight); + setHeight(oldHeight); } void RenderFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool relayoutChildren) @@ -940,16 +875,16 @@ void RenderFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool relayoutC for (RenderBox* child = iterator.first(); child; child = iterator.next()) { if (child->isPositioned() || !child->style()->height().isAuto() || !child->isBlockFlow()) continue; - + RenderBlock* blockChild = toRenderBlock(child); int lineCount = blockChild->lineCount(); if (lineCount <= numVisibleLines) continue; - + int newHeight = blockChild->heightForLineCount(numVisibleLines); if (newHeight == child->height()) continue; - + child->setChildNeedsLayout(true, false); child->setOverrideSize(newHeight); m_flexingChildren = true; @@ -962,11 +897,11 @@ void RenderFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool relayoutC continue; // Get the last line - RootInlineBox* lastLine = blockChild->lineAtIndex(lineCount-1); + RootInlineBox* lastLine = blockChild->lineAtIndex(lineCount - 1); if (!lastLine) continue; - RootInlineBox* lastVisibleLine = blockChild->lineAtIndex(numVisibleLines-1); + RootInlineBox* lastVisibleLine = blockChild->lineAtIndex(numVisibleLines - 1); if (!lastVisibleLine) continue; @@ -975,7 +910,7 @@ void RenderFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool relayoutC DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1)); const Font& font = style(numVisibleLines == 1)->font(); - // Get ellipsis width, and if the last child is an anchor, it will go after the ellipsis, so add in a space and the anchor width too + // Get ellipsis width, and if the last child is an anchor, it will go after the ellipsis, so add in a space and the anchor width too int totalWidth; InlineBox* anchorBox = lastLine->lastChild(); if (anchorBox && anchorBox->renderer()->style()->isLink()) @@ -988,7 +923,7 @@ void RenderFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool relayoutC // See if this width can be accommodated on the last visible line RenderBlock* destBlock = toRenderBlock(lastVisibleLine->renderer()); RenderBlock* srcBlock = toRenderBlock(lastLine->renderer()); - + // FIXME: Directions of src/destBlock could be different from our direction and from one another. if (!srcBlock->style()->isLeftToRightDirection()) continue; @@ -1028,57 +963,55 @@ int RenderFlexibleBox::allowedChildFlex(RenderBox* child, bool expanding, unsign { if (child->isPositioned() || child->style()->boxFlex() == 0.0f || child->style()->boxFlexGroup() != group) return 0; - + if (expanding) { if (isHorizontal()) { // FIXME: For now just handle fixed values. - int maxW = INT_MAX; - int w = child->overrideWidth() - child->borderAndPaddingWidth(); - if (!child->style()->maxWidth().isUndefined() && - child->style()->maxWidth().isFixed()) - maxW = child->style()->maxWidth().value(); + int maxWidth = INT_MAX; + int width = child->overrideWidth() - child->borderAndPaddingWidth(); + if (!child->style()->maxWidth().isUndefined() && child->style()->maxWidth().isFixed()) + maxWidth = child->style()->maxWidth().value(); else if (child->style()->maxWidth().type() == Intrinsic) - maxW = child->maxPreferredLogicalWidth(); + maxWidth = child->maxPreferredLogicalWidth(); else if (child->style()->maxWidth().type() == MinIntrinsic) - maxW = child->minPreferredLogicalWidth(); - if (maxW == INT_MAX) - return maxW; - return max(0, maxW - w); + maxWidth = child->minPreferredLogicalWidth(); + if (maxWidth == INT_MAX) + return maxWidth; + return max(0, maxWidth - width); } else { // FIXME: For now just handle fixed values. - int maxH = INT_MAX; - int h = child->overrideHeight() - child->borderAndPaddingHeight(); - if (!child->style()->maxHeight().isUndefined() && - child->style()->maxHeight().isFixed()) - maxH = child->style()->maxHeight().value(); - if (maxH == INT_MAX) - return maxH; - return max(0, maxH - h); + int maxHeight = INT_MAX; + int height = child->overrideHeight() - child->borderAndPaddingHeight(); + if (!child->style()->maxHeight().isUndefined() && child->style()->maxHeight().isFixed()) + maxHeight = child->style()->maxHeight().value(); + if (maxHeight == INT_MAX) + return maxHeight; + return max(0, maxHeight - height); } } // FIXME: For now just handle fixed values. if (isHorizontal()) { - int minW = child->minPreferredLogicalWidth(); - int w = child->overrideWidth() - child->borderAndPaddingWidth(); + int minWidth = child->minPreferredLogicalWidth(); + int width = child->overrideWidth() - child->borderAndPaddingWidth(); if (child->style()->minWidth().isFixed()) - minW = child->style()->minWidth().value(); + minWidth = child->style()->minWidth().value(); else if (child->style()->minWidth().type() == Intrinsic) - minW = child->maxPreferredLogicalWidth(); + minWidth = child->maxPreferredLogicalWidth(); else if (child->style()->minWidth().type() == MinIntrinsic) - minW = child->minPreferredLogicalWidth(); - - int allowedShrinkage = min(0, minW - w); + minWidth = child->minPreferredLogicalWidth(); + + int allowedShrinkage = min(0, minWidth - width); return allowedShrinkage; } else { if (child->style()->minHeight().isFixed()) { - int minH = child->style()->minHeight().value(); - int h = child->overrideHeight() - child->borderAndPaddingHeight(); - int allowedShrinkage = min(0, minH - h); + int minHeight = child->style()->minHeight().value(); + int height = child->overrideHeight() - child->borderAndPaddingHeight(); + int allowedShrinkage = min(0, minHeight - height); return allowedShrinkage; } } - + return 0; } diff --git a/Source/WebCore/rendering/RenderFrame.cpp b/Source/WebCore/rendering/RenderFrame.cpp index 4b1444b..0ae6eda 100644 --- a/Source/WebCore/rendering/RenderFrame.cpp +++ b/Source/WebCore/rendering/RenderFrame.cpp @@ -64,7 +64,12 @@ void RenderFrame::layout() { FrameView* view = static_cast<FrameView*>(widget()); RenderView* root = view ? view->frame()->contentRenderer() : 0; + + // Do not expand frames which has zero width or height if (!width() || !height() || !root) { + updateWidgetPosition(); + if (view) + view->layout(); setNeedsLayout(false); return; } @@ -75,14 +80,17 @@ void RenderFrame::layout() return; } - int layoutWidth = width(); + // Update the dimensions to get the correct width and height + updateWidgetPosition(); + if (root->preferredLogicalWidthsDirty()) + root->computePreferredLogicalWidths(); + // Expand the frame by setting frame height = content height setWidth(max(view->contentsWidth() + borderAndPaddingWidth(), width())); setHeight(max(view->contentsHeight() + borderAndPaddingHeight(), height())); - // Trigger a layout of the FrameView which will schedule a relayout of this RenderFrame. - if (layoutWidth < width()) - view->layout(); + // Update one more time + updateWidgetPosition(); setNeedsLayout(false); } diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp index 733a418..1871b57 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.cpp +++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp @@ -628,6 +628,7 @@ bool RenderLayerCompositor::checkForPositionedElements(Vector<RenderLayer*>* lis bool fixedSibling = false; bool positionedSibling = false; +#if 0 // For absolute positioned elements, we need to check if they are followed // by a composited element; if so, they also need to be composited, as the // layer display rendering might be incorrect (absolute elements being @@ -650,6 +651,7 @@ bool RenderLayerCompositor::checkForPositionedElements(Vector<RenderLayer*>* lis break; } } +#endif // If we find a fixed layer, let's mark all the following layers as being // composited. The layers' surfaces will be merged if needed UI-side. @@ -737,7 +739,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O bool willBeComposited = needsToBeComposited(layer); -#if ENABLE(COMPOSITED_FIXED_ELEMENTS) +#if 0 && ENABLE(COMPOSITED_FIXED_ELEMENTS) willBeComposited |= layer->shouldComposite(); layer->setMustOverlapCompositedLayers(layer->shouldComposite()); #endif diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp index 8caef04..f37753e 100644 --- a/Source/WebCore/rendering/RenderObject.cpp +++ b/Source/WebCore/rendering/RenderObject.cpp @@ -2029,6 +2029,10 @@ RenderObject* RenderObject::container(RenderBoxModelObject* repaintContainer, bo while (o && o->style()->position() == StaticPosition && !o->isRenderView() && !(o->hasTransform() && o->isRenderBlock())) { if (repaintContainerSkipped && o == repaintContainer) *repaintContainerSkipped = true; +#if ENABLE(SVG) + if (o->isSVGForeignObject()) // foreignObject is the containing block for contents inside it + break; +#endif o = o->parent(); } } diff --git a/Source/WebCore/rendering/RenderObject.h b/Source/WebCore/rendering/RenderObject.h index 005c453..f5fe562 100644 --- a/Source/WebCore/rendering/RenderObject.h +++ b/Source/WebCore/rendering/RenderObject.h @@ -312,6 +312,7 @@ public: inline bool isBeforeContent() const; inline bool isAfterContent() const; + inline bool isBeforeOrAfterContent() const; static inline bool isBeforeContent(const RenderObject* obj) { return obj && obj->isBeforeContent(); } static inline bool isAfterContent(const RenderObject* obj) { return obj && obj->isAfterContent(); } @@ -917,6 +918,11 @@ inline bool RenderObject::isAfterContent() const return true; } +inline bool RenderObject::isBeforeOrAfterContent() const +{ + return isBeforeContent() || isAfterContent(); +} + inline void RenderObject::setNeedsLayout(bool b, bool markParents) { bool alreadyNeededLayout = m_needsLayout; diff --git a/Source/WebCore/rendering/RenderReplaced.cpp b/Source/WebCore/rendering/RenderReplaced.cpp index c27d336..09a7944 100644 --- a/Source/WebCore/rendering/RenderReplaced.cpp +++ b/Source/WebCore/rendering/RenderReplaced.cpp @@ -57,6 +57,14 @@ RenderReplaced::~RenderReplaced() { } +void RenderReplaced::destroy() +{ + if (!documentBeingDestroyed() && parent()) + parent()->dirtyLinesFromChangedChild(this); + + RenderBox::destroy(); +} + void RenderReplaced::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderBox::styleDidChange(diff, oldStyle); diff --git a/Source/WebCore/rendering/RenderReplaced.h b/Source/WebCore/rendering/RenderReplaced.h index d6ebba6..29fc71c 100644 --- a/Source/WebCore/rendering/RenderReplaced.h +++ b/Source/WebCore/rendering/RenderReplaced.h @@ -32,6 +32,8 @@ public: RenderReplaced(Node*, const IntSize& intrinsicSize); virtual ~RenderReplaced(); + virtual void destroy(); + protected: virtual void layout(); diff --git a/Source/WebCore/rendering/RenderWidget.cpp b/Source/WebCore/rendering/RenderWidget.cpp index 894d689..97444cd 100644 --- a/Source/WebCore/rendering/RenderWidget.cpp +++ b/Source/WebCore/rendering/RenderWidget.cpp @@ -125,6 +125,10 @@ void RenderWidget::destroy() document()->axObjectCache()->childrenChanged(this->parent()); document()->axObjectCache()->remove(this); } + + if (!documentBeingDestroyed() && parent()) + parent()->dirtyLinesFromChangedChild(this); + remove(); if (m_hasCounterNodeMap) diff --git a/Source/WebCore/workers/WorkerLocation.cpp b/Source/WebCore/workers/WorkerLocation.cpp index b934abd..319a528 100644 --- a/Source/WebCore/workers/WorkerLocation.cpp +++ b/Source/WebCore/workers/WorkerLocation.cpp @@ -36,7 +36,7 @@ namespace WebCore { String WorkerLocation::href() const { - return m_url.hasPath() ? m_url.prettyURL() : m_url.prettyURL() + "/"; + return m_url.string(); } String WorkerLocation::protocol() const @@ -74,11 +74,6 @@ String WorkerLocation::hash() const return m_url.fragmentIdentifier().isEmpty() ? "" : "#" + m_url.fragmentIdentifier(); } -String WorkerLocation::toString() const -{ - return m_url.hasPath() ? m_url.prettyURL() : m_url.prettyURL() + "/"; -} - } // namespace WebCore diff --git a/Source/WebCore/workers/WorkerLocation.h b/Source/WebCore/workers/WorkerLocation.h index 5200e35..692c0e3 100644 --- a/Source/WebCore/workers/WorkerLocation.h +++ b/Source/WebCore/workers/WorkerLocation.h @@ -30,10 +30,10 @@ #if ENABLE(WORKERS) #include "KURL.h" -#include <wtf/Forward.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> +#include <wtf/text/WTFString.h> namespace WebCore { @@ -57,7 +57,7 @@ namespace WebCore { String search() const; String hash() const; - String toString() const; + String toString() const { return href(); } private: WorkerLocation(const KURL& url) : m_url(url) { } |