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/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/null_transport_surface.h"
16 #include "content/common/gpu/sync_point_manager.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"
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);
37 surface = new NullTransportSurface(manager, stub, handle);
40 surface = CreateNativeSurface(manager, stub, handle);
43 if (!surface.get() || !surface->Initialize())
48 ImageTransportHelper::ImageTransportHelper(ImageTransportSurface* surface,
49 GpuChannelManager* manager,
50 GpuCommandBufferStub* stub,
51 gfx::PluginWindowHandle handle)
54 stub_(stub->AsWeakPtr()),
56 route_id_ = manager_->GenerateRouteID();
57 manager_->AddRoute(route_id_, this);
60 ImageTransportHelper::~ImageTransportHelper() {
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();
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_));
87 bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) {
89 IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper, message)
90 #if defined(OS_MACOSX)
91 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented,
94 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_WakeUpGpu, OnWakeUpGpu);
95 IPC_MESSAGE_UNHANDLED(handled = false)
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));
112 void ImageTransportHelper::SendUpdateVSyncParameters(
113 base::TimeTicks timebase, base::TimeDelta interval) {
114 manager_->Send(new GpuHostMsg_UpdateVSyncParameters(stub_->surface_id(),
119 void ImageTransportHelper::SwapBuffersCompleted(
120 const std::vector<ui::LatencyInfo>& latency_info) {
121 stub_->SwapBuffersCompleted(latency_info);
124 void ImageTransportHelper::SetScheduled(bool is_scheduled) {
125 gpu::GpuScheduler* scheduler = Scheduler();
129 scheduler->SetScheduled(is_scheduled);
132 void ImageTransportHelper::DeferToFence(base::Closure task) {
133 gpu::GpuScheduler* scheduler = Scheduler();
136 scheduler->DeferToFence(task);
139 void ImageTransportHelper::SetPreemptByFlag(
140 scoped_refptr<gpu::PreemptionFlag> preemption_flag) {
141 stub_->channel()->SetPreemptByFlag(preemption_flag);
144 bool ImageTransportHelper::MakeCurrent() {
145 gpu::gles2::GLES2Decoder* decoder = Decoder();
148 return decoder->MakeCurrent();
151 void ImageTransportHelper::SetSwapInterval(gfx::GLContext* context) {
152 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
153 context->SetSwapInterval(0);
155 context->SetSwapInterval(1);
158 gpu::GpuScheduler* ImageTransportHelper::Scheduler() {
161 return stub_->scheduler();
164 gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() {
167 return stub_->decoder();
170 #if defined(OS_MACOSX)
171 void ImageTransportHelper::OnBufferPresented(
172 const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
173 surface_->OnBufferPresented(params);
177 void ImageTransportHelper::OnWakeUpGpu() {
178 surface_->WakeUpGpu();
181 void ImageTransportHelper::Resize(gfx::Size size, float scale_factor) {
182 surface_->OnResize(size, scale_factor);
184 #if defined(OS_ANDROID)
185 manager_->gpu_memory_manager()->ScheduleManage(
186 GpuMemoryManager::kScheduleManageNow);
190 void ImageTransportHelper::SetLatencyInfo(
191 const std::vector<ui::LatencyInfo>& latency_info) {
192 surface_->SetLatencyInfo(latency_info);
195 PassThroughImageTransportSurface::PassThroughImageTransportSurface(
196 GpuChannelManager* manager,
197 GpuCommandBufferStub* stub,
198 gfx::GLSurface* surface)
199 : GLSurfaceAdapter(surface),
200 did_set_swap_interval_(false) {
201 helper_.reset(new ImageTransportHelper(this,
204 gfx::kNullPluginWindow));
207 bool PassThroughImageTransportSurface::Initialize() {
208 // The surface is assumed to have already been initialized.
209 return helper_->Initialize();
212 void PassThroughImageTransportSurface::Destroy() {
213 GLSurfaceAdapter::Destroy();
216 void PassThroughImageTransportSurface::SetLatencyInfo(
217 const std::vector<ui::LatencyInfo>& latency_info) {
218 for (size_t i = 0; i < latency_info.size(); i++)
219 latency_info_.push_back(latency_info[i]);
222 bool PassThroughImageTransportSurface::SwapBuffers() {
223 // GetVsyncValues before SwapBuffers to work around Mali driver bug:
225 SendVSyncUpdateIfAvailable();
226 for (size_t i = 0; i < latency_info_.size(); ++i) {
227 latency_info_[i].AddLatencyNumber(
228 ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0);
230 bool result = gfx::GLSurfaceAdapter::SwapBuffers();
231 for (size_t i = 0; i < latency_info_.size(); i++) {
232 latency_info_[i].AddLatencyNumber(
233 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
236 helper_->SwapBuffersCompleted(latency_info_);
237 latency_info_.clear();
241 bool PassThroughImageTransportSurface::PostSubBuffer(
242 int x, int y, int width, int height) {
243 SendVSyncUpdateIfAvailable();
244 bool result = gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height);
245 for (size_t i = 0; i < latency_info_.size(); i++) {
246 latency_info_[i].AddLatencyNumber(
247 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
250 helper_->SwapBuffersCompleted(latency_info_);
251 latency_info_.clear();
255 bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
256 if (!did_set_swap_interval_) {
257 ImageTransportHelper::SetSwapInterval(context);
258 did_set_swap_interval_ = true;
263 #if defined(OS_MACOSX)
264 void PassThroughImageTransportSurface::OnBufferPresented(
265 const AcceleratedSurfaceMsg_BufferPresented_Params& /* params */) {
270 void PassThroughImageTransportSurface::OnResize(gfx::Size size,
271 float scale_factor) {
275 gfx::Size PassThroughImageTransportSurface::GetSize() {
276 return GLSurfaceAdapter::GetSize();
279 void PassThroughImageTransportSurface::WakeUpGpu() {
283 PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {}
285 void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() {
286 gfx::VSyncProvider* vsync_provider = GetVSyncProvider();
287 if (vsync_provider) {
288 vsync_provider->GetVSyncParameters(
289 base::Bind(&ImageTransportHelper::SendUpdateVSyncParameters,
290 helper_->AsWeakPtr()));
294 } // namespace content