@@ -1308,8 +1308,9 @@ void WebGLRenderingContextBase::destroyGraphicsContextGL()
13081308 removeActivityStateChangeObserver ();
13091309
13101310 if (m_context) {
1311- // first release the big textures allocated for the FBOs
1312- m_context->reshape (0 ,0 );
1311+ // first release the big textures allocated for the FBOs. Need to set (1, 1) because
1312+ // (0, 0) produces an error on the GL layer.
1313+ m_context->reshape (1 , 1 );
13131314 m_context->setClient (nullptr );
13141315 m_context = nullptr ;
13151316 removeActiveContext (*this );
@@ -6786,14 +6787,44 @@ const char* WebGLRenderingContextBase::activeDOMObjectName() const
67866787 return " WebGLRenderingContext" ;
67876788}
67886789
6789- void WebGLRenderingContextBase::suspend (ReasonForSuspension)
6790+ void WebGLRenderingContextBase::suspend (ReasonForSuspension reason )
67906791{
6792+ if (reason != ReasonForSuspension::BackForwardCache)
6793+ return ;
6794+
6795+ // forceLostContext() will queue a task to dispatch the contextLost event. This task won't
6796+ // be executed until resume, when the events are enabled again.
6797+ forceLostContext (WebGLRenderingContextBase::SyntheticLostContext);
6798+ destroyGraphicsContextGL ();
67916799 m_isSuspended = true ;
67926800}
67936801
67946802void WebGLRenderingContextBase::resume ()
67956803{
67966804 m_isSuspended = false ;
6805+
6806+ // The composition requirements update for the page, which will set the appropriate proxy to the
6807+ // GraphicsLayer created for this WebGL context, will be updated after this function, but before
6808+ // any task that we may schedule. Due to this, we need to create the GCGLContext now, we cannot
6809+ // call forceRestoreContext() that will use a timer to call maybeRestoreContext(), we
6810+ // need to call maybeRestoreContext() directly.
6811+
6812+ // At some point after this function ends, the task to dispatch the contextLost event that was scheduled
6813+ // on suspend will run. The problem is that maybeRestoreContext() later in this function will create a new
6814+ // GCGLContext now, so when the task runs, context is not lost anymore and the event won't be sent. Set
6815+ // m_forceDispatchContextLostEvent so the task sends the event even if the context was already restored.
6816+ m_forceDispatchContextLostEvent = true ;
6817+
6818+ // Set restoreRequested to true so maybeRestoreContext() really performs the restore.
6819+ m_contextLostState->restoreRequested = true ;
6820+
6821+ // Set m_queueContextRestoredEvent so maybeRestoreContext() doesn't send the contextRestored
6822+ // event immediately, but queues it. We need to do this because the contextRestored event that was
6823+ // queued on suspension hasn't run yet, and needs ro run before the contextRestored event is
6824+ // dispatched.
6825+ m_queueContextRestoredEvent = true ;
6826+
6827+ maybeRestoreContext ();
67976828}
67986829
67996830bool WebGLRenderingContextBase::getBooleanParameter (GCGLenum pname)
@@ -7961,10 +7992,14 @@ void WebGLRenderingContextBase::scheduleTaskToDispatchContextLostEvent()
79617992
79627993 // It is safe to capture |this| because we keep the canvas element alive and it owns |this|.
79637994 queueTaskKeepingObjectAlive (*canvas, TaskSource::WebGL, [this , canvas] {
7964- if (isContextStopped ())
7965- return ;
7966- if (!isContextLost ())
7967- return ;
7995+ if (m_forceDispatchContextLostEvent)
7996+ m_forceDispatchContextLostEvent = false ;
7997+ else {
7998+ if (isContextStopped ())
7999+ return ;
8000+ if (!isContextLost ())
8001+ return ;
8002+ }
79688003 auto event = WebGLContextEvent::create (eventNames ().webglcontextlostEvent , Event::CanBubble::No, Event::IsCancelable::Yes, emptyString ());
79698004 canvas->dispatchEvent (event);
79708005 m_contextLostState->restoreRequested = event->defaultPrevented ();
@@ -8016,6 +8051,21 @@ void WebGLRenderingContextBase::maybeRestoreContext()
80168051 m_contextLostState = std::nullopt ;
80178052 setupFlags ();
80188053 initializeNewContext ();
8054+
8055+ if (m_queueContextRestoredEvent) {
8056+ m_queueContextRestoredEvent = false ;
8057+
8058+ // It is safe to capture |this| because we keep the canvas element alive and it owns |this|.
8059+ queueTaskKeepingObjectAlive (*canvas, TaskSource::WebGL, [this , canvas] {
8060+ if (isContextStopped ())
8061+ return ;
8062+ if (isContextLost ())
8063+ return ;
8064+ canvas->dispatchEvent (WebGLContextEvent::create (eventNames ().webglcontextrestoredEvent , Event::CanBubble::No, Event::IsCancelable::Yes, emptyString ()));
8065+ });
8066+ return ;
8067+ }
8068+
80198069 if (!isContextLost ())
80208070 canvas->dispatchEvent (WebGLContextEvent::create (eventNames ().webglcontextrestoredEvent , Event::CanBubble::No, Event::IsCancelable::Yes, emptyString ()));
80218071}
0 commit comments