Changeset 151623 in webkit
- Timestamp:
- Jun 16, 2013 10:24:40 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r151622 r151623 1 2013-06-15 Simon Fraser <simon.fraser@apple.com> 2 3 Fixed background images behave strangely with webkit transitions 4 https://bugs.webkit.org/show_bug.cgi?id=65793 5 6 Reviewed by Sam Weinig. 7 8 Ref tests that compare fixed background rendering after a scroll, with and 9 without compositing, with a couple of layer configurations. 10 11 * compositing/backgrounds/fixed-background-on-descendant-expected.html: Added. 12 * compositing/backgrounds/fixed-background-on-descendant.html: Added. 13 * compositing/backgrounds/fixed-backgrounds-expected.html: Added. 14 * compositing/backgrounds/fixed-backgrounds.html: Added. 15 1 16 2013-06-15 Simon Fraser <simon.fraser@apple.com> 2 17 -
trunk/Source/WebCore/ChangeLog
r151622 r151623 1 2013-06-15 Simon Fraser <simon.fraser@apple.com> 2 3 Painting of fixed background images is wrong in composited layers 4 https://bugs.webkit.org/show_bug.cgi?id=65793 5 6 Reviewed by Sam Weinig. 7 8 The code that computed background image geometry for background-attachment:fixed 9 images was unaware of compositing, so often painting the image at the wrong location. 10 11 Fix by having RenderBoxModelObject::calculateBackgroundImageGeometry() do the correct 12 math for fixed backgrounds in composited layer by offsetting the viewport rect by 13 the paint container's absolute position. 14 15 Tests: compositing/backgrounds/fixed-background-on-descendant.html 16 compositing/backgrounds/fixed-backgrounds.html 17 18 * rendering/RenderBox.cpp: 19 (WebCore::RenderBox::getBackgroundPaintedExtent): Now returns a bool indicating 20 whether it is returning a reliable extent rect. It can return false in the case where 21 a background is fixed, since computing the correct extent would require finding 22 the appropriate composited ancestor to pass to calculateBackgroundImageGeometry(). 23 This is OK since this function is used for "background opaque" optimizations. 24 (WebCore::RenderBox::computeBackgroundIsKnownToBeObscured): If getBackgroundPaintedExtent() 25 returns false, return false. 26 (WebCore::RenderBox::maskClipRect): We removed mask-attachment, so we never need to 27 compute the composited ancestor here and can pass null. 28 (WebCore::RenderBox::repaintLayerRectsForImage): Unwrap a comment. 29 If the changed image is related to a fixed background, geometry.hasNonLocalGeometry() 30 will be true. In that cause, just repaint the entire renderer rather than groveling 31 around for a composited ancestor. 32 * rendering/RenderBox.h: Changed name and signature of backgroundPaintedExtent. 33 * rendering/RenderBoxModelObject.cpp: 34 (WebCore::RenderBoxModelObject::paintFillLayerExtended): calculateBackgroundImageGeometry() 35 now needs to know the painting container. 36 (WebCore::RenderBoxModelObject::calculateBackgroundImageGeometry): Now takes a painting 37 container, that is required to correctly compute the viewport-relative offset for fixed 38 backgrounds. geometry.setHasNonLocalGeometry() is set for fixed backgrounds to indicate 39 to callers that, if they didn't pass a paint container, the destRect is not accurate. 40 The main bug fix is also here: we move the viewportRect by the absolute location of 41 paint container, which is equivalent to the composited layer offset. 42 (WebCore::RenderBoxModelObject::getGeometryForBackgroundImage): calculateBackgroundImageGeometry() 43 takes a paint container. 44 * rendering/RenderBoxModelObject.h: 45 (WebCore::RenderBoxModelObject::BackgroundImageGeometry::BackgroundImageGeometry): 46 (WebCore::RenderBoxModelObject::BackgroundImageGeometry::setHasNonLocalGeometry): 47 (WebCore::RenderBoxModelObject::BackgroundImageGeometry::hasNonLocalGeometry): 48 * rendering/RenderImage.cpp: 49 (WebCore::RenderImage::computeBackgroundIsKnownToBeObscured): If getBackgroundPaintedExtent() 50 can't cheaply give an accurate answer, return false. 51 * rendering/RenderLayerBacking.cpp: 52 (WebCore::RenderLayerBacking::updateDirectlyCompositedBackgroundImage): Pass the paint container, 53 which is our own renderer. 54 1 55 2013-06-15 Simon Fraser <simon.fraser@apple.com> 2 56 -
trunk/Source/WebCore/rendering/RenderBox.cpp
r151549 r151623 1141 1141 } 1142 1142 1143 LayoutRect RenderBox::backgroundPaintedExtent() const1143 bool RenderBox::getBackgroundPaintedExtent(LayoutRect& paintedExtent) const 1144 1144 { 1145 1145 ASSERT(hasBackground()); … … 1147 1147 1148 1148 Color backgroundColor = style()->visitedDependentColor(CSSPropertyBackgroundColor); 1149 if (backgroundColor.isValid() && backgroundColor.alpha()) 1150 return backgroundRect; 1151 if (!style()->backgroundLayers()->image() || style()->backgroundLayers()->next()) 1152 return backgroundRect; 1149 if (backgroundColor.isValid() && backgroundColor.alpha()) { 1150 paintedExtent = backgroundRect; 1151 return true; 1152 } 1153 1154 if (!style()->backgroundLayers()->image() || style()->backgroundLayers()->next()) { 1155 paintedExtent = backgroundRect; 1156 return true; 1157 } 1158 1153 1159 BackgroundImageGeometry geometry; 1154 const_cast<RenderBox*>(this)->calculateBackgroundImageGeometry(style()->backgroundLayers(), backgroundRect, geometry); 1155 return geometry.destRect(); 1160 calculateBackgroundImageGeometry(0, style()->backgroundLayers(), backgroundRect, geometry); 1161 paintedExtent = geometry.destRect(); 1162 return !geometry.hasNonLocalGeometry(); 1156 1163 } 1157 1164 … … 1260 1267 return false; 1261 1268 1262 LayoutRect backgroundRect = backgroundPaintedExtent(); 1269 LayoutRect backgroundRect; 1270 if (!getBackgroundPaintedExtent(backgroundRect)) 1271 return false; 1263 1272 return foregroundIsKnownToBeOpaqueInRect(backgroundRect, backgroundObscurationTestMaxDepth); 1264 1273 } … … 1348 1357 if (maskLayer->image()) { 1349 1358 BackgroundImageGeometry geometry; 1350 calculateBackgroundImageGeometry(maskLayer, borderBox, geometry); 1359 // Masks should never have fixed attachment, so it's OK for paintContainer to be null. 1360 calculateBackgroundImageGeometry(0, maskLayer, borderBox, geometry); 1351 1361 result.unite(geometry.destRect()); 1352 1362 } … … 1446 1456 for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) { 1447 1457 if (curLayer->image() && image == curLayer->image()->data() && curLayer->image()->canRender(this, style()->effectiveZoom())) { 1448 // Now that we know this image is being used, compute the renderer and the rect 1449 // if we haven't already 1458 // Now that we know this image is being used, compute the renderer and the rect if we haven't already. 1450 1459 if (!layerRenderer) { 1451 1460 bool drawingRootBackground = drawingBackground && (isRoot() || (isBody() && !document()->documentElement()->renderer()->hasBackground())); … … 1474 1483 1475 1484 BackgroundImageGeometry geometry; 1476 layerRenderer->calculateBackgroundImageGeometry(curLayer, rendererRect, geometry); 1485 layerRenderer->calculateBackgroundImageGeometry(0, curLayer, rendererRect, geometry); 1486 if (geometry.hasNonLocalGeometry()) { 1487 // Rather than incur the costs of computing the paintContainer for renderers with fixed backgrounds 1488 // in order to get the right destRect, just repaint the entire renderer. 1489 layerRenderer->repaint(); 1490 return true; 1491 } 1492 1477 1493 layerRenderer->repaintRectangle(geometry.destRect()); 1478 1494 if (geometry.destRect() == rendererRect) -
trunk/Source/WebCore/rendering/RenderBox.h
r151451 r151623 589 589 virtual void updateFromStyle() OVERRIDE; 590 590 591 LayoutRect backgroundPaintedExtent() const; 591 // Returns false if it could not cheaply compute the extent (e.g. fixed background), in which case the returned rect may be incorrect. 592 bool getBackgroundPaintedExtent(LayoutRect&) const; 592 593 virtual bool foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const; 593 594 virtual bool computeBackgroundIsKnownToBeObscured() OVERRIDE; -
trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp
r151402 r151623 977 977 if (shouldPaintBackgroundImage) { 978 978 BackgroundImageGeometry geometry; 979 calculateBackgroundImageGeometry( bgLayer, scrolledPaintRect, geometry, backgroundObject);979 calculateBackgroundImageGeometry(paintInfo.paintContainer, bgLayer, scrolledPaintRect, geometry, backgroundObject); 980 980 geometry.clip(paintInfo.rect); 981 981 if (!geometry.destRect().isEmpty()) { … … 1215 1215 } 1216 1216 1217 void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fillLayer, const LayoutRect& paintRect,1218 BackgroundImageGeometry& geometry, RenderObject* backgroundObject) 1217 void RenderBoxModelObject::calculateBackgroundImageGeometry(const RenderLayerModelObject* paintContainer, const FillLayer* fillLayer, const LayoutRect& paintRect, 1218 BackgroundImageGeometry& geometry, RenderObject* backgroundObject) const 1219 1219 { 1220 1220 LayoutUnit left = 0; … … 1225 1225 // Determine the background positioning area and set destRect to the background painting area. 1226 1226 // destRect will be adjusted later if the background is non-repeating. 1227 // FIXME: transforms spec says that fixed backgrounds behave like scroll inside transforms. https://bugs.webkit.org/show_bug.cgi?id=15679 1227 1228 bool fixedAttachment = fillLayer->attachment() == FixedBackgroundAttachment; 1228 1229 1229 1230 #if ENABLE(FAST_MOBILE_SCROLLING) 1230 1231 if (view()->frameView() && view()->frameView()->canBlitOnScroll()) { … … 1266 1267 positioningAreaSize = pixelSnappedIntSize(paintRect.size() - LayoutSize(left + right, top + bottom), paintRect.location()); 1267 1268 } else { 1269 geometry.setHasNonLocalGeometry(); 1270 1268 1271 IntRect viewportRect = pixelSnappedIntRect(viewRect()); 1269 1272 if (fixedBackgroundPaintsInLocalCoordinates()) … … 1271 1274 else if (FrameView* frameView = view()->frameView()) 1272 1275 viewportRect.setLocation(IntPoint(frameView->scrollOffsetForFixedPosition())); 1273 1276 1277 if (paintContainer) { 1278 IntPoint absoluteContainerOffset = roundedIntPoint(paintContainer->localToAbsolute(FloatPoint())); 1279 viewportRect.moveBy(-absoluteContainerOffset); 1280 } 1281 1274 1282 geometry.setDestRect(pixelSnappedIntRect(viewportRect)); 1275 1283 positioningAreaSize = geometry.destRect().size(); 1276 1284 } 1277 1285 1278 RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this;1286 const RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this; 1279 1287 IntSize fillTileSize = calculateFillTileSize(fillLayer, positioningAreaSize); 1280 1288 fillLayer->image()->setContainerSizeForRenderer(clientForBackgroundImage, fillTileSize, style()->effectiveZoom()); … … 1309 1317 } 1310 1318 1311 void RenderBoxModelObject::getGeometryForBackgroundImage( IntRect& destRect, IntPoint& phase, IntSize& tileSize)1319 void RenderBoxModelObject::getGeometryForBackgroundImage(const RenderLayerModelObject* paintContainer, IntRect& destRect, IntPoint& phase, IntSize& tileSize) const 1312 1320 { 1313 1321 const FillLayer* backgroundLayer = style()->backgroundLayers(); 1314 1322 BackgroundImageGeometry geometry; 1315 calculateBackgroundImageGeometry( backgroundLayer, destRect, geometry);1323 calculateBackgroundImageGeometry(paintContainer, backgroundLayer, destRect, geometry); 1316 1324 phase = geometry.phase(); 1317 1325 tileSize = geometry.tileSize(); -
trunk/Source/WebCore/rendering/RenderBoxModelObject.h
r151575 r151623 178 178 bool canHaveBoxInfoInRegion() const { return !isFloating() && !isReplaced() && !isInline() && !hasColumns() && !isTableCell() && isBlockFlow(); } 179 179 180 void getGeometryForBackgroundImage( IntRect& destRect, IntPoint& phase, IntSize& tileSize);180 void getGeometryForBackgroundImage(const RenderLayerModelObject* paintContainer, IntRect& destRect, IntPoint& phase, IntSize& tileSize) const; 181 181 #if USE(ACCELERATED_COMPOSITING) 182 182 void contentChanged(ContentChangeType); … … 199 199 class BackgroundImageGeometry { 200 200 public: 201 BackgroundImageGeometry() 202 : m_hasNonLocalGeometry(false) 203 { } 201 204 IntPoint destOrigin() const { return m_destOrigin; } 202 205 void setDestOrigin(const IntPoint& destOrigin) … … 235 238 236 239 void clip(const IntRect&); 240 241 void setHasNonLocalGeometry(bool hasNonLocalGeometry = true) { m_hasNonLocalGeometry = hasNonLocalGeometry; } 242 bool hasNonLocalGeometry() const { return m_hasNonLocalGeometry; } 243 237 244 private: 238 245 IntRect m_destRect; … … 240 247 IntPoint m_phase; 241 248 IntSize m_tileSize; 249 bool m_hasNonLocalGeometry; // Has background-attachment: fixed. Implies that we can't always cheaply compute destRect. 242 250 }; 243 251 244 252 LayoutPoint adjustedPositionRelativeToOffsetParent(const LayoutPoint&) const; 245 253 246 void calculateBackgroundImageGeometry(const FillLayer*, const LayoutRect& paintRect, BackgroundImageGeometry&, RenderObject* = 0);254 void calculateBackgroundImageGeometry(const RenderLayerModelObject* paintContainer, const FillLayer*, const LayoutRect& paintRect, BackgroundImageGeometry&, RenderObject* = 0) const; 247 255 void getBorderEdgeInfo(class BorderEdge[], const RenderStyle*, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const; 248 256 bool borderObscuresBackgroundEdge(const FloatSize& contextScale) const; -
trunk/Source/WebCore/rendering/RenderImage.cpp
r150796 r151623 511 511 if (!hasBackground()) 512 512 return false; 513 return foregroundIsKnownToBeOpaqueInRect(backgroundPaintedExtent(), 0); 513 514 LayoutRect paintedExtent; 515 if (!getBackgroundPaintedExtent(paintedExtent)) 516 return false; 517 return foregroundIsKnownToBeOpaqueInRect(paintedExtent, 0); 514 518 } 515 519 -
trunk/Source/WebCore/rendering/RenderLayerBacking.cpp
r151513 r151623 1465 1465 1466 1466 RefPtr<Image> image = style->backgroundLayers()->image()->cachedImage()->image(); 1467 toRenderBox(renderer())->getGeometryForBackgroundImage( destRect, phase, tileSize);1467 toRenderBox(renderer())->getGeometryForBackgroundImage(m_owningLayer->renderer(), destRect, phase, tileSize); 1468 1468 m_graphicsLayer->setContentsTileSize(tileSize); 1469 1469 m_graphicsLayer->setContentsTilePhase(phase);
Note: See TracChangeset
for help on using the changeset viewer.