- add sources.
[platform/framework/web/crosswalk.git] / src / content / common / gpu / image_transport_surface.cc
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/gl/gl_implementation.h"
19 #include "ui/gl/gl_switches.h"
20 #include "ui/gl/vsync_provider.h"
21
22 namespace content {
23
24 ImageTransportSurface::ImageTransportSurface() {}
25
26 ImageTransportSurface::~ImageTransportSurface() {}
27
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
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
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
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   return true;
77 }
78
79 void ImageTransportHelper::Destroy() {}
80
81 bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) {
82   bool handled = true;
83   IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper, message)
84     IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented,
85                         OnBufferPresented)
86     IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_ResizeViewACK, OnResizeViewACK);
87     IPC_MESSAGE_UNHANDLED(handled = false)
88   IPC_END_MESSAGE_MAP()
89   return handled;
90 }
91
92 void ImageTransportHelper::SendAcceleratedSurfaceBuffersSwapped(
93     GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params) {
94   // TRACE_EVENT for gpu tests:
95   TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
96                        TRACE_EVENT_SCOPE_THREAD,
97                        "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
98                        "width", params.size.width());
99   params.surface_id = stub_->surface_id();
100   params.route_id = route_id_;
101   manager_->Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
102 }
103
104 void ImageTransportHelper::SendAcceleratedSurfacePostSubBuffer(
105     GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params) {
106   params.surface_id = stub_->surface_id();
107   params.route_id = route_id_;
108   manager_->Send(new GpuHostMsg_AcceleratedSurfacePostSubBuffer(params));
109 }
110
111 void ImageTransportHelper::SendAcceleratedSurfaceRelease() {
112   GpuHostMsg_AcceleratedSurfaceRelease_Params params;
113   params.surface_id = stub_->surface_id();
114   manager_->Send(new GpuHostMsg_AcceleratedSurfaceRelease(params));
115 }
116
117 void ImageTransportHelper::SendResizeView(const gfx::Size& size) {
118   manager_->Send(new GpuHostMsg_ResizeView(stub_->surface_id(),
119                                            route_id_,
120                                            size));
121 }
122
123 void ImageTransportHelper::SendUpdateVSyncParameters(
124       base::TimeTicks timebase, base::TimeDelta interval) {
125   manager_->Send(new GpuHostMsg_UpdateVSyncParameters(stub_->surface_id(),
126                                                       timebase,
127                                                       interval));
128 }
129
130 void ImageTransportHelper::SendLatencyInfo(
131     const ui::LatencyInfo& latency_info) {
132   manager_->Send(new GpuHostMsg_FrameDrawn(latency_info));
133 }
134
135 void ImageTransportHelper::SetScheduled(bool is_scheduled) {
136   gpu::GpuScheduler* scheduler = Scheduler();
137   if (!scheduler)
138     return;
139
140   scheduler->SetScheduled(is_scheduled);
141 }
142
143 void ImageTransportHelper::DeferToFence(base::Closure task) {
144   gpu::GpuScheduler* scheduler = Scheduler();
145   DCHECK(scheduler);
146
147   scheduler->DeferToFence(task);
148 }
149
150 void ImageTransportHelper::SetPreemptByFlag(
151     scoped_refptr<gpu::PreemptionFlag> preemption_flag) {
152   stub_->channel()->SetPreemptByFlag(preemption_flag);
153 }
154
155 bool ImageTransportHelper::MakeCurrent() {
156   gpu::gles2::GLES2Decoder* decoder = Decoder();
157   if (!decoder)
158     return false;
159   return decoder->MakeCurrent();
160 }
161
162 void ImageTransportHelper::SetSwapInterval(gfx::GLContext* context) {
163   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
164     context->SetSwapInterval(0);
165   else
166     context->SetSwapInterval(1);
167 }
168
169 void ImageTransportHelper::Suspend() {
170   manager_->Send(new GpuHostMsg_AcceleratedSurfaceSuspend(stub_->surface_id()));
171 }
172
173 gpu::GpuScheduler* ImageTransportHelper::Scheduler() {
174   if (!stub_.get())
175     return NULL;
176   return stub_->scheduler();
177 }
178
179 gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() {
180   if (!stub_.get())
181     return NULL;
182   return stub_->decoder();
183 }
184
185 void ImageTransportHelper::OnBufferPresented(
186     const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
187   surface_->OnBufferPresented(params);
188 }
189
190 void ImageTransportHelper::OnResizeViewACK() {
191   surface_->OnResizeViewACK();
192 }
193
194 void ImageTransportHelper::Resize(gfx::Size size, float scale_factor) {
195   surface_->OnResize(size, scale_factor);
196
197 #if defined(OS_ANDROID)
198   manager_->gpu_memory_manager()->ScheduleManage(
199       GpuMemoryManager::kScheduleManageNow);
200 #endif
201 }
202
203 void ImageTransportHelper::SetLatencyInfo(
204     const ui::LatencyInfo& latency_info) {
205   surface_->SetLatencyInfo(latency_info);
206 }
207
208 PassThroughImageTransportSurface::PassThroughImageTransportSurface(
209     GpuChannelManager* manager,
210     GpuCommandBufferStub* stub,
211     gfx::GLSurface* surface,
212     bool transport)
213     : GLSurfaceAdapter(surface),
214       transport_(transport),
215       did_set_swap_interval_(false),
216       did_unschedule_(false),
217       is_swap_buffers_pending_(false) {
218   helper_.reset(new ImageTransportHelper(this,
219                                          manager,
220                                          stub,
221                                          gfx::kNullPluginWindow));
222 }
223
224 bool PassThroughImageTransportSurface::Initialize() {
225   // The surface is assumed to have already been initialized.
226   return helper_->Initialize();
227 }
228
229 void PassThroughImageTransportSurface::Destroy() {
230   helper_->Destroy();
231   GLSurfaceAdapter::Destroy();
232 }
233
234 bool PassThroughImageTransportSurface::DeferDraws() {
235   if (is_swap_buffers_pending_) {
236     DCHECK(!did_unschedule_);
237     did_unschedule_ = true;
238     helper_->SetScheduled(false);
239     return true;
240   }
241   return false;
242 }
243
244 void PassThroughImageTransportSurface::SetLatencyInfo(
245     const ui::LatencyInfo& latency_info) {
246   latency_info_ = latency_info;
247 }
248
249 bool PassThroughImageTransportSurface::SwapBuffers() {
250   // GetVsyncValues before SwapBuffers to work around Mali driver bug:
251   // crbug.com/223558.
252   SendVSyncUpdateIfAvailable();
253   bool result = gfx::GLSurfaceAdapter::SwapBuffers();
254   latency_info_.AddLatencyNumber(
255       ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
256
257   if (transport_) {
258     DCHECK(!is_swap_buffers_pending_);
259     is_swap_buffers_pending_ = true;
260
261     // Round trip to the browser UI thread, for throttling, by sending a dummy
262     // SwapBuffers message.
263     GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
264     params.surface_handle = 0;
265     params.latency_info = latency_info_;
266     params.size = surface()->GetSize();
267     helper_->SendAcceleratedSurfaceBuffersSwapped(params);
268   } else {
269     helper_->SendLatencyInfo(latency_info_);
270   }
271   return result;
272 }
273
274 bool PassThroughImageTransportSurface::PostSubBuffer(
275     int x, int y, int width, int height) {
276   SendVSyncUpdateIfAvailable();
277   bool result = gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height);
278   latency_info_.AddLatencyNumber(
279       ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
280
281   if (transport_) {
282     DCHECK(!is_swap_buffers_pending_);
283     is_swap_buffers_pending_ = true;
284
285     // Round trip to the browser UI thread, for throttling, by sending a dummy
286     // PostSubBuffer message.
287     GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params;
288     params.surface_handle = 0;
289     params.latency_info = latency_info_;
290     params.surface_size = surface()->GetSize();
291     params.x = x;
292     params.y = y;
293     params.width = width;
294     params.height = height;
295     helper_->SendAcceleratedSurfacePostSubBuffer(params);
296
297     helper_->SetScheduled(false);
298   } else {
299     helper_->SendLatencyInfo(latency_info_);
300   }
301   return result;
302 }
303
304 bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
305   if (!did_set_swap_interval_) {
306     ImageTransportHelper::SetSwapInterval(context);
307     did_set_swap_interval_ = true;
308   }
309   return true;
310 }
311
312 void PassThroughImageTransportSurface::OnBufferPresented(
313     const AcceleratedSurfaceMsg_BufferPresented_Params& /* params */) {
314   DCHECK(transport_);
315   DCHECK(is_swap_buffers_pending_);
316   is_swap_buffers_pending_ = false;
317   if (did_unschedule_) {
318     did_unschedule_ = false;
319     helper_->SetScheduled(true);
320   }
321 }
322
323 void PassThroughImageTransportSurface::OnResizeViewACK() {
324   DCHECK(transport_);
325   Resize(new_size_);
326
327   TRACE_EVENT_ASYNC_END0("gpu", "OnResize", this);
328   helper_->SetScheduled(true);
329 }
330
331 void PassThroughImageTransportSurface::OnResize(gfx::Size size,
332                                                 float scale_factor) {
333   new_size_ = size;
334
335   if (transport_) {
336     helper_->SendResizeView(size);
337     helper_->SetScheduled(false);
338     TRACE_EVENT_ASYNC_BEGIN2("gpu", "OnResize", this,
339                              "width", size.width(), "height", size.height());
340   } else {
341     Resize(new_size_);
342   }
343 }
344
345 gfx::Size PassThroughImageTransportSurface::GetSize() {
346   return GLSurfaceAdapter::GetSize();
347 }
348
349 PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {}
350
351 void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() {
352   gfx::VSyncProvider* vsync_provider = GetVSyncProvider();
353   if (vsync_provider) {
354     vsync_provider->GetVSyncParameters(
355       base::Bind(&ImageTransportHelper::SendUpdateVSyncParameters,
356                  helper_->AsWeakPtr()));
357   }
358 }
359
360 }  // namespace content