diff options
159 files changed, 5033 insertions, 2778 deletions
@@ -127,6 +127,11 @@ LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \ $(WEBCORE_PATH)/platform/animation \ $(WEBCORE_PATH)/platform/graphics \ $(WEBCORE_PATH)/platform/graphics/android \ + $(WEBCORE_PATH)/platform/graphics/android/context \ + $(WEBCORE_PATH)/platform/graphics/android/fonts \ + $(WEBCORE_PATH)/platform/graphics/android/layers \ + $(WEBCORE_PATH)/platform/graphics/android/rendering \ + $(WEBCORE_PATH)/platform/graphics/android/utils \ $(WEBCORE_PATH)/platform/graphics/filters \ $(WEBCORE_PATH)/platform/graphics/gpu \ $(WEBCORE_PATH)/platform/graphics/network \ diff --git a/CleanSpec.mk b/CleanSpec.mk index fda2cf9..d2841a3 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -81,6 +81,7 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_int $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates) # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST @@ -1,57 +1,79 @@ -Copyright (C) 2005 Apple Computer, Inc. All rights reserved. +(WebKit doesn't distribute an explicit license. This LICENSE is derived from +license text in the source.) + +Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, +2006, 2007 Alexander Kellett, Alexey Proskuryakov, Alex Mathews, Allan +Sandfeld Jensen, Alp Toker, Anders Carlsson, Andrew Wellington, Antti +Koivisto, Apple Inc., Arthur Langereis, Baron Schwartz, Bjoern Graf, +Brent Fulgham, Cameron Zwarich, Charles Samuels, Christian Dywan, +Collabora Ltd., Cyrus Patel, Daniel Molkentin, Dave Maclachlan, David +Smith, Dawit Alemayehu, Dirk Mueller, Dirk Schulze, Don Gibson, Enrico +Ros, Eric Seidel, Frederik Holljen, Frerich Raabe, Friedmann Kleint, +George Staikos, Google Inc., Graham Dennis, Harri Porten, Henry Mason, +Hiroyuki Ikezoe, Holger Hans Peter Freyther, IBM, James G. Speth, Jan +Alonzo, Jean-Loup Gailly, John Reis, Jonas Witt, Jon Shier, Jonas +Witt, Julien Chaffraix, Justin Haygood, Kevin Ollivier, Kevin Watters, +Kimmo Kinnunen, Kouhei Sutou, Krzysztof Kowalczyk, Lars Knoll, Luca +Bruno, Maks Orlovich, Malte Starostik, Mark Adler, Martin Jones, +Marvin Decker, Matt Lilek, Michael Emmel, Mitz Pettel, mozilla.org, +Netscape Communications Corporation, Nicholas Shanks, Nikolas +Zimmermann, Nokia, Oliver Hunt, Opened Hand, Paul Johnston, Peter +Kelly, Pioneer Research Center USA, Rich Moore, Rob Buis, Robin Dunn, +Ronald Tschalär, Samuel Weinig, Simon Hausmann, Staikos Computing +Services Inc., Stefan Schimanski, Symantec Corporation, The Dojo +Foundation, The Karbon Developers, Thomas Boyer, Tim Copperfield, +Tobias Anton, Torben Weis, Trolltech, University of Cambridge, Vaclav +Slavik, Waldo Bastian, Xan Lopez, Zack Rusin + +The terms and conditions vary from file to file, but are one of: Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. 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. -3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS 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. - -Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. All rights reserved. +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. 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. + +*OR* Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: +modification, are permitted provided that the following conditions are +met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. + documentation and/or other materials provided with the + distribution. +3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. OR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. 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. +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -484,55 +506,12 @@ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - <one line to give the library's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - <signature of Ty Coon>, 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -676,7 +655,7 @@ such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. - + 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an @@ -986,47 +965,3 @@ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - <one line to give the library's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - <signature of Ty Coon>, 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/Source/JavaScriptCore/wtf/HashTraits.h b/Source/JavaScriptCore/wtf/HashTraits.h index fba5afe..7deeb3a 100644 --- a/Source/JavaScriptCore/wtf/HashTraits.h +++ b/Source/JavaScriptCore/wtf/HashTraits.h @@ -28,6 +28,8 @@ namespace WTF { + class String; + using std::pair; using std::make_pair; @@ -88,6 +90,7 @@ namespace WTF { }; template<typename P> struct HashTraits<RefPtr<P> > : SimpleClassHashTraits<RefPtr<P> > { }; + template<> struct HashTraits<String> : SimpleClassHashTraits<String> { }; // special traits for pairs, helpful for their use in HashMap implementation diff --git a/Source/JavaScriptCore/wtf/text/StringHash.h b/Source/JavaScriptCore/wtf/text/StringHash.h index c47c1d8..497184d 100644 --- a/Source/JavaScriptCore/wtf/text/StringHash.h +++ b/Source/JavaScriptCore/wtf/text/StringHash.h @@ -179,8 +179,6 @@ namespace WTF { } }; - template<> struct HashTraits<String> : SimpleClassHashTraits<String> { }; - } using WTF::StringHash; diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk index 6ddf965..3cf8d54 100644 --- a/Source/WebCore/Android.mk +++ b/Source/WebCore/Android.mk @@ -633,65 +633,74 @@ 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/CanvasLayer.cpp \ - platform/graphics/android/CanvasTexture.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/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/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/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) \ @@ -1263,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/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/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/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/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index b7458e8..1b0513b 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 @@ -135,10 +132,10 @@ 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 * viewMaxTileY * (manager->highEndGfx() ? 4 : 2); + TilesManager* tilesManager = TilesManager::instance(); + int maxTextureCount = viewMaxTileX * viewMaxTileY * (tilesManager->highEndGfx() ? 4 : 2); - manager->setMaxTextureCount(maxTextureCount); + tilesManager->setMaxTextureCount(maxTextureCount); // TODO: investigate whether we can move this return earlier. if ((m_viewport == viewport) @@ -156,10 +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_viewport.width(), m_viewport.height(), scale); } #ifdef MEASURES_PERF @@ -302,10 +298,11 @@ bool GLWebViewState::setLayersRenderingMode(TexturesResult& nbTexturesNeeded) 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) +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(); tilesManager->getProfiler()->nextFrame(viewport.fLeft, viewport.fTop, @@ -328,15 +325,17 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, 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); @@ -348,14 +347,13 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, 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); + 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", @@ -364,15 +362,17 @@ 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(); - 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_frameworkLayersInval.isEmpty(); @@ -402,9 +402,10 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, } } - 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 85c90fd..6d969dd 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.h +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h @@ -49,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; @@ -96,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 @@ -110,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): @@ -128,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 @@ -152,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()). // @@ -180,10 +177,11 @@ public: bool setLayersRenderingMode(TexturesResult&); - 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(); diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index fa620e0..00e6918 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -34,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" @@ -295,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(); } @@ -714,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/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/PlatformGraphicsContext.cpp b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp deleted file mode 100644 index 3c8ea3c..0000000 --- a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp +++ /dev/null @@ -1,1048 +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 "PlatformGraphicsContext.h" - -#include "AffineTransform.h" -#include "Font.h" -#include "Gradient.h" -#include "GraphicsContext.h" -#include "Node.h" -#include "NotImplemented.h" -#include "Path.h" -#include "Pattern.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" - -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 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; -} - -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); -} - -//************************************** -// State structs -//************************************** - -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) - {}; -}; - -struct PlatformGraphicsContext::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; - SkShader* fillShader; - SkColor strokeColor; - SkShader* strokeShader; - bool useAA; - StrokeStyle strokeStyle; - - 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) - { - } - - 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); - } - - ~State() - { - SkSafeUnref(pathEffect); - SkSafeUnref(fillShader); - SkSafeUnref(strokeShader); - } - - 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(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 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); - } - - PlatformGraphicsContext::State cloneInheritedProperties(); -private: - // Not supported. - void operator=(const State&); -}; - -// 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(SkCanvas* canvas, - bool takeCanvasOwnership) - : mCanvas(canvas) - , m_deleteCanvas(takeCanvasOwnership) - , m_stateStack(sizeof(State)) - , m_gc(0) -{ - m_stateStack.append(State()); - m_state = &m_stateStack.last(); -} - -PlatformGraphicsContext::~PlatformGraphicsContext() -{ - if (m_deleteCanvas) - delete mCanvas; -} - -//************************************** -// State management -//************************************** - -void PlatformGraphicsContext::beginTransparencyLayer(float opacity) -{ - SkCanvas* canvas = mCanvas; - canvas->saveLayerAlpha(0, (int)(opacity * 255), TRANSPARENCY_SAVEFLAGS); -} - -void PlatformGraphicsContext::endTransparencyLayer() -{ - mCanvas->restore(); -} - -void PlatformGraphicsContext::save() -{ - m_stateStack.append(m_state->cloneInheritedProperties()); - m_state = &m_stateStack.last(); - - // Save our native canvas. - mCanvas->save(); -} - -void PlatformGraphicsContext::restore() -{ - m_stateStack.removeLast(); - m_state = &m_stateStack.last(); - - // Restore our native canvas. - mCanvas->restore(); -} - -//************************************** -// 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: - SkDEBUGF(("PlatformGraphicsContext::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: - SkDEBUGF(("PlatformGraphicsContext::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; -} - -//************************************** -// Matrix operations -//************************************** - -void PlatformGraphicsContext::concatCTM(const AffineTransform& affine) -{ - mCanvas->concat(affine); -} - -void PlatformGraphicsContext::rotate(float angleInRadians) -{ - mCanvas->rotate(SkFloatToScalar(angleInRadians * (180.0f / 3.14159265f))); -} - -void PlatformGraphicsContext::scale(const FloatSize& size) -{ - mCanvas->scale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height())); -} - -void PlatformGraphicsContext::translate(float x, float y) -{ - mCanvas->translate(SkFloatToScalar(x), SkFloatToScalar(y)); -} - -//************************************** -// Clipping -//************************************** - -void PlatformGraphicsContext::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 PlatformGraphicsContext::canvasClip(const Path& path) -{ - clip(path); -} - -void PlatformGraphicsContext::clip(const FloatRect& rect) -{ - mCanvas->clipRect(rect); -} - -void PlatformGraphicsContext::clip(const Path& path) -{ - mCanvas->clipPath(*path.platformPath(), SkRegion::kIntersect_Op, true); -} - -void PlatformGraphicsContext::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 PlatformGraphicsContext::clipOut(const IntRect& r) -{ - mCanvas->clipRect(r, SkRegion::kDifference_Op); -} - -void PlatformGraphicsContext::clipOut(const Path& p) -{ - mCanvas->clipPath(*p.platformPath(), SkRegion::kDifference_Op); -} - -void PlatformGraphicsContext::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 PlatformGraphicsContext::clearRect(const FloatRect& rect) -{ - SkPaint paint; - - setupPaintFill(&paint); - paint.setXfermodeMode(SkXfermode::kClear_Mode); - mCanvas->drawRect(rect, paint); -} - -//************************************** -// Drawing -//************************************** - -void PlatformGraphicsContext::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 PlatformGraphicsContext::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 PlatformGraphicsContext::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 PlatformGraphicsContext::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 PlatformGraphicsContext::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 PlatformGraphicsContext::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, 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); - } -} - -void PlatformGraphicsContext::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 PlatformGraphicsContext::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 PlatformGraphicsContext::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 PlatformGraphicsContext::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 PlatformGraphicsContext::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 PlatformGraphicsContext::fillRect(const FloatRect& rect) -{ - SkPaint paint; - setupPaintFill(&paint); - mCanvas->drawRect(rect, paint); -} - -void PlatformGraphicsContext::fillRect(const FloatRect& rect, - const Color& color, ColorSpace) -{ - 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 PlatformGraphicsContext::fillRoundedRect( - const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, - const IntSize& bottomLeft, const IntSize& bottomRight, - const Color& color, ColorSpace) -{ - 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 PlatformGraphicsContext::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 PlatformGraphicsContext::strokePath(const Path& pathToStroke) -{ - const SkPath* path = pathToStroke.platformPath(); - if (!path) - return; - - SkPaint paint; - setupPaintStroke(&paint, 0); - - mCanvas->drawPath(*path, paint); -} - -void PlatformGraphicsContext::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/PlatformGraphicsContext.h b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h deleted file mode 100644 index ce126a4..0000000 --- a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h +++ /dev/null @@ -1,150 +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 "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(SkCanvas* canvas, bool takeCanvasOwnership = false); - ~PlatformGraphicsContext(); - - void setGraphicsContext(GraphicsContext* gc) { m_gc = gc; } - - // FIXME: Make mCanvas private - SkCanvas* mCanvas; - // FIXME: This is used by ImageBufferAndroid, which should really be - // managing the canvas lifecycle itself - bool deleteUs() const { return m_deleteCanvas; } - - // State management - void beginTransparencyLayer(float opacity); - void endTransparencyLayer(); - void save(); - void restore(); - - // State values - void setAlpha(float alpha); - void setCompositeOperation(CompositeOperator op); - void setFillColor(const Color& c); - void setFillShader(SkShader* fillShader); - void setLineCap(LineCap cap); - void setLineDash(const DashArray& dashes, float dashOffset); - void setLineJoin(LineJoin join); - void setMiterLimit(float limit); - void setShadow(int radius, int dx, int dy, SkColor c); - void setShouldAntialias(bool useAA); - void setStrokeColor(const Color& c); - void setStrokeShader(SkShader* strokeShader); - void setStrokeStyle(StrokeStyle style); - void setStrokeThickness(float f); - - // FIXME: These setupPaint* should be private, but - // they are used by FontAndroid currently - void setupPaintFill(SkPaint* paint) const; - 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. - bool setupPaintStroke(SkPaint* paint, SkRect* rect, bool isHLine = false); - - // Matrix operations - void concatCTM(const AffineTransform& affine); - void rotate(float angleInRadians); - void scale(const FloatSize& size); - void translate(float x, float y); - const SkMatrix& getTotalMatrix() { return mCanvas->getTotalMatrix(); } - - // Clipping - void addInnerRoundedRectClip(const IntRect& rect, int thickness); - void canvasClip(const Path& path); - void clip(const FloatRect& rect); - void clip(const Path& path); - void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias); - void clipOut(const IntRect& r); - void clipOut(const Path& p); - void clipPath(const Path& pathToClip, WindRule clipRule); - - // Drawing - void clearRect(const FloatRect& rect); - void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix, - CompositeOperator compositeOp, const FloatRect& destRect); - void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, - const SkRect& dst, CompositeOperator op); - void drawConvexPolygon(size_t numPoints, const FloatPoint* points, - bool shouldAntialias); - void drawEllipse(const IntRect& rect); - void drawFocusRing(const Vector<IntRect>& rects, int /* width */, - int /* offset */, const Color& color); - void drawHighlightForText(const Font& font, const TextRun& run, - const FloatPoint& point, int h, - const Color& backgroundColor, ColorSpace colorSpace, - int from, int to, bool isActive); - void drawLine(const IntPoint& point1, const IntPoint& point2); - void drawLineForText(const FloatPoint& pt, float width); - void drawLineForTextChecking(const FloatPoint& pt, float width, - GraphicsContext::TextCheckingLineStyle); - void drawRect(const IntRect& rect); - void fillPath(const Path& pathToFill, WindRule fillRule); - void fillRect(const FloatRect& rect); - void fillRect(const FloatRect& rect, const Color& color, ColorSpace); - void fillRoundedRect(const IntRect& rect, const IntSize& topLeft, - const IntSize& topRight, const IntSize& bottomLeft, - const IntSize& bottomRight, const Color& color, - ColorSpace); - void strokeArc(const IntRect& r, int startAngle, int angleSpan); - void strokePath(const Path& pathToStroke); - void strokeRect(const FloatRect& rect, float lineWidth); - -private: - - // shadowsIgnoreTransforms is only true for canvas's ImageBuffer, which will - // have a GraphicsContext - bool shadowsIgnoreTransforms() const { - return m_gc && m_gc->shadowsIgnoreTransforms(); - } - - void setupPaintCommon(SkPaint* paint) const; - - bool m_deleteCanvas; - struct State; - WTF::Vector<State> m_stateStack; - State* m_state; - GraphicsContext* m_gc; // Back-ptr to our parent -}; - -} -#endif diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.h b/Source/WebCore/platform/graphics/android/TiledTexture.h deleted file mode 100644 index b879d54..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(bool isBaseSurface) - : m_prevTileX(0) - , m_prevTileY(0) - , m_scale(1) - , m_isBaseSurface(isBaseSurface) - { - 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, GLWebViewState* state); - 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_isBaseSurface; -}; - -class DualTiledTexture : public SkRefCnt { -// TODO: investigate webkit threadsafe ref counting -public: - DualTiledTexture(bool isBaseSurface); - ~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/GraphicsContextAndroid.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp index bdc8005..12b53a3 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp @@ -32,6 +32,7 @@ #include "Path.h" #include "Pattern.h" #include "PlatformGraphicsContext.h" +#include "PlatformGraphicsContextSkia.h" #include "SkBitmapRef.h" #include "SkBlurDrawLooper.h" #include "SkBlurMaskFilter.h" @@ -78,14 +79,14 @@ static SkShader* extractShader(Pattern* pat, Gradient* grad) GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height) { - PlatformGraphicsContext* pgc = new PlatformGraphicsContext(new SkCanvas, true); + PlatformGraphicsContextSkia* pgc = new PlatformGraphicsContextSkia(new SkCanvas, true); SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); bitmap.allocPixels(); bitmap.eraseColor(0); - pgc->mCanvas->setBitmapDevice(bitmap); + pgc->getCanvas()->setBitmapDevice(bitmap); GraphicsContext* ctx = new GraphicsContext(pgc); return ctx; @@ -98,7 +99,7 @@ void GraphicsContext::platformInit(PlatformGraphicsContext* gc) if (gc) gc->setGraphicsContext(this); m_data = new GraphicsContextPlatformPrivate(gc); - setPaintingDisabled(!gc || !gc->mCanvas); + setPaintingDisabled(!gc || gc->isPaintingDisabled()); } void GraphicsContext::platformDestroy() @@ -108,11 +109,15 @@ void GraphicsContext::platformDestroy() void GraphicsContext::savePlatformState() { + if (paintingDisabled()) + return; platformContext()->save(); } void GraphicsContext::restorePlatformState() { + if (paintingDisabled()) + return; platformContext()->restore(); } @@ -301,36 +306,50 @@ void GraphicsContext::endTransparencyLayer() void GraphicsContext::setupFillPaint(SkPaint* paint) { + if (paintingDisabled()) + return; platformContext()->setupPaintFill(paint); } void GraphicsContext::setupStrokePaint(SkPaint* paint) { + if (paintingDisabled()) + return; platformContext()->setupPaintStroke(paint, 0); } bool GraphicsContext::setupShadowPaint(SkPaint* paint, SkPoint* offset) { + if (paintingDisabled()) + return false; return platformContext()->setupPaintShadow(paint, offset); } void GraphicsContext::setPlatformStrokeColor(const Color& c, ColorSpace) { + if (paintingDisabled()) + return; platformContext()->setStrokeColor(c); } 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) { + if (paintingDisabled()) + return; platformContext()->setFillColor(c); } @@ -501,30 +520,40 @@ void GraphicsContext::setPlatformShouldAntialias(bool useAA) void GraphicsContext::setPlatformFillGradient(Gradient* fillGradient) { + if (paintingDisabled()) + return; SkShader* shader = extractShader(0, fillGradient); platformContext()->setFillShader(shader); } void GraphicsContext::setPlatformFillPattern(Pattern* fillPattern) { + if (paintingDisabled()) + return; SkShader* shader = extractShader(fillPattern, 0); platformContext()->setFillShader(shader); } void GraphicsContext::setPlatformStrokeGradient(Gradient* strokeGradient) { + if (paintingDisabled()) + return; SkShader* shader = extractShader(0, strokeGradient); platformContext()->setStrokeShader(shader); } void GraphicsContext::setPlatformStrokePattern(Pattern* strokePattern) { + if (paintingDisabled()) + return; SkShader* shader = extractShader(strokePattern, 0); platformContext()->setStrokeShader(shader); } AffineTransform GraphicsContext::getCTM() const { + if (paintingDisabled()) + return AffineTransform(); const SkMatrix& m = platformContext()->getTotalMatrix(); return AffineTransform(SkScalarToDouble(m.getScaleX()), // a SkScalarToDouble(m.getSkewY()), // b @@ -615,5 +644,5 @@ void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc) { - return gc->platformContext()->mCanvas; + 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..a327b79 100644 --- a/Source/WebCore/platform/graphics/android/GlyphMapAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/fonts/GlyphMapAndroid.cpp 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/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp index 7bb632f..ce520b4 100644 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp @@ -35,7 +35,6 @@ namespace WebCore { - // Note: this must match the use of ID 0 specifying the base layer in DrawExtra #define BASE_UNIQUE_ID 0 @@ -54,4 +53,17 @@ void BaseLayerAndroid::getLocalTransform(SkMatrix* matrix) const 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/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h index 0ef39c8..f4cf9f3 100644 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h @@ -49,6 +49,8 @@ public: 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; diff --git a/Source/WebCore/platform/graphics/android/CanvasLayer.cpp b/Source/WebCore/platform/graphics/android/layers/CanvasLayer.cpp index 52bdaaa..1813903 100644 --- a/Source/WebCore/platform/graphics/android/CanvasLayer.cpp +++ b/Source/WebCore/platform/graphics/android/layers/CanvasLayer.cpp @@ -33,6 +33,7 @@ #include "AndroidLog.h" #include "CanvasTexture.h" +#include "DrawQuadData.h" #include "Image.h" #include "ImageBuffer.h" #include "RenderLayerCompositor.h" @@ -70,30 +71,36 @@ CanvasLayer::CanvasLayer(const CanvasLayer& layer) // We are making a copy for the UI, sync the interesting bits m_contentRect = layer.contentRect(); m_offsetFromRenderer = layer.offsetFromRenderer(); - m_texture->setSize(m_contentRect.size()); bool previousState = m_texture->hasValidTexture(); - // Attempt to upload to a surface texture - if (!m_texture->uploadImageBuffer(layer.m_canvas->buffer())) { - // Blargh, no surface texture - fall back to software + 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); - // 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); + } 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); } - } - 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); } } @@ -111,17 +118,26 @@ void CanvasLayer::init() void CanvasLayer::canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect) { - SkIRect irect = SkIRect::MakeXYWH(changedRect.x(), changedRect.y(), - changedRect.width(), changedRect.height()); - m_dirtyCanvas.op(irect, SkRegion::kUnion_Op); + 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(); - SkIRect irect = SkIRect::MakeWH(size.width(), size.height()); - m_dirtyCanvas.op(irect, SkRegion::kUnion_Op); + 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*) @@ -146,6 +162,12 @@ SkBitmapRef* CanvasLayer::bitmap() const 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(); } @@ -179,8 +201,9 @@ bool CanvasLayer::drawGL(bool layerTilesDisabled) SkRect rect = SkRect::MakeXYWH(m_contentRect.x() - m_offsetFromRenderer.width(), m_contentRect.y() - m_offsetFromRenderer.height(), m_contentRect.width(), m_contentRect.height()); - TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect, - m_texture->texture(), 1, true, GL_TEXTURE_EXTERNAL_OES); + TextureQuadData data(m_texture->texture(), GL_TEXTURE_EXTERNAL_OES, + GL_LINEAR, LayerQuad, &m_drawTransform, &rect); + TilesManager::instance()->shader()->drawQuad(&data); } return ret; } diff --git a/Source/WebCore/platform/graphics/android/CanvasLayer.h b/Source/WebCore/platform/graphics/android/layers/CanvasLayer.h index 532dbf2..532dbf2 100644 --- a/Source/WebCore/platform/graphics/android/CanvasLayer.h +++ b/Source/WebCore/platform/graphics/android/layers/CanvasLayer.h diff --git a/Source/WebCore/platform/graphics/android/CanvasTexture.cpp b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp index ca520fd..e4b2bc6 100644 --- a/Source/WebCore/platform/graphics/android/CanvasTexture.cpp +++ b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp @@ -72,7 +72,7 @@ bool CanvasTexture::setHwAccelerated(bool hwAccelerated) m_useHwAcceleration = hwAccelerated; if (!m_ANW.get()) return false; - destroySurfaceTexture(); + destroySurfaceTextureLocked(); return true; } @@ -87,15 +87,15 @@ void CanvasTexture::setSize(const IntSize& size) return; m_size = size; if (m_ANW.get()) { - if (!useSurfaceTexture()) { - m_ANW.clear(); - m_surfaceTexture->abandon(); - m_surfaceTexture.clear(); - } else { + 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(); } } @@ -112,9 +112,16 @@ SurfaceTextureClient* CanvasTexture::nativeWindow() 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); - 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) { + 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(); } @@ -124,11 +131,15 @@ bool CanvasTexture::uploadImageBuffer(ImageBuffer* imageBuffer) 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); - GLUtils::updateSharedSurfaceTextureWithBitmap(anw, bitmap); + if (!GLUtils::updateSharedSurfaceTextureWithBitmap(anw, bitmap)) + return false; m_hasValidTexture = true; return true; } @@ -174,7 +185,7 @@ bool CanvasTexture::updateTexImage() * Called by both threads ********************************************/ -void CanvasTexture::destroySurfaceTexture() +void CanvasTexture::destroySurfaceTextureLocked() { if (m_ANW.get()) { m_ANW.clear(); diff --git a/Source/WebCore/platform/graphics/android/CanvasTexture.h b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.h index 8875af7..98962a0 100644 --- a/Source/WebCore/platform/graphics/android/CanvasTexture.h +++ b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.h @@ -69,7 +69,7 @@ private: /******************************************** * Called by both threads ********************************************/ - void destroySurfaceTexture(); + void destroySurfaceTextureLocked(); /******************************************** * Called by WebKit thread 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 48e36fc..48e36fc 100644 --- a/Source/WebCore/platform/graphics/android/Layer.cpp +++ b/Source/WebCore/platform/graphics/android/layers/Layer.cpp diff --git a/Source/WebCore/platform/graphics/android/Layer.h b/Source/WebCore/platform/graphics/android/layers/Layer.h index 996547b..d87c699 100644 --- a/Source/WebCore/platform/graphics/android/Layer.h +++ b/Source/WebCore/platform/graphics/android/layers/Layer.h @@ -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 167f7e7..81427b8 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 { @@ -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; @@ -91,7 +92,7 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), 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) @@ -177,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); @@ -253,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) @@ -410,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()); @@ -427,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 @@ -609,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) { #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 @@ -689,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? @@ -699,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 @@ -731,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(); @@ -744,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--; } @@ -752,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; } } @@ -856,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(); @@ -909,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) diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h index c7028c5..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,7 +67,6 @@ using namespace android; namespace WebCore { class AndroidAnimation; -class BaseTileTexture; class FixedPositioning; class GLWebViewState; class IFrameLayerAndroid; @@ -256,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; } @@ -273,9 +268,9 @@ 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; } @@ -360,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 97bc32a..97bc32a 100644 --- a/Source/WebCore/platform/graphics/android/LayerContent.h +++ b/Source/WebCore/platform/graphics/android/layers/LayerContent.h diff --git a/Source/WebCore/platform/graphics/android/MediaLayer.cpp b/Source/WebCore/platform/graphics/android/layers/MediaLayer.cpp index 6227ea4..6227ea4 100644 --- a/Source/WebCore/platform/graphics/android/MediaLayer.cpp +++ b/Source/WebCore/platform/graphics/android/layers/MediaLayer.cpp diff --git a/Source/WebCore/platform/graphics/android/MediaLayer.h b/Source/WebCore/platform/graphics/android/layers/MediaLayer.h index 2f39d74..2f39d74 100644 --- a/Source/WebCore/platform/graphics/android/MediaLayer.h +++ b/Source/WebCore/platform/graphics/android/layers/MediaLayer.h 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 faa20a1..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" @@ -176,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 9ea7be2..9ea7be2 100644 --- a/Source/WebCore/platform/graphics/android/MediaTexture.h +++ b/Source/WebCore/platform/graphics/android/layers/MediaTexture.h diff --git a/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp index 6beed16..4398146 100644 --- a/Source/WebCore/platform/graphics/android/PictureLayerContent.cpp +++ b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp @@ -91,6 +91,8 @@ void PictureLayerContent::draw(SkCanvas* canvas) 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 c2c008b..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 { @@ -21,6 +22,8 @@ void PictureSetLayerContent::draw(SkCanvas* canvas) return; android::Mutex::Autolock lock(m_drawLock); + SkRect r = SkRect::MakeWH(width(), height()); + canvas->clipRect(r); m_pictureSet.draw(canvas); } 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 fba62b7..833aea9 100644 --- a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp @@ -41,6 +41,7 @@ #include "SkDevice.h" #include "SkPicture.h" #include "SkTypeface.h" +#include "Tile.h" #include "TilesManager.h" #include <wtf/text/CString.h> diff --git a/Source/WebCore/platform/graphics/android/BaseRenderer.h b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h index ef1e4c2..f225871 100644 --- a/Source/WebCore/platform/graphics/android/BaseRenderer.h +++ b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h @@ -39,7 +39,7 @@ namespace WebCore { class TextureInfo; class TilePainter; -class BaseTile; +class Tile; struct TileRenderInfo { // coordinates of the tile @@ -59,7 +59,7 @@ 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; 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 9c5a079..26bd55d 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp @@ -31,10 +31,13 @@ #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> @@ -385,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); @@ -413,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); @@ -456,14 +459,14 @@ 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. if (tileTexture && renderInfo->isPureColor) { // update basetile's info @@ -525,8 +528,13 @@ bool GLUtils::updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkB ANativeWindow_Buffer buffer; if (ANativeWindow_lock(anw, &buffer, 0)) return false; - if (buffer.width < bitmap.width() || buffer.height < bitmap.height()) + 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. @@ -639,19 +647,21 @@ void GLUtils::convertToTransformationMatrix(const float* matrix, TransformationM matrix[12], matrix[13], matrix[14], matrix[15]); } -void GLUtils::drawBackground(const Color* backgroundColor) +void GLUtils::clearBackgroundIfOpaque(const 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); + 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); } - glClear(GL_COLOR_BUFFER_BIT); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/GLUtils.h b/Source/WebCore/platform/graphics/android/rendering/GLUtils.h index 70ebbd6..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); @@ -86,7 +86,7 @@ public: static bool isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor); static bool skipTransferForPureColor(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); - static void drawBackground(const Color* backgroundColor); + 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..bf43652 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) { @@ -69,7 +72,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 @@ -146,7 +149,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 +162,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 559af1f..208adb6 100644 --- a/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp @@ -36,6 +36,7 @@ #include "SkCanvas.h" #include "SkGpuDevice.h" #include "TilesManager.h" +#include "TransferQueue.h" namespace WebCore { @@ -71,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)", diff --git a/Source/WebCore/platform/graphics/android/GaneshRenderer.h b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h index d7eda24..d7eda24 100644 --- a/Source/WebCore/platform/graphics/android/GaneshRenderer.h +++ b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.cpp b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp index 11a449a..9890331 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 { @@ -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)); @@ -173,8 +174,8 @@ bool ImageTexture::prepareGL(GLWebViewState* state) return false; if (!m_texture && m_picture) { - bool isLayerTile = true; - m_texture = new TiledTexture(isLayerTile); + bool isBaseSurface = false; + m_texture = new TileGrid(isBaseSurface); SkRegion region; region.setRect(0, 0, m_image->width(), m_image->height()); m_texture->markAsDirty(region); @@ -183,8 +184,8 @@ bool ImageTexture::prepareGL(GLWebViewState* state) if (!m_texture) return false; - IntRect visibleArea(0, 0, m_image->width(), m_image->height()); - m_texture->prepareGL(state, 1.0, visibleArea, this); + IntRect unclippedArea(0, 0, m_image->width(), m_image->height()); + m_texture->prepareGL(state, 1.0, unclippedArea, unclippedArea, this); if (m_texture->isReady()) { m_texture->swapTiles(); return false; @@ -197,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()); @@ -216,7 +215,7 @@ float ImageTexture::opacity() return m_layer->drawOpacity(); } -bool ImageTexture::paint(BaseTile* tile, SkCanvas* canvas) +bool ImageTexture::paint(Tile* tile, SkCanvas* canvas) { if (!m_picture) { ALOGV("IT %p COULDNT PAINT, NO PICTURE", this); @@ -236,7 +235,7 @@ 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) { diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.h b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.h index 91c8a29..34430f1 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(Tile* tile, SkCanvas* canvas); virtual float opacity(); int nbTextures(); @@ -97,7 +98,7 @@ private: SkBitmapRef* m_imageRef; SkBitmap* m_image; - TiledTexture* m_texture; + TileGrid* m_texture; 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 910ba21..b5e435b 100644 --- a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp @@ -30,6 +30,7 @@ #include "PaintTileOperation.h" #include "AndroidLog.h" +#include "GLWebViewState.h" #include "ImageTexture.h" #include "ImagesManager.h" #include "LayerAndroid.h" @@ -37,10 +38,12 @@ namespace WebCore { -PaintTileOperation::PaintTileOperation(BaseTile* tile, TilePainter* painter, GLWebViewState* state) +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); @@ -84,6 +87,10 @@ int PaintTileOperation::priority() int priority = 200000; + // 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(); unsigned long long drawDelta = currentDraw - m_tile->drawCount(); diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.h b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h index 468f6d2..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, GLWebViewState* state); + PaintTileOperation(Tile* tile, TilePainter* painter, + GLWebViewState* state, bool isLowResPrefetch); virtual ~PaintTileOperation(); virtual bool operator==(const QueuedOperation* operation); virtual void run(); @@ -48,9 +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 f98efcd..f98efcd 100644 --- a/Source/WebCore/platform/graphics/android/QueuedOperation.h +++ b/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp index bcfe7d8..b880eef 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp @@ -23,16 +23,21 @@ * 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 { @@ -66,8 +71,16 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can 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); diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.h b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h index 39e00f2..39e00f2 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.h +++ b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp index d1b70f7..a0d9e56 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" @@ -423,24 +424,6 @@ void ShaderProgram::setupDrawing(const IntRect& viewRect, const SkRect& visibleR 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); -} - // Calculate the right color value sent into the shader considering the (0,1) // clamp and alpha blending. Color ShaderProgram::shaderColor(Color pureColor, float opacity) @@ -482,33 +465,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) @@ -642,16 +598,20 @@ 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) +// Calculate the matrix given the geometry. +GLfloat* ShaderProgram::getProjectionMatrix(const DrawQuadData* data) { - TransformationMatrix modifiedDrawMatrix = drawMatrix; + DrawQuadType type = data->type(); + const TransformationMatrix* matrix = data->drawMatrix(); + const SkRect* geometry = data->geometry(); + if (type == Blit) + return m_transferProjMtx; + TransformationMatrix modifiedDrawMatrix; + if (type == LayerQuad) + modifiedDrawMatrix = *matrix; // 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); + modifiedDrawMatrix.translate(geometry->fLeft, geometry->fTop); + modifiedDrawMatrix.scale3d(geometry->width(), geometry->height(), 1); TransformationMatrix renderMatrix; if (!m_alphaLayer) @@ -660,26 +620,39 @@ void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix, else renderMatrix = m_projectionMatrix * modifiedDrawMatrix; - GLfloat projectionMatrix[16]; - GLUtils::toGLMatrix(projectionMatrix, renderMatrix); + GLUtils::toGLMatrix(m_tileProjMatrix, renderMatrix); + return m_tileProjMatrix; +} + +void ShaderProgram::drawQuad(const DrawQuadData* data) +{ + GLfloat* matrix = getProjectionMatrix(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, diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.h b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h index 98d45b5..b233f2b 100644 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.h +++ b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h @@ -30,6 +30,10 @@ namespace WebCore { +class DrawQuadData; +class PureColorQuadData; +class TextureQuadData; + enum ShaderType { UndefinedShader = -1, PureColor, @@ -45,14 +49,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 +86,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 +122,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, @@ -170,7 +167,7 @@ public: private: GLuint loadShader(GLenum shaderType, const char* pSource); GLint createProgram(const char* vertexSource, const char* fragmentSource); - void setProjectionMatrix(const SkRect& geometry, GLfloat* mtxPtr); + GLfloat* getProjectionMatrix(const DrawQuadData* data); void setBlendingState(bool enableBlending); void drawQuadInternal(ShaderType type, const GLfloat* matrix, int textureId, float opacity, GLenum textureTarget, GLenum filter, @@ -226,6 +223,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 5d8b726..3ed3aad 100644 --- a/Source/WebCore/platform/graphics/android/LayerGroup.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp @@ -23,80 +23,82 @@ * 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 "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 +110,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 +135,14 @@ 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()); } } -IntRect LayerGroup::visibleArea() +IntRect Surface::visibleArea() { if (singleLayer()) return getFirstLayer()->visibleArea(); @@ -156,33 +158,53 @@ 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) { bool tilesDisabled = layerTilesDisabled && !isBase(); - if (!m_dualTiledTexture) { - ALOGV("prepareGL on LG %p, no DTT, needsTexture? %d", - this, m_dualTiledTexture, needsTexture()); + if (!m_surfaceBacking) { + ALOGV("prepareGL on Surf %p, no SurfBack, needsTexture? %d", + this, m_surfaceBacking, needsTexture()); if (!needsTexture()) return; - m_dualTiledTexture = new DualTiledTexture(isBase()); + m_surfaceBacking = new SurfaceBacking(isBase()); } if (tilesDisabled) { - m_dualTiledTexture->discardTextures(); + m_surfaceBacking->discardTextures(); } else { bool allowZoom = hasText(); // only allow for scale > 1 if painting vectors IntRect prepareArea = computePrepareArea(); + IntRect fullArea = unclippedArea(); + + ALOGV("prepareGL on Surf %p with SurfBack %p, %d layers", + this, m_surfaceBacking, m_layers.size()); - ALOGV("prepareGL on LG %p with DTT %p, %d layers", - this, m_dualTiledTexture, m_layers.size()); - m_dualTiledTexture->prepareGL(getFirstLayer()->state(), allowZoom, - prepareArea, this); + 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()) @@ -196,11 +218,13 @@ bool LayerGroup::drawGL(bool layerTilesDisabled) } bool askRedraw = false; - if (m_dualTiledTexture && !tilesDisabled) { - 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) @@ -210,30 +234,30 @@ bool LayerGroup::drawGL(bool layerTilesDisabled) return askRedraw; } -void LayerGroup::swapTiles() +void Surface::swapTiles() { - if (!m_dualTiledTexture) + if (!m_surfaceBacking) return; - m_dualTiledTexture->swapTiles(); + m_surfaceBacking->swapTiles(); } -bool LayerGroup::isReady() +bool Surface::isReady() { - if (!m_dualTiledTexture) + if (!m_surfaceBacking) return true; - return m_dualTiledTexture->isReady(); + return m_surfaceBacking->isReady(); } -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) @@ -245,24 +269,24 @@ IntRect LayerGroup::computePrepareArea() { return area; } -void LayerGroup::computeTexturesAmount(TexturesResult* result) +void Surface::computeTexturesAmount(TexturesResult* result) { - if (!m_dualTiledTexture || isBase()) + if (!m_surfaceBacking || isBase()) return; - m_dualTiledTexture->computeTexturesAmount(result, getFirstLayer()); + m_surfaceBacking->computeTexturesAmount(result, getFirstLayer()); } -bool LayerGroup::isBase() +bool Surface::isBase() { - // base layer group + // 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(Tile* tile, SkCanvas* canvas) { if (singleLayer()) { getFirstLayer()->contentDraw(canvas, Layer::UnmergedLayers); @@ -294,18 +318,25 @@ bool LayerGroup::paint(BaseTile* tile, SkCanvas* canvas) return true; } -float LayerGroup::opacity() +float Surface::opacity() { if (singleLayer()) 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 edfb30d..756fabd 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,71 @@ class SkRegion; namespace WebCore { -class BaseTile; -class DualTiledTexture; +class Tile; +class SurfaceBacking; class LayerAndroid; class TexturesResult; -class LayerGroup : public TilePainter { +class Surface : public TilePainter { public: - LayerGroup(); - virtual ~LayerGroup(); + Surface(); + virtual ~Surface(); - bool tryUpdateLayerGroup(LayerGroup* oldLayerGroup); + 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(); - 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(); + void setBackground(Color background) { m_background = background; } // TilePainter methods - virtual bool paint(BaseTile* tile, SkCanvas* canvas); + virtual bool paint(Tile* tile, SkCanvas* canvas); virtual float opacity(); + virtual Color* background(); + private: + IntRect computePrepareArea(); + IntRect visibleArea(); + IntRect unclippedArea(); + bool singleLayer() { return m_layers.size() == 1; } + void updateBackground(const Color& background); + 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 +112,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..7c8f570 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp @@ -0,0 +1,171 @@ +/* + * 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_frontTexture = new TileGrid(isBaseSurface); + m_backTexture = new TileGrid(isBaseSurface); + m_scale = -1; + m_futureScale = -1; + m_zooming = false; +} + +SurfaceBacking::~SurfaceBacking() +{ + delete m_frontTexture; + delete m_backTexture; +} + +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; + } + + bool useExpandPrefetch = aggressiveRendering; + 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_frontTexture, m_backTexture); + + if (!m_zooming) { + m_frontTexture->prepareGL(state, m_scale, + prepareArea, unclippedArea, painter, false, useExpandPrefetch); + if (aggressiveRendering) { + // prepare the back tiled texture to render content in low res + float lowResPrefetchScale = m_scale * LOW_RES_PREFETCH_SCALE_MODIFIER; + m_backTexture->prepareGL(state, lowResPrefetchScale, + prepareArea, unclippedArea, painter, true, useExpandPrefetch); + m_backTexture->swapTiles(); + } + } else if (m_zoomUpdateTime < WTF::currentTime()) { + m_backTexture->prepareGL(state, m_futureScale, + prepareArea, unclippedArea, painter, false, useExpandPrefetch); + if (m_backTexture->isReady()) { + // zooming completed, swap the textures and new front tiles + swapTileGrids(); + + m_frontTexture->swapTiles(); + m_backTexture->discardTextures(); + + m_scale = m_futureScale; + m_zooming = false; + } + } +} + +void SurfaceBacking::drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform, + bool aggressiveRendering, const Color* background) +{ + // draw low res prefetch page, if needed + if (aggressiveRendering && !m_zooming && m_frontTexture->isMissingContent()) + m_backTexture->drawGL(visibleArea, opacity, transform); + + m_frontTexture->drawGL(visibleArea, opacity, transform, background); +} + +void SurfaceBacking::markAsDirty(const SkRegion& dirtyArea) +{ + m_backTexture->markAsDirty(dirtyArea); + m_frontTexture->markAsDirty(dirtyArea); +} + +void SurfaceBacking::swapTiles() +{ + m_backTexture->swapTiles(); + m_frontTexture->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* 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; +} + +void SurfaceBacking::swapTileGrids() +{ + TileGrid* temp = m_frontTexture; + m_frontTexture = m_backTexture; + m_backTexture = 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..b04e462 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h @@ -0,0 +1,86 @@ +/* + * 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_frontTexture->discardTextures(); + m_backTexture->discardTextures(); + } + bool isReady() + { + return !m_zooming && m_frontTexture->isReady() && m_scale > 0; + } + + 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: + 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_frontTexture; + TileGrid* m_backTexture; + 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/SurfaceCollection.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp index 1ea192c..cd5ceef 100644 --- a/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp @@ -34,14 +34,14 @@ #include "ClassTracker.h" #include "GLWebViewState.h" #include "LayerAndroid.h" -#include "LayerGroup.h" +#include "Surface.h" #include "ScrollableLayerAndroid.h" #include "TilesManager.h" namespace WebCore { //////////////////////////////////////////////////////////////////////////////// -// TILED PAINTING / GROUPS // +// TILED PAINTING / SURFACES // //////////////////////////////////////////////////////////////////////////////// SurfaceCollection::SurfaceCollection(LayerAndroid* layer) @@ -55,16 +55,19 @@ SurfaceCollection::SurfaceCollection(LayerAndroid* layer) m_compositedRoot->updateLayerPositions(visibleRect); // TODO: updateGLPositionsAndScale? - // allocate groups for layers, merging where possible - ALOGV("new tree, allocating groups for tree %p", m_baseLayer); + // allocate surfaces for layers, merging where possible + ALOGV("new tree, allocating surfaces for tree %p", m_baseLayer); - LayerMergeState layerMergeState(&m_layerGroups); - m_compositedRoot->assignGroups(&layerMergeState); + LayerMergeState layerMergeState(&m_surfaces); + m_compositedRoot->assignSurfaces(&layerMergeState); - // set the layergroups' and tiledpages' update count, to be drawn on painted tiles + // set the layersurfaces' 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); + for (unsigned int i = 0; i < m_surfaces.size(); i++) { + m_surfaces[i]->setUpdateCount(updateCount); + if (m_surfaces[i]->isBase()) + m_surfaces[i]->setBackground(getBackground()); + } #ifdef DEBUG_COUNT ClassTracker::instance()->increment("SurfaceCollection"); @@ -74,9 +77,9 @@ SurfaceCollection::SurfaceCollection(LayerAndroid* layer) SurfaceCollection::~SurfaceCollection() { SkSafeUnref(m_compositedRoot); - for (unsigned int i = 0; i < m_layerGroups.size(); i++) - SkSafeUnref(m_layerGroups[i]); - m_layerGroups.clear(); + for (unsigned int i = 0; i < m_surfaces.size(); i++) + SkSafeUnref(m_surfaces[i]); + m_surfaces.clear(); #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("SurfaceCollection"); @@ -88,8 +91,17 @@ void SurfaceCollection::prepareGL(const SkRect& visibleRect) 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); + 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) @@ -102,8 +114,16 @@ bool SurfaceCollection::drawGL(const SkRect& visibleRect) 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); + + // 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; } @@ -115,8 +135,8 @@ Color SurfaceCollection::getBackground() void SurfaceCollection::swapTiles() { - for (unsigned int i = 0; i < m_layerGroups.size(); i++) - m_layerGroups[i]->swapTiles(); + for (unsigned int i = 0; i < m_surfaces.size(); i++) + m_surfaces[i]->swapTiles(); } bool SurfaceCollection::isReady() @@ -127,9 +147,9 @@ bool SurfaceCollection::isReady() 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]); + 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; } } @@ -138,8 +158,8 @@ bool SurfaceCollection::isReady() void SurfaceCollection::computeTexturesAmount(TexturesResult* result) { - for (unsigned int i = 0; i < m_layerGroups.size(); i++) - m_layerGroups[i]->computeTexturesAmount(result); + for (unsigned int i = 0; i < m_surfaces.size(); i++) + m_surfaces[i]->computeTexturesAmount(result); } //////////////////////////////////////////////////////////////////////////////// @@ -151,14 +171,14 @@ void SurfaceCollection::setIsPainting(SurfaceCollection* drawingSurface) if (!drawingSurface) return; - for (unsigned int i = 0; i < m_layerGroups.size(); i++) { - LayerGroup* newLayerGroup = m_layerGroups[i]; - if (!newLayerGroup->needsTexture()) + 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_layerGroups.size(); j++) { - LayerGroup* oldLayerGroup = drawingSurface->m_layerGroups[j]; - if (newLayerGroup->tryUpdateLayerGroup(oldLayerGroup)) + for (unsigned int j = 0; j < drawingSurface->m_surfaces.size(); j++) { + Surface* oldSurface = drawingSurface->m_surfaces[j]; + if (newSurface->tryUpdateSurface(oldSurface)) break; } } diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollection.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h index e73ec9a..6450c9c 100644 --- a/Source/WebCore/platform/graphics/android/SurfaceCollection.h +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h @@ -29,7 +29,8 @@ #include "Color.h" #include "SkRect.h" #include "SkRefCnt.h" -#include "Vector.h" + +#include <wtf/Vector.h> class SkCanvas; class SkRegion; @@ -37,7 +38,7 @@ class SkRegion; namespace WebCore { class LayerAndroid; -class LayerGroup; +class Surface; class TexturesResult; class SurfaceCollection : public SkRefCnt { @@ -67,7 +68,7 @@ public: private: 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 4c48c14..91335c7 100644 --- a/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp @@ -30,7 +30,7 @@ #include "SurfaceCollectionManager.h" #include "AndroidLog.h" -#include "LayerGroup.h" +#include "private/hwui/DrawGlInfo.h" #include "TilesManager.h" #include "SurfaceCollection.h" @@ -160,18 +160,18 @@ 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); @@ -197,6 +197,31 @@ bool SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, 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; if (m_drawingCollection) { @@ -214,7 +239,7 @@ 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); @@ -227,16 +252,15 @@ bool SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, } // Start doing the actual GL drawing. - GLUtils::drawBackground(&background); - if (m_drawingCollection) - ret |= m_drawingCollection->drawGL(visibleRect); - - if (m_paintingCollection) { - ALOGV("still have painting collection %p", m_paintingCollection); - return true; - } - - return ret; + 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); + if (m_drawingCollection && m_drawingCollection->drawGL(visibleRect)) + returnFlags |= uirenderer::DrawGlInfo::kStatusDraw; + + 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 304d57f..cc98899 100644 --- a/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.h +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.h @@ -49,10 +49,10 @@ 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); + TexturesResult* texturesResultPtr, bool shouldDraw); private: void swap(); 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 4f9e6ef..b12d8b7 100644 --- a/Source/WebCore/platform/graphics/android/TextureOwner.h +++ b/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h @@ -31,14 +31,13 @@ class Layer; namespace WebCore { -class BaseTileTexture; +class TileTexture; class GLWebViewState; class TextureOwner { public: virtual ~TextureOwner() { } - virtual bool removeTexture(BaseTileTexture* texture) = 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 3279ec2..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 { diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.h b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h index 35a3386..08f69ae 100644 --- a/Source/WebCore/platform/graphics/android/TexturesGenerator.h +++ b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h @@ -30,7 +30,7 @@ #include "QueuedOperation.h" #include "TilePainter.h" -#include "Vector.h" +#include <wtf/Vector.h> #include <utils/threads.h> @@ -56,7 +56,7 @@ public: private: QueuedOperation* popNext(); virtual bool threadLoop(); - Vector<QueuedOperation*> mRequestedOperations; + WTF::Vector<QueuedOperation*> mRequestedOperations; android::Mutex mRequestedOperationsLock; android::Condition mRequestedOperationsCond; bool m_waitForCompletion; diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/rendering/Tile.cpp index 7243031..178958d 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,7 +47,7 @@ namespace WebCore { -BaseTile::BaseTile(bool isLayerTile) +Tile::Tile(bool isLayerTile) : m_x(-1) , m_y(-1) , m_frontTexture(0) @@ -55,18 +56,17 @@ BaseTile::BaseTile(bool isLayerTile) , 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); @@ -76,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) @@ -97,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) { @@ -118,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) { @@ -144,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; @@ -154,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; @@ -184,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. @@ -193,51 +189,45 @@ 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) { 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); + 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; @@ -254,9 +244,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; @@ -274,7 +264,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() @@ -283,14 +273,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; @@ -309,7 +299,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; } @@ -402,8 +392,6 @@ void BaseTile::paintBitmap(TilePainter* painter) m_atomicSync.lock(); if (texture == m_backTexture) { - m_isTexturePainted = true; - // set the fullrepaint flags m_fullRepaint = false; @@ -433,7 +421,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); @@ -452,7 +440,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); @@ -462,7 +450,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 @@ -480,7 +468,7 @@ bool BaseTile::swapTexturesIfNeeded() { return false; } -void BaseTile::backTextureTransfer() { +void Tile::backTextureTransfer() { android::AutoMutex lock(m_atomicSync); if (m_state == PaintingStarted) m_state = TransferredUnvalidated; @@ -493,7 +481,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); @@ -502,7 +490,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) { @@ -523,11 +511,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 afb1db2..cc10799 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,7 +39,7 @@ namespace WebCore { class TextureInfo; -class BaseTileTexture; +class TileTexture; class GLWebViewState; /** @@ -58,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 @@ -88,19 +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 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); // the only thread-safe function called by the background thread void paintBitmap(TilePainter* painter); @@ -119,8 +121,8 @@ public: 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; } @@ -131,7 +133,7 @@ public: void backTextureTransferFail(); // TextureOwner implementation - virtual bool removeTexture(BaseTileTexture* texture); + virtual bool removeTexture(TileTexture* texture); private: void validatePaint(); @@ -141,17 +143,14 @@ private: // 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; @@ -159,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. @@ -189,4 +185,4 @@ private: } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) -#endif // BaseTile_h +#endif // Tile_h diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/rendering/TileGrid.cpp index 51e9b35..2510d52 100644 --- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TileGrid.cpp @@ -23,36 +23,51 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define LOG_TAG "TiledTexture" +#define LOG_TAG "TileGrid" #define LOG_NDEBUG 1 #include "config.h" -#include "TiledTexture.h" +#include "TileGrid.h" #include "AndroidLog.h" +#include "DrawQuadData.h" +#include "GLWebViewState.h" #include "PaintTileOperation.h" -#include "SkCanvas.h" -#include "SkPicture.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 { -TiledTexture::~TiledTexture() +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("TiledTexture"); + ClassTracker::instance()->decrement("TileGrid"); #endif removeTiles(); } -bool TiledTexture::isReady() +bool TileGrid::isReady() { bool tilesAllReady = true; bool tilesVisible = false; for (unsigned int i = 0; i < m_tiles.size(); i++) { - BaseTile* tile = m_tiles[i]; + Tile* tile = m_tiles[i]; if (tile->isTileVisible(m_area)) { tilesVisible = true; if (!tile->isTileReady()) { @@ -65,7 +80,7 @@ bool TiledTexture::isReady() // 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", + ALOGV("TG %p, ready %d, visible %d, texturesRemain %d", this, tilesAllReady, tilesVisible, TilesManager::instance()->layerTexturesRemain()); @@ -73,16 +88,24 @@ bool TiledTexture::isReady() || !tilesVisible || tilesAllReady; } -void TiledTexture::swapTiles() +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("TT %p swapping, swaps = %d", this, swaps); + ALOGV("TG %p swapping, swaps = %d", this, swaps); } -IntRect TiledTexture::computeTilesArea(const IntRect& contentArea, float scale) +IntRect TileGrid::computeTilesArea(const IntRect& contentArea, float scale) { IntRect computedArea; IntRect area(contentArea.x() * scale, @@ -90,7 +113,7 @@ IntRect TiledTexture::computeTilesArea(const IntRect& contentArea, float 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()); + 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); @@ -98,8 +121,8 @@ IntRect TiledTexture::computeTilesArea(const IntRect& contentArea, float scale) return computedArea; } - int tileWidth = TilesManager::instance()->layerTileWidth(); - int tileHeight = TilesManager::instance()->layerTileHeight(); + int tileWidth = TilesManager::tileWidth(); + int tileHeight = TilesManager::tileHeight(); computedArea.setX(area.x() / tileWidth); computedArea.setY(area.y() / tileHeight); @@ -110,15 +133,16 @@ IntRect TiledTexture::computeTilesArea(const IntRect& contentArea, float scale) return computedArea; } -void TiledTexture::prepareGL(GLWebViewState* state, float scale, - const IntRect& prepareArea, TilePainter* painter) +void TileGrid::prepareGL(GLWebViewState* state, float scale, + const IntRect& prepareArea, const IntRect& unclippedArea, + TilePainter* painter, bool isLowResPrefetch, bool useExpandPrefetch) { // 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 " + 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(), @@ -129,8 +153,9 @@ void TiledTexture::prepareGL(GLWebViewState* state, float scale, bool goingDown = m_prevTileY < m_area.y(); m_prevTileY = m_area.y(); + TilesManager* tilesManager = TilesManager::instance(); if (scale != m_scale) - TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(painter, m_scale)); + tilesManager->removeOperationsForFilter(new ScaleFilter(painter, m_scale)); m_scale = scale; @@ -140,46 +165,72 @@ void TiledTexture::prepareGL(GLWebViewState* state, float scale, m_tiles[i]->markAsDirty(m_dirtyRegion); // log inval region for the base surface - if (m_isBaseSurface && TilesManager::instance()->getProfiler()->enabled()) { + if (m_isBaseSurface && tilesManager->getProfiler()->enabled()) { SkRegion::Iterator iterator(m_dirtyRegion); while (!iterator.done()) { SkIRect r = iterator.rect(); - TilesManager::instance()->getProfiler()->nextInval(r, scale); + tilesManager->getProfiler()->nextInval(r, scale); iterator.next(); } } m_dirtyRegion.setEmpty(); } + // prepare standard bounds (clearing ExpandPrefetch flag) 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); + 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); + prepareTile(m_area.x() + i, m_area.y() + j, + painter, state, isLowResPrefetch, false); } } + + // prepare expanded bounds + if (useExpandPrefetch) { + 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 TiledTexture::markAsDirty(const SkRegion& invalRegion) +void TileGrid::markAsDirty(const SkRegion& invalRegion) { - ALOGV("TT %p markAsDirty, current region empty %d, new empty %d", + 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 TiledTexture::prepareTile(int x, int y, TilePainter* painter, GLWebViewState* state) +void TileGrid::prepareTile(int x, int y, TilePainter* painter, + GLWebViewState* state, bool isLowResPrefetch, bool isExpandPrefetch) { - BaseTile* tile = getTile(x, y); + Tile* tile = getTile(x, y); if (!tile) { bool isLayerTile = !m_isBaseSurface; - tile = new BaseTile(isLayerTile); + 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); + + tile->setContents(x, y, m_scale, isExpandPrefetch); // TODO: move below (which is largely the same for layers / tiled page) into // prepareGL() function @@ -188,23 +239,24 @@ void TiledTexture::prepareTile(int x, int y, TilePainter* painter, GLWebViewStat 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, state); + 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); } } -BaseTile* TiledTexture::getTile(int x, int y) +Tile* TileGrid::getTile(int x, int y) { for (unsigned int i = 0; i <m_tiles.size(); i++) { - BaseTile* tile = m_tiles[i]; + Tile* tile = m_tiles[i]; if (tile->x() == x && tile->y() == y) return tile; } return 0; } -int TiledTexture::nbTextures(IntRect& area, float scale) +int TileGrid::nbTextures(IntRect& area, float scale) { IntRect tileBounds = computeTilesArea(area, scale); int numberTextures = tileBounds.width() * tileBounds.height(); @@ -212,7 +264,7 @@ int TiledTexture::nbTextures(IntRect& area, float scale) // 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]; + Tile* tile = m_tiles[i]; if (tile->isDirty() && tile->x() >= tileBounds.x() && tile->x() <= tileBounds.maxX() && tile->y() >= tileBounds.y() && tile->y() <= tileBounds.maxY()) @@ -221,25 +273,34 @@ int TiledTexture::nbTextures(IntRect& area, float scale) return numberTextures; } -bool TiledTexture::drawGL(const IntRect& visibleArea, float opacity, - const TransformationMatrix* transform) +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 false; + return; - float m_invScale = 1 / m_scale; - const float tileWidth = TilesManager::layerTileWidth() * m_invScale; - const float tileHeight = TilesManager::layerTileHeight() * m_invScale; + float invScale = 1 / m_scale; + const float tileWidth = TilesManager::tileWidth() * invScale; + const float tileHeight = TilesManager::tileHeight() * invScale; int drawn = 0; - bool askRedraw = false; + + 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); + } + for (unsigned int i = 0; i < m_tiles.size(); i++) { - BaseTile* tile = m_tiles[i]; + Tile* tile = m_tiles[i]; bool tileInView = tile->isTileVisible(m_area); if (tileInView) { - askRedraw |= !tile->isTileReady(); SkRect rect; rect.fLeft = tile->x() * tileWidth; rect.fTop = tile->y() * tileHeight; @@ -248,175 +309,72 @@ bool TiledTexture::drawGL(const IntRect& visibleArea, float opacity, 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); + + bool forceBaseBlending = background ? background->hasAlpha() : false; + bool success = tile->drawGL(opacity, rect, m_scale, transform, + forceBaseBlending); + 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++; } - if (m_isBaseSurface) - TilesManager::instance()->getProfiler()->nextTile(tile, m_invScale, tileInView); + if (semiOpaqueBaseSurface) + TilesManager::instance()->getProfiler()->nextTile(tile, invScale, tileInView); } - 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; -} + // Draw missing Regions with blend turned on + if (semiOpaqueBaseSurface) + drawMissingRegion(missingRegion, opacity, background); -void TiledTexture::removeTiles() -{ - for (unsigned int i = 0; i < m_tiles.size(); i++) { - delete m_tiles[i]; - } - m_tiles.clear(); + ALOGV("TG %p drew %d tiles, scale %f", + this, drawn, m_scale); } -void TiledTexture::discardTextures() +void TileGrid::drawMissingRegion(const SkRegion& region, float opacity, + const Color* background) { - 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; + SkRegion::Iterator iterator(region); + const float tileWidth = TilesManager::tileWidth() / m_scale; + const float tileHeight = TilesManager::tileHeight() / m_scale; + ShaderProgram* shader = TilesManager::instance()->shader(); + 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(); } - return false; -} - -DualTiledTexture::DualTiledTexture(bool isBaseSurface) -{ - m_textureA = new TiledTexture(isBaseSurface); - m_textureB = new TiledTexture(isBaseSurface); - m_frontTexture = m_textureA; - m_backTexture = m_textureB; - m_scale = -1; - m_futureScale = -1; - m_zooming = false; } -DualTiledTexture::~DualTiledTexture() +void TileGrid::removeTiles() { - 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_zooming) - 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; - } + for (unsigned int i = 0; i < m_tiles.size(); i++) { + delete m_tiles[i]; } + m_tiles.clear(); } -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) +void TileGrid::discardTextures() { - // 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; + 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..ffb6c7e --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TileGrid.h @@ -0,0 +1,87 @@ +/* + * 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: + 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, bool isLowResPrefetch = false, + bool useExpandPrefetch = 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..d992aee 100644 --- a/Source/WebCore/platform/graphics/android/TilePainter.h +++ b/Source/WebCore/platform/graphics/android/rendering/TilePainter.h @@ -33,16 +33,18 @@ class SkCanvas; namespace WebCore { -class BaseTile; +class Tile; +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(Tile* tile, 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 f7f9370..39effd7 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,7 +77,7 @@ void BaseTileTexture::discardGLTexture() } } -bool BaseTileTexture::acquire(TextureOwner* owner, bool force) +bool TileTexture::acquire(TextureOwner* owner, bool force) { if (m_owner == owner) return true; @@ -82,7 +85,7 @@ bool BaseTileTexture::acquire(TextureOwner* owner, bool force) return setOwner(owner, force); } -bool BaseTileTexture::setOwner(TextureOwner* owner, bool force) +bool TileTexture::setOwner(TextureOwner* owner, bool force) { 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,38 @@ 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) { 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. + forceBlending |= isLayer; + DrawQuadData commonData(isLayer ? LayerQuad : BaseQuad, transform, &rect, + opacity, forceBlending); + 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); + TextureQuadData data(commonData, m_ownTextureId, GL_TEXTURE_2D, GL_LINEAR); + shader->drawQuad(&data); } } diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.h b/Source/WebCore/platform/graphics/android/rendering/TileTexture.h index d8737b3..5fe43b0 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.h +++ b/Source/WebCore/platform/graphics/android/rendering/TileTexture.h @@ -23,28 +23,31 @@ * 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 @@ -77,13 +80,12 @@ public: Color pureColor() { return m_pureColor; } void drawGL(bool isLayer, const SkRect& rect, float opacity, - const TransformationMatrix* transform); + const TransformationMatrix* transform, bool forceBlending = 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 @@ -94,4 +96,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 1e9aee4..e8b8cd1 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 @@ -110,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++; @@ -126,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++; @@ -140,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) @@ -162,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(); @@ -177,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--) @@ -210,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; } @@ -227,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 @@ -253,7 +254,7 @@ void TilesManager::gatherTextures() m_layerTexturesRemain = true; } -BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) +TileTexture* TilesManager::getAvailableTexture(Tile* owner) { android::Mutex::Autolock lock(m_texturesLock); @@ -268,7 +269,7 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) return owner->backTexture(); } - WTF::Vector<BaseTileTexture*>* availableTexturePool; + WTF::Vector<TileTexture*>* availableTexturePool; if (owner->isLayerTile()) { availableTexturePool = &m_availableTilesTextures; } else { @@ -283,12 +284,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; @@ -309,7 +310,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); @@ -432,16 +433,6 @@ 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) { diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/rendering/TilesManager.h index eed99c2..92c56d3 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.h +++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.h @@ -28,21 +28,21 @@ #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 "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 @@ -74,7 +74,7 @@ public: void gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures, int* nbLayerTextures, int* nbAllocatedLayerTextures); - BaseTileTexture* getAvailableTexture(BaseTile* owner); + TileTexture* getAvailableTexture(Tile* owner); void printTextures(); @@ -88,8 +88,6 @@ public: void setMaxLayerTextureCount(int max); static float tileWidth(); static float tileHeight(); - static float layerTileWidth(); - static float layerTileHeight(); void allocateTiles(); @@ -163,14 +161,14 @@ private: TilesManager(); 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; diff --git a/Source/WebCore/platform/graphics/android/TilesProfiler.cpp b/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.cpp index 2cc6873..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,7 +93,7 @@ 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; diff --git a/Source/WebCore/platform/graphics/android/TilesProfiler.h b/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.h index a13d471..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,7 +60,7 @@ 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 nextTile(Tile* tile, float scale, bool inView); void nextInval(const SkIRect& rect, float scale); int numFrames() { return m_records.size(); @@ -78,7 +80,7 @@ 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 a3552ac..af19f30 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, true, 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) { @@ -204,8 +209,9 @@ void TransferQueue::blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, // 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 +333,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 +348,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 +361,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 +384,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 +415,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); } @@ -422,7 +428,7 @@ void TransferQueue::updateDirtyBaseTiles() if (usedFboForUpload) { glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the standard FBO restoreGLState(); - GLUtils::checkGlError("updateDirtyBaseTiles"); + GLUtils::checkGlError("updateDirtyTiles"); } m_emptyItemCount = m_transferQueueSize; @@ -435,7 +441,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(); } @@ -492,8 +498,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; @@ -516,7 +522,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); } @@ -550,7 +556,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(); @@ -568,8 +574,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 @@ -577,8 +583,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; diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.h b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h index b00ea17..65ff116 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.h +++ b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h @@ -28,13 +28,17 @@ #if USE(ACCELERATED_COMPOSITING) -#include "BaseTile.h" -#include "BaseTileTexture.h" +#include "GLUtils.h" #include "ShaderProgram.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 viewport[4]; GLboolean scissor[1]; @@ -43,7 +47,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 @@ -69,8 +73,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) @@ -84,8 +88,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 @@ -113,7 +117,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); @@ -143,7 +147,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; @@ -170,8 +174,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); @@ -191,7 +195,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/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..42d68a0 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); } 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/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/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/WebKit/android/RenderSkinMediaButton.cpp b/Source/WebKit/android/RenderSkinMediaButton.cpp index febf575..b3aa57d 100644 --- a/Source/WebKit/android/RenderSkinMediaButton.cpp +++ b/Source/WebKit/android/RenderSkinMediaButton.cpp @@ -95,6 +95,9 @@ void RenderSkinMediaButton::Draw(SkCanvas* canvas, const IntRect& r, int buttonT Decode(); } + if (!canvas) + return; + // If we failed to decode, do nothing. This way the browser still works, // and webkit will still draw the label and layout space for us. if (gDecodingFailed) diff --git a/Source/WebKit/android/RenderSkinNinePatch.cpp b/Source/WebKit/android/RenderSkinNinePatch.cpp index ec748f7..9ef0b4a 100644 --- a/Source/WebKit/android/RenderSkinNinePatch.cpp +++ b/Source/WebKit/android/RenderSkinNinePatch.cpp @@ -73,7 +73,7 @@ bool RenderSkinNinePatch::decodeAsset(AssetManager* am, const char* filename, Ni } asset->close(); - if (!peeker.fPatchIsValid) { + if (!peeker.fPatch) { ALOGE("RenderSkinNinePatch::Patch data not valid"); return false; } diff --git a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp index 5e16152..c10f5b3 100644 --- a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp +++ b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp @@ -95,7 +95,7 @@ void ChromeClientAndroid::scheduleCompositingLayerSync() m_needsLayerSync = true; WebViewCore* webViewCore = WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view()); if (webViewCore) - webViewCore->layersDraw(); + webViewCore->contentDraw(); } void ChromeClientAndroid::setNeedsOneShotDrawingSynchronization() @@ -238,11 +238,7 @@ void ChromeClientAndroid::addMessageToConsole(MessageSource, MessageType, Messag android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->addMessageToConsole(message, lineNumber, sourceID, msgLevel); } -void ChromeClientAndroid::formDidBlur(const WebCore::Node* node) -{ - android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->formDidBlur(node); -} - +void ChromeClientAndroid::formDidBlur(const WebCore::Node* node) { notImplemented(); } bool ChromeClientAndroid::canRunBeforeUnloadConfirmPanel() { return true; } bool ChromeClientAndroid::runBeforeUnloadConfirmPanel(const String& message, Frame* frame) { String url = frame->document()->documentURI(); diff --git a/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp b/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp index 95ced96..52aeb23 100644 --- a/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp +++ b/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp @@ -264,7 +264,9 @@ public: if (!m_poster || (!m_poster->getPixels() && !m_poster->pixelRef())) return; - SkCanvas* canvas = ctxt->platformContext()->mCanvas; + SkCanvas* canvas = ctxt->platformContext()->getCanvas(); + if (!canvas) + return; // We paint with the following rules in mind: // - only downscale the poster, never upscale // - maintain the natural aspect ratio of the poster diff --git a/Source/WebKit/android/WebCoreSupport/UrlInterceptResponse.cpp b/Source/WebKit/android/WebCoreSupport/UrlInterceptResponse.cpp index 77e3c32..d846daf 100644 --- a/Source/WebKit/android/WebCoreSupport/UrlInterceptResponse.cpp +++ b/Source/WebKit/android/WebCoreSupport/UrlInterceptResponse.cpp @@ -30,6 +30,7 @@ #include "UrlInterceptResponse.h" #include "WebCoreJni.h" +#include <ScopedLocalRef.h> #include <utils/Log.h> namespace android { @@ -38,15 +39,14 @@ class JavaInputStreamWrapper { public: JavaInputStreamWrapper(JNIEnv* env, jobject inputStream) : m_inputStream(env->NewGlobalRef(inputStream)) - , m_buffer(0) { - LOG_ALWAYS_FATAL_IF(!inputStream); - jclass inputStreamClass = env->FindClass("java/io/InputStream"); - LOG_ALWAYS_FATAL_IF(!inputStreamClass); - m_read = env->GetMethodID(inputStreamClass, "read", "([B)I"); + , m_buffer(NULL) { + LOG_ALWAYS_FATAL_IF(!m_inputStream); + ScopedLocalRef<jclass> inputStreamClass(env, env->FindClass("java/io/InputStream")); + LOG_ALWAYS_FATAL_IF(!inputStreamClass.get()); + m_read = env->GetMethodID(inputStreamClass.get(), "read", "([B)I"); LOG_ALWAYS_FATAL_IF(!m_read); - m_close = env->GetMethodID(inputStreamClass, "close", "()V"); + m_close = env->GetMethodID(inputStreamClass.get(), "close", "()V"); LOG_ALWAYS_FATAL_IF(!m_close); - env->DeleteLocalRef(inputStreamClass); } ~JavaInputStreamWrapper() { @@ -63,10 +63,10 @@ public: JNIEnv* env = JSC::Bindings::getJNIEnv(); // Initialize our read buffer to the capacity of out. if (!m_buffer) { - m_buffer = env->NewByteArray(out->capacity()); - m_buffer = (jbyteArray) env->NewGlobalRef(m_buffer); + ScopedLocalRef<jbyteArray> buffer_local(env, env->NewByteArray(out->capacity())); + m_buffer = static_cast<jbyteArray>(env->NewGlobalRef(buffer_local.get())); } - int size = (int) env->CallIntMethod(m_inputStream, m_read, m_buffer); + int size = env->CallIntMethod(m_inputStream, m_read, m_buffer); if (checkException(env) || size < 0) return; // Copy from m_buffer to out. @@ -82,40 +82,32 @@ private: }; UrlInterceptResponse::UrlInterceptResponse(JNIEnv* env, jobject response) { - jclass javaResponse = env->FindClass("android/webkit/WebResourceResponse"); - LOG_ALWAYS_FATAL_IF(!javaResponse); - jfieldID mimeType = env->GetFieldID(javaResponse, "mMimeType", - "Ljava/lang/String;"); + ScopedLocalRef<jclass> javaResponse(env, env->FindClass("android/webkit/WebResourceResponse")); + LOG_ALWAYS_FATAL_IF(!javaResponse.get()); + jfieldID mimeType = env->GetFieldID(javaResponse.get(), "mMimeType", "Ljava/lang/String;"); LOG_ALWAYS_FATAL_IF(!mimeType); - jfieldID encoding = env->GetFieldID(javaResponse, "mEncoding", - "Ljava/lang/String;"); + jfieldID encoding = env->GetFieldID(javaResponse.get(), "mEncoding", "Ljava/lang/String;"); LOG_ALWAYS_FATAL_IF(!encoding); - jfieldID inputStream = env->GetFieldID(javaResponse, "mInputStream", - "Ljava/io/InputStream;"); + jfieldID inputStream = env->GetFieldID(javaResponse.get(), "mInputStream", "Ljava/io/InputStream;"); LOG_ALWAYS_FATAL_IF(!inputStream); - jobject stream = env->GetObjectField(response, inputStream); - if (stream) - m_inputStream.set(new JavaInputStreamWrapper(env, stream)); + ScopedLocalRef<jobject> stream(env, env->GetObjectField(response, inputStream)); + if (stream.get()) + m_inputStream.set(new JavaInputStreamWrapper(env, stream.get())); - jstring mimeStr = (jstring) env->GetObjectField(response, mimeType); - jstring encodingStr = (jstring) env->GetObjectField(response, encoding); + ScopedLocalRef<jstring> mimeStr(env, static_cast<jstring>(env->GetObjectField(response, mimeType))); + ScopedLocalRef<jstring> encodingStr(env, static_cast<jstring>(env->GetObjectField(response, encoding))); - if (mimeStr) { - const char* s = env->GetStringUTFChars(mimeStr, NULL); - m_mimeType.assign(s, env->GetStringUTFLength(mimeStr)); - env->ReleaseStringUTFChars(mimeStr, s); + if (mimeStr.get()) { + const char* s = env->GetStringUTFChars(mimeStr.get(), NULL); + m_mimeType.assign(s, env->GetStringUTFLength(mimeStr.get())); + env->ReleaseStringUTFChars(mimeStr.get(), s); } - if (encodingStr) { - const char* s = env->GetStringUTFChars(encodingStr, NULL); - m_encoding.assign(s, env->GetStringUTFLength(encodingStr)); - env->ReleaseStringUTFChars(encodingStr, s); + if (encodingStr.get()) { + const char* s = env->GetStringUTFChars(encodingStr.get(), NULL); + m_encoding.assign(s, env->GetStringUTFLength(encodingStr.get())); + env->ReleaseStringUTFChars(encodingStr.get(), s); } - - env->DeleteLocalRef(javaResponse); - env->DeleteLocalRef(stream); - env->DeleteLocalRef(mimeStr); - env->DeleteLocalRef(encodingStr); } UrlInterceptResponse::~UrlInterceptResponse() { diff --git a/Source/WebKit/android/jni/PictureSet.cpp b/Source/WebKit/android/jni/PictureSet.cpp index f3534eb..8beb0ef 100644 --- a/Source/WebKit/android/jni/PictureSet.cpp +++ b/Source/WebKit/android/jni/PictureSet.cpp @@ -38,6 +38,8 @@ #include "SkRegion.h" #include "SkStream.h" +#include "PlatformGraphicsContext.h" + #define MAX_DRAW_TIME 100 #define MIN_SPLITTABLE 400 #define MAX_ADDITIONAL_AREA 0.65 @@ -133,6 +135,9 @@ void PictureSet::add(const Pictures* temp) { Pictures pictureAndBounds = *temp; SkSafeRef(pictureAndBounds.mPicture); +#ifdef CONTEXT_RECORDING + SkSafeRef(pictureAndBounds.mGraphicsOperationCollection); +#endif pictureAndBounds.mWroteElapsed = false; mPictures.append(pictureAndBounds); } @@ -478,13 +483,20 @@ void PictureSet::add(const SkIRect& area, uint32_t elapsed, bool split, bool emp working->mArea.setEmpty(); SkSafeUnref(working->mPicture); working->mPicture = 0; +#ifdef CONTEXT_RECORDING + SkSafeUnref(working->mGraphicsOperationCollection); + working->mGraphicsOperationCollection = 0; +#endif } } // Now we can add the new Picture to the list, with the correct area // that need to be repainted - Pictures pictureAndBounds = {totalArea, 0, totalArea, - elapsed, split, false, false, empty}; + Pictures pictureAndBounds = {totalArea, 0, +#ifdef CONTEXT_RECORDING + 0, +#endif + totalArea, elapsed, split, false, false, empty}; #ifdef FAST_PICTURESET if (mPictures.size() == 0) @@ -525,6 +537,10 @@ void PictureSet::add(const SkIRect& area, uint32_t elapsed, bool split, bool emp working->mArea.setEmpty(); SkSafeUnref(working->mPicture); working->mPicture = 0; +#ifdef CONTEXT_RECORDING + SkSafeUnref(working->mGraphicsOperationCollection); + working->mGraphicsOperationCollection = 0; +#endif } } @@ -677,6 +693,9 @@ void PictureSet::clear() for (Pictures* working = mPictures.begin(); working != last; working++) { working->mArea.setEmpty(); SkSafeUnref(working->mPicture); +#ifdef CONTEXT_RECORDING + SkSafeUnref(working->mGraphicsOperationCollection); +#endif } mPictures.clear(); #endif // FAST_PICTURESET @@ -797,7 +816,14 @@ bool PictureSet::draw(SkCanvas* canvas) canvas->translate(pathBounds.fLeft, pathBounds.fTop); canvas->save(); uint32_t startTime = getThreadMsec(); + +#ifdef CONTEXT_RECORDING + WebCore::PlatformGraphicsContextSkia context(canvas); + working->mGraphicsOperationCollection->apply(&context); +#else canvas->drawPicture(*working->mPicture); +#endif + size_t elapsed = working->mElapsed = getThreadMsec() - startTime; working->mWroteElapsed = true; if (maxElapsed < elapsed && (pathBounds.width() >= MIN_SPLITTABLE || @@ -1060,6 +1086,14 @@ void PictureSet::setPicture(size_t i, SkPicture* p) mPictures[i].mEmpty = emptyPicture(p); } +#ifdef CONTEXT_RECORDING +void PictureSet::setGraphicsOperationCollection(size_t i, WebCore::GraphicsOperationCollection* p) +{ + SkSafeUnref(mPictures[i].mGraphicsOperationCollection); + mPictures[i].mGraphicsOperationCollection = p; +} +#endif + void PictureSet::split(PictureSet* out) const { dump(__FUNCTION__); diff --git a/Source/WebKit/android/jni/PictureSet.h b/Source/WebKit/android/jni/PictureSet.h index 1d9a14d..1e639da 100644 --- a/Source/WebKit/android/jni/PictureSet.h +++ b/Source/WebKit/android/jni/PictureSet.h @@ -45,7 +45,10 @@ #include <wtf/Vector.h> #include <wtf/HashMap.h> +#include "GraphicsOperationCollection.h" + // #define FAST_PICTURESET // use a hierarchy of pictures +// #define CONTEXT_RECORDING // use the new PlatformGraphicsContextRecording class SkCanvas; class SkPicture; @@ -100,6 +103,9 @@ namespace android { const SkIRect& bounds(size_t i) const { return mPictures[i].mArea; } void setPicture(size_t i, SkPicture* p); +#ifdef CONTEXT_RECORDING + void setGraphicsOperationCollection(size_t i, WebCore::GraphicsOperationCollection* p); +#endif void setDrawTimes(const PictureSet& ); size_t size() const { return mPictures.size(); } void split(PictureSet* result) const; @@ -119,9 +125,13 @@ namespace android { int mBucketCountX; int mBucketCountY; #else + struct Pictures { SkIRect mArea; SkPicture* mPicture; +#ifdef CONTEXT_RECORDING + WebCore::GraphicsOperationCollection* mGraphicsOperationCollection; +#endif SkIRect mUnsplit; uint32_t mElapsed; bool mSplit : 8; diff --git a/Source/WebKit/android/jni/ViewStateSerializer.cpp b/Source/WebKit/android/jni/ViewStateSerializer.cpp index bfce349..3fdc3e6 100644 --- a/Source/WebKit/android/jni/ViewStateSerializer.cpp +++ b/Source/WebKit/android/jni/ViewStateSerializer.cpp @@ -40,6 +40,7 @@ #include "PictureLayerContent.h" #include "PictureSet.h" #include "ScrollableLayerAndroid.h" +#include "SkFlattenable.h" #include "SkPicture.h" #include "TilesManager.h" diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp index d0f3830..7a2971a 100644 --- a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -316,7 +316,6 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* ALOG_ASSERT(mJavaFrame->mAutoLogin, "Could not find method autoLogin"); mUserAgent = WTF::String(); - mUserInitiatedAction = false; mBlockNetworkLoads = false; m_renderSkins = 0; } diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.h b/Source/WebKit/android/jni/WebCoreFrameBridge.h index 13f99af..30c1d83 100644 --- a/Source/WebKit/android/jni/WebCoreFrameBridge.h +++ b/Source/WebKit/android/jni/WebCoreFrameBridge.h @@ -128,13 +128,6 @@ class WebFrame : public WebCoreRefObject { // application. void autoLogin(const std::string& loginHeader); - /** - * When the user initiates a click, we set mUserInitiatedAction to true. - * If a load happens due to this click, then we ask the application if it wants - * to override the load. Otherwise, we attempt to load the resource internally. - */ - void setUserInitiatedAction(bool userInitiatedAction) { mUserInitiatedAction = userInitiatedAction; } - WebCore::Page* page() const { return mPage; } // Currently used only by the chrome net stack. A similar field is used by @@ -163,7 +156,6 @@ class WebFrame : public WebCoreRefObject { WebCore::Page* mPage; WTF::String mUserAgent; bool mBlockNetworkLoads; - bool mUserInitiatedAction; WebCore::RenderSkinAndroid* m_renderSkins; }; diff --git a/Source/WebKit/android/jni/WebCoreJni.cpp b/Source/WebKit/android/jni/WebCoreJni.cpp index 6dfc9f1..72ded59 100644 --- a/Source/WebKit/android/jni/WebCoreJni.cpp +++ b/Source/WebKit/android/jni/WebCoreJni.cpp @@ -118,8 +118,10 @@ jobject intRectToRect(JNIEnv* env, const WebCore::IntRect& rect) ALOG_ASSERT(rectClass, "Could not find android/graphics/Rect"); jmethodID rectInit = env->GetMethodID(rectClass, "<init>", "(IIII)V"); ALOG_ASSERT(rectInit, "Could not find init method on Rect"); - return env->NewObject(rectClass, rectInit, rect.x(), rect.y(), + jobject jrect = env->NewObject(rectClass, rectInit, rect.x(), rect.y(), rect.maxX(), rect.maxY()); + env->DeleteLocalRef(rectClass); + return jrect; } jobjectArray intRectVectorToRectArray(JNIEnv* env, Vector<WebCore::IntRect>& rects) diff --git a/Source/WebKit/android/jni/WebFrameView.cpp b/Source/WebKit/android/jni/WebFrameView.cpp index f30e5b7..10e31dc 100644 --- a/Source/WebKit/android/jni/WebFrameView.cpp +++ b/Source/WebKit/android/jni/WebFrameView.cpp @@ -61,7 +61,7 @@ void WebFrameView::draw(WebCore::GraphicsContext* gc, const WebCore::IntRect& re mFrameView->paintContents(gc, rect); else { // FIXME: I'm not entirely sure this ever happens or is needed - gc->setFillColor(Color::white, ColorSpaceDeviceRGB); + gc->setFillColor(WebCore::Color::white, WebCore::ColorSpaceDeviceRGB); gc->fillRect(rect); } } diff --git a/Source/WebKit/android/jni/WebSettings.cpp b/Source/WebKit/android/jni/WebSettings.cpp index 65ac360..cec44c1 100644 --- a/Source/WebKit/android/jni/WebSettings.cpp +++ b/Source/WebKit/android/jni/WebSettings.cpp @@ -118,6 +118,9 @@ struct FieldIds { mGeolocationEnabled = env->GetFieldID(clazz, "mGeolocationEnabled", "Z"); mGeolocationDatabasePath = env->GetFieldID(clazz, "mGeolocationDatabasePath", "Ljava/lang/String;"); mXSSAuditorEnabled = env->GetFieldID(clazz, "mXSSAuditorEnabled", "Z"); +#if ENABLE(LINK_PREFETCH) + mLinkPrefetchEnabled = env->GetFieldID(clazz, "mLinkPrefetchEnabled", "Z"); +#endif mJavaScriptCanOpenWindowsAutomatically = env->GetFieldID(clazz, "mJavaScriptCanOpenWindowsAutomatically", "Z"); mUseWideViewport = env->GetFieldID(clazz, "mUseWideViewport", "Z"); @@ -245,6 +248,9 @@ struct FieldIds { jfieldID mGeolocationEnabled; jfieldID mGeolocationDatabasePath; jfieldID mXSSAuditorEnabled; +#if ENABLE(LINK_PREFETCH) + jfieldID mLinkPrefetchEnabled; +#endif #if ENABLE(DATABASE) || ENABLE(DOM_STORAGE) jfieldID mDatabasePath; jfieldID mDatabasePathHasBeenSet; @@ -545,6 +551,11 @@ public: flag = env->GetBooleanField(obj, gFieldIds->mXSSAuditorEnabled); s->setXSSAuditorEnabled(flag); +#if ENABLE(LINK_PREFETCH) + flag = env->GetBooleanField(obj, gFieldIds->mLinkPrefetchEnabled); + s->setLinkPrefetchEnabled(flag); +#endif + size = env->GetIntField(obj, gFieldIds->mPageCacheCapacity); if (size > 0) { s->setUsesPageCache(true); diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index bb76c80..cdd484b 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -62,6 +62,7 @@ #include "Geolocation.h" #include "GraphicsContext.h" #include "GraphicsJNI.h" +#include "GraphicsOperationCollection.h" #include "HTMLAnchorElement.h" #include "HTMLAreaElement.h" #include "HTMLElement.h" @@ -107,6 +108,7 @@ #include "ResourceRequest.h" #include "RuntimeEnabledFeatures.h" #include "SchemeRegistry.h" +#include "ScopedLocalRef.h" #include "ScriptController.h" #include "SelectionController.h" #include "SelectText.h" @@ -322,7 +324,6 @@ struct WebViewCore::JavaGlue { jweak m_obj; jmethodID m_scrollTo; jmethodID m_contentDraw; - jmethodID m_layersDraw; jmethodID m_requestListBox; jmethodID m_openFileChooser; jmethodID m_requestSingleListBox; @@ -351,7 +352,6 @@ struct WebViewCore::JavaGlue { jmethodID m_getDeviceMotionService; jmethodID m_getDeviceOrientationService; jmethodID m_addMessageToConsole; - jmethodID m_formDidBlur; jmethodID m_focusNodeChanged; jmethodID m_getPluginClass; jmethodID m_showFullScreenPlugin; @@ -371,7 +371,6 @@ struct WebViewCore::JavaGlue { jmethodID m_setWebTextViewAutoFillable; jmethodID m_selectAt; jmethodID m_initEditField; - jmethodID m_updateMatchCount; jmethodID m_chromeCanTakeFocus; jmethodID m_chromeTakeFocus; AutoJObject object(JNIEnv* env) { @@ -398,7 +397,7 @@ struct WebViewCore::TextFieldInitDataGlue { jfieldID m_name; jfieldID m_label; jfieldID m_maxLength; - jfieldID m_nodeBounds; + jfieldID m_contentBounds; jfieldID m_nodeLayerId; jfieldID m_contentRect; }; @@ -421,7 +420,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m , m_textFieldInitDataGlue(new TextFieldInitDataGlue) , m_mainFrame(mainframe) , m_popupReply(0) - , m_blurringNodePointer(0) , m_blockTextfieldUpdates(false) , m_focusBoundsChanged(false) , m_skipContentDraw(false) @@ -458,7 +456,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_javaGlue->m_obj = env->NewWeakGlobalRef(javaWebViewCore); m_javaGlue->m_scrollTo = GetJMethod(env, clazz, "contentScrollTo", "(IIZZ)V"); m_javaGlue->m_contentDraw = GetJMethod(env, clazz, "contentDraw", "()V"); - m_javaGlue->m_layersDraw = GetJMethod(env, clazz, "layersDraw", "()V"); m_javaGlue->m_requestListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[I[I)V"); m_javaGlue->m_openFileChooser = GetJMethod(env, clazz, "openFileChooser", "(Ljava/lang/String;)Ljava/lang/String;"); m_javaGlue->m_requestSingleListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[II)V"); @@ -487,7 +484,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_javaGlue->m_getDeviceMotionService = GetJMethod(env, clazz, "getDeviceMotionService", "()Landroid/webkit/DeviceMotionService;"); m_javaGlue->m_getDeviceOrientationService = GetJMethod(env, clazz, "getDeviceOrientationService", "()Landroid/webkit/DeviceOrientationService;"); m_javaGlue->m_addMessageToConsole = GetJMethod(env, clazz, "addMessageToConsole", "(Ljava/lang/String;ILjava/lang/String;I)V"); - m_javaGlue->m_formDidBlur = GetJMethod(env, clazz, "formDidBlur", "(I)V"); m_javaGlue->m_focusNodeChanged = GetJMethod(env, clazz, "focusNodeChanged", "(ILandroid/webkit/WebViewCore$WebKitHitTest;)V"); m_javaGlue->m_getPluginClass = GetJMethod(env, clazz, "getPluginClass", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Class;"); m_javaGlue->m_showFullScreenPlugin = GetJMethod(env, clazz, "showFullScreenPlugin", "(Landroid/webkit/ViewManager$ChildView;II)V"); @@ -509,7 +505,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_javaGlue->m_setWebTextViewAutoFillable = GetJMethod(env, clazz, "setWebTextViewAutoFillable", "(ILjava/lang/String;)V"); m_javaGlue->m_selectAt = GetJMethod(env, clazz, "selectAt", "(II)V"); m_javaGlue->m_initEditField = GetJMethod(env, clazz, "initEditField", "(IIILandroid/webkit/WebViewCore$TextFieldInitData;)V"); - m_javaGlue->m_updateMatchCount = GetJMethod(env, clazz, "updateMatchCount", "(IILjava/lang/String;)V"); m_javaGlue->m_chromeCanTakeFocus = GetJMethod(env, clazz, "chromeCanTakeFocus", "(I)Z"); m_javaGlue->m_chromeTakeFocus = GetJMethod(env, clazz, "chromeTakeFocus", "(I)V"); env->DeleteLocalRef(clazz); @@ -527,7 +522,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_textFieldInitDataGlue->m_name = env->GetFieldID(tfidClazz, "mName", "Ljava/lang/String;"); m_textFieldInitDataGlue->m_label = env->GetFieldID(tfidClazz, "mLabel", "Ljava/lang/String;"); m_textFieldInitDataGlue->m_maxLength = env->GetFieldID(tfidClazz, "mMaxLength", "I"); - m_textFieldInitDataGlue->m_nodeBounds = env->GetFieldID(tfidClazz, "mNodeBounds", "Landroid/graphics/Rect;"); + m_textFieldInitDataGlue->m_contentBounds = env->GetFieldID(tfidClazz, "mContentBounds", "Landroid/graphics/Rect;"); m_textFieldInitDataGlue->m_nodeLayerId = env->GetFieldID(tfidClazz, "mNodeLayerId", "I"); m_textFieldInitDataGlue->m_contentRect = env->GetFieldID(tfidClazz, "mContentRect", "Landroid/graphics/Rect;"); m_textFieldInitDataGlue->m_constructor = GetJMethod(env, tfidClazz, "<init>", "()V"); @@ -790,7 +785,7 @@ SkPicture* WebViewCore::rebuildPicture(const SkIRect& inval) SkAutoMemoryUsageProbe mup(__FUNCTION__); SkCanvas* recordingCanvas = arp.getRecordingCanvas(); - WebCore::PlatformGraphicsContext pgc(recordingCanvas); + WebCore::PlatformGraphicsContextSkia pgc(recordingCanvas); WebCore::GraphicsContext gc(&pgc); IntPoint origin = view->minimumScrollPosition(); WebCore::IntRect drawArea(inval.fLeft + origin.x(), inval.fTop + origin.y(), @@ -806,6 +801,27 @@ SkPicture* WebViewCore::rebuildPicture(const SkIRect& inval) return picture; } +#ifdef CONTEXT_RECORDING +GraphicsOperationCollection* WebViewCore::rebuildGraphicsOperationCollection(const SkIRect& inval) +{ + WebCore::FrameView* view = m_mainFrame->view(); + int width = view->contentsWidth(); + int height = view->contentsHeight(); + + IntPoint origin = view->minimumScrollPosition(); + WebCore::IntRect drawArea(inval.fLeft + origin.x(), inval.fTop + origin.y(), + inval.width(), inval.height()); + + AutoGraphicsOperationCollection autoPicture(drawArea); + view->platformWidget()->draw(autoPicture.context(), drawArea); + + m_rebuildInval.op(inval, SkRegion::kUnion_Op); + + SkSafeRef(autoPicture.picture()); + return autoPicture.picture(); +} +#endif + void WebViewCore::rebuildPictureSet(PictureSet* pictureSet) { #ifdef FAST_PICTURESET @@ -831,24 +847,16 @@ void WebViewCore::rebuildPictureSet(PictureSet* pictureSet) DBG_SET_LOGD("pictSet=%p [%d] {%d,%d,w=%d,h=%d}", pictureSet, index, inval.fLeft, inval.fTop, inval.width(), inval.height()); pictureSet->setPicture(index, rebuildPicture(inval)); +#ifdef CONTEXT_RECORDING + pictureSet->setGraphicsOperationCollection(index, + rebuildGraphicsOperationCollection(inval)); +#endif } pictureSet->validate(__FUNCTION__); #endif } -bool WebViewCore::updateLayers(LayerAndroid* layers) -{ - // We update the layers - ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client()); - GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync()); - if (root) { - LayerAndroid* updatedLayer = root->contentLayer(); - return layers->updateWithTree(updatedLayer); - } - return true; -} - void WebViewCore::notifyAnimationStarted() { // We notify webkit that the animations have begun @@ -874,16 +882,25 @@ BaseLayerAndroid* WebViewCore::createBaseLayer(SkRegion* region) #if USE(ACCELERATED_COMPOSITING) // We set the background color + Color background = Color::white; if (m_mainFrame && m_mainFrame->document() && m_mainFrame->document()->body()) { + bool hasCSSBackground = false; + Document* document = m_mainFrame->document(); RefPtr<RenderStyle> style = document->styleForElementIgnoringPendingStylesheets(document->body()); if (style->hasBackground()) { - Color color = style->visitedDependentColor(CSSPropertyBackgroundColor); - if (color.isValid() && color.alpha() > 0) - base->setBackgroundColor(color); + background = style->visitedDependentColor(CSSPropertyBackgroundColor); + hasCSSBackground = true; + } + + WebCore::FrameView* view = m_mainFrame->view(); + if (view) { + Color viewBackground = view->baseBackgroundColor(); + background = hasCSSBackground ? viewBackground.blend(background) : viewBackground; } } + base->setBackgroundColor(background); // We update the layers ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client()); @@ -990,16 +1007,6 @@ void WebViewCore::contentDraw() checkException(env); } -void WebViewCore::layersDraw() -{ - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject javaObject = m_javaGlue->object(env); - if (!javaObject.get()) - return; - env->CallVoidMethod(javaObject.get(), m_javaGlue->m_layersDraw); - checkException(env); -} - void WebViewCore::contentInvalidate(const WebCore::IntRect &r) { DBG_SET_LOGD("rect={%d,%d,w=%d,h=%d}", r.x(), r.y(), r.width(), r.height()); @@ -1619,7 +1626,7 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) RenderText* renderText = toRenderText(r); int caretOffset; InlineBox* inlineBox; - start.getInlineBoxAndOffset(DOWNSTREAM, inlineBox, caretOffset); + start.getInlineBoxAndOffset(selection.affinity(), inlineBox, caretOffset); startHandle = renderText->localCaretRect(inlineBox, caretOffset); FloatPoint absoluteOffset = renderText->localToAbsolute(startHandle.location()); startHandle.setX(absoluteOffset.x() - layerOffset.x()); @@ -1667,10 +1674,50 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) selectTextContainer->setCaretRect(SelectText::EndHandle, endHandle); selectTextContainer->setText(range->text()); + selectTextContainer->setTextRect(SelectText::StartHandle, + positionToTextRect(selection.start(), selection.affinity())); + selectTextContainer->setTextRect(SelectText::EndHandle, + positionToTextRect(selection.end(), selection.affinity())); return selectTextContainer; } +IntRect WebViewCore::positionToTextRect(const Position& position, EAffinity affinity) +{ + IntRect textRect; + InlineBox* inlineBox; + int offset; + position.getInlineBoxAndOffset(affinity, inlineBox, offset); + if (inlineBox && inlineBox->isInlineTextBox()) { + InlineTextBox* box = static_cast<InlineTextBox*>(inlineBox); + RootInlineBox* root = box->root(); + RenderText* renderText = box->textRenderer(); + int left = root->logicalLeft(); + int width = root->logicalWidth(); + int top = root->selectionTop(); + int height = root->selectionHeight(); + + Node* node = position.anchorNode(); + LayerAndroid* layer = 0; + int layerId = platformLayerIdFromNode(node, &layer); + IntPoint layerOffset; + layerToAbsoluteOffset(layer, layerOffset); + + if (!renderText->style()->isHorizontalWritingMode()) { + swap(left, top); + swap(width, height); + } + FloatPoint origin(left, top); + FloatPoint absoluteOrigin = renderText->localToAbsolute(origin); + + textRect.setX(absoluteOrigin.x() - layerOffset.x()); + textRect.setWidth(width); + textRect.setY(absoluteOrigin.y() - layerOffset.y()); + textRect.setHeight(height); + } + return textRect; +} + IntPoint WebViewCore::convertGlobalContentToFrameContent(const IntPoint& point, WebCore::Frame* frame) { if (!frame) frame = focusedFrame(); @@ -2890,17 +2937,17 @@ void WebViewCore::passToJs(int generation, const WTF::String& current, updateTextSelection(); } -void WebViewCore::scrollFocusedTextInput(float xPercent, int y) +WebCore::IntRect WebViewCore::scrollFocusedTextInput(float xPercent, int y) { WebCore::Node* focus = currentFocus(); if (!focus) { clearTextEntry(); - return; + return WebCore::IntRect(); } WebCore::RenderTextControl* renderText = toRenderTextControl(focus); if (!renderText) { clearTextEntry(); - return; + return WebCore::IntRect(); } int x = (int) (xPercent * (renderText->scrollWidth() - @@ -2908,6 +2955,9 @@ void WebViewCore::scrollFocusedTextInput(float xPercent, int y) renderText->setScrollLeft(x); renderText->setScrollTop(y); focus->document()->frame()->selection()->recomputeCaretRect(); + LayerAndroid* layer = 0; + platformLayerIdFromNode(focus, &layer); + return absoluteContentRect(focus, layer); } void WebViewCore::setFocusControllerActive(bool active) @@ -3215,6 +3265,23 @@ void WebViewCore::touchUp(int touchGeneration, handleMouseClick(frame, node, false); } +bool WebViewCore::performMouseClick() +{ + WebCore::PlatformMouseEvent mouseDown(m_mousePos, m_mousePos, WebCore::LeftButton, + WebCore::MouseEventPressed, 1, false, false, false, false, + WTF::currentTime()); + // ignore the return from as it will return true if the hit point can trigger selection change + m_mainFrame->eventHandler()->handleMousePressEvent(mouseDown); + WebCore::PlatformMouseEvent mouseUp(m_mousePos, m_mousePos, WebCore::LeftButton, + WebCore::MouseEventReleased, 1, false, false, false, false, + WTF::currentTime()); + bool handled = m_mainFrame->eventHandler()->handleMouseReleaseEvent(mouseUp); + + WebCore::Node* focusNode = currentFocus(); + initializeTextInput(focusNode, false); + return handled; +} + // Check for the "x-webkit-soft-keyboard" attribute. If it is there and // set to hidden, do not show the soft keyboard. Node passed as a parameter // must not be null. @@ -3242,15 +3309,12 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node // Need to special case area tags because an image map could have an area element in the middle // so when attempting to get the default, the point chosen would be follow the wrong link. if (nodePtr->hasTagName(WebCore::HTMLNames::areaTag)) { - webFrame->setUserInitiatedAction(true); nodePtr->dispatchSimulatedClick(0, true, true); - webFrame->setUserInitiatedAction(false); return true; } } if (!valid || !framePtr) framePtr = m_mainFrame; - webFrame->setUserInitiatedAction(true); WebCore::PlatformMouseEvent mouseDown(m_mousePos, m_mousePos, WebCore::LeftButton, WebCore::MouseEventPressed, 1, false, false, false, false, WTF::currentTime()); @@ -3260,7 +3324,6 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node WebCore::MouseEventReleased, 1, false, false, false, false, WTF::currentTime()); bool handled = framePtr->eventHandler()->handleMouseReleaseEvent(mouseUp); - webFrame->setUserInitiatedAction(false); WebCore::Node* focusNode = currentFocus(); initializeTextInput(focusNode, fake); @@ -3337,34 +3400,37 @@ bool WebViewCore::isAutoCompleteEnabled(Node* node) return isEnabled; } -WebCore::IntRect WebViewCore::boundingRect(WebCore::Node* node, +WebCore::IntRect WebViewCore::absoluteContentRect(WebCore::Node* node, LayerAndroid* layer) { - // Caret selection - IntRect boundingRect; + IntRect contentRect; if (node) { RenderObject* render = node->renderer(); - if (render && !render->isBody()) { + if (render && render->isBox() && !render->isBody()) { IntPoint offset = convertGlobalContentToFrameContent(IntPoint(), node->document()->frame()); WebViewCore::layerToAbsoluteOffset(layer, offset); - boundingRect = render->absoluteBoundingBoxRect(true); - boundingRect.move(-offset.x(), -offset.y()); + + RenderBox* renderBox = toRenderBox(render); + contentRect = renderBox->absoluteContentBox(); + contentRect.move(-offset.x(), -offset.y()); } } - return boundingRect; + return contentRect; } jobject WebViewCore::createTextFieldInitData(Node* node) { JNIEnv* env = JSC::Bindings::getJNIEnv(); TextFieldInitDataGlue* classDef = m_textFieldInitDataGlue; - jclass clazz = env->FindClass("android/webkit/WebViewCore$TextFieldInitData"); - jobject initData = env->NewObject(clazz, classDef->m_constructor); + ScopedLocalRef<jclass> clazz(env, + env->FindClass("android/webkit/WebViewCore$TextFieldInitData")); + jobject initData = env->NewObject(clazz.get(), classDef->m_constructor); env->SetIntField(initData, classDef->m_fieldPointer, reinterpret_cast<int>(node)); - env->SetObjectField(initData, classDef->m_text, + ScopedLocalRef<jstring> inputText(env, wtfStringToJstring(env, getInputText(node), true)); + env->SetObjectField(initData, classDef->m_text, inputText.get()); env->SetIntField(initData, classDef->m_type, getInputType(node)); env->SetBooleanField(initData, classDef->m_isSpellCheckEnabled, isSpellCheckEnabled(node)); @@ -3378,16 +3444,18 @@ jobject WebViewCore::createTextFieldInitData(Node* node) isTextInput(document->previousFocusableNode(node, tabEvent.get()))); env->SetBooleanField(initData, classDef->m_isAutoCompleteEnabled, isAutoCompleteEnabled(node)); - env->SetObjectField(initData, classDef->m_name, + ScopedLocalRef<jstring> fieldName(env, wtfStringToJstring(env, getFieldName(node), false)); - env->SetObjectField(initData, classDef->m_name, + env->SetObjectField(initData, classDef->m_name, fieldName.get()); + ScopedLocalRef<jstring> label(env, wtfStringToJstring(env, requestLabel(document->frame(), node), false)); + env->SetObjectField(initData, classDef->m_name, label.get()); env->SetIntField(initData, classDef->m_maxLength, getMaxLength(node)); LayerAndroid* layer = 0; int layerId = platformLayerIdFromNode(node, &layer); - IntRect bounds = boundingRect(node, layer); - env->SetObjectField(initData, classDef->m_nodeBounds, - intRectToRect(env, bounds)); + IntRect bounds = absoluteContentRect(node, layer); + ScopedLocalRef<jobject> jbounds(env, intRectToRect(env, bounds)); + env->SetObjectField(initData, classDef->m_contentBounds, jbounds.get()); env->SetIntField(initData, classDef->m_nodeLayerId, layerId); IntRect contentRect; RenderTextControl* rtc = toRenderTextControl(node); @@ -3396,8 +3464,8 @@ jobject WebViewCore::createTextFieldInitData(Node* node) contentRect.setHeight(rtc->scrollHeight()); contentRect.move(-rtc->scrollLeft(), -rtc->scrollTop()); } - env->SetObjectField(initData, classDef->m_contentRect, - intRectToRect(env, contentRect)); + ScopedLocalRef<jobject> jcontentRect(env, intRectToRect(env, contentRect)); + env->SetObjectField(initData, classDef->m_contentRect, jcontentRect.get()); return initData; } @@ -3412,9 +3480,9 @@ void WebViewCore::initEditField(Node* node) int end = 0; getSelectionOffsets(node, start, end); SelectText* selectText = createSelectText(focusedFrame()->selection()->selection()); + ScopedLocalRef<jobject> initData(env, createTextFieldInitData(node)); env->CallVoidMethod(javaObject.get(), m_javaGlue->m_initEditField, - start, end, reinterpret_cast<int>(selectText), - createTextFieldInitData(node)); + start, end, reinterpret_cast<int>(selectText), initData.get()); checkException(env); } @@ -3436,15 +3504,6 @@ void WebViewCore::popupReply(const int* array, int count) } } -void WebViewCore::formDidBlur(const WebCore::Node* node) -{ - // If the blur is on a text input, keep track of the node so we can - // hide the soft keyboard when the new focus is set, if it is not a - // text input. - if (isTextInput(node)) - m_blurringNodePointer = reinterpret_cast<int>(node); -} - // This is a slightly modified Node::nextNodeConsideringAtomicNodes() with the // extra constraint of limiting the search to inside a containing parent WebCore::Node* nextNodeWithinParent(WebCore::Node* parent, WebCore::Node* start) @@ -3468,6 +3527,7 @@ void WebViewCore::initializeTextInput(WebCore::Node* node, bool fake) { if (node) { if (isTextInput(node)) { + bool showKeyboard = true; initEditField(node); WebCore::RenderTextControl* rtc = toRenderTextControl(node); if (rtc && node->hasTagName(HTMLNames::inputTag)) { @@ -3484,10 +3544,11 @@ void WebViewCore::initializeTextInput(WebCore::Node* node, bool fake) autoFill->formFieldFocused(inputElement); } #endif - } else if (!fake) { - requestKeyboard(false); - } + } else + showKeyboard = false; } + if (!fake) + requestKeyboard(showKeyboard); } else if (!fake && !nodeIsPlugin(node)) { // not a text entry field, put away the keyboard. clearTextEntry(); @@ -3505,12 +3566,7 @@ void WebViewCore::focusNodeChanged(WebCore::Node* newFocus) if (!javaObject.get()) return; if (isTextInput(newFocus)) - initializeTextInput(newFocus); - else if (m_blurringNodePointer) { - env->CallVoidMethod(javaObject.get(), m_javaGlue->m_formDidBlur, m_blurringNodePointer); - checkException(env); - m_blurringNodePointer = 0; - } + initializeTextInput(newFocus, true); HitTestResult focusHitResult; focusHitResult.setInnerNode(newFocus); focusHitResult.setInnerNonSharedNode(newFocus); @@ -4242,19 +4298,15 @@ int WebViewCore::findTextOnPage(const WTF::String &text) frame = frame->tree()->traverseNextWithWrap(false); } while (frame); m_activeMatchIndex = m_matchCount - 1; // prime first findNext - if (!m_matchCount) // send at least one update, even if no hits - updateMatchCount(); - else - findNextOnPage(true); return m_matchCount; } -void WebViewCore::findNextOnPage(bool forward) +int WebViewCore::findNextOnPage(bool forward) { if (!m_mainFrame) - return; + return -1; if (!m_matchCount) - return; + return -1; EditorClientAndroid* client = static_cast<EditorClientAndroid*>( m_mainFrame->editor()->client()); @@ -4301,24 +4353,12 @@ void WebViewCore::findNextOnPage(bool forward) m_mainFrame->selection()->revealSelection( ScrollAlignment::alignCenterIfNeeded, true); } - updateMatchCount(); } // Clear selection so it doesn't display. m_mainFrame->selection()->clear(); client->setUiGeneratedSelectionChange(false); -} - -void WebViewCore::updateMatchCount() const -{ - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject javaObject = m_javaGlue->object(env); - if (!javaObject.get()) - return; - jstring javaText = wtfStringToJstring(env, m_searchText, true); - env->CallVoidMethod(javaObject.get(), m_javaGlue->m_updateMatchCount, - m_activeMatchIndex, m_matchCount, javaText); - checkException(env); + return m_activeMatchIndex; } String WebViewCore::getText(int startX, int startY, int endX, int endY) @@ -4496,10 +4536,12 @@ static void PassToJs(JNIEnv* env, jobject obj, jint nativeClass, } static void ScrollFocusedTextInput(JNIEnv* env, jobject obj, jint nativeClass, - jfloat xPercent, jint y) + jfloat xPercent, jint y, jobject contentBounds) { WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); - viewImpl->scrollFocusedTextInput(xPercent, y); + IntRect bounds = viewImpl->scrollFocusedTextInput(xPercent, y); + if (contentBounds) + GraphicsJNI::irect_to_jrect(bounds, env, contentBounds); } static void SetFocusControllerActive(JNIEnv* env, jobject obj, jint nativeClass, @@ -4525,19 +4567,6 @@ void WebViewCore::addVisitedLink(const UChar* string, int length) m_groupForVisitedLinks->addVisitedLink(string, length); } -static bool UpdateLayers(JNIEnv* env, jobject obj, jint nativeClass, - jint jbaseLayer) -{ - WebViewCore* viewImpl = (WebViewCore*) nativeClass; - BaseLayerAndroid* baseLayer = (BaseLayerAndroid*) jbaseLayer; - if (baseLayer) { - LayerAndroid* root = static_cast<LayerAndroid*>(baseLayer->getChild(0)); - if (root) - return viewImpl->updateLayers(root); - } - return true; -} - static void NotifyAnimationStarted(JNIEnv* env, jobject obj, jint nativeClass) { WebViewCore* viewImpl = (WebViewCore*) nativeClass; @@ -4646,6 +4675,12 @@ static void TouchUp(JNIEnv* env, jobject obj, jint nativeClass, (WebCore::Frame*) frame, (WebCore::Node*) node, x, y); } +static bool MouseClick(JNIEnv* env, jobject obj, jint nativeClass) +{ + WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); + return viewImpl->performMouseClick(); +} + static jstring RetrieveHref(JNIEnv* env, jobject obj, jint nativeClass, jint x, jint y) { @@ -5010,11 +5045,11 @@ static int FindAll(JNIEnv* env, jobject obj, jint nativeClass, return viewImpl->findTextOnPage(wtfText); } -static void FindNext(JNIEnv* env, jobject obj, jint nativeClass, +static int FindNext(JNIEnv* env, jobject obj, jint nativeClass, jboolean forward) { WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); - viewImpl->findNextOnPage(forward); + return viewImpl->findNextOnPage(forward); } // ---------------------------------------------------------------------------- @@ -5055,7 +5090,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) MoveMouse }, { "passToJs", "(IILjava/lang/String;IIZZZZ)V", (void*) PassToJs }, - { "nativeScrollFocusedTextInput", "(IFI)V", + { "nativeScrollFocusedTextInput", "(IFILandroid/graphics/Rect;)V", (void*) ScrollFocusedTextInput }, { "nativeSetFocusControllerActive", "(IZ)V", (void*) SetFocusControllerActive }, @@ -5067,6 +5102,8 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) HandleTouchEvent }, { "nativeTouchUp", "(IIIIII)V", (void*) TouchUp }, + { "nativeMouseClick", "(I)Z", + (void*) MouseClick }, { "nativeRetrieveHref", "(III)Ljava/lang/String;", (void*) RetrieveHref }, { "nativeRetrieveAnchorText", "(III)Ljava/lang/String;", @@ -5075,8 +5112,6 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) RetrieveImageSource }, { "nativeGetContentMinPrefWidth", "(I)I", (void*) GetContentMinPrefWidth }, - { "nativeUpdateLayers", "(II)Z", - (void*) UpdateLayers }, { "nativeNotifyAnimationStarted", "(I)V", (void*) NotifyAnimationStarted }, { "nativeRecordContent", "(ILandroid/graphics/Region;Landroid/graphics/Point;)I", @@ -5137,7 +5172,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) nativeCertTrustChanged }, { "nativeFindAll", "(ILjava/lang/String;)I", (void*) FindAll }, - { "nativeFindNext", "(IZ)V", + { "nativeFindNext", "(IZ)I", (void*) FindNext }, }; diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h index 479f549..00b4bda 100644 --- a/Source/WebKit/android/jni/WebViewCore.h +++ b/Source/WebKit/android/jni/WebViewCore.h @@ -53,6 +53,7 @@ namespace WebCore { class Color; + class GraphicsOperationCollection; class FrameView; class HTMLAnchorElement; class HTMLElement; @@ -85,9 +86,6 @@ class SkPicture; class SkIRect; namespace android { - // TODO: This file hasn't been good about namespace. Remove this temporary - // workaround to build - using namespace WebCore; enum Direction { DIRECTION_BACKWARD = 0, @@ -138,12 +136,6 @@ namespace android { // Followings are called from native WebCore to Java - /** - * Notification that a form was blurred. Pass a message to hide the - * keyboard if it was showing for that Node. - * @param Node The Node that blurred. - */ - void formDidBlur(const WebCore::Node*); void focusNodeChanged(WebCore::Node*); /** @@ -174,7 +166,7 @@ namespace android { void layersDraw(); #if USE(ACCELERATED_COMPOSITING) - GraphicsLayerAndroid* graphicsRootLayer() const; + WebCore::GraphicsLayerAndroid* graphicsRootLayer() const; #endif /** Invalidate the view/screen, NOT the content/DOM, but expressed in @@ -214,7 +206,7 @@ namespace android { * Tell the java side to update the focused textfield * @param pointer Pointer to the node for the input field. * @param changeToPassword If true, we are changing the textfield to - * a password field, and ignore the String + * a password field, and ignore the WTF::String * @param text If changeToPassword is false, this is the new text that * should go into the textfield. */ @@ -290,12 +282,13 @@ namespace android { jobject getDeviceMotionService(); jobject getDeviceOrientationService(); - void addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID, int msgLevel); + void addMessageToConsole(const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceID, int msgLevel); /** * Tell the Java side of the scrollbar mode */ - void setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode); + void setScrollbarModes(WebCore::ScrollbarMode horizontalMode, + WebCore::ScrollbarMode verticalMode); // // Followings support calls from Java to native WebCore @@ -310,7 +303,7 @@ namespace android { // scroll the selection on screen (if necessary). void revealSelection(); - void moveMouse(int x, int y, HitTestResult* hoveredNode = 0); + void moveMouse(int x, int y, WebCore::HitTestResult* hoveredNode = 0); // set the scroll amount that webview.java is currently showing void setScrollOffset(bool sendScrollEvent, int dx, int dy); @@ -326,8 +319,8 @@ namespace android { * @return Whether keyCode was handled by this class. */ bool key(const WebCore::PlatformKeyboardEvent& event); - bool chromeCanTakeFocus(FocusDirection direction); - void chromeTakeFocus(FocusDirection direction); + bool chromeCanTakeFocus(WebCore::FocusDirection direction); + void chromeTakeFocus(WebCore::FocusDirection direction); /** * Handle (trackball) click event / dpad center press from Java. @@ -339,7 +332,9 @@ namespace android { /** * Handle touch event */ - bool handleTouchEvent(int action, Vector<int>& ids, Vector<IntPoint>& points, int actionIndex, int metaState); + bool handleTouchEvent(int action, WTF::Vector<int>& ids, + WTF::Vector<WebCore::IntPoint>& points, + int actionIndex, int metaState); /** * Handle motionUp event from the UI thread (called touchUp in the @@ -355,6 +350,11 @@ namespace android { WebCore::Node* node, int x, int y); /** + * Clicks the mouse at its current location + */ + bool performMouseClick(); + + /** * Sets the index of the label from a popup */ void popupReply(int index); @@ -382,11 +382,11 @@ namespace android { * direction - The direction in which to alter the selection. * granularity - The granularity of the selection modification. * - * returns - The selected HTML as a string. This is not a well formed + * returns - The selected HTML as a WTF::String. This is not a well formed * HTML, rather the selection annotated with the tags of all * intermediary elements it crosses. */ - String modifySelection(const int direction, const int granularity); + WTF::String modifySelection(const int direction, const int granularity); /** * Moves the selection to the given node in a given frame i.e. selects that node. @@ -396,11 +396,11 @@ namespace android { * frame - The frame in which to select is the node to be selected. * node - The node to be selected. * - * returns - The selected HTML as a string. This is not a well formed + * returns - The selected HTML as a WTF::String. This is not a well formed * HTML, rather the selection annotated with the tags of all * intermediary elements it crosses. */ - String moveSelection(WebCore::Frame* frame, WebCore::Node* node); + WTF::String moveSelection(WebCore::Frame* frame, WebCore::Node* node); /** * In the currently focused textfield, replace the characters from oldStart to oldEnd @@ -415,7 +415,7 @@ namespace android { /** * Scroll the focused textfield to (x, y) in document space */ - void scrollFocusedTextInput(float x, int y); + WebCore::IntRect scrollFocusedTextInput(float x, int y); /** * Set the FocusController's active and focused states, so that * the caret will draw (true) or not. @@ -457,7 +457,7 @@ namespace android { void sendPluginSurfaceReady(); // send onLoad event to plugins who are descendents of the given frame - void notifyPluginsOnFrameLoad(const Frame*); + void notifyPluginsOnFrameLoad(const WebCore::Frame*); // gets a rect representing the current on-screen portion of the document void getVisibleScreen(ANPRectI&); @@ -515,11 +515,11 @@ namespace android { void centerFitRect(int x, int y, int width, int height); // return a list of rects matching the touch point (x, y) with the slop - Vector<IntRect> getTouchHighlightRects(int x, int y, int slop, - Node** node, HitTestResult* hitTestResult); + WTF::Vector<WebCore::IntRect> getTouchHighlightRects(int x, int y, int slop, + WebCore::Node** node, WebCore::HitTestResult* hitTestResult); // This does a sloppy hit test AndroidHitTestResult hitTestAtPoint(int x, int y, int slop, bool doMoveMouse = false); - static bool nodeIsClickableOrFocusable(Node* node); + static bool nodeIsClickableOrFocusable(WebCore::Node* node); // Open a file chooser for selecting a file to upload void openFileChooser(PassRefPtr<WebCore::FileChooser> ); @@ -530,13 +530,13 @@ namespace android { bool focusBoundsChanged(); // record the inval area, and the picture size - BaseLayerAndroid* recordContent(SkRegion* , SkIPoint* ); + WebCore::BaseLayerAndroid* recordContent(SkRegion* , SkIPoint* ); // This creates a new BaseLayerAndroid by copying the current m_content // and doing a copy of the layers. The layers' content may be updated // as we are calling layersSync(). - BaseLayerAndroid* createBaseLayer(SkRegion*); - bool updateLayers(LayerAndroid*); + WebCore::BaseLayerAndroid* createBaseLayer(SkRegion*); + bool updateLayers(WebCore::LayerAndroid*); void notifyAnimationStarted(); int textWrapWidth() const { return m_textWrapWidth; } @@ -557,7 +557,7 @@ namespace android { // find on page void resetFindOnPage(); int findTextOnPage(const WTF::String &text); - void findNextOnPage(bool forward); + int findNextOnPage(bool forward); void updateMatchCount() const; #if ENABLE(VIDEO) @@ -600,14 +600,16 @@ namespace android { */ Vector<WebCore::VisibleSelection> getTextRanges( int startX, int startY, int endX, int endY); - static int platformLayerIdFromNode(Node* node, LayerAndroid** outLayer = 0); + static int platformLayerIdFromNode(WebCore::Node* node, + WebCore::LayerAndroid** outLayer = 0); void selectText(int startX, int startY, int endX, int endY); bool selectWordAt(int x, int y); // Converts from the global content coordinates that WebView sends // to frame-local content coordinates using the focused frame - IntPoint convertGlobalContentToFrameContent(const IntPoint& point, WebCore::Frame* frame = 0); - static void layerToAbsoluteOffset(const LayerAndroid* layer, IntPoint& offset); + WebCore::IntPoint convertGlobalContentToFrameContent(const WebCore::IntPoint& point, WebCore::Frame* frame = 0); + static void layerToAbsoluteOffset(const WebCore::LayerAndroid* layer, + WebCore::IntPoint& offset); /** * Returns a text position at a given coordinate. @@ -615,7 +617,7 @@ namespace android { WebCore::VisiblePosition visiblePositionForWindowPoint(int x, int y); // Retrieves the current locale from system properties - void getLocale(String& language, String& region); + void getLocale(String& language, WTF::String& region); // Handles changes in system locale void updateLocale(); @@ -645,6 +647,9 @@ namespace android { void recordPictureSet(PictureSet* master); SkPicture* rebuildPicture(const SkIRect& inval); +#ifdef CONTEXT_RECORDING + WebCore::GraphicsOperationCollection* rebuildGraphicsOperationCollection(const SkIRect& inval); +#endif void rebuildPictureSet(PictureSet* ); void sendNotifyProgressFinished(); /* @@ -660,28 +665,38 @@ namespace android { const WebCore::QualifiedName& ); WebCore::HTMLImageElement* retrieveImageElement(int x, int y); // below are members responsible for accessibility support - String modifySelectionTextNavigationAxis(DOMSelection* selection, int direction, int granularity); - String modifySelectionDomNavigationAxis(DOMSelection* selection, int direction, int granularity); - Text* traverseNextContentTextNode(Node* fromNode, Node* toNode ,int direction); - bool isVisible(Node* node); - bool isHeading(Node* node); - String formatMarkup(DOMSelection* selection); + WTF::String modifySelectionTextNavigationAxis(WebCore::DOMSelection* selection, + int direction, int granularity); + WTF::String modifySelectionDomNavigationAxis(WebCore::DOMSelection* selection, + int direction, int granularity); + WebCore::Text* traverseNextContentTextNode(WebCore::Node* fromNode, + WebCore::Node* toNode, + int direction); + bool isVisible(WebCore::Node* node); + bool isHeading(WebCore::Node* node); + WTF::String formatMarkup(WebCore::DOMSelection* selection); void selectAt(int x, int y); - void scrollNodeIntoView(Frame* frame, Node* node); - bool isContentTextNode(Node* node); - Node* getIntermediaryInputElement(Node* fromNode, Node* toNode, int direction); - bool isContentInputElement(Node* node); - bool isDescendantOf(Node* parent, Node* node); - void advanceAnchorNode(DOMSelection* selection, int direction, String& markup, bool ignoreFirstNode, ExceptionCode& ec); - Node* getNextAnchorNode(Node* anchorNode, bool skipFirstHack, int direction); - Node* getImplicitBoundaryNode(Node* node, unsigned offset, int direction); - jobject createTextFieldInitData(Node* node); + void scrollNodeIntoView(WebCore::Frame* frame, WebCore::Node* node); + bool isContentTextNode(WebCore::Node* node); + WebCore::Node* getIntermediaryInputElement(WebCore::Node* fromNode, + WebCore::Node* toNode, + int direction); + bool isContentInputElement(WebCore::Node* node); + bool isDescendantOf(WebCore::Node* parent, WebCore::Node* node); + void advanceAnchorNode(WebCore::DOMSelection* selection, int direction, + WTF::String& markup, bool ignoreFirstNode, + WebCore::ExceptionCode& ec); + WebCore::Node* getNextAnchorNode(WebCore::Node* anchorNode, + bool skipFirstHack, int direction); + WebCore::Node* getImplicitBoundaryNode(WebCore::Node* node, + unsigned offset, int direction); + jobject createTextFieldInitData(WebCore::Node* node); /** * Calls into java to reset the text edit field with the * current contents and selection. */ - void initEditField(Node* node); + void initEditField(WebCore::Node* node); /** * If node is not a text input field or if it explicitly requests @@ -689,55 +704,59 @@ namespace android { * it is a text input field then initEditField is called and * auto-fill information is requested for HTML form input fields. */ - void initializeTextInput(Node* node, bool fake = false); + void initializeTextInput(WebCore::Node* node, bool fake); /** * Gets the input type a Node. NONE is returned if it isn't an * input field. */ - InputType getInputType(Node* node); + InputType getInputType(WebCore::Node* node); /** * If node is an input field, the spellcheck value for the * field is returned. Otherwise true is returned. */ - static bool isSpellCheckEnabled(Node* node); + static bool isSpellCheckEnabled(WebCore::Node* node); /** * Returns the offsets of the selection area for both normal text * fields and content editable fields. start and end are modified * by this method. */ - static void getSelectionOffsets(Node* node, int& start, int& end); + static void getSelectionOffsets(WebCore::Node* node, int& start, int& end); /** * Gets the plain text of the specified editable text field. node * may be content-editable or a plain text fields. */ - static String getInputText(Node* node); + static WTF::String getInputText(WebCore::Node* node); /** * Gets the RenderTextControl for the given node if it has one. * If its renderer isn't a RenderTextControl, then NULL is returned. */ - static RenderTextControl* toRenderTextControl(Node *node); + static WebCore::RenderTextControl* toRenderTextControl(WebCore::Node *node); /** * Sets the selection for node's editable field to the offsets * between start (inclusive) and end (exclusive). */ - static void setSelection(Node* node, int start, int end); + static void setSelection(WebCore::Node* node, int start, int end); /** * Returns the Position for the given offset for an editable * field. The offset is relative to the node start. */ - static WebCore::Position getPositionForOffset(Node* node, int offset); - - VisiblePosition visiblePositionForContentPoint(int x, int y); - VisiblePosition visiblePositionForContentPoint(const IntPoint& point); - bool selectWordAroundPosition(Frame* frame, VisiblePosition pos); - SelectText* createSelectText(const VisibleSelection&); - static int getMaxLength(Node* node); - static String getFieldName(Node* node); - static bool isAutoCompleteEnabled(Node* node); - IntRect boundingRect(Node* node, LayerAndroid* layer); + static WebCore::Position getPositionForOffset(WebCore::Node* node, int offset); + + WebCore::VisiblePosition visiblePositionForContentPoint(int x, int y); + WebCore::VisiblePosition visiblePositionForContentPoint(const WebCore::IntPoint& point); + bool selectWordAroundPosition(WebCore::Frame* frame, + WebCore::VisiblePosition pos); + SelectText* createSelectText(const WebCore::VisibleSelection&); + static int getMaxLength(WebCore::Node* node); + static WTF::String getFieldName(WebCore::Node* node); + static bool isAutoCompleteEnabled(WebCore::Node* node); + WebCore::IntRect absoluteContentRect(WebCore::Node* node, + WebCore::LayerAndroid* layer); + static WebCore::IntRect positionToTextRect(const WebCore::Position& position, + WebCore::EAffinity affinity); // called from constructor, to add this to a global list static void addInstance(WebViewCore*); @@ -751,7 +770,6 @@ namespace android { struct TextFieldInitDataGlue* m_textFieldInitDataGlue; WebCore::Frame* m_mainFrame; WebCoreReply* m_popupReply; - int m_blurringNodePointer; PictureSet m_content; // the set of pictures to draw SkRegion m_addInval; // the accumulated inval region (not yet drawn) SkRegion m_rebuildInval; // the accumulated region for rebuilt pictures @@ -773,7 +791,7 @@ namespace android { int m_screenHeight;// height of the visible rect in document coordinates int m_textWrapWidth; float m_scale; - PageGroup* m_groupForVisitedLinks; + WebCore::PageGroup* m_groupForVisitedLinks; bool m_isPaused; int m_cacheMode; bool m_fullscreenVideoMode; @@ -791,7 +809,7 @@ namespace android { } int m_screenOnCounter; - Node* m_currentNodeDomNavigationAxis; + WebCore::Node* m_currentNodeDomNavigationAxis; DeviceMotionAndOrientationManager m_deviceMotionAndOrientationManager; #if ENABLE(TOUCH_EVENTS) diff --git a/Source/WebKit/android/nav/SelectText.h b/Source/WebKit/android/nav/SelectText.h index 904b2b9..50bc82e 100644 --- a/Source/WebKit/android/nav/SelectText.h +++ b/Source/WebKit/android/nav/SelectText.h @@ -43,6 +43,8 @@ public: IntRect& caretRect(HandleId id) { return m_caretRects[mapId(id)]; } void setCaretRect(HandleId id, const IntRect& rect) { m_caretRects[mapId(id)] = rect; } + IntRect& textRect(HandleId id) { return m_textRects[mapId(id)]; } + void setTextRect(HandleId id, const IntRect& rect) { m_textRects[mapId(id)] = rect; } int caretLayerId(HandleId id) { return m_caretLayerId[mapId(id)]; } void setCaretLayerId(HandleId id, int layerId) { m_caretLayerId[mapId(id)] = layerId; } @@ -56,6 +58,7 @@ private: HandleId mapId(HandleId id); IntRect m_caretRects[2]; + IntRect m_textRects[2]; int m_caretLayerId[2]; bool m_baseIsFirst; String m_text; diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp index ddb9bcb..44ad1c5 100644 --- a/Source/WebKit/android/nav/WebView.cpp +++ b/Source/WebKit/android/nav/WebView.cpp @@ -30,8 +30,10 @@ #include "AndroidAnimation.h" #include "AndroidLog.h" #include "BaseLayerAndroid.h" +#include "BaseRenderer.h" #include "DrawExtra.h" #include "Frame.h" +#include "GLWebViewState.h" #include "GraphicsJNI.h" #include "HTMLInputElement.h" #include "IntPoint.h" @@ -51,6 +53,7 @@ #include "SkRect.h" #include "SkTime.h" #include "TilesManager.h" +#include "TransferQueue.h" #include "WebCoreJni.h" #include "WebRequestContext.h" #include "WebViewCore.h" @@ -125,6 +128,10 @@ struct JavaGlue { jfieldID m_rectTop; jmethodID m_rectWidth; jmethodID m_rectHeight; + jfieldID m_quadFP1; + jfieldID m_quadFP2; + jfieldID m_quadFP3; + jfieldID m_quadFP4; AutoJObject object(JNIEnv* env) { return getRealObject(env, m_obj); } @@ -156,6 +163,14 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl, WTF::String drawableDir, m_javaGlue.m_rectHeight = GetJMethod(env, rectClass, "height", "()I"); env->DeleteLocalRef(rectClass); + jclass quadFClass = env->FindClass("android/webkit/QuadF"); + ALOG_ASSERT(quadFClass, "Could not find QuadF class"); + m_javaGlue.m_quadFP1 = env->GetFieldID(quadFClass, "p1", "Landroid/graphics/PointF;"); + m_javaGlue.m_quadFP2 = env->GetFieldID(quadFClass, "p2", "Landroid/graphics/PointF;"); + m_javaGlue.m_quadFP3 = env->GetFieldID(quadFClass, "p3", "Landroid/graphics/PointF;"); + m_javaGlue.m_quadFP4 = env->GetFieldID(quadFClass, "p4", "Landroid/graphics/PointF;"); + env->DeleteLocalRef(quadFClass); + env->SetIntField(javaWebView, gWebViewField, (jint)this); m_viewImpl = (WebViewCore*) viewImpl; m_generation = 0; @@ -236,13 +251,13 @@ void scrollRectOnScreen(const IntRect& rect) viewInvalidate(); } -bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect, +int drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect, WebCore::IntRect& webViewRect, int titleBarHeight, - WebCore::IntRect& clip, float scale, int extras) + WebCore::IntRect& clip, float scale, int extras, bool shouldDraw) { #if USE(ACCELERATED_COMPOSITING) if (!m_baseLayer) - return false; + return 0; if (!m_glWebViewState) { TilesManager::instance()->setHighEndGfx(m_isHighEndGfx); @@ -258,12 +273,12 @@ bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect, // if the zoom manager is still initializing. We will be redrawn // once the correct scale is set if (!m_visibleRect.isFinite()) - return false; + return 0; bool treesSwapped = false; bool newTreeHasAnim = false; - bool ret = m_glWebViewState->drawGL(viewRect, m_visibleRect, invalRect, + int ret = m_glWebViewState->drawGL(viewRect, m_visibleRect, invalRect, webViewRect, titleBarHeight, clip, scale, - &treesSwapped, &newTreeHasAnim); + &treesSwapped, &newTreeHasAnim, shouldDraw); if (treesSwapped) { ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); @@ -273,10 +288,9 @@ bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect, checkException(env); } } - if (ret) - return !m_isDrawingPaused; + return m_isDrawingPaused ? 0 : ret; #endif - return false; + return 0; } PictureSet* draw(SkCanvas* canvas, SkColor bgColor, DrawExtras extras, bool split) @@ -292,7 +306,8 @@ PictureSet* draw(SkCanvas* canvas, SkColor bgColor, DrawExtras extras, bool spli int sc = canvas->save(SkCanvas::kClip_SaveFlag); canvas->clipRect(SkRect::MakeLTRB(0, 0, content->width(), content->height()), SkRegion::kDifference_Op); - canvas->drawColor(bgColor); + Color c = m_baseLayer->getBackgroundColor(); + canvas->drawColor(SkColorSetARGBInline(c.alpha(), c.red(), c.green(), c.blue())); canvas->restoreToCount(sc); // call this to be sure we've adjusted for any scrolling or animations @@ -578,43 +593,64 @@ void setTextSelection(SelectText *selection) { setDrawExtra(selection, DrawExtrasSelection); } -int getHandleLayerId(SelectText::HandleId handleId, SkIRect& cursorRect) { +const TransformationMatrix* getLayerTransform(int layerId) { + if (layerId != -1 && m_baseLayer) { + LayerAndroid* layer = m_baseLayer->findById(layerId); + // We need to make sure the drawTransform is up to date as this is + // called before a draw() or drawGL() + if (layer) { + m_baseLayer->updateLayerPositions(m_visibleRect); + return layer->drawTransform(); + } + } + return 0; +} + +int getHandleLayerId(SelectText::HandleId handleId, SkIPoint& cursorPoint, + FloatQuad& textBounds) { SelectText* selectText = static_cast<SelectText*>(getDrawExtra(DrawExtrasSelection)); if (!selectText || !m_baseLayer) return -1; int layerId = selectText->caretLayerId(handleId); - cursorRect = selectText->caretRect(handleId); - if (layerId != -1) { - // We need to make sure the drawTransform is up to date as this is - // called before a draw() or drawGL() - m_baseLayer->updateLayerPositions(m_visibleRect); - LayerAndroid* root = m_baseLayer; - LayerAndroid* layer = root ? root->findById(layerId) : 0; - if (layer && layer->drawTransform()) { - const TransformationMatrix* transform = layer->drawTransform(); - // We're overloading the concept of Rect to be just the two - // points (bottom-left and top-right. - // TODO: Use FloatQuad instead. - IntPoint bottomLeft = transform->mapPoint(IntPoint(cursorRect.fLeft, - cursorRect.fBottom)); - IntPoint topRight = transform->mapPoint(IntPoint(cursorRect.fRight, - cursorRect.fTop)); - cursorRect.setLTRB(bottomLeft.x(), topRight.y(), topRight.x(), - bottomLeft.y()); - } + IntRect cursorRect = selectText->caretRect(handleId); + IntRect textRect = selectText->textRect(handleId); + // Rects exclude the last pixel on right/bottom. We want only included pixels. + cursorPoint.set(cursorRect.x(), cursorRect.maxY() - 1); + textRect.setHeight(std::max(1, textRect.height() - 1)); + textRect.setWidth(std::max(1, textRect.width() - 1)); + textBounds = FloatQuad(textRect); + + const TransformationMatrix* transform = getLayerTransform(layerId); + if (transform) { + // We're overloading the concept of Rect to be just the two + // points (bottom-left and top-right. + cursorPoint = transform->mapPoint(cursorPoint); + textBounds = transform->mapQuad(textBounds); } return layerId; } void mapLayerRect(int layerId, SkIRect& rect) { - if (layerId != -1) { - // We need to make sure the drawTransform is up to date as this is - // called before a draw() or drawGL() - m_baseLayer->updateLayerPositions(m_visibleRect); - LayerAndroid* layer = m_baseLayer ? m_baseLayer->findById(layerId) : 0; - if (layer && layer->drawTransform()) - rect = layer->drawTransform()->mapRect(rect); - } + const TransformationMatrix* transform = getLayerTransform(layerId); + if (transform) + transform->mapRect(rect); +} + +void floatQuadToQuadF(JNIEnv* env, const FloatQuad& nativeTextQuad, + jobject textQuad) +{ + jobject p1 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP1); + jobject p2 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP2); + jobject p3 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP3); + jobject p4 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP4); + GraphicsJNI::point_to_jpointf(nativeTextQuad.p1(), env, p1); + GraphicsJNI::point_to_jpointf(nativeTextQuad.p2(), env, p2); + GraphicsJNI::point_to_jpointf(nativeTextQuad.p3(), env, p3); + GraphicsJNI::point_to_jpointf(nativeTextQuad.p4(), env, p4); + env->DeleteLocalRef(p1); + env->DeleteLocalRef(p2); + env->DeleteLocalRef(p3); + env->DeleteLocalRef(p4); } // This is called when WebView switches rendering modes in a more permanent fashion @@ -656,8 +692,8 @@ private: // local state for WebView class GLDrawFunctor : Functor { public: GLDrawFunctor(WebView* _wvInstance, - bool(WebView::*_funcPtr)(WebCore::IntRect&, WebCore::IntRect*, - WebCore::IntRect&, int, WebCore::IntRect&, jfloat, jint), + int (WebView::*_funcPtr)(WebCore::IntRect&, WebCore::IntRect*, + WebCore::IntRect&, int, WebCore::IntRect&, jfloat, jint, bool), WebCore::IntRect _viewRect, float _scale, int _extras) { wvInstance = _wvInstance; funcPtr = _funcPtr; @@ -682,16 +718,15 @@ class GLDrawFunctor : Functor { WebCore::IntRect clip(info->clipLeft, info->clipTop, info->clipRight - info->clipLeft, info->clipBottom - info->clipTop); + bool shouldDraw = (messageId == uirenderer::DrawGlInfo::kModeDraw); TilesManager::instance()->shader()->setWebViewMatrix(info->transform, info->isLayer); - - bool retVal = (*wvInstance.*funcPtr)(localViewRect, &inval, webViewRect, - titlebarHeight, clip, scale, extras); - if (retVal) { + int returnFlags = (*wvInstance.*funcPtr)(localViewRect, &inval, webViewRect, + titlebarHeight, clip, scale, extras, shouldDraw); + if ((returnFlags & uirenderer::DrawGlInfo::kStatusDraw) != 0) { IntRect finalInval; - if (inval.isEmpty()) { + if (inval.isEmpty()) finalInval = webViewRect; - retVal = true; - } else { + else { finalInval.setX(webViewRect.x() + inval.x()); finalInval.setY(webViewRect.y() + titlebarHeight + inval.y()); finalInval.setWidth(inval.width()); @@ -702,8 +737,9 @@ class GLDrawFunctor : Functor { info->dirtyRight = finalInval.maxX(); info->dirtyBottom = finalInval.maxY(); } - // return 1 if invalidation needed, 0 otherwise - return retVal ? 1 : 0; + // return 1 if invalidation needed, 2 to request non-drawing functor callback, 0 otherwise + ALOGV("returnFlags are %d, shouldDraw %d", returnFlags, shouldDraw); + return returnFlags; } void updateRect(WebCore::IntRect& _viewRect) { viewRect = _viewRect; @@ -716,8 +752,8 @@ class GLDrawFunctor : Functor { } private: WebView* wvInstance; - bool (WebView::*funcPtr)(WebCore::IntRect&, WebCore::IntRect*, - WebCore::IntRect&, int, WebCore::IntRect&, float, int); + int (WebView::*funcPtr)(WebCore::IntRect&, WebCore::IntRect*, + WebCore::IntRect&, int, WebCore::IntRect&, float, int, bool); WebCore::IntRect viewRect; WebCore::IntRect webViewRect; jfloat scale; @@ -1140,13 +1176,18 @@ static void nativeSetTextSelection(JNIEnv *env, jobject obj, jint nativeView, } static jint nativeGetHandleLayerId(JNIEnv *env, jobject obj, jint nativeView, - jint handleIndex, jobject cursorRect) + jint handleIndex, jobject cursorPoint, + jobject textQuad) { WebView* webview = reinterpret_cast<WebView*>(nativeView); - SkIRect nativeRect; - int layerId = webview->getHandleLayerId((SelectText::HandleId) handleIndex, nativeRect); - if (cursorRect) - GraphicsJNI::irect_to_jrect(nativeRect, env, cursorRect); + SkIPoint nativePoint; + FloatQuad nativeTextQuad; + int layerId = webview->getHandleLayerId((SelectText::HandleId) handleIndex, + nativePoint, nativeTextQuad); + if (cursorPoint) + GraphicsJNI::ipoint_to_jpoint(nativePoint, env, cursorPoint); + if (textQuad) + webview->floatQuadToQuadF(env, nativeTextQuad, textQuad); return layerId; } @@ -1247,7 +1288,7 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeSetPauseDrawing }, { "nativeSetTextSelection", "(II)V", (void*) nativeSetTextSelection }, - { "nativeGetHandleLayerId", "(IILandroid/graphics/Rect;)I", + { "nativeGetHandleLayerId", "(IILandroid/graphics/Point;Landroid/webkit/QuadF;)I", (void*) nativeGetHandleLayerId }, { "nativeIsBaseFirst", "(I)Z", (void*) nativeIsBaseFirst }, diff --git a/Source/WebKit/android/plugins/ANPSurfaceInterface.cpp b/Source/WebKit/android/plugins/ANPSurfaceInterface.cpp index 513d251..92dbbcd 100644 --- a/Source/WebKit/android/plugins/ANPSurfaceInterface.cpp +++ b/Source/WebKit/android/plugins/ANPSurfaceInterface.cpp @@ -47,7 +47,7 @@ static struct ANPSurfaceInterfaceJavaGlue { jfieldID surfacePointer; } gSurfaceJavaGlue; -static inline sp<Surface> getSurface(JNIEnv* env, jobject view) { +static inline sp<android::Surface> getSurface(JNIEnv* env, jobject view) { if (!env || !view) { return NULL; } @@ -80,7 +80,7 @@ static inline sp<Surface> getSurface(JNIEnv* env, jobject view) { env->DeleteLocalRef(holder); env->DeleteLocalRef(surface); - return sp<Surface>((Surface*) surfacePointer); + return sp<android::Surface>((android::Surface*) surfacePointer); } static inline ANPBitmapFormat convertPixelFormat(PixelFormat format) { @@ -96,9 +96,9 @@ static bool anp_lock(JNIEnv* env, jobject surfaceView, ANPBitmap* bitmap, ANPRec return false; } - sp<Surface> surface = getSurface(env, surfaceView); + sp<android::Surface> surface = getSurface(env, surfaceView); - if (!bitmap || !Surface::isValid(surface)) { + if (!bitmap || !android::Surface::isValid(surface)) { return false; } @@ -112,7 +112,7 @@ static bool anp_lock(JNIEnv* env, jobject surfaceView, ANPBitmap* bitmap, ANPRec dirtyRegion.set(Rect(0x3FFF, 0x3FFF)); } - Surface::SurfaceInfo info; + android::Surface::SurfaceInfo info; status_t err = surface->lock(&info, &dirtyRegion); if (err < 0) { return false; @@ -150,9 +150,9 @@ static void anp_unlock(JNIEnv* env, jobject surfaceView) { return; } - sp<Surface> surface = getSurface(env, surfaceView); + sp<android::Surface> surface = getSurface(env, surfaceView); - if (!Surface::isValid(surface)) { + if (!android::Surface::isValid(surface)) { return; } |