Home | History | Annotate | Download | only in gpu
      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 #include "content/common/gpu/gpu_channel_manager.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/command_line.h"
      9 #include "content/common/gpu/gpu_channel.h"
     10 #include "content/common/gpu/gpu_memory_manager.h"
     11 #include "content/common/gpu/gpu_messages.h"
     12 #include "content/common/gpu/sync_point_manager.h"
     13 #include "content/common/message_router.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 "gpu/command_buffer/service/shader_translator_cache.h"
     19 #include "ui/gl/gl_bindings.h"
     20 #include "ui/gl/gl_share_group.h"
     21 
     22 namespace content {
     23 
     24 GpuChannelManager::ImageOperation::ImageOperation(
     25     int32 sync_point, base::Closure callback)
     26     : sync_point(sync_point),
     27       callback(callback) {
     28 }
     29 
     30 GpuChannelManager::ImageOperation::~ImageOperation() {
     31 }
     32 
     33 GpuChannelManager::GpuChannelManager(MessageRouter* router,
     34                                      GpuWatchdog* watchdog,
     35                                      base::MessageLoopProxy* io_message_loop,
     36                                      base::WaitableEvent* shutdown_event)
     37     : weak_factory_(this),
     38       io_message_loop_(io_message_loop),
     39       shutdown_event_(shutdown_event),
     40       router_(router),
     41       gpu_memory_manager_(
     42           this,
     43           GpuMemoryManager::kDefaultMaxSurfacesWithFrontbufferSoftLimit),
     44       watchdog_(watchdog),
     45       sync_point_manager_(new SyncPointManager) {
     46   DCHECK(router_);
     47   DCHECK(io_message_loop);
     48   DCHECK(shutdown_event);
     49 }
     50 
     51 GpuChannelManager::~GpuChannelManager() {
     52   gpu_channels_.clear();
     53   if (default_offscreen_surface_.get()) {
     54     default_offscreen_surface_->Destroy();
     55     default_offscreen_surface_ = NULL;
     56   }
     57   DCHECK(image_operations_.empty());
     58 }
     59 
     60 gpu::gles2::ProgramCache* GpuChannelManager::program_cache() {
     61   if (!program_cache_.get() &&
     62       (gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary ||
     63        gfx::g_driver_gl.ext.b_GL_OES_get_program_binary) &&
     64       !CommandLine::ForCurrentProcess()->HasSwitch(
     65           switches::kDisableGpuProgramCache)) {
     66     program_cache_.reset(new gpu::gles2::MemoryProgramCache());
     67   }
     68   return program_cache_.get();
     69 }
     70 
     71 gpu::gles2::ShaderTranslatorCache*
     72 GpuChannelManager::shader_translator_cache() {
     73   if (!shader_translator_cache_.get())
     74     shader_translator_cache_ = new gpu::gles2::ShaderTranslatorCache;
     75   return shader_translator_cache_.get();
     76 }
     77 
     78 void GpuChannelManager::RemoveChannel(int client_id) {
     79   Send(new GpuHostMsg_DestroyChannel(client_id));
     80   gpu_channels_.erase(client_id);
     81 }
     82 
     83 int GpuChannelManager::GenerateRouteID() {
     84   static int last_id = 0;
     85   return ++last_id;
     86 }
     87 
     88 void GpuChannelManager::AddRoute(int32 routing_id, IPC::Listener* listener) {
     89   router_->AddRoute(routing_id, listener);
     90 }
     91 
     92 void GpuChannelManager::RemoveRoute(int32 routing_id) {
     93   router_->RemoveRoute(routing_id);
     94 }
     95 
     96 GpuChannel* GpuChannelManager::LookupChannel(int32 client_id) {
     97   GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
     98   if (iter == gpu_channels_.end())
     99     return NULL;
    100   else
    101     return iter->second;
    102 }
    103 
    104 bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) {
    105   bool handled = true;
    106   IPC_BEGIN_MESSAGE_MAP(GpuChannelManager, msg)
    107     IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel)
    108     IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel)
    109     IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer,
    110                         OnCreateViewCommandBuffer)
    111     IPC_MESSAGE_HANDLER(GpuMsg_CreateImage, OnCreateImage)
    112     IPC_MESSAGE_HANDLER(GpuMsg_DeleteImage, OnDeleteImage)
    113     IPC_MESSAGE_HANDLER(GpuMsg_CreateGpuMemoryBuffer, OnCreateGpuMemoryBuffer)
    114     IPC_MESSAGE_HANDLER(GpuMsg_DestroyGpuMemoryBuffer, OnDestroyGpuMemoryBuffer)
    115     IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader, OnLoadedShader)
    116     IPC_MESSAGE_UNHANDLED(handled = false)
    117   IPC_END_MESSAGE_MAP()
    118   return handled;
    119 }
    120 
    121 bool GpuChannelManager::Send(IPC::Message* msg) { return router_->Send(msg); }
    122 
    123 void GpuChannelManager::OnEstablishChannel(int client_id, bool share_context) {
    124   IPC::ChannelHandle channel_handle;
    125 
    126   gfx::GLShareGroup* share_group = NULL;
    127   gpu::gles2::MailboxManager* mailbox_manager = NULL;
    128   if (share_context) {
    129     if (!share_group_.get()) {
    130       share_group_ = new gfx::GLShareGroup;
    131       DCHECK(!mailbox_manager_.get());
    132       mailbox_manager_ = new gpu::gles2::MailboxManager;
    133     }
    134     share_group = share_group_.get();
    135     mailbox_manager = mailbox_manager_.get();
    136   }
    137 
    138   scoped_ptr<GpuChannel> channel(new GpuChannel(
    139       this, watchdog_, share_group, mailbox_manager, client_id, false));
    140   channel->Init(io_message_loop_.get(), shutdown_event_);
    141   channel_handle.name = channel->GetChannelName();
    142 
    143 #if defined(OS_POSIX)
    144   // On POSIX, pass the renderer-side FD. Also mark it as auto-close so
    145   // that it gets closed after it has been sent.
    146   int renderer_fd = channel->TakeRendererFileDescriptor();
    147   DCHECK_NE(-1, renderer_fd);
    148   channel_handle.socket = base::FileDescriptor(renderer_fd, true);
    149 #endif
    150 
    151   gpu_channels_.set(client_id, channel.Pass());
    152 
    153   Send(new GpuHostMsg_ChannelEstablished(channel_handle));
    154 }
    155 
    156 void GpuChannelManager::OnCloseChannel(
    157     const IPC::ChannelHandle& channel_handle) {
    158   for (GpuChannelMap::iterator iter = gpu_channels_.begin();
    159        iter != gpu_channels_.end(); ++iter) {
    160     if (iter->second->GetChannelName() == channel_handle.name) {
    161       gpu_channels_.erase(iter);
    162       return;
    163     }
    164   }
    165 }
    166 
    167 void GpuChannelManager::OnCreateViewCommandBuffer(
    168     const gfx::GLSurfaceHandle& window,
    169     int32 surface_id,
    170     int32 client_id,
    171     const GPUCreateCommandBufferConfig& init_params,
    172     int32 route_id) {
    173   DCHECK(surface_id);
    174   CreateCommandBufferResult result = CREATE_COMMAND_BUFFER_FAILED;
    175 
    176   GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
    177   if (iter != gpu_channels_.end()) {
    178     result = iter->second->CreateViewCommandBuffer(
    179         window, surface_id, init_params, route_id);
    180   }
    181 
    182   Send(new GpuHostMsg_CommandBufferCreated(result));
    183 }
    184 
    185 void GpuChannelManager::CreateImage(
    186     gfx::PluginWindowHandle window, int32 client_id, int32 image_id) {
    187   gfx::Size size;
    188 
    189   GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
    190   if (iter != gpu_channels_.end()) {
    191     iter->second->CreateImage(window, image_id, &size);
    192   }
    193 
    194   Send(new GpuHostMsg_ImageCreated(size));
    195 }
    196 
    197 void GpuChannelManager::OnCreateImage(
    198     gfx::PluginWindowHandle window, int32 client_id, int32 image_id) {
    199   DCHECK(image_id);
    200 
    201   if (image_operations_.empty()) {
    202     CreateImage(window, client_id, image_id);
    203   } else {
    204     image_operations_.push_back(
    205         new ImageOperation(0, base::Bind(&GpuChannelManager::CreateImage,
    206                                          base::Unretained(this),
    207                                          window,
    208                                          client_id,
    209                                          image_id)));
    210   }
    211 }
    212 
    213 void GpuChannelManager::DeleteImage(int32 client_id, int32 image_id) {
    214   GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
    215   if (iter != gpu_channels_.end()) {
    216     iter->second->DeleteImage(image_id);
    217   }
    218 }
    219 
    220 void GpuChannelManager::OnDeleteImage(
    221     int32 client_id, int32 image_id, int32 sync_point) {
    222   DCHECK(image_id);
    223 
    224   if (!sync_point && image_operations_.empty()) {
    225     DeleteImage(client_id, image_id);
    226   } else {
    227     image_operations_.push_back(
    228         new ImageOperation(sync_point,
    229                            base::Bind(&GpuChannelManager::DeleteImage,
    230                                       base::Unretained(this),
    231                                       client_id,
    232                                       image_id)));
    233     if (sync_point) {
    234       sync_point_manager()->AddSyncPointCallback(
    235           sync_point,
    236           base::Bind(&GpuChannelManager::OnDeleteImageSyncPointRetired,
    237                      base::Unretained(this),
    238                      image_operations_.back()));
    239     }
    240   }
    241 }
    242 
    243 void GpuChannelManager::OnDeleteImageSyncPointRetired(
    244     ImageOperation* image_operation) {
    245   // Mark operation as no longer having a pending sync point.
    246   image_operation->sync_point = 0;
    247 
    248   // De-queue operations until we reach a pending sync point.
    249   while (!image_operations_.empty()) {
    250     // Check if operation has a pending sync point.
    251     if (image_operations_.front()->sync_point)
    252       return;
    253 
    254     image_operations_.front()->callback.Run();
    255     delete image_operations_.front();
    256     image_operations_.pop_front();
    257   }
    258 }
    259 
    260 void GpuChannelManager::OnCreateGpuMemoryBuffer(
    261     const gfx::GpuMemoryBufferHandle& handle,
    262     const gfx::Size& size,
    263     unsigned internalformat,
    264     unsigned usage) {
    265   Send(new GpuHostMsg_GpuMemoryBufferCreated(gfx::GpuMemoryBufferHandle()));
    266 }
    267 
    268 void GpuChannelManager::OnDestroyGpuMemoryBuffer(
    269     const gfx::GpuMemoryBufferHandle& handle,
    270     int32 sync_point) {
    271 }
    272 
    273 void GpuChannelManager::OnLoadedShader(std::string program_proto) {
    274   if (program_cache())
    275     program_cache()->LoadProgram(program_proto);
    276 }
    277 
    278 bool GpuChannelManager::HandleMessagesScheduled() {
    279   for (GpuChannelMap::iterator iter = gpu_channels_.begin();
    280        iter != gpu_channels_.end(); ++iter) {
    281     if (iter->second->handle_messages_scheduled())
    282       return true;
    283   }
    284   return false;
    285 }
    286 
    287 uint64 GpuChannelManager::MessagesProcessed() {
    288   uint64 messages_processed = 0;
    289 
    290   for (GpuChannelMap::iterator iter = gpu_channels_.begin();
    291        iter != gpu_channels_.end(); ++iter) {
    292     messages_processed += iter->second->messages_processed();
    293   }
    294   return messages_processed;
    295 }
    296 
    297 void GpuChannelManager::LoseAllContexts() {
    298   for (GpuChannelMap::iterator iter = gpu_channels_.begin();
    299        iter != gpu_channels_.end(); ++iter) {
    300     iter->second->MarkAllContextsLost();
    301   }
    302   base::MessageLoop::current()->PostTask(
    303       FROM_HERE,
    304       base::Bind(&GpuChannelManager::OnLoseAllContexts,
    305                  weak_factory_.GetWeakPtr()));
    306 }
    307 
    308 void GpuChannelManager::OnLoseAllContexts() {
    309   gpu_channels_.clear();
    310 }
    311 
    312 gfx::GLSurface* GpuChannelManager::GetDefaultOffscreenSurface() {
    313   if (!default_offscreen_surface_.get()) {
    314     default_offscreen_surface_ =
    315         gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size());
    316   }
    317   return default_offscreen_surface_.get();
    318 }
    319 
    320 }  // namespace content
    321