1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_COMMON_GPU_GPU_CHANNEL_H_
6#define CONTENT_COMMON_GPU_GPU_CHANNEL_H_
7
8#include <deque>
9#include <string>
10
11#include "base/id_map.h"
12#include "base/memory/ref_counted.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/memory/scoped_vector.h"
15#include "base/memory/weak_ptr.h"
16#include "base/process/process.h"
17#include "build/build_config.h"
18#include "content/common/gpu/gpu_command_buffer_stub.h"
19#include "content/common/gpu/gpu_memory_manager.h"
20#include "content/common/gpu/gpu_result_codes.h"
21#include "content/common/message_router.h"
22#include "ipc/ipc_sync_channel.h"
23#include "ui/gfx/native_widget_types.h"
24#include "ui/gfx/size.h"
25#include "ui/gl/gl_share_group.h"
26#include "ui/gl/gpu_preference.h"
27
28struct GPUCreateCommandBufferConfig;
29
30namespace base {
31class MessageLoopProxy;
32class WaitableEvent;
33}
34
35namespace gpu {
36class PreemptionFlag;
37namespace gles2 {
38class ImageManager;
39}
40}
41
42namespace IPC {
43class MessageFilter;
44}
45
46namespace content {
47class DevToolsGpuAgent;
48class GpuChannelManager;
49class GpuChannelMessageFilter;
50class GpuWatchdog;
51
52// Encapsulates an IPC channel between the GPU process and one renderer
53// process. On the renderer side there's a corresponding GpuChannelHost.
54class GpuChannel : public IPC::Listener, public IPC::Sender {
55 public:
56  // Takes ownership of the renderer process handle.
57  GpuChannel(GpuChannelManager* gpu_channel_manager,
58             GpuWatchdog* watchdog,
59             gfx::GLShareGroup* share_group,
60             gpu::gles2::MailboxManager* mailbox_manager,
61             int client_id,
62             bool software);
63  virtual ~GpuChannel();
64
65  void Init(base::MessageLoopProxy* io_message_loop,
66            base::WaitableEvent* shutdown_event);
67
68  // Get the GpuChannelManager that owns this channel.
69  GpuChannelManager* gpu_channel_manager() const {
70    return gpu_channel_manager_;
71  }
72
73  // Returns the name of the associated IPC channel.
74  std::string GetChannelName();
75
76#if defined(OS_POSIX)
77  int TakeRendererFileDescriptor();
78#endif  // defined(OS_POSIX)
79
80  base::ProcessId renderer_pid() const { return channel_->GetPeerPID(); }
81
82  int client_id() const { return client_id_; }
83
84  scoped_refptr<base::MessageLoopProxy> io_message_loop() const {
85    return io_message_loop_;
86  }
87
88  // IPC::Listener implementation:
89  virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
90  virtual void OnChannelError() OVERRIDE;
91
92  // IPC::Sender implementation:
93  virtual bool Send(IPC::Message* msg) OVERRIDE;
94
95  // Requeue the message that is currently being processed to the beginning of
96  // the queue. Used when the processing of a message gets aborted because of
97  // unscheduling conditions.
98  void RequeueMessage();
99
100  // This is called when a command buffer transitions from the unscheduled
101  // state to the scheduled state, which potentially means the channel
102  // transitions from the unscheduled to the scheduled state. When this occurs
103  // deferred IPC messaged are handled.
104  void OnScheduled();
105
106  // This is called when a command buffer transitions between scheduled and
107  // descheduled states. When any stub is descheduled, we stop preempting
108  // other channels.
109  void StubSchedulingChanged(bool scheduled);
110
111  CreateCommandBufferResult CreateViewCommandBuffer(
112      const gfx::GLSurfaceHandle& window,
113      int32 surface_id,
114      const GPUCreateCommandBufferConfig& init_params,
115      int32 route_id);
116
117  void CreateImage(
118      gfx::PluginWindowHandle window,
119      int32 image_id,
120      gfx::Size* size);
121  void DeleteImage(int32 image_id);
122
123  gfx::GLShareGroup* share_group() const { return share_group_.get(); }
124
125  GpuCommandBufferStub* LookupCommandBuffer(int32 route_id);
126
127  void LoseAllContexts();
128  void MarkAllContextsLost();
129
130  // Called to add a listener for a particular message routing ID.
131  // Returns true if succeeded.
132  bool AddRoute(int32 route_id, IPC::Listener* listener);
133
134  // Called to remove a listener for a particular message routing ID.
135  void RemoveRoute(int32 route_id);
136
137  gpu::PreemptionFlag* GetPreemptionFlag();
138
139  bool handle_messages_scheduled() const { return handle_messages_scheduled_; }
140  uint64 messages_processed() const { return messages_processed_; }
141
142  // If |preemption_flag->IsSet()|, any stub on this channel
143  // should stop issuing GL commands. Setting this to NULL stops deferral.
144  void SetPreemptByFlag(
145      scoped_refptr<gpu::PreemptionFlag> preemption_flag);
146
147  void CacheShader(const std::string& key, const std::string& shader);
148
149  void AddFilter(IPC::MessageFilter* filter);
150  void RemoveFilter(IPC::MessageFilter* filter);
151
152  uint64 GetMemoryUsage();
153
154 private:
155  friend class GpuChannelMessageFilter;
156
157  void OnDestroy();
158
159  bool OnControlMessageReceived(const IPC::Message& msg);
160
161  void HandleMessage();
162
163  // Message handlers.
164  void OnCreateOffscreenCommandBuffer(
165      const gfx::Size& size,
166      const GPUCreateCommandBufferConfig& init_params,
167      int32 route_id,
168      bool* succeeded);
169  void OnDestroyCommandBuffer(int32 route_id);
170  void OnDevToolsStartEventsRecording(int32 route_id, bool* succeeded);
171  void OnDevToolsStopEventsRecording();
172
173  // Decrement the count of unhandled IPC messages and defer preemption.
174  void MessageProcessed();
175
176  // The lifetime of objects of this class is managed by a GpuChannelManager.
177  // The GpuChannelManager destroy all the GpuChannels that they own when they
178  // are destroyed. So a raw pointer is safe.
179  GpuChannelManager* gpu_channel_manager_;
180
181  scoped_ptr<IPC::SyncChannel> channel_;
182
183  uint64 messages_processed_;
184
185  // Whether the processing of IPCs on this channel is stalled and we should
186  // preempt other GpuChannels.
187  scoped_refptr<gpu::PreemptionFlag> preempting_flag_;
188
189  // If non-NULL, all stubs on this channel should stop processing GL
190  // commands (via their GpuScheduler) when preempted_flag_->IsSet()
191  scoped_refptr<gpu::PreemptionFlag> preempted_flag_;
192
193  std::deque<IPC::Message*> deferred_messages_;
194
195  // The id of the client who is on the other side of the channel.
196  int client_id_;
197
198  // Uniquely identifies the channel within this GPU process.
199  std::string channel_id_;
200
201  // Used to implement message routing functionality to CommandBuffer objects
202  MessageRouter router_;
203
204  // The share group that all contexts associated with a particular renderer
205  // process use.
206  scoped_refptr<gfx::GLShareGroup> share_group_;
207
208  scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_;
209  scoped_refptr<gpu::gles2::ImageManager> image_manager_;
210
211  typedef IDMap<GpuCommandBufferStub, IDMapOwnPointer> StubMap;
212  StubMap stubs_;
213
214  bool log_messages_;  // True if we should log sent and received messages.
215  gpu::gles2::DisallowedFeatures disallowed_features_;
216  GpuWatchdog* watchdog_;
217  bool software_;
218  bool handle_messages_scheduled_;
219  IPC::Message* currently_processing_message_;
220
221  base::WeakPtrFactory<GpuChannel> weak_factory_;
222
223  scoped_refptr<GpuChannelMessageFilter> filter_;
224  scoped_refptr<base::MessageLoopProxy> io_message_loop_;
225  scoped_ptr<DevToolsGpuAgent> devtools_gpu_agent_;
226
227  size_t num_stubs_descheduled_;
228
229  DISALLOW_COPY_AND_ASSIGN(GpuChannel);
230};
231
232}  // namespace content
233
234#endif  // CONTENT_COMMON_GPU_GPU_CHANNEL_H_
235