summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/gpu_channel_host.cc
blob: 1f2eb21f8ab9c1bef22acc916ed3cc85d59000e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright (c) 2010 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 "chrome/renderer/gpu_channel_host.h"

#include "chrome/common/child_process.h"
#include "chrome/common/gpu_messages.h"
#include "chrome/renderer/command_buffer_proxy.h"

GpuChannelHost::GpuChannelHost() : state_(UNCONNECTED) {
}

GpuChannelHost::~GpuChannelHost() {
}

void GpuChannelHost::Connect(const std::string& channel_name) {
  // Open a channel to the GPU process.
  channel_.reset(new IPC::SyncChannel(
      channel_name, IPC::Channel::MODE_CLIENT, this, NULL,
      ChildProcess::current()->io_message_loop(), true,
      ChildProcess::current()->GetShutDownEvent()));

  // It is safe to send IPC messages before the channel completes the connection
  // and receives the hello message from the GPU process. The messages get
  // cached.
  state_ = CONNECTED;
}

void GpuChannelHost::OnMessageReceived(const IPC::Message& message) {
  DCHECK(message.routing_id() != MSG_ROUTING_CONTROL);
  if (!router_.RouteMessage(message)) {
    NOTREACHED() << "GpuChannelHost failed to route message";
  }
}

void GpuChannelHost::OnChannelConnected(int32 peer_pid) {
}

void GpuChannelHost::OnChannelError() {
  state_ = LOST;

  // Channel is invalid and will be reinitialized if this host is requested
  // again.
  channel_.reset();

  // Inform all the proxies that an error has occured. This will be reported via
  // OpenGL as a lost context.
  for (ProxyMap::iterator iter = proxies_.begin();
       iter != proxies_.end(); iter++) {
    router_.RemoveRoute(iter->first);
    iter->second->OnChannelError();
  }

  // The proxies are reference counted so this will not result in their
  // destruction if the client still holds a reference. The proxy will report
  // a lost context, indicating to the client that it needs to be recreated.
  proxies_.clear();
}

bool GpuChannelHost::Send(IPC::Message* message) {
  if (!channel_.get()) {
    delete message;
    return false;
  }

  return channel_->Send(message);
}

CommandBufferProxy* GpuChannelHost::CreateViewCommandBuffer(
    gfx::NativeViewId view) {
#if defined(ENABLE_GPU)
  // An error occurred. Need to get the host again to reinitialize it.
  if (!channel_.get())
    return NULL;

  int32 route_id;
  if (!Send(new GpuChannelMsg_CreateViewCommandBuffer(view, &route_id)) &&
      route_id != MSG_ROUTING_NONE) {
    return NULL;
  }

  CommandBufferProxy* command_buffer = new CommandBufferProxy(this, route_id);
  router_.AddRoute(route_id, command_buffer);
  proxies_[route_id] = command_buffer;
  return command_buffer;
#else
  return NULL;
#endif
}

CommandBufferProxy* GpuChannelHost::CreateOffscreenCommandBuffer(
    CommandBufferProxy* parent,
    const gfx::Size& size,
    uint32 parent_texture_id) {
#if defined(ENABLE_GPU)
  // An error occurred. Need to get the host again to reinitialize it.
  if (!channel_.get())
    return NULL;

  int32 parent_route_id = parent ? parent->route_id() : 0;
  int32 route_id;
  if (!Send(new GpuChannelMsg_CreateOffscreenCommandBuffer(parent_route_id,
                                                           size,
                                                           parent_texture_id,
                                                           &route_id)) &&
      route_id != MSG_ROUTING_NONE) {
    return NULL;
  }

  CommandBufferProxy* command_buffer = new CommandBufferProxy(this, route_id);
  router_.AddRoute(route_id, command_buffer);
  proxies_[route_id] = command_buffer;
  return command_buffer;
#else
  return NULL;
#endif
}

void GpuChannelHost::DestroyCommandBuffer(CommandBufferProxy* command_buffer) {
#if defined(ENABLE_GPU)
  Send(new GpuChannelMsg_DestroyCommandBuffer(command_buffer->route_id()));

  // Check the proxy has not already been removed after a channel error.
  int route_id = command_buffer->route_id();
  if (proxies_.find(command_buffer->route_id()) != proxies_.end()) {
    proxies_.erase(route_id);
    router_.RemoveRoute(route_id);
  }

  delete command_buffer;
#endif
}