Home | History | Annotate | Download | only in gpu
      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 base::CommandLine* command_line =
     96         base::CommandLine::ForCurrentProcess();
     97     if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess))
     98       GetHelper()->SetPreemptByFlag(parent_channel->GetPreemptionFlag());
     99   }
    100 
    101   return true;
    102 }
    103 
    104 bool ImageTransportSurfaceAndroid::OnMakeCurrent(gfx::GLContext* context) {
    105   DidAccessGpu();
    106   return true;
    107 }
    108 
    109 bool ImageTransportSurfaceAndroid::SwapBuffers() {
    110   NOTREACHED();
    111   return false;
    112 }
    113 
    114 void ImageTransportSurfaceAndroid::WakeUpGpu() {
    115   begin_wake_up_time_ = base::TimeTicks::Now();
    116   ScheduleWakeUp();
    117 }
    118 
    119 void ImageTransportSurfaceAndroid::ScheduleWakeUp() {
    120   base::TimeTicks now = base::TimeTicks::Now();
    121   base::TimeTicks last_access_time =
    122       base::TimeTicks::FromInternalValue(g_last_gpu_access_ticks);
    123   TRACE_EVENT2("gpu", "ImageTransportSurfaceAndroid::ScheduleWakeUp",
    124                "idle_time", (now - last_access_time).InMilliseconds(),
    125                "keep_awake_time", (now - begin_wake_up_time_).InMilliseconds());
    126   if (now - last_access_time <
    127       base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs))
    128     return;
    129   if (now - begin_wake_up_time_ >
    130       base::TimeDelta::FromMilliseconds(kMaxKeepAliveTimeMs))
    131     return;
    132 
    133   DoWakeUpGpu();
    134 
    135   base::MessageLoop::current()->PostDelayedTask(
    136       FROM_HERE,
    137       base::Bind(&ImageTransportSurfaceAndroid::ScheduleWakeUp, AsWeakPtr()),
    138       base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs));
    139 }
    140 
    141 void ImageTransportSurfaceAndroid::DoWakeUpGpu() {
    142   if (!GetHelper()->stub()->decoder() ||
    143       !GetHelper()->stub()->decoder()->MakeCurrent())
    144     return;
    145   glFinish();
    146   DidAccessGpu();
    147 }
    148 
    149 DirectSurfaceAndroid::DirectSurfaceAndroid(GpuChannelManager* manager,
    150                                            GpuCommandBufferStub* stub,
    151                                            gfx::GLSurface* surface)
    152     : PassThroughImageTransportSurface(manager, stub, surface) {}
    153 
    154 DirectSurfaceAndroid::~DirectSurfaceAndroid() {}
    155 
    156 bool DirectSurfaceAndroid::SwapBuffers() {
    157   DidAccessGpu();
    158   return PassThroughImageTransportSurface::SwapBuffers();
    159 }
    160 
    161 }  // anonymous namespace
    162 
    163 // static
    164 scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
    165     GpuChannelManager* manager,
    166     GpuCommandBufferStub* stub,
    167     const gfx::GLSurfaceHandle& handle) {
    168   if (handle.transport_type == gfx::NATIVE_TRANSPORT) {
    169     return scoped_refptr<gfx::GLSurface>(
    170         new ImageTransportSurfaceAndroid(manager,
    171                                          stub,
    172                                          manager->GetDefaultOffscreenSurface(),
    173                                          handle.parent_client_id));
    174   }
    175 
    176   DCHECK(GpuSurfaceLookup::GetInstance());
    177   DCHECK_EQ(handle.transport_type, gfx::NATIVE_DIRECT);
    178   ANativeWindow* window =
    179       GpuSurfaceLookup::GetInstance()->AcquireNativeWidget(
    180           stub->surface_id());
    181   scoped_refptr<gfx::GLSurface> surface =
    182       new gfx::NativeViewGLSurfaceEGL(window);
    183   bool initialize_success = surface->Initialize();
    184   if (window)
    185     ANativeWindow_release(window);
    186   if (!initialize_success)
    187     return scoped_refptr<gfx::GLSurface>();
    188 
    189   return scoped_refptr<gfx::GLSurface>(
    190       new DirectSurfaceAndroid(manager, stub, surface.get()));
    191 }
    192 
    193 }  // namespace content
    194