| OLD | NEW |
| (Empty) | |
| 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/renderer/browser_plugin/browser_plugin_texture_provider.h" |
| 6 |
| 7 #include "base/message_loop.h" |
| 8 #include "content/common/browser_plugin_messages.h" |
| 9 #include "content/renderer/browser_plugin/browser_plugin_manager.h" |
| 10 #include "content/renderer/browser_plugin/browser_plugin_manager_impl.h" |
| 11 #include "content/renderer/render_view_impl.h" |
| 12 #include "content/renderer/render_thread_impl.h" |
| 13 |
| 14 using WebKit::WebFloatRect; |
| 15 |
| 16 namespace { |
| 17 int GetMessageInstanceId(const IPC::Message& message) { |
| 18 int message_instance; |
| 19 DCHECK(!message.is_sync()); |
| 20 PickleIterator iter(message); |
| 21 // TODO(scshunt): is there a way to do this that doesn't rely on an int |
| 22 // to work? |
| 23 bool success = iter.ReadInt(&message_instance); |
| 24 DCHECK(success); |
| 25 return message_instance; |
| 26 } |
| 27 } |
| 28 |
| 29 namespace content { |
| 30 |
| 31 // Called on main therad |
| 32 BrowserPluginTextureProvider::BrowserPluginTextureProvider( |
| 33 int instance_id, |
| 34 int host_routing_id, |
| 35 IPC::ChannelProxy* channel_proxy) |
| 36 : client_(0), |
| 37 texture_id_(0), |
| 38 filter_(0), |
| 39 instance_id_(instance_id), |
| 40 main_loop_(base::MessageLoopProxy::current()), |
| 41 channel_proxy_(channel_proxy), |
| 42 host_routing_id_(host_routing_id), |
| 43 has_delayed_swap_(false) { |
| 44 // Once we get a fake ChannelProxy for testing, this should be enabled |
| 45 // DCHECK(channel_proxy_); |
| 46 } |
| 47 |
| 48 // Called on impl thread if we have one, main thread otherwise |
| 49 BrowserPluginTextureProvider::~BrowserPluginTextureProvider() { |
| 50 #ifndef NDBEUG |
| 51 // Destroy() ends our lifetime on the main thread, so this should |
| 52 // not be in use. |
| 53 bool locked = lock_.Try(); |
| 54 DCHECK(locked); |
| 55 lock_.Release(); |
| 56 #endif |
| 57 |
| 58 RemoveFilter(); |
| 59 if (client_) |
| 60 client_->stopUsingProvider(); |
| 61 } |
| 62 |
| 63 // Called on the main thread; ends the lifetime on this thread |
| 64 void BrowserPluginTextureProvider::Destroy() { |
| 65 // We need to release the lock before destruction, so this is |
| 66 // not a scoped lock |
| 67 lock_.Acquire(); |
| 68 |
| 69 if (impl_loop_) { |
| 70 lock_.Release(); |
| 71 impl_loop_->PostTask(FROM_HERE, base::Bind( |
| 72 &BrowserPluginTextureProvider::DestroyImpl, |
| 73 base::Unretained(this))); |
| 74 } else { |
| 75 lock_.Release(); |
| 76 DestroyImpl(); |
| 77 } |
| 78 } |
| 79 |
| 80 // Called on impl thread if we have one, main thread otherwise |
| 81 void BrowserPluginTextureProvider::DestroyImpl() { |
| 82 delete this; |
| 83 } |
| 84 |
| 85 // Called on impl thread (we store our impl thread loop here) |
| 86 void BrowserPluginTextureProvider::setTextureProviderClient(Client* client) { |
| 87 base::AutoLock scoped_lock(lock_); |
| 88 |
| 89 if (client_) { |
| 90 client_->stopUsingProvider(); |
| 91 } |
| 92 |
| 93 if (client) { |
| 94 if (!impl_loop_) { |
| 95 impl_loop_ = base::MessageLoopProxy::current(); |
| 96 |
| 97 SetUpFilter(); |
| 98 main_loop_->PostTask(FROM_HERE, base::Bind( |
| 99 &BrowserPluginTextureProvider::SignalReady, |
| 100 instance_id_)); |
| 101 } |
| 102 // This is tautological if we took the above branch, but |
| 103 // if we already had a loop, we want to verify that we are |
| 104 // on the same one. |
| 105 DCHECK(impl_loop_ == base::MessageLoopProxy::current()); |
| 106 |
| 107 if (has_delayed_swap_) { |
| 108 impl_loop_->PostTask(FROM_HERE, base::Bind( |
| 109 &BrowserPluginTextureProvider::OnBuffersSwapped, |
| 110 base::Unretained(this), |
| 111 instance_id_, |
| 112 texture_id_, |
| 113 delayed_swap_info_)); |
| 114 } |
| 115 } else { |
| 116 if (impl_loop_) { |
| 117 RemoveFilter(); |
| 118 } |
| 119 |
| 120 impl_loop_ = 0; |
| 121 } |
| 122 |
| 123 client_ = client; |
| 124 } |
| 125 |
| 126 // Called on main thread |
| 127 void BrowserPluginTextureProvider::SignalReady(int instance_id) { |
| 128 BrowserPluginManagerImpl::Get()->SignalTextureProviderIsReady(instance_id); |
| 129 } |
| 130 |
| 131 // Called on impl thread |
| 132 unsigned BrowserPluginTextureProvider::textureId() const { |
| 133 return texture_id_; |
| 134 } |
| 135 |
| 136 // Called on impl thread |
| 137 bool BrowserPluginTextureProvider::premultipliedAlpha() const { |
| 138 return true; |
| 139 } |
| 140 |
| 141 // Called on impl thread |
| 142 bool BrowserPluginTextureProvider::flipped() const { |
| 143 return true; |
| 144 } |
| 145 |
| 146 // Called on impl thread |
| 147 WebFloatRect BrowserPluginTextureProvider::uvRect() const { |
| 148 if (texture_size_.width() == 0 || texture_size_.height() == 0) |
| 149 return WebFloatRect(0, 0, 1, 1); |
| 150 |
| 151 return WebFloatRect( |
| 152 0, |
| 153 0, |
| 154 (static_cast<float>(container_size_.width())) / texture_size_.width(), |
| 155 (static_cast<float>(container_size_.height())) / texture_size_.height()); |
| 156 } |
| 157 |
| 158 // Called on impl thread |
| 159 void BrowserPluginTextureProvider::OnMessageReceived( |
| 160 const IPC::Message& message) { |
| 161 IPC_BEGIN_MESSAGE_MAP(BrowserPluginTextureProvider, message) |
| 162 IPC_MESSAGE_HANDLER(BrowserPluginMsg_BuffersSwapped, OnBuffersSwapped) |
| 163 IPC_MESSAGE_HANDLER(BrowserPluginMsg_SurfaceResize, OnSurfaceResize) |
| 164 IPC_END_MESSAGE_MAP() |
| 165 } |
| 166 |
| 167 // Called on impl thread |
| 168 void BrowserPluginTextureProvider::OnBuffersSwapped( |
| 169 int instance_id, |
| 170 uint64 surface_handle, |
| 171 const BrowserPlugin_SwapInfo& info) { |
| 172 DCHECK(surface_handle != 0); |
| 173 DCHECK(client_); |
| 174 DCHECK(instance_id == instance_id_); |
| 175 |
| 176 texture_id_ = surface_handle; |
| 177 client_->didReceiveFrame(); |
| 178 Send(new BrowserPluginHostMsg_BuffersSwappedACK( |
| 179 host_routing_id_, |
| 180 info, |
| 181 client_->insertSyncPoint())); |
| 182 } |
| 183 |
| 184 // Called on impl thread |
| 185 void BrowserPluginTextureProvider::OnSurfaceResize( |
| 186 int instance_id, |
| 187 const gfx::Size& size) { |
| 188 DCHECK(instance_id == instance_id_); |
| 189 texture_size_ = size; |
| 190 } |
| 191 |
| 192 // Called on main thread prior to attaching client |
| 193 void BrowserPluginTextureProvider::SurfaceResize(const gfx::Size& size) { |
| 194 DCHECK(!client_); |
| 195 DCHECK(!impl_loop_); |
| 196 OnSurfaceResize(instance_id_, size); |
| 197 } |
| 198 |
| 199 // Called on any thread |
| 200 void BrowserPluginTextureProvider::Resize(const gfx::Size& size) { |
| 201 base::AutoLock scoped_lock(lock_); |
| 202 |
| 203 if (impl_loop_) |
| 204 impl_loop_->PostTask(FROM_HERE, base::Bind( |
| 205 &BrowserPluginTextureProvider::ResizeImpl, |
| 206 base::Unretained(this), |
| 207 size)); |
| 208 else |
| 209 ResizeImpl(size); |
| 210 } |
| 211 |
| 212 // Called on main thread |
| 213 void BrowserPluginTextureProvider::SetDelayedSwap( |
| 214 uint64 surface_handle, |
| 215 const BrowserPlugin_SwapInfo& info) { |
| 216 base::AutoLock scoped_lock(lock_); |
| 217 |
| 218 if (impl_loop_) { |
| 219 impl_loop_->PostTask(FROM_HERE, base::Bind( |
| 220 &BrowserPluginTextureProvider::OnBuffersSwapped, |
| 221 base::Unretained(this), |
| 222 instance_id_, |
| 223 surface_handle, |
| 224 info)); |
| 225 } else { |
| 226 has_delayed_swap_ = true; |
| 227 delayed_swap_info_ = info; |
| 228 texture_id_ = surface_handle; |
| 229 // TODO(scshunt): Fix this |
| 230 } |
| 231 } |
| 232 |
| 233 // Called on any thread |
| 234 bool BrowserPluginTextureProvider::Send(IPC::Message* message) { |
| 235 DCHECK(channel_proxy_); |
| 236 return channel_proxy_->Send(message); |
| 237 } |
| 238 |
| 239 |
| 240 // Called on impl thread if we have one, otherwise main thread |
| 241 void BrowserPluginTextureProvider::ResizeImpl(const gfx::Size& size) { |
| 242 container_size_ = size; |
| 243 } |
| 244 |
| 245 // Called on impl thread to create a new filter and attach it to the |
| 246 // ChannelProxy |
| 247 void BrowserPluginTextureProvider::SetUpFilter() { |
| 248 DCHECK(channel_proxy_); |
| 249 |
| 250 static const uint32 messages[] = { |
| 251 BrowserPluginMsg_BuffersSwapped::ID, |
| 252 BrowserPluginMsg_SurfaceResize::ID, |
| 253 }; |
| 254 |
| 255 filter_ = new IPC::ForwardingMessageFilter( |
| 256 messages, |
| 257 arraysize(messages), |
| 258 impl_loop_); |
| 259 filter_->AddRoute( |
| 260 instance_id_, |
| 261 base::Bind( |
| 262 &BrowserPluginTextureProvider::OnMessageReceived, |
| 263 base::Unretained(this))); |
| 264 filter_->SetIDCallback(base::Bind(&GetMessageInstanceId)); |
| 265 channel_proxy_->AddFilter(filter_); |
| 266 } |
| 267 |
| 268 // Called on impl thread to clear the filter |
| 269 void BrowserPluginTextureProvider::RemoveFilter() { |
| 270 if (filter_) { |
| 271 DCHECK(impl_loop_); |
| 272 DCHECK(impl_loop_ == base::MessageLoopProxy::current()); |
| 273 channel_proxy_->RemoveFilter(filter_); |
| 274 } |
| 275 } |
| 276 |
| 277 } // namespace content |
| OLD | NEW |