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