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