From f24a1e2b4c8e42794d1636e43bf033f8762410c0 Mon Sep 17 00:00:00 2001 From: "apatrick@chromium.org" Date: Fri, 8 Apr 2011 01:48:48 +0000 Subject: Moved code that runs in both the browser and GPU process from content/gpu to content/common/gpu. Also renamed GpuRenderThread to GpuChannelManager since that is what it really does. The only remaining dependency from content/common/gpu to content/gpu is gpu_watchdog_thread.h. Once that dependency has been reversed it should be possible to move most or all of the code in content/gpu to chrome/gpu. TEST=build, WebGL works, run by trybots. BUG=none Review URL: http://codereview.chromium.org/6793054 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@80883 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/browser/gpu_data_manager.h | 2 +- chrome/browser/gpu_process_host_ui_shim.cc | 18 +- chrome/browser/gpu_process_host_ui_shim.h | 10 +- chrome/chrome_tests.gypi | 6 +- chrome/common/child_process_logging_linux.cc | 4 +- chrome/common/child_process_logging_mac.mm | 4 +- chrome/common/child_process_logging_win.cc | 4 +- chrome/common/chrome_content_gpu_client.h | 2 +- chrome/test/gpu/gpu_pixel_browsertest.cc | 2 +- content/browser/DEPS | 2 - content/browser/gpu_blacklist.cc | 2 +- content/browser/gpu_blacklist_unittest.cc | 2 +- content/common/DEPS | 6 + content/common/gpu/DEPS | 9 + content/common/gpu/OWNERS | 2 + content/common/gpu/content_gpu_client.h | 24 ++ content/common/gpu/gpu_channel.cc | 303 ++++++++++++++ content/common/gpu/gpu_channel.h | 144 +++++++ content/common/gpu/gpu_channel_manager.cc | 147 +++++++ content/common/gpu/gpu_channel_manager.h | 92 +++++ content/common/gpu/gpu_command_buffer_stub.cc | 433 +++++++++++++++++++++ content/common/gpu/gpu_command_buffer_stub.h | 141 +++++++ content/common/gpu/gpu_config.h | 13 + content/common/gpu/gpu_info.cc | 63 +++ content/common/gpu/gpu_info.h | 86 ++++ content/common/gpu/gpu_info_unittest.cc | 26 ++ content/common/gpu/gpu_video_decoder.cc | 427 ++++++++++++++++++++ content/common/gpu/gpu_video_decoder.h | 209 ++++++++++ content/common/gpu/gpu_video_decoder_unittest.cc | 264 +++++++++++++ content/common/gpu/gpu_video_service.cc | 82 ++++ content/common/gpu/gpu_video_service.h | 51 +++ .../gpu/media/fake_gl_video_decode_engine.cc | 132 +++++++ .../common/gpu/media/fake_gl_video_decode_engine.h | 68 ++++ content/common/gpu/media/fake_gl_video_device.cc | 58 +++ content/common/gpu/media/fake_gl_video_device.h | 27 ++ content/common/gpu/media/gpu_video_device.h | 56 +++ content/common/gpu/media/mft_angle_video_device.cc | 52 +++ content/common/gpu/media/mft_angle_video_device.h | 42 ++ content/common/gpu/x_util.cc | 11 + content/common/gpu/x_util.h | 47 +++ content/common/gpu_info.cc | 63 --- content/common/gpu_info.h | 86 ---- content/common/gpu_info_unittest.cc | 26 -- content/common/gpu_messages.h | 2 +- content/content_common.gypi | 47 ++- content/content_gpu.gypi | 33 -- content/gpu/content_gpu_client.h | 24 -- content/gpu/gpu_channel.cc | 302 -------------- content/gpu/gpu_channel.h | 142 ------- content/gpu/gpu_child_thread.cc | 7 +- content/gpu/gpu_child_thread.h | 14 +- content/gpu/gpu_command_buffer_stub.cc | 433 --------------------- content/gpu/gpu_command_buffer_stub.h | 141 ------- content/gpu/gpu_config.h | 13 - content/gpu/gpu_info_collector.h | 2 +- content/gpu/gpu_info_collector_unittest.cc | 2 +- content/gpu/gpu_info_unittest_win.cc | 2 +- content/gpu/gpu_main.cc | 2 +- content/gpu/gpu_render_thread.cc | 148 ------- content/gpu/gpu_render_thread.h | 93 ----- content/gpu/gpu_video_decoder.cc | 427 -------------------- content/gpu/gpu_video_decoder.h | 209 ---------- content/gpu/gpu_video_decoder_unittest.cc | 264 ------------- content/gpu/gpu_video_service.cc | 82 ---- content/gpu/gpu_video_service.h | 51 --- content/gpu/media/fake_gl_video_decode_engine.cc | 132 ------- content/gpu/media/fake_gl_video_decode_engine.h | 68 ---- content/gpu/media/fake_gl_video_device.cc | 58 --- content/gpu/media/fake_gl_video_device.h | 27 -- content/gpu/media/gpu_video_device.h | 56 --- content/gpu/media/mft_angle_video_device.cc | 52 --- content/gpu/media/mft_angle_video_device.h | 42 -- content/gpu/x_util.cc | 11 - content/gpu/x_util.h | 47 --- content/renderer/gpu_channel_host.h | 2 +- 75 files changed, 3105 insertions(+), 3078 deletions(-) create mode 100644 content/common/DEPS create mode 100644 content/common/gpu/DEPS create mode 100644 content/common/gpu/OWNERS create mode 100644 content/common/gpu/content_gpu_client.h create mode 100644 content/common/gpu/gpu_channel.cc create mode 100644 content/common/gpu/gpu_channel.h create mode 100644 content/common/gpu/gpu_channel_manager.cc create mode 100644 content/common/gpu/gpu_channel_manager.h create mode 100644 content/common/gpu/gpu_command_buffer_stub.cc create mode 100644 content/common/gpu/gpu_command_buffer_stub.h create mode 100644 content/common/gpu/gpu_config.h create mode 100644 content/common/gpu/gpu_info.cc create mode 100644 content/common/gpu/gpu_info.h create mode 100644 content/common/gpu/gpu_info_unittest.cc create mode 100644 content/common/gpu/gpu_video_decoder.cc create mode 100644 content/common/gpu/gpu_video_decoder.h create mode 100644 content/common/gpu/gpu_video_decoder_unittest.cc create mode 100644 content/common/gpu/gpu_video_service.cc create mode 100644 content/common/gpu/gpu_video_service.h create mode 100644 content/common/gpu/media/fake_gl_video_decode_engine.cc create mode 100644 content/common/gpu/media/fake_gl_video_decode_engine.h create mode 100644 content/common/gpu/media/fake_gl_video_device.cc create mode 100644 content/common/gpu/media/fake_gl_video_device.h create mode 100644 content/common/gpu/media/gpu_video_device.h create mode 100644 content/common/gpu/media/mft_angle_video_device.cc create mode 100644 content/common/gpu/media/mft_angle_video_device.h create mode 100644 content/common/gpu/x_util.cc create mode 100644 content/common/gpu/x_util.h delete mode 100644 content/common/gpu_info.cc delete mode 100644 content/common/gpu_info.h delete mode 100644 content/common/gpu_info_unittest.cc delete mode 100644 content/gpu/content_gpu_client.h delete mode 100644 content/gpu/gpu_channel.cc delete mode 100644 content/gpu/gpu_channel.h delete mode 100644 content/gpu/gpu_command_buffer_stub.cc delete mode 100644 content/gpu/gpu_command_buffer_stub.h delete mode 100644 content/gpu/gpu_config.h delete mode 100644 content/gpu/gpu_render_thread.cc delete mode 100644 content/gpu/gpu_render_thread.h delete mode 100644 content/gpu/gpu_video_decoder.cc delete mode 100644 content/gpu/gpu_video_decoder.h delete mode 100644 content/gpu/gpu_video_decoder_unittest.cc delete mode 100644 content/gpu/gpu_video_service.cc delete mode 100644 content/gpu/gpu_video_service.h delete mode 100644 content/gpu/media/fake_gl_video_decode_engine.cc delete mode 100644 content/gpu/media/fake_gl_video_decode_engine.h delete mode 100644 content/gpu/media/fake_gl_video_device.cc delete mode 100644 content/gpu/media/fake_gl_video_device.h delete mode 100644 content/gpu/media/gpu_video_device.h delete mode 100644 content/gpu/media/mft_angle_video_device.cc delete mode 100644 content/gpu/media/mft_angle_video_device.h delete mode 100644 content/gpu/x_util.cc delete mode 100644 content/gpu/x_util.h diff --git a/chrome/browser/gpu_data_manager.h b/chrome/browser/gpu_data_manager.h index ade4279..f131b07 100644 --- a/chrome/browser/gpu_data_manager.h +++ b/chrome/browser/gpu_data_manager.h @@ -14,8 +14,8 @@ #include "base/memory/singleton.h" #include "base/values.h" #include "chrome/browser/web_resource/gpu_blacklist_updater.h" +#include "content/common/gpu/gpu_info.h" #include "content/common/gpu_feature_flags.h" -#include "content/common/gpu_info.h" class CommandLine; class DictionaryValue; diff --git a/chrome/browser/gpu_process_host_ui_shim.cc b/chrome/browser/gpu_process_host_ui_shim.cc index 68cb20b..73be07d 100644 --- a/chrome/browser/gpu_process_host_ui_shim.cc +++ b/chrome/browser/gpu_process_host_ui_shim.cc @@ -70,7 +70,7 @@ class UIThreadSender : public IPC::Channel::Sender { DCHECK(!msg->is_sync()); #endif - // When the GpuRenderThread sends an IPC, post it to the UI thread without + // When the GpuChannelManager sends an IPC, post it to the UI thread without // using IPC. bool success = BrowserThread::PostTask( BrowserThread::UI, @@ -82,9 +82,9 @@ class UIThreadSender : public IPC::Channel::Sender { } }; -void ForwardMessageToGpuThread(GpuRenderThread* render_thread, +void ForwardMessageToGpuThread(GpuChannelManager* gpu_channel_manager, IPC::Message* msg) { - bool success = render_thread->OnMessageReceived(*msg); + bool success = gpu_channel_manager->OnMessageReceived(*msg); // If the message was not handled, it is likely it was intended for the // GpuChildThread, which does not exist in single process and in process GPU @@ -163,7 +163,7 @@ GpuProcessHostUIShim::GpuProcessHostUIShim(int host_id, content::CauseForGpuLaunch cause_for_gpu_launch) : host_id_(host_id), gpu_process_(base::kNullProcessHandle), - gpu_render_thread_(NULL), + gpu_channel_manager_(NULL), ui_thread_sender_(NULL) { g_hosts_by_id.AddWithID(this, host_id_); gpu_data_manager_ = GpuDataManager::GetInstance(); @@ -172,7 +172,7 @@ GpuProcessHostUIShim::GpuProcessHostUIShim(int host_id, if (host_id == 0) { gpu_process_ = base::GetCurrentProcessHandle(); ui_thread_sender_ = new UIThreadSender; - gpu_render_thread_ = new GpuRenderThread( + gpu_channel_manager_ = new GpuChannelManager( ui_thread_sender_, NULL, g_browser_process->io_thread()->message_loop(), @@ -278,7 +278,7 @@ bool GpuProcessHostUIShim::Send(IPC::Message* msg) { BrowserThread::GPU, FROM_HERE, NewRunnableFunction(ForwardMessageToGpuThread, - gpu_render_thread_, + gpu_channel_manager_, msg)); } else { success = BrowserThread::PostTask( @@ -488,11 +488,11 @@ GpuProcessHostUIShim::~GpuProcessHostUIShim() { #endif // Ensure these are destroyed on the GPU thread. - if (gpu_render_thread_) { + if (gpu_channel_manager_) { BrowserThread::DeleteSoon(BrowserThread::GPU, FROM_HERE, - gpu_render_thread_); - gpu_render_thread_ = NULL; + gpu_channel_manager_); + gpu_channel_manager_ = NULL; } if (ui_thread_sender_) { BrowserThread::DeleteSoon(BrowserThread::GPU, diff --git a/chrome/browser/gpu_process_host_ui_shim.h b/chrome/browser/gpu_process_host_ui_shim.h index f9fafa5..8bcdb23 100644 --- a/chrome/browser/gpu_process_host_ui_shim.h +++ b/chrome/browser/gpu_process_host_ui_shim.h @@ -21,11 +21,11 @@ #include "base/memory/singleton.h" #include "base/process.h" #include "base/threading/non_thread_safe.h" +#include "content/common/gpu/gpu_channel_manager.h" +#include "content/common/gpu/gpu_info.h" #include "content/common/gpu_feature_flags.h" -#include "content/common/gpu_info.h" #include "content/common/gpu_process_launch_causes.h" #include "content/common/message_router.h" -#include "content/gpu/gpu_render_thread.h" #include "ui/gfx/native_widget_types.h" namespace gfx { @@ -209,9 +209,9 @@ class GpuProcessHostUIShim ViewSurfaceMap acquired_surfaces_; // In single process and in process GPU mode, this references the - // GpuRenderThread or null otherwise. It must be called and deleted on the GPU - // thread. - GpuRenderThread* gpu_render_thread_; + // GpuChannelManager or null otherwise. It must be called and deleted on the + // GPU thread. + GpuChannelManager* gpu_channel_manager_; // This is likewise single process / in process GPU specific. This is a Sender // implementation that forwards IPC messages to this UI shim on the UI thread. diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 57b70c0..b85962e 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1886,7 +1886,7 @@ '../content/browser/webui/web_ui_unittest.cc', '../content/common/font_descriptor_mac_unittest.mm', '../content/common/gpu_feature_flags_unittest.cc', - '../content/common/gpu_info_unittest.cc', + '../content/common/gpu/gpu_info_unittest.cc', '../content/common/mru_cache_unittest.cc', '../content/common/notification_service_unittest.cc', '../content/common/process_watcher_unittest.cc', @@ -1900,8 +1900,8 @@ '../content/gpu/gpu_idirect3d9_mock_win.cc', '../content/gpu/gpu_idirect3d9_mock_win.h', '../content/gpu/gpu_info_collector_unittest.cc', - '../content/gpu/gpu_info_unittest_win.cc', - '../content/gpu/gpu_video_decoder_unittest.cc', + '../content/common/gpu/gpu_info_unittest_win.cc', + '../content/common/gpu/gpu_video_decoder_unittest.cc', '../content/renderer/active_notification_tracker_unittest.cc', '../content/renderer/audio_message_filter_unittest.cc', '../content/renderer/gpu_video_decoder_host_unittest.cc', diff --git a/chrome/common/child_process_logging_linux.cc b/chrome/common/child_process_logging_linux.cc index f15536e..a730761 100644 --- a/chrome/common/child_process_logging_linux.cc +++ b/chrome/common/child_process_logging_linux.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -8,7 +8,7 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "chrome/installer/util/google_update_settings.h" -#include "content/common/gpu_info.h" +#include "content/common/gpu/gpu_info.h" #include "googleurl/src/gurl.h" namespace child_process_logging { diff --git a/chrome/common/child_process_logging_mac.mm b/chrome/common/child_process_logging_mac.mm index 0a13af0..ab3d021 100644 --- a/chrome/common/child_process_logging_mac.mm +++ b/chrome/common/child_process_logging_mac.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -11,7 +11,7 @@ #include "base/stringprintf.h" #include "base/utf_string_conversions.h" #include "chrome/installer/util/google_update_settings.h" -#include "content/common/gpu_info.h" +#include "content/common/gpu/gpu_info.h" #include "googleurl/src/gurl.h" namespace child_process_logging { diff --git a/chrome/common/child_process_logging_win.cc b/chrome/common/child_process_logging_win.cc index 6f9650c..3a937f8 100644 --- a/chrome/common/child_process_logging_win.cc +++ b/chrome/common/child_process_logging_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -12,7 +12,7 @@ #include "base/utf_string_conversions.h" #include "chrome/common/chrome_constants.h" #include "chrome/installer/util/google_update_settings.h" -#include "content/common/gpu_info.h" +#include "content/common/gpu/gpu_info.h" #include "googleurl/src/gurl.h" namespace child_process_logging { diff --git a/chrome/common/chrome_content_gpu_client.h b/chrome/common/chrome_content_gpu_client.h index ad97188..53b3cdf 100644 --- a/chrome/common/chrome_content_gpu_client.h +++ b/chrome/common/chrome_content_gpu_client.h @@ -6,7 +6,7 @@ #define CHROME_COMMON_CHROME_CONTENT_GPU_CLIENT_H_ #pragma once -#include "content/gpu/content_gpu_client.h" +#include "content/common/gpu/content_gpu_client.h" namespace chrome { diff --git a/chrome/test/gpu/gpu_pixel_browsertest.cc b/chrome/test/gpu/gpu_pixel_browsertest.cc index 862d0ba..ae71982 100644 --- a/chrome/test/gpu/gpu_pixel_browsertest.cc +++ b/chrome/test/gpu/gpu_pixel_browsertest.cc @@ -23,7 +23,7 @@ #include "content/browser/gpu_process_host.h" #include "content/browser/renderer_host/render_view_host.h" #include "content/browser/tab_contents/tab_contents.h" -#include "content/common/gpu_info.h" +#include "content/common/gpu/gpu_info.h" #include "googleurl/src/gurl.h" #include "net/base/net_util.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/content/browser/DEPS b/content/browser/DEPS index eb0e8c0..f333397 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS @@ -2,7 +2,5 @@ include_rules = [ # The following directories have been refactored, so no new dependencies # should be added from these directories. "-chrome/browser/extensions", - - "+content/gpu", # For single-process mode. ] diff --git a/content/browser/gpu_blacklist.cc b/content/browser/gpu_blacklist.cc index ee83df3..50486c9 100644 --- a/content/browser/gpu_blacklist.cc +++ b/content/browser/gpu_blacklist.cc @@ -14,7 +14,7 @@ #include "base/sys_info.h" #include "base/values.h" #include "base/version.h" -#include "content/common/gpu_info.h" +#include "content/common/gpu/gpu_info.h" namespace { diff --git a/content/browser/gpu_blacklist_unittest.cc b/content/browser/gpu_blacklist_unittest.cc index ebcf6ba6..79cc0ac 100644 --- a/content/browser/gpu_blacklist_unittest.cc +++ b/content/browser/gpu_blacklist_unittest.cc @@ -11,7 +11,7 @@ #include "base/path_service.h" #include "base/version.h" #include "content/browser/gpu_blacklist.h" -#include "content/common/gpu_info.h" +#include "content/common/gpu/gpu_info.h" #include "testing/gtest/include/gtest/gtest.h" class GpuBlacklistTest : public testing::Test { diff --git a/content/common/DEPS b/content/common/DEPS new file mode 100644 index 0000000..fd53eb5 --- /dev/null +++ b/content/common/DEPS @@ -0,0 +1,6 @@ +include_rules = [ + # Don't add any more dependencies on this directory. Refactoring out the + # remaining dependency on gpu_watchdog_thread.h is underway. + "+content/gpu", +] + diff --git a/content/common/gpu/DEPS b/content/common/gpu/DEPS new file mode 100644 index 0000000..274c1ef --- /dev/null +++ b/content/common/gpu/DEPS @@ -0,0 +1,9 @@ +include_rules = [ + "+chrome/app", + "+gpu/command_buffer", + "+libEGL", + "+libGLESv2", + "+media/base", + "+media/video", + "+skia", +] diff --git a/content/common/gpu/OWNERS b/content/common/gpu/OWNERS new file mode 100644 index 0000000..d73ca87 --- /dev/null +++ b/content/common/gpu/OWNERS @@ -0,0 +1,2 @@ +apatrick@chromium.org +kbr@chromium.org diff --git a/content/common/gpu/content_gpu_client.h b/content/common/gpu/content_gpu_client.h new file mode 100644 index 0000000..3df4de2 --- /dev/null +++ b/content/common/gpu/content_gpu_client.h @@ -0,0 +1,24 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_COMMON_GPU_CONTENT_GPU_CLIENT_H_ +#define CONTENT_COMMON_GPU_CONTENT_GPU_CLIENT_H_ +#pragma once + +#include "content/common/content_client.h" + +struct GPUInfo; + +namespace content { + +// Embedder API for participating in plugin logic. +class ContentGpuClient { + public: + // Sets the data on the gpu to send along with crash reports. + virtual void SetGpuInfo(const GPUInfo& gpu_info) {} +}; + +} // namespace content + +#endif // CONTENT_COMMON_GPU_CONTENT_GPU_CLIENT_H_ diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc new file mode 100644 index 0000000..8df65cd --- /dev/null +++ b/content/common/gpu/gpu_channel.cc @@ -0,0 +1,303 @@ +// Copyright (c) 2011 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. + +#if defined(OS_WIN) +#include +#endif + +#include "content/common/gpu/gpu_channel.h" + +#include "base/command_line.h" +#include "base/process_util.h" +#include "base/string_util.h" +#include "content/common/child_process.h" +#include "content/common/content_client.h" +#include "content/common/content_switches.h" +#include "content/common/gpu_messages.h" +#include "content/common/gpu/gpu_channel_manager.h" +#include "content/common/gpu/gpu_video_service.h" +#include "content/gpu/transport_texture.h" + +#if defined(OS_POSIX) +#include "ipc/ipc_channel_posix.h" +#endif + +GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, + GpuWatchdogThread* gpu_watchdog_thread, + int renderer_id) + : gpu_channel_manager_(gpu_channel_manager), + renderer_id_(renderer_id), + renderer_process_(base::kNullProcessHandle), + renderer_pid_(base::kNullProcessId), + watchdog_thread_(gpu_watchdog_thread) { + DCHECK(gpu_channel_manager); + DCHECK(renderer_id); + const CommandLine* command_line = CommandLine::ForCurrentProcess(); + log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); + disallowed_extensions_.multisampling = + command_line->HasSwitch(switches::kDisableGLMultisampling); +} + +GpuChannel::~GpuChannel() { +#if defined(OS_WIN) + if (renderer_process_) + CloseHandle(renderer_process_); +#endif +} + +TransportTexture* GpuChannel::GetTransportTexture(int32 route_id) { + return transport_textures_.Lookup(route_id); +} + +void GpuChannel::DestroyTransportTexture(int32 route_id) { + transport_textures_.Remove(route_id); + router_.RemoveRoute(route_id); +} + +bool GpuChannel::OnMessageReceived(const IPC::Message& message) { + if (log_messages_) { + VLOG(1) << "received message @" << &message << " on channel @" << this + << " with type " << message.type(); + } + + if (message.routing_id() == MSG_ROUTING_CONTROL) + return OnControlMessageReceived(message); + + if (!router_.RouteMessage(message)) { + // Respond to sync messages even if router failed to route. + if (message.is_sync()) { + IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); + reply->set_reply_error(); + Send(reply); + } + return false; + } + + return true; +} + +void GpuChannel::OnChannelError() { + gpu_channel_manager_->RemoveChannel(renderer_id_); +} + +void GpuChannel::OnChannelConnected(int32 peer_pid) { + renderer_pid_ = peer_pid; +} + +bool GpuChannel::Send(IPC::Message* message) { + if (log_messages_) { + VLOG(1) << "sending message @" << message << " on channel @" << this + << " with type " << message->type(); + } + + if (!channel_.get()) { + delete message; + return false; + } + + return channel_->Send(message); +} + +void GpuChannel::CreateViewCommandBuffer( + gfx::PluginWindowHandle window, + int32 render_view_id, + const GPUCreateCommandBufferConfig& init_params, + int32* route_id) { + *route_id = MSG_ROUTING_NONE; + content::GetContentClient()->SetActiveURL(init_params.active_url); + +#if defined(ENABLE_GPU) + *route_id = GenerateRouteID(); + scoped_ptr stub(new GpuCommandBufferStub( + this, window, NULL, gfx::Size(), disallowed_extensions_, + init_params.allowed_extensions, + init_params.attribs, 0, *route_id, renderer_id_, render_view_id, + watchdog_thread_)); + router_.AddRoute(*route_id, stub.get()); + stubs_.AddWithID(stub.release(), *route_id); +#endif // ENABLE_GPU +} + +#if defined(OS_MACOSX) +void GpuChannel::AcceleratedSurfaceBuffersSwapped( + int32 route_id, uint64 swap_buffers_count) { + GpuCommandBufferStub* stub = stubs_.Lookup(route_id); + if (stub == NULL) + return; + stub->AcceleratedSurfaceBuffersSwapped(swap_buffers_count); +} + +void GpuChannel::DestroyCommandBufferByViewId(int32 render_view_id) { + // This responds to a message from the browser process to destroy the command + // buffer when the window with a GPUProcessor is closed (see + // RenderWidgetHostViewMac::DeallocFakePluginWindowHandle). Find the route id + // that matches the given render_view_id and delete the route. + for (StubMap::const_iterator iter(&stubs_); !iter.IsAtEnd(); iter.Advance()) { + if (iter.GetCurrentValue()->render_view_id() == render_view_id) { + OnDestroyCommandBuffer(iter.GetCurrentKey()); + return; + } + } +} +#endif + +bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg) + IPC_MESSAGE_HANDLER(GpuChannelMsg_Initialize, OnInitialize) + IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateOffscreenCommandBuffer, + OnCreateOffscreenCommandBuffer) + IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyCommandBuffer, + OnDestroyCommandBuffer) + IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateVideoDecoder, + OnCreateVideoDecoder) + IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyVideoDecoder, + OnDestroyVideoDecoder) + IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateTransportTexture, + OnCreateTransportTexture) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + DCHECK(handled); + return handled; +} + +int GpuChannel::GenerateRouteID() { + static int last_id = 0; + return ++last_id; +} + +void GpuChannel::OnInitialize(base::ProcessHandle renderer_process) { + // Initialize should only happen once. + DCHECK(!renderer_process_); + + // Verify that the renderer has passed its own process handle. + if (base::GetProcId(renderer_process) == renderer_pid_) + renderer_process_ = renderer_process; +} + +void GpuChannel::OnCreateOffscreenCommandBuffer( + int32 parent_route_id, + const gfx::Size& size, + const GPUCreateCommandBufferConfig& init_params, + uint32 parent_texture_id, + int32* route_id) { + content::GetContentClient()->SetActiveURL(init_params.active_url); +#if defined(ENABLE_GPU) + *route_id = GenerateRouteID(); + GpuCommandBufferStub* parent_stub = NULL; + if (parent_route_id != 0) + parent_stub = stubs_.Lookup(parent_route_id); + + scoped_ptr stub(new GpuCommandBufferStub( + this, + gfx::kNullPluginWindow, + parent_stub, + size, + disallowed_extensions_, + init_params.allowed_extensions, + init_params.attribs, + parent_texture_id, + *route_id, + 0, 0, watchdog_thread_)); + router_.AddRoute(*route_id, stub.get()); + stubs_.AddWithID(stub.release(), *route_id); +#else + *route_id = MSG_ROUTING_NONE; +#endif +} + +void GpuChannel::OnDestroyCommandBuffer(int32 route_id) { +#if defined(ENABLE_GPU) + if (router_.ResolveRoute(route_id)) { + router_.RemoveRoute(route_id); + stubs_.Remove(route_id); + } +#endif +} + +void GpuChannel::OnCreateVideoDecoder(int32 context_route_id, + int32 decoder_host_id) { +// TODO(cevans): do NOT re-enable this until GpuVideoService has been checked +// for integer overflows, including the classic "width * height" overflow. +#if 0 + VLOG(1) << "GpuChannel::OnCreateVideoDecoder"; + GpuVideoService* service = GpuVideoService::GetInstance(); + if (service == NULL) { + // TODO(hclam): Need to send a failure message. + return; + } + + // The context ID corresponds to the command buffer used. + GpuCommandBufferStub* stub = stubs_.Lookup(context_route_id); + int32 decoder_id = GenerateRouteID(); + + // TODO(hclam): Need to be careful about the lifetime of the command buffer + // decoder. + bool ret = service->CreateVideoDecoder( + this, &router_, decoder_host_id, decoder_id, + stub->processor()->decoder()); + DCHECK(ret) << "Failed to create a GpuVideoDecoder"; +#endif +} + +void GpuChannel::OnDestroyVideoDecoder(int32 decoder_id) { +#if defined(ENABLE_GPU) + LOG(ERROR) << "GpuChannel::OnDestroyVideoDecoder"; + GpuVideoService* service = GpuVideoService::GetInstance(); + if (service == NULL) + return; + service->DestroyVideoDecoder(&router_, decoder_id); +#endif +} + +void GpuChannel::OnCreateTransportTexture(int32 context_route_id, + int32 host_id) { + #if defined(ENABLE_GPU) + GpuCommandBufferStub* stub = stubs_.Lookup(context_route_id); + int32 route_id = GenerateRouteID(); + + scoped_ptr transport( + new TransportTexture(this, channel_.get(), stub->processor()->decoder(), + host_id, route_id)); + router_.AddRoute(route_id, transport.get()); + transport_textures_.AddWithID(transport.release(), route_id); + + IPC::Message* msg = new GpuTransportTextureHostMsg_TransportTextureCreated( + host_id, route_id); + Send(msg); + #endif + } + +bool GpuChannel::Init(MessageLoop* io_message_loop, + base::WaitableEvent* shutdown_event) { + // Check whether we're already initialized. + if (channel_.get()) + return true; + + // Map renderer ID to a (single) channel to that process. + std::string channel_name = GetChannelName(); + channel_.reset(new IPC::SyncChannel( + channel_name, + IPC::Channel::MODE_SERVER, + this, + io_message_loop, + false, + shutdown_event)); + + return true; +} + +std::string GpuChannel::GetChannelName() { + return StringPrintf("%d.r%d.gpu", base::GetCurrentProcId(), renderer_id_); +} + +#if defined(OS_POSIX) +int GpuChannel::GetRendererFileDescriptor() { + int fd = -1; + if (channel_.get()) { + fd = channel_->GetClientFileDescriptor(); + } + return fd; +} +#endif // defined(OS_POSIX) diff --git a/content/common/gpu/gpu_channel.h b/content/common/gpu/gpu_channel.h new file mode 100644 index 0000000..ccce837 --- /dev/null +++ b/content/common/gpu/gpu_channel.h @@ -0,0 +1,144 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_COMMON_GPU_GPU_CHANNEL_H_ +#define CONTENT_COMMON_GPU_GPU_CHANNEL_H_ +#pragma once + +#include +#include +#include + +#include "base/id_map.h" +#include "base/memory/scoped_ptr.h" +#include "base/process.h" +#include "build/build_config.h" +#include "content/common/gpu/gpu_command_buffer_stub.h" +#include "content/common/message_router.h" +#include "ipc/ipc_sync_channel.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gfx/size.h" + +class GpuChannelManager; +class GpuWatchdogThread; +struct GPUCreateCommandBufferConfig; +class MessageLoop; +class TransportTexture; + +namespace base { +class WaitableEvent; +} + +// Encapsulates an IPC channel between the GPU process and one renderer +// process. On the renderer side there's a corresponding GpuChannelHost. +class GpuChannel : public IPC::Channel::Listener, + public IPC::Message::Sender, + public base::RefCountedThreadSafe { + public: + // Takes ownership of the renderer process handle. + GpuChannel(GpuChannelManager* gpu_channel_manager, + GpuWatchdogThread* gpu_watchdog_thread, + int renderer_id); + virtual ~GpuChannel(); + + bool Init(MessageLoop* io_message_loop, base::WaitableEvent* shutdown_event); + + // Get the GpuChannelManager that owns this channel. + GpuChannelManager* gpu_channel_manager() const { + return gpu_channel_manager_; + } + + // Returns the name of the associated IPC channel. + std::string GetChannelName(); + +#if defined(OS_POSIX) + int GetRendererFileDescriptor(); +#endif // defined(OS_POSIX) + + base::ProcessHandle renderer_process() const { + return renderer_process_; + } + + // IPC::Channel::Listener implementation: + virtual bool OnMessageReceived(const IPC::Message& msg); + virtual void OnChannelError(); + virtual void OnChannelConnected(int32 peer_pid); + + // IPC::Message::Sender implementation: + virtual bool Send(IPC::Message* msg); + + void CreateViewCommandBuffer( + gfx::PluginWindowHandle window, + int32 render_view_id, + const GPUCreateCommandBufferConfig& init_params, + int32* route_id); + +#if defined(OS_MACOSX) + virtual void AcceleratedSurfaceBuffersSwapped( + int32 route_id, uint64 swap_buffers_count); + void DestroyCommandBufferByViewId(int32 render_view_id); +#endif + // Get the TransportTexture by ID. + TransportTexture* GetTransportTexture(int32 route_id); + + // Destroy the TransportTexture by ID. This method is only called by + // TransportTexture to delete and detach itself. + void DestroyTransportTexture(int32 route_id); + + private: + bool OnControlMessageReceived(const IPC::Message& msg); + + int GenerateRouteID(); + + // Message handlers. + void OnInitialize(base::ProcessHandle renderer_process); + void OnCreateOffscreenCommandBuffer( + int32 parent_route_id, + const gfx::Size& size, + const GPUCreateCommandBufferConfig& init_params, + uint32 parent_texture_id, + int32* route_id); + void OnDestroyCommandBuffer(int32 route_id); + + void OnCreateVideoDecoder(int32 context_route_id, + int32 decoder_host_id); + void OnDestroyVideoDecoder(int32 decoder_id); + void OnCreateTransportTexture(int32 context_route_id, int32 host_id); + + // The lifetime of objects of this class is managed by a GpuChannelManager. + // The GpuChannelManager destroy all the GpuChannels that they own when they + // are destroyed. So a raw pointer is safe. + GpuChannelManager* gpu_channel_manager_; + + scoped_ptr channel_; + + // The id of the renderer who is on the other side of the channel. + int renderer_id_; + + // Handle to the renderer process that is on the other side of the channel. + base::ProcessHandle renderer_process_; + + // The process id of the renderer process. + base::ProcessId renderer_pid_; + + // Used to implement message routing functionality to CommandBuffer objects + MessageRouter router_; + +#if defined(ENABLE_GPU) + typedef IDMap StubMap; + StubMap stubs_; +#endif // defined (ENABLE_GPU) + + // A collection of transport textures created. + typedef IDMap TransportTextureMap; + TransportTextureMap transport_textures_; + + bool log_messages_; // True if we should log sent and received messages. + gpu::gles2::DisallowedExtensions disallowed_extensions_; + GpuWatchdogThread* watchdog_thread_; + + DISALLOW_COPY_AND_ASSIGN(GpuChannel); +}; + +#endif // CONTENT_COMMON_GPU_GPU_CHANNEL_H_ diff --git a/content/common/gpu/gpu_channel_manager.cc b/content/common/gpu/gpu_channel_manager.cc new file mode 100644 index 0000000..af2c188 --- /dev/null +++ b/content/common/gpu/gpu_channel_manager.cc @@ -0,0 +1,147 @@ +// Copyright (c) 2011 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 "content/common/gpu/gpu_channel_manager.h" + +#include +#include + +#include "app/win/scoped_com_initializer.h" +#include "base/command_line.h" +#include "base/threading/worker_pool.h" +#include "build/build_config.h" +#include "chrome/common/child_process_logging.h" +#include "chrome/common/chrome_switches.h" +#include "content/common/child_process.h" +#include "content/common/gpu_messages.h" +#include "content/gpu/gpu_watchdog_thread.h" +#include "ipc/ipc_channel_handle.h" +#include "ui/gfx/gl/gl_context.h" +#include "ui/gfx/gl/gl_implementation.h" + +GpuChannelManager::GpuChannelManager(IPC::Message::Sender* browser_channel, + GpuWatchdogThread* gpu_watchdog_thread, + MessageLoop* io_message_loop, + base::WaitableEvent* shutdown_event) + : io_message_loop_(io_message_loop), + shutdown_event_(shutdown_event), + browser_channel_(browser_channel), + watchdog_thread_(gpu_watchdog_thread) { + DCHECK(browser_channel); + DCHECK(io_message_loop); + DCHECK(shutdown_event); +} + +GpuChannelManager::~GpuChannelManager() { + gpu_channels_.clear(); +} + +void GpuChannelManager::RemoveChannel(int renderer_id) { + gpu_channels_.erase(renderer_id); +} + +bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) { + bool msg_is_ok = true; + bool handled = true; + IPC_BEGIN_MESSAGE_MAP_EX(GpuChannelManager, msg, msg_is_ok) + IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel) + IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel) + IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer, + OnCreateViewCommandBuffer); + IPC_MESSAGE_HANDLER(GpuMsg_Synchronize, OnSynchronize) +#if defined(OS_MACOSX) + IPC_MESSAGE_HANDLER(GpuMsg_AcceleratedSurfaceBuffersSwappedACK, + OnAcceleratedSurfaceBuffersSwappedACK) + IPC_MESSAGE_HANDLER(GpuMsg_DestroyCommandBuffer, + OnDestroyCommandBuffer) +#endif + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP_EX() + return handled; +} + +bool GpuChannelManager::Send(IPC::Message* msg) { + return browser_channel_->Send(msg); +} + +void GpuChannelManager::OnEstablishChannel(int renderer_id) { + scoped_refptr channel; + IPC::ChannelHandle channel_handle; + GPUInfo gpu_info; + + GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); + if (iter == gpu_channels_.end()) + channel = new GpuChannel(this, watchdog_thread_, renderer_id); + else + channel = iter->second; + + DCHECK(channel != NULL); + + if (channel->Init(io_message_loop_, shutdown_event_)) + gpu_channels_[renderer_id] = channel; + else + channel = NULL; + + if (channel.get()) { + channel_handle.name = channel->GetChannelName(); +#if defined(OS_POSIX) + // On POSIX, pass the renderer-side FD. Also mark it as auto-close so + // that it gets closed after it has been sent. + int renderer_fd = channel->GetRendererFileDescriptor(); + channel_handle.socket = base::FileDescriptor(dup(renderer_fd), true); +#endif + } + + Send(new GpuHostMsg_ChannelEstablished(channel_handle)); +} + +void GpuChannelManager::OnCloseChannel( + const IPC::ChannelHandle& channel_handle) { + for (GpuChannelMap::iterator iter = gpu_channels_.begin(); + iter != gpu_channels_.end(); ++iter) { + if (iter->second->GetChannelName() == channel_handle.name) { + gpu_channels_.erase(iter); + return; + } + } +} + +void GpuChannelManager::OnSynchronize() { + Send(new GpuHostMsg_SynchronizeReply()); +} + +void GpuChannelManager::OnCreateViewCommandBuffer( + gfx::PluginWindowHandle window, + int32 render_view_id, + int32 renderer_id, + const GPUCreateCommandBufferConfig& init_params) { + int32 route_id = MSG_ROUTING_NONE; + + GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); + if (iter != gpu_channels_.end()) { + iter->second->CreateViewCommandBuffer( + window, render_view_id, init_params, &route_id); + } + + Send(new GpuHostMsg_CommandBufferCreated(route_id)); +} + +#if defined(OS_MACOSX) +void GpuChannelManager::OnAcceleratedSurfaceBuffersSwappedACK( + int renderer_id, int32 route_id, uint64 swap_buffers_count) { + GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); + if (iter == gpu_channels_.end()) + return; + scoped_refptr channel = iter->second; + channel->AcceleratedSurfaceBuffersSwapped(route_id, swap_buffers_count); +} +void GpuChannelManager::OnDestroyCommandBuffer( + int renderer_id, int32 renderer_view_id) { + GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); + if (iter == gpu_channels_.end()) + return; + scoped_refptr channel = iter->second; + channel->DestroyCommandBufferByViewId(renderer_view_id); +} +#endif diff --git a/content/common/gpu/gpu_channel_manager.h b/content/common/gpu/gpu_channel_manager.h new file mode 100644 index 0000000..b32136f --- /dev/null +++ b/content/common/gpu/gpu_channel_manager.h @@ -0,0 +1,92 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_GPU_GPU_CHANNEL_MANAGER_H_ +#define CONTENT_GPU_GPU_CHANNEL_MANAGER_H_ +#pragma once + +#include + +#include "base/basictypes.h" +#include "base/hash_tables.h" +#include "base/command_line.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/time.h" +#include "build/build_config.h" +#include "content/common/child_thread.h" +#include "content/common/gpu/gpu_channel.h" +#include "content/common/gpu/gpu_config.h" +#include "content/common/gpu/x_util.h" +#include "ipc/ipc_channel.h" +#include "ipc/ipc_message.h" +#include "ui/gfx/native_widget_types.h" + +namespace IPC { +struct ChannelHandle; +} + +// A GpuChannelManager is a thread responsible for issuing rendering commands +// managing the lifetimes of GPU channels and forwarding IPC requests from the +// browser process to them based on the corresponding renderer ID. +// +// A GpuChannelManager can also be hosted in the browser process in single +// process or in-process GPU modes. In this case there is no corresponding +// GpuChildThread and this is the reason the GpuChildThread is referenced via +// a pointer to IPC::Message::Sender, which can be implemented by other hosts +// to send IPC messages to the browser process IO thread on the +// GpuChannelManager's behalf. +class GpuChannelManager : public IPC::Channel::Listener, + public IPC::Message::Sender { + public: + GpuChannelManager(IPC::Message::Sender* browser_channel, + GpuWatchdogThread* gpu_watchdog_thread, + MessageLoop* io_message_loop, + base::WaitableEvent* shutdown_event); + ~GpuChannelManager(); + + // Remove the channel for a particular renderer. + void RemoveChannel(int renderer_id); + + // Listener overrides. + virtual bool OnMessageReceived(const IPC::Message& msg); + + // Sender overrides. + virtual bool Send(IPC::Message* msg); + + private: + // Message handlers. + void OnEstablishChannel(int renderer_id); + void OnCloseChannel(const IPC::ChannelHandle& channel_handle); + void OnSynchronize(); + void OnCreateViewCommandBuffer( + gfx::PluginWindowHandle window, + int32 render_view_id, + int32 renderer_id, + const GPUCreateCommandBufferConfig& init_params); +#if defined(OS_MACOSX) + void OnAcceleratedSurfaceBuffersSwappedACK( + int renderer_id, int32 route_id, uint64 swap_buffers_count); + void OnDestroyCommandBuffer(int renderer_id, int32 renderer_view_id); +#endif + + MessageLoop* io_message_loop_; + base::WaitableEvent* shutdown_event_; + + // Either an IPC channel to the browser or, if the GpuChannelManager is + // running in the browser process, a Sender implementation that will post + // IPC messages to the UI thread. + IPC::Message::Sender* browser_channel_; + + // These objects manage channels to individual renderer processes there is + // one channel for each renderer process that has connected to this GPU + // process. + typedef base::hash_map > GpuChannelMap; + GpuChannelMap gpu_channels_; + GpuWatchdogThread* watchdog_thread_; + + DISALLOW_COPY_AND_ASSIGN(GpuChannelManager); +}; + +#endif // CONTENT_GPU_GPU_CHANNEL_MANAGER_H_ diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc new file mode 100644 index 0000000..e237dd1 --- /dev/null +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -0,0 +1,433 @@ +// Copyright (c) 2011 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. + +#if defined(ENABLE_GPU) + +#include "base/process_util.h" +#include "base/shared_memory.h" +#include "build/build_config.h" +#include "content/common/child_thread.h" +#include "content/common/gpu_messages.h" +#include "content/common/gpu/gpu_channel.h" +#include "content/common/gpu/gpu_channel_manager.h" +#include "content/common/gpu/gpu_command_buffer_stub.h" +#include "content/gpu/gpu_watchdog_thread.h" +#include "gpu/common/gpu_trace_event.h" + +#if defined(OS_WIN) +#include "base/win/wrapped_window_proc.h" +#endif + +using gpu::Buffer; + +#if defined(OS_WIN) +#define kCompositorWindowOwner L"CompositorWindowOwner" +#endif // defined(OS_WIN) + +GpuCommandBufferStub::GpuCommandBufferStub( + GpuChannel* channel, + gfx::PluginWindowHandle handle, + GpuCommandBufferStub* parent, + const gfx::Size& size, + const gpu::gles2::DisallowedExtensions& disallowed_extensions, + const std::string& allowed_extensions, + const std::vector& attribs, + uint32 parent_texture_id, + int32 route_id, + int32 renderer_id, + int32 render_view_id, + GpuWatchdogThread* gpu_watchdog_thread) + : channel_(channel), + handle_(handle), + parent_( + parent ? parent->AsWeakPtr() : base::WeakPtr()), + initial_size_(size), + disallowed_extensions_(disallowed_extensions), + allowed_extensions_(allowed_extensions), + requested_attribs_(attribs), + parent_texture_id_(parent_texture_id), + route_id_(route_id), +#if defined(OS_WIN) + compositor_window_(NULL), +#endif // defined(OS_WIN) + renderer_id_(renderer_id), + render_view_id_(render_view_id), + watchdog_thread_(gpu_watchdog_thread) { +} + +#if defined(OS_WIN) +static LRESULT CALLBACK CompositorWindowProc( + HWND hwnd, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + case WM_ERASEBKGND: + return 0; + case WM_DESTROY: + RemoveProp(hwnd, kCompositorWindowOwner); + return 0; + case WM_PAINT: { + PAINTSTRUCT paint; + HDC dc = BeginPaint(hwnd, &paint); + if (dc) { + HANDLE h = GetProp(hwnd, kCompositorWindowOwner); + if (h) { + GpuCommandBufferStub* stub = + reinterpret_cast(h); + stub->OnCompositorWindowPainted(); + } + EndPaint(hwnd, &paint); + } + break; + } + default: + return DefWindowProc(hwnd, message, wparam, lparam); + } + return 0; +} + +bool GpuCommandBufferStub::CreateCompositorWindow() { + DCHECK(handle_ != gfx::kNullPluginWindow); + HWND host_window = static_cast(handle_); + + // Create the compositor window itself. + DCHECK(host_window); + static ATOM window_class = 0; + if (!window_class) { + WNDCLASSEX wcex; + wcex.cbSize = sizeof(wcex); + wcex.style = 0; + wcex.lpfnWndProc = base::win::WrappedWindowProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = GetModuleHandle(NULL); + wcex.hIcon = 0; + wcex.hCursor = 0; + wcex.hbrBackground = NULL; + wcex.lpszMenuName = 0; + wcex.lpszClassName = L"CompositorWindowClass"; + wcex.hIconSm = 0; + window_class = RegisterClassEx(&wcex); + DCHECK(window_class); + } + + HWND compositor_window = CreateWindowEx( + WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, + MAKEINTATOM(window_class), + 0, + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DISABLED, + 0, 0, + 0, 0, + host_window, + 0, + GetModuleHandle(NULL), + 0); + if (!compositor_window) { + compositor_window_ = gfx::kNullPluginWindow; + return false; + } + SetProp(compositor_window, kCompositorWindowOwner, + reinterpret_cast(this)); + + RECT parent_rect; + GetClientRect(host_window, &parent_rect); + + UINT flags = SWP_NOSENDCHANGING | SWP_NOCOPYBITS | SWP_NOZORDER | + SWP_NOACTIVATE | SWP_DEFERERASE | SWP_SHOWWINDOW; + SetWindowPos(compositor_window, + NULL, + 0, 0, + parent_rect.right - parent_rect.left, + parent_rect.bottom - parent_rect.top, + flags); + compositor_window_ = static_cast(compositor_window); + return true; +} + +void GpuCommandBufferStub::OnCompositorWindowPainted() { + GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); + gpu_channel_manager->Send(new GpuHostMsg_ScheduleComposite( + renderer_id_, render_view_id_)); +} +#endif // defined(OS_WIN) + + +GpuCommandBufferStub::~GpuCommandBufferStub() { + if (processor_.get()) { + processor_->Destroy(); + } +#if defined(OS_WIN) + if (compositor_window_) { + DestroyWindow(static_cast(compositor_window_)); + compositor_window_ = NULL; + } +#endif // defined(OS_WIN) + + GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); + gpu_channel_manager->Send(new GpuHostMsg_DestroyCommandBuffer( + handle_, renderer_id_, render_view_id_)); +} + +bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(GpuCommandBufferStub, message) + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Initialize, OnInitialize); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_GetState, OnGetState); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_AsyncGetState, OnAsyncGetState); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Flush, OnFlush); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_AsyncFlush, OnAsyncFlush); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateTransferBuffer, + OnCreateTransferBuffer); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RegisterTransferBuffer, + OnRegisterTransferBuffer); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyTransferBuffer, + OnDestroyTransferBuffer); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_GetTransferBuffer, + OnGetTransferBuffer); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ResizeOffscreenFrameBuffer, + OnResizeOffscreenFrameBuffer); +#if defined(OS_MACOSX) + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetWindowSize, OnSetWindowSize); +#endif // defined(OS_MACOSX) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + DCHECK(handled); + return handled; +} + +bool GpuCommandBufferStub::Send(IPC::Message* message) { + return channel_->Send(message); +} + +void GpuCommandBufferStub::OnInitialize( + base::SharedMemoryHandle ring_buffer, + int32 size, + bool* result) { + DCHECK(!command_buffer_.get()); + + *result = false; + + command_buffer_.reset(new gpu::CommandBufferService); + + // Create the child window, if needed +#if defined(OS_WIN) + gfx::PluginWindowHandle output_window_handle; + if (handle_) { + if (!CreateCompositorWindow()) { + return; + } + output_window_handle = compositor_window_; + } else { + output_window_handle = handle_; + } +#else + gfx::PluginWindowHandle output_window_handle = handle_; +#endif // defined(OS_WIN) + +#if defined(OS_WIN) + // Windows dups the shared memory handle it receives into the current process + // and closes it when this variable goes out of scope. + base::SharedMemory shared_memory(ring_buffer, + false, + channel_->renderer_process()); +#else + // POSIX receives a dup of the shared memory handle and closes the dup when + // this variable goes out of scope. + base::SharedMemory shared_memory(ring_buffer, false); +#endif + + // Initialize the CommandBufferService and GPUProcessor. + if (command_buffer_->Initialize(&shared_memory, size)) { + gpu::GPUProcessor* parent_processor = + parent_ ? parent_->processor_.get() : NULL; + processor_.reset(new gpu::GPUProcessor(command_buffer_.get(), NULL)); + if (processor_->Initialize( + output_window_handle, + initial_size_, + disallowed_extensions_, + allowed_extensions_.c_str(), + requested_attribs_, + parent_processor, + parent_texture_id_)) { + command_buffer_->SetPutOffsetChangeCallback( + NewCallback(processor_.get(), + &gpu::GPUProcessor::ProcessCommands)); + processor_->SetSwapBuffersCallback( + NewCallback(this, &GpuCommandBufferStub::OnSwapBuffers)); + if (watchdog_thread_) + processor_->SetCommandProcessedCallback( + NewCallback(this, &GpuCommandBufferStub::OnCommandProcessed)); + +#if defined(OS_MACOSX) + if (handle_) { + // This context conceptually puts its output directly on the + // screen, rendered by the accelerated plugin layer in + // RenderWidgetHostViewMac. Set up a pathway to notify the + // browser process when its contents change. + processor_->SetSwapBuffersCallback( + NewCallback(this, + &GpuCommandBufferStub::SwapBuffersCallback)); + } +#endif // defined(OS_MACOSX) + + // Set up a pathway for resizing the output window or framebuffer at the + // right time relative to other GL commands. + processor_->SetResizeCallback( + NewCallback(this, &GpuCommandBufferStub::ResizeCallback)); + + *result = true; + } else { + processor_.reset(); + command_buffer_.reset(); + } + } +} + +void GpuCommandBufferStub::OnCommandProcessed() { + if (watchdog_thread_) + watchdog_thread_->CheckArmed(); +} + +void GpuCommandBufferStub::OnGetState(gpu::CommandBuffer::State* state) { + *state = command_buffer_->GetState(); +} + +void GpuCommandBufferStub::OnAsyncGetState() { + gpu::CommandBuffer::State state = command_buffer_->GetState(); + Send(new GpuCommandBufferMsg_UpdateState(route_id_, state)); +} + +void GpuCommandBufferStub::OnFlush(int32 put_offset, + gpu::CommandBuffer::State* state) { + *state = command_buffer_->FlushSync(put_offset); +} + +void GpuCommandBufferStub::OnAsyncFlush(int32 put_offset) { + gpu::CommandBuffer::State state = command_buffer_->FlushSync(put_offset); + Send(new GpuCommandBufferMsg_UpdateState(route_id_, state)); +} + +void GpuCommandBufferStub::OnCreateTransferBuffer(int32 size, int32* id) { + *id = command_buffer_->CreateTransferBuffer(size); +} + +void GpuCommandBufferStub::OnRegisterTransferBuffer( + base::SharedMemoryHandle transfer_buffer, + size_t size, + int32* id) { +#if defined(OS_WIN) + // Windows dups the shared memory handle it receives into the current process + // and closes it when this variable goes out of scope. + base::SharedMemory shared_memory(transfer_buffer, + false, + channel_->renderer_process()); +#else + // POSIX receives a dup of the shared memory handle and closes the dup when + // this variable goes out of scope. + base::SharedMemory shared_memory(transfer_buffer, false); +#endif + + *id = command_buffer_->RegisterTransferBuffer(&shared_memory, size); +} + +void GpuCommandBufferStub::OnDestroyTransferBuffer(int32 id) { + command_buffer_->DestroyTransferBuffer(id); +} + +void GpuCommandBufferStub::OnGetTransferBuffer( + int32 id, + base::SharedMemoryHandle* transfer_buffer, + uint32* size) { + *transfer_buffer = base::SharedMemoryHandle(); + *size = 0; + + // Fail if the renderer process has not provided its process handle. + if (!channel_->renderer_process()) + return; + + Buffer buffer = command_buffer_->GetTransferBuffer(id); + if (buffer.shared_memory) { + // Assume service is responsible for duplicating the handle to the calling + // process. + buffer.shared_memory->ShareToProcess(channel_->renderer_process(), + transfer_buffer); + *size = buffer.size; + } +} + +void GpuCommandBufferStub::OnResizeOffscreenFrameBuffer(const gfx::Size& size) { + processor_->ResizeOffscreenFrameBuffer(size); +} + +void GpuCommandBufferStub::OnSwapBuffers() { + GPU_TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSwapBuffers"); + Send(new GpuCommandBufferMsg_SwapBuffers(route_id_)); +} + +#if defined(OS_MACOSX) +void GpuCommandBufferStub::OnSetWindowSize(const gfx::Size& size) { + GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); + // Try using the IOSurface version first. + uint64 new_backing_store = processor_->SetWindowSizeForIOSurface(size); + if (new_backing_store) { + GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params; + params.renderer_id = renderer_id_; + params.render_view_id = render_view_id_; + params.window = handle_; + params.width = size.width(); + params.height = size.height(); + params.identifier = new_backing_store; + gpu_channel_manager->Send( + new GpuHostMsg_AcceleratedSurfaceSetIOSurface(params)); + } else { + // TODO(kbr): figure out what to do here. It wouldn't be difficult + // to support the compositor on 10.5, but the performance would be + // questionable. + NOTREACHED(); + } +} + +void GpuCommandBufferStub::SwapBuffersCallback() { + OnSwapBuffers(); + GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); + GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; + params.renderer_id = renderer_id_; + params.render_view_id = render_view_id_; + params.window = handle_; + params.surface_id = processor_->GetSurfaceId(); + params.route_id = route_id(); + params.swap_buffers_count = processor_->swap_buffers_count(); + gpu_channel_manager->Send( + new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params)); +} + +void GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped( + uint64 swap_buffers_count) { + processor_->set_acknowledged_swap_buffers_count(swap_buffers_count); + // Wake up the GpuProcessor to start doing work again. + processor_->ScheduleProcessCommands(); +} +#endif // defined(OS_MACOSX) + +void GpuCommandBufferStub::ResizeCallback(gfx::Size size) { + if (handle_ == gfx::kNullPluginWindow) { + processor_->decoder()->ResizeOffscreenFrameBuffer(size); + processor_->decoder()->UpdateOffscreenFrameBufferSize(); + } else { +#if defined(OS_LINUX) && !defined(TOUCH_UI) + GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); + bool result = false; + gpu_channel_manager->Send( + new GpuHostMsg_ResizeXID(handle_, size, &result)); +#elif defined(OS_WIN) + HWND hwnd = static_cast(compositor_window_); + UINT swp_flags = SWP_NOSENDCHANGING | SWP_NOOWNERZORDER | SWP_NOCOPYBITS | + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE; + SetWindowPos(hwnd, NULL, 0, 0, size.width(), size.height(), swp_flags); +#endif // defined(OS_LINUX) + } +} + +#endif // defined(ENABLE_GPU) diff --git a/content/common/gpu/gpu_command_buffer_stub.h b/content/common/gpu/gpu_command_buffer_stub.h new file mode 100644 index 0000000..0010b17 --- /dev/null +++ b/content/common/gpu/gpu_command_buffer_stub.h @@ -0,0 +1,141 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_COMMON_GPU_GPU_COMMAND_BUFFER_STUB_H_ +#define CONTENT_COMMON_GPU_GPU_COMMAND_BUFFER_STUB_H_ +#pragma once + +#if defined(ENABLE_GPU) + +#include +#include + +#include "base/memory/weak_ptr.h" +#include "base/process.h" +#include "gpu/command_buffer/service/command_buffer_service.h" +#include "gpu/command_buffer/service/gpu_processor.h" +#include "ipc/ipc_channel.h" +#include "ipc/ipc_message.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gfx/size.h" + +class GpuChannel; +class GpuWatchdogThread; + +class GpuCommandBufferStub + : public IPC::Channel::Listener, + public IPC::Message::Sender, + public base::SupportsWeakPtr { + public: + GpuCommandBufferStub( + GpuChannel* channel, + gfx::PluginWindowHandle handle, + GpuCommandBufferStub* parent, + const gfx::Size& size, + const gpu::gles2::DisallowedExtensions& disallowed_extensions, + const std::string& allowed_extensions, + const std::vector& attribs, + uint32 parent_texture_id, + int32 route_id, + int32 renderer_id, + int32 render_view_id, + GpuWatchdogThread* gpu_watchdog_thread); + + virtual ~GpuCommandBufferStub(); + + // IPC::Channel::Listener implementation: + virtual bool OnMessageReceived(const IPC::Message& message); + + // IPC::Message::Sender implementation: + virtual bool Send(IPC::Message* msg); + + // Get the GLContext associated with this object. + gpu::GPUProcessor* processor() const { return processor_.get(); } + + // Identifies the renderer process. + int32 renderer_id() const { return renderer_id_; } + + // Identifies a particular renderer belonging to the same renderer process. + int32 render_view_id() const { return render_view_id_; } + + // Identifies the various GpuCommandBufferStubs in the GPU process belonging + // to the same renderer process. + int32 route_id() const { return route_id_; } + +#if defined(OS_WIN) + // Called only by the compositor window's window proc + void OnCompositorWindowPainted(); +#endif // defined(OS_WIN) + +#if defined(OS_MACOSX) + // Called only by the GpuChannel. + void AcceleratedSurfaceBuffersSwapped(uint64 swap_buffers_count); +#endif // defined(OS_MACOSX) + + private: + // Message handlers: + void OnInitialize(base::SharedMemoryHandle ring_buffer, + int32 size, + bool* result); + void OnGetState(gpu::CommandBuffer::State* state); + void OnAsyncGetState(); + void OnFlush(int32 put_offset, gpu::CommandBuffer::State* state); + void OnAsyncFlush(int32 put_offset); + void OnCreateTransferBuffer(int32 size, int32* id); + void OnRegisterTransferBuffer(base::SharedMemoryHandle transfer_buffer, + size_t size, + int32* id); + void OnDestroyTransferBuffer(int32 id); + void OnGetTransferBuffer(int32 id, + base::SharedMemoryHandle* transfer_buffer, + uint32* size); + void OnResizeOffscreenFrameBuffer(const gfx::Size& size); + + void OnSwapBuffers(); + void OnCommandProcessed(); + +#if defined(OS_MACOSX) + void OnSetWindowSize(const gfx::Size& size); + void SwapBuffersCallback(); +#endif // defined(OS_MACOSX) + +#if defined(OS_WIN) + bool CreateCompositorWindow(); +#endif // defined(OS_WIN) + + void ResizeCallback(gfx::Size size); + + // The lifetime of objects of this class is managed by a GpuChannel. The + // GpuChannels destroy all the GpuCommandBufferStubs that they own when they + // are destroyed. So a raw pointer is safe. + GpuChannel* channel_; + + gfx::PluginWindowHandle handle_; + base::WeakPtr parent_; + gfx::Size initial_size_; + gpu::gles2::DisallowedExtensions disallowed_extensions_; + std::string allowed_extensions_; + std::vector requested_attribs_; + uint32 parent_texture_id_; + int32 route_id_; + +#if defined(OS_WIN) + HWND compositor_window_; +#endif // defined(OS_WIN) + + // The following two fields are used on Mac OS X to identify the window + // for the rendering results on the browser side. + int32 renderer_id_; + int32 render_view_id_; + + scoped_ptr command_buffer_; + scoped_ptr processor_; + GpuWatchdogThread* watchdog_thread_; + + DISALLOW_COPY_AND_ASSIGN(GpuCommandBufferStub); +}; + +#endif // defined(ENABLE_GPU) + +#endif // CONTENT_COMMON_GPU_GPU_COMMAND_BUFFER_STUB_H_ diff --git a/content/common/gpu/gpu_config.h b/content/common/gpu/gpu_config.h new file mode 100644 index 0000000..8156948 --- /dev/null +++ b/content/common/gpu/gpu_config.h @@ -0,0 +1,13 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_COMMON_GPU_GPU_CONFIG_H_ +#define CONTENT_COMMON_GPU_GPU_CONFIG_H_ +#pragma once + +// This file declares common preprocessor configuration for the GPU process. + +#include "build/build_config.h" + +#endif // CONTENT_COMMON_GPU_GPU_CONFIG_H_ diff --git a/content/common/gpu/gpu_info.cc b/content/common/gpu/gpu_info.cc new file mode 100644 index 0000000..f067baf --- /dev/null +++ b/content/common/gpu/gpu_info.cc @@ -0,0 +1,63 @@ +// Copyright (c) 2011 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 "content/common/gpu/gpu_info.h" + +GPUInfo::GPUInfo() + : finalized(false), + vendor_id(0), + device_id(0), + can_lose_context(false) { +} + +GPUInfo::~GPUInfo() { } + +bool GPUInfo::Merge(const GPUInfo& other) { + if (device_id != other.device_id || vendor_id != other.vendor_id) { + *this = other; + return true; + } + + bool changed = false; + if (!finalized) { + finalized = other.finalized; + initialization_time = other.initialization_time; + if (driver_vendor.empty() && !other.driver_vendor.empty()) { + driver_vendor = other.driver_vendor; + changed = true; + } + if (driver_version.empty() && !other.driver_version.empty()) { + driver_version = other.driver_version; + changed = true; + } + if (driver_date.empty() && !other.driver_date.empty()) { + driver_date = other.driver_date; + changed = true; + } + if (pixel_shader_version.empty()) + pixel_shader_version = other.pixel_shader_version; + if (vertex_shader_version.empty()) + vertex_shader_version = other.vertex_shader_version; + if (gl_version.empty()) + gl_version = other.gl_version; + if (gl_version_string.empty()) + gl_version_string = other.gl_version_string; + if (gl_vendor.empty()) + gl_vendor = other.gl_vendor; + if (gl_renderer.empty() && !other.gl_renderer.empty()) { + gl_renderer = other.gl_renderer; + changed = true; + } + if (gl_extensions.empty()) + gl_extensions = other.gl_extensions; + can_lose_context = other.can_lose_context; +#if defined(OS_WIN) + if (dx_diagnostics.values.size() == 0 && + dx_diagnostics.children.size() == 0) + dx_diagnostics = other.dx_diagnostics; +#endif + } + return changed; +} + diff --git a/content/common/gpu/gpu_info.h b/content/common/gpu/gpu_info.h new file mode 100644 index 0000000..678cb86 --- /dev/null +++ b/content/common/gpu/gpu_info.h @@ -0,0 +1,86 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_COMMON_GPU_GPU_INFO_H_ +#define CONTENT_COMMON_GPU_GPU_INFO_H_ +#pragma once + +// Provides access to the GPU information for the system +// on which chrome is currently running. + +#include + +#include "base/basictypes.h" +#include "base/time.h" +#include "build/build_config.h" +#include "content/common/dx_diag_node.h" + +struct GPUInfo { + GPUInfo(); + ~GPUInfo(); + + // If it's the same GPU, i.e., device id and vendor id are the same, then + // copy over the fields that are not set yet and ignore the rest. + // If it's a different GPU, then reset and copy over everything. + // Return true if something changes that may affect blacklisting; currently + // they are device_id, vendor_id, driver_vendor, driver_version, driver_date, + // and gl_renderer. + bool Merge(const GPUInfo& other); + + // Whether more GPUInfo fields might be collected in the future. + bool finalized; + + // The amount of time taken to get from the process starting to the message + // loop being pumped. + base::TimeDelta initialization_time; + + // The DWORD (uint32) representing the graphics card vendor id. + uint32 vendor_id; + + // The DWORD (uint32) representing the graphics card device id. Device ids + // are unique to vendor, not to one another. + uint32 device_id; + + // The vendor of the graphics driver currently installed. + std::string driver_vendor; + + // The version of the graphics driver currently installed. + std::string driver_version; + + // The date of the graphics driver currently installed. + std::string driver_date; + + // The version of the pixel/fragment shader used by the gpu. + std::string pixel_shader_version; + + // The version of the vertex shader used by the gpu. + std::string vertex_shader_version; + + // The version of OpenGL we are using. + // TODO(zmo): should be able to tell if it's GL or GLES. + std::string gl_version; + + // The GL_VERSION string. "" if we are not using OpenGL. + std::string gl_version_string; + + // The GL_VENDOR string. "" if we are not using OpenGL. + std::string gl_vendor; + + // The GL_RENDERER string. "" if we are not using OpenGL. + std::string gl_renderer; + + // The GL_EXTENSIONS string. "" if we are not using OpenGL. + std::string gl_extensions; + + // The device semantics, i.e. whether the Vista and Windows 7 specific + // semantics are available. + bool can_lose_context; + +#if defined(OS_WIN) + // The information returned by the DirectX Diagnostics Tool. + DxDiagNode dx_diagnostics; +#endif +}; + +#endif // CONTENT_COMMON_GPU_GPU_INFO_H_ diff --git a/content/common/gpu/gpu_info_unittest.cc b/content/common/gpu/gpu_info_unittest.cc new file mode 100644 index 0000000..887b5f1 --- /dev/null +++ b/content/common/gpu/gpu_info_unittest.cc @@ -0,0 +1,26 @@ +// Copyright (c) 2011 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 "content/common/gpu/gpu_info.h" +#include "testing/gtest/include/gtest/gtest.h" + +// Test that an empty GPUInfo has valid members +TEST(GPUInfoBasicTest, EmptyGPUInfo) { + GPUInfo gpu_info; + EXPECT_EQ(gpu_info.finalized, false); + EXPECT_EQ(gpu_info.initialization_time.ToInternalValue(), 0); + EXPECT_EQ(gpu_info.vendor_id, 0u); + EXPECT_EQ(gpu_info.device_id, 0u); + EXPECT_EQ(gpu_info.driver_vendor, ""); + EXPECT_EQ(gpu_info.driver_version, ""); + EXPECT_EQ(gpu_info.driver_date, ""); + EXPECT_EQ(gpu_info.pixel_shader_version, ""); + EXPECT_EQ(gpu_info.vertex_shader_version, ""); + EXPECT_EQ(gpu_info.gl_version, ""); + EXPECT_EQ(gpu_info.gl_version_string, ""); + EXPECT_EQ(gpu_info.gl_vendor, ""); + EXPECT_EQ(gpu_info.gl_renderer, ""); + EXPECT_EQ(gpu_info.gl_extensions, ""); + EXPECT_EQ(gpu_info.can_lose_context, false); +} diff --git a/content/common/gpu/gpu_video_decoder.cc b/content/common/gpu/gpu_video_decoder.cc new file mode 100644 index 0000000..1b89a01 --- /dev/null +++ b/content/common/gpu/gpu_video_decoder.cc @@ -0,0 +1,427 @@ +// Copyright (c) 2011 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 "content/common/gpu/gpu_video_decoder.h" + +#include "base/command_line.h" +#include "content/common/child_thread.h" +#include "content/common/gpu/gpu_channel.h" +#include "content/common/gpu/media/fake_gl_video_device.h" +#include "content/common/gpu/media/fake_gl_video_decode_engine.h" +#include "content/common/gpu_messages.h" +#include "media/base/data_buffer.h" +#include "media/base/media_switches.h" +#include "media/base/video_frame.h" + +#if defined(OS_WIN) +#include "content/common/gpu/media/mft_angle_video_device.h" +#include "media/video/mft_h264_decode_engine.h" +#include +#endif + +struct GpuVideoDecoder::PendingAllocation { + size_t n; + size_t width; + size_t height; + media::VideoFrame::Format format; + std::vector >* frames; + Task* task; +}; + +void GpuVideoDecoder::OnChannelConnected(int32 peer_pid) { +} + +void GpuVideoDecoder::OnChannelError() { +} + +bool GpuVideoDecoder::OnMessageReceived(const IPC::Message& msg) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(GpuVideoDecoder, msg) + IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Initialize, + OnInitialize) + IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Destroy, + OnUninitialize) + IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Flush, + OnFlush) + IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Preroll, + OnPreroll) + IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_EmptyThisBuffer, + OnEmptyThisBuffer) + IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_ProduceVideoFrame, + OnProduceVideoFrame) + IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_VideoFrameAllocated, + OnVideoFrameAllocated) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + DCHECK(handled); + return handled; +} + +bool GpuVideoDecoder::CreateInputTransferBuffer( + uint32 size, + base::SharedMemoryHandle* handle) { + input_transfer_buffer_.reset(new base::SharedMemory); + if (!input_transfer_buffer_.get()) + return false; + + if (!input_transfer_buffer_->CreateAndMapAnonymous(size)) + return false; + + if (!input_transfer_buffer_->ShareToProcess(renderer_handle_, handle)) + return false; + + return true; +} + +void GpuVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) { + info_ = info; + GpuVideoDecoderInitDoneParam param; + param.success = false; + param.input_buffer_handle = base::SharedMemory::NULLHandle(); + + if (!info.success) { + SendInitializeDone(param); + return; + } + + // TODO(jiesun): Check the assumption of input size < original size. + param.input_buffer_size = + info.stream_info.surface_width * info.stream_info.surface_height * 3 / 2; + if (!CreateInputTransferBuffer(param.input_buffer_size, + ¶m.input_buffer_handle)) { + SendInitializeDone(param); + return; + } + + param.success = true; + SendInitializeDone(param); +} + +void GpuVideoDecoder::OnUninitializeComplete() { + SendUninitializeDone(); +} + +void GpuVideoDecoder::OnFlushComplete() { + SendFlushDone(); +} + +void GpuVideoDecoder::OnSeekComplete() { + SendPrerollDone(); +} + +void GpuVideoDecoder::OnError() { + NOTIMPLEMENTED(); +} + +void GpuVideoDecoder::OnFormatChange(VideoStreamInfo stream_info) { + NOTIMPLEMENTED(); +} + +void GpuVideoDecoder::ProduceVideoSample(scoped_refptr buffer) { + SendEmptyBufferDone(); +} + +void GpuVideoDecoder::ConsumeVideoFrame(scoped_refptr frame, + const PipelineStatistics& statistics) { + // TODO(sjl): Do something with the statistics... + + if (frame->IsEndOfStream()) { + SendConsumeVideoFrame(0, 0, 0, kGpuVideoEndOfStream); + return; + } + + int32 frame_id = -1; + for (VideoFrameMap::iterator i = video_frame_map_.begin(); + i != video_frame_map_.end(); ++i) { + if (i->second == frame) { + frame_id = i->first; + break; + } + } + + if (frame_id == -1) { + NOTREACHED() << "VideoFrame not recognized"; + return; + } + + SendConsumeVideoFrame(frame_id, frame->GetTimestamp().InMicroseconds(), + frame->GetDuration().InMicroseconds(), 0); +} + +void* GpuVideoDecoder::GetDevice() { + bool ret = gles2_decoder_->MakeCurrent(); + DCHECK(ret) << "Failed to switch context"; + + // Simply delegate the method call to GpuVideoDevice. + return video_device_->GetDevice(); +} + +void GpuVideoDecoder::AllocateVideoFrames( + int n, size_t width, size_t height, media::VideoFrame::Format format, + std::vector >* frames, Task* task) { + // Since the communication between Renderer and GPU process is by GL textures. + // We need to obtain a set of GL textures by sending IPC commands to the + // Renderer process. The recipient of these commands will be IpcVideoDecoder. + // + // After IpcVideoDecoder replied with a set of textures. We'll assign these + // textures to GpuVideoDevice. They will be used to generate platform + // specific VideoFrames objects that are used by VideoDecodeEngine. + // + // After GL textures are assigned we'll proceed with allocation the + // VideoFrames. GpuVideoDevice::CreateVideoFramesFromGlTextures() will be + // called. + // + // When GpuVideoDevice replied with a set of VideoFrames we'll give + // that to VideoDecodeEngine and the cycle of video frame allocation is done. + // + // Note that this method is called when there's no video frames allocated or + // they were all released. + DCHECK(video_frame_map_.empty()); + + // Save the parameters for allocation. + pending_allocation_.reset(new PendingAllocation()); + pending_allocation_->n = n; + pending_allocation_->width = width; + pending_allocation_->height = height; + pending_allocation_->format = format; + pending_allocation_->frames = frames; + pending_allocation_->task = task; + SendAllocateVideoFrames(n, width, height, format); +} + +void GpuVideoDecoder::ReleaseAllVideoFrames() { + // This method will first call to GpuVideoDevice to release all the resource + // associated with a VideoFrame. + // + // And then we'll call GpuVideoDevice::ReleaseVideoFrame() to remove the set + // of Gl textures associated with the context. + // + // And finally we'll send IPC commands to IpcVideoDecoder to destroy all + // GL textures generated. + bool ret = gles2_decoder_->MakeCurrent(); + DCHECK(ret) << "Failed to switch context"; + + for (VideoFrameMap::iterator i = video_frame_map_.begin(); + i != video_frame_map_.end(); ++i) { + video_device_->ReleaseVideoFrame(i->second); + } + video_frame_map_.clear(); + SendReleaseAllVideoFrames(); +} + +void GpuVideoDecoder::ConvertToVideoFrame( + void* buffer, + scoped_refptr frame, + Task* task) { + // This method is called by VideoDecodeEngine to upload a buffer to a + // VideoFrame. We should just delegate this to GpuVideoDevice which contains + // the actual implementation. + bool ret = gles2_decoder_->MakeCurrent(); + DCHECK(ret) << "Failed to switch context"; + + // Actually doing the upload on the main thread. + ret = video_device_->ConvertToVideoFrame(buffer, frame); + DCHECK(ret) << "Failed to upload video content to a VideoFrame."; + task->Run(); + delete task; +} + +void GpuVideoDecoder::Destroy(Task* task) { + // TODO(hclam): I still need to think what I should do here. +} + +void GpuVideoDecoder::SetVideoDecodeEngine(media::VideoDecodeEngine* engine) { + decode_engine_.reset(engine); +} + +void GpuVideoDecoder::SetGpuVideoDevice(GpuVideoDevice* device) { + video_device_.reset(device); +} + +GpuVideoDecoder::GpuVideoDecoder( + MessageLoop* message_loop, + int32 decoder_host_id, + IPC::Message::Sender* sender, + base::ProcessHandle handle, + gpu::gles2::GLES2Decoder* decoder) + : message_loop_(message_loop), + decoder_host_id_(decoder_host_id), + sender_(sender), + renderer_handle_(handle), + gles2_decoder_(decoder) { + memset(&info_, 0, sizeof(info_)); + + // TODO(jiesun): find a better way to determine which VideoDecodeEngine + // to return on current platform. +#if defined(OS_WIN) + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kEnableAcceleratedDecoding)) { + // The following code are removed so that we don't link them. + // TODO(hclam): Enable the code once the crash is solved on XP. + // decode_engine_.reset(new media::MftH264DecodeEngine(true)); + // video_device_.reset(new MftAngleVideoDevice()); + } +#else + decode_engine_.reset(new FakeGlVideoDecodeEngine()); + video_device_.reset(new FakeGlVideoDevice()); +#endif +} + +GpuVideoDecoder::~GpuVideoDecoder() {} + +void GpuVideoDecoder::OnInitialize(const GpuVideoDecoderInitParam& param) { + // TODO(jiesun): codec id should come from |param|. + media::VideoCodecConfig config(media::kCodecH264, + param.width, + param.height, + param.frame_rate_num, + param.frame_rate_den, + NULL, + 0); + decode_engine_->Initialize(message_loop_, this, this, config); +} + +void GpuVideoDecoder::OnUninitialize() { + decode_engine_->Uninitialize(); +} + +void GpuVideoDecoder::OnFlush() { + decode_engine_->Flush(); +} + +void GpuVideoDecoder::OnPreroll() { + decode_engine_->Seek(); +} + +void GpuVideoDecoder::OnEmptyThisBuffer( + const GpuVideoDecoderInputBufferParam& buffer) { + DCHECK(input_transfer_buffer_->memory()); + + uint8* src = static_cast(input_transfer_buffer_->memory()); + + scoped_refptr input_buffer; + uint8* dst = buffer.size ? new uint8[buffer.size] : NULL; + input_buffer = new media::DataBuffer(dst, buffer.size); + memcpy(dst, src, buffer.size); + SendEmptyBufferACK(); + + // Delegate the method call to VideoDecodeEngine. + decode_engine_->ConsumeVideoSample(input_buffer); +} + +void GpuVideoDecoder::OnProduceVideoFrame(int32 frame_id) { + VideoFrameMap::iterator i = video_frame_map_.find(frame_id); + if (i == video_frame_map_.end()) { + NOTREACHED() << "Received a request of unknown frame ID."; + } + + // Delegate the method call to VideoDecodeEngine. + decode_engine_->ProduceVideoFrame(i->second); +} + +void GpuVideoDecoder::OnVideoFrameAllocated(int32 frame_id, + std::vector textures) { + bool ret = gles2_decoder_->MakeCurrent(); + DCHECK(ret) << "Failed to switch context"; + + // This method is called in response to a video frame allocation request sent + // to the Renderer process. + // We should use the textures to generate a VideoFrame by using + // GpuVideoDevice. The VideoFrame created is added to the internal map. + // If we have generated enough VideoFrame, we call |allocation_callack_| to + // complete the allocation process. + for (size_t i = 0; i < textures.size(); ++i) { + media::VideoFrame::GlTexture gl_texture; + // Translate the client texture id to service texture id. + ret = gles2_decoder_->GetServiceTextureId(textures[i], &gl_texture); + DCHECK(ret) << "Cannot translate client texture ID to service ID"; + textures[i] = gl_texture; + } + + // Use GpuVideoDevice to allocate VideoFrame objects. + scoped_refptr frame; + + ret = video_device_->CreateVideoFrameFromGlTextures( + pending_allocation_->width, pending_allocation_->height, + pending_allocation_->format, textures, &frame); + + DCHECK(ret) << "Failed to allocation VideoFrame from GL textures)"; + pending_allocation_->frames->push_back(frame); + video_frame_map_.insert(std::make_pair(frame_id, frame)); + + if (video_frame_map_.size() == pending_allocation_->n) { + pending_allocation_->task->Run(); + delete pending_allocation_->task; + pending_allocation_.reset(); + } +} + +void GpuVideoDecoder::SendInitializeDone( + const GpuVideoDecoderInitDoneParam& param) { + if (!sender_->Send( + new GpuVideoDecoderHostMsg_InitializeACK(decoder_host_id(), param))) { + LOG(ERROR) << "GpuVideoDecoderMsg_InitializeACK failed"; + } +} + +void GpuVideoDecoder::SendUninitializeDone() { + if (!sender_->Send( + new GpuVideoDecoderHostMsg_DestroyACK(decoder_host_id()))) { + LOG(ERROR) << "GpuVideoDecoderMsg_DestroyACK failed"; + } +} + +void GpuVideoDecoder::SendFlushDone() { + if (!sender_->Send(new GpuVideoDecoderHostMsg_FlushACK(decoder_host_id()))) { + LOG(ERROR) << "GpuVideoDecoderMsg_FlushACK failed"; + } +} + +void GpuVideoDecoder::SendPrerollDone() { + if (!sender_->Send(new GpuVideoDecoderHostMsg_PrerollDone( + decoder_host_id()))) { + LOG(ERROR) << "GpuVideoDecoderMsg_PrerollDone failed"; + } +} + +void GpuVideoDecoder::SendEmptyBufferDone() { + if (!sender_->Send( + new GpuVideoDecoderHostMsg_EmptyThisBufferDone(decoder_host_id()))) { + LOG(ERROR) << "GpuVideoDecoderMsg_EmptyThisBufferDone failed"; + } +} + +void GpuVideoDecoder::SendEmptyBufferACK() { + if (!sender_->Send( + new GpuVideoDecoderHostMsg_EmptyThisBufferACK(decoder_host_id()))) { + LOG(ERROR) << "GpuVideoDecoderMsg_EmptyThisBufferACK failed"; + } +} + +void GpuVideoDecoder::SendConsumeVideoFrame( + int32 frame_id, int64 timestamp, int64 duration, int32 flags) { + if (!sender_->Send( + new GpuVideoDecoderHostMsg_ConsumeVideoFrame( + decoder_host_id(), frame_id, timestamp, duration, flags))) { + LOG(ERROR) << "GpuVideoDecodeHostMsg_ConsumeVideoFrame failed."; + } +} + +void GpuVideoDecoder::SendAllocateVideoFrames( + int n, size_t width, size_t height, media::VideoFrame::Format format) { + if (!sender_->Send( + new GpuVideoDecoderHostMsg_AllocateVideoFrames( + decoder_host_id(), n, width, height, + static_cast(format)))) { + LOG(ERROR) << "GpuVideoDecoderMsg_AllocateVideoFrames failed"; + } +} + +void GpuVideoDecoder::SendReleaseAllVideoFrames() { + if (!sender_->Send( + new GpuVideoDecoderHostMsg_ReleaseAllVideoFrames( + decoder_host_id()))) { + LOG(ERROR) << "GpuVideoDecoderMsg_ReleaseAllVideoFrames failed"; + } +} diff --git a/content/common/gpu/gpu_video_decoder.h b/content/common/gpu/gpu_video_decoder.h new file mode 100644 index 0000000..03cb9dc --- /dev/null +++ b/content/common/gpu/gpu_video_decoder.h @@ -0,0 +1,209 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_COMMON_GPU_GPU_VIDEO_DECODER_H_ +#define CONTENT_COMMON_GPU_GPU_VIDEO_DECODER_H_ + +#include +#include + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/process.h" +#include "base/shared_memory.h" +#include "content/common/gpu/media/gpu_video_device.h" +#include "media/video/video_decode_context.h" +#include "media/video/video_decode_engine.h" +#include "ipc/ipc_channel.h" + +using media::Buffer; +using media::PipelineStatistics; +using media::VideoCodecConfig; +using media::VideoCodecInfo; +using media::VideoStreamInfo; +using media::VideoFrame; + +namespace gpu { +namespace gles2 { +class GLES2Decoder; +} // namespace gles2 +} // namespace gpu + +class GpuChannel; +struct GpuVideoDecoderInitDoneParam; +struct GpuVideoDecoderInitParam; +struct GpuVideoDecoderInputBufferParam; + +// A GpuVideoDecoder is a platform independent video decoder that uses platform +// specific VideoDecodeEngine and GpuVideoDevice for the actual decoding +// operations. +// +// In addition to delegating video related commamnds to VideoDecodeEngine it +// has the following important functions: +// +// BUFFER ALLOCATION +// +// VideoDecodeEngine requires platform specific video frame buffer to operate. +// In order to abstract the platform specific bits GpuVideoDecoderContext is +// used to allocate video frames that a VideoDecodeEngine can use. +// +// Since all the video frames appear to the Renderer process as textures, the +// first thing GpuVideoDecoder needs to do is to ask Renderer process to +// generate and allocate textures. This will establish a texture record in the +// command buffer decoder. After the texture is allocated, this class will +// pass the textures meaningful in the local GLES context to +// GpuVideoDevice for generating VideoFrames that VideoDecodeEngine +// can actually use. +// +// In order to coordinate these operations, GpuVideoDecoder implements +// VideoDecodeContext and is injected into the VideoDecodeEngine. +// +// The sequence of operations is: +// 1. VideoDecodeEngine requests by call AllocateVideoFrames(). +// 2. GpuVideoDecoder receives AllocateVideoFrames() and then call to the +// Renderer process to generate textures. +// 3. Renderer process replied with textures. +// 4. Textures generated are passed into GpuVideoDevice. +// 5. GpuVideoDevice::AllocateVideoFrames() is called to generate +// VideoFrame(s) from the textures. +// 6. GpuVideoDecoder sends the VideoFrame(s) generated to VideoDecodeEngine. +// +// BUFFER UPLOADING +// +// A VideoDecodeEngine always produces some device specific buffer. In order to +// use them in Chrome we always upload them to GL textures. The upload step is +// different on each platform and each subsystem. We perform these special +// upload steps by using GpuVideoDevice which are written for each +// VideoDecodeEngine. +// +// BUFFER MAPPING +// +// GpuVideoDecoder will be working with VideoDecodeEngine, they exchange +// buffers that are only meaningful to VideoDecodeEngine. In order to map that +// to something we can transport in the IPC channel we need a mapping between +// VideoFrame and buffer ID known between GpuVideoDecoder and +// GpuVideoDecoderHost in the Renderer process. +// +// After texture allocation and VideoFrame allocation are done, GpuVideoDecoder +// will maintain such mapping. +// +class GpuVideoDecoder + : public base::RefCountedThreadSafe, + public IPC::Channel::Listener, + public media::VideoDecodeEngine::EventHandler, + public media::VideoDecodeContext { + public: + // Constructor and destructor. + GpuVideoDecoder(MessageLoop* message_loop, + int32 decoder_host_id, + IPC::Message::Sender* sender, + base::ProcessHandle handle, + gpu::gles2::GLES2Decoder* decoder); + virtual ~GpuVideoDecoder(); + + // IPC::Channel::Listener implementation. + virtual void OnChannelConnected(int32 peer_pid); + virtual void OnChannelError(); + virtual bool OnMessageReceived(const IPC::Message& message); + + // VideoDecodeEngine::EventHandler implementation. + virtual void OnInitializeComplete(const VideoCodecInfo& info); + virtual void OnUninitializeComplete(); + virtual void OnFlushComplete(); + virtual void OnSeekComplete(); + virtual void OnError(); + virtual void OnFormatChange(VideoStreamInfo stream_info); + virtual void ProduceVideoSample(scoped_refptr buffer); + virtual void ConsumeVideoFrame(scoped_refptr frame, + const PipelineStatistics& statistics); + + // VideoDecodeContext implementation. + virtual void* GetDevice(); + virtual void AllocateVideoFrames( + int n, size_t width, size_t height, media::VideoFrame::Format format, + std::vector >* frames, Task* task); + virtual void ReleaseAllVideoFrames(); + virtual void ConvertToVideoFrame(void* buffer, + scoped_refptr frame, + Task* task); + virtual void Destroy(Task* task); + + // These methods are used in unit test only. + void SetVideoDecodeEngine(media::VideoDecodeEngine* engine); + void SetGpuVideoDevice(GpuVideoDevice* device); + + private: + struct PendingAllocation; + + int32 decoder_host_id() { return decoder_host_id_; } + + bool CreateInputTransferBuffer(uint32 size, + base::SharedMemoryHandle* handle); + + // These methods are message handlers for the messages sent from the Renderer + // process. + void OnInitialize(const GpuVideoDecoderInitParam& param); + void OnUninitialize(); + void OnFlush(); + void OnPreroll(); + void OnEmptyThisBuffer(const GpuVideoDecoderInputBufferParam& buffer); + void OnProduceVideoFrame(int32 frame_id); + void OnVideoFrameAllocated(int32 frame_id, std::vector textures); + + // Helper methods for sending messages to the Renderer process. + void SendInitializeDone(const GpuVideoDecoderInitDoneParam& param); + void SendUninitializeDone(); + void SendFlushDone(); + void SendPrerollDone(); + void SendEmptyBufferDone(); + void SendEmptyBufferACK(); + void SendConsumeVideoFrame(int32 frame_id, int64 timestamp, int64 duration, + int32 flags); + void SendAllocateVideoFrames( + int n, size_t width, size_t height, media::VideoFrame::Format format); + void SendReleaseAllVideoFrames(); + + // The message loop that this object should run on. + MessageLoop* message_loop_; + + // ID of GpuVideoDecoderHost in the Renderer Process. + int32 decoder_host_id_; + + // Used only in system memory path. i.e. Remove this later. + scoped_refptr frame_; + + IPC::Message::Sender* sender_; + base::ProcessHandle renderer_handle_; + + // The GLES2 decoder has the context associated with this decoder. This object + // is used to switch context and translate client texture ID to service ID. + gpu::gles2::GLES2Decoder* gles2_decoder_; + + // Memory for transfering the input data for the hardware video decoder. + scoped_ptr input_transfer_buffer_; + + // VideoDecodeEngine is used to do the actual video decoding. + scoped_ptr decode_engine_; + + // GpuVideoDevice is used to generate VideoFrame(s) from GL textures. The + // frames generated are understood by the decode engine. + scoped_ptr video_device_; + + // Contain information for allocation VideoFrame(s). + scoped_ptr pending_allocation_; + + // Contains the mapping between a |frame_id| and VideoFrame generated by + // GpuVideoDevice from the associated GL textures. + // TODO(hclam): Using a faster data structure than map. + typedef std::map > VideoFrameMap; + VideoFrameMap video_frame_map_; + + media::VideoCodecInfo info_; + + DISALLOW_COPY_AND_ASSIGN(GpuVideoDecoder); +}; + +#endif // CONTENT_COMMON_GPU_GPU_VIDEO_DECODER_H_ diff --git a/content/common/gpu/gpu_video_decoder_unittest.cc b/content/common/gpu/gpu_video_decoder_unittest.cc new file mode 100644 index 0000000..b9c846f --- /dev/null +++ b/content/common/gpu/gpu_video_decoder_unittest.cc @@ -0,0 +1,264 @@ +// Copyright (c) 2011 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 "base/message_loop.h" +#include "base/process.h" +#include "content/common/gpu/gpu_video_decoder.h" +#include "content/common/gpu_messages.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" +#include "ipc/ipc_message_utils.h" +#include "media/base/pipeline.h" +#include "media/video/video_mock_objects.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; +using testing::DoAll; +using testing::NotNull; +using testing::Return; +using testing::SetArgumentPointee; + +static const int32 kFrameId = 10; +static const int32 kDecoderHostId = 50; +static const media::VideoFrame::GlTexture kClientTexture = 101; +static const media::VideoFrame::GlTexture kServiceTexture = 102; +static const size_t kWidth = 320; +static const size_t kHeight = 240; + +class MockGpuVideoDevice : public GpuVideoDevice { + public: + MockGpuVideoDevice() {} + virtual ~MockGpuVideoDevice() {} + + MOCK_METHOD0(GetDevice, void*()); + MOCK_METHOD5(CreateVideoFrameFromGlTextures, + bool(size_t, size_t, media::VideoFrame::Format, + const std::vector&, + scoped_refptr*)); + MOCK_METHOD1(ReleaseVideoFrame, + void(const scoped_refptr& frame)); + MOCK_METHOD2(ConvertToVideoFrame, + bool(void* buffer, scoped_refptr frame)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockGpuVideoDevice); +}; + +ACTION_P(InitializationDone, handler) { + media::VideoCodecInfo info; + info.success = true; + info.provides_buffers = false; + info.stream_info.surface_format = media::VideoFrame::RGBA; + info.stream_info.surface_type = media::VideoFrame::TYPE_SYSTEM_MEMORY; + info.stream_info.surface_width = kWidth; + info.stream_info.surface_height = kHeight; + handler->OnInitializeComplete(info); +} + +ACTION_P(SendVideoFrameAllocated, handler) { + std::vector textures; + textures.push_back(kClientTexture); + GpuVideoDecoderMsg_VideoFrameAllocated msg(0, kFrameId, textures); + handler->OnMessageReceived(msg); +} + +ACTION_P2(SendConsumeVideoFrame, handler, frame) { + media::PipelineStatistics statistics; + handler->ConsumeVideoFrame(frame, statistics); +} + +class GpuVideoDecoderTest : public testing::Test, + public IPC::Message::Sender { + public: + GpuVideoDecoderTest() { + // Create the mock objects. + gles2_decoder_.reset(new gpu::gles2::MockGLES2Decoder()); + + gpu_video_decoder_ = new GpuVideoDecoder( + &message_loop_, kDecoderHostId, this, base::kNullProcessHandle, + gles2_decoder_.get()); + + // Create the mock objects. + mock_engine_ = new media::MockVideoDecodeEngine(); + mock_device_ = new MockGpuVideoDevice(); + + // Inject the mock objects. + gpu_video_decoder_->SetVideoDecodeEngine(mock_engine_); + gpu_video_decoder_->SetGpuVideoDevice(mock_device_); + + // VideoFrame for GpuVideoDevice. + media::VideoFrame::GlTexture textures[] = { kServiceTexture, 0, 0 }; + media::VideoFrame::CreateFrameGlTexture(media::VideoFrame::RGBA, + kWidth, kHeight, textures, + &device_frame_); + } + + virtual ~GpuVideoDecoderTest() { + gpu_video_decoder_->SetVideoDecodeEngine(NULL); + gpu_video_decoder_->SetGpuVideoDevice(NULL); + } + + // This method is used to dispatch IPC messages to mock methods. + virtual bool Send(IPC::Message* msg) { + EXPECT_TRUE(msg); + if (!msg) + return false; + + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(GpuVideoDecoderTest, *msg) + IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_InitializeACK, + OnInitializeDone) + IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_DestroyACK, + OnUninitializeDone) + IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_FlushACK, + OnFlushDone) + IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_EmptyThisBufferACK, + OnEmptyThisBufferACK) + IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_EmptyThisBufferDone, + OnEmptyThisBufferDone) + IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_AllocateVideoFrames, + OnAllocateVideoFrames) + IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_ReleaseAllVideoFrames, + OnReleaseAllVideoFrames) + IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_ConsumeVideoFrame, + OnConsumeVideoFrame) + IPC_MESSAGE_UNHANDLED_ERROR() + IPC_END_MESSAGE_MAP() + EXPECT_TRUE(handled); + delete msg; + return true; + } + + // Mock methods for handling output IPC messages. + MOCK_METHOD1(OnInitializeDone, + void(const GpuVideoDecoderInitDoneParam& param)); + MOCK_METHOD0(OnUninitializeDone, void()); + MOCK_METHOD0(OnFlushDone, void()); + MOCK_METHOD0(OnEmptyThisBufferDone, void()); + MOCK_METHOD4(OnConsumeVideoFrame, void(int32 device_frame_id, int64 timestamp, + int64 duration, int32 flags)); + MOCK_METHOD0(OnEmptyThisBufferACK, void()); + MOCK_METHOD4(OnAllocateVideoFrames, void(int32 n, uint32 width, + uint32 height, int32 format)); + MOCK_METHOD0(OnReleaseAllVideoFrames, void()); + + // Receive events from GpuVideoDecoder. + MOCK_METHOD0(VideoFramesAllocated, void()); + + void Initialize() { + // VideoDecodeEngine is called. + EXPECT_CALL(*mock_engine_, Initialize(_, _, _, _)) + .WillOnce(InitializationDone(gpu_video_decoder_)); + + // Expect that initialization is completed. + EXPECT_CALL(*this, OnInitializeDone(_)); + + // Send an initialiaze message to GpuVideoDecoder. + GpuVideoDecoderInitParam param; + param.width = kWidth; + param.height = kHeight; + + GpuVideoDecoderMsg_Initialize msg(0, param); + gpu_video_decoder_->OnMessageReceived(msg); + } + + void AllocateVideoFrames() { + // Expect that IPC messages are sent. We'll reply with some GL textures. + EXPECT_CALL(*this, OnAllocateVideoFrames( + 1, kWidth, kHeight, static_cast(media::VideoFrame::RGBA))) + .WillOnce(SendVideoFrameAllocated(gpu_video_decoder_)); + + // Expect that MakeCurrent() is called. + EXPECT_CALL(*gles2_decoder_.get(), MakeCurrent()) + .WillOnce(Return(true)) + .RetiresOnSaturation(); + + // Expect that translate method is called. + EXPECT_CALL(*gles2_decoder_.get(), + GetServiceTextureId(kClientTexture, NotNull())) + .WillOnce(DoAll(SetArgumentPointee<1>(kServiceTexture), Return(true))); + + // And then GpuVideoDevice is called to create VideoFrame from GL textures. + EXPECT_CALL(*mock_device_, + CreateVideoFrameFromGlTextures(kWidth, kHeight, + media::VideoFrame::RGBA, _, + NotNull())) + .WillOnce(DoAll(SetArgumentPointee<4>(device_frame_), Return(true))); + + // Finally the task is called. + EXPECT_CALL(*this, VideoFramesAllocated()); + + // Pretend calling GpuVideoDecoder for allocating frames. + gpu_video_decoder_->AllocateVideoFrames( + 1, kWidth, kHeight, media::VideoFrame::RGBA, &decoder_frames_, + NewRunnableMethod(this, &GpuVideoDecoderTest::VideoFramesAllocated)); + } + + void ReleaseVideoFrames() { + // Expect that MakeCurrent() is called. + EXPECT_CALL(*gles2_decoder_.get(), MakeCurrent()) + .WillOnce(Return(true)) + .RetiresOnSaturation(); + + // Expect that video frame is released. + EXPECT_CALL(*mock_device_, ReleaseVideoFrame(device_frame_)); + + // Expect that IPC message is send to release video frame. + EXPECT_CALL(*this, OnReleaseAllVideoFrames()); + + // Call to GpuVideoDecoder to release all video frames. + gpu_video_decoder_->ReleaseAllVideoFrames(); + } + + void BufferExchange() { + // Expect that we call to produce video frame. + EXPECT_CALL(*mock_engine_, ProduceVideoFrame(device_frame_)) + .WillOnce(SendConsumeVideoFrame(gpu_video_decoder_, device_frame_)) + .RetiresOnSaturation(); + + // Expect that consume video frame is called. + EXPECT_CALL(*this, OnConsumeVideoFrame(kFrameId, 0, 0, 0)) + .RetiresOnSaturation(); + + // Ask the GpuVideoDecoder to produce a video frame. + GpuVideoDecoderMsg_ProduceVideoFrame msg(0, kFrameId); + gpu_video_decoder_->OnMessageReceived(msg); + } + + private: + scoped_refptr gpu_video_decoder_; + MockGpuVideoDevice* mock_device_; + media::MockVideoDecodeEngine* mock_engine_; + scoped_ptr gles2_decoder_; + std::vector > decoder_frames_; + scoped_refptr device_frame_; + + MessageLoop message_loop_; + + DISALLOW_COPY_AND_ASSIGN(GpuVideoDecoderTest); +}; + +TEST_F(GpuVideoDecoderTest, Initialize) { + Initialize(); +} + +TEST_F(GpuVideoDecoderTest, AllocateVideoFrames) { + Initialize(); + AllocateVideoFrames(); +} + +TEST_F(GpuVideoDecoderTest, ReleaseVideoFrames) { + Initialize(); + AllocateVideoFrames(); + ReleaseVideoFrames(); +} + +TEST_F(GpuVideoDecoderTest, BufferExchange) { + Initialize(); + AllocateVideoFrames(); + BufferExchange(); + BufferExchange(); + ReleaseVideoFrames(); +} + +DISABLE_RUNNABLE_METHOD_REFCOUNT(GpuVideoDecoderTest); diff --git a/content/common/gpu/gpu_video_service.cc b/content/common/gpu/gpu_video_service.cc new file mode 100644 index 0000000..3128534 --- /dev/null +++ b/content/common/gpu/gpu_video_service.cc @@ -0,0 +1,82 @@ +// Copyright (c) 2011 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 "content/common/gpu/gpu_channel.h" +#include "content/common/gpu/gpu_video_decoder.h" +#include "content/common/gpu/gpu_video_service.h" +#include "content/common/gpu_messages.h" + +struct GpuVideoService::GpuVideoDecoderInfo { + scoped_refptr decoder; + GpuChannel* channel; +}; + + +GpuVideoService::GpuVideoService() { + // TODO(jiesun): move this time consuming stuff out of here. + IntializeGpuVideoService(); +} + +GpuVideoService::~GpuVideoService() { + // TODO(jiesun): move this time consuming stuff out of here. + UnintializeGpuVideoService(); +} + +// static +GpuVideoService* GpuVideoService::GetInstance() { + return Singleton::get(); +} + +void GpuVideoService::OnChannelConnected(int32 peer_pid) { + LOG(ERROR) << "GpuVideoService::OnChannelConnected"; +} + +void GpuVideoService::OnChannelError() { + LOG(ERROR) << "GpuVideoService::OnChannelError"; +} + +bool GpuVideoService::OnMessageReceived(const IPC::Message& msg) { +#if 0 + IPC_BEGIN_MESSAGE_MAP(GpuVideoService, msg) + IPC_MESSAGE_UNHANDLED_ERROR() + IPC_END_MESSAGE_MAP() +#endif + return false; +} + +bool GpuVideoService::IntializeGpuVideoService() { + return true; +} + +bool GpuVideoService::UnintializeGpuVideoService() { + return true; +} + +bool GpuVideoService::CreateVideoDecoder( + GpuChannel* channel, + MessageRouter* router, + int32 decoder_host_id, + int32 decoder_id, + gpu::gles2::GLES2Decoder* gles2_decoder) { + GpuVideoDecoderInfo decoder_info; + decoder_info.decoder = new GpuVideoDecoder(MessageLoop::current(), + decoder_host_id, + channel, + channel->renderer_process(), + gles2_decoder); + decoder_info.channel = channel; + decoder_map_[decoder_id] = decoder_info; + router->AddRoute(decoder_id, decoder_info.decoder); + + channel->Send(new GpuVideoDecoderHostMsg_CreateVideoDecoderDone( + decoder_host_id, decoder_id)); + return true; +} + +void GpuVideoService::DestroyVideoDecoder( + MessageRouter* router, + int32 decoder_id) { + router->RemoveRoute(decoder_id); + decoder_map_.erase(decoder_id); +} diff --git a/content/common/gpu/gpu_video_service.h b/content/common/gpu/gpu_video_service.h new file mode 100644 index 0000000..8c39db3 --- /dev/null +++ b/content/common/gpu/gpu_video_service.h @@ -0,0 +1,51 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_COMMON_GPU_GPU_VIDEO_SERVICE_H_ +#define CONTENT_COMMON_GPU_GPU_VIDEO_SERVICE_H_ + +#include + +#include "base/memory/ref_counted.h" +#include "base/memory/singleton.h" +#include "content/common/gpu/gpu_video_decoder.h" +#include "ipc/ipc_channel.h" + +class GpuChannel; + +class GpuVideoService : public IPC::Channel::Listener { + public: + static GpuVideoService* GetInstance(); + + // IPC::Channel::Listener. + virtual void OnChannelConnected(int32 peer_pid); + virtual void OnChannelError(); + virtual bool OnMessageReceived(const IPC::Message& message); + + // TODO(hclam): Remove return value. + bool CreateVideoDecoder(GpuChannel* channel, + MessageRouter* router, + int32 decoder_host_id, + int32 decoder_id, + gpu::gles2::GLES2Decoder* gles2_decoder); + void DestroyVideoDecoder(MessageRouter* router, + int32 decoder_id); + + private: + struct GpuVideoDecoderInfo; + + GpuVideoService(); + virtual ~GpuVideoService(); + + std::map decoder_map_; + + // Specialize video service on different platform will override. + virtual bool IntializeGpuVideoService(); + virtual bool UnintializeGpuVideoService(); + + friend struct DefaultSingletonTraits; + DISALLOW_COPY_AND_ASSIGN(GpuVideoService); +}; + +#endif // CONTENT_COMMON_GPU_GPU_VIDEO_SERVICE_H_ diff --git a/content/common/gpu/media/fake_gl_video_decode_engine.cc b/content/common/gpu/media/fake_gl_video_decode_engine.cc new file mode 100644 index 0000000..02fa4fb --- /dev/null +++ b/content/common/gpu/media/fake_gl_video_decode_engine.cc @@ -0,0 +1,132 @@ +// Copyright (c) 2011 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 "content/common/gpu/media/fake_gl_video_decode_engine.h" + +#include "media/base/limits.h" +#include "media/base/video_frame.h" +#include "media/video/video_decode_context.h" + +FakeGlVideoDecodeEngine::FakeGlVideoDecodeEngine() + : width_(0), + height_(0), + handler_(NULL), + context_(NULL) { +} + +FakeGlVideoDecodeEngine::~FakeGlVideoDecodeEngine() { +} + +void FakeGlVideoDecodeEngine::Initialize( + MessageLoop* message_loop, + media::VideoDecodeEngine::EventHandler* event_handler, + media::VideoDecodeContext* context, + const media::VideoCodecConfig& config) { + handler_ = event_handler; + context_ = context; + width_ = config.width(); + height_ = config.height(); + + // Create an internal VideoFrame that we can write to. This is going to be + // uploaded through VideoDecodeContext. + media::VideoFrame::CreateFrame( + media::VideoFrame::RGBA, width_, height_, base::TimeDelta(), + base::TimeDelta(), &internal_frame_); + memset(internal_frame_->data(media::VideoFrame::kRGBPlane), 0, + height_ * internal_frame_->stride(media::VideoFrame::kRGBPlane)); + + // Use VideoDecodeContext to allocate VideoFrame that can be consumed by + // external body. + // TODO(hclam): It is horrible to use constants everywhere in the code! + // The number of frames come from VideoRendererBase in the renderer, this is + // horrible! + context_->AllocateVideoFrames( + media::Limits::kMaxVideoFrames, width_, height_, media::VideoFrame::RGBA, + &external_frames_, + NewRunnableMethod(this, + &FakeGlVideoDecodeEngine::AllocationCompleteTask)); +} + +void FakeGlVideoDecodeEngine::AllocationCompleteTask() { + DCHECK(media::Limits::kMaxVideoFrames == external_frames_.size()); + DCHECK_EQ(media::VideoFrame::TYPE_GL_TEXTURE, external_frames_[0]->type()); + + media::VideoCodecInfo info; + info.success = true; + info.provides_buffers = true; + info.stream_info.surface_format = media::VideoFrame::RGBA; + info.stream_info.surface_type = media::VideoFrame::TYPE_GL_TEXTURE; + info.stream_info.surface_width = width_; + info.stream_info.surface_height = height_; + handler_->OnInitializeComplete(info); +} + +void FakeGlVideoDecodeEngine::Uninitialize() { + handler_->OnUninitializeComplete(); +} + +void FakeGlVideoDecodeEngine::Flush() { + handler_->OnFlushComplete(); +} + +void FakeGlVideoDecodeEngine::Seek() { + // TODO(hclam): This is a big hack to continue playing because we need to + // *push* decoded frames to downstream. The model used in VideoRendererBase + // to wait for *push* is flawed. + for (size_t i = 0; i < external_frames_.size(); ++i) + handler_->ConsumeVideoFrame(external_frames_[i], dummy_stats_); + handler_->OnSeekComplete(); +} + +void FakeGlVideoDecodeEngine::ConsumeVideoSample( + scoped_refptr sample) { + DCHECK(!pending_frames_.empty()); + scoped_refptr frame = pending_frames_.front(); + pending_frames_.pop(); + + frame->SetDuration(sample->GetDuration()); + frame->SetTimestamp(sample->GetTimestamp()); + + // Generate a pattern to the internal frame and then uploads it. + int size = width_ * height_ * 4; + scoped_array buffer(new uint8[size]); + memset(buffer.get(), 255, size); + + uint8* row = internal_frame_->data(media::VideoFrame::kRGBPlane); + static int seed = 0; + + for (int y = 0; y < height_; ++y) { + int offset = y % 3; + for (int x = 0; x < width_; ++x) { + row[x * 4 + offset + 1] = seed++; + seed &= 255; + } + row += width_ * 4; + } + ++seed; + + // After we have filled the content upload the internal frame to the + // VideoFrame allocated through VideoDecodeContext. + context_->ConvertToVideoFrame( + internal_frame_, frame, + NewRunnableMethod(this, &FakeGlVideoDecodeEngine::UploadCompleteTask, + frame)); +} + +void FakeGlVideoDecodeEngine::ProduceVideoFrame( + scoped_refptr frame) { + // Enqueue the frame to the pending queue. + pending_frames_.push(frame); + + // Fake that we need some buffer. + handler_->ProduceVideoSample(NULL); +} + +void FakeGlVideoDecodeEngine::UploadCompleteTask( + scoped_refptr frame) { + // |frame| is the upload target. We can immediately send this frame out. + handler_->ConsumeVideoFrame(frame, dummy_stats_); +} + +DISABLE_RUNNABLE_METHOD_REFCOUNT(FakeGlVideoDecodeEngine); diff --git a/content/common/gpu/media/fake_gl_video_decode_engine.h b/content/common/gpu/media/fake_gl_video_decode_engine.h new file mode 100644 index 0000000..899c84f --- /dev/null +++ b/content/common/gpu/media/fake_gl_video_decode_engine.h @@ -0,0 +1,68 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_GPU_MEDIA_FAKE_GL_VIDEO_DECODE_ENGINE_H_ +#define CONTENT_GPU_MEDIA_FAKE_GL_VIDEO_DECODE_ENGINE_H_ + +#include +#include + +#include "base/memory/scoped_ptr.h" +#include "media/base/pipeline.h" +#include "media/video/video_decode_engine.h" + +namespace media { +class VideoDecodeContext; +class VideoFrame; +} // namespace media + +class FakeGlVideoDecodeEngine : public media::VideoDecodeEngine { + public: + FakeGlVideoDecodeEngine(); + virtual ~FakeGlVideoDecodeEngine(); + + virtual void Initialize( + MessageLoop* message_loop, + media::VideoDecodeEngine::EventHandler* event_handler, + media::VideoDecodeContext* context, + const media::VideoCodecConfig& config); + + virtual void Uninitialize(); + virtual void Flush(); + virtual void Seek(); + virtual void ConsumeVideoSample(scoped_refptr buffer); + virtual void ProduceVideoFrame(scoped_refptr frame); + + private: + // This method is called when video frames allocation is completed by + // VideoDecodeContext. + void AllocationCompleteTask(); + + // This method is called by VideoDecodeContext when uploading to a VideoFrame + // has completed. + void UploadCompleteTask(scoped_refptr frame); + + int width_; + int height_; + media::VideoDecodeEngine::EventHandler* handler_; + media::VideoDecodeContext* context_; + + // Internal video frame that is to be uploaded through VideoDecodeContext. + scoped_refptr internal_frame_; + + // VideoFrame(s) allocated through VideoDecodeContext. These frames are + // opaque to us. And we need an extra upload step. + std::vector > external_frames_; + + // These are the video frames that are waiting for input buffer to generate + // fake pattern in them. + std::queue > pending_frames_; + + // Dummy statistics. + media::PipelineStatistics dummy_stats_; + + DISALLOW_COPY_AND_ASSIGN(FakeGlVideoDecodeEngine); +}; + +#endif // CONTENT_GPU_MEDIA_FAKE_GL_VIDEO_DECODE_ENGINE_H_ diff --git a/content/common/gpu/media/fake_gl_video_device.cc b/content/common/gpu/media/fake_gl_video_device.cc new file mode 100644 index 0000000..172b701 --- /dev/null +++ b/content/common/gpu/media/fake_gl_video_device.cc @@ -0,0 +1,58 @@ +// Copyright (c) 2011 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 "content/common/gpu/media/fake_gl_video_device.h" + +#include "media/base/video_frame.h" +#include "ui/gfx/gl/gl_bindings.h" + +void* FakeGlVideoDevice::GetDevice() { + // No actual hardware device should be used. + return NULL; +} + +bool FakeGlVideoDevice::CreateVideoFrameFromGlTextures( + size_t width, size_t height, media::VideoFrame::Format format, + const std::vector& textures, + scoped_refptr* frame) { + media::VideoFrame::GlTexture texture_array[media::VideoFrame::kMaxPlanes]; + memset(texture_array, 0, sizeof(texture_array)); + + for (size_t i = 0; i < textures.size(); ++i) { + texture_array[i] = textures[i]; + } + + media::VideoFrame::CreateFrameGlTexture(format, + width, + height, + texture_array, + frame); + return *frame != NULL; +} + +void FakeGlVideoDevice::ReleaseVideoFrame( + const scoped_refptr& frame) { + // We didn't need to anything here because we didin't allocate any resources + // for the VideoFrame(s) generated. +} + +bool FakeGlVideoDevice::ConvertToVideoFrame( + void* buffer, scoped_refptr frame) { + // Assume we are in the right context and then upload the content to the + // texture. + glBindTexture(GL_TEXTURE_2D, + frame->gl_texture(media::VideoFrame::kRGBPlane)); + + // |buffer| is also a VideoFrame. + scoped_refptr frame_to_upload( + reinterpret_cast(buffer)); + DCHECK_EQ(frame->width(), frame_to_upload->width()); + DCHECK_EQ(frame->height(), frame_to_upload->height()); + DCHECK_EQ(frame->format(), frame_to_upload->format()); + glTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, frame_to_upload->width(), + frame_to_upload->height(), 0, GL_RGBA, + GL_UNSIGNED_BYTE, frame_to_upload->data(media::VideoFrame::kRGBPlane)); + return true; +} diff --git a/content/common/gpu/media/fake_gl_video_device.h b/content/common/gpu/media/fake_gl_video_device.h new file mode 100644 index 0000000..4f5233b --- /dev/null +++ b/content/common/gpu/media/fake_gl_video_device.h @@ -0,0 +1,27 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_GPU_MEDIA_FAKE_GL_VIDEO_DEVICE_H_ +#define CONTENT_GPU_MEDIA_FAKE_GL_VIDEO_DEVICE_H_ + +#include "content/common/gpu/media/gpu_video_device.h" + +// A simple GpuVideoDevice that create VideoFrame with GL textures. +// It uploads frames in RGBA format in system memory to the GL texture. +class FakeGlVideoDevice : public GpuVideoDevice { + public: + virtual ~FakeGlVideoDevice() {} + + virtual void* GetDevice(); + virtual bool CreateVideoFrameFromGlTextures( + size_t width, size_t height, media::VideoFrame::Format format, + const std::vector& textures, + scoped_refptr* frame); + virtual void ReleaseVideoFrame( + const scoped_refptr& frame); + virtual bool ConvertToVideoFrame(void* buffer, + scoped_refptr frame); +}; + +#endif // CONTENT_GPU_MEDIA_FAKE_GL_VIDEO_DEVICE_H_ diff --git a/content/common/gpu/media/gpu_video_device.h b/content/common/gpu/media/gpu_video_device.h new file mode 100644 index 0000000..dcba5f2 --- /dev/null +++ b/content/common/gpu/media/gpu_video_device.h @@ -0,0 +1,56 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_GPU_MEDIA_GPU_VIDEO_DEVICE_H_ +#define CONTENT_GPU_MEDIA_GPU_VIDEO_DEVICE_H_ + +#include + +#include "media/base/video_frame.h" +#include "media/video/video_decode_context.h" + +// A GpuVideoDevice is used by GpuVideoDecoder to allocate video frames +// meaningful to a corresponding VideoDecodeEngine. +// +// GpuVideoDecoder will provide a set of GL textures to this class and then +// GpuVideoDevice will transform the textures into a set of VideoFrame +// objects that can be used by VideoDecodeEngine. +// +// See text in GpuVideoDecoder for the overall flow for buffer allocation. +// +// Since all graphics commands execute on the main thread in the GPU process +// all the methods provided by this class are synchronous. +class GpuVideoDevice { + public: + virtual ~GpuVideoDevice() {} + + // Get the hardware video decoding device handle. + virtual void* GetDevice() = 0; + + // The following method is used by GpuVideoDecoder to create VideoFrame(s) + // associated with some GL textures. + // + // VideoFrame generated is used by VideoDecodeEngine for output buffer. + // + // |frame| will contain the VideoFrame generated. + // + // Return true if the operation was successful. + virtual bool CreateVideoFrameFromGlTextures( + size_t width, size_t height, media::VideoFrame::Format format, + const std::vector& textures, + scoped_refptr* frame) = 0; + + // Release VideoFrame generated. + virtual void ReleaseVideoFrame( + const scoped_refptr& frame) = 0; + + // Upload a device specific buffer to a VideoFrame object that can be used in + // the GPU process. + // + // Return true if successful. + virtual bool ConvertToVideoFrame(void* buffer, + scoped_refptr frame) = 0; +}; + +#endif // CONTENT_GPU_MEDIA_GPU_VIDEO_DEVICE_H_ diff --git a/content/common/gpu/media/mft_angle_video_device.cc b/content/common/gpu/media/mft_angle_video_device.cc new file mode 100644 index 0000000..a044e1aa --- /dev/null +++ b/content/common/gpu/media/mft_angle_video_device.cc @@ -0,0 +1,52 @@ +// Copyright (c) 2011 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 "content/common/gpu/media/mft_angle_video_device.h" + +#include + +#include "media/base/video_frame.h" +#include "third_party/angle/src/libGLESv2/main.h" + +MftAngleVideoDevice::MftAngleVideoDevice() + : device_(reinterpret_cast( + eglGetCurrentDisplay())->getDevice()) { +} + +void* MftAngleVideoDevice::GetDevice() { + return device_; +} + +bool MftAngleVideoDevice::CreateVideoFrameFromGlTextures( + size_t width, size_t height, media::VideoFrame::Format format, + const std::vector& textures, + scoped_refptr* frame) { + media::VideoFrame::GlTexture texture_array[media::VideoFrame::kMaxPlanes]; + memset(texture_array, 0, sizeof(texture_array)); + + for (size_t i = 0; i < textures.size(); ++i) { + texture_array[i] = textures[i]; + } + + media::VideoFrame::CreateFrameGlTexture(format, + width, + height, + texture_array, + frame); + return *frame != NULL; +} + +void MftAngleVideoDevice::ReleaseVideoFrame( + const scoped_refptr& frame) { + // We didn't need to anything here because we didn't allocate any resources + // for the VideoFrame(s) generated. +} + +bool MftAngleVideoDevice::ConvertToVideoFrame( + void* buffer, scoped_refptr frame) { + gl::Context* context = (gl::Context*)eglGetCurrentContext(); + // TODO(hclam): Connect ANGLE to upload the surface to texture when changes + // to ANGLE is done. + return true; +} diff --git a/content/common/gpu/media/mft_angle_video_device.h b/content/common/gpu/media/mft_angle_video_device.h new file mode 100644 index 0000000..8abe461 --- /dev/null +++ b/content/common/gpu/media/mft_angle_video_device.h @@ -0,0 +1,42 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_GPU_MEDIA_MFT_ANGLE_VIDEO_DEVICE_H_ +#define CONTENT_GPU_MEDIA_MFT_ANGLE_VIDEO_DEVICE_H_ + +#include "base/scoped_comptr_win.h" +#include "content/common/gpu/media/gpu_video_device.h" + +struct IDirect3DDevice9; +extern "C" const GUID IID_IDirect3DDevice9; + +namespace media { +class VideoFrame; +} // namespace media + +// This class is used to provide hardware video device, video frames and +// allow video frames to be uploaded to their final render target. +// +// This specifically serves MftH264DecodeEngine in the context of ANGLE. +class MftAngleVideoDevice : public GpuVideoDevice { + public: + MftAngleVideoDevice(); + virtual ~MftAngleVideoDevice() {} + + // GpuVideoDevice implementation. + virtual void* GetDevice(); + virtual bool CreateVideoFrameFromGlTextures( + size_t width, size_t height, media::VideoFrame::Format format, + const std::vector& textures, + scoped_refptr* frame); + virtual void ReleaseVideoFrame( + const scoped_refptr& frame); + virtual bool ConvertToVideoFrame(void* buffer, + scoped_refptr frame); + + private: + ScopedComPtr device_; +}; + +#endif // CONTENT_GPU_MEDIA_MFT_ANGLE_VIDEO_DEVICE_H_ diff --git a/content/common/gpu/x_util.cc b/content/common/gpu/x_util.cc new file mode 100644 index 0000000..486b00e --- /dev/null +++ b/content/common/gpu/x_util.cc @@ -0,0 +1,11 @@ +// Copyright (c) 2011 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 "content/common/gpu/x_util.h" + +#include + +void ScopedPtrXFree::operator()(void* x) const { + ::XFree(x); +} diff --git a/content/common/gpu/x_util.h b/content/common/gpu/x_util.h new file mode 100644 index 0000000..c6305c5 --- /dev/null +++ b/content/common/gpu/x_util.h @@ -0,0 +1,47 @@ +// Copyright (c) 2011 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. + +#ifndef CHROME_GPU_X_UTIL_H_ +#define CHROME_GPU_X_UTIL_H_ +#pragma once + +// Some X-Windows specific stuff. This can be included on any platform, and will +// be a NOP on non-Linux ones. + +#include "build/build_config.h" +#include "content/common/gpu/gpu_config.h" + +#if defined(OS_LINUX) + +// Forward declares ------------------------------------------------------------ +// +// X Windows headers do a lot of evil stuff, like "#define Status int" which +// will cause many problems when combined with our other header files (like +// ones that define a class local enum called "Status." +// +// These definitions are not Kosher, but allow us to remove this dependency and +// actually compile X at all. + +typedef unsigned long XID; + +extern "C" { + +typedef struct _XDisplay Display; +typedef struct __GLXcontextRec *GLXContext; + +} // extern "C" + +// Utils ----------------------------------------------------------------------- + +// scoped_ptr functor for XFree(). Use as follows: +// scoped_ptr_mallox foo(...); +// where "XVisualInfo" is any X type that is freed with XFree. +class ScopedPtrXFree { + public: + void operator()(void* x) const; +}; + +#endif // OS_LINUX + +#endif // CHROME_GPU_X_UTIL_H_ diff --git a/content/common/gpu_info.cc b/content/common/gpu_info.cc deleted file mode 100644 index 6b4d0a7..0000000 --- a/content/common/gpu_info.cc +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2011 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 "content/common/gpu_info.h" - -GPUInfo::GPUInfo() - : finalized(false), - vendor_id(0), - device_id(0), - can_lose_context(false) { -} - -GPUInfo::~GPUInfo() { } - -bool GPUInfo::Merge(const GPUInfo& other) { - if (device_id != other.device_id || vendor_id != other.vendor_id) { - *this = other; - return true; - } - - bool changed = false; - if (!finalized) { - finalized = other.finalized; - initialization_time = other.initialization_time; - if (driver_vendor.empty() && !other.driver_vendor.empty()) { - driver_vendor = other.driver_vendor; - changed = true; - } - if (driver_version.empty() && !other.driver_version.empty()) { - driver_version = other.driver_version; - changed = true; - } - if (driver_date.empty() && !other.driver_date.empty()) { - driver_date = other.driver_date; - changed = true; - } - if (pixel_shader_version.empty()) - pixel_shader_version = other.pixel_shader_version; - if (vertex_shader_version.empty()) - vertex_shader_version = other.vertex_shader_version; - if (gl_version.empty()) - gl_version = other.gl_version; - if (gl_version_string.empty()) - gl_version_string = other.gl_version_string; - if (gl_vendor.empty()) - gl_vendor = other.gl_vendor; - if (gl_renderer.empty() && !other.gl_renderer.empty()) { - gl_renderer = other.gl_renderer; - changed = true; - } - if (gl_extensions.empty()) - gl_extensions = other.gl_extensions; - can_lose_context = other.can_lose_context; -#if defined(OS_WIN) - if (dx_diagnostics.values.size() == 0 && - dx_diagnostics.children.size() == 0) - dx_diagnostics = other.dx_diagnostics; -#endif - } - return changed; -} - diff --git a/content/common/gpu_info.h b/content/common/gpu_info.h deleted file mode 100644 index 402535e..0000000 --- a/content/common/gpu_info.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef CONTENT_COMMON_GPU_INFO_H_ -#define CONTENT_COMMON_GPU_INFO_H_ -#pragma once - -// Provides access to the GPU information for the system -// on which chrome is currently running. - -#include - -#include "base/basictypes.h" -#include "base/time.h" -#include "build/build_config.h" -#include "content/common/dx_diag_node.h" - -struct GPUInfo { - GPUInfo(); - ~GPUInfo(); - - // If it's the same GPU, i.e., device id and vendor id are the same, then - // copy over the fields that are not set yet and ignore the rest. - // If it's a different GPU, then reset and copy over everything. - // Return true if something changes that may affect blacklisting; currently - // they are device_id, vendor_id, driver_vendor, driver_version, driver_date, - // and gl_renderer. - bool Merge(const GPUInfo& other); - - // Whether more GPUInfo fields might be collected in the future. - bool finalized; - - // The amount of time taken to get from the process starting to the message - // loop being pumped. - base::TimeDelta initialization_time; - - // The DWORD (uint32) representing the graphics card vendor id. - uint32 vendor_id; - - // The DWORD (uint32) representing the graphics card device id. Device ids - // are unique to vendor, not to one another. - uint32 device_id; - - // The vendor of the graphics driver currently installed. - std::string driver_vendor; - - // The version of the graphics driver currently installed. - std::string driver_version; - - // The date of the graphics driver currently installed. - std::string driver_date; - - // The version of the pixel/fragment shader used by the gpu. - std::string pixel_shader_version; - - // The version of the vertex shader used by the gpu. - std::string vertex_shader_version; - - // The version of OpenGL we are using. - // TODO(zmo): should be able to tell if it's GL or GLES. - std::string gl_version; - - // The GL_VERSION string. "" if we are not using OpenGL. - std::string gl_version_string; - - // The GL_VENDOR string. "" if we are not using OpenGL. - std::string gl_vendor; - - // The GL_RENDERER string. "" if we are not using OpenGL. - std::string gl_renderer; - - // The GL_EXTENSIONS string. "" if we are not using OpenGL. - std::string gl_extensions; - - // The device semantics, i.e. whether the Vista and Windows 7 specific - // semantics are available. - bool can_lose_context; - -#if defined(OS_WIN) - // The information returned by the DirectX Diagnostics Tool. - DxDiagNode dx_diagnostics; -#endif -}; - -#endif // CONTENT_COMMON_GPU_INFO_H_ diff --git a/content/common/gpu_info_unittest.cc b/content/common/gpu_info_unittest.cc deleted file mode 100644 index 34f0ee6..0000000 --- a/content/common/gpu_info_unittest.cc +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2010 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 "content/common/gpu_info.h" -#include "testing/gtest/include/gtest/gtest.h" - -// Test that an empty GPUInfo has valid members -TEST(GPUInfoBasicTest, EmptyGPUInfo) { - GPUInfo gpu_info; - EXPECT_EQ(gpu_info.finalized, false); - EXPECT_EQ(gpu_info.initialization_time.ToInternalValue(), 0); - EXPECT_EQ(gpu_info.vendor_id, 0u); - EXPECT_EQ(gpu_info.device_id, 0u); - EXPECT_EQ(gpu_info.driver_vendor, ""); - EXPECT_EQ(gpu_info.driver_version, ""); - EXPECT_EQ(gpu_info.driver_date, ""); - EXPECT_EQ(gpu_info.pixel_shader_version, ""); - EXPECT_EQ(gpu_info.vertex_shader_version, ""); - EXPECT_EQ(gpu_info.gl_version, ""); - EXPECT_EQ(gpu_info.gl_version_string, ""); - EXPECT_EQ(gpu_info.gl_vendor, ""); - EXPECT_EQ(gpu_info.gl_renderer, ""); - EXPECT_EQ(gpu_info.gl_extensions, ""); - EXPECT_EQ(gpu_info.can_lose_context, false); -} diff --git a/content/common/gpu_messages.h b/content/common/gpu_messages.h index 5a188c4..6a8dc4f 100644 --- a/content/common/gpu_messages.h +++ b/content/common/gpu_messages.h @@ -8,7 +8,7 @@ #include "base/shared_memory.h" #include "content/common/common_param_traits.h" -#include "content/common/gpu_info.h" +#include "content/common/gpu/gpu_info.h" #include "content/common/gpu_process_launch_causes.h" #include "gpu/command_buffer/common/command_buffer.h" #include "gpu/ipc/gpu_command_buffer_traits.h" diff --git a/content/content_common.gypi b/content/content_common.gypi index a8e4def..2c0b552 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -13,6 +13,7 @@ '../third_party/icu/icu.gyp:icuuc', '../third_party/npapi/npapi.gyp:npapi', '../third_party/WebKit/Source/WebKit/chromium/WebKit.gyp:webkit', + '../ui/gfx/gl/gl.gyp:gl', '../webkit/support/webkit_support.gyp:appcache', '../webkit/support/webkit_support.gyp:blob', '../webkit/support/webkit_support.gyp:database', @@ -98,8 +99,25 @@ 'common/geolocation_messages.h', 'common/geoposition.cc', 'common/geoposition.h', - 'common/gpu_info.cc', - 'common/gpu_info.h', + 'common/gpu/content_gpu_client.h', + 'common/gpu/gpu_channel.cc', + 'common/gpu/gpu_channel.h', + 'common/gpu/gpu_channel_manager.cc', + 'common/gpu/gpu_channel_manager.h', + 'common/gpu/gpu_command_buffer_stub.cc', + 'common/gpu/gpu_command_buffer_stub.h', + 'common/gpu/gpu_config.h', + 'common/gpu/gpu_info.cc', + 'common/gpu/gpu_info.h', + 'common/gpu/gpu_video_decoder.cc', + 'common/gpu/gpu_video_decoder.h', + 'common/gpu/gpu_video_service.cc', + 'common/gpu/gpu_video_service.h', + 'common/gpu/media/gpu_video_device.h', + 'common/gpu/media/fake_gl_video_decode_engine.cc', + 'common/gpu/media/fake_gl_video_decode_engine.h', + 'common/gpu/media/fake_gl_video_device.cc', + 'common/gpu/media/fake_gl_video_device.h', 'common/gpu_process_launch_causes.h', 'common/gpu_messages.h', 'common/hi_res_timer_manager_posix.cc', @@ -195,6 +213,20 @@ 'conditions': [ ['OS=="win"', { 'msvs_guid': '062E9260-304A-4657-A74C-0D3AA1A0A0A4', + 'sources': [ + 'common/gpu/media/mft_angle_video_device.cc', + 'common/gpu/media/mft_angle_video_device.h', + ], + 'include_dirs': [ + '<(DEPTH)/third_party/angle/include', + '<(DEPTH)/third_party/angle/src', + '<(DEPTH)/third_party/wtl/include', + '$(DXSDK_DIR)/include', + ], + 'dependencies': [ + '../third_party/angle/src/build_angle.gyp:libEGL', + '../third_party/angle/src/build_angle.gyp:libGLESv2', + ], }], ['OS!="linux"', { 'sources!': [ @@ -221,11 +253,22 @@ '../build/linux/system.gyp:gtk', ], }], + ['OS=="linux" and target_arch!="arm"', { + 'sources': [ + 'common/gpu/x_util.cc', + 'common/gpu/x_util.h', + ], + }], ['toolkit_views==1', { 'sources': [ 'common/native_web_keyboard_event_views.cc', ], }], + ['enable_gpu==1', { + 'dependencies': [ + '../gpu/gpu.gyp:command_buffer_service', + ], + }], ], }, ], diff --git a/content/content_gpu.gypi b/content/content_gpu.gypi index cebb9ec..ffa7c4c 100644 --- a/content/content_gpu.gypi +++ b/content/content_gpu.gypi @@ -14,17 +14,10 @@ 'dependencies': [ 'content_common', '../base/base.gyp:base', - '../media/media.gyp:media', '../skia/skia.gyp:skia', '../ui/gfx/gl/gl.gyp:gl', ], 'sources': [ - 'gpu/content_gpu_client.h', - 'gpu/gpu_channel.cc', - 'gpu/gpu_channel.h', - 'gpu/gpu_command_buffer_stub.cc', - 'gpu/gpu_command_buffer_stub.h', - 'gpu/gpu_config.h', 'gpu/gpu_dx_diagnostics_win.cc', 'gpu/gpu_info_collector_linux.cc', 'gpu/gpu_info_collector_mac.mm', @@ -36,19 +29,8 @@ 'gpu/gpu_process.h', 'gpu/gpu_child_thread.cc', 'gpu/gpu_child_thread.h', - 'gpu/gpu_render_thread.cc', - 'gpu/gpu_render_thread.h', - 'gpu/gpu_video_decoder.cc', - 'gpu/gpu_video_decoder.h', - 'gpu/gpu_video_service.cc', - 'gpu/gpu_video_service.h', 'gpu/gpu_watchdog_thread.cc', 'gpu/gpu_watchdog_thread.h', - 'gpu/media/gpu_video_device.h', - 'gpu/media/fake_gl_video_decode_engine.cc', - 'gpu/media/fake_gl_video_decode_engine.h', - 'gpu/media/fake_gl_video_device.cc', - 'gpu/media/fake_gl_video_device.h', 'gpu/transport_texture.cc', 'gpu/transport_texture.h', ], @@ -111,21 +93,6 @@ ], }, ], - 'sources': [ - 'gpu/media/mft_angle_video_device.cc', - 'gpu/media/mft_angle_video_device.h', - ], - }], - ['OS=="linux" and target_arch!="arm"', { - 'sources': [ - 'gpu/x_util.cc', - 'gpu/x_util.h', - ], - }], - ['enable_gpu==1', { - 'dependencies': [ - '../gpu/gpu.gyp:command_buffer_service', - ], }], ], }, diff --git a/content/gpu/content_gpu_client.h b/content/gpu/content_gpu_client.h deleted file mode 100644 index e87f90b..0000000 --- a/content/gpu/content_gpu_client.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef CONTENT_GPU_CONTENT_GPU_CLIENT_H_ -#define CONTENT_GPU_CONTENT_GPU_CLIENT_H_ -#pragma once - -#include "content/common/content_client.h" - -struct GPUInfo; - -namespace content { - -// Embedder API for participating in plugin logic. -class ContentGpuClient { - public: - // Sets the data on the gpu to send along with crash reports. - virtual void SetGpuInfo(const GPUInfo& gpu_info) {} -}; - -} // namespace content - -#endif // CONTENT_GPU_CONTENT_GPU_CLIENT_H_ diff --git a/content/gpu/gpu_channel.cc b/content/gpu/gpu_channel.cc deleted file mode 100644 index b81f9868..0000000 --- a/content/gpu/gpu_channel.cc +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright (c) 2011 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. - -#if defined(OS_WIN) -#include -#endif - -#include "content/gpu/gpu_channel.h" - -#include "base/command_line.h" -#include "base/process_util.h" -#include "base/string_util.h" -#include "content/common/child_process.h" -#include "content/common/content_client.h" -#include "content/common/content_switches.h" -#include "content/common/gpu_messages.h" -#include "content/gpu/gpu_render_thread.h" -#include "content/gpu/gpu_video_service.h" -#include "content/gpu/transport_texture.h" - -#if defined(OS_POSIX) -#include "ipc/ipc_channel_posix.h" -#endif - -GpuChannel::GpuChannel(GpuRenderThread* gpu_render_thread, - GpuWatchdogThread* gpu_watchdog_thread, - int renderer_id) - : gpu_render_thread_(gpu_render_thread), - renderer_id_(renderer_id), - renderer_process_(base::kNullProcessHandle), - renderer_pid_(base::kNullProcessId), - watchdog_thread_(gpu_watchdog_thread) { - DCHECK(gpu_render_thread); - DCHECK(renderer_id); - const CommandLine* command_line = CommandLine::ForCurrentProcess(); - log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); - disallowed_extensions_.multisampling = - command_line->HasSwitch(switches::kDisableGLMultisampling); -} - -GpuChannel::~GpuChannel() { -#if defined(OS_WIN) - if (renderer_process_) - CloseHandle(renderer_process_); -#endif -} - -bool GpuChannel::OnMessageReceived(const IPC::Message& message) { - if (log_messages_) { - VLOG(1) << "received message @" << &message << " on channel @" << this - << " with type " << message.type(); - } - - if (message.routing_id() == MSG_ROUTING_CONTROL) - return OnControlMessageReceived(message); - - if (!router_.RouteMessage(message)) { - // Respond to sync messages even if router failed to route. - if (message.is_sync()) { - IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); - reply->set_reply_error(); - Send(reply); - } - return false; - } - - return true; -} - -void GpuChannel::OnChannelError() { - gpu_render_thread_->RemoveChannel(renderer_id_); -} - -void GpuChannel::OnChannelConnected(int32 peer_pid) { - renderer_pid_ = peer_pid; -} - -bool GpuChannel::Send(IPC::Message* message) { - if (log_messages_) { - VLOG(1) << "sending message @" << message << " on channel @" << this - << " with type " << message->type(); - } - - if (!channel_.get()) { - delete message; - return false; - } - - return channel_->Send(message); -} - -void GpuChannel::CreateViewCommandBuffer( - gfx::PluginWindowHandle window, - int32 render_view_id, - const GPUCreateCommandBufferConfig& init_params, - int32* route_id) { - *route_id = MSG_ROUTING_NONE; - content::GetContentClient()->SetActiveURL(init_params.active_url); - -#if defined(ENABLE_GPU) - *route_id = GenerateRouteID(); - scoped_ptr stub(new GpuCommandBufferStub( - this, window, NULL, gfx::Size(), disallowed_extensions_, - init_params.allowed_extensions, - init_params.attribs, 0, *route_id, renderer_id_, render_view_id, - watchdog_thread_)); - router_.AddRoute(*route_id, stub.get()); - stubs_.AddWithID(stub.release(), *route_id); -#endif // ENABLE_GPU -} - -#if defined(OS_MACOSX) -void GpuChannel::AcceleratedSurfaceBuffersSwapped( - int32 route_id, uint64 swap_buffers_count) { - GpuCommandBufferStub* stub = stubs_.Lookup(route_id); - if (stub == NULL) - return; - stub->AcceleratedSurfaceBuffersSwapped(swap_buffers_count); -} - -void GpuChannel::DestroyCommandBufferByViewId(int32 render_view_id) { - // This responds to a message from the browser process to destroy the command - // buffer when the window with a GPUProcessor is closed (see - // RenderWidgetHostViewMac::DeallocFakePluginWindowHandle). Find the route id - // that matches the given render_view_id and delete the route. - for (StubMap::const_iterator iter(&stubs_); !iter.IsAtEnd(); iter.Advance()) { - if (iter.GetCurrentValue()->render_view_id() == render_view_id) { - OnDestroyCommandBuffer(iter.GetCurrentKey()); - return; - } - } -} -#endif - -TransportTexture* GpuChannel::GetTransportTexture(int32 route_id) { - return transport_textures_.Lookup(route_id); -} - -void GpuChannel::DestroyTransportTexture(int32 route_id) { - transport_textures_.Remove(route_id); - router_.RemoveRoute(route_id); -} - -bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg) - IPC_MESSAGE_HANDLER(GpuChannelMsg_Initialize, OnInitialize) - IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateOffscreenCommandBuffer, - OnCreateOffscreenCommandBuffer) - IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyCommandBuffer, - OnDestroyCommandBuffer) - IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateVideoDecoder, - OnCreateVideoDecoder) - IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyVideoDecoder, - OnDestroyVideoDecoder) - IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateTransportTexture, - OnCreateTransportTexture) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - DCHECK(handled); - return handled; -} - -int GpuChannel::GenerateRouteID() { - static int last_id = 0; - return ++last_id; -} - -void GpuChannel::OnInitialize(base::ProcessHandle renderer_process) { - // Initialize should only happen once. - DCHECK(!renderer_process_); - - // Verify that the renderer has passed its own process handle. - if (base::GetProcId(renderer_process) == renderer_pid_) - renderer_process_ = renderer_process; -} - -void GpuChannel::OnCreateOffscreenCommandBuffer( - int32 parent_route_id, - const gfx::Size& size, - const GPUCreateCommandBufferConfig& init_params, - uint32 parent_texture_id, - int32* route_id) { - content::GetContentClient()->SetActiveURL(init_params.active_url); -#if defined(ENABLE_GPU) - *route_id = GenerateRouteID(); - GpuCommandBufferStub* parent_stub = NULL; - if (parent_route_id != 0) - parent_stub = stubs_.Lookup(parent_route_id); - - scoped_ptr stub(new GpuCommandBufferStub( - this, - gfx::kNullPluginWindow, - parent_stub, - size, - disallowed_extensions_, - init_params.allowed_extensions, - init_params.attribs, - parent_texture_id, - *route_id, - 0, 0, watchdog_thread_)); - router_.AddRoute(*route_id, stub.get()); - stubs_.AddWithID(stub.release(), *route_id); -#else - *route_id = MSG_ROUTING_NONE; -#endif -} - -void GpuChannel::OnDestroyCommandBuffer(int32 route_id) { -#if defined(ENABLE_GPU) - if (router_.ResolveRoute(route_id)) { - router_.RemoveRoute(route_id); - stubs_.Remove(route_id); - } -#endif -} - -void GpuChannel::OnCreateVideoDecoder(int32 context_route_id, - int32 decoder_host_id) { -// TODO(cevans): do NOT re-enable this until GpuVideoService has been checked -// for integer overflows, including the classic "width * height" overflow. -#if 0 - VLOG(1) << "GpuChannel::OnCreateVideoDecoder"; - GpuVideoService* service = GpuVideoService::GetInstance(); - if (service == NULL) { - // TODO(hclam): Need to send a failure message. - return; - } - - // The context ID corresponds to the command buffer used. - GpuCommandBufferStub* stub = stubs_.Lookup(context_route_id); - int32 decoder_id = GenerateRouteID(); - - // TODO(hclam): Need to be careful about the lifetime of the command buffer - // decoder. - bool ret = service->CreateVideoDecoder( - this, &router_, decoder_host_id, decoder_id, - stub->processor()->decoder()); - DCHECK(ret) << "Failed to create a GpuVideoDecoder"; -#endif -} - -void GpuChannel::OnDestroyVideoDecoder(int32 decoder_id) { -#if defined(ENABLE_GPU) - GpuVideoService* service = GpuVideoService::GetInstance(); - if (service == NULL) - return; - service->DestroyVideoDecoder(&router_, decoder_id); -#endif -} - -void GpuChannel::OnCreateTransportTexture(int32 context_route_id, - int32 host_id) { -#if defined(ENABLE_GPU) - GpuCommandBufferStub* stub = stubs_.Lookup(context_route_id); - int32 route_id = GenerateRouteID(); - - scoped_ptr transport( - new TransportTexture(this, channel_.get(), stub->processor()->decoder(), - host_id, route_id)); - router_.AddRoute(route_id, transport.get()); - transport_textures_.AddWithID(transport.release(), route_id); - - IPC::Message* msg = new GpuTransportTextureHostMsg_TransportTextureCreated( - host_id, route_id); - Send(msg); -#endif -} - -bool GpuChannel::Init(MessageLoop* io_message_loop, - base::WaitableEvent* shutdown_event) { - // Check whether we're already initialized. - if (channel_.get()) - return true; - - // Map renderer ID to a (single) channel to that process. - std::string channel_name = GetChannelName(); - channel_.reset(new IPC::SyncChannel( - channel_name, - IPC::Channel::MODE_SERVER, - this, - io_message_loop, - false, - shutdown_event)); - - return true; -} - -std::string GpuChannel::GetChannelName() { - return StringPrintf("%d.r%d.gpu", base::GetCurrentProcId(), renderer_id_); -} - -#if defined(OS_POSIX) -int GpuChannel::GetRendererFileDescriptor() { - int fd = -1; - if (channel_.get()) { - fd = channel_->GetClientFileDescriptor(); - } - return fd; -} -#endif // defined(OS_POSIX) diff --git a/content/gpu/gpu_channel.h b/content/gpu/gpu_channel.h deleted file mode 100644 index 497e47c..0000000 --- a/content/gpu/gpu_channel.h +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef CONTENT_GPU_GPU_CHANNEL_H_ -#define CONTENT_GPU_GPU_CHANNEL_H_ -#pragma once - -#include -#include -#include - -#include "base/id_map.h" -#include "base/memory/scoped_ptr.h" -#include "base/process.h" -#include "build/build_config.h" -#include "content/common/message_router.h" -#include "content/gpu/gpu_command_buffer_stub.h" -#include "ipc/ipc_sync_channel.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/gfx/size.h" - -class GpuRenderThread; -class GpuWatchdogThread; -struct GPUCreateCommandBufferConfig; -class MessageLoop; -class TransportTexture; - -namespace base { -class WaitableEvent; -} - -// Encapsulates an IPC channel between the GPU process and one renderer -// process. On the renderer side there's a corresponding GpuChannelHost. -class GpuChannel : public IPC::Channel::Listener, - public IPC::Message::Sender, - public base::RefCountedThreadSafe { - public: - // Takes ownership of the renderer process handle. - GpuChannel(GpuRenderThread* gpu_render_thread, - GpuWatchdogThread* gpu_watchdog_thread, - int renderer_id); - virtual ~GpuChannel(); - - bool Init(MessageLoop* io_message_loop, base::WaitableEvent* shutdown_event); - - // Get the GpuThread that owns this channel. - GpuRenderThread* gpu_render_thread() const { return gpu_render_thread_; } - - // Returns the name of the associated IPC channel. - std::string GetChannelName(); - -#if defined(OS_POSIX) - int GetRendererFileDescriptor(); -#endif // defined(OS_POSIX) - - base::ProcessHandle renderer_process() const { - return renderer_process_; - } - - // IPC::Channel::Listener implementation: - virtual bool OnMessageReceived(const IPC::Message& msg); - virtual void OnChannelError(); - virtual void OnChannelConnected(int32 peer_pid); - - // IPC::Message::Sender implementation: - virtual bool Send(IPC::Message* msg); - - void CreateViewCommandBuffer( - gfx::PluginWindowHandle window, - int32 render_view_id, - const GPUCreateCommandBufferConfig& init_params, - int32* route_id); - -#if defined(OS_MACOSX) - virtual void AcceleratedSurfaceBuffersSwapped( - int32 route_id, uint64 swap_buffers_count); - void DestroyCommandBufferByViewId(int32 render_view_id); -#endif - - // Get the TransportTexture by ID. - TransportTexture* GetTransportTexture(int32 route_id); - - // Destroy the TransportTexture by ID. This method is only called by - // TransportTexture to delete and detach itself. - void DestroyTransportTexture(int32 route_id); - - private: - bool OnControlMessageReceived(const IPC::Message& msg); - - int GenerateRouteID(); - - // Message handlers. - void OnInitialize(base::ProcessHandle renderer_process); - void OnCreateOffscreenCommandBuffer( - int32 parent_route_id, - const gfx::Size& size, - const GPUCreateCommandBufferConfig& init_params, - uint32 parent_texture_id, - int32* route_id); - void OnDestroyCommandBuffer(int32 route_id); - void OnCreateVideoDecoder(int32 context_route_id, - int32 decoder_host_id); - void OnDestroyVideoDecoder(int32 decoder_id); - void OnCreateTransportTexture(int32 context_route_id, int32 host_id); - - // The lifetime of objects of this class is managed by a GpuRenderThread. The - // GpuRenderThreads destroy all the GpuChannels that they own when they - // are destroyed. So a raw pointer is safe. - GpuRenderThread* gpu_render_thread_; - - scoped_ptr channel_; - - // The id of the renderer who is on the other side of the channel. - int renderer_id_; - - // Handle to the renderer process that is on the other side of the channel. - base::ProcessHandle renderer_process_; - - // The process id of the renderer process. - base::ProcessId renderer_pid_; - - // Used to implement message routing functionality to CommandBuffer objects - MessageRouter router_; - -#if defined(ENABLE_GPU) - typedef IDMap StubMap; - StubMap stubs_; -#endif // defined (ENABLE_GPU) - - // A collection of transport textures created. - typedef IDMap TransportTextureMap; - TransportTextureMap transport_textures_; - - bool log_messages_; // True if we should log sent and received messages. - gpu::gles2::DisallowedExtensions disallowed_extensions_; - GpuWatchdogThread* watchdog_thread_; - - DISALLOW_COPY_AND_ASSIGN(GpuChannel); -}; - -#endif // CONTENT_GPU_GPU_CHANNEL_H_ diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc index 9597c0c..f0a8aad 100644 --- a/content/gpu/gpu_child_thread.cc +++ b/content/gpu/gpu_child_thread.cc @@ -13,8 +13,8 @@ #include "build/build_config.h" #include "chrome/common/chrome_switches.h" #include "content/common/child_process.h" +#include "content/common/gpu/content_gpu_client.h" #include "content/common/gpu_messages.h" -#include "content/gpu/content_gpu_client.h" #include "content/gpu/gpu_info_collector.h" #include "content/gpu/gpu_watchdog_thread.h" #include "ipc/ipc_channel_handle.h" @@ -110,7 +110,8 @@ bool GpuChildThread::OnControlMessageReceived(const IPC::Message& msg) { if (handled) return true; - return render_thread_.get() && render_thread_->OnMessageReceived(msg); + return gpu_channel_manager_.get() && + gpu_channel_manager_->OnMessageReceived(msg); } void GpuChildThread::OnInitialize() { @@ -187,7 +188,7 @@ void GpuChildThread::OnInitialize() { // Defer creation of the render thread. This is to prevent it from handling // IPC messages before the sandbox has been enabled and all other necessary // initialization has succeeded. - render_thread_.reset(new GpuRenderThread( + gpu_channel_manager_.reset(new GpuChannelManager( this, watchdog_thread_, ChildProcess::current()->io_message_loop(), diff --git a/content/gpu/gpu_child_thread.h b/content/gpu/gpu_child_thread.h index b488725..b8853fa 100644 --- a/content/gpu/gpu_child_thread.h +++ b/content/gpu/gpu_child_thread.h @@ -15,11 +15,11 @@ #include "base/time.h" #include "build/build_config.h" #include "content/common/child_thread.h" -#include "content/common/gpu_info.h" -#include "content/gpu/gpu_channel.h" -#include "content/gpu/gpu_config.h" -#include "content/gpu/gpu_render_thread.h" -#include "content/gpu/x_util.h" +#include "content/common/gpu/gpu_channel.h" +#include "content/common/gpu/gpu_channel_manager.h" +#include "content/common/gpu/gpu_config.h" +#include "content/common/gpu/gpu_info.h" +#include "content/common/gpu/x_util.h" #include "ui/gfx/native_widget_types.h" namespace IPC { @@ -34,7 +34,7 @@ class GpuWatchdogThread; // The main thread of the GPU child process. There will only ever be one of // these per process. It does process initialization and shutdown. It forwards -// IPC messages to GpuRenderThread, which is responsible for issuing rendering +// IPC messages to GpuChannelManager, which is responsible for issuing rendering // commands to the GPU. class GpuChildThread : public ChildThread { public: @@ -79,7 +79,7 @@ class GpuChildThread : public ChildThread { bool collecting_dx_diagnostics_; #endif - scoped_ptr render_thread_; + scoped_ptr gpu_channel_manager_; // Information about the GPU, such as device and vendor ID. GPUInfo gpu_info_; diff --git a/content/gpu/gpu_command_buffer_stub.cc b/content/gpu/gpu_command_buffer_stub.cc deleted file mode 100644 index 2d0ec51..0000000 --- a/content/gpu/gpu_command_buffer_stub.cc +++ /dev/null @@ -1,433 +0,0 @@ -// Copyright (c) 2011 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. - -#if defined(ENABLE_GPU) - -#include "base/process_util.h" -#include "base/shared_memory.h" -#include "build/build_config.h" -#include "content/common/gpu_messages.h" -#include "content/common/child_thread.h" -#include "content/gpu/gpu_channel.h" -#include "content/gpu/gpu_command_buffer_stub.h" -#include "content/gpu/gpu_render_thread.h" -#include "content/gpu/gpu_watchdog_thread.h" -#include "gpu/common/gpu_trace_event.h" - -#if defined(OS_WIN) -#include "base/win/wrapped_window_proc.h" -#endif - -using gpu::Buffer; - -#if defined(OS_WIN) -#define kCompositorWindowOwner L"CompositorWindowOwner" -#endif // defined(OS_WIN) - -GpuCommandBufferStub::GpuCommandBufferStub( - GpuChannel* channel, - gfx::PluginWindowHandle handle, - GpuCommandBufferStub* parent, - const gfx::Size& size, - const gpu::gles2::DisallowedExtensions& disallowed_extensions, - const std::string& allowed_extensions, - const std::vector& attribs, - uint32 parent_texture_id, - int32 route_id, - int32 renderer_id, - int32 render_view_id, - GpuWatchdogThread* gpu_watchdog_thread) - : channel_(channel), - handle_(handle), - parent_( - parent ? parent->AsWeakPtr() : base::WeakPtr()), - initial_size_(size), - disallowed_extensions_(disallowed_extensions), - allowed_extensions_(allowed_extensions), - requested_attribs_(attribs), - parent_texture_id_(parent_texture_id), - route_id_(route_id), -#if defined(OS_WIN) - compositor_window_(NULL), -#endif // defined(OS_WIN) - renderer_id_(renderer_id), - render_view_id_(render_view_id), - watchdog_thread_(gpu_watchdog_thread) { -} - -#if defined(OS_WIN) -static LRESULT CALLBACK CompositorWindowProc( - HWND hwnd, - UINT message, - WPARAM wparam, - LPARAM lparam) { - switch (message) { - case WM_ERASEBKGND: - return 0; - case WM_DESTROY: - RemoveProp(hwnd, kCompositorWindowOwner); - return 0; - case WM_PAINT: { - PAINTSTRUCT paint; - HDC dc = BeginPaint(hwnd, &paint); - if (dc) { - HANDLE h = GetProp(hwnd, kCompositorWindowOwner); - if (h) { - GpuCommandBufferStub* stub = - reinterpret_cast(h); - stub->OnCompositorWindowPainted(); - } - EndPaint(hwnd, &paint); - } - break; - } - default: - return DefWindowProc(hwnd, message, wparam, lparam); - } - return 0; -} - -bool GpuCommandBufferStub::CreateCompositorWindow() { - DCHECK(handle_ != gfx::kNullPluginWindow); - HWND host_window = static_cast(handle_); - - // Create the compositor window itself. - DCHECK(host_window); - static ATOM window_class = 0; - if (!window_class) { - WNDCLASSEX wcex; - wcex.cbSize = sizeof(wcex); - wcex.style = 0; - wcex.lpfnWndProc = base::win::WrappedWindowProc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = GetModuleHandle(NULL); - wcex.hIcon = 0; - wcex.hCursor = 0; - wcex.hbrBackground = NULL; - wcex.lpszMenuName = 0; - wcex.lpszClassName = L"CompositorWindowClass"; - wcex.hIconSm = 0; - window_class = RegisterClassEx(&wcex); - DCHECK(window_class); - } - - HWND compositor_window = CreateWindowEx( - WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, - MAKEINTATOM(window_class), - 0, - WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DISABLED, - 0, 0, - 0, 0, - host_window, - 0, - GetModuleHandle(NULL), - 0); - if (!compositor_window) { - compositor_window_ = gfx::kNullPluginWindow; - return false; - } - SetProp(compositor_window, kCompositorWindowOwner, - reinterpret_cast(this)); - - RECT parent_rect; - GetClientRect(host_window, &parent_rect); - - UINT flags = SWP_NOSENDCHANGING | SWP_NOCOPYBITS | SWP_NOZORDER | - SWP_NOACTIVATE | SWP_DEFERERASE | SWP_SHOWWINDOW; - SetWindowPos(compositor_window, - NULL, - 0, 0, - parent_rect.right - parent_rect.left, - parent_rect.bottom - parent_rect.top, - flags); - compositor_window_ = static_cast(compositor_window); - return true; -} - -void GpuCommandBufferStub::OnCompositorWindowPainted() { - GpuRenderThread* render_thread = channel_->gpu_render_thread(); - render_thread->Send(new GpuHostMsg_ScheduleComposite( - renderer_id_, render_view_id_)); -} -#endif // defined(OS_WIN) - - -GpuCommandBufferStub::~GpuCommandBufferStub() { - if (processor_.get()) { - processor_->Destroy(); - } -#if defined(OS_WIN) - if (compositor_window_) { - DestroyWindow(static_cast(compositor_window_)); - compositor_window_ = NULL; - } -#endif // defined(OS_WIN) - - GpuRenderThread* render_thread = channel_->gpu_render_thread(); - render_thread->Send(new GpuHostMsg_DestroyCommandBuffer( - handle_, renderer_id_, render_view_id_)); -} - -bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(GpuCommandBufferStub, message) - IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Initialize, OnInitialize); - IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_GetState, OnGetState); - IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_AsyncGetState, OnAsyncGetState); - IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Flush, OnFlush); - IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_AsyncFlush, OnAsyncFlush); - IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateTransferBuffer, - OnCreateTransferBuffer); - IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RegisterTransferBuffer, - OnRegisterTransferBuffer); - IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyTransferBuffer, - OnDestroyTransferBuffer); - IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_GetTransferBuffer, - OnGetTransferBuffer); - IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ResizeOffscreenFrameBuffer, - OnResizeOffscreenFrameBuffer); -#if defined(OS_MACOSX) - IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetWindowSize, OnSetWindowSize); -#endif // defined(OS_MACOSX) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - DCHECK(handled); - return handled; -} - -bool GpuCommandBufferStub::Send(IPC::Message* message) { - return channel_->Send(message); -} - -void GpuCommandBufferStub::OnInitialize( - base::SharedMemoryHandle ring_buffer, - int32 size, - bool* result) { - DCHECK(!command_buffer_.get()); - - *result = false; - - command_buffer_.reset(new gpu::CommandBufferService); - - // Create the child window, if needed -#if defined(OS_WIN) - gfx::PluginWindowHandle output_window_handle; - if (handle_) { - if (!CreateCompositorWindow()) { - return; - } - output_window_handle = compositor_window_; - } else { - output_window_handle = handle_; - } -#else - gfx::PluginWindowHandle output_window_handle = handle_; -#endif // defined(OS_WIN) - -#if defined(OS_WIN) - // Windows dups the shared memory handle it receives into the current process - // and closes it when this variable goes out of scope. - base::SharedMemory shared_memory(ring_buffer, - false, - channel_->renderer_process()); -#else - // POSIX receives a dup of the shared memory handle and closes the dup when - // this variable goes out of scope. - base::SharedMemory shared_memory(ring_buffer, false); -#endif - - // Initialize the CommandBufferService and GPUProcessor. - if (command_buffer_->Initialize(&shared_memory, size)) { - gpu::GPUProcessor* parent_processor = - parent_ ? parent_->processor_.get() : NULL; - processor_.reset(new gpu::GPUProcessor(command_buffer_.get(), NULL)); - if (processor_->Initialize( - output_window_handle, - initial_size_, - disallowed_extensions_, - allowed_extensions_.c_str(), - requested_attribs_, - parent_processor, - parent_texture_id_)) { - command_buffer_->SetPutOffsetChangeCallback( - NewCallback(processor_.get(), - &gpu::GPUProcessor::ProcessCommands)); - processor_->SetSwapBuffersCallback( - NewCallback(this, &GpuCommandBufferStub::OnSwapBuffers)); - if (watchdog_thread_) - processor_->SetCommandProcessedCallback( - NewCallback(this, &GpuCommandBufferStub::OnCommandProcessed)); - -#if defined(OS_MACOSX) - if (handle_) { - // This context conceptually puts its output directly on the - // screen, rendered by the accelerated plugin layer in - // RenderWidgetHostViewMac. Set up a pathway to notify the - // browser process when its contents change. - processor_->SetSwapBuffersCallback( - NewCallback(this, - &GpuCommandBufferStub::SwapBuffersCallback)); - } -#endif // defined(OS_MACOSX) - - // Set up a pathway for resizing the output window or framebuffer at the - // right time relative to other GL commands. - processor_->SetResizeCallback( - NewCallback(this, &GpuCommandBufferStub::ResizeCallback)); - - *result = true; - } else { - processor_.reset(); - command_buffer_.reset(); - } - } -} - -void GpuCommandBufferStub::OnCommandProcessed() { - if (watchdog_thread_) - watchdog_thread_->CheckArmed(); -} - -void GpuCommandBufferStub::OnGetState(gpu::CommandBuffer::State* state) { - *state = command_buffer_->GetState(); -} - -void GpuCommandBufferStub::OnAsyncGetState() { - gpu::CommandBuffer::State state = command_buffer_->GetState(); - Send(new GpuCommandBufferMsg_UpdateState(route_id_, state)); -} - -void GpuCommandBufferStub::OnFlush(int32 put_offset, - gpu::CommandBuffer::State* state) { - *state = command_buffer_->FlushSync(put_offset); -} - -void GpuCommandBufferStub::OnAsyncFlush(int32 put_offset) { - gpu::CommandBuffer::State state = command_buffer_->FlushSync(put_offset); - Send(new GpuCommandBufferMsg_UpdateState(route_id_, state)); -} - -void GpuCommandBufferStub::OnCreateTransferBuffer(int32 size, int32* id) { - *id = command_buffer_->CreateTransferBuffer(size); -} - -void GpuCommandBufferStub::OnRegisterTransferBuffer( - base::SharedMemoryHandle transfer_buffer, - size_t size, - int32* id) { -#if defined(OS_WIN) - // Windows dups the shared memory handle it receives into the current process - // and closes it when this variable goes out of scope. - base::SharedMemory shared_memory(transfer_buffer, - false, - channel_->renderer_process()); -#else - // POSIX receives a dup of the shared memory handle and closes the dup when - // this variable goes out of scope. - base::SharedMemory shared_memory(transfer_buffer, false); -#endif - - *id = command_buffer_->RegisterTransferBuffer(&shared_memory, size); -} - -void GpuCommandBufferStub::OnDestroyTransferBuffer(int32 id) { - command_buffer_->DestroyTransferBuffer(id); -} - -void GpuCommandBufferStub::OnGetTransferBuffer( - int32 id, - base::SharedMemoryHandle* transfer_buffer, - uint32* size) { - *transfer_buffer = base::SharedMemoryHandle(); - *size = 0; - - // Fail if the renderer process has not provided its process handle. - if (!channel_->renderer_process()) - return; - - Buffer buffer = command_buffer_->GetTransferBuffer(id); - if (buffer.shared_memory) { - // Assume service is responsible for duplicating the handle to the calling - // process. - buffer.shared_memory->ShareToProcess(channel_->renderer_process(), - transfer_buffer); - *size = buffer.size; - } -} - -void GpuCommandBufferStub::OnResizeOffscreenFrameBuffer(const gfx::Size& size) { - processor_->ResizeOffscreenFrameBuffer(size); -} - -void GpuCommandBufferStub::OnSwapBuffers() { - GPU_TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSwapBuffers"); - Send(new GpuCommandBufferMsg_SwapBuffers(route_id_)); -} - -#if defined(OS_MACOSX) -void GpuCommandBufferStub::OnSetWindowSize(const gfx::Size& size) { - GpuRenderThread* gpu_render_thread = channel_->gpu_render_thread(); - // Try using the IOSurface version first. - uint64 new_backing_store = processor_->SetWindowSizeForIOSurface(size); - if (new_backing_store) { - GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params; - params.renderer_id = renderer_id_; - params.render_view_id = render_view_id_; - params.window = handle_; - params.width = size.width(); - params.height = size.height(); - params.identifier = new_backing_store; - gpu_render_thread->Send( - new GpuHostMsg_AcceleratedSurfaceSetIOSurface(params)); - } else { - // TODO(kbr): figure out what to do here. It wouldn't be difficult - // to support the compositor on 10.5, but the performance would be - // questionable. - NOTREACHED(); - } -} - -void GpuCommandBufferStub::SwapBuffersCallback() { - OnSwapBuffers(); - GpuRenderThread* gpu_render_thread = channel_->gpu_render_thread(); - GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; - params.renderer_id = renderer_id_; - params.render_view_id = render_view_id_; - params.window = handle_; - params.surface_id = processor_->GetSurfaceId(); - params.route_id = route_id(); - params.swap_buffers_count = processor_->swap_buffers_count(); - gpu_render_thread->Send( - new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params)); -} - -void GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped( - uint64 swap_buffers_count) { - processor_->set_acknowledged_swap_buffers_count(swap_buffers_count); - // Wake up the GpuProcessor to start doing work again. - processor_->ScheduleProcessCommands(); -} -#endif // defined(OS_MACOSX) - -void GpuCommandBufferStub::ResizeCallback(gfx::Size size) { - if (handle_ == gfx::kNullPluginWindow) { - processor_->decoder()->ResizeOffscreenFrameBuffer(size); - processor_->decoder()->UpdateOffscreenFrameBufferSize(); - } else { -#if defined(OS_LINUX) && !defined(TOUCH_UI) - GpuRenderThread* gpu_render_thread = channel_->gpu_render_thread(); - bool result = false; - gpu_render_thread->Send( - new GpuHostMsg_ResizeXID(handle_, size, &result)); -#elif defined(OS_WIN) - HWND hwnd = static_cast(compositor_window_); - UINT swp_flags = SWP_NOSENDCHANGING | SWP_NOOWNERZORDER | SWP_NOCOPYBITS | - SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE; - SetWindowPos(hwnd, NULL, 0, 0, size.width(), size.height(), swp_flags); -#endif // defined(OS_LINUX) - } -} - -#endif // defined(ENABLE_GPU) diff --git a/content/gpu/gpu_command_buffer_stub.h b/content/gpu/gpu_command_buffer_stub.h deleted file mode 100644 index 1af3afa..0000000 --- a/content/gpu/gpu_command_buffer_stub.h +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef CONTENT_GPU_GPU_COMMAND_BUFFER_STUB_H_ -#define CONTENT_GPU_GPU_COMMAND_BUFFER_STUB_H_ -#pragma once - -#if defined(ENABLE_GPU) - -#include -#include - -#include "base/memory/weak_ptr.h" -#include "base/process.h" -#include "gpu/command_buffer/service/command_buffer_service.h" -#include "gpu/command_buffer/service/gpu_processor.h" -#include "ipc/ipc_channel.h" -#include "ipc/ipc_message.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/gfx/size.h" - -class GpuChannel; -class GpuWatchdogThread; - -class GpuCommandBufferStub - : public IPC::Channel::Listener, - public IPC::Message::Sender, - public base::SupportsWeakPtr { - public: - GpuCommandBufferStub( - GpuChannel* channel, - gfx::PluginWindowHandle handle, - GpuCommandBufferStub* parent, - const gfx::Size& size, - const gpu::gles2::DisallowedExtensions& disallowed_extensions, - const std::string& allowed_extensions, - const std::vector& attribs, - uint32 parent_texture_id, - int32 route_id, - int32 renderer_id, - int32 render_view_id, - GpuWatchdogThread* gpu_watchdog_thread); - - virtual ~GpuCommandBufferStub(); - - // IPC::Channel::Listener implementation: - virtual bool OnMessageReceived(const IPC::Message& message); - - // IPC::Message::Sender implementation: - virtual bool Send(IPC::Message* msg); - - // Get the GLContext associated with this object. - gpu::GPUProcessor* processor() const { return processor_.get(); } - - // Identifies the renderer process. - int32 renderer_id() const { return renderer_id_; } - - // Identifies a particular renderer belonging to the same renderer process. - int32 render_view_id() const { return render_view_id_; } - - // Identifies the various GpuCommandBufferStubs in the GPU process belonging - // to the same renderer process. - int32 route_id() const { return route_id_; } - -#if defined(OS_WIN) - // Called only by the compositor window's window proc - void OnCompositorWindowPainted(); -#endif // defined(OS_WIN) - -#if defined(OS_MACOSX) - // Called only by the GpuChannel. - void AcceleratedSurfaceBuffersSwapped(uint64 swap_buffers_count); -#endif // defined(OS_MACOSX) - - private: - // Message handlers: - void OnInitialize(base::SharedMemoryHandle ring_buffer, - int32 size, - bool* result); - void OnGetState(gpu::CommandBuffer::State* state); - void OnAsyncGetState(); - void OnFlush(int32 put_offset, gpu::CommandBuffer::State* state); - void OnAsyncFlush(int32 put_offset); - void OnCreateTransferBuffer(int32 size, int32* id); - void OnRegisterTransferBuffer(base::SharedMemoryHandle transfer_buffer, - size_t size, - int32* id); - void OnDestroyTransferBuffer(int32 id); - void OnGetTransferBuffer(int32 id, - base::SharedMemoryHandle* transfer_buffer, - uint32* size); - void OnResizeOffscreenFrameBuffer(const gfx::Size& size); - - void OnSwapBuffers(); - void OnCommandProcessed(); - -#if defined(OS_MACOSX) - void OnSetWindowSize(const gfx::Size& size); - void SwapBuffersCallback(); -#endif // defined(OS_MACOSX) - -#if defined(OS_WIN) - bool CreateCompositorWindow(); -#endif // defined(OS_WIN) - - void ResizeCallback(gfx::Size size); - - // The lifetime of objects of this class is managed by a GpuChannel. The - // GpuChannels destroy all the GpuCommandBufferStubs that they own when they - // are destroyed. So a raw pointer is safe. - GpuChannel* channel_; - - gfx::PluginWindowHandle handle_; - base::WeakPtr parent_; - gfx::Size initial_size_; - gpu::gles2::DisallowedExtensions disallowed_extensions_; - std::string allowed_extensions_; - std::vector requested_attribs_; - uint32 parent_texture_id_; - int32 route_id_; - -#if defined(OS_WIN) - HWND compositor_window_; -#endif // defined(OS_WIN) - - // The following two fields are used on Mac OS X to identify the window - // for the rendering results on the browser side. - int32 renderer_id_; - int32 render_view_id_; - - scoped_ptr command_buffer_; - scoped_ptr processor_; - GpuWatchdogThread* watchdog_thread_; - - DISALLOW_COPY_AND_ASSIGN(GpuCommandBufferStub); -}; - -#endif // defined(ENABLE_GPU) - -#endif // CONTENT_GPU_GPU_COMMAND_BUFFER_STUB_H_ diff --git a/content/gpu/gpu_config.h b/content/gpu/gpu_config.h deleted file mode 100644 index 8aba7bf..0000000 --- a/content/gpu/gpu_config.h +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef CONTENT_GPU_GPU_CONFIG_H_ -#define CONTENT_GPU_GPU_CONFIG_H_ -#pragma once - -// This file declares common preprocessor configuration for the GPU process. - -#include "build/build_config.h" - -#endif // CONTENT_GPU_GPU_CONFIG_H_ diff --git a/content/gpu/gpu_info_collector.h b/content/gpu/gpu_info_collector.h index eb669a0..f911c9c 100644 --- a/content/gpu/gpu_info_collector.h +++ b/content/gpu/gpu_info_collector.h @@ -8,7 +8,7 @@ #include "base/basictypes.h" #include "build/build_config.h" -#include "content/common/gpu_info.h" +#include "content/common/gpu/gpu_info.h" struct IDirect3D9; diff --git a/content/gpu/gpu_info_collector_unittest.cc b/content/gpu/gpu_info_collector_unittest.cc index d787e89..5196c557 100644 --- a/content/gpu/gpu_info_collector_unittest.cc +++ b/content/gpu/gpu_info_collector_unittest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "base/memory/scoped_ptr.h" -#include "content/common/gpu_info.h" +#include "content/common/gpu/gpu_info.h" #include "content/gpu/gpu_info_collector.h" #include "gpu/command_buffer/common/gl_mock.h" #include "testing/gmock/include/gmock/gmock.h" diff --git a/content/gpu/gpu_info_unittest_win.cc b/content/gpu/gpu_info_unittest_win.cc index 0629fbd..03a00f3 100644 --- a/content/gpu/gpu_info_unittest_win.cc +++ b/content/gpu/gpu_info_unittest_win.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "base/memory/scoped_ptr.h" -#include "content/common/gpu_info.h" +#include "content/gpu/common/gpu/gpu_info.h" #include "content/gpu/gpu_idirect3d9_mock_win.h" #include "content/gpu/gpu_info_collector.h" #include "testing/gmock/include/gmock/gmock.h" diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc index 4076ad8..422175c 100644 --- a/content/gpu/gpu_main.cc +++ b/content/gpu/gpu_main.cc @@ -15,9 +15,9 @@ #include "base/threading/platform_thread.h" #include "build/build_config.h" #include "content/common/content_switches.h" +#include "content/common/gpu/gpu_config.h" #include "content/common/main_function_params.h" #include "content/gpu/gpu_child_thread.h" -#include "content/gpu/gpu_config.h" #include "content/gpu/gpu_process.h" #if defined(OS_MACOSX) diff --git a/content/gpu/gpu_render_thread.cc b/content/gpu/gpu_render_thread.cc deleted file mode 100644 index 784d3e5..0000000 --- a/content/gpu/gpu_render_thread.cc +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2011 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 "content/gpu/gpu_render_thread.h" - -#include -#include - -#include "app/win/scoped_com_initializer.h" -#include "base/command_line.h" -#include "base/threading/worker_pool.h" -#include "build/build_config.h" -#include "chrome/common/child_process_logging.h" -#include "chrome/common/chrome_switches.h" -#include "content/common/child_process.h" -#include "content/common/gpu_messages.h" -#include "content/gpu/gpu_child_thread.h" -#include "content/gpu/gpu_info_collector.h" -#include "content/gpu/gpu_watchdog_thread.h" -#include "ipc/ipc_channel_handle.h" -#include "ui/gfx/gl/gl_context.h" -#include "ui/gfx/gl/gl_implementation.h" - -GpuRenderThread::GpuRenderThread(IPC::Message::Sender* browser_channel, - GpuWatchdogThread* gpu_watchdog_thread, - MessageLoop* io_message_loop, - base::WaitableEvent* shutdown_event) - : io_message_loop_(io_message_loop), - shutdown_event_(shutdown_event), - browser_channel_(browser_channel), - watchdog_thread_(gpu_watchdog_thread) { - DCHECK(browser_channel); - DCHECK(io_message_loop); - DCHECK(shutdown_event); -} - -GpuRenderThread::~GpuRenderThread() { - gpu_channels_.clear(); -} - -void GpuRenderThread::RemoveChannel(int renderer_id) { - gpu_channels_.erase(renderer_id); -} - -bool GpuRenderThread::OnMessageReceived(const IPC::Message& msg) { - bool msg_is_ok = true; - bool handled = true; - IPC_BEGIN_MESSAGE_MAP_EX(GpuRenderThread, msg, msg_is_ok) - IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel) - IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel) - IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer, - OnCreateViewCommandBuffer); - IPC_MESSAGE_HANDLER(GpuMsg_Synchronize, OnSynchronize) -#if defined(OS_MACOSX) - IPC_MESSAGE_HANDLER(GpuMsg_AcceleratedSurfaceBuffersSwappedACK, - OnAcceleratedSurfaceBuffersSwappedACK) - IPC_MESSAGE_HANDLER(GpuMsg_DestroyCommandBuffer, - OnDestroyCommandBuffer) -#endif - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP_EX() - return handled; -} - -bool GpuRenderThread::Send(IPC::Message* msg) { - return browser_channel_->Send(msg); -} - -void GpuRenderThread::OnEstablishChannel(int renderer_id) { - scoped_refptr channel; - IPC::ChannelHandle channel_handle; - GPUInfo gpu_info; - - GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); - if (iter == gpu_channels_.end()) - channel = new GpuChannel(this, watchdog_thread_, renderer_id); - else - channel = iter->second; - - DCHECK(channel != NULL); - - if (channel->Init(io_message_loop_, shutdown_event_)) - gpu_channels_[renderer_id] = channel; - else - channel = NULL; - - if (channel.get()) { - channel_handle.name = channel->GetChannelName(); -#if defined(OS_POSIX) - // On POSIX, pass the renderer-side FD. Also mark it as auto-close so - // that it gets closed after it has been sent. - int renderer_fd = channel->GetRendererFileDescriptor(); - channel_handle.socket = base::FileDescriptor(dup(renderer_fd), true); -#endif - } - - Send(new GpuHostMsg_ChannelEstablished(channel_handle)); -} - -void GpuRenderThread::OnCloseChannel(const IPC::ChannelHandle& channel_handle) { - for (GpuChannelMap::iterator iter = gpu_channels_.begin(); - iter != gpu_channels_.end(); ++iter) { - if (iter->second->GetChannelName() == channel_handle.name) { - gpu_channels_.erase(iter); - return; - } - } -} - -void GpuRenderThread::OnSynchronize() { - Send(new GpuHostMsg_SynchronizeReply()); -} - -void GpuRenderThread::OnCreateViewCommandBuffer( - gfx::PluginWindowHandle window, - int32 render_view_id, - int32 renderer_id, - const GPUCreateCommandBufferConfig& init_params) { - int32 route_id = MSG_ROUTING_NONE; - - GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); - if (iter != gpu_channels_.end()) { - iter->second->CreateViewCommandBuffer( - window, render_view_id, init_params, &route_id); - } - - Send(new GpuHostMsg_CommandBufferCreated(route_id)); -} - -#if defined(OS_MACOSX) -void GpuRenderThread::OnAcceleratedSurfaceBuffersSwappedACK( - int renderer_id, int32 route_id, uint64 swap_buffers_count) { - GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); - if (iter == gpu_channels_.end()) - return; - scoped_refptr channel = iter->second; - channel->AcceleratedSurfaceBuffersSwapped(route_id, swap_buffers_count); -} -void GpuRenderThread::OnDestroyCommandBuffer( - int renderer_id, int32 renderer_view_id) { - GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); - if (iter == gpu_channels_.end()) - return; - scoped_refptr channel = iter->second; - channel->DestroyCommandBufferByViewId(renderer_view_id); -} -#endif diff --git a/content/gpu/gpu_render_thread.h b/content/gpu/gpu_render_thread.h deleted file mode 100644 index 6292864..0000000 --- a/content/gpu/gpu_render_thread.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef CONTENT_GPU_GPU_RENDER_THREAD_H_ -#define CONTENT_GPU_GPU_RENDER_THREAD_H_ -#pragma once - -#include - -#include "base/basictypes.h" -#include "base/hash_tables.h" -#include "base/command_line.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/time.h" -#include "build/build_config.h" -#include "content/common/child_thread.h" -#include "content/common/gpu_info.h" -#include "content/gpu/gpu_channel.h" -#include "content/gpu/gpu_config.h" -#include "content/gpu/x_util.h" -#include "ipc/ipc_channel.h" -#include "ipc/ipc_message.h" -#include "ui/gfx/native_widget_types.h" - -namespace IPC { -struct ChannelHandle; -} - -// A GpuRenderThread is a thread responsible for issuing rendering commands to -// a GPU. There is currently only one per GPU process. This might change. Assume -// there are many, all running on different threads. -// -// A GpuRenderThread can also be hosted in the browser process in single process -// or in-process GPU modes. In this case there is no corresponding -// GpuChildThread and this is the reason the GpuChildThread is referenced via -// a pointer to IPC::Message::Sender, which can be implemented by other hosts -// to send IPC messages to the browser process IO thread on the -// GpuRenderThread's behalf. -class GpuRenderThread : public IPC::Channel::Listener, - public IPC::Message::Sender { - public: - GpuRenderThread(IPC::Message::Sender* browser_channel, - GpuWatchdogThread* gpu_watchdog_thread, - MessageLoop* io_message_loop, - base::WaitableEvent* shutdown_event); - ~GpuRenderThread(); - - // Remove the channel for a particular renderer. - void RemoveChannel(int renderer_id); - - // Listener overrides. - virtual bool OnMessageReceived(const IPC::Message& msg); - - // Sender overrides. - virtual bool Send(IPC::Message* msg); - - private: - // Message handlers. - void OnEstablishChannel(int renderer_id); - void OnCloseChannel(const IPC::ChannelHandle& channel_handle); - void OnSynchronize(); - void OnCreateViewCommandBuffer( - gfx::PluginWindowHandle window, - int32 render_view_id, - int32 renderer_id, - const GPUCreateCommandBufferConfig& init_params); -#if defined(OS_MACOSX) - void OnAcceleratedSurfaceBuffersSwappedACK( - int renderer_id, int32 route_id, uint64 swap_buffers_count); - void OnDestroyCommandBuffer(int renderer_id, int32 renderer_view_id); -#endif - - MessageLoop* io_message_loop_; - base::WaitableEvent* shutdown_event_; - - // Either an IPC channel to the browser or, if the GpuRenderThread is - // running in the browser process, a Sender implementation that will post - // IPC messages to the UI thread. - IPC::Message::Sender* browser_channel_; - - // These objects manage channels to individual renderer processes there is - // one channel for each renderer process that has connected to this GPU - // process. - typedef base::hash_map > GpuChannelMap; - GpuChannelMap gpu_channels_; - GpuWatchdogThread* watchdog_thread_; - - DISALLOW_COPY_AND_ASSIGN(GpuRenderThread); -}; - -#endif // CONTENT_GPU_GPU_RENDER_THREAD_H_ diff --git a/content/gpu/gpu_video_decoder.cc b/content/gpu/gpu_video_decoder.cc deleted file mode 100644 index 0416fcd..0000000 --- a/content/gpu/gpu_video_decoder.cc +++ /dev/null @@ -1,427 +0,0 @@ -// Copyright (c) 2011 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 "content/gpu/gpu_video_decoder.h" - -#include "base/command_line.h" -#include "content/common/child_thread.h" -#include "content/common/gpu_messages.h" -#include "content/gpu/gpu_channel.h" -#include "content/gpu/media/fake_gl_video_decode_engine.h" -#include "content/gpu/media/fake_gl_video_device.h" -#include "media/base/data_buffer.h" -#include "media/base/media_switches.h" -#include "media/base/video_frame.h" - -#if defined(OS_WIN) -#include "content/gpu/media/mft_angle_video_device.h" -#include "media/video/mft_h264_decode_engine.h" -#include -#endif - -struct GpuVideoDecoder::PendingAllocation { - size_t n; - size_t width; - size_t height; - media::VideoFrame::Format format; - std::vector >* frames; - Task* task; -}; - -void GpuVideoDecoder::OnChannelConnected(int32 peer_pid) { -} - -void GpuVideoDecoder::OnChannelError() { -} - -bool GpuVideoDecoder::OnMessageReceived(const IPC::Message& msg) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(GpuVideoDecoder, msg) - IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Initialize, - OnInitialize) - IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Destroy, - OnUninitialize) - IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Flush, - OnFlush) - IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Preroll, - OnPreroll) - IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_EmptyThisBuffer, - OnEmptyThisBuffer) - IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_ProduceVideoFrame, - OnProduceVideoFrame) - IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_VideoFrameAllocated, - OnVideoFrameAllocated) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - DCHECK(handled); - return handled; -} - -bool GpuVideoDecoder::CreateInputTransferBuffer( - uint32 size, - base::SharedMemoryHandle* handle) { - input_transfer_buffer_.reset(new base::SharedMemory); - if (!input_transfer_buffer_.get()) - return false; - - if (!input_transfer_buffer_->CreateAndMapAnonymous(size)) - return false; - - if (!input_transfer_buffer_->ShareToProcess(renderer_handle_, handle)) - return false; - - return true; -} - -void GpuVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) { - info_ = info; - GpuVideoDecoderInitDoneParam param; - param.success = false; - param.input_buffer_handle = base::SharedMemory::NULLHandle(); - - if (!info.success) { - SendInitializeDone(param); - return; - } - - // TODO(jiesun): Check the assumption of input size < original size. - param.input_buffer_size = - info.stream_info.surface_width * info.stream_info.surface_height * 3 / 2; - if (!CreateInputTransferBuffer(param.input_buffer_size, - ¶m.input_buffer_handle)) { - SendInitializeDone(param); - return; - } - - param.success = true; - SendInitializeDone(param); -} - -void GpuVideoDecoder::OnUninitializeComplete() { - SendUninitializeDone(); -} - -void GpuVideoDecoder::OnFlushComplete() { - SendFlushDone(); -} - -void GpuVideoDecoder::OnSeekComplete() { - SendPrerollDone(); -} - -void GpuVideoDecoder::OnError() { - NOTIMPLEMENTED(); -} - -void GpuVideoDecoder::OnFormatChange(VideoStreamInfo stream_info) { - NOTIMPLEMENTED(); -} - -void GpuVideoDecoder::ProduceVideoSample(scoped_refptr buffer) { - SendEmptyBufferDone(); -} - -void GpuVideoDecoder::ConsumeVideoFrame(scoped_refptr frame, - const PipelineStatistics& statistics) { - // TODO(sjl): Do something with the statistics... - - if (frame->IsEndOfStream()) { - SendConsumeVideoFrame(0, 0, 0, kGpuVideoEndOfStream); - return; - } - - int32 frame_id = -1; - for (VideoFrameMap::iterator i = video_frame_map_.begin(); - i != video_frame_map_.end(); ++i) { - if (i->second == frame) { - frame_id = i->first; - break; - } - } - - if (frame_id == -1) { - NOTREACHED() << "VideoFrame not recognized"; - return; - } - - SendConsumeVideoFrame(frame_id, frame->GetTimestamp().InMicroseconds(), - frame->GetDuration().InMicroseconds(), 0); -} - -void* GpuVideoDecoder::GetDevice() { - bool ret = gles2_decoder_->MakeCurrent(); - DCHECK(ret) << "Failed to switch context"; - - // Simply delegate the method call to GpuVideoDevice. - return video_device_->GetDevice(); -} - -void GpuVideoDecoder::AllocateVideoFrames( - int n, size_t width, size_t height, media::VideoFrame::Format format, - std::vector >* frames, Task* task) { - // Since the communication between Renderer and GPU process is by GL textures. - // We need to obtain a set of GL textures by sending IPC commands to the - // Renderer process. The recipient of these commands will be IpcVideoDecoder. - // - // After IpcVideoDecoder replied with a set of textures. We'll assign these - // textures to GpuVideoDevice. They will be used to generate platform - // specific VideoFrames objects that are used by VideoDecodeEngine. - // - // After GL textures are assigned we'll proceed with allocation the - // VideoFrames. GpuVideoDevice::CreateVideoFramesFromGlTextures() will be - // called. - // - // When GpuVideoDevice replied with a set of VideoFrames we'll give - // that to VideoDecodeEngine and the cycle of video frame allocation is done. - // - // Note that this method is called when there's no video frames allocated or - // they were all released. - DCHECK(video_frame_map_.empty()); - - // Save the parameters for allocation. - pending_allocation_.reset(new PendingAllocation()); - pending_allocation_->n = n; - pending_allocation_->width = width; - pending_allocation_->height = height; - pending_allocation_->format = format; - pending_allocation_->frames = frames; - pending_allocation_->task = task; - SendAllocateVideoFrames(n, width, height, format); -} - -void GpuVideoDecoder::ReleaseAllVideoFrames() { - // This method will first call to GpuVideoDevice to release all the resource - // associated with a VideoFrame. - // - // And then we'll call GpuVideoDevice::ReleaseVideoFrame() to remove the set - // of Gl textures associated with the context. - // - // And finally we'll send IPC commands to IpcVideoDecoder to destroy all - // GL textures generated. - bool ret = gles2_decoder_->MakeCurrent(); - DCHECK(ret) << "Failed to switch context"; - - for (VideoFrameMap::iterator i = video_frame_map_.begin(); - i != video_frame_map_.end(); ++i) { - video_device_->ReleaseVideoFrame(i->second); - } - video_frame_map_.clear(); - SendReleaseAllVideoFrames(); -} - -void GpuVideoDecoder::ConvertToVideoFrame( - void* buffer, - scoped_refptr frame, - Task* task) { - // This method is called by VideoDecodeEngine to upload a buffer to a - // VideoFrame. We should just delegate this to GpuVideoDevice which contains - // the actual implementation. - bool ret = gles2_decoder_->MakeCurrent(); - DCHECK(ret) << "Failed to switch context"; - - // Actually doing the upload on the main thread. - ret = video_device_->ConvertToVideoFrame(buffer, frame); - DCHECK(ret) << "Failed to upload video content to a VideoFrame."; - task->Run(); - delete task; -} - -void GpuVideoDecoder::Destroy(Task* task) { - // TODO(hclam): I still need to think what I should do here. -} - -void GpuVideoDecoder::SetVideoDecodeEngine(media::VideoDecodeEngine* engine) { - decode_engine_.reset(engine); -} - -void GpuVideoDecoder::SetGpuVideoDevice(GpuVideoDevice* device) { - video_device_.reset(device); -} - -GpuVideoDecoder::GpuVideoDecoder( - MessageLoop* message_loop, - int32 decoder_host_id, - IPC::Message::Sender* sender, - base::ProcessHandle handle, - gpu::gles2::GLES2Decoder* decoder) - : message_loop_(message_loop), - decoder_host_id_(decoder_host_id), - sender_(sender), - renderer_handle_(handle), - gles2_decoder_(decoder) { - memset(&info_, 0, sizeof(info_)); - - // TODO(jiesun): find a better way to determine which VideoDecodeEngine - // to return on current platform. -#if defined(OS_WIN) - const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(switches::kEnableAcceleratedDecoding)) { - // The following code are removed so that we don't link them. - // TODO(hclam): Enable the code once the crash is solved on XP. - // decode_engine_.reset(new media::MftH264DecodeEngine(true)); - // video_device_.reset(new MftAngleVideoDevice()); - } -#else - decode_engine_.reset(new FakeGlVideoDecodeEngine()); - video_device_.reset(new FakeGlVideoDevice()); -#endif -} - -GpuVideoDecoder::~GpuVideoDecoder() {} - -void GpuVideoDecoder::OnInitialize(const GpuVideoDecoderInitParam& param) { - // TODO(jiesun): codec id should come from |param|. - media::VideoCodecConfig config(media::kCodecH264, - param.width, - param.height, - param.frame_rate_num, - param.frame_rate_den, - NULL, - 0); - decode_engine_->Initialize(message_loop_, this, this, config); -} - -void GpuVideoDecoder::OnUninitialize() { - decode_engine_->Uninitialize(); -} - -void GpuVideoDecoder::OnFlush() { - decode_engine_->Flush(); -} - -void GpuVideoDecoder::OnPreroll() { - decode_engine_->Seek(); -} - -void GpuVideoDecoder::OnEmptyThisBuffer( - const GpuVideoDecoderInputBufferParam& buffer) { - DCHECK(input_transfer_buffer_->memory()); - - uint8* src = static_cast(input_transfer_buffer_->memory()); - - scoped_refptr input_buffer; - uint8* dst = buffer.size ? new uint8[buffer.size] : NULL; - input_buffer = new media::DataBuffer(dst, buffer.size); - memcpy(dst, src, buffer.size); - SendEmptyBufferACK(); - - // Delegate the method call to VideoDecodeEngine. - decode_engine_->ConsumeVideoSample(input_buffer); -} - -void GpuVideoDecoder::OnProduceVideoFrame(int32 frame_id) { - VideoFrameMap::iterator i = video_frame_map_.find(frame_id); - if (i == video_frame_map_.end()) { - NOTREACHED() << "Received a request of unknown frame ID."; - } - - // Delegate the method call to VideoDecodeEngine. - decode_engine_->ProduceVideoFrame(i->second); -} - -void GpuVideoDecoder::OnVideoFrameAllocated(int32 frame_id, - std::vector textures) { - bool ret = gles2_decoder_->MakeCurrent(); - DCHECK(ret) << "Failed to switch context"; - - // This method is called in response to a video frame allocation request sent - // to the Renderer process. - // We should use the textures to generate a VideoFrame by using - // GpuVideoDevice. The VideoFrame created is added to the internal map. - // If we have generated enough VideoFrame, we call |allocation_callack_| to - // complete the allocation process. - for (size_t i = 0; i < textures.size(); ++i) { - media::VideoFrame::GlTexture gl_texture; - // Translate the client texture id to service texture id. - ret = gles2_decoder_->GetServiceTextureId(textures[i], &gl_texture); - DCHECK(ret) << "Cannot translate client texture ID to service ID"; - textures[i] = gl_texture; - } - - // Use GpuVideoDevice to allocate VideoFrame objects. - scoped_refptr frame; - - ret = video_device_->CreateVideoFrameFromGlTextures( - pending_allocation_->width, pending_allocation_->height, - pending_allocation_->format, textures, &frame); - - DCHECK(ret) << "Failed to allocation VideoFrame from GL textures)"; - pending_allocation_->frames->push_back(frame); - video_frame_map_.insert(std::make_pair(frame_id, frame)); - - if (video_frame_map_.size() == pending_allocation_->n) { - pending_allocation_->task->Run(); - delete pending_allocation_->task; - pending_allocation_.reset(); - } -} - -void GpuVideoDecoder::SendInitializeDone( - const GpuVideoDecoderInitDoneParam& param) { - if (!sender_->Send( - new GpuVideoDecoderHostMsg_InitializeACK(decoder_host_id(), param))) { - LOG(ERROR) << "GpuVideoDecoderMsg_InitializeACK failed"; - } -} - -void GpuVideoDecoder::SendUninitializeDone() { - if (!sender_->Send( - new GpuVideoDecoderHostMsg_DestroyACK(decoder_host_id()))) { - LOG(ERROR) << "GpuVideoDecoderMsg_DestroyACK failed"; - } -} - -void GpuVideoDecoder::SendFlushDone() { - if (!sender_->Send(new GpuVideoDecoderHostMsg_FlushACK(decoder_host_id()))) { - LOG(ERROR) << "GpuVideoDecoderMsg_FlushACK failed"; - } -} - -void GpuVideoDecoder::SendPrerollDone() { - if (!sender_->Send(new GpuVideoDecoderHostMsg_PrerollDone( - decoder_host_id()))) { - LOG(ERROR) << "GpuVideoDecoderMsg_PrerollDone failed"; - } -} - -void GpuVideoDecoder::SendEmptyBufferDone() { - if (!sender_->Send( - new GpuVideoDecoderHostMsg_EmptyThisBufferDone(decoder_host_id()))) { - LOG(ERROR) << "GpuVideoDecoderMsg_EmptyThisBufferDone failed"; - } -} - -void GpuVideoDecoder::SendEmptyBufferACK() { - if (!sender_->Send( - new GpuVideoDecoderHostMsg_EmptyThisBufferACK(decoder_host_id()))) { - LOG(ERROR) << "GpuVideoDecoderMsg_EmptyThisBufferACK failed"; - } -} - -void GpuVideoDecoder::SendConsumeVideoFrame( - int32 frame_id, int64 timestamp, int64 duration, int32 flags) { - if (!sender_->Send( - new GpuVideoDecoderHostMsg_ConsumeVideoFrame( - decoder_host_id(), frame_id, timestamp, duration, flags))) { - LOG(ERROR) << "GpuVideoDecodeHostMsg_ConsumeVideoFrame failed."; - } -} - -void GpuVideoDecoder::SendAllocateVideoFrames( - int n, size_t width, size_t height, media::VideoFrame::Format format) { - if (!sender_->Send( - new GpuVideoDecoderHostMsg_AllocateVideoFrames( - decoder_host_id(), n, width, height, - static_cast(format)))) { - LOG(ERROR) << "GpuVideoDecoderMsg_AllocateVideoFrames failed"; - } -} - -void GpuVideoDecoder::SendReleaseAllVideoFrames() { - if (!sender_->Send( - new GpuVideoDecoderHostMsg_ReleaseAllVideoFrames( - decoder_host_id()))) { - LOG(ERROR) << "GpuVideoDecoderMsg_ReleaseAllVideoFrames failed"; - } -} diff --git a/content/gpu/gpu_video_decoder.h b/content/gpu/gpu_video_decoder.h deleted file mode 100644 index 87d214e..0000000 --- a/content/gpu/gpu_video_decoder.h +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef CONTENT_GPU_GPU_VIDEO_DECODER_H_ -#define CONTENT_GPU_GPU_VIDEO_DECODER_H_ - -#include -#include - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/process.h" -#include "base/shared_memory.h" -#include "content/gpu/media/gpu_video_device.h" -#include "media/video/video_decode_context.h" -#include "media/video/video_decode_engine.h" -#include "ipc/ipc_channel.h" - -using media::Buffer; -using media::PipelineStatistics; -using media::VideoCodecConfig; -using media::VideoCodecInfo; -using media::VideoStreamInfo; -using media::VideoFrame; - -namespace gpu { -namespace gles2 { -class GLES2Decoder; -} // namespace gles2 -} // namespace gpu - -class GpuChannel; -struct GpuVideoDecoderInitDoneParam; -struct GpuVideoDecoderInitParam; -struct GpuVideoDecoderInputBufferParam; - -// A GpuVideoDecoder is a platform independent video decoder that uses platform -// specific VideoDecodeEngine and GpuVideoDevice for the actual decoding -// operations. -// -// In addition to delegating video related commamnds to VideoDecodeEngine it -// has the following important functions: -// -// BUFFER ALLOCATION -// -// VideoDecodeEngine requires platform specific video frame buffer to operate. -// In order to abstract the platform specific bits GpuVideoDecoderContext is -// used to allocate video frames that a VideoDecodeEngine can use. -// -// Since all the video frames appear to the Renderer process as textures, the -// first thing GpuVideoDecoder needs to do is to ask Renderer process to -// generate and allocate textures. This will establish a texture record in the -// command buffer decoder. After the texture is allocated, this class will -// pass the textures meaningful in the local GLES context to -// GpuVideoDevice for generating VideoFrames that VideoDecodeEngine -// can actually use. -// -// In order to coordinate these operations, GpuVideoDecoder implements -// VideoDecodeContext and is injected into the VideoDecodeEngine. -// -// The sequence of operations is: -// 1. VideoDecodeEngine requests by call AllocateVideoFrames(). -// 2. GpuVideoDecoder receives AllocateVideoFrames() and then call to the -// Renderer process to generate textures. -// 3. Renderer process replied with textures. -// 4. Textures generated are passed into GpuVideoDevice. -// 5. GpuVideoDevice::AllocateVideoFrames() is called to generate -// VideoFrame(s) from the textures. -// 6. GpuVideoDecoder sends the VideoFrame(s) generated to VideoDecodeEngine. -// -// BUFFER UPLOADING -// -// A VideoDecodeEngine always produces some device specific buffer. In order to -// use them in Chrome we always upload them to GL textures. The upload step is -// different on each platform and each subsystem. We perform these special -// upload steps by using GpuVideoDevice which are written for each -// VideoDecodeEngine. -// -// BUFFER MAPPING -// -// GpuVideoDecoder will be working with VideoDecodeEngine, they exchange -// buffers that are only meaningful to VideoDecodeEngine. In order to map that -// to something we can transport in the IPC channel we need a mapping between -// VideoFrame and buffer ID known between GpuVideoDecoder and -// GpuVideoDecoderHost in the Renderer process. -// -// After texture allocation and VideoFrame allocation are done, GpuVideoDecoder -// will maintain such mapping. -// -class GpuVideoDecoder - : public base::RefCountedThreadSafe, - public IPC::Channel::Listener, - public media::VideoDecodeEngine::EventHandler, - public media::VideoDecodeContext { - public: - // Constructor and destructor. - GpuVideoDecoder(MessageLoop* message_loop, - int32 decoder_host_id, - IPC::Message::Sender* sender, - base::ProcessHandle handle, - gpu::gles2::GLES2Decoder* decoder); - virtual ~GpuVideoDecoder(); - - // IPC::Channel::Listener implementation. - virtual void OnChannelConnected(int32 peer_pid); - virtual void OnChannelError(); - virtual bool OnMessageReceived(const IPC::Message& message); - - // VideoDecodeEngine::EventHandler implementation. - virtual void OnInitializeComplete(const VideoCodecInfo& info); - virtual void OnUninitializeComplete(); - virtual void OnFlushComplete(); - virtual void OnSeekComplete(); - virtual void OnError(); - virtual void OnFormatChange(VideoStreamInfo stream_info); - virtual void ProduceVideoSample(scoped_refptr buffer); - virtual void ConsumeVideoFrame(scoped_refptr frame, - const PipelineStatistics& statistics); - - // VideoDecodeContext implementation. - virtual void* GetDevice(); - virtual void AllocateVideoFrames( - int n, size_t width, size_t height, media::VideoFrame::Format format, - std::vector >* frames, Task* task); - virtual void ReleaseAllVideoFrames(); - virtual void ConvertToVideoFrame(void* buffer, - scoped_refptr frame, - Task* task); - virtual void Destroy(Task* task); - - // These methods are used in unit test only. - void SetVideoDecodeEngine(media::VideoDecodeEngine* engine); - void SetGpuVideoDevice(GpuVideoDevice* device); - - private: - struct PendingAllocation; - - int32 decoder_host_id() { return decoder_host_id_; } - - bool CreateInputTransferBuffer(uint32 size, - base::SharedMemoryHandle* handle); - - // These methods are message handlers for the messages sent from the Renderer - // process. - void OnInitialize(const GpuVideoDecoderInitParam& param); - void OnUninitialize(); - void OnFlush(); - void OnPreroll(); - void OnEmptyThisBuffer(const GpuVideoDecoderInputBufferParam& buffer); - void OnProduceVideoFrame(int32 frame_id); - void OnVideoFrameAllocated(int32 frame_id, std::vector textures); - - // Helper methods for sending messages to the Renderer process. - void SendInitializeDone(const GpuVideoDecoderInitDoneParam& param); - void SendUninitializeDone(); - void SendFlushDone(); - void SendPrerollDone(); - void SendEmptyBufferDone(); - void SendEmptyBufferACK(); - void SendConsumeVideoFrame(int32 frame_id, int64 timestamp, int64 duration, - int32 flags); - void SendAllocateVideoFrames( - int n, size_t width, size_t height, media::VideoFrame::Format format); - void SendReleaseAllVideoFrames(); - - // The message loop that this object should run on. - MessageLoop* message_loop_; - - // ID of GpuVideoDecoderHost in the Renderer Process. - int32 decoder_host_id_; - - // Used only in system memory path. i.e. Remove this later. - scoped_refptr frame_; - - IPC::Message::Sender* sender_; - base::ProcessHandle renderer_handle_; - - // The GLES2 decoder has the context associated with this decoder. This object - // is used to switch context and translate client texture ID to service ID. - gpu::gles2::GLES2Decoder* gles2_decoder_; - - // Memory for transfering the input data for the hardware video decoder. - scoped_ptr input_transfer_buffer_; - - // VideoDecodeEngine is used to do the actual video decoding. - scoped_ptr decode_engine_; - - // GpuVideoDevice is used to generate VideoFrame(s) from GL textures. The - // frames generated are understood by the decode engine. - scoped_ptr video_device_; - - // Contain information for allocation VideoFrame(s). - scoped_ptr pending_allocation_; - - // Contains the mapping between a |frame_id| and VideoFrame generated by - // GpuVideoDevice from the associated GL textures. - // TODO(hclam): Using a faster data structure than map. - typedef std::map > VideoFrameMap; - VideoFrameMap video_frame_map_; - - media::VideoCodecInfo info_; - - DISALLOW_COPY_AND_ASSIGN(GpuVideoDecoder); -}; - -#endif // CONTENT_GPU_GPU_VIDEO_DECODER_H_ diff --git a/content/gpu/gpu_video_decoder_unittest.cc b/content/gpu/gpu_video_decoder_unittest.cc deleted file mode 100644 index afb396b..0000000 --- a/content/gpu/gpu_video_decoder_unittest.cc +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright (c) 2010 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 "base/message_loop.h" -#include "base/process.h" -#include "content/common/gpu_messages.h" -#include "content/gpu/gpu_video_decoder.h" -#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" -#include "ipc/ipc_message_utils.h" -#include "media/base/pipeline.h" -#include "media/video/video_mock_objects.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::_; -using testing::DoAll; -using testing::NotNull; -using testing::Return; -using testing::SetArgumentPointee; - -static const int32 kFrameId = 10; -static const int32 kDecoderHostId = 50; -static const media::VideoFrame::GlTexture kClientTexture = 101; -static const media::VideoFrame::GlTexture kServiceTexture = 102; -static const size_t kWidth = 320; -static const size_t kHeight = 240; - -class MockGpuVideoDevice : public GpuVideoDevice { - public: - MockGpuVideoDevice() {} - virtual ~MockGpuVideoDevice() {} - - MOCK_METHOD0(GetDevice, void*()); - MOCK_METHOD5(CreateVideoFrameFromGlTextures, - bool(size_t, size_t, media::VideoFrame::Format, - const std::vector&, - scoped_refptr*)); - MOCK_METHOD1(ReleaseVideoFrame, - void(const scoped_refptr& frame)); - MOCK_METHOD2(ConvertToVideoFrame, - bool(void* buffer, scoped_refptr frame)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockGpuVideoDevice); -}; - -ACTION_P(InitializationDone, handler) { - media::VideoCodecInfo info; - info.success = true; - info.provides_buffers = false; - info.stream_info.surface_format = media::VideoFrame::RGBA; - info.stream_info.surface_type = media::VideoFrame::TYPE_SYSTEM_MEMORY; - info.stream_info.surface_width = kWidth; - info.stream_info.surface_height = kHeight; - handler->OnInitializeComplete(info); -} - -ACTION_P(SendVideoFrameAllocated, handler) { - std::vector textures; - textures.push_back(kClientTexture); - GpuVideoDecoderMsg_VideoFrameAllocated msg(0, kFrameId, textures); - handler->OnMessageReceived(msg); -} - -ACTION_P2(SendConsumeVideoFrame, handler, frame) { - media::PipelineStatistics statistics; - handler->ConsumeVideoFrame(frame, statistics); -} - -class GpuVideoDecoderTest : public testing::Test, - public IPC::Message::Sender { - public: - GpuVideoDecoderTest() { - // Create the mock objects. - gles2_decoder_.reset(new gpu::gles2::MockGLES2Decoder()); - - gpu_video_decoder_ = new GpuVideoDecoder( - &message_loop_, kDecoderHostId, this, base::kNullProcessHandle, - gles2_decoder_.get()); - - // Create the mock objects. - mock_engine_ = new media::MockVideoDecodeEngine(); - mock_device_ = new MockGpuVideoDevice(); - - // Inject the mock objects. - gpu_video_decoder_->SetVideoDecodeEngine(mock_engine_); - gpu_video_decoder_->SetGpuVideoDevice(mock_device_); - - // VideoFrame for GpuVideoDevice. - media::VideoFrame::GlTexture textures[] = { kServiceTexture, 0, 0 }; - media::VideoFrame::CreateFrameGlTexture(media::VideoFrame::RGBA, - kWidth, kHeight, textures, - &device_frame_); - } - - virtual ~GpuVideoDecoderTest() { - gpu_video_decoder_->SetVideoDecodeEngine(NULL); - gpu_video_decoder_->SetGpuVideoDevice(NULL); - } - - // This method is used to dispatch IPC messages to mock methods. - virtual bool Send(IPC::Message* msg) { - EXPECT_TRUE(msg); - if (!msg) - return false; - - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(GpuVideoDecoderTest, *msg) - IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_InitializeACK, - OnInitializeDone) - IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_DestroyACK, - OnUninitializeDone) - IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_FlushACK, - OnFlushDone) - IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_EmptyThisBufferACK, - OnEmptyThisBufferACK) - IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_EmptyThisBufferDone, - OnEmptyThisBufferDone) - IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_AllocateVideoFrames, - OnAllocateVideoFrames) - IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_ReleaseAllVideoFrames, - OnReleaseAllVideoFrames) - IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_ConsumeVideoFrame, - OnConsumeVideoFrame) - IPC_MESSAGE_UNHANDLED_ERROR() - IPC_END_MESSAGE_MAP() - EXPECT_TRUE(handled); - delete msg; - return true; - } - - // Mock methods for handling output IPC messages. - MOCK_METHOD1(OnInitializeDone, - void(const GpuVideoDecoderInitDoneParam& param)); - MOCK_METHOD0(OnUninitializeDone, void()); - MOCK_METHOD0(OnFlushDone, void()); - MOCK_METHOD0(OnEmptyThisBufferDone, void()); - MOCK_METHOD4(OnConsumeVideoFrame, void(int32 device_frame_id, int64 timestamp, - int64 duration, int32 flags)); - MOCK_METHOD0(OnEmptyThisBufferACK, void()); - MOCK_METHOD4(OnAllocateVideoFrames, void(int32 n, uint32 width, - uint32 height, int32 format)); - MOCK_METHOD0(OnReleaseAllVideoFrames, void()); - - // Receive events from GpuVideoDecoder. - MOCK_METHOD0(VideoFramesAllocated, void()); - - void Initialize() { - // VideoDecodeEngine is called. - EXPECT_CALL(*mock_engine_, Initialize(_, _, _, _)) - .WillOnce(InitializationDone(gpu_video_decoder_)); - - // Expect that initialization is completed. - EXPECT_CALL(*this, OnInitializeDone(_)); - - // Send an initialiaze message to GpuVideoDecoder. - GpuVideoDecoderInitParam param; - param.width = kWidth; - param.height = kHeight; - - GpuVideoDecoderMsg_Initialize msg(0, param); - gpu_video_decoder_->OnMessageReceived(msg); - } - - void AllocateVideoFrames() { - // Expect that IPC messages are sent. We'll reply with some GL textures. - EXPECT_CALL(*this, OnAllocateVideoFrames( - 1, kWidth, kHeight, static_cast(media::VideoFrame::RGBA))) - .WillOnce(SendVideoFrameAllocated(gpu_video_decoder_)); - - // Expect that MakeCurrent() is called. - EXPECT_CALL(*gles2_decoder_.get(), MakeCurrent()) - .WillOnce(Return(true)) - .RetiresOnSaturation(); - - // Expect that translate method is called. - EXPECT_CALL(*gles2_decoder_.get(), - GetServiceTextureId(kClientTexture, NotNull())) - .WillOnce(DoAll(SetArgumentPointee<1>(kServiceTexture), Return(true))); - - // And then GpuVideoDevice is called to create VideoFrame from GL textures. - EXPECT_CALL(*mock_device_, - CreateVideoFrameFromGlTextures(kWidth, kHeight, - media::VideoFrame::RGBA, _, - NotNull())) - .WillOnce(DoAll(SetArgumentPointee<4>(device_frame_), Return(true))); - - // Finally the task is called. - EXPECT_CALL(*this, VideoFramesAllocated()); - - // Pretend calling GpuVideoDecoder for allocating frames. - gpu_video_decoder_->AllocateVideoFrames( - 1, kWidth, kHeight, media::VideoFrame::RGBA, &decoder_frames_, - NewRunnableMethod(this, &GpuVideoDecoderTest::VideoFramesAllocated)); - } - - void ReleaseVideoFrames() { - // Expect that MakeCurrent() is called. - EXPECT_CALL(*gles2_decoder_.get(), MakeCurrent()) - .WillOnce(Return(true)) - .RetiresOnSaturation(); - - // Expect that video frame is released. - EXPECT_CALL(*mock_device_, ReleaseVideoFrame(device_frame_)); - - // Expect that IPC message is send to release video frame. - EXPECT_CALL(*this, OnReleaseAllVideoFrames()); - - // Call to GpuVideoDecoder to release all video frames. - gpu_video_decoder_->ReleaseAllVideoFrames(); - } - - void BufferExchange() { - // Expect that we call to produce video frame. - EXPECT_CALL(*mock_engine_, ProduceVideoFrame(device_frame_)) - .WillOnce(SendConsumeVideoFrame(gpu_video_decoder_, device_frame_)) - .RetiresOnSaturation(); - - // Expect that consume video frame is called. - EXPECT_CALL(*this, OnConsumeVideoFrame(kFrameId, 0, 0, 0)) - .RetiresOnSaturation(); - - // Ask the GpuVideoDecoder to produce a video frame. - GpuVideoDecoderMsg_ProduceVideoFrame msg(0, kFrameId); - gpu_video_decoder_->OnMessageReceived(msg); - } - - private: - scoped_refptr gpu_video_decoder_; - MockGpuVideoDevice* mock_device_; - media::MockVideoDecodeEngine* mock_engine_; - scoped_ptr gles2_decoder_; - std::vector > decoder_frames_; - scoped_refptr device_frame_; - - MessageLoop message_loop_; - - DISALLOW_COPY_AND_ASSIGN(GpuVideoDecoderTest); -}; - -TEST_F(GpuVideoDecoderTest, Initialize) { - Initialize(); -} - -TEST_F(GpuVideoDecoderTest, AllocateVideoFrames) { - Initialize(); - AllocateVideoFrames(); -} - -TEST_F(GpuVideoDecoderTest, ReleaseVideoFrames) { - Initialize(); - AllocateVideoFrames(); - ReleaseVideoFrames(); -} - -TEST_F(GpuVideoDecoderTest, BufferExchange) { - Initialize(); - AllocateVideoFrames(); - BufferExchange(); - BufferExchange(); - ReleaseVideoFrames(); -} - -DISABLE_RUNNABLE_METHOD_REFCOUNT(GpuVideoDecoderTest); diff --git a/content/gpu/gpu_video_service.cc b/content/gpu/gpu_video_service.cc deleted file mode 100644 index 355aabc..0000000 --- a/content/gpu/gpu_video_service.cc +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2011 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 "content/common/gpu_messages.h" -#include "content/gpu/gpu_channel.h" -#include "content/gpu/gpu_video_decoder.h" -#include "content/gpu/gpu_video_service.h" - -struct GpuVideoService::GpuVideoDecoderInfo { - scoped_refptr decoder; - GpuChannel* channel; -}; - - -GpuVideoService::GpuVideoService() { - // TODO(jiesun): move this time consuming stuff out of here. - IntializeGpuVideoService(); -} - -GpuVideoService::~GpuVideoService() { - // TODO(jiesun): move this time consuming stuff out of here. - UnintializeGpuVideoService(); -} - -// static -GpuVideoService* GpuVideoService::GetInstance() { - return Singleton::get(); -} - -void GpuVideoService::OnChannelConnected(int32 peer_pid) { - LOG(ERROR) << "GpuVideoService::OnChannelConnected"; -} - -void GpuVideoService::OnChannelError() { - LOG(ERROR) << "GpuVideoService::OnChannelError"; -} - -bool GpuVideoService::OnMessageReceived(const IPC::Message& msg) { -#if 0 - IPC_BEGIN_MESSAGE_MAP(GpuVideoService, msg) - IPC_MESSAGE_UNHANDLED_ERROR() - IPC_END_MESSAGE_MAP() -#endif - return false; -} - -bool GpuVideoService::IntializeGpuVideoService() { - return true; -} - -bool GpuVideoService::UnintializeGpuVideoService() { - return true; -} - -bool GpuVideoService::CreateVideoDecoder( - GpuChannel* channel, - MessageRouter* router, - int32 decoder_host_id, - int32 decoder_id, - gpu::gles2::GLES2Decoder* gles2_decoder) { - GpuVideoDecoderInfo decoder_info; - decoder_info.decoder = new GpuVideoDecoder(MessageLoop::current(), - decoder_host_id, - channel, - channel->renderer_process(), - gles2_decoder); - decoder_info.channel = channel; - decoder_map_[decoder_id] = decoder_info; - router->AddRoute(decoder_id, decoder_info.decoder); - - channel->Send(new GpuVideoDecoderHostMsg_CreateVideoDecoderDone( - decoder_host_id, decoder_id)); - return true; -} - -void GpuVideoService::DestroyVideoDecoder( - MessageRouter* router, - int32 decoder_id) { - router->RemoveRoute(decoder_id); - decoder_map_.erase(decoder_id); -} diff --git a/content/gpu/gpu_video_service.h b/content/gpu/gpu_video_service.h deleted file mode 100644 index 91f9261e..0000000 --- a/content/gpu/gpu_video_service.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef CONTENT_GPU_GPU_VIDEO_SERVICE_H_ -#define CONTENT_GPU_GPU_VIDEO_SERVICE_H_ - -#include - -#include "base/memory/ref_counted.h" -#include "base/memory/singleton.h" -#include "content/gpu/gpu_video_decoder.h" -#include "ipc/ipc_channel.h" - -class GpuChannel; - -class GpuVideoService : public IPC::Channel::Listener { - public: - static GpuVideoService* GetInstance(); - - // IPC::Channel::Listener. - virtual void OnChannelConnected(int32 peer_pid); - virtual void OnChannelError(); - virtual bool OnMessageReceived(const IPC::Message& message); - - // TODO(hclam): Remove return value. - bool CreateVideoDecoder(GpuChannel* channel, - MessageRouter* router, - int32 decoder_host_id, - int32 decoder_id, - gpu::gles2::GLES2Decoder* gles2_decoder); - void DestroyVideoDecoder(MessageRouter* router, - int32 decoder_id); - - private: - struct GpuVideoDecoderInfo; - - GpuVideoService(); - virtual ~GpuVideoService(); - - std::map decoder_map_; - - // Specialize video service on different platform will override. - virtual bool IntializeGpuVideoService(); - virtual bool UnintializeGpuVideoService(); - - friend struct DefaultSingletonTraits; - DISALLOW_COPY_AND_ASSIGN(GpuVideoService); -}; - -#endif // CONTENT_GPU_GPU_VIDEO_SERVICE_H_ diff --git a/content/gpu/media/fake_gl_video_decode_engine.cc b/content/gpu/media/fake_gl_video_decode_engine.cc deleted file mode 100644 index 0486a01..0000000 --- a/content/gpu/media/fake_gl_video_decode_engine.cc +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) 2011 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 "content/gpu/media/fake_gl_video_decode_engine.h" - -#include "media/base/limits.h" -#include "media/base/video_frame.h" -#include "media/video/video_decode_context.h" - -FakeGlVideoDecodeEngine::FakeGlVideoDecodeEngine() - : width_(0), - height_(0), - handler_(NULL), - context_(NULL) { -} - -FakeGlVideoDecodeEngine::~FakeGlVideoDecodeEngine() { -} - -void FakeGlVideoDecodeEngine::Initialize( - MessageLoop* message_loop, - media::VideoDecodeEngine::EventHandler* event_handler, - media::VideoDecodeContext* context, - const media::VideoCodecConfig& config) { - handler_ = event_handler; - context_ = context; - width_ = config.width(); - height_ = config.height(); - - // Create an internal VideoFrame that we can write to. This is going to be - // uploaded through VideoDecodeContext. - media::VideoFrame::CreateFrame( - media::VideoFrame::RGBA, width_, height_, base::TimeDelta(), - base::TimeDelta(), &internal_frame_); - memset(internal_frame_->data(media::VideoFrame::kRGBPlane), 0, - height_ * internal_frame_->stride(media::VideoFrame::kRGBPlane)); - - // Use VideoDecodeContext to allocate VideoFrame that can be consumed by - // external body. - // TODO(hclam): It is horrible to use constants everywhere in the code! - // The number of frames come from VideoRendererBase in the renderer, this is - // horrible! - context_->AllocateVideoFrames( - media::Limits::kMaxVideoFrames, width_, height_, media::VideoFrame::RGBA, - &external_frames_, - NewRunnableMethod(this, - &FakeGlVideoDecodeEngine::AllocationCompleteTask)); -} - -void FakeGlVideoDecodeEngine::AllocationCompleteTask() { - DCHECK(media::Limits::kMaxVideoFrames == external_frames_.size()); - DCHECK_EQ(media::VideoFrame::TYPE_GL_TEXTURE, external_frames_[0]->type()); - - media::VideoCodecInfo info; - info.success = true; - info.provides_buffers = true; - info.stream_info.surface_format = media::VideoFrame::RGBA; - info.stream_info.surface_type = media::VideoFrame::TYPE_GL_TEXTURE; - info.stream_info.surface_width = width_; - info.stream_info.surface_height = height_; - handler_->OnInitializeComplete(info); -} - -void FakeGlVideoDecodeEngine::Uninitialize() { - handler_->OnUninitializeComplete(); -} - -void FakeGlVideoDecodeEngine::Flush() { - handler_->OnFlushComplete(); -} - -void FakeGlVideoDecodeEngine::Seek() { - // TODO(hclam): This is a big hack to continue playing because we need to - // *push* decoded frames to downstream. The model used in VideoRendererBase - // to wait for *push* is flawed. - for (size_t i = 0; i < external_frames_.size(); ++i) - handler_->ConsumeVideoFrame(external_frames_[i], dummy_stats_); - handler_->OnSeekComplete(); -} - -void FakeGlVideoDecodeEngine::ConsumeVideoSample( - scoped_refptr sample) { - DCHECK(!pending_frames_.empty()); - scoped_refptr frame = pending_frames_.front(); - pending_frames_.pop(); - - frame->SetDuration(sample->GetDuration()); - frame->SetTimestamp(sample->GetTimestamp()); - - // Generate a pattern to the internal frame and then uploads it. - int size = width_ * height_ * 4; - scoped_array buffer(new uint8[size]); - memset(buffer.get(), 255, size); - - uint8* row = internal_frame_->data(media::VideoFrame::kRGBPlane); - static int seed = 0; - - for (int y = 0; y < height_; ++y) { - int offset = y % 3; - for (int x = 0; x < width_; ++x) { - row[x * 4 + offset + 1] = seed++; - seed &= 255; - } - row += width_ * 4; - } - ++seed; - - // After we have filled the content upload the internal frame to the - // VideoFrame allocated through VideoDecodeContext. - context_->ConvertToVideoFrame( - internal_frame_, frame, - NewRunnableMethod(this, &FakeGlVideoDecodeEngine::UploadCompleteTask, - frame)); -} - -void FakeGlVideoDecodeEngine::ProduceVideoFrame( - scoped_refptr frame) { - // Enqueue the frame to the pending queue. - pending_frames_.push(frame); - - // Fake that we need some buffer. - handler_->ProduceVideoSample(NULL); -} - -void FakeGlVideoDecodeEngine::UploadCompleteTask( - scoped_refptr frame) { - // |frame| is the upload target. We can immediately send this frame out. - handler_->ConsumeVideoFrame(frame, dummy_stats_); -} - -DISABLE_RUNNABLE_METHOD_REFCOUNT(FakeGlVideoDecodeEngine); diff --git a/content/gpu/media/fake_gl_video_decode_engine.h b/content/gpu/media/fake_gl_video_decode_engine.h deleted file mode 100644 index 899c84f..0000000 --- a/content/gpu/media/fake_gl_video_decode_engine.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef CONTENT_GPU_MEDIA_FAKE_GL_VIDEO_DECODE_ENGINE_H_ -#define CONTENT_GPU_MEDIA_FAKE_GL_VIDEO_DECODE_ENGINE_H_ - -#include -#include - -#include "base/memory/scoped_ptr.h" -#include "media/base/pipeline.h" -#include "media/video/video_decode_engine.h" - -namespace media { -class VideoDecodeContext; -class VideoFrame; -} // namespace media - -class FakeGlVideoDecodeEngine : public media::VideoDecodeEngine { - public: - FakeGlVideoDecodeEngine(); - virtual ~FakeGlVideoDecodeEngine(); - - virtual void Initialize( - MessageLoop* message_loop, - media::VideoDecodeEngine::EventHandler* event_handler, - media::VideoDecodeContext* context, - const media::VideoCodecConfig& config); - - virtual void Uninitialize(); - virtual void Flush(); - virtual void Seek(); - virtual void ConsumeVideoSample(scoped_refptr buffer); - virtual void ProduceVideoFrame(scoped_refptr frame); - - private: - // This method is called when video frames allocation is completed by - // VideoDecodeContext. - void AllocationCompleteTask(); - - // This method is called by VideoDecodeContext when uploading to a VideoFrame - // has completed. - void UploadCompleteTask(scoped_refptr frame); - - int width_; - int height_; - media::VideoDecodeEngine::EventHandler* handler_; - media::VideoDecodeContext* context_; - - // Internal video frame that is to be uploaded through VideoDecodeContext. - scoped_refptr internal_frame_; - - // VideoFrame(s) allocated through VideoDecodeContext. These frames are - // opaque to us. And we need an extra upload step. - std::vector > external_frames_; - - // These are the video frames that are waiting for input buffer to generate - // fake pattern in them. - std::queue > pending_frames_; - - // Dummy statistics. - media::PipelineStatistics dummy_stats_; - - DISALLOW_COPY_AND_ASSIGN(FakeGlVideoDecodeEngine); -}; - -#endif // CONTENT_GPU_MEDIA_FAKE_GL_VIDEO_DECODE_ENGINE_H_ diff --git a/content/gpu/media/fake_gl_video_device.cc b/content/gpu/media/fake_gl_video_device.cc deleted file mode 100644 index 18fb09e..0000000 --- a/content/gpu/media/fake_gl_video_device.cc +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2011 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 "content/gpu/media/fake_gl_video_device.h" - -#include "media/base/video_frame.h" -#include "ui/gfx/gl/gl_bindings.h" - -void* FakeGlVideoDevice::GetDevice() { - // No actual hardware device should be used. - return NULL; -} - -bool FakeGlVideoDevice::CreateVideoFrameFromGlTextures( - size_t width, size_t height, media::VideoFrame::Format format, - const std::vector& textures, - scoped_refptr* frame) { - media::VideoFrame::GlTexture texture_array[media::VideoFrame::kMaxPlanes]; - memset(texture_array, 0, sizeof(texture_array)); - - for (size_t i = 0; i < textures.size(); ++i) { - texture_array[i] = textures[i]; - } - - media::VideoFrame::CreateFrameGlTexture(format, - width, - height, - texture_array, - frame); - return *frame != NULL; -} - -void FakeGlVideoDevice::ReleaseVideoFrame( - const scoped_refptr& frame) { - // We didn't need to anything here because we didin't allocate any resources - // for the VideoFrame(s) generated. -} - -bool FakeGlVideoDevice::ConvertToVideoFrame( - void* buffer, scoped_refptr frame) { - // Assume we are in the right context and then upload the content to the - // texture. - glBindTexture(GL_TEXTURE_2D, - frame->gl_texture(media::VideoFrame::kRGBPlane)); - - // |buffer| is also a VideoFrame. - scoped_refptr frame_to_upload( - reinterpret_cast(buffer)); - DCHECK_EQ(frame->width(), frame_to_upload->width()); - DCHECK_EQ(frame->height(), frame_to_upload->height()); - DCHECK_EQ(frame->format(), frame_to_upload->format()); - glTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, frame_to_upload->width(), - frame_to_upload->height(), 0, GL_RGBA, - GL_UNSIGNED_BYTE, frame_to_upload->data(media::VideoFrame::kRGBPlane)); - return true; -} diff --git a/content/gpu/media/fake_gl_video_device.h b/content/gpu/media/fake_gl_video_device.h deleted file mode 100644 index f5acb1a..0000000 --- a/content/gpu/media/fake_gl_video_device.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef CONTENT_GPU_MEDIA_FAKE_GL_VIDEO_DEVICE_H_ -#define CONTENT_GPU_MEDIA_FAKE_GL_VIDEO_DEVICE_H_ - -#include "content/gpu/media/gpu_video_device.h" - -// A simple GpuVideoDevice that create VideoFrame with GL textures. -// It uploads frames in RGBA format in system memory to the GL texture. -class FakeGlVideoDevice : public GpuVideoDevice { - public: - virtual ~FakeGlVideoDevice() {} - - virtual void* GetDevice(); - virtual bool CreateVideoFrameFromGlTextures( - size_t width, size_t height, media::VideoFrame::Format format, - const std::vector& textures, - scoped_refptr* frame); - virtual void ReleaseVideoFrame( - const scoped_refptr& frame); - virtual bool ConvertToVideoFrame(void* buffer, - scoped_refptr frame); -}; - -#endif // CONTENT_GPU_MEDIA_FAKE_GL_VIDEO_DEVICE_H_ diff --git a/content/gpu/media/gpu_video_device.h b/content/gpu/media/gpu_video_device.h deleted file mode 100644 index dcba5f2..0000000 --- a/content/gpu/media/gpu_video_device.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef CONTENT_GPU_MEDIA_GPU_VIDEO_DEVICE_H_ -#define CONTENT_GPU_MEDIA_GPU_VIDEO_DEVICE_H_ - -#include - -#include "media/base/video_frame.h" -#include "media/video/video_decode_context.h" - -// A GpuVideoDevice is used by GpuVideoDecoder to allocate video frames -// meaningful to a corresponding VideoDecodeEngine. -// -// GpuVideoDecoder will provide a set of GL textures to this class and then -// GpuVideoDevice will transform the textures into a set of VideoFrame -// objects that can be used by VideoDecodeEngine. -// -// See text in GpuVideoDecoder for the overall flow for buffer allocation. -// -// Since all graphics commands execute on the main thread in the GPU process -// all the methods provided by this class are synchronous. -class GpuVideoDevice { - public: - virtual ~GpuVideoDevice() {} - - // Get the hardware video decoding device handle. - virtual void* GetDevice() = 0; - - // The following method is used by GpuVideoDecoder to create VideoFrame(s) - // associated with some GL textures. - // - // VideoFrame generated is used by VideoDecodeEngine for output buffer. - // - // |frame| will contain the VideoFrame generated. - // - // Return true if the operation was successful. - virtual bool CreateVideoFrameFromGlTextures( - size_t width, size_t height, media::VideoFrame::Format format, - const std::vector& textures, - scoped_refptr* frame) = 0; - - // Release VideoFrame generated. - virtual void ReleaseVideoFrame( - const scoped_refptr& frame) = 0; - - // Upload a device specific buffer to a VideoFrame object that can be used in - // the GPU process. - // - // Return true if successful. - virtual bool ConvertToVideoFrame(void* buffer, - scoped_refptr frame) = 0; -}; - -#endif // CONTENT_GPU_MEDIA_GPU_VIDEO_DEVICE_H_ diff --git a/content/gpu/media/mft_angle_video_device.cc b/content/gpu/media/mft_angle_video_device.cc deleted file mode 100644 index 355ffa3..0000000 --- a/content/gpu/media/mft_angle_video_device.cc +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2011 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 "content/gpu/media/mft_angle_video_device.h" - -#include - -#include "media/base/video_frame.h" -#include "third_party/angle/src/libGLESv2/main.h" - -MftAngleVideoDevice::MftAngleVideoDevice() - : device_(reinterpret_cast( - eglGetCurrentDisplay())->getDevice()) { -} - -void* MftAngleVideoDevice::GetDevice() { - return device_; -} - -bool MftAngleVideoDevice::CreateVideoFrameFromGlTextures( - size_t width, size_t height, media::VideoFrame::Format format, - const std::vector& textures, - scoped_refptr* frame) { - media::VideoFrame::GlTexture texture_array[media::VideoFrame::kMaxPlanes]; - memset(texture_array, 0, sizeof(texture_array)); - - for (size_t i = 0; i < textures.size(); ++i) { - texture_array[i] = textures[i]; - } - - media::VideoFrame::CreateFrameGlTexture(format, - width, - height, - texture_array, - frame); - return *frame != NULL; -} - -void MftAngleVideoDevice::ReleaseVideoFrame( - const scoped_refptr& frame) { - // We didn't need to anything here because we didn't allocate any resources - // for the VideoFrame(s) generated. -} - -bool MftAngleVideoDevice::ConvertToVideoFrame( - void* buffer, scoped_refptr frame) { - gl::Context* context = (gl::Context*)eglGetCurrentContext(); - // TODO(hclam): Connect ANGLE to upload the surface to texture when changes - // to ANGLE is done. - return true; -} diff --git a/content/gpu/media/mft_angle_video_device.h b/content/gpu/media/mft_angle_video_device.h deleted file mode 100644 index 6d85de2..0000000 --- a/content/gpu/media/mft_angle_video_device.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef CONTENT_GPU_MEDIA_MFT_ANGLE_VIDEO_DEVICE_H_ -#define CONTENT_GPU_MEDIA_MFT_ANGLE_VIDEO_DEVICE_H_ - -#include "base/scoped_comptr_win.h" -#include "content/gpu/media/gpu_video_device.h" - -struct IDirect3DDevice9; -extern "C" const GUID IID_IDirect3DDevice9; - -namespace media { -class VideoFrame; -} // namespace media - -// This class is used to provide hardware video device, video frames and -// allow video frames to be uploaded to their final render target. -// -// This specifically serves MftH264DecodeEngine in the context of ANGLE. -class MftAngleVideoDevice : public GpuVideoDevice { - public: - MftAngleVideoDevice(); - virtual ~MftAngleVideoDevice() {} - - // GpuVideoDevice implementation. - virtual void* GetDevice(); - virtual bool CreateVideoFrameFromGlTextures( - size_t width, size_t height, media::VideoFrame::Format format, - const std::vector& textures, - scoped_refptr* frame); - virtual void ReleaseVideoFrame( - const scoped_refptr& frame); - virtual bool ConvertToVideoFrame(void* buffer, - scoped_refptr frame); - - private: - ScopedComPtr device_; -}; - -#endif // CONTENT_GPU_MEDIA_MFT_ANGLE_VIDEO_DEVICE_H_ diff --git a/content/gpu/x_util.cc b/content/gpu/x_util.cc deleted file mode 100644 index 72089e6..0000000 --- a/content/gpu/x_util.cc +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2011 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 "content/gpu/x_util.h" - -#include - -void ScopedPtrXFree::operator()(void* x) const { - ::XFree(x); -} diff --git a/content/gpu/x_util.h b/content/gpu/x_util.h deleted file mode 100644 index c854080..0000000 --- a/content/gpu/x_util.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2010 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. - -#ifndef CHROME_GPU_X_UTIL_H_ -#define CHROME_GPU_X_UTIL_H_ -#pragma once - -// Some X-Windows specific stuff. This can be included on any platform, and will -// be a NOP on non-Linux ones. - -#include "build/build_config.h" -#include "content/gpu/gpu_config.h" - -#if defined(OS_LINUX) - -// Forward declares ------------------------------------------------------------ -// -// X Windows headers do a lot of evil stuff, like "#define Status int" which -// will cause many problems when combined with our other header files (like -// ones that define a class local enum called "Status." -// -// These definitions are not Kosher, but allow us to remove this dependency and -// actually compile X at all. - -typedef unsigned long XID; - -extern "C" { - -typedef struct _XDisplay Display; -typedef struct __GLXcontextRec *GLXContext; - -} // extern "C" - -// Utils ----------------------------------------------------------------------- - -// scoped_ptr functor for XFree(). Use as follows: -// scoped_ptr_mallox foo(...); -// where "XVisualInfo" is any X type that is freed with XFree. -class ScopedPtrXFree { - public: - void operator()(void* x) const; -}; - -#endif // OS_LINUX - -#endif // CHROME_GPU_X_UTIL_H_ diff --git a/content/renderer/gpu_channel_host.h b/content/renderer/gpu_channel_host.h index c39652f..fa1d60d 100644 --- a/content/renderer/gpu_channel_host.h +++ b/content/renderer/gpu_channel_host.h @@ -12,7 +12,7 @@ #include "base/hash_tables.h" #include "base/memory/scoped_ptr.h" #include "base/process_util.h" -#include "content/common/gpu_info.h" +#include "content/common/gpu/gpu_info.h" #include "content/common/message_router.h" #include "ipc/ipc_channel_handle.h" #include "ipc/ipc_sync_channel.h" -- cgit v1.1