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
ImageTransportSurface()28 ImageTransportSurface::ImageTransportSurface() {}
29
~ImageTransportSurface()30 ImageTransportSurface::~ImageTransportSurface() {}
31
CreateSurface(GpuChannelManager * manager,GpuCommandBufferStub * stub,const gfx::GLSurfaceHandle & handle)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
ImageTransportHelper(ImageTransportSurface * surface,GpuChannelManager * manager,GpuCommandBufferStub * stub,gfx::PluginWindowHandle handle)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
~ImageTransportHelper()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
Initialize()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
Destroy()86 void ImageTransportHelper::Destroy() {}
87
OnMessageReceived(const IPC::Message & message)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
SendAcceleratedSurfaceBuffersSwapped(GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params)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
SendAcceleratedSurfacePostSubBuffer(GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params)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
SendAcceleratedSurfaceRelease()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
SendUpdateVSyncParameters(base::TimeTicks timebase,base::TimeDelta interval)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
SendLatencyInfo(const std::vector<ui::LatencyInfo> & latency_info)131 void ImageTransportHelper::SendLatencyInfo(
132 const std::vector<ui::LatencyInfo>& latency_info) {
133 manager_->Send(new GpuHostMsg_FrameDrawn(latency_info));
134 }
135
SetScheduled(bool is_scheduled)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
DeferToFence(base::Closure task)144 void ImageTransportHelper::DeferToFence(base::Closure task) {
145 gpu::GpuScheduler* scheduler = Scheduler();
146 DCHECK(scheduler);
147
148 scheduler->DeferToFence(task);
149 }
150
SetPreemptByFlag(scoped_refptr<gpu::PreemptionFlag> preemption_flag)151 void ImageTransportHelper::SetPreemptByFlag(
152 scoped_refptr<gpu::PreemptionFlag> preemption_flag) {
153 stub_->channel()->SetPreemptByFlag(preemption_flag);
154 }
155
MakeCurrent()156 bool ImageTransportHelper::MakeCurrent() {
157 gpu::gles2::GLES2Decoder* decoder = Decoder();
158 if (!decoder)
159 return false;
160 return decoder->MakeCurrent();
161 }
162
SetSwapInterval(gfx::GLContext * context)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
Suspend()178 void ImageTransportHelper::Suspend() {
179 manager_->Send(new GpuHostMsg_AcceleratedSurfaceSuspend(stub_->surface_id()));
180 }
181
Scheduler()182 gpu::GpuScheduler* ImageTransportHelper::Scheduler() {
183 if (!stub_.get())
184 return NULL;
185 return stub_->scheduler();
186 }
187
Decoder()188 gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() {
189 if (!stub_.get())
190 return NULL;
191 return stub_->decoder();
192 }
193
OnBufferPresented(const AcceleratedSurfaceMsg_BufferPresented_Params & params)194 void ImageTransportHelper::OnBufferPresented(
195 const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
196 surface_->OnBufferPresented(params);
197 }
198
OnWakeUpGpu()199 void ImageTransportHelper::OnWakeUpGpu() {
200 surface_->WakeUpGpu();
201 }
202
Resize(gfx::Size size,float scale_factor)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
SetLatencyInfo(const std::vector<ui::LatencyInfo> & latency_info)212 void ImageTransportHelper::SetLatencyInfo(
213 const std::vector<ui::LatencyInfo>& latency_info) {
214 surface_->SetLatencyInfo(latency_info);
215 }
216
PassThroughImageTransportSurface(GpuChannelManager * manager,GpuCommandBufferStub * stub,gfx::GLSurface * surface)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
Initialize()229 bool PassThroughImageTransportSurface::Initialize() {
230 // The surface is assumed to have already been initialized.
231 return helper_->Initialize();
232 }
233
Destroy()234 void PassThroughImageTransportSurface::Destroy() {
235 helper_->Destroy();
236 GLSurfaceAdapter::Destroy();
237 }
238
SetLatencyInfo(const std::vector<ui::LatencyInfo> & latency_info)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
SwapBuffers()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
PostSubBuffer(int x,int y,int width,int height)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
OnMakeCurrent(gfx::GLContext * context)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
OnBufferPresented(const AcceleratedSurfaceMsg_BufferPresented_Params &)282 void PassThroughImageTransportSurface::OnBufferPresented(
283 const AcceleratedSurfaceMsg_BufferPresented_Params& /* params */) {
284 NOTREACHED();
285 }
286
OnResize(gfx::Size size,float scale_factor)287 void PassThroughImageTransportSurface::OnResize(gfx::Size size,
288 float scale_factor) {
289 Resize(size);
290 }
291
GetSize()292 gfx::Size PassThroughImageTransportSurface::GetSize() {
293 return GLSurfaceAdapter::GetSize();
294 }
295
WakeUpGpu()296 void PassThroughImageTransportSurface::WakeUpGpu() {
297 NOTIMPLEMENTED();
298 }
299
~PassThroughImageTransportSurface()300 PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {}
301
SendVSyncUpdateIfAvailable()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