diff --git a/patch/Release-823.patch b/patch/Release-823.patch new file mode 100644 index 0000000000000000000000000000000000000000..3ca3787c1bb85c5683fb58067c33017bc0f29935 --- /dev/null +++ b/patch/Release-823.patch @@ -0,0 +1,633 @@ +diff --git a/src/content/test/data/gpu/webgl-overly-large-uniform.html b/src/content/test/data/gpu/webgl-overly-large-uniform.html +new file mode 100644 +index 0000000000000..9b28fa5ebc2d6 +--- /dev/null ++++ b/src/content/test/data/gpu/webgl-overly-large-uniform.html +@@ -0,0 +1,137 @@ ++ ++
++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/content/test/gpu/gpu_tests/context_lost_integration_test.py b/src/content/test/gpu/gpu_tests/context_lost_integration_test.py +index 9096205323b23..315338ca8795a 100755 +--- a/src/content/test/gpu/gpu_tests/context_lost_integration_test.py ++++ b/src/content/test/gpu/gpu_tests/context_lost_integration_test.py +@@ -160,6 +160,8 @@ class ContextLostIntegrationTest(gpu_integration_test.GpuIntegrationTest): + 'webgl_with_select_element.html'), + ('ContextLost_WebGLContextLostInHiddenTab', + 'webgl.html?query=kill_after_notification'), ++ ('ContextLost_WebGLContextLostOverlyLargeUniform', ++ 'webgl-overly-large-uniform.html'), + ('ContextLost_WebGLBlockedAfterJSNavigation', + 'webgl-domain-blocking-page1.html'), + ('ContextLost_WebGLUnblockedAfterUserInitiatedReload', +@@ -387,6 +389,16 @@ class ContextLostIntegrationTest(gpu_integration_test.GpuIntegrationTest): + tab.Activate() + self._WaitForTabAndCheckCompletion() + ++ def _ContextLost_WebGLContextLostOverlyLargeUniform(self, ++ test_path: str) -> None: ++ self.RestartBrowserIfNecessaryWithArgs([ ++ cba.DISABLE_DOMAIN_BLOCKING_FOR_3D_APIS, ++ '--enable-features=DisableArrayBufferSizeLimitsForTesting' ++ ]) ++ self._NavigateAndWaitForLoad(test_path) ++ # No reason to wait more than 10 seconds for this test to complete. ++ self._WaitForTabAndCheckCompletion(timeout=10) ++ + def _ContextLost_WebGLBlockedAfterJSNavigation(self, test_path): + self.RestartBrowserIfNecessaryWithArgs([]) + self._NavigateAndWaitForLoad(test_path) +diff --git a/src/gpu/command_buffer/client/client_discardable_manager_unittest.cc b/src/gpu/command_buffer/client/client_discardable_manager_unittest.cc +index 4b86fca0a696d..026ee81f42bdc 100644 +--- a/src/gpu/command_buffer/client/client_discardable_manager_unittest.cc ++++ b/src/gpu/command_buffer/client/client_discardable_manager_unittest.cc +@@ -45,6 +45,9 @@ class FakeCommandBuffer : public CommandBuffer { + EXPECT_TRUE(found != active_ids_.end()); + active_ids_.erase(found); + } ++ void ForceLostContext(error::ContextLostReason reason) override { ++ // No-op; doesn't need to be exercised here. ++ } + + private: + int32_t next_id_ = 1; +diff --git a/src/gpu/command_buffer/client/client_test_helper.cc b/src/gpu/command_buffer/client/client_test_helper.cc +index 4fd55a3274a87..826f466f40cfa 100644 +--- a/src/gpu/command_buffer/client/client_test_helper.cc ++++ b/src/gpu/command_buffer/client/client_test_helper.cc +@@ -158,6 +158,13 @@ void MockClientCommandBuffer::DelegateToFake() { + this, &FakeCommandBufferServiceBase::DestroyTransferBufferHelper)); + } + ++void MockClientCommandBuffer::ForceLostContext( ++ error::ContextLostReason reason) { ++ // TODO(kbr): add a test for a call to this method. ++ SetParseError(error::kLostContext); ++ SetContextLostReason(reason); ++} ++ + MockClientCommandBufferMockFlush::MockClientCommandBufferMockFlush() { + DelegateToFake(); + } +diff --git a/src/gpu/command_buffer/client/client_test_helper.h b/src/gpu/command_buffer/client/client_test_helper.h +index bd0cc0739efaa..2548be832472a 100644 +--- a/src/gpu/command_buffer/client/client_test_helper.h ++++ b/src/gpu/command_buffer/client/client_test_helper.h +@@ -86,6 +86,8 @@ class MockClientCommandBuffer : public CommandBuffer, + + void SetTokenForSetGetBuffer(int32_t token) { token_ = token; } + ++ void ForceLostContext(error::ContextLostReason reason) override; ++ + private: + int32_t put_offset_ = 0; + int32_t token_ = 10000; // All token checks in the tests should pass. +diff --git a/src/gpu/command_buffer/client/cmd_buffer_helper.cc b/src/gpu/command_buffer/client/cmd_buffer_helper.cc +index 620fa6535a890..5d9d1c23dddf7 100644 +--- a/src/gpu/command_buffer/client/cmd_buffer_helper.cc ++++ b/src/gpu/command_buffer/client/cmd_buffer_helper.cc +@@ -157,7 +157,8 @@ void CommandBufferHelper::UpdateCachedState(const CommandBuffer::State& state) { + (state.set_get_buffer_count != set_get_buffer_count_); + cached_get_offset_ = service_on_old_buffer_ ? 0 : state.get_offset; + cached_last_token_read_ = state.token; +- context_lost_ = error::IsError(state.error); ++ // Don't transition from a lost context to a working context. ++ context_lost_ |= error::IsError(state.error); + } + + bool CommandBufferHelper::WaitForGetOffsetInRange(int32_t start, int32_t end) { +@@ -296,7 +297,6 @@ void CommandBufferHelper::WaitForAvailableEntries(int32_t count) { + if (!AllocateRingBuffer()) + return; + DCHECK(HaveRingBuffer()); +- DCHECK(count < total_entry_count_); + if (put_ + count > total_entry_count_) { + // There's not enough room between the current put and the end of the + // buffer, so we need to wrap. We will add noops all the way to the end, +@@ -344,7 +344,16 @@ void CommandBufferHelper::WaitForAvailableEntries(int32_t count) { + put_)) + return; + CalcImmediateEntries(count); +- DCHECK_GE(immediate_entry_count_, count); ++ if (immediate_entry_count_ < count) { ++ // Tell the underlying command buffer to signal a lost context to higher ++ // levels. ++ command_buffer_->ForceLostContext(error::kGuilty); ++ // Free the ring buffer and lose context. ++ FreeRingBuffer(); ++ usable_ = false; ++ context_lost_ = true; ++ return; ++ } + } + } + } +diff --git a/src/gpu/command_buffer/common/command_buffer.h b/src/gpu/command_buffer/common/command_buffer.h +index 6335c4757f2e2..5ac9069424fe3 100644 +--- a/src/gpu/command_buffer/common/command_buffer.h ++++ b/src/gpu/command_buffer/common/command_buffer.h +@@ -125,6 +125,10 @@ class GPU_EXPORT CommandBuffer { + // before it is safe to call this function to destroy it. + virtual void DestroyTransferBuffer(int32_t id) = 0; + ++ // Forcibly lose this context. Used by higher-level code when it determines ++ // the necessity to do so. Has no effect if the context has already been lost. ++ virtual void ForceLostContext(error::ContextLostReason reason) = 0; ++ + private: + DISALLOW_COPY_AND_ASSIGN(CommandBuffer); + }; +diff --git a/src/gpu/command_buffer/service/command_buffer_direct.cc b/src/gpu/command_buffer/service/command_buffer_direct.cc +index e32139b6bfd65..6a7f7e55487ef 100644 +--- a/src/gpu/command_buffer/service/command_buffer_direct.cc ++++ b/src/gpu/command_buffer/service/command_buffer_direct.cc +@@ -63,6 +63,11 @@ void CommandBufferDirect::DestroyTransferBuffer(int32_t id) { + service_.DestroyTransferBuffer(id); + } + ++void CommandBufferDirect::ForceLostContext(error::ContextLostReason reason) { ++ service_.SetContextLostReason(reason); ++ service_.SetParseError(error::kLostContext); ++} ++ + CommandBufferServiceClient::CommandBatchProcessedResult + CommandBufferDirect::OnCommandBatchProcessed() { + return kContinueExecution; +diff --git a/src/gpu/command_buffer/service/command_buffer_direct.h b/src/gpu/command_buffer/service/command_buffer_direct.h +index d03ac687b6f4b..4d8175c3f56fa 100644 +--- a/src/gpu/command_buffer/service/command_buffer_direct.h ++++ b/src/gpu/command_buffer/service/command_buffer_direct.h +@@ -40,6 +40,7 @@ class GPU_EXPORT CommandBufferDirect : public CommandBuffer, + TransferBufferAllocationOption option = + TransferBufferAllocationOption::kLoseContextOnOOM) override; + void DestroyTransferBuffer(int32_t id) override; ++ void ForceLostContext(error::ContextLostReason reason) override; + + // CommandBufferServiceClient implementation: + CommandBatchProcessedResult OnCommandBatchProcessed() override; +diff --git a/src/gpu/ipc/client/command_buffer_proxy_impl.cc b/src/gpu/ipc/client/command_buffer_proxy_impl.cc +index bfafcdc9524d8..77455d492fbfc 100644 +--- a/src/gpu/ipc/client/command_buffer_proxy_impl.cc ++++ b/src/gpu/ipc/client/command_buffer_proxy_impl.cc +@@ -407,6 +407,22 @@ void CommandBufferProxyImpl::DestroyTransferBuffer(int32_t id) { + GpuCommandBufferMsg_DestroyTransferBuffer(route_id_, id)); + } + ++void CommandBufferProxyImpl::ForceLostContext(error::ContextLostReason reason) { ++ CheckLock(); ++ base::AutoLock lock(last_state_lock_); ++ if (last_state_.error == gpu::error::kLostContext) { ++ // Per specification, do nothing if the context is already lost. ++ return; ++ } ++ last_state_.error = gpu::error::kLostContext; ++ // The caller determines the context lost reason. ++ last_state_.context_lost_reason = reason; ++ // Calling code may be in an indeterminate state (possibly including ++ // being in a GpuControlClient callback), so avoid re-entering the ++ // GpuControlClient here. ++ DisconnectChannelInFreshCallStack(); ++} ++ + void CommandBufferProxyImpl::SetGpuControlClient(GpuControlClient* client) { + CheckLock(); + gpu_control_client_ = client; +diff --git a/src/gpu/ipc/client/command_buffer_proxy_impl.h b/src/gpu/ipc/client/command_buffer_proxy_impl.h +index 3a541f708a32e..540ca3486d869 100644 +--- a/src/gpu/ipc/client/command_buffer_proxy_impl.h ++++ b/src/gpu/ipc/client/command_buffer_proxy_impl.h +@@ -111,6 +111,7 @@ class GPU_EXPORT CommandBufferProxyImpl : public gpu::CommandBuffer, + TransferBufferAllocationOption option = + TransferBufferAllocationOption::kLoseContextOnOOM) override; + void DestroyTransferBuffer(int32_t id) override; ++ void ForceLostContext(error::ContextLostReason reason) override; + + // gpu::GpuControl implementation: + void SetGpuControlClient(GpuControlClient* client) override; +diff --git a/src/gpu/ipc/in_process_command_buffer.cc b/src/gpu/ipc/in_process_command_buffer.cc +index 18dc45de9fa89..e3e9c59e54588 100644 +--- a/src/gpu/ipc/in_process_command_buffer.cc ++++ b/src/gpu/ipc/in_process_command_buffer.cc +@@ -1040,6 +1040,21 @@ void InProcessCommandBuffer::DestroyTransferBuffer(int32_t id) { + gpu_thread_weak_ptr_factory_.GetWeakPtr(), id)); + } + ++void InProcessCommandBuffer::ForceLostContext(error::ContextLostReason reason) { ++ ScheduleGpuTask( ++ base::BindOnce(&InProcessCommandBuffer::ForceLostContextOnGpuThread, ++ gpu_thread_weak_ptr_factory_.GetWeakPtr(), reason)); ++} ++ ++void InProcessCommandBuffer::ForceLostContextOnGpuThread( ++ error::ContextLostReason reason) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); ++ ++ // Similar implementation to CommandBufferDirect. ++ command_buffer_->SetContextLostReason(reason); ++ command_buffer_->SetParseError(error::kLostContext); ++} ++ + void InProcessCommandBuffer::DestroyTransferBufferOnGpuThread(int32_t id) { + DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); + command_buffer_->DestroyTransferBuffer(id); +diff --git a/src/gpu/ipc/in_process_command_buffer.h b/src/gpu/ipc/in_process_command_buffer.h +index 82d4dc1c7263d..5c32e278a30ca 100644 +--- a/src/gpu/ipc/in_process_command_buffer.h ++++ b/src/gpu/ipc/in_process_command_buffer.h +@@ -142,6 +142,7 @@ class GL_IN_PROCESS_CONTEXT_EXPORT InProcessCommandBuffer + TransferBufferAllocationOption option = + TransferBufferAllocationOption::kLoseContextOnOOM) override; + void DestroyTransferBuffer(int32_t id) override; ++ void ForceLostContext(error::ContextLostReason reason) override; + + // GpuControl implementation (called on client thread): + void SetGpuControlClient(GpuControlClient*) override; +@@ -313,6 +314,7 @@ class GL_IN_PROCESS_CONTEXT_EXPORT InProcessCommandBuffer + void RegisterTransferBufferOnGpuThread(int32_t id, + scoped_refptr