Changeset 59682 in webkit
- Timestamp:
- May 18, 2010 12:32:46 PM (14 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r59681 r59682 1 2010-05-18 Adam Roben <aroben@apple.com> 2 3 Fix a crash when a page that uses accelerated compositing loads soon 4 after the computer wakes from sleep 5 6 The set-up: 7 8 For a short time after waking from sleep, IDirect3D9::CreateDevice 9 will fail. This caused WKCACFLayerRenderer::createRenderer to fail, 10 and meant that WKCACFLayerRenderer never allocated a root layer. 11 WebView wouldn't notice that createRenderer failed, and would go ahead 12 and try to use the root layer anyway, resulting in a crash. 13 14 The fix: 15 16 We now allocate the root layer (and all the other members of 17 WKCACFLayerRenderer that aren't dependent on having an 18 IDirect3DDevice9) in WKCACFLayerRenderer's constructor. This way the 19 layers will always be present, even when creating the D3D device 20 fails. 21 22 There are two remaining problems: 23 1) This results in slightly more memory usage in the case where 24 CreateDevice fails. 25 2) Once we get into this bad state, the WebView doesn't repaint 26 until we navigate somewhere else. 27 28 (2) is covered by 29 <http://webkit.org/b/39297>/<rdar://problem/7997431>. We'll fix it by 30 retrying CreateDevice later in hopes that it will succeed after more 31 time has passed. This will in turn fix (1). (We should never end up in 32 a case where CreateDevice fails forever because we already did some 33 preliminary checks in acceleratedCompositingAvailable().) 34 35 Fixes <http://webkit.org/b/39295> <rdar://problem/7971319> Crash 36 (preceded by assertion) in WKCACFLayerRenderer::setNeedsDisplay when 37 computer wakes from sleep on particular page 38 39 Reviewed by John Sullivan. 40 41 * manual-tests/crash-after-wake-from-sleep.html: Added. This 42 is the Poster Circle demo from webkit.org/blog, but modified to 43 automatically reload every 5 seconds and with instructions to put the 44 computer to sleep and wake it up again. 45 46 * platform/graphics/win/WKCACFLayerRenderer.cpp: 47 (WebCore::WKCACFLayerRenderer::WKCACFLayerRenderer): Moved code to 48 initialize m_context, m_renderContext, and m_*Layer here... 49 (WebCore::WKCACFLayerRenderer::createRenderer): ...from here. 50 1 51 2010-05-18 Adam Roben <aroben@apple.com> 2 52 -
trunk/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
r59610 r59682 225 225 WKCACFLayerRenderer::WKCACFLayerRenderer() 226 226 : m_triedToCreateD3DRenderer(false) 227 , m_renderContext(0) 227 , m_rootLayer(WKCACFRootLayer::create(this)) 228 , m_scrollLayer(WKCACFLayer::create(WKCACFLayer::Layer)) 229 , m_clipLayer(WKCACFLayer::create(WKCACFLayer::Layer)) 230 , m_context(AdoptCF, CACFContextCreate(0)) 231 , m_renderContext(static_cast<CARenderContext*>(CACFContextGetRenderContext(m_context.get()))) 228 232 , m_renderer(0) 229 233 , m_hostWindow(0) … … 234 238 , m_mustResetLostDeviceBeforeRendering(false) 235 239 { 236 #ifndef NDEBUG237 char* printTreeFlag = getenv("CA_PRINT_TREE");238 m_printTree = printTreeFlag && atoi(printTreeFlag);239 #endif240 }241 242 WKCACFLayerRenderer::~WKCACFLayerRenderer()243 {244 destroyRenderer();245 }246 247 WKCACFLayer* WKCACFLayerRenderer::rootLayer() const248 {249 return m_rootLayer.get();250 }251 252 void WKCACFLayerRenderer::setScrollFrame(const IntPoint& position, const IntSize& size)253 {254 m_scrollSize = size;255 m_scrollPosition = position;256 257 updateScrollFrame();258 }259 260 void WKCACFLayerRenderer::updateScrollFrame()261 {262 CGRect frameBounds = bounds();263 m_clipLayer->setBounds(CGRectMake(0, 0, m_scrollSize.width(), m_scrollSize.height()));264 m_clipLayer->setPosition(CGPointMake(0, frameBounds.size.height));265 if (m_rootChildLayer) {266 CGRect rootBounds = m_rootChildLayer->bounds();267 m_scrollLayer->setBounds(rootBounds);268 }269 m_scrollLayer->setPosition(CGPointMake(-m_scrollPosition.x(), m_scrollPosition.y() + m_scrollSize.height()));270 }271 272 void WKCACFLayerRenderer::setRootContents(CGImageRef image)273 {274 ASSERT(m_rootLayer);275 m_rootLayer->setContents(image);276 renderSoon();277 }278 279 void WKCACFLayerRenderer::setRootContentsAndDisplay(CGImageRef image)280 {281 ASSERT(m_rootLayer);282 m_rootLayer->setContents(image);283 paint();284 }285 286 void WKCACFLayerRenderer::setRootChildLayer(WKCACFLayer* layer)287 {288 if (!m_scrollLayer)289 return;290 291 m_scrollLayer->removeAllSublayers();292 m_rootChildLayer = layer;293 if (layer) {294 m_scrollLayer->addSublayer(layer);295 // Adjust the scroll frame accordingly296 updateScrollFrame();297 }298 }299 300 void WKCACFLayerRenderer::setNeedsDisplay()301 {302 ASSERT(m_rootLayer);303 m_rootLayer->setNeedsDisplay(0);304 renderSoon();305 }306 307 bool WKCACFLayerRenderer::createRenderer()308 {309 if (m_triedToCreateD3DRenderer)310 return m_d3dDevice;311 312 m_triedToCreateD3DRenderer = true;313 D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();314 315 if (!d3d() || !::IsWindow(m_hostWindow))316 return false;317 318 // D3D doesn't like to make back buffers for 0 size windows. We skirt this problem if we make the319 // passed backbuffer width and height non-zero. The window will necessarily get set to a non-zero320 // size eventually, and then the backbuffer size will get reset.321 RECT rect;322 GetClientRect(m_hostWindow, &rect);323 324 if (rect.left-rect.right == 0 || rect.bottom-rect.top == 0) {325 parameters.BackBufferWidth = 1;326 parameters.BackBufferHeight = 1;327 }328 329 COMPtr<IDirect3DDevice9> device;330 if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hostWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, ¶meters, &device)))331 return false;332 333 // Now that we've created the IDirect3DDevice9 based on the capabilities we334 // got from the IDirect3D9 global object, we requery the device for its335 // actual capabilities. The capabilities returned by the device can336 // sometimes be more complete, for example when using software vertex337 // processing.338 D3DCAPS9 deviceCaps;339 if (FAILED(device->GetDeviceCaps(&deviceCaps)))340 return false;341 342 if (!hardwareCapabilitiesIndicateCoreAnimationSupport(deviceCaps))343 return false;344 345 m_d3dDevice = device;346 347 D3DXMATRIXA16 projection;348 D3DXMatrixOrthoOffCenterRH(&projection, rect.left, rect.right, rect.top, rect.bottom, -1.0f, 1.0f);349 350 m_d3dDevice->SetTransform(D3DTS_PROJECTION, &projection);351 352 m_context.adoptCF(CACFContextCreate(0));353 240 windowsForContexts().set(m_context.get(), this); 354 241 355 m_renderContext = static_cast<CARenderContext*>(CACFContextGetRenderContext(m_context.get()));356 m_renderer = CARenderOGLNew(&kCARenderDX9Callbacks, m_d3dDevice.get(), 0);357 358 // Create the root hierarchy.359 242 // Under the root layer, we have a clipping layer to clip the content, 360 243 // that contains a scroll layer that we use for scrolling the content. … … 366 249 // Scrolling will affect only the position of the scroll layer without affecting the bounds. 367 250 368 m_rootLayer = WKCACFRootLayer::create(this);369 251 m_rootLayer->setName("WKCACFLayerRenderer rootLayer"); 370 371 m_clipLayer = WKCACFLayer::create(WKCACFLayer::Layer);372 252 m_clipLayer->setName("WKCACFLayerRenderer clipLayer"); 373 374 m_scrollLayer = WKCACFLayer::create(WKCACFLayer::Layer);375 253 m_scrollLayer->setName("WKCACFLayerRenderer scrollLayer"); 376 254 … … 387 265 #endif 388 266 267 if (m_context) 268 m_rootLayer->becomeRootLayerForContext(m_context.get()); 269 270 #ifndef NDEBUG 271 char* printTreeFlag = getenv("CA_PRINT_TREE"); 272 m_printTree = printTreeFlag && atoi(printTreeFlag); 273 #endif 274 } 275 276 WKCACFLayerRenderer::~WKCACFLayerRenderer() 277 { 278 destroyRenderer(); 279 } 280 281 WKCACFLayer* WKCACFLayerRenderer::rootLayer() const 282 { 283 return m_rootLayer.get(); 284 } 285 286 void WKCACFLayerRenderer::setScrollFrame(const IntPoint& position, const IntSize& size) 287 { 288 m_scrollSize = size; 289 m_scrollPosition = position; 290 291 updateScrollFrame(); 292 } 293 294 void WKCACFLayerRenderer::updateScrollFrame() 295 { 296 CGRect frameBounds = bounds(); 297 m_clipLayer->setBounds(CGRectMake(0, 0, m_scrollSize.width(), m_scrollSize.height())); 298 m_clipLayer->setPosition(CGPointMake(0, frameBounds.size.height)); 299 if (m_rootChildLayer) { 300 CGRect rootBounds = m_rootChildLayer->bounds(); 301 m_scrollLayer->setBounds(rootBounds); 302 } 303 m_scrollLayer->setPosition(CGPointMake(-m_scrollPosition.x(), m_scrollPosition.y() + m_scrollSize.height())); 304 } 305 306 void WKCACFLayerRenderer::setRootContents(CGImageRef image) 307 { 308 ASSERT(m_rootLayer); 309 m_rootLayer->setContents(image); 310 renderSoon(); 311 } 312 313 void WKCACFLayerRenderer::setRootContentsAndDisplay(CGImageRef image) 314 { 315 ASSERT(m_rootLayer); 316 m_rootLayer->setContents(image); 317 paint(); 318 } 319 320 void WKCACFLayerRenderer::setRootChildLayer(WKCACFLayer* layer) 321 { 322 if (!m_scrollLayer) 323 return; 324 325 m_scrollLayer->removeAllSublayers(); 326 m_rootChildLayer = layer; 327 if (layer) { 328 m_scrollLayer->addSublayer(layer); 329 // Adjust the scroll frame accordingly 330 updateScrollFrame(); 331 } 332 } 333 334 void WKCACFLayerRenderer::setNeedsDisplay() 335 { 336 ASSERT(m_rootLayer); 337 m_rootLayer->setNeedsDisplay(0); 338 renderSoon(); 339 } 340 341 bool WKCACFLayerRenderer::createRenderer() 342 { 343 if (m_triedToCreateD3DRenderer) 344 return m_d3dDevice; 345 346 m_triedToCreateD3DRenderer = true; 347 D3DPRESENT_PARAMETERS parameters = initialPresentationParameters(); 348 349 if (!d3d() || !::IsWindow(m_hostWindow)) 350 return false; 351 352 // D3D doesn't like to make back buffers for 0 size windows. We skirt this problem if we make the 353 // passed backbuffer width and height non-zero. The window will necessarily get set to a non-zero 354 // size eventually, and then the backbuffer size will get reset. 355 RECT rect; 356 GetClientRect(m_hostWindow, &rect); 357 358 if (rect.left-rect.right == 0 || rect.bottom-rect.top == 0) { 359 parameters.BackBufferWidth = 1; 360 parameters.BackBufferHeight = 1; 361 } 362 363 COMPtr<IDirect3DDevice9> device; 364 if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hostWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, ¶meters, &device))) 365 return false; 366 367 // Now that we've created the IDirect3DDevice9 based on the capabilities we 368 // got from the IDirect3D9 global object, we requery the device for its 369 // actual capabilities. The capabilities returned by the device can 370 // sometimes be more complete, for example when using software vertex 371 // processing. 372 D3DCAPS9 deviceCaps; 373 if (FAILED(device->GetDeviceCaps(&deviceCaps))) 374 return false; 375 376 if (!hardwareCapabilitiesIndicateCoreAnimationSupport(deviceCaps)) 377 return false; 378 379 m_d3dDevice = device; 380 381 D3DXMATRIXA16 projection; 382 D3DXMatrixOrthoOffCenterRH(&projection, rect.left, rect.right, rect.top, rect.bottom, -1.0f, 1.0f); 383 384 m_d3dDevice->SetTransform(D3DTS_PROJECTION, &projection); 385 386 m_renderer = CARenderOGLNew(&kCARenderDX9Callbacks, m_d3dDevice.get(), 0); 387 389 388 if (IsWindow(m_hostWindow)) 390 389 m_rootLayer->setFrame(bounds()); 391 392 if (m_context)393 m_rootLayer->becomeRootLayerForContext(m_context.get());394 390 395 391 return true;
Note: See TracChangeset
for help on using the changeset viewer.