Respond with QuotaExceededError when IndexedDB has no disk space on open.
[chromium-blink-merge.git] / content / common / gpu / gpu_channel_manager.cc
blob8b466bd0b2b8fd5ad1f70adfba50afea3910217c
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.
5 #include "content/common/gpu/gpu_channel_manager.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "content/child/child_thread.h"
10 #include "content/common/gpu/gpu_channel.h"
11 #include "content/common/gpu/gpu_memory_manager.h"
12 #include "content/common/gpu/gpu_messages.h"
13 #include "content/common/gpu/sync_point_manager.h"
14 #include "gpu/command_buffer/service/feature_info.h"
15 #include "gpu/command_buffer/service/gpu_switches.h"
16 #include "gpu/command_buffer/service/mailbox_manager.h"
17 #include "gpu/command_buffer/service/memory_program_cache.h"
18 #include "ui/gl/gl_bindings.h"
19 #include "ui/gl/gl_share_group.h"
21 namespace content {
23 GpuChannelManager::ImageOperation::ImageOperation(
24 int32 sync_point, base::Closure callback)
25 : sync_point(sync_point),
26 callback(callback) {
29 GpuChannelManager::ImageOperation::~ImageOperation() {
32 GpuChannelManager::GpuChannelManager(ChildThread* gpu_child_thread,
33 GpuWatchdog* watchdog,
34 base::MessageLoopProxy* io_message_loop,
35 base::WaitableEvent* shutdown_event)
36 : weak_factory_(this),
37 io_message_loop_(io_message_loop),
38 shutdown_event_(shutdown_event),
39 gpu_child_thread_(gpu_child_thread),
40 gpu_memory_manager_(
41 this,
42 GpuMemoryManager::kDefaultMaxSurfacesWithFrontbufferSoftLimit),
43 watchdog_(watchdog),
44 sync_point_manager_(new SyncPointManager) {
45 DCHECK(gpu_child_thread);
46 DCHECK(io_message_loop);
47 DCHECK(shutdown_event);
50 GpuChannelManager::~GpuChannelManager() {
51 gpu_channels_.clear();
52 if (default_offscreen_surface_.get()) {
53 default_offscreen_surface_->Destroy();
54 default_offscreen_surface_ = NULL;
56 DCHECK(image_operations_.empty());
59 gpu::gles2::ProgramCache* GpuChannelManager::program_cache() {
60 if (!program_cache_.get() &&
61 (gfx::g_driver_gl.ext.b_ARB_get_program_binary ||
62 gfx::g_driver_gl.ext.b_OES_get_program_binary) &&
63 !CommandLine::ForCurrentProcess()->HasSwitch(
64 switches::kDisableGpuProgramCache)) {
65 program_cache_.reset(new gpu::gles2::MemoryProgramCache());
67 return program_cache_.get();
70 void GpuChannelManager::RemoveChannel(int client_id) {
71 Send(new GpuHostMsg_DestroyChannel(client_id));
72 gpu_channels_.erase(client_id);
75 int GpuChannelManager::GenerateRouteID() {
76 static int last_id = 0;
77 return ++last_id;
80 void GpuChannelManager::AddRoute(int32 routing_id, IPC::Listener* listener) {
81 gpu_child_thread_->AddRoute(routing_id, listener);
84 void GpuChannelManager::RemoveRoute(int32 routing_id) {
85 gpu_child_thread_->RemoveRoute(routing_id);
88 GpuChannel* GpuChannelManager::LookupChannel(int32 client_id) {
89 GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
90 if (iter == gpu_channels_.end())
91 return NULL;
92 else
93 return iter->second.get();
96 bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) {
97 bool msg_is_ok = true;
98 bool handled = true;
99 IPC_BEGIN_MESSAGE_MAP_EX(GpuChannelManager, msg, msg_is_ok)
100 IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel)
101 IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel)
102 IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer,
103 OnCreateViewCommandBuffer)
104 IPC_MESSAGE_HANDLER(GpuMsg_CreateImage, OnCreateImage)
105 IPC_MESSAGE_HANDLER(GpuMsg_DeleteImage, OnDeleteImage)
106 IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader, OnLoadedShader)
107 IPC_MESSAGE_UNHANDLED(handled = false)
108 IPC_END_MESSAGE_MAP_EX()
109 return handled;
112 bool GpuChannelManager::Send(IPC::Message* msg) {
113 return gpu_child_thread_->Send(msg);
116 void GpuChannelManager::OnEstablishChannel(int client_id, bool share_context) {
117 IPC::ChannelHandle channel_handle;
119 gfx::GLShareGroup* share_group = NULL;
120 gpu::gles2::MailboxManager* mailbox_manager = NULL;
121 if (share_context) {
122 if (!share_group_.get()) {
123 share_group_ = new gfx::GLShareGroup;
124 DCHECK(!mailbox_manager_.get());
125 mailbox_manager_ = new gpu::gles2::MailboxManager;
127 share_group = share_group_.get();
128 mailbox_manager = mailbox_manager_.get();
131 scoped_refptr<GpuChannel> channel = new GpuChannel(this,
132 watchdog_,
133 share_group,
134 mailbox_manager,
135 client_id,
136 false);
137 if (channel->Init(io_message_loop_.get(), shutdown_event_)) {
138 gpu_channels_[client_id] = channel;
139 channel_handle.name = channel->GetChannelName();
141 #if defined(OS_POSIX)
142 // On POSIX, pass the renderer-side FD. Also mark it as auto-close so
143 // that it gets closed after it has been sent.
144 int renderer_fd = channel->TakeRendererFileDescriptor();
145 DCHECK_NE(-1, renderer_fd);
146 channel_handle.socket = base::FileDescriptor(renderer_fd, true);
147 #endif
150 Send(new GpuHostMsg_ChannelEstablished(channel_handle));
153 void GpuChannelManager::OnCloseChannel(
154 const IPC::ChannelHandle& channel_handle) {
155 for (GpuChannelMap::iterator iter = gpu_channels_.begin();
156 iter != gpu_channels_.end(); ++iter) {
157 if (iter->second->GetChannelName() == channel_handle.name) {
158 gpu_channels_.erase(iter);
159 return;
164 void GpuChannelManager::OnCreateViewCommandBuffer(
165 const gfx::GLSurfaceHandle& window,
166 int32 surface_id,
167 int32 client_id,
168 const GPUCreateCommandBufferConfig& init_params) {
169 DCHECK(surface_id);
170 int32 route_id = MSG_ROUTING_NONE;
172 GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
173 if (iter != gpu_channels_.end()) {
174 iter->second->CreateViewCommandBuffer(
175 window, surface_id, init_params, &route_id);
178 Send(new GpuHostMsg_CommandBufferCreated(route_id));
181 void GpuChannelManager::CreateImage(
182 gfx::PluginWindowHandle window, int32 client_id, int32 image_id) {
183 gfx::Size size;
185 GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
186 if (iter != gpu_channels_.end()) {
187 iter->second->CreateImage(window, image_id, &size);
190 Send(new GpuHostMsg_ImageCreated(size));
193 void GpuChannelManager::OnCreateImage(
194 gfx::PluginWindowHandle window, int32 client_id, int32 image_id) {
195 DCHECK(image_id);
197 if (image_operations_.empty()) {
198 CreateImage(window, client_id, image_id);
199 } else {
200 image_operations_.push_back(
201 new ImageOperation(0, base::Bind(&GpuChannelManager::CreateImage,
202 base::Unretained(this),
203 window,
204 client_id,
205 image_id)));
209 void GpuChannelManager::DeleteImage(int32 client_id, int32 image_id) {
210 GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
211 if (iter != gpu_channels_.end()) {
212 iter->second->DeleteImage(image_id);
216 void GpuChannelManager::OnDeleteImage(
217 int32 client_id, int32 image_id, int32 sync_point) {
218 DCHECK(image_id);
220 if (!sync_point && image_operations_.empty()) {
221 DeleteImage(client_id, image_id);
222 } else {
223 image_operations_.push_back(
224 new ImageOperation(sync_point,
225 base::Bind(&GpuChannelManager::DeleteImage,
226 base::Unretained(this),
227 client_id,
228 image_id)));
229 if (sync_point) {
230 sync_point_manager()->AddSyncPointCallback(
231 sync_point,
232 base::Bind(&GpuChannelManager::OnDeleteImageSyncPointRetired,
233 base::Unretained(this),
234 image_operations_.back()));
239 void GpuChannelManager::OnDeleteImageSyncPointRetired(
240 ImageOperation* image_operation) {
241 // Mark operation as no longer having a pending sync point.
242 image_operation->sync_point = 0;
244 // De-queue operations until we reach a pending sync point.
245 while (!image_operations_.empty()) {
246 // Check if operation has a pending sync point.
247 if (image_operations_.front()->sync_point)
248 return;
250 image_operations_.front()->callback.Run();
251 delete image_operations_.front();
252 image_operations_.pop_front();
256 void GpuChannelManager::OnLoadedShader(std::string program_proto) {
257 if (program_cache())
258 program_cache()->LoadProgram(program_proto);
261 bool GpuChannelManager::HandleMessagesScheduled() {
262 for (GpuChannelMap::iterator iter = gpu_channels_.begin();
263 iter != gpu_channels_.end(); ++iter) {
264 if (iter->second->handle_messages_scheduled())
265 return true;
267 return false;
270 uint64 GpuChannelManager::MessagesProcessed() {
271 uint64 messages_processed = 0;
273 for (GpuChannelMap::iterator iter = gpu_channels_.begin();
274 iter != gpu_channels_.end(); ++iter) {
275 messages_processed += iter->second->messages_processed();
277 return messages_processed;
280 void GpuChannelManager::LoseAllContexts() {
281 for (GpuChannelMap::iterator iter = gpu_channels_.begin();
282 iter != gpu_channels_.end(); ++iter) {
283 iter->second->MarkAllContextsLost();
285 base::MessageLoop::current()->PostTask(
286 FROM_HERE,
287 base::Bind(&GpuChannelManager::OnLoseAllContexts,
288 weak_factory_.GetWeakPtr()));
291 void GpuChannelManager::OnLoseAllContexts() {
292 gpu_channels_.clear();
295 gfx::GLSurface* GpuChannelManager::GetDefaultOffscreenSurface() {
296 if (!default_offscreen_surface_.get()) {
297 default_offscreen_surface_ =
298 gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1));
300 return default_offscreen_surface_.get();
303 } // namespace content