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 26 namespace content { 27 28 ImageTransportSurface::ImageTransportSurface() {} 29 30 ImageTransportSurface::~ImageTransportSurface() {} 31 32 scoped_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 47 ImageTransportHelper::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 59 ImageTransportHelper::~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 67 bool 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 86 void ImageTransportHelper::Destroy() {} 87 88 bool 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 99 void 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 111 void 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 118 void ImageTransportHelper::SendAcceleratedSurfaceRelease() { 119 GpuHostMsg_AcceleratedSurfaceRelease_Params params; 120 params.surface_id = stub_->surface_id(); 121 manager_->Send(new GpuHostMsg_AcceleratedSurfaceRelease(params)); 122 } 123 124 void ImageTransportHelper::SendUpdateVSyncParameters( 125 base::TimeTicks timebase, base::TimeDelta interval) { 126 manager_->Send(new GpuHostMsg_UpdateVSyncParameters(stub_->surface_id(), 127 timebase, 128 interval)); 129 } 130 131 void ImageTransportHelper::SendLatencyInfo( 132 const std::vector<ui::LatencyInfo>& latency_info) { 133 manager_->Send(new GpuHostMsg_FrameDrawn(latency_info)); 134 } 135 136 void ImageTransportHelper::SetScheduled(bool is_scheduled) { 137 gpu::GpuScheduler* scheduler = Scheduler(); 138 if (!scheduler) 139 return; 140 141 scheduler->SetScheduled(is_scheduled); 142 } 143 144 void ImageTransportHelper::DeferToFence(base::Closure task) { 145 gpu::GpuScheduler* scheduler = Scheduler(); 146 DCHECK(scheduler); 147 148 scheduler->DeferToFence(task); 149 } 150 151 void ImageTransportHelper::SetPreemptByFlag( 152 scoped_refptr<gpu::PreemptionFlag> preemption_flag) { 153 stub_->channel()->SetPreemptByFlag(preemption_flag); 154 } 155 156 bool ImageTransportHelper::MakeCurrent() { 157 gpu::gles2::GLES2Decoder* decoder = Decoder(); 158 if (!decoder) 159 return false; 160 return decoder->MakeCurrent(); 161 } 162 163 void 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 178 void ImageTransportHelper::Suspend() { 179 manager_->Send(new GpuHostMsg_AcceleratedSurfaceSuspend(stub_->surface_id())); 180 } 181 182 gpu::GpuScheduler* ImageTransportHelper::Scheduler() { 183 if (!stub_.get()) 184 return NULL; 185 return stub_->scheduler(); 186 } 187 188 gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() { 189 if (!stub_.get()) 190 return NULL; 191 return stub_->decoder(); 192 } 193 194 void ImageTransportHelper::OnBufferPresented( 195 const AcceleratedSurfaceMsg_BufferPresented_Params& params) { 196 surface_->OnBufferPresented(params); 197 } 198 199 void ImageTransportHelper::OnWakeUpGpu() { 200 surface_->WakeUpGpu(); 201 } 202 203 void 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 212 void ImageTransportHelper::SetLatencyInfo( 213 const std::vector<ui::LatencyInfo>& latency_info) { 214 surface_->SetLatencyInfo(latency_info); 215 } 216 217 PassThroughImageTransportSurface::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 229 bool PassThroughImageTransportSurface::Initialize() { 230 // The surface is assumed to have already been initialized. 231 return helper_->Initialize(); 232 } 233 234 void PassThroughImageTransportSurface::Destroy() { 235 helper_->Destroy(); 236 GLSurfaceAdapter::Destroy(); 237 } 238 239 void 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 245 bool 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 260 bool 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 274 bool 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 282 void PassThroughImageTransportSurface::OnBufferPresented( 283 const AcceleratedSurfaceMsg_BufferPresented_Params& /* params */) { 284 NOTREACHED(); 285 } 286 287 void PassThroughImageTransportSurface::OnResize(gfx::Size size, 288 float scale_factor) { 289 Resize(size); 290 } 291 292 gfx::Size PassThroughImageTransportSurface::GetSize() { 293 return GLSurfaceAdapter::GetSize(); 294 } 295 296 void PassThroughImageTransportSurface::WakeUpGpu() { 297 NOTIMPLEMENTED(); 298 } 299 300 PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {} 301 302 void 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