• 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 #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