image_transport_surface.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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/image_transport_surface.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/command_line.h" 10#include "base/debug/trace_event.h" 11#include "content/common/gpu/gpu_channel.h" 12#include "content/common/gpu/gpu_channel_manager.h" 13#include "content/common/gpu/gpu_command_buffer_stub.h" 14#include "content/common/gpu/gpu_messages.h" 15#include "content/common/gpu/sync_point_manager.h" 16#include "content/common/gpu/texture_image_transport_surface.h" 17#include "gpu/command_buffer/service/gpu_scheduler.h" 18#include "ui/gfx/vsync_provider.h" 19#include "ui/gl/gl_implementation.h" 20#include "ui/gl/gl_switches.h" 21 22namespace content { 23 24ImageTransportSurface::ImageTransportSurface() {} 25 26ImageTransportSurface::~ImageTransportSurface() {} 27 28scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface( 29 GpuChannelManager* manager, 30 GpuCommandBufferStub* stub, 31 const gfx::GLSurfaceHandle& handle) { 32 scoped_refptr<gfx::GLSurface> surface; 33 if (handle.transport_type == gfx::TEXTURE_TRANSPORT) 34 surface = new TextureImageTransportSurface(manager, stub, handle); 35 else 36 surface = CreateNativeSurface(manager, stub, handle); 37 38 if (!surface.get() || !surface->Initialize()) 39 return NULL; 40 return surface; 41} 42 43ImageTransportHelper::ImageTransportHelper(ImageTransportSurface* surface, 44 GpuChannelManager* manager, 45 GpuCommandBufferStub* stub, 46 gfx::PluginWindowHandle handle) 47 : surface_(surface), 48 manager_(manager), 49 stub_(stub->AsWeakPtr()), 50 handle_(handle) { 51 route_id_ = manager_->GenerateRouteID(); 52 manager_->AddRoute(route_id_, this); 53} 54 55ImageTransportHelper::~ImageTransportHelper() { 56 if (stub_.get()) { 57 stub_->SetLatencyInfoCallback( 58 base::Callback<void(const std::vector<ui::LatencyInfo>&)>()); 59 } 60 manager_->RemoveRoute(route_id_); 61} 62 63bool ImageTransportHelper::Initialize() { 64 gpu::gles2::GLES2Decoder* decoder = Decoder(); 65 66 if (!decoder) 67 return false; 68 69 decoder->SetResizeCallback( 70 base::Bind(&ImageTransportHelper::Resize, base::Unretained(this))); 71 72 stub_->SetLatencyInfoCallback( 73 base::Bind(&ImageTransportHelper::SetLatencyInfo, 74 base::Unretained(this))); 75 76 manager_->Send(new GpuHostMsg_AcceleratedSurfaceInitialized( 77 stub_->surface_id(), route_id_)); 78 79 return true; 80} 81 82void ImageTransportHelper::Destroy() {} 83 84bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) { 85 bool handled = true; 86 IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper, message) 87 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented, 88 OnBufferPresented) 89 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_ResizeViewACK, OnResizeViewACK); 90 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_WakeUpGpu, OnWakeUpGpu); 91 IPC_MESSAGE_UNHANDLED(handled = false) 92 IPC_END_MESSAGE_MAP() 93 return handled; 94} 95 96void ImageTransportHelper::SendAcceleratedSurfaceBuffersSwapped( 97 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params) { 98 // TRACE_EVENT for gpu tests: 99 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers", 100 TRACE_EVENT_SCOPE_THREAD, 101 "GLImpl", static_cast<int>(gfx::GetGLImplementation()), 102 "width", params.size.width()); 103 params.surface_id = stub_->surface_id(); 104 params.route_id = route_id_; 105 manager_->Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params)); 106} 107 108void ImageTransportHelper::SendAcceleratedSurfacePostSubBuffer( 109 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params) { 110 params.surface_id = stub_->surface_id(); 111 params.route_id = route_id_; 112 manager_->Send(new GpuHostMsg_AcceleratedSurfacePostSubBuffer(params)); 113} 114 115void ImageTransportHelper::SendAcceleratedSurfaceRelease() { 116 GpuHostMsg_AcceleratedSurfaceRelease_Params params; 117 params.surface_id = stub_->surface_id(); 118 manager_->Send(new GpuHostMsg_AcceleratedSurfaceRelease(params)); 119} 120 121void ImageTransportHelper::SendResizeView(const gfx::Size& size) { 122 manager_->Send(new GpuHostMsg_ResizeView(stub_->surface_id(), 123 route_id_, 124 size)); 125} 126 127void ImageTransportHelper::SendUpdateVSyncParameters( 128 base::TimeTicks timebase, base::TimeDelta interval) { 129 manager_->Send(new GpuHostMsg_UpdateVSyncParameters(stub_->surface_id(), 130 timebase, 131 interval)); 132} 133 134void ImageTransportHelper::SendLatencyInfo( 135 const std::vector<ui::LatencyInfo>& latency_info) { 136 manager_->Send(new GpuHostMsg_FrameDrawn(latency_info)); 137} 138 139void ImageTransportHelper::SetScheduled(bool is_scheduled) { 140 gpu::GpuScheduler* scheduler = Scheduler(); 141 if (!scheduler) 142 return; 143 144 scheduler->SetScheduled(is_scheduled); 145} 146 147void ImageTransportHelper::DeferToFence(base::Closure task) { 148 gpu::GpuScheduler* scheduler = Scheduler(); 149 DCHECK(scheduler); 150 151 scheduler->DeferToFence(task); 152} 153 154void ImageTransportHelper::SetPreemptByFlag( 155 scoped_refptr<gpu::PreemptionFlag> preemption_flag) { 156 stub_->channel()->SetPreemptByFlag(preemption_flag); 157} 158 159bool ImageTransportHelper::MakeCurrent() { 160 gpu::gles2::GLES2Decoder* decoder = Decoder(); 161 if (!decoder) 162 return false; 163 return decoder->MakeCurrent(); 164} 165 166void ImageTransportHelper::SetSwapInterval(gfx::GLContext* context) { 167 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) 168 context->SetSwapInterval(0); 169 else 170 context->SetSwapInterval(1); 171} 172 173void ImageTransportHelper::Suspend() { 174 manager_->Send(new GpuHostMsg_AcceleratedSurfaceSuspend(stub_->surface_id())); 175} 176 177gpu::GpuScheduler* ImageTransportHelper::Scheduler() { 178 if (!stub_.get()) 179 return NULL; 180 return stub_->scheduler(); 181} 182 183gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() { 184 if (!stub_.get()) 185 return NULL; 186 return stub_->decoder(); 187} 188 189void ImageTransportHelper::OnBufferPresented( 190 const AcceleratedSurfaceMsg_BufferPresented_Params& params) { 191 surface_->OnBufferPresented(params); 192} 193 194void ImageTransportHelper::OnResizeViewACK() { 195 surface_->OnResizeViewACK(); 196} 197 198void ImageTransportHelper::OnWakeUpGpu() { 199 surface_->WakeUpGpu(); 200} 201 202void ImageTransportHelper::Resize(gfx::Size size, float scale_factor) { 203 surface_->OnResize(size, scale_factor); 204 205#if defined(OS_ANDROID) 206 manager_->gpu_memory_manager()->ScheduleManage( 207 GpuMemoryManager::kScheduleManageNow); 208#endif 209} 210 211void ImageTransportHelper::SetLatencyInfo( 212 const std::vector<ui::LatencyInfo>& latency_info) { 213 surface_->SetLatencyInfo(latency_info); 214} 215 216PassThroughImageTransportSurface::PassThroughImageTransportSurface( 217 GpuChannelManager* manager, 218 GpuCommandBufferStub* stub, 219 gfx::GLSurface* surface, 220 bool transport) 221 : GLSurfaceAdapter(surface), 222 transport_(transport), 223 did_set_swap_interval_(false), 224 did_unschedule_(false), 225 is_swap_buffers_pending_(false) { 226 helper_.reset(new ImageTransportHelper(this, 227 manager, 228 stub, 229 gfx::kNullPluginWindow)); 230} 231 232bool PassThroughImageTransportSurface::Initialize() { 233 // The surface is assumed to have already been initialized. 234 return helper_->Initialize(); 235} 236 237void PassThroughImageTransportSurface::Destroy() { 238 helper_->Destroy(); 239 GLSurfaceAdapter::Destroy(); 240} 241 242bool PassThroughImageTransportSurface::DeferDraws() { 243 if (is_swap_buffers_pending_) { 244 DCHECK(!did_unschedule_); 245 did_unschedule_ = true; 246 helper_->SetScheduled(false); 247 return true; 248 } 249 return false; 250} 251 252void PassThroughImageTransportSurface::SetLatencyInfo( 253 const std::vector<ui::LatencyInfo>& latency_info) { 254 for (size_t i = 0; i < latency_info.size(); i++) 255 latency_info_.push_back(latency_info[i]); 256} 257 258bool PassThroughImageTransportSurface::SwapBuffers() { 259 // GetVsyncValues before SwapBuffers to work around Mali driver bug: 260 // crbug.com/223558. 261 SendVSyncUpdateIfAvailable(); 262 bool result = gfx::GLSurfaceAdapter::SwapBuffers(); 263 for (size_t i = 0; i < latency_info_.size(); i++) { 264 latency_info_[i].AddLatencyNumber( 265 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0); 266 } 267 268 if (transport_) { 269 DCHECK(!is_swap_buffers_pending_); 270 is_swap_buffers_pending_ = true; 271 272 // Round trip to the browser UI thread, for throttling, by sending a dummy 273 // SwapBuffers message. 274 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; 275 params.surface_handle = 0; 276 params.latency_info.swap(latency_info_); 277 params.size = surface()->GetSize(); 278 helper_->SendAcceleratedSurfaceBuffersSwapped(params); 279 } else { 280 helper_->SendLatencyInfo(latency_info_); 281 } 282 latency_info_.clear(); 283 return result; 284} 285 286bool PassThroughImageTransportSurface::PostSubBuffer( 287 int x, int y, int width, int height) { 288 SendVSyncUpdateIfAvailable(); 289 bool result = gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height); 290 for (size_t i = 0; i < latency_info_.size(); i++) { 291 latency_info_[i].AddLatencyNumber( 292 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0); 293 } 294 295 if (transport_) { 296 DCHECK(!is_swap_buffers_pending_); 297 is_swap_buffers_pending_ = true; 298 299 // Round trip to the browser UI thread, for throttling, by sending a dummy 300 // PostSubBuffer message. 301 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; 302 params.surface_handle = 0; 303 params.latency_info.swap(latency_info_); 304 params.surface_size = surface()->GetSize(); 305 params.x = x; 306 params.y = y; 307 params.width = width; 308 params.height = height; 309 helper_->SendAcceleratedSurfacePostSubBuffer(params); 310 311 helper_->SetScheduled(false); 312 } else { 313 helper_->SendLatencyInfo(latency_info_); 314 } 315 latency_info_.clear(); 316 return result; 317} 318 319bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { 320 if (!did_set_swap_interval_) { 321 ImageTransportHelper::SetSwapInterval(context); 322 did_set_swap_interval_ = true; 323 } 324 return true; 325} 326 327void PassThroughImageTransportSurface::OnBufferPresented( 328 const AcceleratedSurfaceMsg_BufferPresented_Params& /* params */) { 329 DCHECK(transport_); 330 DCHECK(is_swap_buffers_pending_); 331 is_swap_buffers_pending_ = false; 332 if (did_unschedule_) { 333 did_unschedule_ = false; 334 helper_->SetScheduled(true); 335 } 336} 337 338void PassThroughImageTransportSurface::OnResizeViewACK() { 339 DCHECK(transport_); 340 Resize(new_size_); 341 342 TRACE_EVENT_ASYNC_END0("gpu", "OnResize", this); 343 helper_->SetScheduled(true); 344} 345 346void PassThroughImageTransportSurface::OnResize(gfx::Size size, 347 float scale_factor) { 348 new_size_ = size; 349 350 if (transport_) { 351 helper_->SendResizeView(size); 352 helper_->SetScheduled(false); 353 TRACE_EVENT_ASYNC_BEGIN2("gpu", "OnResize", this, 354 "width", size.width(), "height", size.height()); 355 } else { 356 Resize(new_size_); 357 } 358} 359 360gfx::Size PassThroughImageTransportSurface::GetSize() { 361 return GLSurfaceAdapter::GetSize(); 362} 363 364void PassThroughImageTransportSurface::WakeUpGpu() { 365 NOTIMPLEMENTED(); 366} 367 368PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {} 369 370void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() { 371 gfx::VSyncProvider* vsync_provider = GetVSyncProvider(); 372 if (vsync_provider) { 373 vsync_provider->GetVSyncParameters( 374 base::Bind(&ImageTransportHelper::SendUpdateVSyncParameters, 375 helper_->AsWeakPtr())); 376 } 377} 378 379} // namespace content 380