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.
5 #include "content/common/gpu/image_transport_surface.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/trace_event/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/null_transport_surface.h"
16 #include "gpu/command_buffer/service/sync_point_manager.h"
17 #include "ui/gfx/vsync_provider.h"
18 #include "ui/gl/gl_implementation.h"
19 #include "ui/gl/gl_switches.h"
23 ImageTransportSurface::ImageTransportSurface() {}
25 ImageTransportSurface::~ImageTransportSurface() {}
27 scoped_refptr
<gfx::GLSurface
> ImageTransportSurface::CreateSurface(
28 GpuChannelManager
* manager
,
29 GpuCommandBufferStub
* stub
,
30 const gfx::GLSurfaceHandle
& handle
) {
31 scoped_refptr
<gfx::GLSurface
> surface
;
32 if (handle
.transport_type
== gfx::NULL_TRANSPORT
) {
33 #if defined(OS_ANDROID)
34 surface
= CreateTransportSurface(manager
, stub
, handle
);
36 surface
= new NullTransportSurface(manager
, stub
, handle
);
39 surface
= CreateNativeSurface(manager
, stub
, handle
);
42 if (!surface
.get() || !surface
->Initialize())
47 ImageTransportHelper::ImageTransportHelper(ImageTransportSurface
* surface
,
48 GpuChannelManager
* manager
,
49 GpuCommandBufferStub
* stub
,
50 gfx::PluginWindowHandle handle
)
53 stub_(stub
->AsWeakPtr()),
55 route_id_
= manager_
->GenerateRouteID();
56 manager_
->AddRoute(route_id_
, this);
59 ImageTransportHelper::~ImageTransportHelper() {
61 stub_
->SetLatencyInfoCallback(
62 base::Callback
<void(const std::vector
<ui::LatencyInfo
>&)>());
64 manager_
->RemoveRoute(route_id_
);
67 bool ImageTransportHelper::Initialize() {
68 gpu::gles2::GLES2Decoder
* decoder
= Decoder();
73 decoder
->SetResizeCallback(
74 base::Bind(&ImageTransportHelper::Resize
, base::Unretained(this)));
76 stub_
->SetLatencyInfoCallback(
77 base::Bind(&ImageTransportHelper::SetLatencyInfo
,
78 base::Unretained(this)));
80 manager_
->Send(new GpuHostMsg_AcceleratedSurfaceInitialized(
81 stub_
->surface_id(), route_id_
));
86 bool ImageTransportHelper::OnMessageReceived(const IPC::Message
& message
) {
88 IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper
, message
)
89 #if defined(OS_MACOSX)
90 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented
,
93 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_WakeUpGpu
, OnWakeUpGpu
);
94 IPC_MESSAGE_UNHANDLED(handled
= false)
99 #if defined(OS_MACOSX)
100 void ImageTransportHelper::SendAcceleratedSurfaceBuffersSwapped(
101 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params
) {
102 // TRACE_EVENT for gpu tests:
103 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
104 TRACE_EVENT_SCOPE_THREAD
,
105 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
106 "width", params
.size
.width());
107 params
.surface_id
= stub_
->surface_id();
108 params
.route_id
= route_id_
;
109 manager_
->Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params
));
113 void ImageTransportHelper::SetPreemptByFlag(
114 scoped_refptr
<gpu::PreemptionFlag
> preemption_flag
) {
115 stub_
->channel()->SetPreemptByFlag(preemption_flag
);
118 bool ImageTransportHelper::MakeCurrent() {
119 gpu::gles2::GLES2Decoder
* decoder
= Decoder();
122 return decoder
->MakeCurrent();
125 void ImageTransportHelper::SetSwapInterval(gfx::GLContext
* context
) {
126 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
127 switches::kDisableGpuVsync
))
128 context
->ForceSwapIntervalZero(true);
130 context
->SetSwapInterval(1);
133 gpu::gles2::GLES2Decoder
* ImageTransportHelper::Decoder() {
136 return stub_
->decoder();
139 #if defined(OS_MACOSX)
140 void ImageTransportHelper::OnBufferPresented(
141 const AcceleratedSurfaceMsg_BufferPresented_Params
& params
) {
142 surface_
->OnBufferPresented(params
);
146 void ImageTransportHelper::OnWakeUpGpu() {
147 surface_
->WakeUpGpu();
150 void ImageTransportHelper::Resize(gfx::Size size
, float scale_factor
) {
151 surface_
->OnResize(size
, scale_factor
);
153 #if defined(OS_ANDROID)
154 manager_
->gpu_memory_manager()->ScheduleManage(
155 GpuMemoryManager::kScheduleManageNow
);
159 void ImageTransportHelper::SetLatencyInfo(
160 const std::vector
<ui::LatencyInfo
>& latency_info
) {
161 surface_
->SetLatencyInfo(latency_info
);
164 PassThroughImageTransportSurface::PassThroughImageTransportSurface(
165 GpuChannelManager
* manager
,
166 GpuCommandBufferStub
* stub
,
167 gfx::GLSurface
* surface
)
168 : GLSurfaceAdapter(surface
),
169 did_set_swap_interval_(false),
170 weak_ptr_factory_(this) {
171 helper_
.reset(new ImageTransportHelper(this,
174 gfx::kNullPluginWindow
));
177 bool PassThroughImageTransportSurface::Initialize() {
178 // The surface is assumed to have already been initialized.
179 return helper_
->Initialize();
182 void PassThroughImageTransportSurface::Destroy() {
183 GLSurfaceAdapter::Destroy();
186 void PassThroughImageTransportSurface::SetLatencyInfo(
187 const std::vector
<ui::LatencyInfo
>& latency_info
) {
188 for (size_t i
= 0; i
< latency_info
.size(); i
++)
189 latency_info_
.push_back(latency_info
[i
]);
192 gfx::SwapResult
PassThroughImageTransportSurface::SwapBuffers() {
193 // GetVsyncValues before SwapBuffers to work around Mali driver bug:
195 SendVSyncUpdateIfAvailable();
197 base::TimeTicks swap_time
= base::TimeTicks::Now();
198 for (auto& latency
: latency_info_
) {
199 latency
.AddLatencyNumberWithTimestamp(
200 ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT
, 0, 0, swap_time
, 1);
203 // We use WeakPtr here to avoid manual management of life time of an instance
204 // of this class. Callback will not be called once the instance of this class
205 // is destroyed. However, this also means that the callback can be run on
206 // the calling thread only.
207 std::vector
<ui::LatencyInfo
>* latency_info_ptr
=
208 new std::vector
<ui::LatencyInfo
>();
209 latency_info_ptr
->swap(latency_info_
);
210 return gfx::GLSurfaceAdapter::SwapBuffersAsync(base::Bind(
211 &PassThroughImageTransportSurface::SwapBuffersCallBack
,
212 weak_ptr_factory_
.GetWeakPtr(), base::Owned(latency_info_ptr
)))
213 ? gfx::SwapResult::SWAP_ACK
214 : gfx::SwapResult::SWAP_FAILED
;
217 gfx::SwapResult
PassThroughImageTransportSurface::PostSubBuffer(int x
,
221 SendVSyncUpdateIfAvailable();
223 base::TimeTicks swap_time
= base::TimeTicks::Now();
224 for (auto& latency
: latency_info_
) {
225 latency
.AddLatencyNumberWithTimestamp(
226 ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT
, 0, 0, swap_time
, 1);
229 // We use WeakPtr here to avoid manual management of life time of an instance
230 // of this class. Callback will not be called once the instance of this class
231 // is destroyed. However, this also means that the callback can be run on
232 // the calling thread only.
233 std::vector
<ui::LatencyInfo
>* latency_info_ptr
=
234 new std::vector
<ui::LatencyInfo
>();
235 latency_info_ptr
->swap(latency_info_
);
236 return gfx::GLSurfaceAdapter::PostSubBufferAsync(
238 base::Bind(&PassThroughImageTransportSurface::SwapBuffersCallBack
,
239 weak_ptr_factory_
.GetWeakPtr(),
240 base::Owned(latency_info_ptr
)))
241 ? gfx::SwapResult::SWAP_ACK
242 : gfx::SwapResult::SWAP_FAILED
;
245 void PassThroughImageTransportSurface::SwapBuffersCallBack(
246 std::vector
<ui::LatencyInfo
>* latency_info_ptr
,
247 gfx::SwapResult result
) {
248 base::TimeTicks swap_ack_time
= base::TimeTicks::Now();
249 for (auto& latency
: *latency_info_ptr
) {
250 latency
.AddLatencyNumberWithTimestamp(
251 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT
, 0, 0,
255 helper_
->stub()->SendSwapBuffersCompleted(*latency_info_ptr
, result
);
258 bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext
* context
) {
259 if (!did_set_swap_interval_
) {
260 ImageTransportHelper::SetSwapInterval(context
);
261 did_set_swap_interval_
= true;
266 #if defined(OS_MACOSX)
267 void PassThroughImageTransportSurface::OnBufferPresented(
268 const AcceleratedSurfaceMsg_BufferPresented_Params
& /* params */) {
273 void PassThroughImageTransportSurface::OnResize(gfx::Size size
,
274 float scale_factor
) {
278 gfx::Size
PassThroughImageTransportSurface::GetSize() {
279 return GLSurfaceAdapter::GetSize();
282 void PassThroughImageTransportSurface::WakeUpGpu() {
286 PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {}
288 void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() {
289 gfx::VSyncProvider
* vsync_provider
= GetVSyncProvider();
290 if (vsync_provider
) {
291 vsync_provider
->GetVSyncParameters(
292 base::Bind(&GpuCommandBufferStub::SendUpdateVSyncParameters
,
293 helper_
->stub()->AsWeakPtr()));
297 } // namespace content