Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(840)

Unified Diff: content/common/gpu/gpu_channel.cc

Issue 7253052: Execute all GL commands up to the put offset reported by a flush. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/common/gpu/gpu_channel.h ('k') | content/common/gpu/gpu_command_buffer_stub.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/common/gpu/gpu_channel.cc
===================================================================
--- content/common/gpu/gpu_channel.cc (revision 92876)
+++ content/common/gpu/gpu_channel.cc (working copy)
@@ -33,7 +33,8 @@
renderer_process_(base::kNullProcessHandle),
renderer_pid_(base::kNullProcessId),
share_group_(new gfx::GLShareGroup),
- watchdog_(watchdog) {
+ watchdog_(watchdog),
+ task_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
DCHECK(gpu_channel_manager);
DCHECK(renderer_id);
const CommandLine* command_line = CommandLine::ForCurrentProcess();
@@ -86,9 +87,20 @@
<< " with type " << message.type();
}
+ // Control messages are not deferred and can be handled out of order with
+ // respect to routed ones.
if (message.routing_id() == MSG_ROUTING_CONTROL)
return OnControlMessageReceived(message);
+ // If the channel is unscheduled, defer sync and async messages until it is
+ // rescheduled. Also, even if the channel is scheduled, do not allow newly
+ // received messages to be handled before previously received deferred ones;
+ // append them to the deferred queue as well.
+ if (!IsScheduled() || !deferred_messages_.empty()) {
+ deferred_messages_.push(new IPC::Message(message));
+ return true;
+ }
+
if (!router_.RouteMessage(message)) {
// Respond to sync messages even if router failed to route.
if (message.is_sync()) {
@@ -99,6 +111,20 @@
return false;
}
+ // If the channel becomes unscheduled as a result of handling the message,
+ // synthesize an IPC message to flush the command buffer that became
+ // unscheduled.
+ for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_);
+ !it.IsAtEnd();
+ it.Advance()) {
+ GpuCommandBufferStub* stub = it.GetCurrentValue();
+ if (!stub->IsScheduled()) {
+ DCHECK(deferred_messages_.empty());
+ deferred_messages_.push(new GpuCommandBufferMsg_Rescheduled(
+ stub->route_id()));
+ }
+ }
+
return true;
}
@@ -127,6 +153,30 @@
return channel_->Send(message);
}
+bool GpuChannel::IsScheduled() {
+ for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_);
+ !it.IsAtEnd();
+ it.Advance()) {
+ GpuCommandBufferStub* stub = it.GetCurrentValue();
+ if (!stub->IsScheduled())
+ return false;
+ }
+
+ return true;
+}
+
+void GpuChannel::OnScheduled() {
+ // Post a task to handle any deferred messages. The deferred message queue is
+ // not emptied here, which ensures that OnMessageReceived will continue to
+ // defer newly received messages until the ones in the queue have all been
+ // handled by HandleDeferredMessages. HandleDeferredMessages is invoked as a
+ // task to prevent reentrancy.
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ task_factory_.NewRunnableMethod(
+ &GpuChannel::HandleDeferredMessages));
+}
+
void GpuChannel::LoseAllContexts() {
gpu_channel_manager_->LoseAllContexts();
}
@@ -218,7 +268,7 @@
// 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());
+ OnDestroyCommandBuffer(iter.GetCurrentKey(), NULL);
return;
}
}
@@ -226,15 +276,17 @@
#endif
bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) {
+ // Always use IPC_MESSAGE_HANDLER_DELAY_REPLY for synchronous message handlers
+ // here. This is so the reply can be delayed if the scheduler is unscheduled.
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_CreateOffscreenSurface,
- OnCreateOffscreenSurface)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuChannelMsg_CreateOffscreenCommandBuffer,
+ OnCreateOffscreenCommandBuffer)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuChannelMsg_DestroyCommandBuffer,
+ OnDestroyCommandBuffer)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuChannelMsg_CreateOffscreenSurface,
+ OnCreateOffscreenSurface)
IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroySurface, OnDestroySurface)
IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateTransportTexture,
OnCreateTransportTexture)
@@ -244,6 +296,21 @@
return handled;
}
+void GpuChannel::HandleDeferredMessages() {
+ // Empty the deferred queue so OnMessageRecieved does not defer on that
+ // account and to prevent an infinite loop if the scheduler is unscheduled
+ // as a result of handling already deferred messages.
+ std::queue<IPC::Message*> deferred_messages_copy;
+ std::swap(deferred_messages_copy, deferred_messages_);
+
+ while (!deferred_messages_copy.empty()) {
+ scoped_ptr<IPC::Message> message(deferred_messages_copy.front());
+ deferred_messages_copy.pop();
+
+ OnMessageReceived(*message);
+ }
+}
+
int GpuChannel::GenerateRouteID() {
static int last_id = 0;
return ++last_id;
@@ -261,10 +328,12 @@
void GpuChannel::OnCreateOffscreenCommandBuffer(
const gfx::Size& size,
const GPUCreateCommandBufferConfig& init_params,
- int32* route_id) {
+ IPC::Message* reply_message) {
+ int32 route_id = MSG_ROUTING_NONE;
+
content::GetContentClient()->SetActiveURL(init_params.active_url);
#if defined(ENABLE_GPU)
- *route_id = GenerateRouteID();
+ route_id = GenerateRouteID();
scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub(
this,
@@ -273,36 +342,38 @@
disallowed_extensions_,
init_params.allowed_extensions,
init_params.attribs,
- *route_id,
+ route_id,
0, 0, watchdog_));
- router_.AddRoute(*route_id, stub.get());
- stubs_.AddWithID(stub.release(), *route_id);
+ router_.AddRoute(route_id, stub.get());
+ stubs_.AddWithID(stub.release(), route_id);
TRACE_EVENT1("gpu", "GpuChannel::OnCreateOffscreenCommandBuffer",
"route_id", route_id);
-#else
- *route_id = MSG_ROUTING_NONE;
#endif
+
+ GpuChannelMsg_CreateOffscreenCommandBuffer::WriteReplyParams(
+ reply_message,
+ route_id);
+ Send(reply_message);
}
-void GpuChannel::OnDestroyCommandBuffer(int32 route_id) {
+void GpuChannel::OnDestroyCommandBuffer(int32 route_id,
+ IPC::Message* reply_message) {
#if defined(ENABLE_GPU)
TRACE_EVENT1("gpu", "GpuChannel::OnDestroyCommandBuffer",
"route_id", route_id);
if (router_.ResolveRoute(route_id)) {
- GpuCommandBufferStub* stub = stubs_.Lookup(route_id);
- // In case the renderer is currently blocked waiting for a sync reply from
- // the stub, allow the stub to clean up and unblock pending messages here:
- if (stub != NULL)
- stub->CommandBufferWasDestroyed();
router_.RemoveRoute(route_id);
stubs_.Remove(route_id);
}
#endif
+
+ if (reply_message)
+ Send(reply_message);
}
void GpuChannel::OnCreateOffscreenSurface(const gfx::Size& size,
- int* route_id) {
- *route_id = MSG_ROUTING_NONE;
+ IPC::Message* reply_message) {
+ int route_id = MSG_ROUTING_NONE;
#if defined(ENABLE_GPU)
scoped_refptr<gfx::GLSurface> surface(
@@ -310,15 +381,19 @@
if (!surface.get())
return;
- *route_id = GenerateRouteID();
+ route_id = GenerateRouteID();
scoped_ptr<GpuSurfaceStub> stub (new GpuSurfaceStub(this,
- *route_id,
+ route_id,
surface.release()));
- router_.AddRoute(*route_id, stub.get());
- surfaces_.AddWithID(stub.release(), *route_id);
+ router_.AddRoute(route_id, stub.get());
+ surfaces_.AddWithID(stub.release(), route_id);
#endif
+
+ GpuChannelMsg_CreateOffscreenSurface::WriteReplyParams(reply_message,
+ route_id);
+ Send(reply_message);
}
void GpuChannel::OnDestroySurface(int route_id) {
« no previous file with comments | « content/common/gpu/gpu_channel.h ('k') | content/common/gpu/gpu_command_buffer_stub.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698