diff options
author | gusfernandez <gusfernandez@chromium.org> | 2014-11-21 17:00:08 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-11-22 01:00:32 +0000 |
commit | 44a73aac041d87ae260a46f8c8e917af0e3a29ce (patch) | |
tree | fb329c565035f09dd464091638a556302f4b4efe | |
parent | d964d77deec9eecd17ad04d7db469c30ee11f705 (diff) | |
download | chromium_src-44a73aac041d87ae260a46f8c8e917af0e3a29ce.zip chromium_src-44a73aac041d87ae260a46f8c8e917af0e3a29ce.tar.gz chromium_src-44a73aac041d87ae260a46f8c8e917af0e3a29ce.tar.bz2 |
Infrastructure for temporarily relinquishing GPU resources.
Chromecast needs to release all OpenGL/EGL resources before
launching an external app which will own the screen and GPU.
This includes the EGL display type and window as well as the
default off-screen pbuffer which were previously retained until the GPU process exits.
BUG=432268
Review URL: https://codereview.chromium.org/712343003
Cr-Commit-Position: refs/heads/master@{#305331}
-rw-r--r-- | content/browser/gpu/gpu_process_host_ui_shim.cc | 16 | ||||
-rw-r--r-- | content/browser/gpu/gpu_process_host_ui_shim.h | 5 | ||||
-rw-r--r-- | content/common/gpu/gpu_channel_manager.cc | 25 | ||||
-rw-r--r-- | content/common/gpu/gpu_channel_manager.h | 2 | ||||
-rw-r--r-- | content/common/gpu/gpu_messages.h | 8 | ||||
-rw-r--r-- | ui/gl/gl_surface.cc | 4 | ||||
-rw-r--r-- | ui/gl/gl_surface.h | 4 | ||||
-rw-r--r-- | ui/gl/gl_surface_egl.cc | 74 | ||||
-rw-r--r-- | ui/gl/gl_surface_egl.h | 1 | ||||
-rw-r--r-- | ui/ozone/platform/dri/dri_gpu_platform_support.cc | 5 | ||||
-rw-r--r-- | ui/ozone/platform/dri/dri_gpu_platform_support.h | 1 | ||||
-rw-r--r-- | ui/ozone/public/gpu_platform_support.cc | 6 | ||||
-rw-r--r-- | ui/ozone/public/gpu_platform_support.h | 3 |
13 files changed, 142 insertions, 12 deletions
diff --git a/content/browser/gpu/gpu_process_host_ui_shim.cc b/content/browser/gpu/gpu_process_host_ui_shim.cc index 63caa7b..c92a72d 100644 --- a/content/browser/gpu/gpu_process_host_ui_shim.cc +++ b/content/browser/gpu/gpu_process_host_ui_shim.cc @@ -7,6 +7,7 @@ #include <algorithm> #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/debug/trace_event.h" #include "base/id_map.h" #include "base/lazy_instance.h" @@ -188,6 +189,13 @@ bool GpuProcessHostUIShim::OnMessageReceived(const IPC::Message& message) { return OnControlMessageReceived(message); } +void GpuProcessHostUIShim::RelinquishGpuResources( + const base::Closure& callback) { + DCHECK(relinquish_callback_.is_null()); + relinquish_callback_ = callback; + Send(new GpuMsg_RelinquishResources()); +} + void GpuProcessHostUIShim::SimulateRemoveAllContext() { Send(new GpuMsg_Clean()); } @@ -220,6 +228,8 @@ bool GpuProcessHostUIShim::OnControlMessageReceived( OnGraphicsInfoCollected) IPC_MESSAGE_HANDLER(GpuHostMsg_VideoMemoryUsageStats, OnVideoMemoryUsageStatsReceived); + IPC_MESSAGE_HANDLER(GpuHostMsg_ResourcesRelinquished, + OnResourcesRelinquished) IPC_MESSAGE_UNHANDLED_ERROR() IPC_END_MESSAGE_MAP() @@ -290,4 +300,10 @@ void GpuProcessHostUIShim::OnVideoMemoryUsageStatsReceived( video_memory_usage_stats); } +void GpuProcessHostUIShim::OnResourcesRelinquished() { + if (!relinquish_callback_.is_null()) { + base::ResetAndReturn(&relinquish_callback_).Run(); + } +} + } // namespace content diff --git a/content/browser/gpu/gpu_process_host_ui_shim.h b/content/browser/gpu/gpu_process_host_ui_shim.h index e47dc90..9d9ec53 100644 --- a/content/browser/gpu/gpu_process_host_ui_shim.h +++ b/content/browser/gpu/gpu_process_host_ui_shim.h @@ -12,7 +12,7 @@ #include <string> -#include "base/callback_forward.h" +#include "base/callback.h" #include "base/compiler_specific.h" #include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" @@ -72,6 +72,7 @@ class GpuProcessHostUIShim : public IPC::Listener, // actually received on the IO thread. bool OnMessageReceived(const IPC::Message& message) override; + CONTENT_EXPORT void RelinquishGpuResources(const base::Closure& callback); CONTENT_EXPORT void SimulateRemoveAllContext(); CONTENT_EXPORT void SimulateCrash(); CONTENT_EXPORT void SimulateHang(); @@ -93,9 +94,11 @@ class GpuProcessHostUIShim : public IPC::Listener, const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params); void OnVideoMemoryUsageStatsReceived( const GPUVideoMemoryUsageStats& video_memory_usage_stats); + void OnResourcesRelinquished(); // The serial number of the GpuProcessHost / GpuProcessHostUIShim pair. int host_id_; + base::Closure relinquish_callback_; }; } // namespace content diff --git a/content/common/gpu/gpu_channel_manager.cc b/content/common/gpu/gpu_channel_manager.cc index 69154f0..d9285313 100644 --- a/content/common/gpu/gpu_channel_manager.cc +++ b/content/common/gpu/gpu_channel_manager.cc @@ -20,6 +20,10 @@ #include "ipc/message_filter.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_share_group.h" +#if defined(USE_OZONE) +#include "ui/ozone/public/gpu_platform_support.h" +#include "ui/ozone/public/ozone_platform.h" +#endif namespace content { @@ -162,6 +166,7 @@ bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) { OnCreateViewCommandBuffer) IPC_MESSAGE_HANDLER(GpuMsg_DestroyGpuMemoryBuffer, OnDestroyGpuMemoryBuffer) IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader, OnLoadedShader) + IPC_MESSAGE_HANDLER(GpuMsg_RelinquishResources, OnRelinquishResources) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -323,4 +328,24 @@ gfx::GLSurface* GpuChannelManager::GetDefaultOffscreenSurface() { return default_offscreen_surface_.get(); } +void GpuChannelManager::OnRelinquishResources() { + if (default_offscreen_surface_.get()) { + default_offscreen_surface_->DestroyAndTerminateDisplay(); + default_offscreen_surface_ = nullptr; + } +#if defined(USE_OZONE) + ui::OzonePlatform::GetInstance() + ->GetGpuPlatformSupport() + ->RelinquishGpuResources( + base::Bind(&GpuChannelManager::OnResourcesRelinquished, + weak_factory_.GetWeakPtr())); +#else + OnResourcesRelinquished(); +#endif +} + +void GpuChannelManager::OnResourcesRelinquished() { + Send(new GpuHostMsg_ResourcesRelinquished()); +} + } // namespace content diff --git a/content/common/gpu/gpu_channel_manager.h b/content/common/gpu/gpu_channel_manager.h index 1b5f668..037758f 100644 --- a/content/common/gpu/gpu_channel_manager.h +++ b/content/common/gpu/gpu_channel_manager.h @@ -134,6 +134,8 @@ class GpuChannelManager : public IPC::Listener, gfx::GpuMemoryBufferId id, int client_id, int32 sync_point); + void OnRelinquishResources(); + void OnResourcesRelinquished(); void OnLoseAllContexts(); diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index 839de2d..52ab4c0 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h @@ -301,6 +301,11 @@ IPC_MESSAGE_CONTROL0(GpuMsg_DisableWatchdog) // Tells the GPU process that the browser has seen a GPU switch. IPC_MESSAGE_CONTROL0(GpuMsg_GpuSwitched) +// Tells the GPU process to delete the default_offscreen surface. It will also +// close the display and any other resources when the last GL surface is +// deleted. GPU process will respond with GphHosMsg_ResourcesRelinquished. +IPC_MESSAGE_CONTROL0(GpuMsg_RelinquishResources) + //------------------------------------------------------------------------------ // GPU Host Messages // These are messages to the browser. @@ -402,6 +407,9 @@ IPC_MESSAGE_CONTROL1(GpuHostMsg_DidDestroyOffscreenContext, IPC_MESSAGE_CONTROL1(GpuHostMsg_GpuMemoryUmaStats, content::GPUMemoryUmaStats /* GPU memory UMA stats */) +// Response to GpuMsg_RelinquishResources. +IPC_MESSAGE_CONTROL0(GpuHostMsg_ResourcesRelinquished) + //------------------------------------------------------------------------------ // GPU Channel Messages // These are messages from a renderer process to the GPU process. diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc index 620cee7..e2f1717 100644 --- a/ui/gl/gl_surface.cc +++ b/ui/gl/gl_surface.cc @@ -165,6 +165,10 @@ bool GLSurface::Initialize() { return true; } +void GLSurface::DestroyAndTerminateDisplay() { + Destroy(); +} + bool GLSurface::Resize(const gfx::Size& size) { NOTIMPLEMENTED(); return false; diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h index 54bcc37..1302cce 100644 --- a/ui/gl/gl_surface.h +++ b/ui/gl/gl_surface.h @@ -38,6 +38,10 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> { // Destroys the surface. virtual void Destroy() = 0; + // Destroys the surface and terminates its underlying display. This must be + // the last surface which uses the display. + virtual void DestroyAndTerminateDisplay(); + virtual bool Resize(const gfx::Size& size); // Recreate the surface without changing the size. diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc index 19119a9..3a453b6 100644 --- a/ui/gl/gl_surface_egl.cc +++ b/ui/gl/gl_surface_egl.cc @@ -61,7 +61,16 @@ namespace { EGLConfig g_config; EGLDisplay g_display; -EGLNativeDisplayType g_native_display; +EGLNativeDisplayType g_native_display_type; + +// In the Cast environment, we need to destroy the EGLNativeDisplayType and +// EGLDisplay returned by the GPU platform when we switch to an external app +// which will temporarily own all screen and GPU resources. +// Even though Chromium is still in the background. +// As such, it must be reinitialized each time we come back to the foreground. +bool g_initialized = false; +int g_num_surfaces = 0; +bool g_terminate_pending = false; const char* g_egl_extensions = NULL; bool g_egl_create_context_robustness_supported = false; @@ -105,21 +114,34 @@ class EGLSyncControlVSyncProvider DISALLOW_COPY_AND_ASSIGN(EGLSyncControlVSyncProvider); }; +void DeinitializeEgl() { + if (g_initialized) { + g_initialized = false; + eglTerminate(g_display); + } +} + } // namespace -GLSurfaceEGL::GLSurfaceEGL() {} +GLSurfaceEGL::GLSurfaceEGL() { + ++g_num_surfaces; + if (!g_initialized) { + bool result = GLSurfaceEGL::InitializeOneOff(); + DCHECK(result); + DCHECK(g_initialized); + } +} bool GLSurfaceEGL::InitializeOneOff() { - static bool initialized = false; - if (initialized) + if (g_initialized) return true; - g_native_display = GetPlatformDefaultEGLNativeDisplay(); + g_native_display_type = GetPlatformDefaultEGLNativeDisplay(); #if defined(OS_WIN) - g_display = GetPlatformDisplay(g_native_display); + g_display = GetPlatformDisplay(g_native_display_type); #else - g_display = eglGetDisplay(g_native_display); + g_display = eglGetDisplay(g_native_display_type); #endif if (!g_display) { @@ -187,6 +209,12 @@ bool GLSurfaceEGL::InitializeOneOff() { g_egl_window_fixed_size_supported = HasEGLExtension("EGL_ANGLE_window_fixed_size"); + // We always succeed beyond this point so set g_initialized here to avoid + // infinite recursion through CreateGLContext and GetDisplay + // if g_egl_surfaceless_context_supported. + g_initialized = true; + g_terminate_pending = false; + // TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary // workaround, since code written for Android WebView takes different paths // based on whether GL surface objects have underlying EGL surface handles, @@ -216,24 +244,35 @@ bool GLSurfaceEGL::InitializeOneOff() { } #endif - initialized = true; - return true; } EGLDisplay GLSurfaceEGL::GetDisplay() { + DCHECK(g_initialized); return g_display; } +// static EGLDisplay GLSurfaceEGL::GetHardwareDisplay() { + if (!g_initialized) { + bool result = GLSurfaceEGL::InitializeOneOff(); + DCHECK(result); + } return g_display; } +// static EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() { - return g_native_display; + if (!g_initialized) { + bool result = GLSurfaceEGL::InitializeOneOff(); + DCHECK(result); + } + return g_native_display_type; } const char* GLSurfaceEGL::GetEGLExtensions() { + // No need for InitializeOneOff. Assume that extensions will not change + // after the first initialization. return g_egl_extensions; } @@ -249,7 +288,20 @@ bool GLSurfaceEGL::IsEGLSurfacelessContextSupported() { return g_egl_surfaceless_context_supported; } -GLSurfaceEGL::~GLSurfaceEGL() {} +void GLSurfaceEGL::DestroyAndTerminateDisplay() { + DCHECK(g_initialized); + DCHECK_EQ(g_num_surfaces, 1); + Destroy(); + g_terminate_pending = true; +} + +GLSurfaceEGL::~GLSurfaceEGL() { + DCHECK_GT(g_num_surfaces, 0) << "Bad surface count"; + if (--g_num_surfaces == 0 && g_terminate_pending) { + DeinitializeEgl(); + g_terminate_pending = false; + } +} #if defined(OS_WIN) static const EGLint kDisplayAttribsWarp[] { diff --git a/ui/gl/gl_surface_egl.h b/ui/gl/gl_surface_egl.h index 952ccad..720c7dd 100644 --- a/ui/gl/gl_surface_egl.h +++ b/ui/gl/gl_surface_egl.h @@ -29,6 +29,7 @@ class GL_EXPORT GLSurfaceEGL : public GLSurface { GLSurfaceEGL(); // Implement GLSurface. + void DestroyAndTerminateDisplay() override; EGLDisplay GetDisplay() override; static bool InitializeOneOff(); diff --git a/ui/ozone/platform/dri/dri_gpu_platform_support.cc b/ui/ozone/platform/dri/dri_gpu_platform_support.cc index b3ddbd8..58e2a45 100644 --- a/ui/ozone/platform/dri/dri_gpu_platform_support.cc +++ b/ui/ozone/platform/dri/dri_gpu_platform_support.cc @@ -198,4 +198,9 @@ void DriGpuPlatformSupport::OnRelinquishDisplayControl() { ndd_->RelinquishDisplayControl(); } +void DriGpuPlatformSupport::RelinquishGpuResources( + const base::Closure& callback) { + callback.Run(); +} + } // namespace ui diff --git a/ui/ozone/platform/dri/dri_gpu_platform_support.h b/ui/ozone/platform/dri/dri_gpu_platform_support.h index 05ab767..f3f54d2 100644 --- a/ui/ozone/platform/dri/dri_gpu_platform_support.h +++ b/ui/ozone/platform/dri/dri_gpu_platform_support.h @@ -41,6 +41,7 @@ class DriGpuPlatformSupport : public GpuPlatformSupport { // GpuPlatformSupport: void OnChannelEstablished(IPC::Sender* sender) override; + void RelinquishGpuResources(const base::Closure& callback) override; // IPC::Listener: bool OnMessageReceived(const IPC::Message& message) override; diff --git a/ui/ozone/public/gpu_platform_support.cc b/ui/ozone/public/gpu_platform_support.cc index 4b7f527..a2457cd 100644 --- a/ui/ozone/public/gpu_platform_support.cc +++ b/ui/ozone/public/gpu_platform_support.cc @@ -17,8 +17,14 @@ class StubGpuPlatformSupport : public GpuPlatformSupport { // GpuPlatformSupport: void OnChannelEstablished(IPC::Sender* sender) override {} bool OnMessageReceived(const IPC::Message&) override { return false; } + void RelinquishGpuResources(const base::Closure& callback) override; }; +void StubGpuPlatformSupport::RelinquishGpuResources( + const base::Closure& callback) { + callback.Run(); +} + } // namespace GpuPlatformSupport::GpuPlatformSupport() { diff --git a/ui/ozone/public/gpu_platform_support.h b/ui/ozone/public/gpu_platform_support.h index c912fa0..ed2b4c8 100644 --- a/ui/ozone/public/gpu_platform_support.h +++ b/ui/ozone/public/gpu_platform_support.h @@ -5,6 +5,7 @@ #ifndef UI_OZONE_PUBLIC_GPU_PLATFORM_SUPPORT_H_ #define UI_OZONE_PUBLIC_GPU_PLATFORM_SUPPORT_H_ +#include "base/callback.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_sender.h" #include "ui/ozone/ozone_base_export.h" @@ -21,6 +22,8 @@ class OZONE_BASE_EXPORT GpuPlatformSupport : public IPC::Listener { // Called when the GPU process is spun up & channel established. virtual void OnChannelEstablished(IPC::Sender* sender) = 0; + + virtual void RelinquishGpuResources(const base::Closure& callback) = 0; }; // Create a stub implementation. |