Changeset 269809 in webkit
- Timestamp:
- Nov 13, 2020, 6:11:30 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/WebProcess/GPU/graphics/RemoteImageBufferProxy.h (modified) (4 diffs)
-
Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp (modified) (4 diffs)
-
Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h (modified) (3 diffs)
-
Source/WebKit/WebProcess/GPU/graphics/RemoteResourceCacheProxy.h (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r269808 r269809 1 2020-11-13 Chris Dumez <cdumez@apple.com> 2 3 [GPUProcess] Add basic GPUProcess crash handling for canvas 4 https://bugs.webkit.org/show_bug.cgi?id=218924 5 6 Reviewed by Simon Fraser. 7 8 Update RemoteRenderingBackendProxy to be a GPUProcessConnection::Client so that it 9 gets notified when the IPC connection to the GPUProcess gets severed. When this 10 happens, RemoteRenderingBackendProxy clears all its SharedMemory handles and 11 sends IPC messages to the GPU process to recreate all the ImageBuffers we had. 12 13 * WebProcess/GPU/graphics/RemoteImageBufferProxy.h: 14 (WebKit::RemoteImageBufferProxy::create): 15 (WebKit::RemoteImageBufferProxy::clearBackend): 16 (WebKit::RemoteImageBufferProxy::size const): 17 (WebKit::RemoteImageBufferProxy::renderingMode const): 18 (WebKit::RemoteImageBufferProxy::colorSpace const): 19 (WebKit::RemoteImageBufferProxy::pixelFormat const): 20 (WebKit::RemoteImageBufferProxy::RemoteImageBufferProxy): 21 * WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp: 22 (WebKit::RemoteRenderingBackendProxy::RemoteRenderingBackendProxy): 23 (WebKit::RemoteRenderingBackendProxy::connectToGPUProcess): 24 (WebKit::recreateImage): 25 (WebKit::RemoteRenderingBackendProxy::gpuProcessConnectionDidClose): 26 (WebKit::RemoteRenderingBackendProxy::createImageBuffer): 27 * WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h: 28 * WebProcess/GPU/graphics/RemoteResourceCacheProxy.h: 29 (WebKit::RemoteResourceCacheProxy::imageBuffers const): 30 1 31 2020-11-13 Chris Dumez <cdumez@apple.com> 2 32 -
trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteImageBufferProxy.h
r269753 r269809 49 49 50 50 public: 51 static RefPtr<RemoteImageBufferProxy> create(const WebCore::FloatSize& size, float resolutionScale, RemoteRenderingBackendProxy& remoteRenderingBackendProxy)51 static RefPtr<RemoteImageBufferProxy> create(const WebCore::FloatSize& size, WebCore::RenderingMode renderingMode, float resolutionScale, WebCore::ColorSpace colorSpace, WebCore::PixelFormat pixelFormat, RemoteRenderingBackendProxy& remoteRenderingBackendProxy) 52 52 { 53 53 if (BackendType::calculateBackendSize(size, resolutionScale).isEmpty()) 54 54 return nullptr; 55 55 56 return adoptRef(new RemoteImageBufferProxy(size, re moteRenderingBackendProxy));56 return adoptRef(new RemoteImageBufferProxy(size, renderingMode, resolutionScale, colorSpace, pixelFormat, remoteRenderingBackendProxy)); 57 57 } 58 58 … … 66 66 } 67 67 68 void clearBackend() { m_backend = nullptr; } 69 68 70 void createBackend(const WebCore::FloatSize& logicalSize, const WebCore::IntSize& backendSize, float resolutionScale, WebCore::ColorSpace colorSpace, WebCore::PixelFormat pixelFormat, ImageBufferBackendHandle handle) 69 71 { … … 77 79 } 78 80 81 const WebCore::FloatSize& size() const { return m_size; } 82 WebCore::RenderingMode renderingMode() const { return m_renderingMode; } 83 float resolutionScale() const final { return m_resolutionScale; } 84 WebCore::ColorSpace colorSpace() const { return m_colorSpace; } 85 WebCore::PixelFormat pixelFormat() const { return m_pixelFormat; } 86 79 87 protected: 80 RemoteImageBufferProxy(const WebCore::FloatSize& size, RemoteRenderingBackendProxy& remoteRenderingBackendProxy)88 RemoteImageBufferProxy(const WebCore::FloatSize& size, WebCore::RenderingMode renderingMode, float resolutionScale, WebCore::ColorSpace colorSpace, WebCore::PixelFormat pixelFormat, RemoteRenderingBackendProxy& remoteRenderingBackendProxy) 81 89 : BaseDisplayListImageBuffer(size, this) 82 90 , m_remoteRenderingBackendProxy(makeWeakPtr(remoteRenderingBackendProxy)) 91 , m_size(size) 92 , m_renderingMode(renderingMode) 93 , m_resolutionScale(resolutionScale) 94 , m_colorSpace(colorSpace) 95 , m_pixelFormat(pixelFormat) 83 96 { 84 97 ASSERT(m_remoteRenderingBackendProxy); … … 304 317 WeakPtr<RemoteRenderingBackendProxy> m_remoteRenderingBackendProxy; 305 318 size_t m_itemCountInCurrentDisplayList { 0 }; 319 WebCore::FloatSize m_size; 320 WebCore::RenderingMode m_renderingMode; 321 float m_resolutionScale; 322 WebCore::ColorSpace m_colorSpace; 323 WebCore::PixelFormat m_pixelFormat; 306 324 }; 307 325 -
trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp
r269710 r269809 31 31 #include "DisplayListWriterHandle.h" 32 32 #include "GPUConnectionToWebProcess.h" 33 #include "GPUProcessConnection.h"34 33 #include "ImageDataReference.h" 35 34 #include "PlatformRemoteImageBufferProxy.h" … … 50 49 RemoteRenderingBackendProxy::RemoteRenderingBackendProxy() 51 50 { 52 // Register itself as a MessageReceiver in the GPUProcessConnection. 53 IPC::MessageReceiverMap& messageReceiverMap = WebProcess::singleton().ensureGPUProcessConnection().messageReceiverMap(); 54 messageReceiverMap.addMessageReceiver(Messages::RemoteRenderingBackendProxy::messageReceiverName(), m_renderingBackendIdentifier.toUInt64(), *this); 55 56 // Create the RemoteRenderingBackend 57 send(Messages::GPUConnectionToWebProcess::CreateRenderingBackend(m_renderingBackendIdentifier), 0); 51 connectToGPUProcess(); 58 52 } 59 53 … … 68 62 } 69 63 64 void RemoteRenderingBackendProxy::connectToGPUProcess() 65 { 66 auto& connection = WebProcess::singleton().ensureGPUProcessConnection(); 67 connection.addClient(*this); 68 connection.messageReceiverMap().addMessageReceiver(Messages::RemoteRenderingBackendProxy::messageReceiverName(), m_renderingBackendIdentifier.toUInt64(), *this); 69 70 send(Messages::GPUConnectionToWebProcess::CreateRenderingBackend(m_renderingBackendIdentifier), 0); 71 } 72 73 template<typename T> 74 static void recreateImageBuffer(RemoteRenderingBackendProxy& proxy, T& imageBuffer, RenderingResourceIdentifier resourceIdentifier, RenderingBackendIdentifier renderingBackendIdentifier) 75 { 76 imageBuffer.clearBackend(); 77 proxy.send(Messages::RemoteRenderingBackend::CreateImageBuffer(imageBuffer.size(), imageBuffer.renderingMode(), imageBuffer.resolutionScale(), imageBuffer.colorSpace(), imageBuffer.pixelFormat(), resourceIdentifier), renderingBackendIdentifier); 78 } 79 80 void RemoteRenderingBackendProxy::reestablishGPUProcessConnection() 81 { 82 connectToGPUProcess(); 83 84 for (auto& pair : m_remoteResourceCacheProxy.imageBuffers()) { 85 if (auto& baseImageBuffer = pair.value) { 86 if (is<AcceleratedRemoteImageBufferProxy>(*baseImageBuffer)) 87 recreateImageBuffer(*this, downcast<AcceleratedRemoteImageBufferProxy>(*baseImageBuffer), pair.key, m_renderingBackendIdentifier); 88 else 89 recreateImageBuffer(*this, downcast<UnacceleratedRemoteImageBufferProxy>(*baseImageBuffer), pair.key, m_renderingBackendIdentifier); 90 } 91 } 92 } 93 94 void RemoteRenderingBackendProxy::gpuProcessConnectionDidClose(GPUProcessConnection& previousConnection) 95 { 96 previousConnection.removeClient(*this); 97 98 m_identifiersOfReusableHandles.clear(); 99 m_identifiersOfHandlesAvailableForWriting.clear(); 100 m_sharedDisplayListHandles.clear(); 101 102 reestablishGPUProcessConnection(); 103 } 104 70 105 IPC::Connection* RemoteRenderingBackendProxy::messageSenderConnection() const 71 106 { … … 95 130 96 131 if (renderingMode == RenderingMode::Accelerated) 97 imageBuffer = AcceleratedRemoteImageBufferProxy::create(size, re solutionScale, *this);132 imageBuffer = AcceleratedRemoteImageBufferProxy::create(size, renderingMode, resolutionScale, colorSpace, pixelFormat, *this); 98 133 99 134 if (!imageBuffer) 100 imageBuffer = UnacceleratedRemoteImageBufferProxy::create(size, re solutionScale, *this);135 imageBuffer = UnacceleratedRemoteImageBufferProxy::create(size, renderingMode, resolutionScale, colorSpace, pixelFormat, *this); 101 136 102 137 if (imageBuffer) { -
trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h
r269710 r269809 28 28 #if ENABLE(GPU_PROCESS) 29 29 30 #include "GPUProcessConnection.h" 30 31 #include "ImageBufferBackendHandle.h" 31 32 #include "MessageReceiver.h" … … 57 58 : public IPC::MessageSender 58 59 , private IPC::MessageReceiver 59 , public CanMakeWeakPtr<RemoteRenderingBackendProxy>{60 , public GPUProcessConnection::Client { 60 61 public: 61 62 static std::unique_ptr<RemoteRenderingBackendProxy> create(); … … 87 88 RemoteRenderingBackendProxy(); 88 89 90 // GPUProcessConnection::Client 91 void gpuProcessConnectionDidClose(GPUProcessConnection&) final; 92 93 void connectToGPUProcess(); 94 void reestablishGPUProcessConnection(); 89 95 void updateReusableHandles(); 90 96 -
trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteResourceCacheProxy.h
r269708 r269809 50 50 void cacheNativeImage(WebCore::NativeImage&); 51 51 52 using ImageBufferHashMap = HashMap<WebCore::RenderingResourceIdentifier, WeakPtr<WebCore::ImageBuffer>>; 53 const ImageBufferHashMap& imageBuffers() const { return m_imageBuffers; } 54 52 55 private: 53 using ImageBufferHashMap = HashMap<WebCore::RenderingResourceIdentifier, WeakPtr<WebCore::ImageBuffer>>;54 56 using NativeImageHashMap = HashMap<WebCore::RenderingResourceIdentifier, WeakPtr<WebCore::NativeImage>>; 55 57 -
trunk/Tools/ChangeLog
r269804 r269809 1 2020-11-13 Chris Dumez <cdumez@apple.com> 2 3 [GPUProcess] Add basic GPUProcess crash handling for canvas 4 https://bugs.webkit.org/show_bug.cgi?id=218924 5 6 Reviewed by Simon Fraser. 7 8 Add API test coverage. 9 10 * TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm: 11 (convertToCGImage): 12 (getPixelIndex): 13 (TEST): 14 1 15 2020-11-13 Aakash Jain <aakash_jain@apple.com> 2 16 -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm
r269750 r269809 36 36 #import <wtf/RetainPtr.h> 37 37 38 #if PLATFORM(MAC) 39 typedef NSImage *PlatformImage; 40 typedef NSWindow *PlatformWindow; 41 42 static RetainPtr<CGImageRef> convertToCGImage(NSImage *image) 43 { 44 return [image CGImageForProposedRect:nil context:nil hints:nil]; 45 } 46 47 #else 48 typedef UIImage *PlatformImage; 49 typedef UIWindow *PlatformWindow; 50 51 static RetainPtr<CGImageRef> convertToCGImage(UIImage *image) 52 { 53 return image.CGImage; 54 } 55 #endif 56 57 static NSInteger getPixelIndex(NSInteger x, NSInteger y, NSInteger width) 58 { 59 return (y * width + x) * 4; 60 } 61 38 62 TEST(GPUProcess, RelaunchOnCrash) 39 63 { … … 261 285 EXPECT_EQ(webViewPID, [webView _webProcessIdentifier]); 262 286 } 287 288 static NSString *testCanvasPage = @"<body> \n" 289 "<canvas id='myCanvas' width='400px' height='400px'>\n" 290 "<script> \n" 291 "var context = document.getElementById('myCanvas').getContext('2d'); \n" 292 "</script> \n" 293 "</body>"; 294 295 TEST(GPUProcess, CanvasBasicCrashHandling) 296 { 297 auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 298 for (_WKInternalDebugFeature *feature in [WKPreferences _internalDebugFeatures]) { 299 if ([feature.key isEqualToString:@"UseGPUProcessForCanvasRenderingEnabled"]) { 300 [[configuration preferences] _setEnabled:YES forInternalDebugFeature:feature]; 301 break; 302 } 303 } 304 305 NSInteger viewWidth = 400; 306 NSInteger viewHeight = 400; 307 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, viewWidth, viewHeight) configuration:configuration.get() addToWindow:NO]); 308 309 RetainPtr<PlatformWindow> window; 310 CGFloat backingScaleFactor; 311 312 #if PLATFORM(MAC) 313 window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]); 314 [[window contentView] addSubview:webView.get()]; 315 backingScaleFactor = [window backingScaleFactor]; 316 #elif PLATFORM(IOS_FAMILY) 317 window = adoptNS([[UIWindow alloc] initWithFrame:[webView frame]]); 318 [window addSubview:webView.get()]; 319 backingScaleFactor = [[window screen] scale]; 320 #endif 321 322 [webView synchronouslyLoadHTMLString:testCanvasPage]; 323 324 auto webViewPID = [webView _webProcessIdentifier]; 325 326 // Try painting the canvas red. 327 __block bool done = false; 328 [webView evaluateJavaScript:@"context.fillStyle = '#FF0000'; context.fillRect(0, 0, 400, 400);" completionHandler:^(id result, NSError *error) { 329 EXPECT_TRUE(!error); 330 done = true; 331 }]; 332 TestWebKitAPI::Util::run(&done); 333 334 [webView waitForNextPresentationUpdate]; 335 336 // The GPU process should have been launched. 337 auto* processPool = configuration.get().processPool; 338 unsigned timeout = 0; 339 while (![processPool _gpuProcessIdentifier] && timeout++ < 100) 340 TestWebKitAPI::Util::sleep(0.1); 341 auto gpuProcessPID = [processPool _gpuProcessIdentifier]; 342 EXPECT_NE(0, gpuProcessPID); 343 344 auto snapshotConfiguration = adoptNS([[WKSnapshotConfiguration alloc] init]); 345 [snapshotConfiguration setRect:NSMakeRect(0, 0, 150, 150)]; 346 [snapshotConfiguration setSnapshotWidth:@(150)]; 347 [snapshotConfiguration setAfterScreenUpdates:YES]; 348 349 // Make sure a red square is painted. 350 done = false; 351 [webView takeSnapshotWithConfiguration:snapshotConfiguration.get() completionHandler:^(PlatformImage snapshotImage, NSError *error) { 352 EXPECT_TRUE(!error); 353 354 RetainPtr<CGImageRef> cgImage = convertToCGImage(snapshotImage); 355 RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB()); 356 357 NSInteger viewWidthInPixels = viewWidth * backingScaleFactor; 358 NSInteger viewHeightInPixels = viewHeight * backingScaleFactor; 359 360 uint8_t *rgba = (unsigned char *)calloc(viewWidthInPixels * viewHeightInPixels * 4, sizeof(unsigned char)); 361 RetainPtr<CGContextRef> context = CGBitmapContextCreate(rgba, viewWidthInPixels, viewHeightInPixels, 8, 4 * viewWidthInPixels, colorSpace.get(), kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 362 CGContextDrawImage(context.get(), CGRectMake(0, 0, viewWidthInPixels, viewHeightInPixels), cgImage.get()); 363 364 NSInteger pixelIndex = getPixelIndex(50, 50, viewWidthInPixels); 365 EXPECT_EQ(255, rgba[pixelIndex]); 366 EXPECT_EQ(0, rgba[pixelIndex + 1]); 367 EXPECT_EQ(0, rgba[pixelIndex + 2]); 368 369 pixelIndex = getPixelIndex(100, 100, viewWidthInPixels); 370 EXPECT_EQ(255, rgba[pixelIndex]); 371 EXPECT_EQ(0, rgba[pixelIndex + 1]); 372 EXPECT_EQ(0, rgba[pixelIndex + 2]); 373 374 free(rgba); 375 376 done = true; 377 }]; 378 TestWebKitAPI::Util::run(&done); 379 380 // Kill the GPUProcess. 381 kill(gpuProcessPID, 9); 382 383 // GPU Process should get relaunched. 384 timeout = 0; 385 while ((![processPool _gpuProcessIdentifier] || [processPool _gpuProcessIdentifier] == gpuProcessPID) && timeout++ < 100) 386 TestWebKitAPI::Util::sleep(0.1); 387 EXPECT_NE([processPool _gpuProcessIdentifier], 0); 388 EXPECT_NE([processPool _gpuProcessIdentifier], gpuProcessPID); 389 gpuProcessPID = [processPool _gpuProcessIdentifier]; 390 391 // WebProcess should not have crashed. 392 EXPECT_EQ(webViewPID, [webView _webProcessIdentifier]); 393 394 // Try painting the canvas green. 395 done = false; 396 [webView evaluateJavaScript:@"context.fillStyle = '#00FF00'; context.fillRect(0, 0, 400, 400);" completionHandler:^(id result, NSError *error) { 397 EXPECT_TRUE(!error); 398 done = true; 399 }]; 400 TestWebKitAPI::Util::run(&done); 401 402 [webView waitForNextPresentationUpdate]; 403 404 // Make sure a green square is painted. 405 done = false; 406 [webView takeSnapshotWithConfiguration:snapshotConfiguration.get() completionHandler:^(PlatformImage snapshotImage, NSError *error) { 407 EXPECT_TRUE(!error); 408 409 RetainPtr<CGImageRef> cgImage = convertToCGImage(snapshotImage); 410 RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB()); 411 412 NSInteger viewWidthInPixels = viewWidth * backingScaleFactor; 413 NSInteger viewHeightInPixels = viewHeight * backingScaleFactor; 414 415 uint8_t *rgba = (unsigned char *)calloc(viewWidthInPixels * viewHeightInPixels * 4, sizeof(unsigned char)); 416 RetainPtr<CGContextRef> context = CGBitmapContextCreate(rgba, viewWidthInPixels, viewHeightInPixels, 8, 4 * viewWidthInPixels, colorSpace.get(), kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 417 CGContextDrawImage(context.get(), CGRectMake(0, 0, viewWidthInPixels, viewHeightInPixels), cgImage.get()); 418 419 NSInteger pixelIndex = getPixelIndex(50, 50, viewWidthInPixels); 420 EXPECT_EQ(0, rgba[pixelIndex]); 421 EXPECT_EQ(255, rgba[pixelIndex + 1]); 422 EXPECT_EQ(0, rgba[pixelIndex + 2]); 423 424 pixelIndex = getPixelIndex(100, 100, viewWidthInPixels); 425 EXPECT_EQ(0, rgba[pixelIndex]); 426 EXPECT_EQ(255, rgba[pixelIndex + 1]); 427 EXPECT_EQ(0, rgba[pixelIndex + 2]); 428 429 free(rgba); 430 431 done = true; 432 }]; 433 TestWebKitAPI::Util::run(&done); 434 }
Note:
See TracChangeset
for help on using the changeset viewer.