Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / common / gpu / image_transport_surface_android.cc
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.
4
5 #include "content/common/gpu/image_transport_surface.h"
6
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"
16
17 namespace content {
18 namespace {
19
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
23 // draw.
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;
28
29 void DidAccessGpu() {
30   g_last_gpu_access_ticks = base::TimeTicks::Now().ToInternalValue();
31 }
32
33 class ImageTransportSurfaceAndroid
34     : public PassThroughImageTransportSurface,
35       public base::SupportsWeakPtr<ImageTransportSurfaceAndroid> {
36  public:
37   ImageTransportSurfaceAndroid(GpuChannelManager* manager,
38                                GpuCommandBufferStub* stub,
39                                gfx::GLSurface* surface,
40                                uint32 parent_client_id);
41
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;
47
48  protected:
49   virtual ~ImageTransportSurfaceAndroid();
50
51  private:
52   void ScheduleWakeUp();
53   void DoWakeUpGpu();
54
55   uint32 parent_client_id_;
56   base::TimeTicks begin_wake_up_time_;
57 };
58
59 class DirectSurfaceAndroid : public PassThroughImageTransportSurface {
60  public:
61   DirectSurfaceAndroid(GpuChannelManager* manager,
62                        GpuCommandBufferStub* stub,
63                        gfx::GLSurface* surface);
64
65   // gfx::GLSurface implementation.
66   virtual bool SwapBuffers() OVERRIDE;
67
68  protected:
69   virtual ~DirectSurfaceAndroid();
70
71  private:
72   DISALLOW_COPY_AND_ASSIGN(DirectSurfaceAndroid);
73 };
74
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) {}
82
83 ImageTransportSurfaceAndroid::~ImageTransportSurfaceAndroid() {}
84
85 bool ImageTransportSurfaceAndroid::Initialize() {
86   if (!surface())
87     return false;
88
89   if (!PassThroughImageTransportSurface::Initialize())
90     return false;
91
92   GpuChannel* parent_channel =
93       GetHelper()->manager()->LookupChannel(parent_client_id_);
94   if (parent_channel) {
95     const CommandLine* command_line = CommandLine::ForCurrentProcess();
96     if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess))
97       GetHelper()->SetPreemptByFlag(parent_channel->GetPreemptionFlag());
98   }
99
100   return true;
101 }
102
103 bool ImageTransportSurfaceAndroid::OnMakeCurrent(gfx::GLContext* context) {
104   DidAccessGpu();
105   return PassThroughImageTransportSurface::OnMakeCurrent(context);
106 }
107
108 bool ImageTransportSurfaceAndroid::SwapBuffers() {
109   NOTREACHED();
110   return false;
111 }
112
113 void ImageTransportSurfaceAndroid::WakeUpGpu() {
114   begin_wake_up_time_ = base::TimeTicks::Now();
115   ScheduleWakeUp();
116 }
117
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))
127     return;
128   if (now - begin_wake_up_time_ >
129       base::TimeDelta::FromMilliseconds(kMaxKeepAliveTimeMs))
130     return;
131
132   DoWakeUpGpu();
133
134   base::MessageLoop::current()->PostDelayedTask(
135       FROM_HERE,
136       base::Bind(&ImageTransportSurfaceAndroid::ScheduleWakeUp, AsWeakPtr()),
137       base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs));
138 }
139
140 void ImageTransportSurfaceAndroid::DoWakeUpGpu() {
141   if (!GetHelper()->stub()->decoder() ||
142       !GetHelper()->stub()->decoder()->MakeCurrent())
143     return;
144   glFinish();
145   DidAccessGpu();
146 }
147
148 DirectSurfaceAndroid::DirectSurfaceAndroid(GpuChannelManager* manager,
149                                            GpuCommandBufferStub* stub,
150                                            gfx::GLSurface* surface)
151     : PassThroughImageTransportSurface(manager, stub, surface) {}
152
153 DirectSurfaceAndroid::~DirectSurfaceAndroid() {}
154
155 bool DirectSurfaceAndroid::SwapBuffers() {
156   DidAccessGpu();
157   return PassThroughImageTransportSurface::SwapBuffers();
158 }
159
160 }  // anonymous namespace
161
162 // static
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,
170                                          stub,
171                                          manager->GetDefaultOffscreenSurface(),
172                                          handle.parent_client_id));
173   }
174
175   DCHECK(GpuSurfaceLookup::GetInstance());
176   DCHECK_EQ(handle.transport_type, gfx::NATIVE_DIRECT);
177   ANativeWindow* window =
178       GpuSurfaceLookup::GetInstance()->AcquireNativeWidget(
179           stub->surface_id());
180   scoped_refptr<gfx::GLSurface> surface =
181       new gfx::NativeViewGLSurfaceEGL(window);
182   bool initialize_success = surface->Initialize();
183   if (window)
184     ANativeWindow_release(window);
185   if (!initialize_success)
186     return scoped_refptr<gfx::GLSurface>();
187
188   return scoped_refptr<gfx::GLSurface>(
189       new DirectSurfaceAndroid(manager, stub, surface.get()));
190 }
191
192 }  // namespace content