#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop_proxy.h"
-#include "base/rand_util.h"
+#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/timer/timer.h"
+#include "content/common/gpu/devtools_gpu_agent.h"
#include "content/common/gpu/gpu_channel_manager.h"
#include "content/common/gpu/gpu_messages.h"
-#include "content/common/gpu/media/gpu_video_encode_accelerator.h"
#include "content/common/gpu/sync_point_manager.h"
#include "content/public/common/content_switches.h"
-#include "crypto/hmac.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/service/gpu_scheduler.h"
#include "gpu/command_buffer/service/image_manager.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "ipc/ipc_channel.h"
-#include "ipc/ipc_channel_proxy.h"
+#include "ipc/message_filter.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_image.h"
#include "ui/gl/gl_surface.h"
#include "ipc/ipc_channel_posix.h"
#endif
-#if defined(OS_ANDROID)
-#include "content/common/gpu/stream_texture_manager_android.h"
-#endif
-
namespace content {
namespace {
// posting a task to insert the GpuCommandBufferMsg_RetireSyncPoint message
// into the channel's queue.
// - it generates mailbox names for clients of the GPU process on the IO thread.
-class GpuChannelMessageFilter : public IPC::ChannelProxy::MessageFilter {
+class GpuChannelMessageFilter : public IPC::MessageFilter {
public:
- // Takes ownership of gpu_channel (see below).
- GpuChannelMessageFilter(const std::string& private_key,
- base::WeakPtr<GpuChannel>* gpu_channel,
+ GpuChannelMessageFilter(base::WeakPtr<GpuChannel> gpu_channel,
scoped_refptr<SyncPointManager> sync_point_manager,
scoped_refptr<base::MessageLoopProxy> message_loop)
: preemption_state_(IDLE),
gpu_channel_(gpu_channel),
- channel_(NULL),
+ sender_(NULL),
sync_point_manager_(sync_point_manager),
message_loop_(message_loop),
messages_forwarded_to_channel_(0),
- a_stub_is_descheduled_(false),
- hmac_(crypto::HMAC::SHA256) {
- bool success = hmac_.Init(base::StringPiece(private_key));
- DCHECK(success);
- }
+ a_stub_is_descheduled_(false) {}
- virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE {
- DCHECK(!channel_);
- channel_ = channel;
+ virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE {
+ DCHECK(!sender_);
+ sender_ = sender;
}
virtual void OnFilterRemoved() OVERRIDE {
- DCHECK(channel_);
- channel_ = NULL;
+ DCHECK(sender_);
+ sender_ = NULL;
}
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
- DCHECK(channel_);
-
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(GpuChannelMessageFilter, message)
- IPC_MESSAGE_HANDLER(GpuChannelMsg_GenerateMailboxNames,
- OnGenerateMailboxNames)
- IPC_MESSAGE_HANDLER(GpuChannelMsg_GenerateMailboxNamesAsync,
- OnGenerateMailboxNamesAsync)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
+ DCHECK(sender_);
+ bool handled = false;
if (message.type() == GpuCommandBufferMsg_RetireSyncPoint::ID) {
// This message should not be sent explicitly by the renderer.
- NOTREACHED();
+ DLOG(ERROR) << "Client should not send "
+ "GpuCommandBufferMsg_RetireSyncPoint message";
handled = true;
}
}
bool Send(IPC::Message* message) {
- return channel_->Send(message);
+ return sender_->Send(message);
}
protected:
- virtual ~GpuChannelMessageFilter() {
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &GpuChannelMessageFilter::DeleteWeakPtrOnMainThread, gpu_channel_));
- }
+ virtual ~GpuChannelMessageFilter() {}
private:
- // Message handlers.
- void OnGenerateMailboxNames(unsigned num, std::vector<gpu::Mailbox>* result) {
- TRACE_EVENT1("gpu", "OnGenerateMailboxNames", "num", num);
-
- result->resize(num);
-
- for (unsigned i = 0; i < num; ++i) {
- char name[GL_MAILBOX_SIZE_CHROMIUM];
- base::RandBytes(name, sizeof(name) / 2);
-
- bool success = hmac_.Sign(
- base::StringPiece(name, sizeof(name) / 2),
- reinterpret_cast<unsigned char*>(name) + sizeof(name) / 2,
- sizeof(name) / 2);
- DCHECK(success);
-
- (*result)[i].SetName(reinterpret_cast<int8*>(name));
- }
- }
-
- void OnGenerateMailboxNamesAsync(unsigned num) {
- std::vector<gpu::Mailbox> names;
- OnGenerateMailboxNames(num, &names);
- Send(new GpuChannelMsg_GenerateMailboxNamesReply(names));
- }
-
enum PreemptionState {
// Either there's no other channel to preempt, there are no messages
// pending processing, or we just finished preempting and have to wait
}
static void InsertSyncPointOnMainThread(
- base::WeakPtr<GpuChannel>* gpu_channel,
+ base::WeakPtr<GpuChannel> gpu_channel,
scoped_refptr<SyncPointManager> manager,
int32 routing_id,
uint32 sync_point) {
// with it, but if that fails for any reason (channel or stub already
// deleted, invalid routing id), we need to retire the sync point
// immediately.
- if (gpu_channel->get()) {
- GpuCommandBufferStub* stub = gpu_channel->get()->LookupCommandBuffer(
- routing_id);
+ if (gpu_channel) {
+ GpuCommandBufferStub* stub = gpu_channel->LookupCommandBuffer(routing_id);
if (stub) {
stub->AddSyncPoint(sync_point);
GpuCommandBufferMsg_RetireSyncPoint message(routing_id, sync_point);
- gpu_channel->get()->OnMessageReceived(message);
+ gpu_channel->OnMessageReceived(message);
return;
} else {
- gpu_channel->get()->MessageProcessed();
+ gpu_channel->MessageProcessed();
}
}
manager->RetireSyncPoint(sync_point);
}
- static void DeleteWeakPtrOnMainThread(
- base::WeakPtr<GpuChannel>* gpu_channel) {
- delete gpu_channel;
- }
-
- // NOTE: this is a pointer to a weak pointer. It is never dereferenced on the
- // IO thread, it's only passed through - therefore the WeakPtr assumptions are
- // respected.
- base::WeakPtr<GpuChannel>* gpu_channel_;
- IPC::Channel* channel_;
+ // NOTE: this weak pointer is never dereferenced on the IO thread, it's only
+ // passed through - therefore the WeakPtr assumptions are respected.
+ base::WeakPtr<GpuChannel> gpu_channel_;
+ IPC::Sender* sender_;
scoped_refptr<SyncPointManager> sync_point_manager_;
scoped_refptr<base::MessageLoopProxy> message_loop_;
scoped_refptr<gpu::PreemptionFlag> preempting_flag_;
base::OneShotTimer<GpuChannelMessageFilter> timer_;
bool a_stub_is_descheduled_;
-
- crypto::HMAC hmac_;
};
GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager,
watchdog_(watchdog),
software_(software),
handle_messages_scheduled_(false),
- processed_get_state_fast_(false),
currently_processing_message_(NULL),
weak_factory_(this),
num_stubs_descheduled_(0) {
channel_id_ = IPC::Channel::GenerateVerifiedChannelID("gpu");
const CommandLine* command_line = CommandLine::ForCurrentProcess();
log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages);
- disallowed_features_.multisampling =
- command_line->HasSwitch(switches::kDisableGLMultisampling);
-#if defined(OS_ANDROID)
- stream_texture_manager_.reset(new StreamTextureManagerAndroid(this));
-#endif
}
+GpuChannel::~GpuChannel() {
+ STLDeleteElements(&deferred_messages_);
+ if (preempting_flag_.get())
+ preempting_flag_->Reset();
+}
-bool GpuChannel::Init(base::MessageLoopProxy* io_message_loop,
+void GpuChannel::Init(base::MessageLoopProxy* io_message_loop,
base::WaitableEvent* shutdown_event) {
DCHECK(!channel_.get());
// Map renderer ID to a (single) channel to that process.
- channel_.reset(new IPC::SyncChannel(
- channel_id_,
- IPC::Channel::MODE_SERVER,
- this,
- io_message_loop,
- false,
- shutdown_event));
-
- base::WeakPtr<GpuChannel>* weak_ptr(new base::WeakPtr<GpuChannel>(
- weak_factory_.GetWeakPtr()));
-
- filter_ = new GpuChannelMessageFilter(
- mailbox_manager_->private_key(),
- weak_ptr,
- gpu_channel_manager_->sync_point_manager(),
- base::MessageLoopProxy::current());
+ channel_ = IPC::SyncChannel::Create(channel_id_,
+ IPC::Channel::MODE_SERVER,
+ this,
+ io_message_loop,
+ false,
+ shutdown_event);
+
+ filter_ =
+ new GpuChannelMessageFilter(weak_factory_.GetWeakPtr(),
+ gpu_channel_manager_->sync_point_manager(),
+ base::MessageLoopProxy::current());
io_message_loop_ = io_message_loop;
channel_->AddFilter(filter_.get());
- return true;
+ devtools_gpu_agent_.reset(new DevToolsGpuAgent(this));
}
std::string GpuChannel::GetChannelName() {
<< " with type " << message.type();
}
- if (message.type() == GpuCommandBufferMsg_GetStateFast::ID) {
- if (processed_get_state_fast_) {
- // Require a non-GetStateFast message in between two GetStateFast
- // messages, to ensure progress is made.
- std::deque<IPC::Message*>::iterator point = deferred_messages_.begin();
-
- while (point != deferred_messages_.end() &&
- (*point)->type() == GpuCommandBufferMsg_GetStateFast::ID) {
- ++point;
- }
-
- if (point != deferred_messages_.end()) {
- ++point;
- }
-
- deferred_messages_.insert(point, new IPC::Message(message));
- } else {
- // Move GetStateFast commands to the head of the queue, so the renderer
- // doesn't have to wait any longer than necessary.
- deferred_messages_.push_front(new IPC::Message(message));
- }
+ if (message.type() == GpuCommandBufferMsg_WaitForTokenInRange::ID ||
+ message.type() == GpuCommandBufferMsg_WaitForGetOffsetInRange::ID) {
+ // Move Wait commands to the head of the queue, so the renderer
+ // doesn't have to wait any longer than necessary.
+ deferred_messages_.push_front(new IPC::Message(message));
} else {
deferred_messages_.push_back(new IPC::Message(message));
}
}
}
-void GpuChannel::CreateViewCommandBuffer(
+CreateCommandBufferResult GpuChannel::CreateViewCommandBuffer(
const gfx::GLSurfaceHandle& window,
int32 surface_id,
const GPUCreateCommandBufferConfig& init_params,
- int32* route_id) {
+ int32 route_id) {
TRACE_EVENT1("gpu",
"GpuChannel::CreateViewCommandBuffer",
"surface_id",
surface_id);
- *route_id = MSG_ROUTING_NONE;
-
GpuCommandBufferStub* share_group = stubs_.Lookup(init_params.share_group_id);
// Virtualize compositor contexts on OS X to prevent performance regressions
use_virtualized_gl_context = true;
#endif
- *route_id = GenerateRouteID();
scoped_ptr<GpuCommandBufferStub> stub(
new GpuCommandBufferStub(this,
share_group,
init_params.attribs,
init_params.gpu_preference,
use_virtualized_gl_context,
- *route_id,
+ route_id,
surface_id,
watchdog_,
software_,
init_params.active_url));
if (preempted_flag_.get())
stub->SetPreemptByFlag(preempted_flag_);
- router_.AddRoute(*route_id, stub.get());
- stubs_.AddWithID(stub.release(), *route_id);
+ if (!router_.AddRoute(route_id, stub.get())) {
+ DLOG(ERROR) << "GpuChannel::CreateViewCommandBuffer(): "
+ "failed to add route";
+ return CREATE_COMMAND_BUFFER_FAILED_AND_CHANNEL_LOST;
+ }
+ stubs_.AddWithID(stub.release(), route_id);
+ return CREATE_COMMAND_BUFFER_SUCCEEDED;
}
GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32 route_id) {
}
}
-void GpuChannel::DestroySoon() {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&GpuChannel::OnDestroy, this));
-}
-
-int GpuChannel::GenerateRouteID() {
- static int last_id = 0;
- return ++last_id;
-}
-
-void GpuChannel::AddRoute(int32 route_id, IPC::Listener* listener) {
- router_.AddRoute(route_id, listener);
+bool GpuChannel::AddRoute(int32 route_id, IPC::Listener* listener) {
+ return router_.AddRoute(route_id, listener);
}
void GpuChannel::RemoveRoute(int32 route_id) {
}
}
-GpuChannel::~GpuChannel() {
- if (preempting_flag_.get())
- preempting_flag_->Reset();
-}
-
void GpuChannel::OnDestroy() {
TRACE_EVENT0("gpu", "GpuChannel::OnDestroy");
gpu_channel_manager_->RemoveChannel(client_id_);
OnCreateOffscreenCommandBuffer)
IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyCommandBuffer,
OnDestroyCommandBuffer)
- IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateVideoEncoder, OnCreateVideoEncoder)
- IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyVideoEncoder,
- OnDestroyVideoEncoder)
-#if defined(OS_ANDROID)
- IPC_MESSAGE_HANDLER(GpuChannelMsg_RegisterStreamTextureProxy,
- OnRegisterStreamTextureProxy)
- IPC_MESSAGE_HANDLER(GpuChannelMsg_EstablishStreamTexture,
- OnEstablishStreamTexture)
- IPC_MESSAGE_HANDLER(GpuChannelMsg_SetStreamTextureSize,
- OnSetStreamTextureSize)
-#endif
- IPC_MESSAGE_HANDLER(
- GpuChannelMsg_CollectRenderingStatsForSurface,
- OnCollectRenderingStatsForSurface)
+ IPC_MESSAGE_HANDLER(GpuChannelMsg_DevToolsStartEventsRecording,
+ OnDevToolsStartEventsRecording)
+ IPC_MESSAGE_HANDLER(GpuChannelMsg_DevToolsStopEventsRecording,
+ OnDevToolsStopEventsRecording)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
DCHECK(handled) << msg.type();
deferred_messages_.pop_front();
bool message_processed = true;
- processed_get_state_fast_ =
- (message->type() == GpuCommandBufferMsg_GetStateFast::ID);
-
currently_processing_message_ = message.get();
bool result;
if (message->routing_id() == MSG_ROUTING_CONTROL)
void GpuChannel::OnCreateOffscreenCommandBuffer(
const gfx::Size& size,
const GPUCreateCommandBufferConfig& init_params,
- int32* route_id) {
+ int32 route_id,
+ bool* succeeded) {
TRACE_EVENT0("gpu", "GpuChannel::OnCreateOffscreenCommandBuffer");
GpuCommandBufferStub* share_group = stubs_.Lookup(init_params.share_group_id);
- *route_id = GenerateRouteID();
-
scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub(
this,
share_group,
init_params.attribs,
init_params.gpu_preference,
false,
- *route_id,
+ route_id,
0,
watchdog_,
software_,
init_params.active_url));
if (preempted_flag_.get())
stub->SetPreemptByFlag(preempted_flag_);
- router_.AddRoute(*route_id, stub.get());
- stubs_.AddWithID(stub.release(), *route_id);
+ if (!router_.AddRoute(route_id, stub.get())) {
+ DLOG(ERROR) << "GpuChannel::OnCreateOffscreenCommandBuffer(): "
+ "failed to add route";
+ *succeeded = false;
+ return;
+ }
+ stubs_.AddWithID(stub.release(), route_id);
TRACE_EVENT1("gpu", "GpuChannel::OnCreateOffscreenCommandBuffer",
"route_id", route_id);
+ *succeeded = true;
}
void GpuChannel::OnDestroyCommandBuffer(int32 route_id) {
}
}
-void GpuChannel::OnCreateVideoEncoder(int32* route_id) {
- TRACE_EVENT0("gpu", "GpuChannel::OnCreateVideoEncoder");
-
- *route_id = GenerateRouteID();
- GpuVideoEncodeAccelerator* encoder =
- new GpuVideoEncodeAccelerator(this, *route_id);
- router_.AddRoute(*route_id, encoder);
- video_encoders_.AddWithID(encoder, *route_id);
-}
-
-void GpuChannel::OnDestroyVideoEncoder(int32 route_id) {
- TRACE_EVENT1(
- "gpu", "GpuChannel::OnDestroyVideoEncoder", "route_id", route_id);
- GpuVideoEncodeAccelerator* encoder = video_encoders_.Lookup(route_id);
- if (!encoder)
- return;
- router_.RemoveRoute(route_id);
- video_encoders_.Remove(route_id);
-}
-
-#if defined(OS_ANDROID)
-void GpuChannel::OnRegisterStreamTextureProxy(
- int32 stream_id, int32* route_id) {
- // Note that route_id is only used for notifications sent out from here.
- // StreamTextureManager owns all texture objects and for incoming messages
- // it finds the correct object based on stream_id.
- *route_id = GenerateRouteID();
- stream_texture_manager_->RegisterStreamTextureProxy(stream_id, *route_id);
-}
-
-void GpuChannel::OnEstablishStreamTexture(
- int32 stream_id, int32 primary_id, int32 secondary_id) {
- stream_texture_manager_->EstablishStreamTexture(
- stream_id, primary_id, secondary_id);
+void GpuChannel::OnDevToolsStartEventsRecording(int32 route_id,
+ bool* succeeded) {
+ *succeeded = devtools_gpu_agent_->StartEventsRecording(route_id);
}
-void GpuChannel::OnSetStreamTextureSize(
- int32 stream_id, const gfx::Size& size) {
- stream_texture_manager_->SetStreamTextureSize(stream_id, size);
-}
-#endif
-
-void GpuChannel::OnCollectRenderingStatsForSurface(
- int32 surface_id, GpuRenderingStats* stats) {
- for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_);
- !it.IsAtEnd(); it.Advance()) {
- int texture_upload_count =
- it.GetCurrentValue()->decoder()->GetTextureUploadCount();
- base::TimeDelta total_texture_upload_time =
- it.GetCurrentValue()->decoder()->GetTotalTextureUploadTime();
- base::TimeDelta total_processing_commands_time =
- it.GetCurrentValue()->decoder()->GetTotalProcessingCommandsTime();
-
- stats->global_texture_upload_count += texture_upload_count;
- stats->global_total_texture_upload_time += total_texture_upload_time;
- stats->global_total_processing_commands_time +=
- total_processing_commands_time;
- if (it.GetCurrentValue()->surface_id() == surface_id) {
- stats->texture_upload_count += texture_upload_count;
- stats->total_texture_upload_time += total_texture_upload_time;
- stats->total_processing_commands_time += total_processing_commands_time;
- }
- }
-
- GPUVideoMemoryUsageStats usage_stats;
- gpu_channel_manager_->gpu_memory_manager()->GetVideoMemoryUsageStats(
- &usage_stats);
- stats->global_video_memory_bytes_allocated = usage_stats.bytes_allocated;
+void GpuChannel::OnDevToolsStopEventsRecording() {
+ devtools_gpu_agent_->StopEventsRecording();
}
void GpuChannel::MessageProcessed() {
new GpuHostMsg_CacheShader(client_id_, key, shader));
}
-void GpuChannel::AddFilter(IPC::ChannelProxy::MessageFilter* filter) {
+void GpuChannel::AddFilter(IPC::MessageFilter* filter) {
channel_->AddFilter(filter);
}
-void GpuChannel::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) {
+void GpuChannel::RemoveFilter(IPC::MessageFilter* filter) {
channel_->RemoveFilter(filter);
}
+uint64 GpuChannel::GetMemoryUsage() {
+ uint64 size = 0;
+ for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_);
+ !it.IsAtEnd(); it.Advance()) {
+ size += it.GetCurrentValue()->GetMemoryUsage();
+ }
+ return size;
+}
+
} // namespace content