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/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"
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::TEXTURE_TRANSPORT)
34 surface = new TextureImageTransportSurface(manager, stub, handle);
36 surface = CreateNativeSurface(manager, stub, handle);
38 if (!surface.get() || !surface->Initialize())
43 ImageTransportHelper::ImageTransportHelper(ImageTransportSurface* surface,
44 GpuChannelManager* manager,
45 GpuCommandBufferStub* stub,
46 gfx::PluginWindowHandle handle)
49 stub_(stub->AsWeakPtr()),
51 route_id_ = manager_->GenerateRouteID();
52 manager_->AddRoute(route_id_, this);
55 ImageTransportHelper::~ImageTransportHelper() {
57 stub_->SetLatencyInfoCallback(
58 base::Callback<void(const ui::LatencyInfo&)>());
60 manager_->RemoveRoute(route_id_);
63 bool ImageTransportHelper::Initialize() {
64 gpu::gles2::GLES2Decoder* decoder = Decoder();
69 decoder->SetResizeCallback(
70 base::Bind(&ImageTransportHelper::Resize, base::Unretained(this)));
72 stub_->SetLatencyInfoCallback(
73 base::Bind(&ImageTransportHelper::SetLatencyInfo,
74 base::Unretained(this)));
79 void ImageTransportHelper::Destroy() {}
81 bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) {
83 IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper, message)
84 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented,
86 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_ResizeViewACK, OnResizeViewACK);
87 IPC_MESSAGE_UNHANDLED(handled = false)
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));
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));
111 void ImageTransportHelper::SendAcceleratedSurfaceRelease() {
112 GpuHostMsg_AcceleratedSurfaceRelease_Params params;
113 params.surface_id = stub_->surface_id();
114 manager_->Send(new GpuHostMsg_AcceleratedSurfaceRelease(params));
117 void ImageTransportHelper::SendResizeView(const gfx::Size& size) {
118 manager_->Send(new GpuHostMsg_ResizeView(stub_->surface_id(),
123 void ImageTransportHelper::SendUpdateVSyncParameters(
124 base::TimeTicks timebase, base::TimeDelta interval) {
125 manager_->Send(new GpuHostMsg_UpdateVSyncParameters(stub_->surface_id(),
130 void ImageTransportHelper::SendLatencyInfo(
131 const ui::LatencyInfo& latency_info) {
132 manager_->Send(new GpuHostMsg_FrameDrawn(latency_info));
135 void ImageTransportHelper::SetScheduled(bool is_scheduled) {
136 gpu::GpuScheduler* scheduler = Scheduler();
140 scheduler->SetScheduled(is_scheduled);
143 void ImageTransportHelper::DeferToFence(base::Closure task) {
144 gpu::GpuScheduler* scheduler = Scheduler();
147 scheduler->DeferToFence(task);
150 void ImageTransportHelper::SetPreemptByFlag(
151 scoped_refptr<gpu::PreemptionFlag> preemption_flag) {
152 stub_->channel()->SetPreemptByFlag(preemption_flag);
155 bool ImageTransportHelper::MakeCurrent() {
156 gpu::gles2::GLES2Decoder* decoder = Decoder();
159 return decoder->MakeCurrent();
162 void ImageTransportHelper::SetSwapInterval(gfx::GLContext* context) {
163 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
164 context->SetSwapInterval(0);
166 context->SetSwapInterval(1);
169 void ImageTransportHelper::Suspend() {
170 manager_->Send(new GpuHostMsg_AcceleratedSurfaceSuspend(stub_->surface_id()));
173 gpu::GpuScheduler* ImageTransportHelper::Scheduler() {
176 return stub_->scheduler();
179 gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() {
182 return stub_->decoder();
185 void ImageTransportHelper::OnBufferPresented(
186 const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
187 surface_->OnBufferPresented(params);
190 void ImageTransportHelper::OnResizeViewACK() {
191 surface_->OnResizeViewACK();
194 void ImageTransportHelper::Resize(gfx::Size size, float scale_factor) {
195 surface_->OnResize(size, scale_factor);
197 #if defined(OS_ANDROID)
198 manager_->gpu_memory_manager()->ScheduleManage(
199 GpuMemoryManager::kScheduleManageNow);
203 void ImageTransportHelper::SetLatencyInfo(
204 const ui::LatencyInfo& latency_info) {
205 surface_->SetLatencyInfo(latency_info);
208 PassThroughImageTransportSurface::PassThroughImageTransportSurface(
209 GpuChannelManager* manager,
210 GpuCommandBufferStub* stub,
211 gfx::GLSurface* surface,
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,
221 gfx::kNullPluginWindow));
224 bool PassThroughImageTransportSurface::Initialize() {
225 // The surface is assumed to have already been initialized.
226 return helper_->Initialize();
229 void PassThroughImageTransportSurface::Destroy() {
231 GLSurfaceAdapter::Destroy();
234 bool PassThroughImageTransportSurface::DeferDraws() {
235 if (is_swap_buffers_pending_) {
236 DCHECK(!did_unschedule_);
237 did_unschedule_ = true;
238 helper_->SetScheduled(false);
244 void PassThroughImageTransportSurface::SetLatencyInfo(
245 const ui::LatencyInfo& latency_info) {
246 latency_info_ = latency_info;
249 bool PassThroughImageTransportSurface::SwapBuffers() {
250 // GetVsyncValues before SwapBuffers to work around Mali driver bug:
252 SendVSyncUpdateIfAvailable();
253 bool result = gfx::GLSurfaceAdapter::SwapBuffers();
254 latency_info_.AddLatencyNumber(
255 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
258 DCHECK(!is_swap_buffers_pending_);
259 is_swap_buffers_pending_ = true;
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);
269 helper_->SendLatencyInfo(latency_info_);
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);
282 DCHECK(!is_swap_buffers_pending_);
283 is_swap_buffers_pending_ = true;
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();
293 params.width = width;
294 params.height = height;
295 helper_->SendAcceleratedSurfacePostSubBuffer(params);
297 helper_->SetScheduled(false);
299 helper_->SendLatencyInfo(latency_info_);
304 bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
305 if (!did_set_swap_interval_) {
306 ImageTransportHelper::SetSwapInterval(context);
307 did_set_swap_interval_ = true;
312 void PassThroughImageTransportSurface::OnBufferPresented(
313 const AcceleratedSurfaceMsg_BufferPresented_Params& /* params */) {
315 DCHECK(is_swap_buffers_pending_);
316 is_swap_buffers_pending_ = false;
317 if (did_unschedule_) {
318 did_unschedule_ = false;
319 helper_->SetScheduled(true);
323 void PassThroughImageTransportSurface::OnResizeViewACK() {
327 TRACE_EVENT_ASYNC_END0("gpu", "OnResize", this);
328 helper_->SetScheduled(true);
331 void PassThroughImageTransportSurface::OnResize(gfx::Size size,
332 float scale_factor) {
336 helper_->SendResizeView(size);
337 helper_->SetScheduled(false);
338 TRACE_EVENT_ASYNC_BEGIN2("gpu", "OnResize", this,
339 "width", size.width(), "height", size.height());
345 gfx::Size PassThroughImageTransportSurface::GetSize() {
346 return GLSurfaceAdapter::GetSize();
349 PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {}
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()));
360 } // namespace content