15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/image_transport_surface.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/command_line.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/common/gpu/gpu_channel.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/common/gpu/gpu_channel_manager.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/common/gpu/gpu_command_buffer_stub.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_surface_lookup.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/common/gpu/image_transport_surface.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/public/common/content_switches.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_surface_egl.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace {
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Amount of time the GPU is allowed to idle before it powers down.
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int kMaxGpuIdleTimeMs = 40;
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Maximum amount of time we keep pinging the GPU waiting for the client to
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// draw.
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int kMaxKeepAliveTimeMs = 200;
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Last time we know the GPU was powered on. Global for tracking across all
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// transport surfaces.
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)int64 g_last_gpu_access_ticks;
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DidAccessGpu() {
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  g_last_gpu_access_ticks = base::TimeTicks::Now().ToInternalValue();
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class ImageTransportSurfaceAndroid
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : public PassThroughImageTransportSurface,
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      public base::SupportsWeakPtr<ImageTransportSurfaceAndroid> {
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ImageTransportSurfaceAndroid(GpuChannelManager* manager,
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                               GpuCommandBufferStub* stub,
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                               gfx::GLSurface* surface,
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                               uint32 parent_client_id);
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // gfx::GLSurface implementation.
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual bool Initialize() OVERRIDE;
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual bool SwapBuffers() OVERRIDE;
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE;
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void WakeUpGpu() OVERRIDE;
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) protected:
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~ImageTransportSurfaceAndroid();
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void ScheduleWakeUp();
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void DoWakeUpGpu();
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  uint32 parent_client_id_;
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::TimeTicks begin_wake_up_time_;
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class DirectSurfaceAndroid : public PassThroughImageTransportSurface {
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DirectSurfaceAndroid(GpuChannelManager* manager,
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                       GpuCommandBufferStub* stub,
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                       gfx::GLSurface* surface);
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // gfx::GLSurface implementation.
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual bool SwapBuffers() OVERRIDE;
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) protected:
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~DirectSurfaceAndroid();
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DirectSurfaceAndroid);
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ImageTransportSurfaceAndroid::ImageTransportSurfaceAndroid(
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    GpuChannelManager* manager,
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    GpuCommandBufferStub* stub,
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::GLSurface* surface,
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    uint32 parent_client_id)
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : PassThroughImageTransportSurface(manager, stub, surface),
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      parent_client_id_(parent_client_id) {}
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ImageTransportSurfaceAndroid::~ImageTransportSurfaceAndroid() {}
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool ImageTransportSurfaceAndroid::Initialize() {
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!surface())
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!PassThroughImageTransportSurface::Initialize())
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GpuChannel* parent_channel =
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      GetHelper()->manager()->LookupChannel(parent_client_id_);
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (parent_channel) {
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const base::CommandLine* command_line =
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        base::CommandLine::ForCurrentProcess();
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess))
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      GetHelper()->SetPreemptByFlag(parent_channel->GetPreemptionFlag());
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return true;
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool ImageTransportSurfaceAndroid::OnMakeCurrent(gfx::GLContext* context) {
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DidAccessGpu();
10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return true;
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool ImageTransportSurfaceAndroid::SwapBuffers() {
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NOTREACHED();
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return false;
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ImageTransportSurfaceAndroid::WakeUpGpu() {
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  begin_wake_up_time_ = base::TimeTicks::Now();
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ScheduleWakeUp();
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ImageTransportSurfaceAndroid::ScheduleWakeUp() {
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::TimeTicks now = base::TimeTicks::Now();
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::TimeTicks last_access_time =
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::TimeTicks::FromInternalValue(g_last_gpu_access_ticks);
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TRACE_EVENT2("gpu", "ImageTransportSurfaceAndroid::ScheduleWakeUp",
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               "idle_time", (now - last_access_time).InMilliseconds(),
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               "keep_awake_time", (now - begin_wake_up_time_).InMilliseconds());
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (now - last_access_time <
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs))
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (now - begin_wake_up_time_ >
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(kMaxKeepAliveTimeMs))
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DoWakeUpGpu();
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FROM_HERE,
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(&ImageTransportSurfaceAndroid::ScheduleWakeUp, AsWeakPtr()),
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs));
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ImageTransportSurfaceAndroid::DoWakeUpGpu() {
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!GetHelper()->stub()->decoder() ||
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      !GetHelper()->stub()->decoder()->MakeCurrent())
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  glFinish();
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DidAccessGpu();
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)DirectSurfaceAndroid::DirectSurfaceAndroid(GpuChannelManager* manager,
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                           GpuCommandBufferStub* stub,
1515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                           gfx::GLSurface* surface)
1525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : PassThroughImageTransportSurface(manager, stub, surface) {}
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)DirectSurfaceAndroid::~DirectSurfaceAndroid() {}
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool DirectSurfaceAndroid::SwapBuffers() {
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DidAccessGpu();
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return PassThroughImageTransportSurface::SwapBuffers();
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // anonymous namespace
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuChannelManager* manager,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuCommandBufferStub* stub,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::GLSurfaceHandle& handle) {
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (handle.transport_type == gfx::NATIVE_TRANSPORT) {
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return scoped_refptr<gfx::GLSurface>(
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        new ImageTransportSurfaceAndroid(manager,
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         stub,
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         manager->GetDefaultOffscreenSurface(),
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         handle.parent_client_id));
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(GpuSurfaceLookup::GetInstance());
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(handle.transport_type, gfx::NATIVE_DIRECT);
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ANativeWindow* window =
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GpuSurfaceLookup::GetInstance()->AcquireNativeWidget(
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          stub->surface_id());
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<gfx::GLSurface> surface =
1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      new gfx::NativeViewGLSurfaceEGL(window);
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool initialize_success = surface->Initialize();
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (window)
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ANativeWindow_release(window);
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!initialize_success)
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return scoped_refptr<gfx::GLSurface>();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return scoped_refptr<gfx::GLSurface>(
1905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      new DirectSurfaceAndroid(manager, stub, surface.get()));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
194