• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 namespace content {
23 
ImageTransportSurface()24 ImageTransportSurface::ImageTransportSurface() {}
25 
~ImageTransportSurface()26 ImageTransportSurface::~ImageTransportSurface() {}
27 
CreateSurface(GpuChannelManager * manager,GpuCommandBufferStub * stub,const gfx::GLSurfaceHandle & handle)28 scoped_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 
ImageTransportHelper(ImageTransportSurface * surface,GpuChannelManager * manager,GpuCommandBufferStub * stub,gfx::PluginWindowHandle handle)43 ImageTransportHelper::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 
~ImageTransportHelper()55 ImageTransportHelper::~ImageTransportHelper() {
56   if (stub_.get()) {
57     stub_->SetLatencyInfoCallback(
58         base::Callback<void(const ui::LatencyInfo&)>());
59   }
60   manager_->RemoveRoute(route_id_);
61 }
62 
Initialize()63 bool 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 
Destroy()82 void ImageTransportHelper::Destroy() {}
83 
OnMessageReceived(const IPC::Message & message)84 bool 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 
SendAcceleratedSurfaceBuffersSwapped(GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params)96 void 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 
SendAcceleratedSurfacePostSubBuffer(GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params)108 void 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 
SendAcceleratedSurfaceRelease()115 void ImageTransportHelper::SendAcceleratedSurfaceRelease() {
116   GpuHostMsg_AcceleratedSurfaceRelease_Params params;
117   params.surface_id = stub_->surface_id();
118   manager_->Send(new GpuHostMsg_AcceleratedSurfaceRelease(params));
119 }
120 
SendResizeView(const gfx::Size & size)121 void ImageTransportHelper::SendResizeView(const gfx::Size& size) {
122   manager_->Send(new GpuHostMsg_ResizeView(stub_->surface_id(),
123                                            route_id_,
124                                            size));
125 }
126 
SendUpdateVSyncParameters(base::TimeTicks timebase,base::TimeDelta interval)127 void ImageTransportHelper::SendUpdateVSyncParameters(
128       base::TimeTicks timebase, base::TimeDelta interval) {
129   manager_->Send(new GpuHostMsg_UpdateVSyncParameters(stub_->surface_id(),
130                                                       timebase,
131                                                       interval));
132 }
133 
SendLatencyInfo(const ui::LatencyInfo & latency_info)134 void ImageTransportHelper::SendLatencyInfo(
135     const ui::LatencyInfo& latency_info) {
136   manager_->Send(new GpuHostMsg_FrameDrawn(latency_info));
137 }
138 
SetScheduled(bool is_scheduled)139 void ImageTransportHelper::SetScheduled(bool is_scheduled) {
140   gpu::GpuScheduler* scheduler = Scheduler();
141   if (!scheduler)
142     return;
143 
144   scheduler->SetScheduled(is_scheduled);
145 }
146 
DeferToFence(base::Closure task)147 void ImageTransportHelper::DeferToFence(base::Closure task) {
148   gpu::GpuScheduler* scheduler = Scheduler();
149   DCHECK(scheduler);
150 
151   scheduler->DeferToFence(task);
152 }
153 
SetPreemptByFlag(scoped_refptr<gpu::PreemptionFlag> preemption_flag)154 void ImageTransportHelper::SetPreemptByFlag(
155     scoped_refptr<gpu::PreemptionFlag> preemption_flag) {
156   stub_->channel()->SetPreemptByFlag(preemption_flag);
157 }
158 
MakeCurrent()159 bool ImageTransportHelper::MakeCurrent() {
160   gpu::gles2::GLES2Decoder* decoder = Decoder();
161   if (!decoder)
162     return false;
163   return decoder->MakeCurrent();
164 }
165 
SetSwapInterval(gfx::GLContext * context)166 void ImageTransportHelper::SetSwapInterval(gfx::GLContext* context) {
167   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
168     context->SetSwapInterval(0);
169   else
170     context->SetSwapInterval(1);
171 }
172 
Suspend()173 void ImageTransportHelper::Suspend() {
174   manager_->Send(new GpuHostMsg_AcceleratedSurfaceSuspend(stub_->surface_id()));
175 }
176 
Scheduler()177 gpu::GpuScheduler* ImageTransportHelper::Scheduler() {
178   if (!stub_.get())
179     return NULL;
180   return stub_->scheduler();
181 }
182 
Decoder()183 gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() {
184   if (!stub_.get())
185     return NULL;
186   return stub_->decoder();
187 }
188 
OnBufferPresented(const AcceleratedSurfaceMsg_BufferPresented_Params & params)189 void ImageTransportHelper::OnBufferPresented(
190     const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
191   surface_->OnBufferPresented(params);
192 }
193 
OnResizeViewACK()194 void ImageTransportHelper::OnResizeViewACK() {
195   surface_->OnResizeViewACK();
196 }
197 
OnWakeUpGpu()198 void ImageTransportHelper::OnWakeUpGpu() {
199   surface_->WakeUpGpu();
200 }
201 
Resize(gfx::Size size,float scale_factor)202 void 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 
SetLatencyInfo(const ui::LatencyInfo & latency_info)211 void ImageTransportHelper::SetLatencyInfo(
212     const ui::LatencyInfo& latency_info) {
213   surface_->SetLatencyInfo(latency_info);
214 }
215 
PassThroughImageTransportSurface(GpuChannelManager * manager,GpuCommandBufferStub * stub,gfx::GLSurface * surface,bool transport)216 PassThroughImageTransportSurface::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 
Initialize()232 bool PassThroughImageTransportSurface::Initialize() {
233   // The surface is assumed to have already been initialized.
234   return helper_->Initialize();
235 }
236 
Destroy()237 void PassThroughImageTransportSurface::Destroy() {
238   helper_->Destroy();
239   GLSurfaceAdapter::Destroy();
240 }
241 
DeferDraws()242 bool 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 
SetLatencyInfo(const ui::LatencyInfo & latency_info)252 void PassThroughImageTransportSurface::SetLatencyInfo(
253     const ui::LatencyInfo& latency_info) {
254   latency_info_ = latency_info;
255 }
256 
SwapBuffers()257 bool PassThroughImageTransportSurface::SwapBuffers() {
258   // GetVsyncValues before SwapBuffers to work around Mali driver bug:
259   // crbug.com/223558.
260   SendVSyncUpdateIfAvailable();
261   bool result = gfx::GLSurfaceAdapter::SwapBuffers();
262   latency_info_.AddLatencyNumber(
263       ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
264 
265   if (transport_) {
266     DCHECK(!is_swap_buffers_pending_);
267     is_swap_buffers_pending_ = true;
268 
269     // Round trip to the browser UI thread, for throttling, by sending a dummy
270     // SwapBuffers message.
271     GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
272     params.surface_handle = 0;
273     params.latency_info = latency_info_;
274     params.size = surface()->GetSize();
275     helper_->SendAcceleratedSurfaceBuffersSwapped(params);
276   } else {
277     helper_->SendLatencyInfo(latency_info_);
278   }
279   return result;
280 }
281 
PostSubBuffer(int x,int y,int width,int height)282 bool PassThroughImageTransportSurface::PostSubBuffer(
283     int x, int y, int width, int height) {
284   SendVSyncUpdateIfAvailable();
285   bool result = gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height);
286   latency_info_.AddLatencyNumber(
287       ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
288 
289   if (transport_) {
290     DCHECK(!is_swap_buffers_pending_);
291     is_swap_buffers_pending_ = true;
292 
293     // Round trip to the browser UI thread, for throttling, by sending a dummy
294     // PostSubBuffer message.
295     GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params;
296     params.surface_handle = 0;
297     params.latency_info = latency_info_;
298     params.surface_size = surface()->GetSize();
299     params.x = x;
300     params.y = y;
301     params.width = width;
302     params.height = height;
303     helper_->SendAcceleratedSurfacePostSubBuffer(params);
304 
305     helper_->SetScheduled(false);
306   } else {
307     helper_->SendLatencyInfo(latency_info_);
308   }
309   return result;
310 }
311 
OnMakeCurrent(gfx::GLContext * context)312 bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
313   if (!did_set_swap_interval_) {
314     ImageTransportHelper::SetSwapInterval(context);
315     did_set_swap_interval_ = true;
316   }
317   return true;
318 }
319 
OnBufferPresented(const AcceleratedSurfaceMsg_BufferPresented_Params &)320 void PassThroughImageTransportSurface::OnBufferPresented(
321     const AcceleratedSurfaceMsg_BufferPresented_Params& /* params */) {
322   DCHECK(transport_);
323   DCHECK(is_swap_buffers_pending_);
324   is_swap_buffers_pending_ = false;
325   if (did_unschedule_) {
326     did_unschedule_ = false;
327     helper_->SetScheduled(true);
328   }
329 }
330 
OnResizeViewACK()331 void PassThroughImageTransportSurface::OnResizeViewACK() {
332   DCHECK(transport_);
333   Resize(new_size_);
334 
335   TRACE_EVENT_ASYNC_END0("gpu", "OnResize", this);
336   helper_->SetScheduled(true);
337 }
338 
OnResize(gfx::Size size,float scale_factor)339 void PassThroughImageTransportSurface::OnResize(gfx::Size size,
340                                                 float scale_factor) {
341   new_size_ = size;
342 
343   if (transport_) {
344     helper_->SendResizeView(size);
345     helper_->SetScheduled(false);
346     TRACE_EVENT_ASYNC_BEGIN2("gpu", "OnResize", this,
347                              "width", size.width(), "height", size.height());
348   } else {
349     Resize(new_size_);
350   }
351 }
352 
GetSize()353 gfx::Size PassThroughImageTransportSurface::GetSize() {
354   return GLSurfaceAdapter::GetSize();
355 }
356 
WakeUpGpu()357 void PassThroughImageTransportSurface::WakeUpGpu() {
358   NOTIMPLEMENTED();
359 }
360 
~PassThroughImageTransportSurface()361 PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {}
362 
SendVSyncUpdateIfAvailable()363 void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() {
364   gfx::VSyncProvider* vsync_provider = GetVSyncProvider();
365   if (vsync_provider) {
366     vsync_provider->GetVSyncParameters(
367       base::Bind(&ImageTransportHelper::SendUpdateVSyncParameters,
368                  helper_->AsWeakPtr()));
369   }
370 }
371 
372 }  // namespace content
373