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