blob: 4de3cfc23d9449098b6f6665f977be9fd6c11c27 [file] [log] [blame]
// 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