| // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "gpu/ipc/service/gpu_channel_test_common.h" |
| |
| #include <memory> |
| |
| #include "base/memory/unsafe_shared_memory_region.h" |
| #include "base/run_loop.h" |
| #include "base/test/bind.h" |
| #include "base/test/test_simple_task_runner.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "base/trace_event/memory_dump_manager.h" |
| #include "gpu/command_buffer/common/activity_flags.h" |
| #include "gpu/command_buffer/service/scheduler.h" |
| #include "gpu/command_buffer/service/shared_image_manager.h" |
| #include "gpu/command_buffer/service/sync_point_manager.h" |
| #include "gpu/ipc/service/context_url.h" |
| #include "gpu/ipc/service/gpu_channel.h" |
| #include "gpu/ipc/service/gpu_channel_manager.h" |
| #include "gpu/ipc/service/gpu_channel_manager_delegate.h" |
| #include "ui/gl/init/gl_factory.h" |
| #include "ui/gl/test/gl_surface_test_support.h" |
| #include "url/gurl.h" |
| |
| namespace gpu { |
| |
| class TestGpuChannelManagerDelegate : public GpuChannelManagerDelegate { |
| public: |
| TestGpuChannelManagerDelegate(Scheduler* scheduler) : scheduler_(scheduler) {} |
| ~TestGpuChannelManagerDelegate() override = default; |
| |
| // GpuChannelManagerDelegate implementation: |
| void RegisterDisplayContext(gpu::DisplayContext* context) override {} |
| void UnregisterDisplayContext(gpu::DisplayContext* context) override {} |
| void LoseAllContexts() override {} |
| void DidCreateContextSuccessfully() override {} |
| void DidCreateOffscreenContext(const GURL& active_url) override {} |
| void DidDestroyChannel(int client_id) override {} |
| void DidDestroyAllChannels() override {} |
| void DidDestroyOffscreenContext(const GURL& active_url) override {} |
| void DidLoseContext(bool offscreen, |
| error::ContextLostReason reason, |
| const GURL& active_url) override {} |
| void StoreShaderToDisk(int32_t client_id, |
| const std::string& key, |
| const std::string& shader) override {} |
| void MaybeExitOnContextLost() override { is_exiting_ = true; } |
| bool IsExiting() const override { return is_exiting_; } |
| #if defined(OS_WIN) |
| void DidUpdateOverlayInfo(const gpu::OverlayInfo& overlay_info) override {} |
| void DidUpdateHDRStatus(bool hdr_enabled) override {} |
| void SendCreatedChildWindow(SurfaceHandle parent_window, |
| SurfaceHandle child_window) override {} |
| #endif |
| |
| Scheduler* GetGpuScheduler() override { return scheduler_; } |
| |
| private: |
| bool is_exiting_ = false; |
| Scheduler* const scheduler_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestGpuChannelManagerDelegate); |
| }; |
| |
| GpuChannelTestCommon::GpuChannelTestCommon(bool use_stub_bindings) |
| : GpuChannelTestCommon(std::vector<int32_t>(), use_stub_bindings) {} |
| |
| GpuChannelTestCommon::GpuChannelTestCommon( |
| std::vector<int32_t> enabled_workarounds, |
| bool use_stub_bindings) |
| : memory_dump_manager_( |
| base::trace_event::MemoryDumpManager::CreateInstanceForTesting()), |
| sync_point_manager_(new SyncPointManager()), |
| shared_image_manager_(new SharedImageManager(false /* thread_safe */)), |
| scheduler_(new Scheduler(task_environment_.GetMainThreadTaskRunner(), |
| sync_point_manager_.get(), |
| GpuPreferences())), |
| channel_manager_delegate_( |
| new TestGpuChannelManagerDelegate(scheduler_.get())) { |
| // We need GL bindings to actually initialize command buffers. |
| if (use_stub_bindings) { |
| gl::GLSurfaceTestSupport::InitializeOneOffWithStubBindings(); |
| } else { |
| gl::GLSurfaceTestSupport::InitializeOneOff(); |
| } |
| |
| GpuFeatureInfo feature_info; |
| feature_info.enabled_gpu_driver_bug_workarounds = |
| std::move(enabled_workarounds); |
| |
| channel_manager_ = std::make_unique<GpuChannelManager>( |
| GpuPreferences(), channel_manager_delegate_.get(), nullptr, /* watchdog */ |
| task_environment_.GetMainThreadTaskRunner(), |
| task_environment_.GetMainThreadTaskRunner(), scheduler_.get(), |
| sync_point_manager_.get(), shared_image_manager_.get(), |
| nullptr, /* gpu_memory_buffer_factory */ |
| std::move(feature_info), GpuProcessActivityFlags(), |
| gl::init::CreateOffscreenGLSurface(gfx::Size()), |
| nullptr /* image_decode_accelerator_worker */); |
| } |
| |
| GpuChannelTestCommon::~GpuChannelTestCommon() { |
| // Command buffers can post tasks and run GL in destruction so do this first. |
| channel_manager_ = nullptr; |
| task_environment_.RunUntilIdle(); |
| gl::init::ShutdownGL(false); |
| } |
| |
| GpuChannel* GpuChannelTestCommon::CreateChannel(int32_t client_id, |
| bool is_gpu_host) { |
| uint64_t kClientTracingId = 1; |
| GpuChannel* channel = channel_manager()->EstablishChannel( |
| client_id, kClientTracingId, is_gpu_host, true); |
| channel->InitForTesting(&sink_); |
| base::ProcessId kProcessId = 1; |
| channel->OnChannelConnected(kProcessId); |
| return channel; |
| } |
| |
| void GpuChannelTestCommon::CreateCommandBuffer( |
| GpuChannel& channel, |
| mojom::CreateCommandBufferParamsPtr init_params, |
| int32_t routing_id, |
| base::UnsafeSharedMemoryRegion shared_state, |
| ContextResult* out_result, |
| Capabilities* out_capabilities) { |
| base::RunLoop loop; |
| auto quit = loop.QuitClosure(); |
| channel.CreateCommandBuffer( |
| std::move(init_params), routing_id, std::move(shared_state), |
| base::BindLambdaForTesting( |
| [&](ContextResult result, const Capabilities& capabilities) { |
| *out_result = result; |
| *out_capabilities = capabilities; |
| quit.Run(); |
| })); |
| loop.Run(); |
| } |
| |
| void GpuChannelTestCommon::HandleMessage(GpuChannel* channel, |
| IPC::Message* msg) { |
| // Some IPCs (such as GpuCommandBufferMsg_Initialize) will generate more |
| // delayed responses, drop those if they exist. |
| sink_.ClearMessages(); |
| |
| // Needed to appease DCHECKs. |
| msg->set_unblock(false); |
| |
| // Message filter gets message first on IO thread. |
| channel->HandleMessageForTesting(*msg); |
| |
| // Run the HandleMessage task posted to the main thread. |
| task_environment_.RunUntilIdle(); |
| |
| // Replies are sent to the sink. |
| if (msg->is_sync()) { |
| const IPC::Message* reply_msg = sink_.GetMessageAt(0); |
| ASSERT_TRUE(reply_msg); |
| EXPECT_TRUE(!reply_msg->is_reply_error()); |
| |
| EXPECT_TRUE(IPC::SyncMessage::IsMessageReplyTo( |
| *reply_msg, IPC::SyncMessage::GetMessageId(*msg))); |
| |
| IPC::MessageReplyDeserializer* deserializer = |
| static_cast<IPC::SyncMessage*>(msg)->GetReplyDeserializer(); |
| ASSERT_TRUE(deserializer); |
| deserializer->SerializeOutputParameters(*reply_msg); |
| |
| delete deserializer; |
| } |
| |
| sink_.ClearMessages(); |
| |
| delete msg; |
| } |
| |
| base::UnsafeSharedMemoryRegion GpuChannelTestCommon::GetSharedMemoryRegion() { |
| return base::UnsafeSharedMemoryRegion::Create( |
| sizeof(CommandBufferSharedState)); |
| } |
| |
| } // namespace gpu |