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 22#if defined(OS_WIN) 23#include "ui/base/win/shell.h" 24#endif 25 26namespace content { 27 28ImageTransportSurface::ImageTransportSurface() {} 29 30ImageTransportSurface::~ImageTransportSurface() {} 31 32scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface( 33 GpuChannelManager* manager, 34 GpuCommandBufferStub* stub, 35 const gfx::GLSurfaceHandle& handle) { 36 scoped_refptr<gfx::GLSurface> surface; 37 if (handle.transport_type == gfx::TEXTURE_TRANSPORT) 38 surface = new TextureImageTransportSurface(manager, stub, handle); 39 else 40 surface = CreateNativeSurface(manager, stub, handle); 41 42 if (!surface.get() || !surface->Initialize()) 43 return NULL; 44 return surface; 45} 46 47ImageTransportHelper::ImageTransportHelper(ImageTransportSurface* surface, 48 GpuChannelManager* manager, 49 GpuCommandBufferStub* stub, 50 gfx::PluginWindowHandle handle) 51 : surface_(surface), 52 manager_(manager), 53 stub_(stub->AsWeakPtr()), 54 handle_(handle) { 55 route_id_ = manager_->GenerateRouteID(); 56 manager_->AddRoute(route_id_, this); 57} 58 59ImageTransportHelper::~ImageTransportHelper() { 60 if (stub_.get()) { 61 stub_->SetLatencyInfoCallback( 62 base::Callback<void(const std::vector<ui::LatencyInfo>&)>()); 63 } 64 manager_->RemoveRoute(route_id_); 65} 66 67bool ImageTransportHelper::Initialize() { 68 gpu::gles2::GLES2Decoder* decoder = Decoder(); 69 70 if (!decoder) 71 return false; 72 73 decoder->SetResizeCallback( 74 base::Bind(&ImageTransportHelper::Resize, base::Unretained(this))); 75 76 stub_->SetLatencyInfoCallback( 77 base::Bind(&ImageTransportHelper::SetLatencyInfo, 78 base::Unretained(this))); 79 80 manager_->Send(new GpuHostMsg_AcceleratedSurfaceInitialized( 81 stub_->surface_id(), route_id_)); 82 83 return true; 84} 85 86void ImageTransportHelper::Destroy() {} 87 88bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) { 89 bool handled = true; 90 IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper, message) 91 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented, 92 OnBufferPresented) 93 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_WakeUpGpu, OnWakeUpGpu); 94 IPC_MESSAGE_UNHANDLED(handled = false) 95 IPC_END_MESSAGE_MAP() 96 return handled; 97} 98 99void ImageTransportHelper::SendAcceleratedSurfaceBuffersSwapped( 100 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params) { 101 // TRACE_EVENT for gpu tests: 102 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers", 103 TRACE_EVENT_SCOPE_THREAD, 104 "GLImpl", static_cast<int>(gfx::GetGLImplementation()), 105 "width", params.size.width()); 106 params.surface_id = stub_->surface_id(); 107 params.route_id = route_id_; 108 manager_->Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params)); 109} 110 111void ImageTransportHelper::SendAcceleratedSurfacePostSubBuffer( 112 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params) { 113 params.surface_id = stub_->surface_id(); 114 params.route_id = route_id_; 115 manager_->Send(new GpuHostMsg_AcceleratedSurfacePostSubBuffer(params)); 116} 117 118void ImageTransportHelper::SendAcceleratedSurfaceRelease() { 119 GpuHostMsg_AcceleratedSurfaceRelease_Params params; 120 params.surface_id = stub_->surface_id(); 121 manager_->Send(new GpuHostMsg_AcceleratedSurfaceRelease(params)); 122} 123 124void ImageTransportHelper::SendUpdateVSyncParameters( 125 base::TimeTicks timebase, base::TimeDelta interval) { 126 manager_->Send(new GpuHostMsg_UpdateVSyncParameters(stub_->surface_id(), 127 timebase, 128 interval)); 129} 130 131void ImageTransportHelper::SendLatencyInfo( 132 const std::vector<ui::LatencyInfo>& latency_info) { 133 manager_->Send(new GpuHostMsg_FrameDrawn(latency_info)); 134} 135 136void ImageTransportHelper::SetScheduled(bool is_scheduled) { 137 gpu::GpuScheduler* scheduler = Scheduler(); 138 if (!scheduler) 139 return; 140 141 scheduler->SetScheduled(is_scheduled); 142} 143 144void ImageTransportHelper::DeferToFence(base::Closure task) { 145 gpu::GpuScheduler* scheduler = Scheduler(); 146 DCHECK(scheduler); 147 148 scheduler->DeferToFence(task); 149} 150 151void ImageTransportHelper::SetPreemptByFlag( 152 scoped_refptr<gpu::PreemptionFlag> preemption_flag) { 153 stub_->channel()->SetPreemptByFlag(preemption_flag); 154} 155 156bool ImageTransportHelper::MakeCurrent() { 157 gpu::gles2::GLES2Decoder* decoder = Decoder(); 158 if (!decoder) 159 return false; 160 return decoder->MakeCurrent(); 161} 162 163void ImageTransportHelper::SetSwapInterval(gfx::GLContext* context) { 164#if defined(OS_WIN) 165 // If Aero Glass is enabled, then the renderer will handle ratelimiting and 166 // there's no tearing, so waiting for vsync is unnecessary. 167 if (ui::win::IsAeroGlassEnabled()) { 168 context->SetSwapInterval(0); 169 return; 170 } 171#endif 172 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) 173 context->SetSwapInterval(0); 174 else 175 context->SetSwapInterval(1); 176} 177 178void ImageTransportHelper::Suspend() { 179 manager_->Send(new GpuHostMsg_AcceleratedSurfaceSuspend(stub_->surface_id())); 180} 181 182gpu::GpuScheduler* ImageTransportHelper::Scheduler() { 183 if (!stub_.get()) 184 return NULL; 185 return stub_->scheduler(); 186} 187 188gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() { 189 if (!stub_.get()) 190 return NULL; 191 return stub_->decoder(); 192} 193 194void ImageTransportHelper::OnBufferPresented( 195 const AcceleratedSurfaceMsg_BufferPresented_Params& params) { 196 surface_->OnBufferPresented(params); 197} 198 199void ImageTransportHelper::OnWakeUpGpu() { 200 surface_->WakeUpGpu(); 201} 202 203void ImageTransportHelper::Resize(gfx::Size size, float scale_factor) { 204 surface_->OnResize(size, scale_factor); 205 206#if defined(OS_ANDROID) 207 manager_->gpu_memory_manager()->ScheduleManage( 208 GpuMemoryManager::kScheduleManageNow); 209#endif 210} 211 212void ImageTransportHelper::SetLatencyInfo( 213 const std::vector<ui::LatencyInfo>& latency_info) { 214 surface_->SetLatencyInfo(latency_info); 215} 216 217PassThroughImageTransportSurface::PassThroughImageTransportSurface( 218 GpuChannelManager* manager, 219 GpuCommandBufferStub* stub, 220 gfx::GLSurface* surface) 221 : GLSurfaceAdapter(surface), 222 did_set_swap_interval_(false) { 223 helper_.reset(new ImageTransportHelper(this, 224 manager, 225 stub, 226 gfx::kNullPluginWindow)); 227} 228 229bool PassThroughImageTransportSurface::Initialize() { 230 // The surface is assumed to have already been initialized. 231 return helper_->Initialize(); 232} 233 234void PassThroughImageTransportSurface::Destroy() { 235 helper_->Destroy(); 236 GLSurfaceAdapter::Destroy(); 237} 238 239void PassThroughImageTransportSurface::SetLatencyInfo( 240 const std::vector<ui::LatencyInfo>& latency_info) { 241 for (size_t i = 0; i < latency_info.size(); i++) 242 latency_info_.push_back(latency_info[i]); 243} 244 245bool PassThroughImageTransportSurface::SwapBuffers() { 246 // GetVsyncValues before SwapBuffers to work around Mali driver bug: 247 // crbug.com/223558. 248 SendVSyncUpdateIfAvailable(); 249 bool result = gfx::GLSurfaceAdapter::SwapBuffers(); 250 for (size_t i = 0; i < latency_info_.size(); i++) { 251 latency_info_[i].AddLatencyNumber( 252 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0); 253 } 254 255 helper_->SendLatencyInfo(latency_info_); 256 latency_info_.clear(); 257 return result; 258} 259 260bool PassThroughImageTransportSurface::PostSubBuffer( 261 int x, int y, int width, int height) { 262 SendVSyncUpdateIfAvailable(); 263 bool result = gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height); 264 for (size_t i = 0; i < latency_info_.size(); i++) { 265 latency_info_[i].AddLatencyNumber( 266 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0); 267 } 268 269 helper_->SendLatencyInfo(latency_info_); 270 latency_info_.clear(); 271 return result; 272} 273 274bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { 275 if (!did_set_swap_interval_) { 276 ImageTransportHelper::SetSwapInterval(context); 277 did_set_swap_interval_ = true; 278 } 279 return true; 280} 281 282void PassThroughImageTransportSurface::OnBufferPresented( 283 const AcceleratedSurfaceMsg_BufferPresented_Params& /* params */) { 284 NOTREACHED(); 285} 286 287void PassThroughImageTransportSurface::OnResize(gfx::Size size, 288 float scale_factor) { 289 Resize(size); 290} 291 292gfx::Size PassThroughImageTransportSurface::GetSize() { 293 return GLSurfaceAdapter::GetSize(); 294} 295 296void PassThroughImageTransportSurface::WakeUpGpu() { 297 NOTIMPLEMENTED(); 298} 299 300PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {} 301 302void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() { 303 gfx::VSyncProvider* vsync_provider = GetVSyncProvider(); 304 if (vsync_provider) { 305 vsync_provider->GetVSyncParameters( 306 base::Bind(&ImageTransportHelper::SendUpdateVSyncParameters, 307 helper_->AsWeakPtr())); 308 } 309} 310 311} // namespace content 312