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/command_line.h"
8 #include "base/logging.h"
9 #include "content/common/gpu/gpu_channel.h"
10 #include "content/common/gpu/gpu_channel_manager.h"
11 #include "content/common/gpu/gpu_command_buffer_stub.h"
12 #include "content/common/gpu/gpu_surface_lookup.h"
13 #include "content/common/gpu/image_transport_surface.h"
14 #include "content/public/common/content_switches.h"
15 #include "ui/gl/gl_surface_egl.h"
20 // Amount of time the GPU is allowed to idle before it powers down.
21 const int kMaxGpuIdleTimeMs = 40;
22 // Maximum amount of time we keep pinging the GPU waiting for the client to
24 const int kMaxKeepAliveTimeMs = 200;
25 // Last time we know the GPU was powered on. Global for tracking across all
26 // transport surfaces.
27 int64 g_last_gpu_access_ticks;
30 g_last_gpu_access_ticks = base::TimeTicks::Now().ToInternalValue();
33 class ImageTransportSurfaceAndroid
34 : public PassThroughImageTransportSurface,
35 public base::SupportsWeakPtr<ImageTransportSurfaceAndroid> {
37 ImageTransportSurfaceAndroid(GpuChannelManager* manager,
38 GpuCommandBufferStub* stub,
39 gfx::GLSurface* surface,
40 uint32 parent_client_id);
42 // gfx::GLSurface implementation.
43 virtual bool Initialize() OVERRIDE;
44 virtual bool SwapBuffers() OVERRIDE;
45 virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE;
46 virtual void WakeUpGpu() OVERRIDE;
49 virtual ~ImageTransportSurfaceAndroid();
52 void ScheduleWakeUp();
55 uint32 parent_client_id_;
56 base::TimeTicks begin_wake_up_time_;
59 class DirectSurfaceAndroid : public PassThroughImageTransportSurface {
61 DirectSurfaceAndroid(GpuChannelManager* manager,
62 GpuCommandBufferStub* stub,
63 gfx::GLSurface* surface);
65 // gfx::GLSurface implementation.
66 virtual bool SwapBuffers() OVERRIDE;
69 virtual ~DirectSurfaceAndroid();
72 DISALLOW_COPY_AND_ASSIGN(DirectSurfaceAndroid);
75 ImageTransportSurfaceAndroid::ImageTransportSurfaceAndroid(
76 GpuChannelManager* manager,
77 GpuCommandBufferStub* stub,
78 gfx::GLSurface* surface,
79 uint32 parent_client_id)
80 : PassThroughImageTransportSurface(manager, stub, surface),
81 parent_client_id_(parent_client_id) {}
83 ImageTransportSurfaceAndroid::~ImageTransportSurfaceAndroid() {}
85 bool ImageTransportSurfaceAndroid::Initialize() {
89 if (!PassThroughImageTransportSurface::Initialize())
92 GpuChannel* parent_channel =
93 GetHelper()->manager()->LookupChannel(parent_client_id_);
95 const CommandLine* command_line = CommandLine::ForCurrentProcess();
96 if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess))
97 GetHelper()->SetPreemptByFlag(parent_channel->GetPreemptionFlag());
103 bool ImageTransportSurfaceAndroid::OnMakeCurrent(gfx::GLContext* context) {
105 return PassThroughImageTransportSurface::OnMakeCurrent(context);
108 bool ImageTransportSurfaceAndroid::SwapBuffers() {
113 void ImageTransportSurfaceAndroid::WakeUpGpu() {
114 begin_wake_up_time_ = base::TimeTicks::Now();
118 void ImageTransportSurfaceAndroid::ScheduleWakeUp() {
119 base::TimeTicks now = base::TimeTicks::Now();
120 base::TimeTicks last_access_time =
121 base::TimeTicks::FromInternalValue(g_last_gpu_access_ticks);
122 TRACE_EVENT2("gpu", "ImageTransportSurfaceAndroid::ScheduleWakeUp",
123 "idle_time", (now - last_access_time).InMilliseconds(),
124 "keep_awake_time", (now - begin_wake_up_time_).InMilliseconds());
125 if (now - last_access_time <
126 base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs))
128 if (now - begin_wake_up_time_ >
129 base::TimeDelta::FromMilliseconds(kMaxKeepAliveTimeMs))
134 base::MessageLoop::current()->PostDelayedTask(
136 base::Bind(&ImageTransportSurfaceAndroid::ScheduleWakeUp, AsWeakPtr()),
137 base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs));
140 void ImageTransportSurfaceAndroid::DoWakeUpGpu() {
141 if (!GetHelper()->stub()->decoder() ||
142 !GetHelper()->stub()->decoder()->MakeCurrent())
148 DirectSurfaceAndroid::DirectSurfaceAndroid(GpuChannelManager* manager,
149 GpuCommandBufferStub* stub,
150 gfx::GLSurface* surface)
151 : PassThroughImageTransportSurface(manager, stub, surface) {}
153 DirectSurfaceAndroid::~DirectSurfaceAndroid() {}
155 bool DirectSurfaceAndroid::SwapBuffers() {
157 return PassThroughImageTransportSurface::SwapBuffers();
160 } // anonymous namespace
163 scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
164 GpuChannelManager* manager,
165 GpuCommandBufferStub* stub,
166 const gfx::GLSurfaceHandle& handle) {
167 if (handle.transport_type == gfx::NATIVE_TRANSPORT) {
168 return scoped_refptr<gfx::GLSurface>(
169 new ImageTransportSurfaceAndroid(manager,
171 manager->GetDefaultOffscreenSurface(),
172 handle.parent_client_id));
175 DCHECK(GpuSurfaceLookup::GetInstance());
176 DCHECK_EQ(handle.transport_type, gfx::NATIVE_DIRECT);
177 ANativeWindow* window =
178 GpuSurfaceLookup::GetInstance()->AcquireNativeWidget(
180 scoped_refptr<gfx::GLSurface> surface =
181 new gfx::NativeViewGLSurfaceEGL(window);
182 bool initialize_success = surface->Initialize();
184 ANativeWindow_release(window);
185 if (!initialize_success)
186 return scoped_refptr<gfx::GLSurface>();
188 return scoped_refptr<gfx::GLSurface>(
189 new DirectSurfaceAndroid(manager, stub, surface.get()));
192 } // namespace content