diff options
Diffstat (limited to 'Source')
17 files changed, 221 insertions, 109 deletions
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index a6bf6af..3975545 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -531,8 +531,8 @@ void GraphicsLayerAndroid::updateScrollingLayers() if (layerNeedsOverflow) { ASSERT(!m_foregroundLayer && !m_foregroundClipLayer); m_foregroundLayer = new ScrollableLayerAndroid(layer); + m_foregroundLayer->setIntrinsicallyComposited(true); - // TODO: can clip layer be set to not intrinsically composited? m_foregroundClipLayer = new LayerAndroid(layer); m_foregroundClipLayer->setMasksToBounds(true); m_foregroundClipLayer->addChild(m_foregroundLayer); diff --git a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp index 62a5824..3241a61 100644 --- a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp @@ -79,8 +79,10 @@ void BaseLayerAndroid::updatePositionsRecursive(const SkRect& visibleContentRect { updateLayerPositions(visibleContentRect); TransformationMatrix ident; - FloatRect clip(0, 0, 1e10, 1e10); - updateGLPositionsAndScale(ident, clip, 1, state()->scale()); + FloatRect clip(0, 0, getWidth(), getHeight()); + + float scale = state() ? state()->scale() : 1.0f; + updateGLPositionsAndScale(ident, clip, 1, scale); } ForegroundBaseLayerAndroid::ForegroundBaseLayerAndroid(LayerContent* content) diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp index feb2d99..7a25e7f 100644 --- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp @@ -133,11 +133,13 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), m_replicatedLayerPosition = layer.m_replicatedLayerPosition; +#ifdef ABSOLUTE_POSITION // If we have absolute elements, we may need to reorder them if they // are followed by another layer that is not also absolutely positioned. // (as absolutely positioned elements are out of the normal flow) bool hasAbsoluteChildren = false; bool hasOnlyAbsoluteFollowers = true; + for (int i = 0; i < layer.countChildren(); i++) { if (layer.getChild(i)->isPositionAbsolute()) { hasAbsoluteChildren = true; @@ -169,6 +171,10 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), for (int i = 0; i < layer.countChildren(); i++) addChild(layer.getChild(i)->copy())->unref(); } +#else + for (int i = 0; i < layer.countChildren(); i++) + addChild(layer.getChild(i)->copy())->unref(); +#endif KeyframesMap::const_iterator end = layer.m_animations.end(); for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) { @@ -572,9 +578,9 @@ void LayerAndroid::showLayer(int indent) IntRect visible = visibleContentArea(); IntRect clip(m_clippingRect.x(), m_clippingRect.y(), m_clippingRect.width(), m_clippingRect.height()); - ALOGD("%s %s %s (%d) [%d:%x - 0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) " + ALOGD("%s s:%x %s %s (%d) [%d:%x - 0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) " "clip (%d, %d, %d, %d) %s %s m_content(%x), pic w: %d h: %d originalLayer: %x %d", - spaces, m_haveClip ? "CLIP LAYER" : "", subclassName().ascii().data(), + spaces, m_surface, m_haveClip ? "CLIP LAYER" : "", subclassName().ascii().data(), subclassType(), uniqueId(), this, m_owningLayer, needsTexture() ? "needsTexture" : "", m_imageCRC ? "hasImage" : "", @@ -620,19 +626,8 @@ bool LayerAndroid::canJoinSurface(Surface* surface) LayerAndroid* lastLayer = surface->getFirstLayer(); - // isolate non-tiled layers - // TODO: remove this check so that multiple tiled layers with a invisible - // one inbetween can be merged - if (!needsTexture() || !lastLayer->needsTexture()) - return false; - - // isolate clipped layers - // TODO: paint correctly with clip when merged - if (m_haveClip || lastLayer->m_haveClip) - return false; - // isolate intrinsically composited layers - if (m_intrinsicallyComposited || lastLayer->m_intrinsicallyComposited) + if (needsIsolatedSurface() || lastLayer->needsIsolatedSurface()) return false; // TODO: investigate potential for combining transformed layers @@ -640,11 +635,6 @@ bool LayerAndroid::canJoinSurface(Surface* surface) || !lastLayer->m_drawTransform.isIdentityOrTranslation()) return false; - // 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? return true; #endif @@ -664,24 +654,26 @@ void LayerAndroid::assignSurfaces(LayerMergeState* mergeState) } #ifdef LAYER_MERGING_DEBUG - ALOGD("%*slayer %p(%d) rl %p %s surface %p, fixed %d, anim %d, intCom %d, haveClip %d scroll %d", + ALOGD("%*slayer %p(%d) rl %p %s surface %p lvl: %d, fixed %d, anim %d, intCom %d, haveClip %d scroll %d hasText (layer: %d surface: %d) hasContent %d size %.2f x %.2f", 4*mergeState->depth, "", this, m_uniqueId, m_owningLayer, needNewSurface ? "NEW" : "joins", mergeState->currentSurface, + mergeState->nonMergeNestedLevel, isPositionFixed(), m_animations.size() != 0, m_intrinsicallyComposited, m_haveClip, - contentIsScrollable()); + contentIsScrollable(), m_content ? m_content->hasText() : -1, + mergeState->currentSurface ? mergeState->currentSurface->hasText() : -1, + needsTexture(), getWidth(), getHeight()); #endif mergeState->currentSurface->addLayer(this, m_drawTransform); m_surface = mergeState->currentSurface; - if (m_haveClip || contentIsScrollable() || isPositionFixed()) { + if (contentIsScrollable() || isPositionFixed()) { // disable layer merging within the children of these layer types mergeState->nonMergeNestedLevel++; } - // 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 @@ -699,13 +691,17 @@ void LayerAndroid::assignSurfaces(LayerMergeState* mergeState) mergeState->depth--; } - if (m_haveClip || contentIsScrollable() || isPositionFixed()) { + if (contentIsScrollable() || isPositionFixed()) { // re-enable joining mergeState->nonMergeNestedLevel--; // disallow layers painting after to join with this surface mergeState->currentSurface = 0; } + + if (needsIsolatedSurface()) + mergeState->currentSurface = 0; + } // We call this in WebViewCore, when copying the tree of layers. diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h index c7c795f..52df0cf 100644 --- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h @@ -281,6 +281,9 @@ public: Surface* surface() { return m_surface; } void setIntrinsicallyComposited(bool intCom) { m_intrinsicallyComposited = intCom; } + bool needsIsolatedSurface() { + return (needsTexture() && m_intrinsicallyComposited) || m_animations.size(); + } int setHwAccelerated(bool hwAccelerated); diff --git a/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp index 2819baa..6ff71d9 100644 --- a/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp @@ -198,11 +198,12 @@ const TransformationMatrix* ImageTexture::transform() if (!m_layer) return 0; - IntRect layerArea = m_layer->fullContentArea(); - 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()); TransformationMatrix d = *(m_layer->drawTransform()); TransformationMatrix m; + float scaleW = 1.0f; + float scaleH = 1.0f; + getImageToLayerScale(&scaleW, &scaleH); + m.scaleNonUniform(scaleW, scaleH); m_layerMatrix = d.multiply(m); return &m_layerMatrix; @@ -228,6 +229,24 @@ bool ImageTexture::paint(SkCanvas* canvas) return true; } +void ImageTexture::getImageToLayerScale(float* scaleW, float* scaleH) const +{ + if (!scaleW || !scaleH) + return; + + + IntRect layerArea = m_layer->fullContentArea(); + + if (layerArea.width() == 0 || layerArea.height() == 0) + return; + + // calculate X, Y scale difference between image pixel coordinates and layer + // content coordinates + + *scaleW = static_cast<float>(layerArea.width()) / static_cast<float>(m_image->width()); + *scaleH = static_cast<float>(layerArea.height()) / static_cast<float>(m_image->height()); +} + void ImageTexture::drawGL(LayerAndroid* layer, float opacity, FloatPoint* offset) { @@ -242,6 +261,16 @@ void ImageTexture::drawGL(LayerAndroid* layer, if (m_tileGrid) { bool force3dContentVisible = true; IntRect visibleContentArea = m_layer->visibleContentArea(force3dContentVisible); + + // transform visibleContentArea size to image size + float scaleW = 1.0f; + float scaleH = 1.0f; + getImageToLayerScale(&scaleW, &scaleH); + visibleContentArea.setX(visibleContentArea.x() / scaleW); + visibleContentArea.setWidth(visibleContentArea.width() / scaleW); + visibleContentArea.setY(visibleContentArea.y() / scaleH); + visibleContentArea.setHeight(visibleContentArea.height() / scaleH); + const TransformationMatrix* transformation = transform(); if (offset) m_layerMatrix.translate(offset->x(), offset->y()); diff --git a/Source/WebCore/platform/graphics/android/rendering/ImageTexture.h b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.h index 0571b83..99bec90 100644 --- a/Source/WebCore/platform/graphics/android/rendering/ImageTexture.h +++ b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.h @@ -95,6 +95,7 @@ public: private: const TransformationMatrix* transform(); + void getImageToLayerScale(float* scaleW, float* scaleH) const; SkBitmapRef* m_imageRef; SkBitmap* m_image; diff --git a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp index 2ec2659..7e4e918 100644 --- a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp @@ -226,19 +226,20 @@ void Surface::prepareGL(bool layerTilesDisabled, bool updateWithBlit) bool Surface::drawGL(bool layerTilesDisabled) { bool tilesDisabled = layerTilesDisabled && !isBase(); - if (!getFirstLayer()->visible()) + if (singleLayer() && !getFirstLayer()->visible()) return false; bool isBaseLayer = isBase() || getFirstLayer()->subclassType() == LayerAndroid::FixedBackgroundImageLayer || getFirstLayer()->subclassType() == LayerAndroid::ForegroundBaseLayer; - if (!isBaseLayer) { - // TODO: why are clipping regions wrong for base layer? - FloatRect drawClip = getFirstLayer()->drawClip(); - FloatRect clippingRect = TilesManager::instance()->shader()->rectInInvViewCoord(drawClip); - TilesManager::instance()->shader()->clip(clippingRect); + FloatRect drawClip = getFirstLayer()->drawClip(); + if (!singleLayer()) { + for (unsigned int i = 1; i < m_layers.size(); i++) + drawClip.unite(m_layers[i]->drawClip()); } + FloatRect clippingRect = TilesManager::instance()->shader()->rectInInvViewCoord(drawClip); + TilesManager::instance()->shader()->clip(clippingRect); bool askRedraw = false; if (m_surfaceBacking && !tilesDisabled) { diff --git a/Source/WebCore/platform/graphics/android/rendering/Surface.h b/Source/WebCore/platform/graphics/android/rendering/Surface.h index a79a286..7100125 100644 --- a/Source/WebCore/platform/graphics/android/rendering/Surface.h +++ b/Source/WebCore/platform/graphics/android/rendering/Surface.h @@ -93,7 +93,7 @@ public: LayerMergeState(Vector<Surface*>* const allGroups) : surfaceList(allGroups) , currentSurface(0) - , nonMergeNestedLevel(-1) // start at -1 to ignore first LayerAndroid's clipping + , nonMergeNestedLevel(0) , depth(0) {} diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp index 558d720..f3415af 100644 --- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp @@ -245,4 +245,14 @@ void SurfaceCollection::updateLayerPositions(const SkRect& visibleContentRect) #endif } +int SurfaceCollection::backedSize() +{ + int count = 0; + for (unsigned int i = 0; i < m_surfaces.size(); i++) { + if (m_surfaces[i]->needsTexture()) + count++; + } + return count; +} + } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h index 8debd6a..b502142 100644 --- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h @@ -67,6 +67,9 @@ public: bool hasCompositedAnimations(); void updateScrollableLayer(int layerId, int x, int y); + int size() { return m_surfaces.size(); } + int backedSize(); + private: void updateLayerPositions(const SkRect& visibleContentRect); BaseLayerAndroid* m_compositedRoot; diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp index 8f2dcba..b4fd699 100644 --- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp @@ -296,6 +296,12 @@ int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, GLUtils::clearBackgroundIfOpaque(&background); } +#ifdef DEBUG + ALOGV("Drawing %d / %d surfaces", + m_drawingCollection ? m_drawingCollection->backedSize() : -1, + m_drawingCollection ? m_drawingCollection->size() : -1); +#endif + if (m_drawingCollection && m_drawingCollection->drawGL(visibleContentRect)) returnFlags |= DrawGlInfo::kStatusDraw; diff --git a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp index 41d6709..f273091 100644 --- a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp @@ -265,9 +265,9 @@ void TransferQueue::setHasGLContext(bool hasContext) void TransferQueue::emptyAndAbandonQueue() { for (int i = 0 ; i < m_transferQueueSize; i++) - m_transferQueue[i].status = emptyItem; + clearItemInTranferQueue(i); m_emptyItemCount = m_transferQueueSize; - m_pureColorTileQueue.clear(); + clearPureColorQueue(); if (m_sharedSurfaceTexture.get()) { m_sharedSurfaceTexture->abandon(); @@ -295,7 +295,7 @@ void TransferQueue::setPendingDiscard() if (m_transferQueue[i].status == pendingBlit) m_transferQueue[i].status = pendingDiscard; - m_pureColorTileQueue.clear(); + clearPureColorQueue(); bool GLContextExisted = getHasGLContext(); // Unblock the Tex Gen thread first before Tile Page deletion. @@ -307,6 +307,15 @@ void TransferQueue::setPendingDiscard() m_transferQueueItemCond.signal(); } +void TransferQueue::clearPureColorQueue() +{ + for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) { + SkSafeUnref(m_pureColorTileQueue[i].savedTilePainter); + m_pureColorTileQueue[i].savedTilePainter = 0; + } + m_pureColorTileQueue.clear(); +} + void TransferQueue::updatePureColorTiles() { for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) { @@ -324,7 +333,7 @@ void TransferQueue::updatePureColorTiles() ALOGV("Warning: Don't expect an emptyItem here."); } } - m_pureColorTileQueue.clear(); + clearPureColorQueue(); } // Call on UI thread to copy from the shared Surface Texture to the Tile's texture. @@ -363,8 +372,7 @@ void TransferQueue::updateDirtyTiles() if (result != OK) ALOGE("unexpected error: updateTexImage return %d", result); } - m_transferQueue[index].savedTilePtr = 0; - m_transferQueue[index].status = emptyItem; + if (obsoleteTile) { ALOGV("Warning: the texture is obsolete for this baseTile"); index = (index + 1) % m_transferQueueSize; @@ -391,7 +399,7 @@ void TransferQueue::updateDirtyTiles() destTexture->setPure(false); destTexture->transferComplete(); - + clearItemInTranferQueue(index); ALOGV("Blit tile x, y %d %d with dest texture %p to destTexture->m_ownTextureId %d", m_transferQueue[index].savedTilePtr, destTexture, @@ -469,6 +477,14 @@ void TransferQueue::addItemInPureColorQueue(const TileRenderInfo* renderInfo) m_pureColorTileQueue.append(data); } +void TransferQueue::clearItemInTranferQueue(int index) +{ + m_transferQueue[index].savedTilePtr = 0; + SkSafeUnref(m_transferQueue[index].savedTilePainter); + m_transferQueue[index].savedTilePainter = 0; + m_transferQueue[index].status = emptyItem; +} + // Translates the info from TileRenderInfo and others to TileTransferData. // This is used by pure color tiles and normal tiles. void TransferQueue::addItemCommon(const TileRenderInfo* renderInfo, @@ -476,6 +492,8 @@ void TransferQueue::addItemCommon(const TileRenderInfo* renderInfo, TileTransferData* data) { data->savedTileTexturePtr = renderInfo->baseTile->backTexture(); + data->savedTilePainter = renderInfo->tilePainter; + SkSafeRef(data->savedTilePainter); data->savedTilePtr = renderInfo->baseTile; data->status = pendingBlit; data->uploadType = type; @@ -552,10 +570,7 @@ void TransferQueue::cleanupPendingDiscard() tile->discardBackTexture(); ALOGV("transfer queue discarded tile %p, removed texture", tile); } - - m_transferQueue[index].savedTilePtr = 0; - m_transferQueue[index].savedTileTexturePtr = 0; - m_transferQueue[index].status = emptyItem; + clearItemInTranferQueue(index); } index = (index + 1) % m_transferQueueSize; } diff --git a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h index 44d3c37..9d33ff5 100644 --- a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h +++ b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h @@ -37,6 +37,7 @@ namespace WebCore { class Tile; +class TilePainter; class TileTexture; struct GLState { @@ -75,6 +76,7 @@ public: TileTransferData() : status(emptyItem) , savedTilePtr(0) + , savedTilePainter(0) , savedTileTexturePtr(0) , uploadType(DEFAULT_UPLOAD_TYPE) , bitmap(0) @@ -90,6 +92,7 @@ public: TransferItemStatus status; Tile* savedTilePtr; + TilePainter* savedTilePainter; // Ref count the tilePainter to keep the tile alive. TileTexture* savedTileTexturePtr; TextureUploadType uploadType; // This is only useful in Cpu upload code path, so it will be dynamically @@ -178,10 +181,12 @@ private: GLuint srcTexId, GLenum srcTexTarget, int index); + void clearItemInTranferQueue(int index); void addItemCommon(const TileRenderInfo* renderInfo, TextureUploadType type, TileTransferData* data); void updatePureColorTiles(); + void clearPureColorQueue(); // Note that the m_transferQueueIndex only changed in the TexGen thread // where we are going to move on to update the next item in the queue. int m_transferQueueIndex; diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp index 7d70533..f5dddc0 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.cpp +++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp @@ -302,6 +302,7 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update bool layersChanged = false; #if ENABLE(COMPOSITED_FIXED_ELEMENTS) + compState.m_positionedSibling = false; compState.m_hasFixedElement = false; #endif #if ENABLE(ANDROID_OVERFLOW_SCROLL) @@ -657,27 +658,25 @@ bool RenderLayerCompositor::checkForPositionedElements(Vector<RenderLayer*>* lis // composited. The layers' surfaces will be merged if needed UI-side. for (int j = 0; j < listSize; ++j) { RenderLayer* currentLayer = list->at(j); - if (currentLayer->shouldComposite()) - continue; - if (currentLayer->isFixed() && needsToBeComposited(currentLayer)) { - haveFixedLayer = j; - fixedSibling = true; - } + // clear the composited flag first + currentLayer->setShouldComposite(false); - // Bypass fixed layers with a width or height or 1 or less... - IntRect currentLayerBounds = currentLayer->renderer()->localToAbsoluteQuad( - FloatRect(currentLayer->localBoundingBox())).enclosingBoundingBox(); - if ((currentLayerBounds.width() <= 1 - || currentLayerBounds.height() <= 1) - && haveFixedLayer == j) { - haveFixedLayer = -1; - fixedSibling = false; + if (currentLayer->isFixed() && needsToBeComposited(currentLayer)) { + // Ignore fixed layers with a width or height or 1 or less... + IntRect currentLayerBounds = currentLayer->renderer()->localToAbsoluteQuad( + FloatRect(currentLayer->localBoundingBox())).enclosingBoundingBox(); + if (currentLayerBounds.width() > 1 && currentLayerBounds.height() > 1) { + haveFixedLayer = j; + fixedSibling = true; + } + continue; } - if (haveFixedLayer != -1 && haveFixedLayer != j) + if (haveFixedLayer != -1) currentLayer->setShouldComposite(true); } + return positionedSibling || fixedSibling; } @@ -867,6 +866,8 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O #if ENABLE(COMPOSITED_FIXED_ELEMENTS) if (childState.m_hasFixedElement) compositingState.m_hasFixedElement = true; + if (childState.m_positionedSibling) + compositingState.m_positionedSibling = true; #endif #if ENABLE(ANDROID_OVERFLOW_SCROLL) if (childState.m_hasScrollableElement) @@ -889,7 +890,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O #if ENABLE(ANDROID_OVERFLOW_SCROLL) // We also need to check that we don't have a scrollable layer, as this // would not have set the m_subtreeIsCompositing flag - if (layer->isRootLayer() && !childState.m_subtreeIsCompositing && !childState.m_hasScrollableElement && !childState.m_hasFixedElement && !requiresCompositingLayer(layer) && !m_forceCompositingMode) { + if (layer->isRootLayer() && !childState.m_subtreeIsCompositing + && !childState.m_hasScrollableElement && !childState.m_positionedSibling && !childState.m_hasFixedElement + && !requiresCompositingLayer(layer) && !m_forceCompositingMode) { #else if (layer->isRootLayer() && !childState.m_subtreeIsCompositing && !requiresCompositingLayer(layer) && !m_forceCompositingMode) { #endif @@ -1425,13 +1428,8 @@ bool RenderLayerCompositor::requiresCompositingForAndroidLayers(const RenderLaye #if ENABLE(COMPOSITED_FIXED_ELEMENTS) // Enable composited layers (for fixed elements) - if (layer->isFixed()) { - // Skip fixed layers with a width or height of 1 or less... - IntRect bounds = layer->renderer()->localToAbsoluteQuad( - FloatRect(layer->localBoundingBox())).enclosingBoundingBox(); - if (bounds.width() > 1 && bounds.height() > 1) - return true; - } + if (layer->isFixed()) + return true; #endif if (layer->renderer()->isCanvas()) diff --git a/Source/WebKit/android/jni/PicturePile.cpp b/Source/WebKit/android/jni/PicturePile.cpp index f3e46ac..ccdfa59 100644 --- a/Source/WebKit/android/jni/PicturePile.cpp +++ b/Source/WebKit/android/jni/PicturePile.cpp @@ -144,9 +144,11 @@ void PicturePile::setSize(const IntSize& size) // TODO: See above about just adding invals for new content m_pile.clear(); m_webkitInvals.clear(); - IntRect area(0, 0, size.width(), size.height()); - m_webkitInvals.append(area); - m_pile.append(area); + if (!size.isEmpty()) { + IntRect area(0, 0, size.width(), size.height()); + m_webkitInvals.append(area); + m_pile.append(area); + } } void PicturePile::updatePicturesIfNeeded(PicturePainter* painter) diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index af76daa..8870b70 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -617,7 +617,7 @@ WebCore::Node* WebViewCore::currentFocus() return focusedFrame()->document()->focusedNode(); } -void WebViewCore::recordPicturePile() +void WebViewCore::layout() { TRACE_METHOD(); @@ -631,9 +631,7 @@ void WebViewCore::recordPicturePile() // it's fine for layout to gather invalidates, but defeat sending a message // back to java to call webkitDraw, since we're already in the middle of // doing that - m_skipContentDraw = true; bool success = layoutIfNeededRecursive(m_mainFrame); - m_skipContentDraw = false; // We may be mid-layout and thus cannot draw. if (!success) @@ -699,16 +697,16 @@ void WebViewCore::recordPicturePile() view->forceLayout(); // Relayout similar to above - m_skipContentDraw = true; - bool success = layoutIfNeededRecursive(m_mainFrame); - m_skipContentDraw = false; - if (!success) - return; - - // Set the computed content width - width = view->contentsWidth(); - height = view->contentsHeight(); + layoutIfNeededRecursive(m_mainFrame); } +} + +void WebViewCore::recordPicturePile() +{ + // if the webkit page dimensions changed, discard the pictureset and redraw. + WebCore::FrameView* view = m_mainFrame->view(); + int width = view ? view->contentsWidth() : 0; + int height = view ? view->contentsHeight() : 0; m_content.setSize(IntSize(width, height)); @@ -732,6 +730,11 @@ bool WebViewCore::focusBoundsChanged() void WebViewCore::paintContents(WebCore::GraphicsContext* gc, WebCore::IntRect& dirty) { WebCore::FrameView* view = m_mainFrame->view(); + if (!view) { + gc->setFillColor(WebCore::Color::white, WebCore::ColorSpaceDeviceRGB); + gc->fillColor(); + return; + } IntPoint origin = view->minimumScrollPosition(); IntRect drawArea = dirty; @@ -813,7 +816,7 @@ void WebViewCore::notifyAnimationStarted() } -BaseLayerAndroid* WebViewCore::createBaseLayer() +BaseLayerAndroid* WebViewCore::createBaseLayer(GraphicsLayerAndroid* root) { // We set the background color Color background = Color::white; @@ -878,15 +881,7 @@ BaseLayerAndroid* WebViewCore::createBaseLayer() SkSafeUnref(content); - m_skipContentDraw = true; - bool layoutSucceeded = layoutIfNeededRecursive(m_mainFrame); - m_skipContentDraw = false; - // Layout only fails if called during a layout. - ALOG_ASSERT(layoutSucceeded, "Can never be called recursively"); - // We update the layers - ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client()); - GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync()); if (root) { LayerAndroid* copyLayer = new LayerAndroid(*root->contentLayer()); base->addChild(copyLayer); @@ -899,9 +894,14 @@ BaseLayerAndroid* WebViewCore::createBaseLayer() BaseLayerAndroid* WebViewCore::recordContent(SkIPoint* point) { + m_skipContentDraw = true; + layout(); + ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client()); + GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync()); + m_skipContentDraw = false; recordPicturePile(); - BaseLayerAndroid* baseLayer = createBaseLayer(); + BaseLayerAndroid* baseLayer = createBaseLayer(root); baseLayer->markAsDirty(m_content.dirtyRegion()); m_content.dirtyRegion().setEmpty(); @@ -1686,6 +1686,35 @@ IntPoint WebViewCore::convertGlobalContentToFrameContent(const IntPoint& point, return IntPoint(point.x() + frameOffset.x(), point.y() + frameOffset.y()); } +Position WebViewCore::trimSelectionPosition(const Position &start, const Position& stop) +{ + int direction = comparePositions(start, stop); + if (direction == 0) + return start; + bool forward = direction < 0; + EAffinity affinity = forward ? DOWNSTREAM : UPSTREAM; + bool move; + Position pos = start; + bool movedTooFar = false; + do { + move = true; + Node* node = pos.anchorNode(); + if (node && node->isTextNode() && node->renderer()) { + RenderText *textRenderer = toRenderText(node->renderer()); + move = !textRenderer->textLength(); + } + if (move) { + Position nextPos = forward ? pos.next() : pos.previous(); + movedTooFar = nextPos.isNull() || pos == nextPos + || ((comparePositions(nextPos, stop) < 0) != forward); + pos = nextPos; + } + } while (move && !movedTooFar); + if (movedTooFar) + pos = stop; + return pos; +} + void WebViewCore::selectText(int startX, int startY, int endX, int endY) { SelectionController* sc = focusedFrame()->selection(); @@ -1722,7 +1751,11 @@ void WebViewCore::selectText(int startX, int startY, int endX, int endY) endPosition = prevEndPosition; } - VisibleSelection selection(startPosition, endPosition); + Position start = startPosition.deepEquivalent(); + Position end = endPosition.deepEquivalent(); + start = trimSelectionPosition(start, end); + end = trimSelectionPosition(end, start); + VisibleSelection selection(start, end); // Only allow changes between caret positions or to text selection. bool selectChangeAllowed = (!selection.isCaret() || sc->isCaret()); if (selectChangeAllowed && sc->shouldChangeSelection(selection)) @@ -1750,7 +1783,7 @@ bool WebViewCore::nodeIsClickableOrFocusable(Node* node) AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool doMoveMouse) { if (doMoveMouse) - moveMouse(x, y); + moveMouse(x, y, 0, true); HitTestResult hitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y), false, false, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly, IntSize(slop, slop)); AndroidHitTestResult androidHitResult(this, hitTestResult); @@ -1909,7 +1942,7 @@ AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool do testRect.move(frameAdjust.x(), frameAdjust.y()); testRect.intersect(rect); if (!testRect.contains(x, y)) - moveMouse(testRect.center().x(), testRect.center().y()); + moveMouse(testRect.center().x(), testRect.center().y(), 0, true); } } else { androidHitResult.searchContentDetectors(); @@ -2088,10 +2121,12 @@ static PluginView* nodeIsPlugin(Node* node) { /////////////////////////////////////////////////////////////////////////////// // Update mouse position -void WebViewCore::moveMouse(int x, int y, HitTestResult* hoveredNode) +void WebViewCore::moveMouse(int x, int y, HitTestResult* hoveredNode, bool isClickCandidate) { // mouse event expects the position in the window coordinate m_mousePos = WebCore::IntPoint(x - m_scrollOffsetX, y - m_scrollOffsetY); + if (isClickCandidate) + m_mouseClickPos = m_mousePos; // validNode will still return true if the node is null, as long as we have // a valid frame. Do not want to make a call on frame unless it is valid. WebCore::PlatformMouseEvent mouseEvent(m_mousePos, m_mousePos, @@ -3207,12 +3242,12 @@ bool WebViewCore::handleTouchEvent(int action, Vector<int>& ids, Vector<IntPoint bool WebViewCore::performMouseClick() { - WebCore::PlatformMouseEvent mouseDown(m_mousePos, m_mousePos, WebCore::LeftButton, + WebCore::PlatformMouseEvent mouseDown(m_mouseClickPos, m_mouseClickPos, 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::PlatformMouseEvent mouseUp(m_mouseClickPos, m_mouseClickPos, WebCore::LeftButton, WebCore::MouseEventReleased, 1, false, false, false, false, WTF::currentTime()); bool handled = m_mainFrame->eventHandler()->handleMouseReleaseEvent(mouseUp); diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h index a3c1e7c..bfd9387 100644 --- a/Source/WebKit/android/jni/WebViewCore.h +++ b/Source/WebKit/android/jni/WebViewCore.h @@ -161,11 +161,6 @@ namespace android { */ void contentDraw(); - /** - * copy the layers to the UI side - */ - void layersDraw(); - #if USE(ACCELERATED_COMPOSITING) WebCore::GraphicsLayerAndroid* graphicsRootLayer() const; #endif @@ -304,7 +299,8 @@ namespace android { // scroll the selection on screen (if necessary). void revealSelection(); - void moveMouse(int x, int y, WebCore::HitTestResult* hoveredNode = 0); + void moveMouse(int x, int y, WebCore::HitTestResult* hoveredNode = 0, + bool isClickCandidate = false); // set the scroll amount that webview.java is currently showing void setScrollOffset(bool sendScrollEvent, int dx, int dy); @@ -517,7 +513,7 @@ namespace android { // 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(). - WebCore::BaseLayerAndroid* createBaseLayer(); + WebCore::BaseLayerAndroid* createBaseLayer(GraphicsLayerAndroid* root); bool updateLayers(WebCore::LayerAndroid*); void notifyAnimationStarted(); @@ -618,6 +614,7 @@ namespace android { }; WebCore::Node* currentFocus(); + void layout(); // Create a set of pictures to represent the drawn DOM, driven by // the invalidated region and the time required to draw (used to draw) void recordPicturePile(); @@ -738,6 +735,8 @@ namespace android { static WebCore::IntRect positionToTextRect(const WebCore::Position& position, WebCore::EAffinity affinity); static bool isLtr(const WebCore::Position& position); + static WebCore::Position trimSelectionPosition( + const WebCore::Position& start, const WebCore::Position& stop); // called from constructor, to add this to a global list static void addInstance(WebViewCore*); @@ -768,6 +767,13 @@ namespace android { int m_scrollOffsetY; // webview.java's current scroll in Y double m_scrollSetTime; // when the scroll was last set WebCore::IntPoint m_mousePos; + // This is the location at which we will click. This is tracked + // separately from m_mousePos, because m_mousePos may be updated + // in the interval between ACTION_UP and when the click fires since + // that occurs after a delay. This also works around potential hardware + // issues if we get onHoverEvents when using the touch screen, as that + // will nullify the slop checking we do in hitTest (aka, ACTION_DOWN) + WebCore::IntPoint m_mouseClickPos; int m_screenWidth; // width of the visible rect in document coordinates int m_screenHeight;// height of the visible rect in document coordinates int m_textWrapWidth; |