Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / common / gpu / image_transport_surface.cc
blobf1908a75cbd216148055298c004045e6d896567e
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"
7 #include "base/bind.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_context.h"
19 #include "ui/gl/gl_implementation.h"
20 #include "ui/gl/gl_switches.h"
22 namespace content {
24 ImageTransportSurface::ImageTransportSurface() {}
26 ImageTransportSurface::~ImageTransportSurface() {}
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::NULL_TRANSPORT) {
34 #if defined(OS_ANDROID)
35 surface = CreateTransportSurface(manager, stub, handle);
36 #else
37 surface = new NullTransportSurface(manager, stub, handle);
38 #endif
39 } else {
40 surface = CreateNativeSurface(manager, stub, handle);
43 if (!surface.get() || !surface->Initialize())
44 return NULL;
45 return surface;
48 ImageTransportHelper::ImageTransportHelper(ImageTransportSurface* surface,
49 GpuChannelManager* manager,
50 GpuCommandBufferStub* stub,
51 gfx::PluginWindowHandle handle)
52 : surface_(surface),
53 manager_(manager),
54 stub_(stub->AsWeakPtr()),
55 handle_(handle) {
56 route_id_ = manager_->GenerateRouteID();
57 manager_->AddRoute(route_id_, this);
60 ImageTransportHelper::~ImageTransportHelper() {
61 if (stub_.get()) {
62 stub_->SetLatencyInfoCallback(
63 base::Callback<void(const std::vector<ui::LatencyInfo>&)>());
65 manager_->RemoveRoute(route_id_);
68 bool ImageTransportHelper::Initialize() {
69 gpu::gles2::GLES2Decoder* decoder = Decoder();
71 if (!decoder)
72 return false;
74 decoder->SetResizeCallback(
75 base::Bind(&ImageTransportHelper::Resize, base::Unretained(this)));
77 stub_->SetLatencyInfoCallback(
78 base::Bind(&ImageTransportHelper::SetLatencyInfo,
79 base::Unretained(this)));
81 manager_->Send(new GpuHostMsg_AcceleratedSurfaceInitialized(
82 stub_->surface_id(), route_id_));
84 return true;
87 bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) {
88 bool handled = true;
89 IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper, message)
90 #if defined(OS_MACOSX)
91 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented,
92 OnBufferPresented)
93 #endif
94 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_WakeUpGpu, OnWakeUpGpu);
95 IPC_MESSAGE_UNHANDLED(handled = false)
96 IPC_END_MESSAGE_MAP()
97 return handled;
100 #if defined(OS_MACOSX)
101 void ImageTransportHelper::SendAcceleratedSurfaceBuffersSwapped(
102 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params) {
103 // TRACE_EVENT for gpu tests:
104 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
105 TRACE_EVENT_SCOPE_THREAD,
106 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
107 "width", params.size.width());
108 params.surface_id = stub_->surface_id();
109 params.route_id = route_id_;
110 manager_->Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
112 #endif
114 void ImageTransportHelper::SetPreemptByFlag(
115 scoped_refptr<gpu::PreemptionFlag> preemption_flag) {
116 stub_->channel()->SetPreemptByFlag(preemption_flag);
119 bool ImageTransportHelper::MakeCurrent() {
120 gpu::gles2::GLES2Decoder* decoder = Decoder();
121 if (!decoder)
122 return false;
123 return decoder->MakeCurrent();
126 void ImageTransportHelper::SetSwapInterval(gfx::GLContext* context) {
127 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
128 switches::kDisableGpuVsync))
129 context->ForceSwapIntervalZero(true);
130 else
131 context->SetSwapInterval(1);
134 gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() {
135 if (!stub_.get())
136 return NULL;
137 return stub_->decoder();
140 #if defined(OS_MACOSX)
141 void ImageTransportHelper::OnBufferPresented(
142 const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
143 surface_->OnBufferPresented(params);
145 #endif
147 void ImageTransportHelper::OnWakeUpGpu() {
148 surface_->WakeUpGpu();
151 void ImageTransportHelper::Resize(gfx::Size size, float scale_factor) {
152 surface_->OnResize(size, scale_factor);
154 #if defined(OS_ANDROID)
155 manager_->gpu_memory_manager()->ScheduleManage(
156 GpuMemoryManager::kScheduleManageNow);
157 #endif
160 void ImageTransportHelper::SetLatencyInfo(
161 const std::vector<ui::LatencyInfo>& latency_info) {
162 surface_->SetLatencyInfo(latency_info);
165 PassThroughImageTransportSurface::PassThroughImageTransportSurface(
166 GpuChannelManager* manager,
167 GpuCommandBufferStub* stub,
168 gfx::GLSurface* surface)
169 : GLSurfaceAdapter(surface),
170 did_set_swap_interval_(false),
171 weak_ptr_factory_(this) {
172 helper_.reset(new ImageTransportHelper(this,
173 manager,
174 stub,
175 gfx::kNullPluginWindow));
178 bool PassThroughImageTransportSurface::Initialize() {
179 // The surface is assumed to have already been initialized.
180 return helper_->Initialize();
183 void PassThroughImageTransportSurface::Destroy() {
184 GLSurfaceAdapter::Destroy();
187 void PassThroughImageTransportSurface::SetLatencyInfo(
188 const std::vector<ui::LatencyInfo>& latency_info) {
189 for (size_t i = 0; i < latency_info.size(); i++)
190 latency_info_.push_back(latency_info[i]);
193 gfx::SwapResult PassThroughImageTransportSurface::SwapBuffers() {
194 // GetVsyncValues before SwapBuffers to work around Mali driver bug:
195 // crbug.com/223558.
196 SendVSyncUpdateIfAvailable();
198 base::TimeTicks swap_time = base::TimeTicks::Now();
199 for (auto& latency : latency_info_) {
200 latency.AddLatencyNumberWithTimestamp(
201 ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1);
204 // We use WeakPtr here to avoid manual management of life time of an instance
205 // of this class. Callback will not be called once the instance of this class
206 // is destroyed. However, this also means that the callback can be run on
207 // the calling thread only.
208 std::vector<ui::LatencyInfo>* latency_info_ptr =
209 new std::vector<ui::LatencyInfo>();
210 latency_info_ptr->swap(latency_info_);
211 return gfx::GLSurfaceAdapter::SwapBuffersAsync(base::Bind(
212 &PassThroughImageTransportSurface::SwapBuffersCallBack,
213 weak_ptr_factory_.GetWeakPtr(), base::Owned(latency_info_ptr)))
214 ? gfx::SwapResult::SWAP_ACK
215 : gfx::SwapResult::SWAP_FAILED;
218 gfx::SwapResult PassThroughImageTransportSurface::PostSubBuffer(int x,
219 int y,
220 int width,
221 int height) {
222 SendVSyncUpdateIfAvailable();
224 base::TimeTicks swap_time = base::TimeTicks::Now();
225 for (auto& latency : latency_info_) {
226 latency.AddLatencyNumberWithTimestamp(
227 ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1);
230 // We use WeakPtr here to avoid manual management of life time of an instance
231 // of this class. Callback will not be called once the instance of this class
232 // is destroyed. However, this also means that the callback can be run on
233 // the calling thread only.
234 std::vector<ui::LatencyInfo>* latency_info_ptr =
235 new std::vector<ui::LatencyInfo>();
236 latency_info_ptr->swap(latency_info_);
237 return gfx::GLSurfaceAdapter::PostSubBufferAsync(
238 x, y, width, height,
239 base::Bind(&PassThroughImageTransportSurface::SwapBuffersCallBack,
240 weak_ptr_factory_.GetWeakPtr(),
241 base::Owned(latency_info_ptr)))
242 ? gfx::SwapResult::SWAP_ACK
243 : gfx::SwapResult::SWAP_FAILED;
246 void PassThroughImageTransportSurface::SwapBuffersCallBack(
247 std::vector<ui::LatencyInfo>* latency_info_ptr,
248 gfx::SwapResult result) {
249 base::TimeTicks swap_ack_time = base::TimeTicks::Now();
250 for (auto& latency : *latency_info_ptr) {
251 latency.AddLatencyNumberWithTimestamp(
252 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0,
253 swap_ack_time, 1);
256 helper_->stub()->SendSwapBuffersCompleted(*latency_info_ptr, result);
259 bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
260 if (!did_set_swap_interval_) {
261 ImageTransportHelper::SetSwapInterval(context);
262 did_set_swap_interval_ = true;
264 return true;
267 #if defined(OS_MACOSX)
268 void PassThroughImageTransportSurface::OnBufferPresented(
269 const AcceleratedSurfaceMsg_BufferPresented_Params& /* params */) {
270 NOTREACHED();
272 #endif
274 void PassThroughImageTransportSurface::OnResize(gfx::Size size,
275 float scale_factor) {
276 Resize(size);
279 gfx::Size PassThroughImageTransportSurface::GetSize() {
280 return GLSurfaceAdapter::GetSize();
283 void PassThroughImageTransportSurface::WakeUpGpu() {
284 NOTREACHED();
287 PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {}
289 void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() {
290 gfx::VSyncProvider* vsync_provider = GetVSyncProvider();
291 if (vsync_provider) {
292 vsync_provider->GetVSyncParameters(
293 base::Bind(&GpuCommandBufferStub::SendUpdateVSyncParameters,
294 helper_->stub()->AsWeakPtr()));
298 } // namespace content