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_CLIENT_GPU_CHANNEL_HOST_H_ 6 #define CONTENT_COMMON_GPU_CLIENT_GPU_CHANNEL_HOST_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "base/atomic_sequence_num.h" 12 #include "base/containers/hash_tables.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/weak_ptr.h" 16 #include "base/process/process.h" 17 #include "base/synchronization/lock.h" 18 #include "content/common/content_export.h" 19 #include "content/common/gpu/gpu_process_launch_causes.h" 20 #include "content/common/message_router.h" 21 #include "gpu/config/gpu_info.h" 22 #include "ipc/ipc_channel_handle.h" 23 #include "ipc/ipc_channel_proxy.h" 24 #include "ipc/ipc_sync_channel.h" 25 #include "media/video/video_decode_accelerator.h" 26 #include "media/video/video_encode_accelerator.h" 27 #include "ui/gfx/gpu_memory_buffer.h" 28 #include "ui/gfx/native_widget_types.h" 29 #include "ui/gfx/size.h" 30 #include "ui/gl/gpu_preference.h" 31 32 class GURL; 33 class TransportTextureService; 34 struct GPUCreateCommandBufferConfig; 35 36 namespace base { 37 class MessageLoop; 38 class MessageLoopProxy; 39 } 40 41 namespace gpu { 42 struct Mailbox; 43 } 44 45 namespace IPC { 46 class SyncMessageFilter; 47 } 48 49 namespace content { 50 class CommandBufferProxyImpl; 51 class GpuChannelHost; 52 struct GpuRenderingStats; 53 54 struct GpuListenerInfo { 55 GpuListenerInfo(); 56 ~GpuListenerInfo(); 57 58 base::WeakPtr<IPC::Listener> listener; 59 scoped_refptr<base::MessageLoopProxy> loop; 60 }; 61 62 class CONTENT_EXPORT GpuChannelHostFactory { 63 public: 64 typedef base::Callback<void(const gfx::Size)> CreateImageCallback; 65 66 virtual ~GpuChannelHostFactory() {} 67 68 virtual bool IsMainThread() = 0; 69 virtual base::MessageLoop* GetMainLoop() = 0; 70 virtual scoped_refptr<base::MessageLoopProxy> GetIOLoopProxy() = 0; 71 virtual base::WaitableEvent* GetShutDownEvent() = 0; 72 virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory(size_t size) = 0; 73 virtual int32 CreateViewCommandBuffer( 74 int32 surface_id, const GPUCreateCommandBufferConfig& init_params) = 0; 75 virtual void CreateImage( 76 gfx::PluginWindowHandle window, 77 int32 image_id, 78 const CreateImageCallback& callback) = 0; 79 virtual void DeleteImage(int32 image_id, int32 sync_point) = 0; 80 virtual scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer( 81 size_t width, 82 size_t height, 83 unsigned internalformat) = 0; 84 }; 85 86 // Encapsulates an IPC channel between the client and one GPU process. 87 // On the GPU process side there's a corresponding GpuChannel. 88 // Every method can be called on any thread with a message loop, except for the 89 // IO thread. 90 class GpuChannelHost : public IPC::Sender, 91 public base::RefCountedThreadSafe<GpuChannelHost> { 92 public: 93 // Must be called on the main thread (as defined by the factory). 94 static scoped_refptr<GpuChannelHost> Create( 95 GpuChannelHostFactory* factory, 96 int gpu_host_id, 97 const gpu::GPUInfo& gpu_info, 98 const IPC::ChannelHandle& channel_handle); 99 100 // Returns true if |handle| is a valid GpuMemoryBuffer handle that 101 // can be shared to the GPU process. 102 static bool IsValidGpuMemoryBuffer(gfx::GpuMemoryBufferHandle handle); 103 104 bool IsLost() const { 105 DCHECK(channel_filter_.get()); 106 return channel_filter_->IsLost(); 107 } 108 109 // The GPU stats reported by the GPU process. 110 const gpu::GPUInfo& gpu_info() const { return gpu_info_; } 111 112 // IPC::Sender implementation: 113 virtual bool Send(IPC::Message* msg) OVERRIDE; 114 115 // Create and connect to a command buffer in the GPU process. 116 CommandBufferProxyImpl* CreateViewCommandBuffer( 117 int32 surface_id, 118 CommandBufferProxyImpl* share_group, 119 const std::vector<int32>& attribs, 120 const GURL& active_url, 121 gfx::GpuPreference gpu_preference); 122 123 // Create and connect to a command buffer in the GPU process. 124 CommandBufferProxyImpl* CreateOffscreenCommandBuffer( 125 const gfx::Size& size, 126 CommandBufferProxyImpl* share_group, 127 const std::vector<int32>& attribs, 128 const GURL& active_url, 129 gfx::GpuPreference gpu_preference); 130 131 // Creates a video decoder in the GPU process. 132 scoped_ptr<media::VideoDecodeAccelerator> CreateVideoDecoder( 133 int command_buffer_route_id, 134 media::VideoCodecProfile profile, 135 media::VideoDecodeAccelerator::Client* client); 136 137 // Creates a video encoder in the GPU process. 138 scoped_ptr<media::VideoEncodeAccelerator> CreateVideoEncoder( 139 media::VideoEncodeAccelerator::Client* client); 140 141 // Destroy a command buffer created by this channel. 142 void DestroyCommandBuffer(CommandBufferProxyImpl* command_buffer); 143 144 // Collect rendering stats from GPU process. 145 bool CollectRenderingStatsForSurface( 146 int surface_id, GpuRenderingStats* stats); 147 148 // Add a route for the current message loop. 149 void AddRoute(int route_id, base::WeakPtr<IPC::Listener> listener); 150 void RemoveRoute(int route_id); 151 152 GpuChannelHostFactory* factory() const { return factory_; } 153 int gpu_host_id() const { return gpu_host_id_; } 154 155 // Returns a handle to the shared memory that can be sent via IPC to the 156 // GPU process. The caller is responsible for ensuring it is closed. Returns 157 // an invalid handle on failure. 158 base::SharedMemoryHandle ShareToGpuProcess( 159 base::SharedMemoryHandle source_handle); 160 161 // Generates |num| unique mailbox names that can be used with 162 // GL_texture_mailbox_CHROMIUM. Unlike genMailboxCHROMIUM, this IPC is 163 // handled only on the GPU process' IO thread, and so is not effectively 164 // a finish. 165 bool GenerateMailboxNames(unsigned num, std::vector<gpu::Mailbox>* names); 166 167 // Reserve one unused transfer buffer ID. 168 int32 ReserveTransferBufferId(); 169 170 // Returns a GPU memory buffer handle to the buffer that can be sent via 171 // IPC to the GPU process. The caller is responsible for ensuring it is 172 // closed. Returns an invalid handle on failure. 173 gfx::GpuMemoryBufferHandle ShareGpuMemoryBufferToGpuProcess( 174 gfx::GpuMemoryBufferHandle source_handle); 175 176 // Reserve one unused gpu memory buffer ID. 177 int32 ReserveGpuMemoryBufferId(); 178 179 private: 180 friend class base::RefCountedThreadSafe<GpuChannelHost>; 181 GpuChannelHost(GpuChannelHostFactory* factory, 182 int gpu_host_id, 183 const gpu::GPUInfo& gpu_info); 184 virtual ~GpuChannelHost(); 185 void Connect(const IPC::ChannelHandle& channel_handle); 186 187 // A filter used internally to route incoming messages from the IO thread 188 // to the correct message loop. It also maintains some shared state between 189 // all the contexts. 190 class MessageFilter : public IPC::ChannelProxy::MessageFilter { 191 public: 192 MessageFilter(); 193 194 // Called on the IO thread. 195 void AddRoute(int route_id, 196 base::WeakPtr<IPC::Listener> listener, 197 scoped_refptr<base::MessageLoopProxy> loop); 198 // Called on the IO thread. 199 void RemoveRoute(int route_id); 200 201 // IPC::ChannelProxy::MessageFilter implementation 202 // (called on the IO thread): 203 virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; 204 virtual void OnChannelError() OVERRIDE; 205 206 // The following methods can be called on any thread. 207 208 // Whether the channel is lost. 209 bool IsLost() const; 210 211 // Gets mailboxes from the pool, and return the number of mailboxes to ask 212 // the GPU process to maintain a good pool size. The caller is responsible 213 // for sending the GpuChannelMsg_GenerateMailboxNamesAsync message. 214 size_t GetMailboxNames(size_t num, std::vector<gpu::Mailbox>* names); 215 216 private: 217 virtual ~MessageFilter(); 218 bool OnControlMessageReceived(const IPC::Message& msg); 219 220 // Message handlers. 221 void OnGenerateMailboxNamesReply(const std::vector<gpu::Mailbox>& names); 222 223 // Threading notes: |listeners_| is only accessed on the IO thread. Every 224 // other field is protected by |lock_|. 225 typedef base::hash_map<int, GpuListenerInfo> ListenerMap; 226 ListenerMap listeners_; 227 228 // Protects all fields below this one. 229 mutable base::Lock lock_; 230 231 // Whether the channel has been lost. 232 bool lost_; 233 234 // A pool of valid mailbox names. 235 std::vector<gpu::Mailbox> mailbox_name_pool_; 236 237 // Number of pending mailbox requested from the GPU process. 238 size_t requested_mailboxes_; 239 }; 240 241 // Threading notes: all fields are constant during the lifetime of |this| 242 // except: 243 // - |next_transfer_buffer_id_|, atomic type 244 // - |next_gpu_memory_buffer_id_|, atomic type 245 // - |proxies_|, protected by |context_lock_| 246 GpuChannelHostFactory* const factory_; 247 const int gpu_host_id_; 248 249 const gpu::GPUInfo gpu_info_; 250 251 scoped_ptr<IPC::SyncChannel> channel_; 252 scoped_refptr<MessageFilter> channel_filter_; 253 254 // A filter for sending messages from thread other than the main thread. 255 scoped_refptr<IPC::SyncMessageFilter> sync_filter_; 256 257 // Transfer buffer IDs are allocated in sequence. 258 base::AtomicSequenceNumber next_transfer_buffer_id_; 259 260 // Gpu memory buffer IDs are allocated in sequence. 261 base::AtomicSequenceNumber next_gpu_memory_buffer_id_; 262 263 // Protects proxies_. 264 mutable base::Lock context_lock_; 265 // Used to look up a proxy from its routing id. 266 typedef base::hash_map<int, CommandBufferProxyImpl*> ProxyMap; 267 ProxyMap proxies_; 268 269 DISALLOW_COPY_AND_ASSIGN(GpuChannelHost); 270 }; 271 272 } // namespace content 273 274 #endif // CONTENT_COMMON_GPU_CLIENT_GPU_CHANNEL_HOST_H_ 275