15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_channel.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <queue>
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/stl_util.h"
197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h"
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h"
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/common/gpu/devtools_gpu_agent.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_channel_manager.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_messages.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/sync_point_manager.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_switches.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "gpu/command_buffer/common/mailbox.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "gpu/command_buffer/service/gpu_scheduler.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/image_manager.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/mailbox_manager.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_channel.h"
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ipc/message_filter.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_image.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_surface.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_channel_posix.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Number of milliseconds between successive vsync. Many GL commands block
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// on vsync, so thresholds for preemption should be multiples of this.
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kVsyncIntervalMs = 17;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Amount of time that we will wait for an IPC to be processed before
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// preempting. After a preemption, we must wait this long before triggering
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// another preemption.
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kPreemptWaitTimeMs = 2 * kVsyncIntervalMs;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Once we trigger a preemption, the maximum duration that we will wait
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// before clearing the preemption.
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kMaxPreemptTimeMs = kVsyncIntervalMs;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Stop the preemption once the time for the longest pending IPC drops
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// below this threshold.
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kStopPreemptThresholdMs = kVsyncIntervalMs;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // anonymous namespace
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This filter does three things:
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// - it counts and timestamps each message forwarded to the channel
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   so that we can preempt other channels if a message takes too long to
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   process. To guarantee fairness, we must wait a minimum amount of time
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   before preempting and we limit the amount of time that we can preempt in
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   one shot (see constants above).
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - it handles the GpuCommandBufferMsg_InsertSyncPoint message on the IO
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   thread, generating the sync point ID and responding immediately, and then
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   posting a task to insert the GpuCommandBufferMsg_RetireSyncPoint message
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   into the channel's queue.
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// - it generates mailbox names for clients of the GPU process on the IO thread.
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass GpuChannelMessageFilter : public IPC::MessageFilter {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GpuChannelMessageFilter(base::WeakPtr<GpuChannel> gpu_channel,
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          scoped_refptr<SyncPointManager> sync_point_manager,
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          scoped_refptr<base::MessageLoopProxy> message_loop)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : preemption_state_(IDLE),
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        gpu_channel_(gpu_channel),
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        sender_(NULL),
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sync_point_manager_(sync_point_manager),
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        message_loop_(message_loop),
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        messages_forwarded_to_channel_(0),
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        a_stub_is_descheduled_(false) {}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE {
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DCHECK(!sender_);
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    sender_ = sender;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnFilterRemoved() OVERRIDE {
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DCHECK(sender_);
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    sender_ = NULL;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DCHECK(sender_);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool handled = false;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (message.type() == GpuCommandBufferMsg_RetireSyncPoint::ID) {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // This message should not be sent explicitly by the renderer.
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DLOG(ERROR) << "Client should not send "
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     "GpuCommandBufferMsg_RetireSyncPoint message";
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      handled = true;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // All other messages get processed by the GpuChannel.
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!handled) {
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      messages_forwarded_to_channel_++;
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (preempting_flag_.get())
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pending_messages_.push(PendingMessage(messages_forwarded_to_channel_));
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatePreemptionState();
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (message.type() == GpuCommandBufferMsg_InsertSyncPoint::ID) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint32 sync_point = sync_point_manager_->GenerateSyncPoint();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GpuCommandBufferMsg_InsertSyncPoint::WriteReplyParams(reply, sync_point);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Send(reply);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message_loop_->PostTask(FROM_HERE, base::Bind(
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &GpuChannelMessageFilter::InsertSyncPointOnMainThread,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          gpu_channel_,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          sync_point_manager_,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          message.routing_id(),
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          sync_point));
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      handled = true;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return handled;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void MessageProcessed(uint64 messages_processed) {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    while (!pending_messages_.empty() &&
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           pending_messages_.front().message_number <= messages_processed)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_messages_.pop();
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdatePreemptionState();
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetPreemptingFlagAndSchedulingState(
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gpu::PreemptionFlag* preempting_flag,
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool a_stub_is_descheduled) {
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    preempting_flag_ = preempting_flag;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    a_stub_is_descheduled_ = a_stub_is_descheduled;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void UpdateStubSchedulingState(bool a_stub_is_descheduled) {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    a_stub_is_descheduled_ = a_stub_is_descheduled;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdatePreemptionState();
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool Send(IPC::Message* message) {
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return sender_->Send(message);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~GpuChannelMessageFilter() {}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  enum PreemptionState {
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Either there's no other channel to preempt, there are no messages
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // pending processing, or we just finished preempting and have to wait
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // before preempting again.
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IDLE,
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We are waiting kPreemptWaitTimeMs before checking if we should preempt.
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WAITING,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We can preempt whenever any IPC processing takes more than
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // kPreemptWaitTimeMs.
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECKING,
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We are currently preempting (i.e. no stub is descheduled).
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PREEMPTING,
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We would like to preempt, but some stub is descheduled.
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WOULD_PREEMPT_DESCHEDULED,
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PreemptionState preemption_state_;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Maximum amount of time that we can spend in PREEMPTING.
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // It is reset when we transition to IDLE.
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta max_preemption_time_;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct PendingMessage {
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint64 message_number;
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeTicks time_received;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    explicit PendingMessage(uint64 message_number)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        : message_number(message_number),
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          time_received(base::TimeTicks::Now()) {
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void UpdatePreemptionState() {
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (preemption_state_) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case IDLE:
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (preempting_flag_.get() && !pending_messages_.empty())
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          TransitionToWaiting();
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case WAITING:
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // A timer will transition us to CHECKING.
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DCHECK(timer_.IsRunning());
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case CHECKING:
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!pending_messages_.empty()) {
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::TimeDelta time_elapsed =
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              base::TimeTicks::Now() - pending_messages_.front().time_received;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (time_elapsed.InMilliseconds() < kPreemptWaitTimeMs) {
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // Schedule another check for when the IPC may go long.
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            timer_.Start(
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                FROM_HERE,
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                base::TimeDelta::FromMilliseconds(kPreemptWaitTimeMs) -
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    time_elapsed,
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                this, &GpuChannelMessageFilter::UpdatePreemptionState);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          } else {
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (a_stub_is_descheduled_)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              TransitionToWouldPreemptDescheduled();
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            else
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              TransitionToPreempting();
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case PREEMPTING:
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // A TransitionToIdle() timer should always be running in this state.
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DCHECK(timer_.IsRunning());
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (a_stub_is_descheduled_)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          TransitionToWouldPreemptDescheduled();
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        else
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          TransitionToIdleIfCaughtUp();
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case WOULD_PREEMPT_DESCHEDULED:
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // A TransitionToIdle() timer should never be running in this state.
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DCHECK(!timer_.IsRunning());
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!a_stub_is_descheduled_)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          TransitionToPreempting();
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        else
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          TransitionToIdleIfCaughtUp();
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      default:
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        NOTREACHED();
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void TransitionToIdleIfCaughtUp() {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(preemption_state_ == PREEMPTING ||
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           preemption_state_ == WOULD_PREEMPT_DESCHEDULED);
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (pending_messages_.empty()) {
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TransitionToIdle();
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TimeDelta time_elapsed =
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::TimeTicks::Now() - pending_messages_.front().time_received;
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (time_elapsed.InMilliseconds() < kStopPreemptThresholdMs)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        TransitionToIdle();
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void TransitionToIdle() {
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(preemption_state_ == PREEMPTING ||
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           preemption_state_ == WOULD_PREEMPT_DESCHEDULED);
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Stop any outstanding timer set to force us from PREEMPTING to IDLE.
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    timer_.Stop();
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    preemption_state_ = IDLE;
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    preempting_flag_->Reset();
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_COUNTER_ID1("gpu", "GpuChannel::Preempting", this, 0);
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdatePreemptionState();
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void TransitionToWaiting() {
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(preemption_state_, IDLE);
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!timer_.IsRunning());
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    preemption_state_ = WAITING;
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    timer_.Start(
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::TimeDelta::FromMilliseconds(kPreemptWaitTimeMs),
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        this, &GpuChannelMessageFilter::TransitionToChecking);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void TransitionToChecking() {
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(preemption_state_, WAITING);
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!timer_.IsRunning());
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    preemption_state_ = CHECKING;
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    max_preemption_time_ = base::TimeDelta::FromMilliseconds(kMaxPreemptTimeMs);
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdatePreemptionState();
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void TransitionToPreempting() {
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(preemption_state_ == CHECKING ||
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           preemption_state_ == WOULD_PREEMPT_DESCHEDULED);
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!a_stub_is_descheduled_);
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Stop any pending state update checks that we may have queued
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // while CHECKING.
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (preemption_state_ == CHECKING)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      timer_.Stop();
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    preemption_state_ = PREEMPTING;
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    preempting_flag_->Set();
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_COUNTER_ID1("gpu", "GpuChannel::Preempting", this, 1);
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    timer_.Start(
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       FROM_HERE,
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       max_preemption_time_,
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       this, &GpuChannelMessageFilter::TransitionToIdle);
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdatePreemptionState();
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void TransitionToWouldPreemptDescheduled() {
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(preemption_state_ == CHECKING ||
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           preemption_state_ == PREEMPTING);
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(a_stub_is_descheduled_);
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (preemption_state_ == CHECKING) {
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Stop any pending state update checks that we may have queued
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // while CHECKING.
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      timer_.Stop();
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Stop any TransitionToIdle() timers that we may have queued
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // while PREEMPTING.
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      timer_.Stop();
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_preemption_time_ = timer_.desired_run_time() - base::TimeTicks::Now();
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (max_preemption_time_ < base::TimeDelta()) {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        TransitionToIdle();
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    preemption_state_ = WOULD_PREEMPT_DESCHEDULED;
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    preempting_flag_->Reset();
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_COUNTER_ID1("gpu", "GpuChannel::Preempting", this, 0);
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdatePreemptionState();
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void InsertSyncPointOnMainThread(
336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::WeakPtr<GpuChannel> gpu_channel,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_refptr<SyncPointManager> manager,
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int32 routing_id,
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      uint32 sync_point) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This function must ensure that the sync point will be retired. Normally
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we'll find the stub based on the routing ID, and associate the sync point
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // with it, but if that fails for any reason (channel or stub already
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // deleted, invalid routing id), we need to retire the sync point
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // immediately.
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (gpu_channel) {
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GpuCommandBufferStub* stub = gpu_channel->LookupCommandBuffer(routing_id);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (stub) {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        stub->AddSyncPoint(sync_point);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GpuCommandBufferMsg_RetireSyncPoint message(routing_id, sync_point);
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        gpu_channel->OnMessageReceived(message);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        gpu_channel->MessageProcessed();
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manager->RetireSyncPoint(sync_point);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // NOTE: this weak pointer is never dereferenced on the IO thread, it's only
360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // passed through - therefore the WeakPtr assumptions are respected.
361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WeakPtr<GpuChannel> gpu_channel_;
362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IPC::Sender* sender_;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SyncPointManager> sync_point_manager_;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> message_loop_;
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<gpu::PreemptionFlag> preempting_flag_;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::queue<PendingMessage> pending_messages_;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Count of the number of IPCs forwarded to the GpuChannel.
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint64 messages_forwarded_to_channel_;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::OneShotTimer<GpuChannelMessageFilter> timer_;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool a_stub_is_descheduled_;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager,
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       GpuWatchdog* watchdog,
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       gfx::GLShareGroup* share_group,
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       gpu::gles2::MailboxManager* mailbox,
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int client_id,
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       bool software)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : gpu_channel_manager_(gpu_channel_manager),
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      messages_processed_(0),
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_id_(client_id),
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      share_group_(share_group ? share_group : new gfx::GLShareGroup),
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mailbox_manager_(mailbox ? mailbox : new gpu::gles2::MailboxManager),
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image_manager_(new gpu::gles2::ImageManager),
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      watchdog_(watchdog),
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      software_(software),
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handle_messages_scheduled_(false),
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      currently_processing_message_(NULL),
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this),
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      num_stubs_descheduled_(0) {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(gpu_channel_manager);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(client_id);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_id_ = IPC::Channel::GenerateVerifiedChannelID("gpu");
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CommandLine* command_line = CommandLine::ForCurrentProcess();
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)GpuChannel::~GpuChannel() {
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  STLDeleteElements(&deferred_messages_);
405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (preempting_flag_.get())
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    preempting_flag_->Reset();
407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GpuChannel::Init(base::MessageLoopProxy* io_message_loop,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      base::WaitableEvent* shutdown_event) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!channel_.get());
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Map renderer ID to a (single) channel to that process.
41446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  channel_ = IPC::SyncChannel::Create(channel_id_,
41546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                      IPC::Channel::MODE_SERVER,
41646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                      this,
41746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                      io_message_loop,
41846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                      false,
41946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                      shutdown_event);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  filter_ =
422cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new GpuChannelMessageFilter(weak_factory_.GetWeakPtr(),
423cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  gpu_channel_manager_->sync_point_manager(),
424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  base::MessageLoopProxy::current());
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  io_message_loop_ = io_message_loop;
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  channel_->AddFilter(filter_.get());
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
428f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  devtools_gpu_agent_.reset(new DevToolsGpuAgent(this));
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GpuChannel::GetChannelName() {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return channel_id_;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int GpuChannel::TakeRendererFileDescriptor() {
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!channel_) {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return channel_->TakeClientFileDescriptor();
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_POSIX)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuChannel::OnMessageReceived(const IPC::Message& message) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (log_messages_) {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "received message @" << &message << " on channel @" << this
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " with type " << message.type();
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
451c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (message.type() == GpuCommandBufferMsg_WaitForTokenInRange::ID ||
452c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      message.type() == GpuCommandBufferMsg_WaitForGetOffsetInRange::ID) {
453c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Move Wait commands to the head of the queue, so the renderer
454c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // doesn't have to wait any longer than necessary.
455c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    deferred_messages_.push_front(new IPC::Message(message));
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deferred_messages_.push_back(new IPC::Message(message));
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnScheduled();
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannel::OnChannelError() {
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gpu_channel_manager_->RemoveChannel(client_id_);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuChannel::Send(IPC::Message* message) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The GPU process must never send a synchronous IPC message to the renderer
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // process. This could result in deadlock.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!message->is_sync());
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (log_messages_) {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "sending message @" << message << " on channel @" << this
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " with type " << message->type();
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!channel_) {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete message;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return channel_->Send(message);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuChannel::RequeueMessage() {
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(currently_processing_message_);
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  deferred_messages_.push_front(
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new IPC::Message(*currently_processing_message_));
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  messages_processed_--;
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  currently_processing_message_ = NULL;
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannel::OnScheduled() {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (handle_messages_scheduled_)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post a task to handle any deferred messages. The deferred message queue is
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not emptied here, which ensures that OnMessageReceived will continue to
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // defer newly received messages until the ones in the queue have all been
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handled by HandleMessage. HandleMessage is invoked as a
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task to prevent reentrancy.
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&GpuChannel::HandleMessage, weak_factory_.GetWeakPtr()));
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handle_messages_scheduled_ = true;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuChannel::StubSchedulingChanged(bool scheduled) {
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool a_stub_was_descheduled = num_stubs_descheduled_ > 0;
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (scheduled) {
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    num_stubs_descheduled_--;
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OnScheduled();
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    num_stubs_descheduled_++;
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_LE(num_stubs_descheduled_, stubs_.size());
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool a_stub_is_descheduled = num_stubs_descheduled_ > 0;
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (a_stub_is_descheduled != a_stub_was_descheduled) {
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (preempting_flag_.get()) {
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      io_message_loop_->PostTask(
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          FROM_HERE,
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&GpuChannelMessageFilter::UpdateStubSchedulingState,
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     filter_,
525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     a_stub_is_descheduled));
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5309a3a4bc965704498ea9f22876627cda96ff9a77eBo LiuCreateCommandBufferResult GpuChannel::CreateViewCommandBuffer(
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::GLSurfaceHandle& window,
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 surface_id,
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GPUCreateCommandBufferConfig& init_params,
534c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int32 route_id) {
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT1("gpu",
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "GpuChannel::CreateViewCommandBuffer",
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "surface_id",
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               surface_id);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuCommandBufferStub* share_group = stubs_.Lookup(init_params.share_group_id);
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Virtualize compositor contexts on OS X to prevent performance regressions
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // when enabling FCM.
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // http://crbug.com/180463
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool use_virtualized_gl_context = false;
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_MACOSX)
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  use_virtualized_gl_context = true;
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<GpuCommandBufferStub> stub(
551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new GpuCommandBufferStub(this,
552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               share_group,
553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               window,
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               mailbox_manager_.get(),
555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               image_manager_.get(),
556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               gfx::Size(),
557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               disallowed_features_,
558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               init_params.attribs,
559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               init_params.gpu_preference,
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               use_virtualized_gl_context,
561c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                               route_id,
562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               surface_id,
563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               watchdog_,
564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               software_,
565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               init_params.active_url));
566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (preempted_flag_.get())
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    stub->SetPreemptByFlag(preempted_flag_);
568c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!router_.AddRoute(route_id, stub.get())) {
569c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DLOG(ERROR) << "GpuChannel::CreateViewCommandBuffer(): "
570c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   "failed to add route";
5719a3a4bc965704498ea9f22876627cda96ff9a77eBo Liu    return CREATE_COMMAND_BUFFER_FAILED_AND_CHANNEL_LOST;
572c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
573c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  stubs_.AddWithID(stub.release(), route_id);
5749a3a4bc965704498ea9f22876627cda96ff9a77eBo Liu  return CREATE_COMMAND_BUFFER_SUCCEEDED;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32 route_id) {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return stubs_.Lookup(route_id);
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannel::CreateImage(
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::PluginWindowHandle window,
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 image_id,
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Size* size) {
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT1("gpu",
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "GpuChannel::CreateImage",
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "image_id",
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               image_id);
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *size = gfx::Size();
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (image_manager_->LookupImage(image_id)) {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "CreateImage failed, image_id already in use.";
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<gfx::GLImage> image = gfx::GLImage::CreateGLImage(window);
598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!image.get())
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  image_manager_->AddImage(image.get(), image_id);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *size = image->GetSize();
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannel::DeleteImage(int32 image_id) {
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT1("gpu",
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "GpuChannel::DeleteImage",
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "image_id",
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               image_id);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  image_manager_->RemoveImage(image_id);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannel::LoseAllContexts() {
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gpu_channel_manager_->LoseAllContexts();
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid GpuChannel::MarkAllContextsLost() {
6197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_);
6207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch       !it.IsAtEnd(); it.Advance()) {
6217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    it.GetCurrentValue()->MarkContextLost();
6227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
6237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
6247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
625c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool GpuChannel::AddRoute(int32 route_id, IPC::Listener* listener) {
626c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return router_.AddRoute(route_id, listener);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannel::RemoveRoute(int32 route_id) {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  router_.RemoveRoute(route_id);
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gpu::PreemptionFlag* GpuChannel::GetPreemptionFlag() {
634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!preempting_flag_.get()) {
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    preempting_flag_ = new gpu::PreemptionFlag;
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    io_message_loop_->PostTask(
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE, base::Bind(
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &GpuChannelMessageFilter::SetPreemptingFlagAndSchedulingState,
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            filter_, preempting_flag_, num_stubs_descheduled_ > 0));
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return preempting_flag_.get();
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuChannel::SetPreemptByFlag(
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<gpu::PreemptionFlag> preempted_flag) {
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  preempted_flag_ = preempted_flag;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       !it.IsAtEnd(); it.Advance()) {
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    it.GetCurrentValue()->SetPreemptByFlag(preempted_flag_);
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannel::OnDestroy() {
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuChannel::OnDestroy");
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gpu_channel_manager_->RemoveChannel(client_id_);
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg)
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateOffscreenCommandBuffer,
6633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                        OnCreateOffscreenCommandBuffer)
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyCommandBuffer,
6653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                        OnDestroyCommandBuffer)
666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuChannelMsg_DevToolsStartEventsRecording,
667f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        OnDevToolsStartEventsRecording)
668f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuChannelMsg_DevToolsStopEventsRecording,
669f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        OnDevToolsStopEventsRecording)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(handled) << msg.type();
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannel::HandleMessage() {
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handle_messages_scheduled_ = false;
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (deferred_messages_.empty())
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool should_fast_track_ack = false;
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IPC::Message* m = deferred_messages_.front();
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GpuCommandBufferStub* stub = stubs_.Lookup(m->routing_id());
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  do {
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (stub) {
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!stub->IsScheduled())
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (stub->IsPreempted()) {
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        OnScheduled();
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<IPC::Message> message(m);
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deferred_messages_.pop_front();
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool message_processed = true;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    currently_processing_message_ = message.get();
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool result;
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (message->routing_id() == MSG_ROUTING_CONTROL)
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result = OnControlMessageReceived(*message);
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result = router_.RouteMessage(*message);
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    currently_processing_message_ = NULL;
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!result) {
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Respond to sync messages even if router failed to route.
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (message->is_sync()) {
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IPC::Message* reply = IPC::SyncMessage::GenerateReply(&*message);
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reply->set_reply_error();
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Send(reply);
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If the command buffer becomes unscheduled as a result of handling the
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // message but still has more commands to process, synthesize an IPC
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // message to flush that command buffer.
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (stub) {
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (stub->HasUnprocessedCommands()) {
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          deferred_messages_.push_front(new GpuCommandBufferMsg_Rescheduled(
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              stub->route_id()));
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          message_processed = false;
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (message_processed)
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MessageProcessed();
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We want the EchoACK following the SwapBuffers to be sent as close as
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // possible, avoiding scheduling other channels in the meantime.
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    should_fast_track_ack = false;
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!deferred_messages_.empty()) {
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      m = deferred_messages_.front();
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stub = stubs_.Lookup(m->routing_id());
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      should_fast_track_ack =
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          (m->type() == GpuCommandBufferMsg_Echo::ID) &&
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          stub && stub->IsScheduled();
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } while (should_fast_track_ack);
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!deferred_messages_.empty()) {
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnScheduled();
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannel::OnCreateOffscreenCommandBuffer(
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& size,
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GPUCreateCommandBufferConfig& init_params,
749c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int32 route_id,
750c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    bool* succeeded) {
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuChannel::OnCreateOffscreenCommandBuffer");
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuCommandBufferStub* share_group = stubs_.Lookup(init_params.share_group_id);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub(
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      share_group,
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::GLSurfaceHandle(),
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mailbox_manager_.get(),
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image_manager_.get(),
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size,
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      disallowed_features_,
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      init_params.attribs,
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      init_params.gpu_preference,
764c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      false,
765c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      route_id,
766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      0,
767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      watchdog_,
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      software_,
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      init_params.active_url));
770868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (preempted_flag_.get())
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    stub->SetPreemptByFlag(preempted_flag_);
772c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!router_.AddRoute(route_id, stub.get())) {
773c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DLOG(ERROR) << "GpuChannel::OnCreateOffscreenCommandBuffer(): "
774c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   "failed to add route";
775c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    *succeeded = false;
776c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
777c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
778c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  stubs_.AddWithID(stub.release(), route_id);
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT1("gpu", "GpuChannel::OnCreateOffscreenCommandBuffer",
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "route_id", route_id);
781c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  *succeeded = true;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuChannel::OnDestroyCommandBuffer(int32 route_id) {
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT1("gpu", "GpuChannel::OnDestroyCommandBuffer",
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "route_id", route_id);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
788c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GpuCommandBufferStub* stub = stubs_.Lookup(route_id);
789c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!stub)
790c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool need_reschedule = (stub && !stub->IsScheduled());
792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  router_.RemoveRoute(route_id);
793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stubs_.Remove(route_id);
794c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // In case the renderer is currently blocked waiting for a sync reply from the
795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // stub, we need to make sure to reschedule the GpuChannel here.
796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (need_reschedule) {
797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // This stub won't get a chance to reschedule, so update the count now.
798c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StubSchedulingChanged(true);
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
802c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GpuChannel::OnDevToolsStartEventsRecording(int32 route_id,
803c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                bool* succeeded) {
804c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  *succeeded = devtools_gpu_agent_->StartEventsRecording(route_id);
805f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
806f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
807f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void GpuChannel::OnDevToolsStopEventsRecording() {
808f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  devtools_gpu_agent_->StopEventsRecording();
809f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
810f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuChannel::MessageProcessed() {
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  messages_processed_++;
813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (preempting_flag_.get()) {
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    io_message_loop_->PostTask(
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&GpuChannelMessageFilter::MessageProcessed,
817868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   filter_,
818868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   messages_processed_));
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuChannel::CacheShader(const std::string& key,
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const std::string& shader) {
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gpu_channel_manager_->Send(
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new GpuHostMsg_CacheShader(client_id_, key, shader));
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid GpuChannel::AddFilter(IPC::MessageFilter* filter) {
829424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  channel_->AddFilter(filter);
830424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
831424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
8325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid GpuChannel::RemoveFilter(IPC::MessageFilter* filter) {
833424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  channel_->RemoveFilter(filter);
834424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
835424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
836effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochuint64 GpuChannel::GetMemoryUsage() {
837effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  uint64 size = 0;
838effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_);
839effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch       !it.IsAtEnd(); it.Advance()) {
840effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    size += it.GetCurrentValue()->GetMemoryUsage();
841effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
842effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return size;
843effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
844effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
846