root/content/common/gpu/gpu_channel_manager.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. callback
  2. sync_point_manager_
  3. program_cache
  4. shader_translator_cache
  5. RemoveChannel
  6. GenerateRouteID
  7. AddRoute
  8. RemoveRoute
  9. LookupChannel
  10. OnMessageReceived
  11. Send
  12. OnEstablishChannel
  13. OnCloseChannel
  14. OnCreateViewCommandBuffer
  15. CreateImage
  16. OnCreateImage
  17. DeleteImage
  18. OnDeleteImage
  19. OnDeleteImageSyncPointRetired
  20. OnLoadedShader
  21. HandleMessagesScheduled
  22. MessagesProcessed
  23. LoseAllContexts
  24. OnLoseAllContexts
  25. GetDefaultOffscreenSurface

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/common/gpu/gpu_channel_manager.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "content/common/gpu/gpu_channel.h"
#include "content/common/gpu/gpu_memory_manager.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/gpu/sync_point_manager.h"
#include "content/common/message_router.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/memory_program_cache.h"
#include "gpu/command_buffer/service/shader_translator_cache.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_share_group.h"

namespace content {

GpuChannelManager::ImageOperation::ImageOperation(
    int32 sync_point, base::Closure callback)
    : sync_point(sync_point),
      callback(callback) {
}

GpuChannelManager::ImageOperation::~ImageOperation() {
}

GpuChannelManager::GpuChannelManager(MessageRouter* router,
                                     GpuWatchdog* watchdog,
                                     base::MessageLoopProxy* io_message_loop,
                                     base::WaitableEvent* shutdown_event)
    : weak_factory_(this),
      io_message_loop_(io_message_loop),
      shutdown_event_(shutdown_event),
      router_(router),
      gpu_memory_manager_(
          this,
          GpuMemoryManager::kDefaultMaxSurfacesWithFrontbufferSoftLimit),
      watchdog_(watchdog),
      sync_point_manager_(new SyncPointManager) {
  DCHECK(router_);
  DCHECK(io_message_loop);
  DCHECK(shutdown_event);
}

GpuChannelManager::~GpuChannelManager() {
  gpu_channels_.clear();
  if (default_offscreen_surface_.get()) {
    default_offscreen_surface_->Destroy();
    default_offscreen_surface_ = NULL;
  }
  DCHECK(image_operations_.empty());
}

gpu::gles2::ProgramCache* GpuChannelManager::program_cache() {
  if (!program_cache_.get() &&
      (gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary ||
       gfx::g_driver_gl.ext.b_GL_OES_get_program_binary) &&
      !CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableGpuProgramCache)) {
    program_cache_.reset(new gpu::gles2::MemoryProgramCache());
  }
  return program_cache_.get();
}

gpu::gles2::ShaderTranslatorCache*
GpuChannelManager::shader_translator_cache() {
  if (!shader_translator_cache_.get())
    shader_translator_cache_ = new gpu::gles2::ShaderTranslatorCache;
  return shader_translator_cache_.get();
}

void GpuChannelManager::RemoveChannel(int client_id) {
  Send(new GpuHostMsg_DestroyChannel(client_id));
  gpu_channels_.erase(client_id);
}

int GpuChannelManager::GenerateRouteID() {
  static int last_id = 0;
  return ++last_id;
}

void GpuChannelManager::AddRoute(int32 routing_id, IPC::Listener* listener) {
  router_->AddRoute(routing_id, listener);
}

void GpuChannelManager::RemoveRoute(int32 routing_id) {
  router_->RemoveRoute(routing_id);
}

GpuChannel* GpuChannelManager::LookupChannel(int32 client_id) {
  GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
  if (iter == gpu_channels_.end())
    return NULL;
  else
    return iter->second.get();
}

bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) {
  bool msg_is_ok = true;
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP_EX(GpuChannelManager, msg, msg_is_ok)
    IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel)
    IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel)
    IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer,
                        OnCreateViewCommandBuffer)
    IPC_MESSAGE_HANDLER(GpuMsg_CreateImage, OnCreateImage)
    IPC_MESSAGE_HANDLER(GpuMsg_DeleteImage, OnDeleteImage)
    IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader, OnLoadedShader)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP_EX()
  return handled;
}

bool GpuChannelManager::Send(IPC::Message* msg) { return router_->Send(msg); }

void GpuChannelManager::OnEstablishChannel(int client_id, bool share_context) {
  IPC::ChannelHandle channel_handle;

  gfx::GLShareGroup* share_group = NULL;
  gpu::gles2::MailboxManager* mailbox_manager = NULL;
  if (share_context) {
    if (!share_group_.get()) {
      share_group_ = new gfx::GLShareGroup;
      DCHECK(!mailbox_manager_.get());
      mailbox_manager_ = new gpu::gles2::MailboxManager;
    }
    share_group = share_group_.get();
    mailbox_manager = mailbox_manager_.get();
  }

  scoped_refptr<GpuChannel> channel = new GpuChannel(this,
                                                     watchdog_,
                                                     share_group,
                                                     mailbox_manager,
                                                     client_id,
                                                     false);
  channel->Init(io_message_loop_.get(), shutdown_event_);
  gpu_channels_[client_id] = channel;
  channel_handle.name = channel->GetChannelName();

#if defined(OS_POSIX)
  // On POSIX, pass the renderer-side FD. Also mark it as auto-close so
  // that it gets closed after it has been sent.
  int renderer_fd = channel->TakeRendererFileDescriptor();
  DCHECK_NE(-1, renderer_fd);
  channel_handle.socket = base::FileDescriptor(renderer_fd, true);
#endif

  Send(new GpuHostMsg_ChannelEstablished(channel_handle));
}

void GpuChannelManager::OnCloseChannel(
    const IPC::ChannelHandle& channel_handle) {
  for (GpuChannelMap::iterator iter = gpu_channels_.begin();
       iter != gpu_channels_.end(); ++iter) {
    if (iter->second->GetChannelName() == channel_handle.name) {
      gpu_channels_.erase(iter);
      return;
    }
  }
}

void GpuChannelManager::OnCreateViewCommandBuffer(
    const gfx::GLSurfaceHandle& window,
    int32 surface_id,
    int32 client_id,
    const GPUCreateCommandBufferConfig& init_params) {
  DCHECK(surface_id);
  int32 route_id = MSG_ROUTING_NONE;

  GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
  if (iter != gpu_channels_.end()) {
    iter->second->CreateViewCommandBuffer(
        window, surface_id, init_params, &route_id);
  }

  Send(new GpuHostMsg_CommandBufferCreated(route_id));
}

void GpuChannelManager::CreateImage(
    gfx::PluginWindowHandle window, int32 client_id, int32 image_id) {
  gfx::Size size;

  GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
  if (iter != gpu_channels_.end()) {
    iter->second->CreateImage(window, image_id, &size);
  }

  Send(new GpuHostMsg_ImageCreated(size));
}

void GpuChannelManager::OnCreateImage(
    gfx::PluginWindowHandle window, int32 client_id, int32 image_id) {
  DCHECK(image_id);

  if (image_operations_.empty()) {
    CreateImage(window, client_id, image_id);
  } else {
    image_operations_.push_back(
        new ImageOperation(0, base::Bind(&GpuChannelManager::CreateImage,
                                         base::Unretained(this),
                                         window,
                                         client_id,
                                         image_id)));
  }
}

void GpuChannelManager::DeleteImage(int32 client_id, int32 image_id) {
  GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
  if (iter != gpu_channels_.end()) {
    iter->second->DeleteImage(image_id);
  }
}

void GpuChannelManager::OnDeleteImage(
    int32 client_id, int32 image_id, int32 sync_point) {
  DCHECK(image_id);

  if (!sync_point && image_operations_.empty()) {
    DeleteImage(client_id, image_id);
  } else {
    image_operations_.push_back(
        new ImageOperation(sync_point,
                           base::Bind(&GpuChannelManager::DeleteImage,
                                      base::Unretained(this),
                                      client_id,
                                      image_id)));
    if (sync_point) {
      sync_point_manager()->AddSyncPointCallback(
          sync_point,
          base::Bind(&GpuChannelManager::OnDeleteImageSyncPointRetired,
                     base::Unretained(this),
                     image_operations_.back()));
    }
  }
}

void GpuChannelManager::OnDeleteImageSyncPointRetired(
    ImageOperation* image_operation) {
  // Mark operation as no longer having a pending sync point.
  image_operation->sync_point = 0;

  // De-queue operations until we reach a pending sync point.
  while (!image_operations_.empty()) {
    // Check if operation has a pending sync point.
    if (image_operations_.front()->sync_point)
      return;

    image_operations_.front()->callback.Run();
    delete image_operations_.front();
    image_operations_.pop_front();
  }
}

void GpuChannelManager::OnLoadedShader(std::string program_proto) {
  if (program_cache())
    program_cache()->LoadProgram(program_proto);
}

bool GpuChannelManager::HandleMessagesScheduled() {
  for (GpuChannelMap::iterator iter = gpu_channels_.begin();
       iter != gpu_channels_.end(); ++iter) {
    if (iter->second->handle_messages_scheduled())
      return true;
  }
  return false;
}

uint64 GpuChannelManager::MessagesProcessed() {
  uint64 messages_processed = 0;

  for (GpuChannelMap::iterator iter = gpu_channels_.begin();
       iter != gpu_channels_.end(); ++iter) {
    messages_processed += iter->second->messages_processed();
  }
  return messages_processed;
}

void GpuChannelManager::LoseAllContexts() {
  for (GpuChannelMap::iterator iter = gpu_channels_.begin();
       iter != gpu_channels_.end(); ++iter) {
    iter->second->MarkAllContextsLost();
  }
  base::MessageLoop::current()->PostTask(
      FROM_HERE,
      base::Bind(&GpuChannelManager::OnLoseAllContexts,
                 weak_factory_.GetWeakPtr()));
}

void GpuChannelManager::OnLoseAllContexts() {
  gpu_channels_.clear();
}

gfx::GLSurface* GpuChannelManager::GetDefaultOffscreenSurface() {
  if (!default_offscreen_surface_.get()) {
    default_offscreen_surface_ =
        gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1));
  }
  return default_offscreen_surface_.get();
}

}  // namespace content

/* [<][>][^][v][top][bottom][index][help] */