Changeset 243356 in webkit
- Timestamp:
- Mar 21, 2019, 7:47:35 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 16 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/inspector/canvas/recording-2d.html (modified) (4 diffs)
-
LayoutTests/inspector/canvas/recording-bitmaprenderer.html (modified) (3 diffs)
-
LayoutTests/inspector/canvas/recording-html-2d.html (modified) (3 diffs)
-
LayoutTests/inspector/canvas/recording-webgl.html (modified) (3 diffs)
-
LayoutTests/inspector/canvas/setRecordingAutoCaptureFrameCount.html (modified) (2 diffs)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/html/HTMLCanvasElement.cpp (modified) (1 diff)
-
Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp (modified) (5 diffs)
-
Source/WebCore/html/canvas/WebGLRenderingContextBase.h (modified) (3 diffs)
-
Source/WebCore/inspector/InspectorCanvas.cpp (modified) (6 diffs)
-
Source/WebCore/inspector/InspectorCanvas.h (modified) (3 diffs)
-
Source/WebCore/inspector/agents/InspectorCanvasAgent.cpp (modified) (31 diffs)
-
Source/WebCore/inspector/agents/InspectorCanvasAgent.h (modified) (2 diffs)
-
Source/WebCore/platform/graphics/GraphicsContext3D.h (modified) (3 diffs)
-
Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r243355 r243356 1 2019-03-21 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: Safari Canvas Inspector seems to show the canvas being rendered twice per frame. 4 https://bugs.webkit.org/show_bug.cgi?id=196082 5 <rdar://problem/49113496> 6 7 Reviewed by Dean Jackson. 8 9 * inspector/canvas/recording-2d.html: 10 * inspector/canvas/recording-bitmaprenderer.html: 11 * inspector/canvas/recording-html-2d.html: 12 * inspector/canvas/recording-webgl.html: 13 * inspector/canvas/setRecordingAutoCaptureFrameCount.html: 14 1 15 2019-03-21 Joseph Pecoraro <pecoraro@apple.com> 2 16 -
trunk/LayoutTests/inspector/canvas/recording-2d.html
r237808 r243356 40 40 bitmap = await createImageBitmap(image); 41 41 42 document.body.appendChild(canvas);43 44 42 ctx.save(); 45 43 cancelActions(); … … 54 52 } 55 53 56 let timeoutID= NaN;54 let requestAnimationFrameId = NaN; 57 55 let saveCount = 1; 58 56 … … 62 60 ctx.restore(); // Ensures the state is reset between test cases. 63 61 64 c learTimeout(timeoutID);65 timeoutID= NaN;62 cancelAnimationFrame(requestAnimationFrameId); 63 requestAnimationFrameId = NaN; 66 64 67 65 ctx.save(); // Ensures the state is reset between test cases. … … 400 398 frames[index++](); 401 399 if (index < frames.length) 402 timeoutID = setTimeout(executeFrameFunction, 0);400 requestAnimationFrameId = requestAnimationFrame(executeFrameFunction); 403 401 }; 404 402 executeFrameFunction(); -
trunk/LayoutTests/inspector/canvas/recording-bitmaprenderer.html
r237777 r243356 24 24 ctx = canvas.getContext("bitmaprenderer"); 25 25 26 document.body.appendChild(canvas);26 cancelActions(); 27 27 28 28 runTest(); … … 35 35 } 36 36 37 let timeoutID= NaN;37 let requestAnimationFrameId = NaN; 38 38 39 39 function cancelActions() { 40 c learTimeout(timeoutID);41 timeoutID= NaN;40 cancelAnimationFrame(requestAnimationFrameId); 41 requestAnimationFrameId = NaN; 42 42 43 43 createImageBitmap(transparentImage).then((transparentBitmap) => { … … 69 69 frames[index++](); 70 70 if (index < frames.length) 71 timeoutID = setTimeout(executeFrameFunction, 0);71 requestAnimationFrameId = requestAnimationFrame(executeFrameFunction); 72 72 }; 73 73 executeFrameFunction(); -
trunk/LayoutTests/inspector/canvas/recording-html-2d.html
r242809 r243356 40 40 imageBitmap = await createImageBitmap(image); 41 41 42 document.body.appendChild(canvas);42 cancelActions(); 43 43 44 44 context.strokeStyle = "red"; … … 57 57 } 58 58 59 let requestAnimationFrameId = NaN; 60 59 61 function cancelActions() { 62 cancelAnimationFrame(requestAnimationFrameId); 63 requestAnimationFrameId = NaN; 64 65 context.resetTransform(); 66 context.beginPath(); 67 context.clearRect(0, 0, context.canvas.width, context.canvas.height); 60 68 } 61 69 … … 98 106 frames[index++](); 99 107 if (index < frames.length) 100 timeoutID = setTimeout(executeFrameFunction, 0);108 requestAnimationFrameId = requestAnimationFrame(executeFrameFunction); 101 109 }; 102 110 executeFrameFunction(); -
trunk/LayoutTests/inspector/canvas/recording-webgl.html
r237777 r243356 50 50 texture = context.createTexture(); 51 51 52 document.body.appendChild(context.canvas);52 cancelActions(); 53 53 54 54 runTest(); … … 61 61 } 62 62 63 let timeoutID= NaN;63 let requestAnimationFrameId = NaN; 64 64 65 65 function cancelActions() { 66 c learTimeout(timeoutID);67 timeoutID= NaN;66 cancelAnimationFrame(requestAnimationFrameId); 67 requestAnimationFrameId = NaN; 68 68 69 69 context.clearColor(0.0, 0.0, 0.0, 0.0); … … 503 503 frames[index++](); 504 504 if (index < frames.length) 505 timeoutID = setTimeout(executeFrameFunction, 0);505 requestAnimationFrameId = requestAnimationFrame(executeFrameFunction); 506 506 }; 507 507 executeFrameFunction(); -
trunk/LayoutTests/inspector/canvas/setRecordingAutoCaptureFrameCount.html
r237681 r243356 7 7 window.internals.settings.setWebGLErrorsToConsoleEnabled(false); 8 8 9 let timeoutID= NaN;9 let requestAnimationFrameId = NaN; 10 10 11 11 function cancelActions() { 12 c learTimeout(timeoutID);13 timeoutID= NaN;12 cancelAnimationFrame(requestAnimationFrameId); 13 requestAnimationFrameId = NaN; 14 14 } 15 15 … … 20 20 21 21 if (index < frames.length) 22 timeoutID = setTimeout(executeFrameFunction, 0);22 requestAnimationFrameId = requestAnimationFrame(executeFrameFunction); 23 23 else { 24 24 setTimeout(() => { -
trunk/Source/WebCore/ChangeLog
r243354 r243356 1 2019-03-21 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: Safari Canvas Inspector seems to show the canvas being rendered twice per frame. 4 https://bugs.webkit.org/show_bug.cgi?id=196082 5 <rdar://problem/49113496> 6 7 Reviewed by Dean Jackson. 8 9 Tests: inspector/canvas/recording-2d.html 10 inspector/canvas/recording-bitmaprenderer.html 11 inspector/canvas/recording-html-2d.html 12 inspector/canvas/recording-webgl.html 13 inspector/canvas/setRecordingAutoCaptureFrameCount.html 14 15 WebGL `<canvas>` follow a different "rendering" path such that `HTMLCanvasElement::paint` 16 isn't called. Previously, there was a 0s timer that was started after the first action of a 17 frame was recorded (for the case that the `<canvas>` isn't attached to the DOM) that would 18 automatically stop the recording. It was possible that actions in two different "frame"s 19 were recorded as part of the same frame, because the WebGL `<canvas>` would instead fall 20 back to the timer to know when the "frame" had ended. 21 22 Now, there is additional instrumentation for the WebGL specific rendering path. 23 Additionally, replace the 0s timer with a microtask for more "immediate" calling. 24 25 * html/HTMLCanvasElement.cpp: 26 (WebCore::HTMLCanvasElement::paint): 27 Ensure that the `InspectorInstrumentation` call is last. This matches what we expect, as 28 before we were instrumenting right before is it about to paint. 29 30 * platform/graphics/GraphicsContext3D.h: 31 (WebCore::GraphicsContext3D::Client::~Client): Added. 32 (WebCore::GraphicsContext3D::addClient): Added. 33 (WebCore::GraphicsContext3D::removeClient): Added. 34 (WebCore::GraphicsContext3D::setWebGLContext): Deleted. 35 * platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp: 36 (WebCore::GraphicsContext3D::markLayerComposited): 37 (WebCore::GraphicsContext3D::forceContextLost): 38 (WebCore::GraphicsContext3D::recycleContext): 39 (WebCore::GraphicsContext3D::dispatchContextChangedNotification): 40 * html/canvas/WebGLRenderingContextBase.h: 41 * html/canvas/WebGLRenderingContextBase.cpp: 42 (WebCore::WebGLRenderingContextBase::WebGLRenderingContextBase): 43 (WebCore::WebGLRenderingContextBase::destroyGraphicsContext3D): 44 (WebCore::WebGLRenderingContextBase::didComposite): Added. 45 (WebCore::WebGLRenderingContextBase::forceContextLost): 46 (WebCore::WebGLRenderingContextBase::recycleContext): 47 (WebCore::WebGLRenderingContextBase::dispatchContextChangedNotification): Added. 48 (WebCore::WebGLRenderingContextBase::dispatchContextChangedEvent): Deleted. 49 Introduce a `GraphicsContext3DClient` abstract class, rather than passing the 50 `WebGLRenderingContextBase` directly to the `GraphicsContext3D` (layering violation). 51 Notify the client whenever the `GraphicsContext3D` composites, which will in turn notify the 52 `InspectorCanvasAgent` so that it knows that the "frame" is over. 53 54 * inspector/agents/InspectorCanvasAgent.h: 55 * inspector/agents/InspectorCanvasAgent.cpp: 56 (WebCore::InspectorCanvasAgent::InspectorCanvasAgent): 57 (WebCore::InspectorCanvasAgent::requestNode): 58 (WebCore::InspectorCanvasAgent::requestContent): 59 (WebCore::InspectorCanvasAgent::requestCSSCanvasClientNodes): 60 (WebCore::InspectorCanvasAgent::resolveCanvasContext): 61 (WebCore::InspectorCanvasAgent::startRecording): 62 (WebCore::InspectorCanvasAgent::stopRecording): 63 (WebCore::InspectorCanvasAgent::requestShaderSource): 64 (WebCore::InspectorCanvasAgent::updateShader): 65 (WebCore::InspectorCanvasAgent::setShaderProgramDisabled): 66 (WebCore::InspectorCanvasAgent::setShaderProgramHighlighted): 67 (WebCore::InspectorCanvasAgent::didChangeCSSCanvasClientNodes): 68 (WebCore::InspectorCanvasAgent::didChangeCanvasMemory): 69 (WebCore::InspectorCanvasAgent::recordCanvasAction): 70 (WebCore::InspectorCanvasAgent::canvasDestroyed): 71 (WebCore::InspectorCanvasAgent::didFinishRecordingCanvasFrame): 72 (WebCore::InspectorCanvasAgent::consoleStartRecordingCanvas): 73 (WebCore::InspectorCanvasAgent::didEnableExtension): 74 (WebCore::InspectorCanvasAgent::didCreateProgram): 75 (WebCore::InspectorCanvasAgent::willDeleteProgram): 76 (WebCore::InspectorCanvasAgent::isShaderProgramDisabled): 77 (WebCore::InspectorCanvasAgent::isShaderProgramHighlighted): 78 (WebCore::InspectorCanvasAgent::clearCanvasData): 79 (WebCore::InspectorCanvasAgent::assertInspectorCanvas): 80 (WebCore::InspectorCanvasAgent::findInspectorCanvas): 81 (WebCore::InspectorCanvasAgent::assertInspectorProgram): 82 (WebCore::InspectorCanvasAgent::findInspectorProgram): 83 (WebCore::InspectorCanvasAgent::canvasRecordingTimerFired): Deleted. 84 Replace raw pointers with `RefPtr`s. This is primarily used so that the microtask (instead 85 of a timer) that is enqueued after the first action of each frame is recorded can access a 86 ref-counted instance of an `InspectorCanvas`, ensuring that it isn't destructed. 87 88 * inspector/InspectorCanvas.h: 89 * inspector/InspectorCanvas.cpp: 90 (WebCore::InspectorCanvas::canvasElement): 91 (WebCore::InspectorCanvas::recordAction): 92 (WebCore::InspectorCanvas::finalizeFrame): 93 (WebCore::InspectorCanvas::releaseObjectForRecording): Added. 94 (WebCore::InspectorCanvas::getCanvasContentAsDataURL): 95 (WebCore::InspectorCanvas::appendActionSnapshotIfNeeded): 96 (WebCore::InspectorCanvas::buildInitialState): 97 (WebCore::InspectorCanvas::releaseInitialState): Deleted. 98 (WebCore::InspectorCanvas::releaseFrames): Deleted. 99 (WebCore::InspectorCanvas::releaseData): Deleted. 100 Move the recording payload construction logic to `InspectorCanvas` so the actual data 101 doesn't need to leave that class. 102 Drive-by: unify the logic for getting the contents of a canvas from `InspectorCanvasAgent`. 103 1 104 2019-03-21 Tim Horton <timothy_horton@apple.com> 2 105 -
trunk/Source/WebCore/html/HTMLCanvasElement.cpp
r243163 r243356 669 669 void HTMLCanvasElement::paint(GraphicsContext& context, const LayoutRect& r) 670 670 { 671 // Clear the dirty rect 672 m_dirtyRect = FloatRect(); 673 674 if (!context.paintingDisabled()) { 675 bool shouldPaint = true; 676 677 if (m_context) { 678 shouldPaint = paintsIntoCanvasBuffer() || document().printing(); 679 if (shouldPaint) 680 m_context->paintRenderingResultsToCanvas(); 681 } 682 683 if (shouldPaint) { 684 if (hasCreatedImageBuffer()) { 685 ImageBuffer* imageBuffer = buffer(); 686 if (imageBuffer) { 687 if (m_presentedImage) { 688 ImageOrientationDescription orientationDescription; 689 #if ENABLE(CSS_IMAGE_ORIENTATION) 690 orientationDescription.setImageOrientationEnum(renderer()->style().imageOrientation()); 691 #endif 692 context.drawImage(*m_presentedImage, snappedIntRect(r), ImagePaintingOptions(orientationDescription)); 693 } else 694 context.drawImageBuffer(*imageBuffer, snappedIntRect(r)); 695 } 696 } 697 698 if (isGPUBased()) 699 downcast<GPUBasedCanvasRenderingContext>(*m_context).markLayerComposited(); 700 } 701 } 702 671 703 if (UNLIKELY(m_context && m_context->callTracingActive())) 672 704 InspectorInstrumentation::didFinishRecordingCanvasFrame(*m_context); 673 674 // Clear the dirty rect675 m_dirtyRect = FloatRect();676 677 if (context.paintingDisabled())678 return;679 680 if (m_context) {681 if (!paintsIntoCanvasBuffer() && !document().printing())682 return;683 684 m_context->paintRenderingResultsToCanvas();685 }686 687 if (hasCreatedImageBuffer()) {688 ImageBuffer* imageBuffer = buffer();689 if (imageBuffer) {690 if (m_presentedImage) {691 ImageOrientationDescription orientationDescription;692 #if ENABLE(CSS_IMAGE_ORIENTATION)693 orientationDescription.setImageOrientationEnum(renderer()->style().imageOrientation());694 #endif695 context.drawImage(*m_presentedImage, snappedIntRect(r), ImagePaintingOptions(orientationDescription));696 } else697 context.drawImageBuffer(*imageBuffer, snappedIntRect(r));698 }699 }700 701 if (isGPUBased())702 downcast<GPUBasedCanvasRenderingContext>(*m_context).markLayerComposited();703 705 } 704 706 -
trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp
r243163 r243356 662 662 m_contextGroup->addContext(*this); 663 663 664 m_context-> setWebGLContext(this);664 m_context->addClient(*this); 665 665 666 666 m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDims); … … 915 915 916 916 if (m_context) { 917 m_context->removeClient(*this); 917 918 m_context->setContextLostCallback(nullptr); 918 919 m_context->setErrorMessageCallback(nullptr); … … 5043 5044 } 5044 5045 5045 void WebGLRenderingContextBase::recycleContext()5046 {5047 printToConsole(MessageLevel::Error, "There are too many active WebGL contexts on this page, the oldest context will be lost.");5048 // Using SyntheticLostContext means the developer won't be able to force the restoration5049 // of the context by calling preventDefault() in a "webglcontextlost" event handler.5050 forceLostContext(SyntheticLostContext);5051 destroyGraphicsContext3D();5052 }5053 5054 5046 void WebGLRenderingContextBase::loseContextImpl(WebGLRenderingContextBase::LostContextMode mode) 5055 5047 { … … 6226 6218 } 6227 6219 6228 void WebGLRenderingContextBase::dispatchContextChangedEvent()6229 {6230 auto* canvas = htmlCanvas();6231 if (!canvas)6232 return;6233 6234 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextchangedEvent, Event::CanBubble::No, Event::IsCancelable::Yes, emptyString()));6235 }6236 6237 6220 void WebGLRenderingContextBase::simulateContextChanged() 6238 6221 { … … 6514 6497 } 6515 6498 6499 void WebGLRenderingContextBase::didComposite() 6500 { 6501 if (UNLIKELY(callTracingActive())) 6502 InspectorInstrumentation::didFinishRecordingCanvasFrame(*this); 6503 } 6504 6505 void WebGLRenderingContextBase::forceContextLost() 6506 { 6507 forceLostContext(WebGLRenderingContextBase::RealLostContext); 6508 } 6509 6510 void WebGLRenderingContextBase::recycleContext() 6511 { 6512 printToConsole(MessageLevel::Error, "There are too many active WebGL contexts on this page, the oldest context will be lost."); 6513 // Using SyntheticLostContext means the developer won't be able to force the restoration 6514 // of the context by calling preventDefault() in a "webglcontextlost" event handler. 6515 forceLostContext(SyntheticLostContext); 6516 destroyGraphicsContext3D(); 6517 } 6518 6519 void WebGLRenderingContextBase::dispatchContextChangedNotification() 6520 { 6521 auto* canvas = htmlCanvas(); 6522 if (!canvas) 6523 return; 6524 6525 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextchangedEvent, Event::CanBubble::No, Event::IsCancelable::Yes, emptyString())); 6526 } 6527 6528 6516 6529 } // namespace WebCore 6517 6530 -
trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h
r239427 r243356 95 95 using WebGLCanvas = WTF::Variant<RefPtr<HTMLCanvasElement>, RefPtr<OffscreenCanvas>>; 96 96 97 class WebGLRenderingContextBase : public G PUBasedCanvasRenderingContext, private ActivityStateChangeObserver {97 class WebGLRenderingContextBase : public GraphicsContext3D::Client, public GPUBasedCanvasRenderingContext, private ActivityStateChangeObserver { 98 98 public: 99 99 static std::unique_ptr<WebGLRenderingContextBase> create(CanvasBase&, WebGLContextAttributes&, const String&); … … 331 331 }; 332 332 void forceLostContext(LostContextMode); 333 void recycleContext();334 333 void forceRestoreContext(); 335 334 void loseContextImpl(LostContextMode); 336 void dispatchContextChangedEvent();337 335 WEBCORE_EXPORT void simulateContextChanged(); 338 336 … … 359 357 // Used for testing only, from Internals. 360 358 WEBCORE_EXPORT void setFailNextGPUStatusCheck(); 359 360 // GraphicsContext3D::Client 361 void didComposite() override; 362 void forceContextLost() override; 363 void recycleContext() override; 364 void dispatchContextChangedNotification() override; 361 365 362 366 protected: -
trunk/Source/WebCore/inspector/InspectorCanvas.cpp
r242759 r243356 90 90 HTMLCanvasElement* InspectorCanvas::canvasElement() 91 91 { 92 auto* canvasBase = &m_context.canvasBase(); 93 if (is<HTMLCanvasElement>(canvasBase)) 94 return downcast<HTMLCanvasElement>(canvasBase); 92 if (is<HTMLCanvasElement>(m_context.canvasBase())) 93 return &downcast<HTMLCanvasElement>(m_context.canvasBase()); 95 94 return nullptr; 96 95 } … … 138 137 { 139 138 if (!m_initialState) { 139 // We should only construct the initial state for the first action of the recording. 140 ASSERT(!m_frames && !m_currentActions); 141 140 142 m_initialState = buildInitialState(); 141 143 m_bufferUsed += m_initialState->memoryCost(); … … 172 174 } 173 175 174 RefPtr<Inspector::Protocol::Recording::InitialState>&& InspectorCanvas::releaseInitialState() 175 { 176 return WTFMove(m_initialState); 177 } 178 179 RefPtr<JSON::ArrayOf<Inspector::Protocol::Recording::Frame>>&& InspectorCanvas::releaseFrames() 176 void InspectorCanvas::finalizeFrame() 180 177 { 181 178 appendActionSnapshotIfNeeded(); 182 179 183 return WTFMove(m_frames);184 }185 186 RefPtr<JSON::ArrayOf<JSON::Value>>&& InspectorCanvas::releaseData()187 {188 m_indexedDuplicateData.clear();189 return WTFMove(m_serializedDuplicateData);190 }191 192 void InspectorCanvas::finalizeFrame()193 {194 180 if (m_frames && m_frames->length() && !std::isnan(m_currentFrameStartTime)) { 195 181 auto currentFrame = static_cast<Inspector::Protocol::Recording::Frame*>(m_frames->get(m_frames->length() - 1).get()); … … 312 298 } 313 299 300 Ref<Inspector::Protocol::Recording::Recording> InspectorCanvas::releaseObjectForRecording() 301 { 302 ASSERT(!m_currentActions); 303 ASSERT(!m_actionNeedingSnapshot); 304 ASSERT(!m_frames); 305 306 // FIXME: <https://webkit.org/b/176008> Web Inspector: Record actions performed on WebGL2RenderingContext 307 308 Inspector::Protocol::Recording::Type type; 309 if (is<CanvasRenderingContext2D>(m_context)) 310 type = Inspector::Protocol::Recording::Type::Canvas2D; 311 else if (is<ImageBitmapRenderingContext>(m_context)) 312 type = Inspector::Protocol::Recording::Type::CanvasBitmapRenderer; 313 #if ENABLE(WEBGL) 314 else if (is<WebGLRenderingContext>(m_context)) 315 type = Inspector::Protocol::Recording::Type::CanvasWebGL; 316 #endif 317 else { 318 ASSERT_NOT_REACHED(); 319 type = Inspector::Protocol::Recording::Type::Canvas2D; 320 } 321 322 auto recording = Inspector::Protocol::Recording::Recording::create() 323 .setVersion(Inspector::Protocol::Recording::VERSION) 324 .setType(type) 325 .setInitialState(m_initialState.releaseNonNull()) 326 .setData(m_serializedDuplicateData.releaseNonNull()) 327 .release(); 328 329 if (!m_recordingName.isEmpty()) 330 recording->setName(m_recordingName); 331 332 resetRecordingData(); 333 334 return recording; 335 } 336 337 String InspectorCanvas::getCanvasContentAsDataURL(ErrorString& errorString) 338 { 339 // FIXME: <https://webkit.org/b/173621> Web Inspector: Support getting the content of WebMetal context; 340 if (!is<CanvasRenderingContext2D>(m_context) 341 #if ENABLE(WEBGL) 342 && !is<WebGLRenderingContextBase>(m_context) 343 #endif 344 && !is<ImageBitmapRenderingContext>(m_context)) { 345 errorString = "Unsupported canvas context type"_s; 346 return emptyString(); 347 } 348 349 // FIXME: <https://webkit.org/b/180833> Web Inspector: support OffscreenCanvas for Canvas related operations 350 auto* node = canvasElement(); 351 if (!node) { 352 errorString = "Context isn't related to an HTMLCanvasElement"_s; 353 return emptyString(); 354 } 355 356 #if ENABLE(WEBGL) 357 if (is<WebGLRenderingContextBase>(m_context)) 358 downcast<WebGLRenderingContextBase>(m_context).setPreventBufferClearForInspector(true); 359 #endif 360 361 ExceptionOr<UncachedString> result = node->toDataURL("image/png"_s); 362 363 #if ENABLE(WEBGL) 364 if (is<WebGLRenderingContextBase>(m_context)) 365 downcast<WebGLRenderingContextBase>(m_context).setPreventBufferClearForInspector(false); 366 #endif 367 368 if (result.hasException()) { 369 errorString = result.releaseException().releaseMessage(); 370 return emptyString(); 371 } 372 373 return result.releaseReturnValue().string; 374 } 375 314 376 void InspectorCanvas::appendActionSnapshotIfNeeded() 315 377 { … … 317 379 return; 318 380 319 m_actionNeedingSnapshot->addItem(indexForData(getCanvasContentAsDataURL())); 381 m_bufferUsed -= m_actionNeedingSnapshot->memoryCost(); 382 383 ErrorString ignored; 384 m_actionNeedingSnapshot->addItem(indexForData(getCanvasContentAsDataURL(ignored))); 385 386 m_bufferUsed += m_actionNeedingSnapshot->memoryCost(); 387 320 388 m_actionNeedingSnapshot = nullptr; 321 }322 323 String InspectorCanvas::getCanvasContentAsDataURL()324 {325 // FIXME: <https://webkit.org/b/180833> Web Inspector: support OffscreenCanvas for Canvas related operations326 327 auto* node = canvasElement();328 if (!node)329 return String();330 331 #if ENABLE(WEBGL)332 if (is<WebGLRenderingContextBase>(m_context))333 downcast<WebGLRenderingContextBase>(m_context).setPreventBufferClearForInspector(true);334 #endif335 336 ExceptionOr<UncachedString> result = node->toDataURL("image/png"_s);337 338 #if ENABLE(WEBGL)339 if (is<WebGLRenderingContextBase>(m_context))340 downcast<WebGLRenderingContextBase>(m_context).setPreventBufferClearForInspector(false);341 #endif342 343 if (result.hasException())344 return String();345 346 return result.releaseReturnValue().string;347 389 } 348 390 … … 562 604 initialStatePayload->setParameters(WTFMove(parametersPayload)); 563 605 564 initialStatePayload->setContent(getCanvasContentAsDataURL()); 606 ErrorString ignored; 607 initialStatePayload->setContent(getCanvasContentAsDataURL(ignored)); 565 608 566 609 return initialStatePayload; -
trunk/Source/WebCore/inspector/InspectorCanvas.h
r239427 r243356 45 45 class ImageData; 46 46 47 typedef String ErrorString; 48 47 49 class InspectorCanvas final : public RefCounted<InspectorCanvas> { 48 50 public: … … 59 61 void recordAction(const String&, Vector<RecordCanvasActionVariant>&& = { }); 60 62 61 RefPtr<Inspector::Protocol::Recording::InitialState>&& releaseInitialState(); 62 RefPtr<JSON::ArrayOf<Inspector::Protocol::Recording::Frame>>&& releaseFrames(); 63 RefPtr<JSON::ArrayOf<JSON::Value>>&& releaseData(); 63 Ref<JSON::ArrayOf<Inspector::Protocol::Recording::Frame>> releaseFrames() { return m_frames.releaseNonNull(); } 64 64 65 65 void finalizeFrame(); 66 66 void markCurrentFrameIncomplete(); 67 67 68 const String& recordingName() const { return m_recordingName; }69 68 void setRecordingName(const String& name) { m_recordingName = name; } 70 69 … … 77 76 78 77 Ref<Inspector::Protocol::Canvas::Canvas> buildObjectForCanvas(bool captureBacktrace); 78 Ref<Inspector::Protocol::Recording::Recording> releaseObjectForRecording(); 79 80 String getCanvasContentAsDataURL(ErrorString&); 79 81 80 82 private: 81 83 InspectorCanvas(CanvasRenderingContext&); 82 84 void appendActionSnapshotIfNeeded(); 83 String getCanvasContentAsDataURL();84 85 85 86 using DuplicateDataVariant = Variant< -
trunk/Source/WebCore/inspector/agents/InspectorCanvasAgent.cpp
r243303 r243356 27 27 #include "InspectorCanvasAgent.h" 28 28 29 #include "ActiveDOMCallbackMicrotask.h" 29 30 #include "CanvasRenderingContext.h" 30 31 #include "CanvasRenderingContext2D.h" … … 38 39 #include "JSExecState.h" 39 40 #include "JSImageBitmapRenderingContext.h" 41 #include "Microtasks.h" 40 42 #include "OffscreenCanvas.h" 41 43 #include "ScriptState.h" … … 79 81 , m_inspectedPage(context.inspectedPage) 80 82 , m_canvasDestroyedTimer(*this, &InspectorCanvasAgent::canvasDestroyedTimerFired) 81 , m_canvasRecordingTimer(*this, &InspectorCanvasAgent::canvasRecordingTimerFired)82 83 { 83 84 } … … 148 149 void InspectorCanvasAgent::requestNode(ErrorString& errorString, const String& canvasId, int* nodeId) 149 150 { 150 auto *inspectorCanvas = assertInspectorCanvas(errorString, canvasId);151 auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId); 151 152 if (!inspectorCanvas) 152 153 return; … … 169 170 void InspectorCanvasAgent::requestContent(ErrorString& errorString, const String& canvasId, String* content) 170 171 { 171 auto* inspectorCanvas = assertInspectorCanvas(errorString, canvasId); 172 if (!inspectorCanvas) 173 return; 174 175 // FIXME: <https://webkit.org/b/180833> Web Inspector: support OffscreenCanvas for Canvas related operations 176 177 if (auto* node = inspectorCanvas->canvasElement()) { 178 if (is<CanvasRenderingContext2D>(inspectorCanvas->context()) || is<ImageBitmapRenderingContext>(inspectorCanvas->context())) { 179 auto result = node->toDataURL("image/png"_s); 180 if (result.hasException()) { 181 errorString = result.releaseException().releaseMessage(); 182 return; 183 } 184 *content = result.releaseReturnValue().string; 185 return; 186 } 187 188 #if ENABLE(WEBGL) 189 if (is<WebGLRenderingContextBase>(inspectorCanvas->context())) { 190 WebGLRenderingContextBase& contextWebGLBase = downcast<WebGLRenderingContextBase>(inspectorCanvas->context()); 191 192 contextWebGLBase.setPreventBufferClearForInspector(true); 193 auto result = node->toDataURL("image/png"_s); 194 contextWebGLBase.setPreventBufferClearForInspector(false); 195 196 if (result.hasException()) { 197 errorString = result.releaseException().releaseMessage(); 198 return; 199 } 200 *content = result.releaseReturnValue().string; 201 return; 202 } 203 #endif 204 } 205 206 // FIXME: <https://webkit.org/b/173621> Web Inspector: Support getting the content of WebMetal context; 207 errorString = "Unsupported canvas context type"_s; 172 auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId); 173 if (!inspectorCanvas) 174 return; 175 176 *content = inspectorCanvas->getCanvasContentAsDataURL(errorString); 208 177 } 209 178 210 179 void InspectorCanvasAgent::requestCSSCanvasClientNodes(ErrorString& errorString, const String& canvasId, RefPtr<JSON::ArrayOf<int>>& result) 211 180 { 212 auto *inspectorCanvas = assertInspectorCanvas(errorString, canvasId);181 auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId); 213 182 if (!inspectorCanvas) 214 183 return; … … 251 220 void InspectorCanvasAgent::resolveCanvasContext(ErrorString& errorString, const String& canvasId, const String* objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result) 252 221 { 253 auto *inspectorCanvas = assertInspectorCanvas(errorString, canvasId);222 auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId); 254 223 if (!inspectorCanvas) 255 224 return; … … 280 249 void InspectorCanvasAgent::startRecording(ErrorString& errorString, const String& canvasId, const int* frameCount, const int* memoryLimit) 281 250 { 282 auto *inspectorCanvas = assertInspectorCanvas(errorString, canvasId);251 auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId); 283 252 if (!inspectorCanvas) 284 253 return; … … 299 268 void InspectorCanvasAgent::stopRecording(ErrorString& errorString, const String& canvasId) 300 269 { 301 auto *inspectorCanvas = assertInspectorCanvas(errorString, canvasId);270 auto inspectorCanvas = assertInspectorCanvas(errorString, canvasId); 302 271 if (!inspectorCanvas) 303 272 return; … … 314 283 { 315 284 #if ENABLE(WEBGL) 316 auto *inspectorProgram = assertInspectorProgram(errorString, programId);285 auto inspectorProgram = assertInspectorProgram(errorString, programId); 317 286 if (!inspectorProgram) 318 287 return; … … 336 305 { 337 306 #if ENABLE(WEBGL) 338 auto *inspectorProgram = assertInspectorProgram(errorString, programId);307 auto inspectorProgram = assertInspectorProgram(errorString, programId); 339 308 if (!inspectorProgram) 340 309 return; … … 367 336 { 368 337 #if ENABLE(WEBGL) 369 auto *inspectorProgram = assertInspectorProgram(errorString, programId);338 auto inspectorProgram = assertInspectorProgram(errorString, programId); 370 339 if (!inspectorProgram) 371 340 return; … … 382 351 { 383 352 #if ENABLE(WEBGL) 384 auto *inspectorProgram = assertInspectorProgram(errorString, programId);353 auto inspectorProgram = assertInspectorProgram(errorString, programId); 385 354 if (!inspectorProgram) 386 355 return; … … 425 394 } 426 395 427 auto *inspectorCanvas = findInspectorCanvas(*context);396 auto inspectorCanvas = findInspectorCanvas(*context); 428 397 ASSERT(inspectorCanvas); 429 398 if (!inspectorCanvas) … … 451 420 void InspectorCanvasAgent::didChangeCanvasMemory(CanvasRenderingContext& context) 452 421 { 453 auto *inspectorCanvas = findInspectorCanvas(context);422 auto inspectorCanvas = findInspectorCanvas(context); 454 423 ASSERT(inspectorCanvas); 455 424 if (!inspectorCanvas) … … 464 433 void InspectorCanvasAgent::recordCanvasAction(CanvasRenderingContext& canvasRenderingContext, const String& name, Vector<RecordCanvasActionVariant>&& parameters) 465 434 { 466 auto *inspectorCanvas = findInspectorCanvas(canvasRenderingContext);435 auto inspectorCanvas = findInspectorCanvas(canvasRenderingContext); 467 436 ASSERT(inspectorCanvas); 468 437 if (!inspectorCanvas) … … 473 442 return; 474 443 444 // Only enqueue a microtask for the first action of each frame. Any subsequent actions will be 445 // covered by the initial microtask until the next frame. 446 if (!inspectorCanvas->currentFrameHasData()) { 447 if (auto* scriptExecutionContext = inspectorCanvas->context().canvasBase().scriptExecutionContext()) { 448 auto& queue = MicrotaskQueue::mainThreadQueue(); 449 queue.append(std::make_unique<ActiveDOMCallbackMicrotask>(queue, *scriptExecutionContext, [&, protectedInspectorCanvas = inspectorCanvas.copyRef()] { 450 if (auto* canvasElement = protectedInspectorCanvas->canvasElement()) { 451 if (canvasElement->isDescendantOf(canvasElement->document())) 452 return; 453 } 454 455 if (protectedInspectorCanvas->context().callTracingActive()) 456 didFinishRecordingCanvasFrame(protectedInspectorCanvas->context()); 457 })); 458 } 459 } 460 475 461 inspectorCanvas->recordAction(name, WTFMove(parameters)); 476 477 if (!m_canvasRecordingTimer.isActive())478 m_canvasRecordingTimer.startOneShot(0_s);479 462 480 463 if (!inspectorCanvas->hasBufferSpace()) … … 488 471 return; 489 472 490 auto* inspectorCanvas = findInspectorCanvas(*context); 473 auto inspectorCanvas = findInspectorCanvas(*context); 474 ASSERT(inspectorCanvas); 491 475 if (!inspectorCanvas) 492 476 return; … … 505 489 void InspectorCanvasAgent::didFinishRecordingCanvasFrame(CanvasRenderingContext& context, bool forceDispatch) 506 490 { 507 auto *inspectorCanvas = findInspectorCanvas(context);491 auto inspectorCanvas = findInspectorCanvas(context); 508 492 ASSERT(inspectorCanvas); 509 493 if (!inspectorCanvas) … … 516 500 if (forceDispatch) { 517 501 m_frontendDispatcher->recordingFinished(inspectorCanvas->identifier(), nullptr); 518 519 502 inspectorCanvas->resetRecordingData(); 520 503 } … … 532 515 return; 533 516 534 // FIXME: <https://webkit.org/b/176008> Web Inspector: Record actions performed on WebGL2RenderingContext 535 536 Inspector::Protocol::Recording::Type type; 537 if (is<CanvasRenderingContext2D>(inspectorCanvas->context())) 538 type = Inspector::Protocol::Recording::Type::Canvas2D; 539 else if (is<ImageBitmapRenderingContext>(inspectorCanvas->context())) 540 type = Inspector::Protocol::Recording::Type::CanvasBitmapRenderer; 541 #if ENABLE(WEBGL) 542 else if (is<WebGLRenderingContext>(inspectorCanvas->context())) 543 type = Inspector::Protocol::Recording::Type::CanvasWebGL; 544 #endif 545 else { 546 ASSERT_NOT_REACHED(); 547 type = Inspector::Protocol::Recording::Type::Canvas2D; 548 } 549 550 auto recording = Inspector::Protocol::Recording::Recording::create() 551 .setVersion(Inspector::Protocol::Recording::VERSION) 552 .setType(type) 553 .setInitialState(inspectorCanvas->releaseInitialState()) 554 .setData(inspectorCanvas->releaseData()) 555 .release(); 556 557 const String& name = inspectorCanvas->recordingName(); 558 if (!name.isEmpty()) 559 recording->setName(name); 560 561 m_frontendDispatcher->recordingFinished(inspectorCanvas->identifier(), WTFMove(recording)); 562 563 inspectorCanvas->resetRecordingData(); 517 m_frontendDispatcher->recordingFinished(inspectorCanvas->identifier(), inspectorCanvas->releaseObjectForRecording()); 564 518 } 565 519 566 520 void InspectorCanvasAgent::consoleStartRecordingCanvas(CanvasRenderingContext& context, JSC::ExecState& exec, JSC::JSObject* options) 567 521 { 568 auto *inspectorCanvas = findInspectorCanvas(context);522 auto inspectorCanvas = findInspectorCanvas(context); 569 523 ASSERT(inspectorCanvas); 570 524 if (!inspectorCanvas) … … 588 542 void InspectorCanvasAgent::didEnableExtension(WebGLRenderingContextBase& context, const String& extension) 589 543 { 590 auto *inspectorCanvas = findInspectorCanvas(context);544 auto inspectorCanvas = findInspectorCanvas(context); 591 545 ASSERT(inspectorCanvas); 592 546 if (!inspectorCanvas) … … 598 552 void InspectorCanvasAgent::didCreateProgram(WebGLRenderingContextBase& context, WebGLProgram& program) 599 553 { 600 auto *inspectorCanvas = findInspectorCanvas(context);554 auto inspectorCanvas = findInspectorCanvas(context); 601 555 ASSERT(inspectorCanvas); 602 556 if (!inspectorCanvas) … … 611 565 void InspectorCanvasAgent::willDeleteProgram(WebGLProgram& program) 612 566 { 613 auto *inspectorProgram = findInspectorProgram(program);567 auto inspectorProgram = findInspectorProgram(program); 614 568 if (!inspectorProgram) 615 569 return; … … 621 575 bool InspectorCanvasAgent::isShaderProgramDisabled(WebGLProgram& program) 622 576 { 623 auto* inspectorProgram = findInspectorProgram(program); 577 auto inspectorProgram = findInspectorProgram(program); 578 ASSERT(inspectorProgram); 624 579 if (!inspectorProgram) 625 580 return false; … … 630 585 bool InspectorCanvasAgent::isShaderProgramHighlighted(WebGLProgram& program) 631 586 { 632 auto* inspectorProgram = findInspectorProgram(program); 587 auto inspectorProgram = findInspectorProgram(program); 588 ASSERT(inspectorProgram); 633 589 if (!inspectorProgram) 634 590 return false; … … 675 631 } 676 632 677 void InspectorCanvasAgent::canvasRecordingTimerFired()678 {679 for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values()) {680 if (!inspectorCanvas->context().callTracingActive())681 continue;682 683 didFinishRecordingCanvasFrame(inspectorCanvas->context());684 }685 }686 687 633 void InspectorCanvasAgent::clearCanvasData() 688 634 { … … 691 637 692 638 m_identifierToInspectorCanvas.clear(); 639 #if ENABLE(WEBGL) 640 m_identifierToInspectorProgram.clear(); 693 641 m_removedCanvasIdentifiers.clear(); 694 #if ENABLE(WEBGL) 695 m_identifierToInspectorProgram.clear(); 696 #endif 697 698 if (m_canvasRecordingTimer.isActive()) 699 m_canvasRecordingTimer.stop(); 642 #endif 700 643 701 644 if (m_canvasDestroyedTimer.isActive()) … … 746 689 } 747 690 748 InspectorCanvas*InspectorCanvasAgent::assertInspectorCanvas(ErrorString& errorString, const String& identifier)749 { 750 RefPtr<InspectorCanvas>inspectorCanvas = m_identifierToInspectorCanvas.get(identifier);691 RefPtr<InspectorCanvas> InspectorCanvasAgent::assertInspectorCanvas(ErrorString& errorString, const String& identifier) 692 { 693 auto inspectorCanvas = m_identifierToInspectorCanvas.get(identifier); 751 694 if (!inspectorCanvas) { 752 695 errorString = "No canvas for given identifier."_s; … … 754 697 } 755 698 756 return inspectorCanvas .get();757 } 758 759 InspectorCanvas*InspectorCanvasAgent::findInspectorCanvas(CanvasRenderingContext& context)699 return inspectorCanvas; 700 } 701 702 RefPtr<InspectorCanvas> InspectorCanvasAgent::findInspectorCanvas(CanvasRenderingContext& context) 760 703 { 761 704 for (auto& inspectorCanvas : m_identifierToInspectorCanvas.values()) { 762 705 if (&inspectorCanvas->context() == &context) 763 return inspectorCanvas .get();706 return inspectorCanvas; 764 707 } 765 708 … … 776 719 } 777 720 778 InspectorShaderProgram*InspectorCanvasAgent::assertInspectorProgram(ErrorString& errorString, const String& identifier)779 { 780 RefPtr<InspectorShaderProgram>inspectorProgram = m_identifierToInspectorProgram.get(identifier);721 RefPtr<InspectorShaderProgram> InspectorCanvasAgent::assertInspectorProgram(ErrorString& errorString, const String& identifier) 722 { 723 auto inspectorProgram = m_identifierToInspectorProgram.get(identifier); 781 724 if (!inspectorProgram) { 782 725 errorString = "No shader program for given identifier."_s; … … 784 727 } 785 728 786 return inspectorProgram .get();787 } 788 789 InspectorShaderProgram*InspectorCanvasAgent::findInspectorProgram(WebGLProgram& program)729 return inspectorProgram; 730 } 731 732 RefPtr<InspectorShaderProgram> InspectorCanvasAgent::findInspectorProgram(WebGLProgram& program) 790 733 { 791 734 for (auto& inspectorProgram : m_identifierToInspectorProgram.values()) { 792 735 if (&inspectorProgram->program() == &program) 793 return inspectorProgram .get();736 return inspectorProgram; 794 737 } 795 738 -
trunk/Source/WebCore/inspector/agents/InspectorCanvasAgent.h
r243303 r243356 113 113 114 114 void canvasDestroyedTimerFired(); 115 void canvasRecordingTimerFired();116 115 void clearCanvasData(); 117 116 InspectorCanvas& bindCanvas(CanvasRenderingContext&, bool captureBacktrace); 118 117 String unbindCanvas(InspectorCanvas&); 119 InspectorCanvas*assertInspectorCanvas(ErrorString&, const String& identifier);120 InspectorCanvas*findInspectorCanvas(CanvasRenderingContext&);118 RefPtr<InspectorCanvas> assertInspectorCanvas(ErrorString&, const String& identifier); 119 RefPtr<InspectorCanvas> findInspectorCanvas(CanvasRenderingContext&); 121 120 #if ENABLE(WEBGL) 122 121 String unbindProgram(InspectorShaderProgram&); 123 InspectorShaderProgram* assertInspectorProgram(ErrorString&, const String& identifier); 124 InspectorShaderProgram* findInspectorProgram(WebGLProgram&); 125 126 HashMap<String, RefPtr<InspectorShaderProgram>> m_identifierToInspectorProgram; 122 RefPtr<InspectorShaderProgram> assertInspectorProgram(ErrorString&, const String& identifier); 123 RefPtr<InspectorShaderProgram> findInspectorProgram(WebGLProgram&); 127 124 #endif 128 125 … … 134 131 135 132 HashMap<String, RefPtr<InspectorCanvas>> m_identifierToInspectorCanvas; 133 #if ENABLE(WEBGL) 134 HashMap<String, RefPtr<InspectorShaderProgram>> m_identifierToInspectorProgram; 135 #endif 136 136 Vector<String> m_removedCanvasIdentifiers; 137 137 138 Optional<size_t> m_recordingAutoCaptureFrameCount; 139 138 140 Timer m_canvasDestroyedTimer; 139 Timer m_canvasRecordingTimer;140 141 }; 141 142 -
trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h
r242205 r243356 121 121 class GraphicsContext3D : public RefCounted<GraphicsContext3D> { 122 122 public: 123 class Client { 124 public: 125 virtual ~Client() { } 126 virtual void didComposite() = 0; 127 virtual void forceContextLost() = 0; 128 virtual void recycleContext() = 0; 129 virtual void dispatchContextChangedNotification() = 0; 130 }; 131 123 132 enum { 124 133 // WebGL 1 constants … … 765 774 766 775 bool makeContextCurrent(); 767 void setWebGLContext(WebGLRenderingContextBase* base) { m_webglContext = base; } 776 777 void addClient(Client& client) { m_clients.add(&client); } 778 void removeClient(Client& client) { m_clients.remove(&client); } 768 779 769 780 // With multisampling on, blit from multisampleFBO to regular FBO. … … 1508 1519 #endif 1509 1520 1510 // FIXME: Layering violation. 1511 WebGLRenderingContextBase* m_webglContext { nullptr }; 1521 HashSet<Client*> m_clients; 1512 1522 1513 1523 bool m_isForWebGL2 { false }; -
trunk/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp
r242205 r243356 2017 2017 { 2018 2018 m_layerComposited = true; 2019 2020 for (auto* client : m_clients) 2021 client->didComposite(); 2019 2022 } 2020 2023 … … 2026 2029 void GraphicsContext3D::forceContextLost() 2027 2030 { 2028 #if ENABLE(WEBGL) 2029 if (m_webglContext) 2030 m_webglContext->forceLostContext(WebGLRenderingContextBase::RealLostContext); 2031 #endif 2031 for (auto* client : m_clients) 2032 client->forceContextLost(); 2032 2033 } 2033 2034 2034 2035 void GraphicsContext3D::recycleContext() 2035 2036 { 2036 #if ENABLE(WEBGL) 2037 if (m_webglContext) 2038 m_webglContext->recycleContext(); 2039 #endif 2037 for (auto* client : m_clients) 2038 client->recycleContext(); 2040 2039 } 2041 2040 2042 2041 void GraphicsContext3D::dispatchContextChangedNotification() 2043 2042 { 2044 #if ENABLE(WEBGL) 2045 if (m_webglContext) 2046 m_webglContext->dispatchContextChangedEvent(); 2047 #endif 2043 for (auto* client : m_clients) 2044 client->dispatchContextChangedNotification(); 2048 2045 } 2049 2046
Note:
See TracChangeset
for help on using the changeset viewer.