// 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/child_thread.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 "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 "ui/gl/gl_bindings.h"
#include "ui/gl/gl_share_group.h"

GpuChannelManager::GpuChannelManager(ChildThread* gpu_child_thread,
                                     GpuWatchdog* watchdog,
                                     base::MessageLoopProxy* io_message_loop,
                                     base::WaitableEvent* shutdown_event)
    : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
      io_message_loop_(io_message_loop),
      shutdown_event_(shutdown_event),
      gpu_child_thread_(gpu_child_thread),
      ALLOW_THIS_IN_INITIALIZER_LIST(gpu_memory_manager_(this,
          GpuMemoryManager::kDefaultMaxSurfacesWithFrontbufferSoftLimit)),
      watchdog_(watchdog),
      sync_point_manager_(new SyncPointManager),
      program_cache_(NULL) {
  DCHECK(gpu_child_thread);
  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;
  }
}

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

void GpuChannelManager::RemoveChannel(int 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) {
  gpu_child_thread_->AddRoute(routing_id, listener);
}

void GpuChannelManager::RemoveRoute(int32 routing_id) {
  gpu_child_thread_->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;
}

void GpuChannelManager::AppendAllCommandBufferStubs(
    std::vector<GpuCommandBufferStubBase*>& stubs) {
  for (GpuChannelMap::const_iterator it = gpu_channels_.begin();
      it != gpu_channels_.end(); ++it ) {
    it->second->AppendAllCommandBufferStubs(stubs);
  }
}

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_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP_EX()
  return handled;
}

bool GpuChannelManager::Send(IPC::Message* msg) {
  return gpu_child_thread_->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_) {
      share_group_ = new gfx::GLShareGroup;
      DCHECK(!mailbox_manager_);
      mailbox_manager_ = new gpu::gles2::MailboxManager;
    }
    share_group = share_group_;
    mailbox_manager = mailbox_manager_;
  }

  scoped_refptr<GpuChannel> channel = new GpuChannel(this,
                                                     watchdog_,
                                                     share_group,
                                                     mailbox_manager,
                                                     client_id,
                                                     false);
  if (channel->Init(io_message_loop_, 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::LoseAllContexts() {
  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(
        false, gfx::Size(1, 1));
  }
  return default_offscreen_surface_.get();
}
