diff options
Diffstat (limited to 'WebCore/platform')
21 files changed, 319 insertions, 197 deletions
diff --git a/WebCore/platform/android/PlatformBridge.h b/WebCore/platform/android/PlatformBridge.h index 3f559d5..faa823e 100644 --- a/WebCore/platform/android/PlatformBridge.h +++ b/WebCore/platform/android/PlatformBridge.h @@ -149,8 +149,8 @@ public: static int memoryUsageMB(); static int actualMemoryUsageMB(); - static int visibleScreenWidth(const FrameView*); - static int visibleScreenHeight(const FrameView*); + static int screenWidthInDocCoord(const FrameView*); + static int screenHeightInDocCoord(const FrameView*); }; } diff --git a/WebCore/platform/android/PopupMenuAndroid.cpp b/WebCore/platform/android/PopupMenuAndroid.cpp index 2bae724..f4c351f 100644 --- a/WebCore/platform/android/PopupMenuAndroid.cpp +++ b/WebCore/platform/android/PopupMenuAndroid.cpp @@ -31,7 +31,7 @@ class PopupReply : public android::WebCoreReply { public: - PopupReply(const IntRect& rect, android::WebViewCore* view, PopupMenuClient* client) + PopupReply(const IntRect& rect, android::WebViewCore* view, ListPopupMenuClient* client) : m_rect(rect) , m_viewImpl(view) , m_popupClient(client) @@ -53,9 +53,23 @@ public: m_viewImpl->contentInvalidate(m_rect); } - virtual void replyIntArray(const int*, int) { - // Should never be called. - SkASSERT(false); + virtual void replyIntArray(const int* values, int count) + { + if (m_popupClient) { + m_popupClient->popupDidHide(); + if (0 == count) { + m_popupClient->valueChanged(-1, true); + } else { + for (int i = 0; i < count; i++) { + m_popupClient->listBoxSelectItem(values[i], + i != 0 /* allowMultiplySelection */, + false /* shift */, + i == count - 1 /* fireOnChangeNow */); + } + } + } + if (m_viewImpl) + m_viewImpl->contentInvalidate(m_rect); } void disconnectClient() @@ -67,12 +81,12 @@ private: IntRect m_rect; // FIXME: Do not need this if we handle ChromeClientAndroid::formStateDidChange android::WebViewCore* m_viewImpl; - PopupMenuClient* m_popupClient; + ListPopupMenuClient* m_popupClient; }; namespace WebCore { -PopupMenuAndroid::PopupMenuAndroid(PopupMenuClient* menuList) +PopupMenuAndroid::PopupMenuAndroid(ListPopupMenuClient* menuList) : m_popupClient(menuList) , m_reply(0) { @@ -91,8 +105,7 @@ void PopupMenuAndroid::disconnectClient() m_reply = 0; } } -// Copied from WebViewCore.cpp. Once we move ListBox handling to this class, -// we can remove the one in WebViewCore.cpp. + // Convert a WTF::String into an array of characters where the first // character represents the length, for easy conversion to java. static uint16_t* stringConverter(const WTF::String& text) @@ -122,9 +135,7 @@ void PopupMenuAndroid::show(const IntRect& rect, FrameView* frameView, int) SkTDArray<int> enabledArray; SkTDArray<int> selectedArray; int size = m_popupClient->listSize(); - // If we use this for ListBoxes in addition to MenuLists, we will need to - // account for 'multiple' - bool multiple = false; + bool multiple = m_popupClient->multiple(); for (int i = 0; i < size; i++) { *names.append() = stringConverter(m_popupClient->itemText(i)); if (m_popupClient->itemIsSeparator(i)) { diff --git a/WebCore/platform/android/PopupMenuAndroid.h b/WebCore/platform/android/PopupMenuAndroid.h index 48bce44..6c2c015 100644 --- a/WebCore/platform/android/PopupMenuAndroid.h +++ b/WebCore/platform/android/PopupMenuAndroid.h @@ -34,18 +34,18 @@ class PopupReply; namespace WebCore { class FrameView; -class PopupMenuClient; +class ListPopupMenuClient; class PopupMenuAndroid : public PopupMenu { public: - PopupMenuAndroid(PopupMenuClient*); + PopupMenuAndroid(ListPopupMenuClient*); virtual ~PopupMenuAndroid(); virtual void show(const IntRect&, FrameView*, int); virtual void hide() { } virtual void updateFromElement() { } virtual void disconnectClient(); private: - PopupMenuClient* m_popupClient; + ListPopupMenuClient* m_popupClient; PopupReply* m_reply; }; diff --git a/WebCore/platform/android/RenderThemeAndroid.cpp b/WebCore/platform/android/RenderThemeAndroid.cpp index 87e7a6d..66f034d 100644 --- a/WebCore/platform/android/RenderThemeAndroid.cpp +++ b/WebCore/platform/android/RenderThemeAndroid.cpp @@ -52,9 +52,15 @@ namespace WebCore { // dropdowns, we want a much smaller height, which encompasses the text. const int listboxPadding = 5; -// This is the color of selection in a textfield. It was obtained by checking -// the color of selection in TextViews in the system. -const RGBA32 selectionColor = makeRGB(255, 146, 0); +// This is the color of selection in a textfield. It was computed from +// frameworks/base/core/res/res/values/colors.xml, which uses #9983CC39 +// (decimal a = 153, r = 131, g = 204, b = 57) +// for all four highlighted text values. Blending this with white yields: +// R = (131 * 153 + 255 * (255 - 153)) / 255 -> 180.6 +// G = (204 * 153 + 255 * (255 - 153)) / 255 -> 224.4 +// B = ( 57 * 153 + 255 * (255 - 153)) / 255 -> 136.2 + +const RGBA32 selectionColor = makeRGB(181, 224, 136); static SkCanvas* getCanvasFromInfo(const PaintInfo& info) { @@ -351,57 +357,9 @@ void RenderThemeAndroid::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle* sty bool RenderThemeAndroid::paintTextArea(RenderObject* obj, const PaintInfo& info, const IntRect& rect) { - if (!obj->isListBox()) - return true; - - paintCombo(obj, info, rect); - RenderStyle* style = obj->style(); - if (style) - style->setColor(Color::transparent); - Node* node = obj->node(); - if (!node || !node->hasTagName(HTMLNames::selectTag)) - return true; - - HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node); - // The first item may be visible. Make sure it does not draw. - // If it has a style, it overrides the RenderListBox's style, so we - // need to make sure both are set to transparent. - node = select->item(0); - if (node) { - RenderObject* renderer = node->renderer(); - if (renderer) { - RenderStyle* renderStyle = renderer->style(); - if (renderStyle) - renderStyle->setColor(Color::transparent); - } - } - // Find the first selected option, and draw its text. - // FIXME: In a later change, if there is more than one item selected, - // draw a string that says "X items" like iPhone Safari does - int index = select->selectedIndex(); - node = select->item(index); - if (!node || !node->hasTagName(HTMLNames::optionTag)) - return true; - - HTMLOptionElement* option = static_cast<HTMLOptionElement*>(node); - String label = option->textIndentedToRespectGroupLabel(); - SkRect r(rect); - - SkPaint paint; - paint.setAntiAlias(true); - paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); - // Values for text size and positioning determined by trial and error - paint.setTextSize(r.height() - SkIntToScalar(6)); - - SkCanvas* canvas = getCanvasFromInfo(info); - int saveCount = canvas->save(); - r.fRight -= SkIntToScalar(RenderSkinCombo::extraWidth()); - canvas->clipRect(r); - canvas->drawText(label.characters(), label.length() << 1, - r.fLeft + SkIntToScalar(5), r.fBottom - SkIntToScalar(5), paint); - canvas->restoreToCount(saveCount); - - return true; + if (obj->isMenuList()) + paintCombo(obj, info, rect); + return true; } void RenderThemeAndroid::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const @@ -414,16 +372,7 @@ bool RenderThemeAndroid::paintSearchField(RenderObject*, const PaintInfo&, const return true; } -void RenderThemeAndroid::adjustListboxStyle(CSSStyleSelector*, RenderStyle* style, Element*) const -{ - style->setPaddingRight(Length(RenderSkinCombo::extraWidth(), Fixed)); - style->setMaxHeight(Length(style->fontSize() + listboxPadding, Fixed)); - // Make webkit draw invisible, since it will simply draw the first element - style->setColor(Color::transparent); - addIntrinsicMargins(style); -} - -static void adjustMenuListStyleCommon(RenderStyle* style, Element* e) +static void adjustMenuListStyleCommon(RenderStyle* style) { // Added to make room for our arrow and make the touch target less cramped. style->setPaddingLeft(Length(RenderSkinCombo::padding(), Fixed)); @@ -432,9 +381,14 @@ static void adjustMenuListStyleCommon(RenderStyle* style, Element* e) style->setPaddingRight(Length(RenderSkinCombo::extraWidth(), Fixed)); } +void RenderThemeAndroid::adjustListboxStyle(CSSStyleSelector*, RenderStyle* style, Element*) const +{ + adjustMenuListButtonStyle(0, style, 0); +} + void RenderThemeAndroid::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element* e) const { - adjustMenuListStyleCommon(style, e); + adjustMenuListStyleCommon(style); addIntrinsicMargins(style); } @@ -450,7 +404,8 @@ bool RenderThemeAndroid::paintMenuList(RenderObject* obj, const PaintInfo& info, return paintCombo(obj, info, rect); } -void RenderThemeAndroid::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element* e) const +void RenderThemeAndroid::adjustMenuListButtonStyle(CSSStyleSelector*, + RenderStyle* style, Element*) const { // Copied from RenderThemeSafari. const float baseFontSize = 11.0f; @@ -468,7 +423,7 @@ void RenderThemeAndroid::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyl const int padding = 4; style->setPaddingTop(Length(padding, Fixed)); style->setPaddingLeft(Length(padding, Fixed)); - adjustMenuListStyleCommon(style, e); + adjustMenuListStyleCommon(style); } bool RenderThemeAndroid::paintMenuListButton(RenderObject* obj, const PaintInfo& info, const IntRect& rect) diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp index 77f673a..d16b53e 100644 --- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp +++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp @@ -47,6 +47,8 @@ BackedDoubleBufferedTexture::BackedDoubleBufferedTexture(uint32_t w, uint32_t h, , m_usedLevel(-1) , m_config(config) , m_owner(0) + , m_delayedReleaseOwner(0) + , m_delayedRelease(false) , m_busy(false) { m_size.set(w, h); @@ -117,15 +119,27 @@ TextureInfo* BackedDoubleBufferedTexture::producerLock() void BackedDoubleBufferedTexture::producerRelease() { DoubleBufferedTexture::producerRelease(); - android::Mutex::Autolock lock(m_busyLock); - m_busy = false; + setNotBusy(); } void BackedDoubleBufferedTexture::producerReleaseAndSwap() { DoubleBufferedTexture::producerReleaseAndSwap(); + setNotBusy(); +} + +void BackedDoubleBufferedTexture::setNotBusy() +{ android::Mutex::Autolock lock(m_busyLock); m_busy = false; + if (m_delayedRelease) { + if (m_owner == m_delayedReleaseOwner) { + m_owner->removeOwned(this); + m_owner = 0; + } + m_delayedRelease = false; + m_delayedReleaseOwner = 0; + } } bool BackedDoubleBufferedTexture::busy() @@ -175,24 +189,45 @@ bool BackedDoubleBufferedTexture::setOwner(TextureOwner* owner) { // if the writable texture is busy (i.e. currently being written to) then we // can't change the owner out from underneath that texture - android::Mutex::Autolock lock(m_busyLock); - if (!m_busy) { + m_busyLock.lock(); + bool busy = m_busy; + m_busyLock.unlock(); + if (!busy) { + // if we are not busy we can try to remove the texture from the layer; + // LayerAndroid::removeTexture() is protected by the same lock as + // LayerAndroid::paintBitmapGL(), so either we execute removeTexture() + // first and paintBitmapGL() will bail out, or we execute it after, + // and paintBitmapGL() will mark the texture as busy before + // relinquishing the lock. LayerAndroid::removeTexture() will call + // BackedDoubleBufferedTexture::release(), which will then do nothing + // if the texture is busy and we then don't return true. + bool proceed = true; if (m_owner && m_owner != owner) - m_owner->removeTexture(this); - m_owner = owner; - owner->addOwned(this); - return true; + proceed = m_owner->removeTexture(this); + + if (proceed) { + m_owner = owner; + owner->addOwned(this); + return true; + } } return false; } -void BackedDoubleBufferedTexture::release(TextureOwner* owner) +bool BackedDoubleBufferedTexture::release(TextureOwner* owner) { + android::Mutex::Autolock lock(m_busyLock); if (m_owner == owner) { - m_owner->removeOwned(this); - m_owner = 0; + if (!m_busy) { + m_owner->removeOwned(this); + m_owner = 0; + return true; + } else { + m_delayedRelease = true; + m_delayedReleaseOwner = owner; + } } - + return false; } } // namespace WebCore diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h index 1c50d87..b1f170b 100644 --- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h +++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h @@ -68,7 +68,7 @@ public: // allows consumer thread to assign ownership of the texture to the tile. It // returns false if ownership cannot be transferred because the tile is busy bool acquire(TextureOwner* owner); - void release(TextureOwner* owner); + bool release(TextureOwner* owner); // set the texture owner if not busy. Return false if busy, true otherwise. bool setOwner(TextureOwner* owner); @@ -78,6 +78,7 @@ public: SkCanvas* canvas(); // only used by the producer thread bool busy(); + void setNotBusy(); const SkSize& getSize() const { return m_size; } @@ -98,6 +99,12 @@ private: SkBitmap::Config m_config; TextureOwner* m_owner; + // When trying to release a texture, we may delay this if the texture is + // currently used (busy being painted). We use the following two variables + // to do so in setNotBusy() + TextureOwner* m_delayedReleaseOwner; + bool m_delayedRelease; + // This values signals that the texture is currently in use by the consumer. // This allows us to prevent the owner of the texture from changing while the // consumer is holding a lock on the texture. diff --git a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index 3483e44..584add1 100644 --- a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -116,12 +116,11 @@ void BaseLayerAndroid::drawCanvas(SkCanvas* canvas) } #if USE(ACCELERATED_COMPOSITING) -bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale) +bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, double currentTime) { if (!m_glWebViewState) return false; - double currentTime = WTF::currentTime(); bool goingDown = m_previousVisible.fTop - viewport.fTop <= 0; bool goingLeft = m_previousVisible.fLeft - viewport.fLeft >= 0; @@ -282,7 +281,8 @@ bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect, shader->setViewport(visibleRect); shader->resetBlending(); - ret = drawBasePictureInGL(visibleRect, scale); + double currentTime = WTF::currentTime(); + ret = drawBasePictureInGL(visibleRect, scale, currentTime); if (countChildren() >= 1) { LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0)); @@ -311,7 +311,7 @@ bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect, scale = m_glWebViewState->futureScale(); } compositedRoot->setScale(scale); - compositedRoot->computeTextureSize(); + compositedRoot->computeTextureSize(currentTime); compositedRoot->reserveGLTextures(); #ifdef DEBUG @@ -337,12 +337,6 @@ bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect, glBindBuffer(GL_ARRAY_BUFFER, 0); m_previousVisible = visibleRect; -#ifdef DEBUG_COUNT - XLOG("GLWebViewState(%d) DoubleBufferedTexture(%d) BaseTile(%d) TileSet(%d) TiledPage(%d)", - GLWebViewState::count(), DoubleBufferedTexture::count(), - BaseTile::count(), TileSet::count(), TiledPage::count()); -#endif // DEBUG_COUNT - #endif // USE(ACCELERATED_COMPOSITING) #ifdef DEBUG ClassTracker::instance()->show(); diff --git a/WebCore/platform/graphics/android/BaseLayerAndroid.h b/WebCore/platform/graphics/android/BaseLayerAndroid.h index c57b13d..cb1caef 100644 --- a/WebCore/platform/graphics/android/BaseLayerAndroid.h +++ b/WebCore/platform/graphics/android/BaseLayerAndroid.h @@ -59,7 +59,7 @@ public: void swapExtra(BaseLayerAndroid* base) { m_extra.swap(base->m_extra); } private: #if USE(ACCELERATED_COMPOSITING) - bool drawBasePictureInGL(SkRect& viewport, float scale); + bool drawBasePictureInGL(SkRect& viewport, float scale, double currentTime); GLWebViewState* m_glWebViewState; android::Mutex m_drawLock; diff --git a/WebCore/platform/graphics/android/BaseTile.cpp b/WebCore/platform/graphics/android/BaseTile.cpp index 2942f24..bfd5118 100644 --- a/WebCore/platform/graphics/android/BaseTile.cpp +++ b/WebCore/platform/graphics/android/BaseTile.cpp @@ -107,13 +107,14 @@ void BaseTile::reserveTexture() m_texture = texture; } -void BaseTile::removeTexture(BackedDoubleBufferedTexture* texture) +bool BaseTile::removeTexture(BackedDoubleBufferedTexture* texture) { XLOG("%x removeTexture res: %x... page %x", this, m_texture, m_page); // We update atomically, so paintBitmap() can see the correct value android::AutoMutex lock(m_atomicSync); if (m_texture == texture) m_texture = 0; + return true; } void BaseTile::setScale(float scale) @@ -264,18 +265,18 @@ void BaseTile::paintBitmap() canvas->restore(); -#ifdef DEBUG - SkPaint paint; - paint.setARGB(128, 255, 0, 0); - paint.setStrokeWidth(3); - canvas->drawLine(0, 0, tileWidth, tileHeight, paint); - paint.setARGB(128, 0, 255, 0); - canvas->drawLine(0, tileHeight, tileWidth, 0, paint); - paint.setARGB(128, 0, 0, 255); - canvas->drawLine(0, 0, tileWidth, 0, paint); - canvas->drawLine(tileWidth, 0, tileWidth, tileHeight, paint); - drawTileInfo(canvas, texture, x, y, scale); -#endif + if (TilesManager::instance()->getShowVisualIndicator()) { + SkPaint paint; + paint.setARGB(128, 255, 0, 0); + paint.setStrokeWidth(3); + canvas->drawLine(0, 0, tileWidth, tileHeight, paint); + paint.setARGB(128, 0, 255, 0); + canvas->drawLine(0, tileHeight, tileWidth, 0, paint); + paint.setARGB(128, 0, 0, 255); + canvas->drawLine(0, 0, tileWidth, 0, paint); + canvas->drawLine(tileWidth, 0, tileWidth, tileHeight, paint); + drawTileInfo(canvas, texture, x, y, scale); + } texture->setTile(x, y); texture->producerUpdate(textureInfo); diff --git a/WebCore/platform/graphics/android/BaseTile.h b/WebCore/platform/graphics/android/BaseTile.h index 0527fcd..af7df3a 100644 --- a/WebCore/platform/graphics/android/BaseTile.h +++ b/WebCore/platform/graphics/android/BaseTile.h @@ -90,7 +90,7 @@ public: BackedDoubleBufferedTexture* texture() { return m_texture; } // TextureOwner implementation - virtual void removeTexture(BackedDoubleBufferedTexture* texture); + virtual bool removeTexture(BackedDoubleBufferedTexture* texture); virtual TiledPage* page() { return m_page; } private: diff --git a/WebCore/platform/graphics/android/GLWebViewState.cpp b/WebCore/platform/graphics/android/GLWebViewState.cpp index d57abf8..3d2f6c8 100644 --- a/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -93,7 +93,8 @@ GLWebViewState::~GLWebViewState() #endif } -void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect) +void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect, + bool showVisualIndicator) { android::Mutex::Autolock lock(m_baseLayerLock); if (!layer) { @@ -109,26 +110,28 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect) // We only update the layers if we are not currently // waiting for a tiledPage to be painted if (m_baseLayerUpdate) { + layer->safeRef(); m_currentBaseLayer->safeUnref(); m_currentBaseLayer = layer; - m_currentBaseLayer->safeRef(); } inval(rect); + + TilesManager::instance()->setShowVisualIndicator(showVisualIndicator); } void GLWebViewState::unlockBaseLayerUpdate() { m_baseLayerUpdate = true; android::Mutex::Autolock lock(m_baseLayerLock); + m_baseLayer->safeRef(); m_currentBaseLayer->safeUnref(); m_currentBaseLayer = m_baseLayer; - m_currentBaseLayer->safeRef(); inval(m_invalidateRect); IntRect empty; m_invalidateRect = empty; } void GLWebViewState::setExtra(BaseLayerAndroid* layer, SkPicture& picture, - const IntRect& rect) + const IntRect& rect, bool allowSame) { android::Mutex::Autolock lock(m_baseLayerLock); if (!m_baseLayerUpdate) @@ -136,7 +139,7 @@ void GLWebViewState::setExtra(BaseLayerAndroid* layer, SkPicture& picture, layer->setExtra(picture); - if (m_lastInval == rect) + if (!allowSame && m_lastInval == rect) return; if (!rect.isEmpty()) @@ -296,6 +299,19 @@ void GLWebViewState::setViewport(SkRect& viewport, float scale) m_tiledPageB->updateBaseTileSize(); } +bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, float scale, SkColor color) +{ + m_baseLayerLock.lock(); + BaseLayerAndroid* baseLayer = m_currentBaseLayer; + baseLayer->safeRef(); + m_baseLayerLock.unlock(); + if (!baseLayer) + return false; + bool ret = baseLayer->drawGL(rect, viewport, scale, color); + baseLayer->safeUnref(); + return ret; +} + } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/android/GLWebViewState.h b/WebCore/platform/graphics/android/GLWebViewState.h index d45340d..d265b41 100644 --- a/WebCore/platform/graphics/android/GLWebViewState.h +++ b/WebCore/platform/graphics/android/GLWebViewState.h @@ -168,8 +168,8 @@ public: void resetTransitionTime() { m_transitionTime = -1; } unsigned int paintBaseLayerContent(SkCanvas* canvas); - void setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect); - void setExtra(BaseLayerAndroid*, SkPicture&, const IntRect&); + void setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect, bool showVisualIndicator); + void setExtra(BaseLayerAndroid*, SkPicture&, const IntRect&, bool allowSame); void scheduleUpdate(const double& currentTime, const SkIRect& viewport, float scale); TiledPage* sibling(TiledPage* page); @@ -205,6 +205,9 @@ public: return false; } + bool drawGL(IntRect& rect, SkRect& viewport, + float scale, SkColor color = SK_ColorWHITE); + void setBackgroundColor(SkColor color) { m_backgroundColor = color; } SkColor getBackgroundColor() { return m_backgroundColor; } diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index e887964..ccc872a 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -271,7 +271,17 @@ void GraphicsLayerAndroid::setPosition(const FloatPoint& point) if (point == m_position) return; - GraphicsLayer::setPosition(point); + FloatPoint pos(point); +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + // Add the scroll position back in. When scrolling a layer, all the children + // are positioned based on the content scroll. Adding the scroll position + // back in allows the children to draw based on 0,0. + RenderLayer* layer = renderLayerFromClient(m_client); + if (layer && layer->parent() && layer->parent()->hasOverflowScroll()) + pos += layer->parent()->scrolledContentOffset(); +#endif + + GraphicsLayer::setPosition(pos); #ifdef LAYER_DEBUG_2 LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)", @@ -279,7 +289,7 @@ void GraphicsLayerAndroid::setPosition(const FloatPoint& point) m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height()); #endif updateFixedPosition(); - m_contentLayer->setPosition(point.x(), point.y()); + m_contentLayer->setPosition(pos.x(), pos.y()); askForSync(); } @@ -368,31 +378,6 @@ void GraphicsLayerAndroid::setDrawsContent(bool drawsContent) if (m_contentLayer->isRootLayer()) return; if (m_drawsContent) { -#if ENABLE(ANDROID_OVERFLOW_SCROLL) - RenderLayer* layer = renderLayerFromClient(m_client); - if (layer) { - if (layer->hasOverflowScroll() && !m_foregroundLayer) { - m_foregroundLayer = new ScrollableLayerAndroid(); - m_foregroundClipLayer = new LayerAndroid(false); - m_foregroundClipLayer->setMasksToBounds(true); - - m_foregroundClipLayer->addChild(m_foregroundLayer); - m_contentLayer->addChild(m_foregroundClipLayer); - } else if (layer->isRootLayer() - && layer->renderer()->frame()->ownerRenderer()) { - // We have to do another check for scrollable content since an - // iframe might be compositing for other reasons. - FrameView* view = layer->renderer()->frame()->view(); - if (view->hasOverflowScroll()) { - // Replace the content layer with a scrollable layer. - LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer); - m_contentLayer->unref(); - m_contentLayer = layer; - } - } - } -#endif - m_haveContents = true; setNeedsDisplay(); } @@ -478,6 +463,77 @@ private: GraphicsLayerPaintingPhase m_originalPhase; }; +void GraphicsLayerAndroid::updateScrollingLayers() +{ +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + RenderLayer* layer = renderLayerFromClient(m_client); + if (!layer || !m_haveContents) + return; + bool hasOverflowScroll = m_foregroundLayer || m_contentLayer->contentIsScrollable(); + bool layerNeedsOverflow = layer->hasOverflowScroll(); + bool iframeNeedsOverflow = layer->isRootLayer() && + layer->renderer()->frame()->ownerRenderer() && + layer->renderer()->frame()->view()->hasOverflowScroll(); + + if (hasOverflowScroll && (layerNeedsOverflow || iframeNeedsOverflow)) { + // Already has overflow layers. + return; + } + if (!hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow) { + // Does not need overflow layers. + return; + } + if (layerNeedsOverflow || iframeNeedsOverflow) { + ASSERT(!hasOverflowScroll); + if (layerNeedsOverflow) { + ASSERT(!m_foregroundLayer && !m_foregroundClipLayer); + m_foregroundLayer = new ScrollableLayerAndroid(); + m_foregroundClipLayer = new LayerAndroid(false); + m_foregroundClipLayer->setMasksToBounds(true); + m_foregroundClipLayer->addChild(m_foregroundLayer); + m_contentLayer->addChild(m_foregroundClipLayer); + } else { + ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable()); + // No need to copy the children as they will be removed and synced. + m_contentLayer->removeChildren(); + // Replace the content layer with a scrollable layer. + LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer); + m_contentLayer->unref(); + m_contentLayer = layer; + if (m_parent) { + // The content layer has changed so the parent needs to sync + // children. + static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true; + } + } + // Need to rebuild our children based on the new structure. + m_needsSyncChildren = true; + } else { + ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow); + ASSERT(m_contentLayer); + // Remove the foreground layers. + if (m_foregroundLayer) { + m_foregroundLayer->unref(); + m_foregroundLayer = 0; + m_foregroundClipLayer->unref(); + m_foregroundClipLayer = 0; + } + // No need to copy over children. + m_contentLayer->removeChildren(); + LayerAndroid* layer = new LayerAndroid(*m_contentLayer); + m_contentLayer->unref(); + m_contentLayer = layer; + if (m_parent) { + // The content layer has changed so the parent needs to sync + // children. + static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true; + } + // Children are all re-parented. + m_needsSyncChildren = true; + } +#endif +} + bool GraphicsLayerAndroid::repaint() { LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ", @@ -506,8 +562,13 @@ bool GraphicsLayerAndroid::repaint() m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height()); // Paint everything else into the main recording canvas. phase.clear(GraphicsLayerPaintBackground); - if (!paintContext(m_foregroundLayer->recordContext(), contentsRect)) - return false; + + // Paint at 0,0. + IntSize scroll = layer->scrolledContentOffset(); + layer->scrollToOffset(0, 0, true, false); + // At this point, it doesn't matter if painting failed. + (void) paintContext(m_foregroundLayer->recordContext(), contentsRect); + layer->scrollToOffset(scroll.width(), scroll.height(), true, false); // Construct the clip layer for masking the contents. IntRect clip = layer->renderer()->absoluteBoundingBoxRect(); @@ -830,10 +891,16 @@ void GraphicsLayerAndroid::syncChildren() { if (m_needsSyncChildren) { m_contentLayer->removeChildren(); - if (m_foregroundClipLayer) + LayerAndroid* layer = m_contentLayer; + if (m_foregroundClipLayer) { m_contentLayer->addChild(m_foregroundClipLayer); + // Use the scrollable content layer as the parent of the children so + // that they move with the content. + layer = m_foregroundLayer; + layer->removeChildren(); + } for (unsigned int i = 0; i < m_children.size(); i++) - m_contentLayer->addChild(m_children[i]->platformLayer()); + layer->addChild(m_children[i]->platformLayer()); m_needsSyncChildren = false; } } @@ -857,6 +924,7 @@ void GraphicsLayerAndroid::syncCompositingState() for (unsigned int i = 0; i < m_children.size(); i++) m_children[i]->syncCompositingState(); + updateScrollingLayers(); syncChildren(); syncMask(); diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h index ce6bac1..da247ca 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h @@ -127,6 +127,7 @@ private: void syncMask(); void updateFixedPosition(); + void updateScrollingLayers(); // with SkPicture, we always repaint the entire layer's content. bool repaint(); diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp index ad71ef2..35979f6 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -75,7 +75,8 @@ LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(), m_reservedTexture(0), m_pictureUsed(0), m_requestSent(false), - m_scale(1) + m_scale(1), + m_lastComputeTextureSize(0) { m_backgroundColor = 0; @@ -123,6 +124,7 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer), m_dirty = layer.m_dirty; m_pictureUsed = layer.m_pictureUsed; m_scale = layer.m_scale; + m_lastComputeTextureSize = 0; for (int i = 0; i < layer.countChildren(); i++) addChild(layer.getChild(i)->copy())->unref(); @@ -147,7 +149,8 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(), m_drawingTexture(0), m_reservedTexture(0), m_requestSent(false), - m_scale(1) + m_scale(1), + m_lastComputeTextureSize(0) { m_backgroundColor = 0; m_dirty = false; @@ -157,28 +160,31 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(), #endif } -void LayerAndroid::removeTexture(BackedDoubleBufferedTexture* aTexture) +bool LayerAndroid::removeTexture(BackedDoubleBufferedTexture* aTexture) { LayerTexture* texture = static_cast<LayerTexture*>(aTexture); android::AutoMutex lock(m_atomicSync); + + bool textureReleased = true; if (!texture) { // remove ourself from both textures if (m_drawingTexture) - m_drawingTexture->release(this); + textureReleased &= m_drawingTexture->release(this); if (m_reservedTexture && m_reservedTexture != m_drawingTexture) - m_reservedTexture->release(this); + textureReleased &= m_reservedTexture->release(this); } else { if (m_drawingTexture && m_drawingTexture == texture) - m_drawingTexture->release(this); + textureReleased &= m_drawingTexture->release(this); if (m_reservedTexture && m_reservedTexture == texture && m_reservedTexture != m_drawingTexture) - m_reservedTexture->release(this); + textureReleased &= m_reservedTexture->release(this); } if (m_drawingTexture && m_drawingTexture->owner() != this) m_drawingTexture = 0; if (m_reservedTexture && m_reservedTexture->owner() != this) m_reservedTexture = 0; + return textureReleased; } LayerAndroid::~LayerAndroid() @@ -648,8 +654,12 @@ static inline bool compareLayerFullSize(const LayerAndroid* a, const LayerAndroi return sizeA > sizeB; } -void LayerAndroid::computeTextureSize() +void LayerAndroid::computeTextureSize(double time) { + if (m_lastComputeTextureSize + s_computeTextureDelay > time) + return; + m_lastComputeTextureSize = time; + // First, we collect the layers, computing m_layerTextureRect // as being clipped against the viewport Vector <LayerAndroid*> layers; @@ -929,7 +939,7 @@ void LayerAndroid::paintBitmapGL() // If LayerAndroid::removeTexture() is called before us, we'd have bailed // out early as texture would have been null; if it is called after us, we'd // have marked the texture has being busy, and the texture will not be - // destroy immediately. + // destroyed immediately. texture->producerAcquireContext(); TextureInfo* textureInfo = texture->producerLock(); m_atomicSync.unlock(); @@ -982,25 +992,25 @@ void LayerAndroid::contentDraw(SkCanvas* canvas) canvas->drawPicture(*m_extra); m_atomicSync.unlock(); -#ifdef LAYER_DEBUG - float w = getSize().width(); - float h = getSize().height(); - SkPaint paint; - paint.setARGB(128, 255, 0, 0); - canvas->drawLine(0, 0, w, h, paint); - canvas->drawLine(0, h, w, 0, paint); - paint.setARGB(128, 0, 255, 0); - 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); - - if (m_isFixed) { - SkPaint paint; - paint.setARGB(80, 255, 0, 0); - canvas->drawRect(m_fixedRect, paint); + if (TilesManager::instance()->getShowVisualIndicator()) { + float w = getSize().width(); + float h = getSize().height(); + SkPaint paint; + paint.setARGB(128, 255, 0, 0); + canvas->drawLine(0, 0, w, h, paint); + canvas->drawLine(0, h, w, 0, paint); + paint.setARGB(128, 0, 255, 0); + 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); + + if (m_isFixed) { + SkPaint paint; + paint.setARGB(80, 255, 0, 0); + canvas->drawRect(m_fixedRect, paint); + } } -#endif } void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h index 53e513b..0d5a878 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.h +++ b/WebCore/platform/graphics/android/LayerAndroid.h @@ -94,7 +94,7 @@ public: virtual ~LayerAndroid(); // TextureOwner methods - virtual void removeTexture(BackedDoubleBufferedTexture* texture); + virtual bool removeTexture(BackedDoubleBufferedTexture* texture); LayerTexture* texture() { return m_reservedTexture; } virtual TiledPage* page() { return 0; } @@ -111,7 +111,7 @@ public: void showLayers(int indent = 0); // Texture size functions - void computeTextureSize(); + void computeTextureSize(double time); void collect(Vector<LayerAndroid*>& layers, int& size); int clippedTextureSize() const; @@ -325,6 +325,10 @@ private: float m_scale; + // We try to not always compute the texture size, as this is quite heavy + static const double s_computeTextureDelay = 0.2; // 200 ms + double m_lastComputeTextureSize; + // 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. diff --git a/WebCore/platform/graphics/android/TextureOwner.h b/WebCore/platform/graphics/android/TextureOwner.h index c421e8a..684efac 100644 --- a/WebCore/platform/graphics/android/TextureOwner.h +++ b/WebCore/platform/graphics/android/TextureOwner.h @@ -36,7 +36,7 @@ class BackedDoubleBufferedTexture; class TextureOwner { public: virtual ~TextureOwner(); - virtual void removeTexture(BackedDoubleBufferedTexture* texture) = 0; + virtual bool removeTexture(BackedDoubleBufferedTexture* texture) = 0; virtual TiledPage* page() = 0; void addOwned(BackedDoubleBufferedTexture*); diff --git a/WebCore/platform/graphics/android/TilesManager.cpp b/WebCore/platform/graphics/android/TilesManager.cpp index 8bea60c..16fb782 100644 --- a/WebCore/platform/graphics/android/TilesManager.cpp +++ b/WebCore/platform/graphics/android/TilesManager.cpp @@ -89,6 +89,7 @@ TilesManager::TilesManager() , m_maxTextureCount(0) , m_expandedTileBounds(false) , m_generatorReady(false) + , m_showVisualIndicator(false) { XLOG("TilesManager ctor"); m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION); diff --git a/WebCore/platform/graphics/android/TilesManager.h b/WebCore/platform/graphics/android/TilesManager.h index 29b7fc1..107b121 100644 --- a/WebCore/platform/graphics/android/TilesManager.h +++ b/WebCore/platform/graphics/android/TilesManager.h @@ -108,6 +108,14 @@ public: m_expandedTileBounds = enabled; } + bool getShowVisualIndicator() { + return m_showVisualIndicator; + } + + void setShowVisualIndicator(bool showVisualIndicator) { + m_showVisualIndicator = showVisualIndicator; + } + private: TilesManager(); @@ -129,6 +137,8 @@ private: bool m_generatorReady; + bool m_showVisualIndicator; + sp<TexturesGenerator> m_pixmapsGenerationThread; android::Mutex m_texturesLock; diff --git a/WebCore/platform/graphics/android/android_graphics.cpp b/WebCore/platform/graphics/android/android_graphics.cpp index c046858..e50cfec 100644 --- a/WebCore/platform/graphics/android/android_graphics.cpp +++ b/WebCore/platform/graphics/android/android_graphics.cpp @@ -109,14 +109,8 @@ void CursorRing::draw(SkCanvas* canvas, LayerAndroid* layer, IntRect* inval) inval->unite(m_lastBounds); } -bool CursorRing::setup() +void CursorRing::setIsButton(const CachedNode* node) { - m_node->localCursorRings(m_frame, &m_rings); - if (!m_rings.size()) { - DBG_NAV_LOG("!rings.size()"); - m_viewImpl->m_hasCursorBounds = false; - return false; - } m_isButton = false; m_viewImpl->gButtonMutex.lock(); // If this is a button drawn by us (rather than webkit) do not draw the @@ -124,7 +118,7 @@ bool CursorRing::setup() // Should be in sync with recordButtons, since that will be called // before this. if (m_viewImpl->m_buttons.size() > 0) { - WebCore::Node* cursorPointer = (WebCore::Node*) m_node->nodePointer(); + WebCore::Node* cursorPointer = (WebCore::Node*) node->nodePointer(); Container* end = m_viewImpl->m_buttons.end(); for (Container* ptr = m_viewImpl->m_buttons.begin(); ptr != end; ptr++) { if (ptr->matches(cursorPointer)) { @@ -134,6 +128,17 @@ bool CursorRing::setup() } } m_viewImpl->gButtonMutex.unlock(); +} + +bool CursorRing::setup() +{ + m_node->localCursorRings(m_frame, &m_rings); + if (!m_rings.size()) { + DBG_NAV_LOG("!rings.size()"); + m_viewImpl->m_hasCursorBounds = false; + return false; + } + setIsButton(m_node); m_bounds = m_node->localBounds(m_frame); m_viewImpl->updateCursorBounds(m_root, m_frame, m_node); diff --git a/WebCore/platform/graphics/android/android_graphics.h b/WebCore/platform/graphics/android/android_graphics.h index 9f52a27..be309a6 100644 --- a/WebCore/platform/graphics/android/android_graphics.h +++ b/WebCore/platform/graphics/android/android_graphics.h @@ -54,6 +54,7 @@ public: CursorRing(WebViewCore* core) : m_viewImpl(core) {} virtual ~CursorRing() {} virtual void draw(SkCanvas* , LayerAndroid* , IntRect* ); + void setIsButton(const CachedNode* ); bool setup(); private: friend class WebView; |