diff options
9 files changed, 72 insertions, 29 deletions
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index 85fa23f..09c647b 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -183,7 +183,7 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval TilesManager::instance()->setShowVisualIndicator(showVisualIndicator); } -void GLWebViewState::setRings(Vector<IntRect>& rings, bool isPressed) +void GLWebViewState::setRings(Vector<IntRect>& rings, bool isPressed, bool isButton) { android::Mutex::Autolock lock(m_baseLayerLock); m_displayRings = true; @@ -195,6 +195,7 @@ void GLWebViewState::setRings(Vector<IntRect>& rings, bool isPressed) m_rings.op(rings.at(i), SkRegion::kUnion_Op); } m_ringsIsPressed = isPressed; + m_ringsIsButton = isButton; } void GLWebViewState::invalRegion(const SkRegion& region) @@ -277,6 +278,10 @@ void GLWebViewState::drawFocusRing(SkRect& srcRect) RING_COLOR_G, RING_COLOR_B); + if (srcRect.fRight <= srcRect.fLeft || srcRect.fBottom <= srcRect.fTop) { + // Invalid rect, reject it + return; + } TilesManager::instance()->shader()->drawQuad(srcRect, m_focusRingTexture, RING_COLOR_ALPHA); } @@ -284,6 +289,16 @@ void GLWebViewState::drawFocusRing(SkRect& srcRect) void GLWebViewState::paintExtras() { if (m_displayRings && !m_rings.isEmpty()) { + // Update the clip + SkIRect skbounds = m_rings.getBounds(); + if (skbounds.isEmpty()) + return; + FloatRect glclip; + glclip.setX(skbounds.fLeft); + glclip.setY(skbounds.fTop); + glclip.setWidth(skbounds.fRight - skbounds.fLeft); + glclip.setHeight(skbounds.fBottom - skbounds.fTop); + TilesManager::instance()->shader()->clip(glclip); if (m_ringsIsPressed) { SkRegion::Iterator rgnIter(m_rings); while (!rgnIter.done()) { @@ -294,6 +309,8 @@ void GLWebViewState::paintExtras() rgnIter.next(); } } + if (m_ringsIsButton && m_ringsIsPressed) + return; SkPath path; if (!m_rings.getBoundaryPath(&path)) return; @@ -589,9 +606,6 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, double currentTime = setupDrawing(rect, viewport, webViewRect, titleBarHeight, clip, scale); bool ret = baseLayer->drawGL(currentTime, compositedRoot, rect, viewport, scale, buffersSwappedPtr); - // Reset the clip to make sure we can draw the rings. If this isn't done, the - // current clip will be the clip of whatever layer was last drawn - TilesManager::instance()->shader()->clip(clip); paintExtras(); glBindBuffer(GL_ARRAY_BUFFER, 0); diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h index 6c7d31e..27e8148 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.h +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h @@ -177,7 +177,7 @@ public: void setExtra(BaseLayerAndroid*, SkPicture&, const IntRect&, bool allowSame); void paintExtras(); - void setRings(Vector<IntRect>& rings, bool isPressed); + void setRings(Vector<IntRect>& rings, bool isPressed, bool isButton); void resetRings(); void drawFocusRing(SkRect& rect); @@ -271,6 +271,7 @@ private: bool m_displayRings; SkRegion m_rings; bool m_ringsIsPressed; + bool m_ringsIsButton; int m_focusRingTexture; bool m_isScrolling; diff --git a/Source/WebCore/platform/graphics/android/ImageTexture.h b/Source/WebCore/platform/graphics/android/ImageTexture.h index 7e51d2b..c2ea77c 100644 --- a/Source/WebCore/platform/graphics/android/ImageTexture.h +++ b/Source/WebCore/platform/graphics/android/ImageTexture.h @@ -70,6 +70,7 @@ public: void release(); unsigned int refCount() { return m_refCount; } SkBitmapRef* imageRef() { return m_imageRef; } + SkBitmap* bitmap() { return m_image; } private: diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h index 38d867f..cd52937 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h @@ -57,6 +57,7 @@ namespace android { class DrawExtra; void serializeLayer(WebCore::LayerAndroid* layer, SkWStream* stream); WebCore::LayerAndroid* deserializeLayer(SkStream* stream); +void cleanupImageRefs(WebCore::LayerAndroid* layer); } using namespace android; @@ -266,8 +267,10 @@ public: void setIsIframe(bool isIframe) { m_isIframe = isIframe; } float zValue() const { return m_zValue; } + // ViewStateSerializer friends friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream); friend LayerAndroid* android::deserializeLayer(SkStream* stream); + friend void android::cleanupImageRefs(LayerAndroid* layer); PaintedSurface* texture() { return m_texture; } void assignTextureTo(LayerAndroid* newTree); @@ -330,16 +333,14 @@ private: float m_anchorPointZ; float m_drawOpacity; - // Note that m_recordingPicture and m_contentsImage are mutually exclusive; + // Note that m_recordingPicture and m_imageRef are mutually exclusive; // m_recordingPicture is used when WebKit is asked to paint the layer's - // content, while m_contentsImage contains an image that we directly + // content, while m_imageRef contains an image that we directly // composite, using the layer's dimensions as a destination rect. // We do this as if the layer only contains an image, directly compositing // it is a much faster method than using m_recordingPicture. SkPicture* m_recordingPicture; - SkBitmap* m_contentsImage; - typedef HashMap<pair<String, int>, RefPtr<AndroidAnimation> > KeyframesMap; KeyframesMap m_animations; diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index cf66de5..f077d48 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -458,11 +458,11 @@ void TilesManager::showImages() } } -ImageTexture* TilesManager::getTextureForImage(SkBitmapRef* img) +ImageTexture* TilesManager::getTextureForImage(SkBitmapRef* img, bool retain) { android::Mutex::Autolock lock(m_imagesLock); ImageTexture* image = m_images.get(img); - if (image) + if (retain && image) image->retain(); return image; } diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h index 071aa88..1549581 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.h +++ b/Source/WebCore/platform/graphics/android/TilesManager.h @@ -179,7 +179,7 @@ public: } void addImage(SkBitmapRef* img); void removeImage(SkBitmapRef* img); - ImageTexture* getTextureForImage(SkBitmapRef* img); + ImageTexture* getTextureForImage(SkBitmapRef* img, bool retain = true); void showImages(); private: diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp index e757080..4f4f553 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.cpp +++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp @@ -1533,7 +1533,13 @@ bool RenderLayerCompositor::requiresCompositingForPlugin(RenderObject* renderer) // Don't go into compositing mode if height or width are zero, or size is 1x1. IntRect contentBox = pluginRenderer->contentBoxRect(); +#if PLATFORM(ANDROID) + // allow all plugins including 1x1 to be composited, so that they are drawn, + // and acquire an ANativeWindow on the UI thread + return contentBox.height() * contentBox.width() > 0; +#else return contentBox.height() * contentBox.width() > 1; +#endif } bool RenderLayerCompositor::requiresCompositingForFrame(RenderObject* renderer) const diff --git a/Source/WebKit/android/jni/ViewStateSerializer.cpp b/Source/WebKit/android/jni/ViewStateSerializer.cpp index b3556c3..c896637 100644 --- a/Source/WebKit/android/jni/ViewStateSerializer.cpp +++ b/Source/WebKit/android/jni/ViewStateSerializer.cpp @@ -32,6 +32,7 @@ #include "PictureSet.h" #include "ScrollableLayerAndroid.h" #include "SkPicture.h" +#include "TilesManager.h" #include <JNIUtility.h> #include <JNIHelp.h> @@ -109,6 +110,11 @@ static BaseLayerAndroid* nativeDeserializeViewState(JNIEnv* env, jobject, jobjec if (childLayer) layer->addChild(childLayer); } + // Now double back and delete any imageRefs + for (int i = 0; i < layer->countChildren(); i++) { + LayerAndroid* childLayer = static_cast<LayerAndroid*>(layer->getChild(i)); + cleanupImageRefs(childLayer); + } delete stream; return layer; } @@ -290,12 +296,15 @@ void serializeLayer(LayerAndroid* layer, SkWStream* stream) stream->writeBool(layer->m_preserves3D); stream->writeScalar(layer->m_anchorPointZ); stream->writeScalar(layer->m_drawOpacity); - bool hasContentsImage = layer->m_contentsImage != 0; + bool hasContentsImage = layer->m_imageRef != 0; stream->writeBool(hasContentsImage); if (hasContentsImage) { SkFlattenableWriteBuffer buffer(1024); buffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag); - layer->m_contentsImage->flatten(buffer); + ImageTexture* imagetexture = + TilesManager::instance()->getTextureForImage(layer->m_imageRef, false); + if (imagetexture && imagetexture->bitmap()) + imagetexture->bitmap()->flatten(buffer); stream->write32(buffer.size()); buffer.writeToStream(stream); } @@ -374,8 +383,12 @@ LayerAndroid* deserializeLayer(SkStream* stream) SkAutoMalloc storage(size); stream->read(storage.get(), size); SkFlattenableReadBuffer buffer(storage.get(), size); - layer->m_contentsImage = new SkBitmap(); - layer->m_contentsImage->unflatten(buffer); + SkBitmap contentsImage; + contentsImage.unflatten(buffer); + SkBitmapRef* imageRef = new SkBitmapRef(contentsImage); + layer->setContentsImage(imageRef); + // We delay deleting the imageRef until after deserialization to make + // sure we have unique keys } bool hasRecordingPicture = stream->readBool(); if (hasRecordingPicture) { @@ -404,6 +417,17 @@ LayerAndroid* deserializeLayer(SkStream* stream) return layer; } +void cleanupImageRefs(LayerAndroid* layer) +{ + if (!layer) + return; + int count = layer->countChildren(); + for (int i = 0; i < count; i++) + cleanupImageRefs(layer->getChild(i)); + if (layer->m_imageRef) + delete layer->m_imageRef; +} + /* * JNI registration */ diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp index 7aae758..13e1f5f 100644 --- a/Source/WebKit/android/nav/WebView.cpp +++ b/Source/WebKit/android/nav/WebView.cpp @@ -83,6 +83,8 @@ #define TRIM_MEMORY_BACKGROUND 40 // Moderate free (clear cached tiles, keep visible ones) #define TRIM_MEMORY_UI_HIDDEN 20 +// Duration to show the pressed cursor ring +#define PRESSED_STATE_DURATION 400 namespace android { @@ -282,6 +284,7 @@ void hideCursor() return; DBG_NAV_LOG(""); hideCursor(root); + viewInvalidate(); } void hideCursor(CachedRoot* root) @@ -289,7 +292,6 @@ void hideCursor(CachedRoot* root) DBG_NAV_LOG("inner"); m_viewImpl->m_hasCursorBounds = false; root->hideCursor(); - viewInvalidate(); } #if DUMP_NAV_CACHE @@ -556,7 +558,7 @@ bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect, WebCore::In break; case DrawExtrasCursorRing: if (drawCursorPreamble(root) && m_ring.setup()) { - if (!m_ring.m_isButton) + if (m_ring.m_isPressed || m_ringAnimationEnd == UINT_MAX) extra = &m_ring; drawCursorPostamble(); } @@ -574,7 +576,7 @@ bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect, WebCore::In if (extra) { if (extra == &m_ring) { WTF::Vector<IntRect> rings; - if (root == m_ring.m_frame) + if (!m_ring.m_isButton && root == m_ring.m_frame) rings = m_ring.rings(); else { // TODO: Fix the navcache to work with layers correctly @@ -584,11 +586,12 @@ bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect, WebCore::In for (size_t i = 0; i < m_ring.m_node->rings().size(); i++) { IntRect rect = m_ring.m_node->rings().at(i); rect = m_ring.m_frame->adjustBounds(m_ring.m_node, rect); - rect.inflate(4); + if (!m_ring.m_isButton) + rect.inflate(4); rings.append(rect); } } - m_glWebViewState->setRings(rings, m_ring.m_isPressed); + m_glWebViewState->setRings(rings, m_ring.m_isPressed, m_ring.m_isButton); extra = 0; } else { LayerAndroid mainPicture(m_navPictureUI); @@ -598,13 +601,6 @@ bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect, WebCore::In extra->draw(canvas, &mainPicture, &rect); picture.endRecording(); } - } else if (root && extras == DrawExtrasCursorRing && m_ring.m_isButton) { - const CachedFrame* cachedFrame; - const CachedNode* cachedCursor = root->currentCursor(&cachedFrame); - if (cachedCursor) { - rect = cachedCursor->bounds(cachedFrame); - allowSame = true; - } } m_glWebViewState->setExtra(m_baseLayer, picture, rect, allowSame); @@ -1246,7 +1242,7 @@ void setFindIsEmpty() void showCursorTimed() { DBG_NAV_LOG(""); - m_ringAnimationEnd = SkTime::GetMSecs() + 500; + m_ringAnimationEnd = SkTime::GetMSecs() + PRESSED_STATE_DURATION; viewInvalidate(); } |