GPU workaround to simulate Out of Memory errors with large textures
[chromium-blink-merge.git] / content / common / gpu / image_transport_surface_android.cc
blob6d67df285a7746650139872627e8ae5d95cf94a4
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/null_transport_surface.h"
14 #include "content/public/common/content_switches.h"
15 #include "ui/gl/gl_surface_egl.h"
17 namespace content {
18 namespace {
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;
29 void DidAccessGpu() {
30 g_last_gpu_access_ticks = base::TimeTicks::Now().ToInternalValue();
33 class ImageTransportSurfaceAndroid
34 : public NullTransportSurface,
35 public base::SupportsWeakPtr<ImageTransportSurfaceAndroid> {
36 public:
37 ImageTransportSurfaceAndroid(GpuChannelManager* manager,
38 GpuCommandBufferStub* stub,
39 const gfx::GLSurfaceHandle& handle);
41 // gfx::GLSurface implementation.
42 bool OnMakeCurrent(gfx::GLContext* context) override;
43 void WakeUpGpu() override;
45 protected:
46 ~ImageTransportSurfaceAndroid() override;
48 private:
49 void ScheduleWakeUp();
50 void DoWakeUpGpu();
52 base::TimeTicks begin_wake_up_time_;
55 class DirectSurfaceAndroid : public PassThroughImageTransportSurface {
56 public:
57 DirectSurfaceAndroid(GpuChannelManager* manager,
58 GpuCommandBufferStub* stub,
59 gfx::GLSurface* surface);
61 // gfx::GLSurface implementation.
62 bool SwapBuffers() override;
64 protected:
65 ~DirectSurfaceAndroid() override;
67 private:
68 DISALLOW_COPY_AND_ASSIGN(DirectSurfaceAndroid);
71 ImageTransportSurfaceAndroid::ImageTransportSurfaceAndroid(
72 GpuChannelManager* manager,
73 GpuCommandBufferStub* stub,
74 const gfx::GLSurfaceHandle& handle)
75 : NullTransportSurface(manager, stub, handle) {}
77 ImageTransportSurfaceAndroid::~ImageTransportSurfaceAndroid() {}
79 bool ImageTransportSurfaceAndroid::OnMakeCurrent(gfx::GLContext* context) {
80 DidAccessGpu();
81 return true;
84 void ImageTransportSurfaceAndroid::WakeUpGpu() {
85 begin_wake_up_time_ = base::TimeTicks::Now();
86 ScheduleWakeUp();
89 void ImageTransportSurfaceAndroid::ScheduleWakeUp() {
90 base::TimeTicks now = base::TimeTicks::Now();
91 base::TimeTicks last_access_time =
92 base::TimeTicks::FromInternalValue(g_last_gpu_access_ticks);
93 TRACE_EVENT2("gpu", "ImageTransportSurfaceAndroid::ScheduleWakeUp",
94 "idle_time", (now - last_access_time).InMilliseconds(),
95 "keep_awake_time", (now - begin_wake_up_time_).InMilliseconds());
96 if (now - last_access_time <
97 base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs))
98 return;
99 if (now - begin_wake_up_time_ >
100 base::TimeDelta::FromMilliseconds(kMaxKeepAliveTimeMs))
101 return;
103 DoWakeUpGpu();
105 base::MessageLoop::current()->PostDelayedTask(
106 FROM_HERE,
107 base::Bind(&ImageTransportSurfaceAndroid::ScheduleWakeUp, AsWeakPtr()),
108 base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs));
111 void ImageTransportSurfaceAndroid::DoWakeUpGpu() {
112 if (!GetHelper()->stub()->decoder() ||
113 !GetHelper()->stub()->decoder()->MakeCurrent())
114 return;
115 glFinish();
116 DidAccessGpu();
119 DirectSurfaceAndroid::DirectSurfaceAndroid(GpuChannelManager* manager,
120 GpuCommandBufferStub* stub,
121 gfx::GLSurface* surface)
122 : PassThroughImageTransportSurface(manager, stub, surface) {}
124 DirectSurfaceAndroid::~DirectSurfaceAndroid() {}
126 bool DirectSurfaceAndroid::SwapBuffers() {
127 DidAccessGpu();
128 return PassThroughImageTransportSurface::SwapBuffers();
131 } // anonymous namespace
133 // static
134 scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateTransportSurface(
135 GpuChannelManager* manager,
136 GpuCommandBufferStub* stub,
137 const gfx::GLSurfaceHandle& handle) {
138 DCHECK_EQ(gfx::NULL_TRANSPORT, handle.transport_type);
139 return scoped_refptr<gfx::GLSurface>(
140 new ImageTransportSurfaceAndroid(manager, stub, handle));
143 // static
144 scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
145 GpuChannelManager* manager,
146 GpuCommandBufferStub* stub,
147 const gfx::GLSurfaceHandle& handle) {
148 DCHECK(GpuSurfaceLookup::GetInstance());
149 DCHECK_EQ(handle.transport_type, gfx::NATIVE_DIRECT);
150 ANativeWindow* window =
151 GpuSurfaceLookup::GetInstance()->AcquireNativeWidget(
152 stub->surface_id());
153 scoped_refptr<gfx::GLSurface> surface =
154 new gfx::NativeViewGLSurfaceEGL(window);
155 bool initialize_success = surface->Initialize();
156 if (window)
157 ANativeWindow_release(window);
158 if (!initialize_success)
159 return scoped_refptr<gfx::GLSurface>();
161 return scoped_refptr<gfx::GLSurface>(
162 new DirectSurfaceAndroid(manager, stub, surface.get()));
165 } // namespace content