summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgusfernandez <gusfernandez@chromium.org>2014-11-21 17:00:08 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-22 01:00:32 +0000
commit44a73aac041d87ae260a46f8c8e917af0e3a29ce (patch)
treefb329c565035f09dd464091638a556302f4b4efe
parentd964d77deec9eecd17ad04d7db469c30ee11f705 (diff)
downloadchromium_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.cc16
-rw-r--r--content/browser/gpu/gpu_process_host_ui_shim.h5
-rw-r--r--content/common/gpu/gpu_channel_manager.cc25
-rw-r--r--content/common/gpu/gpu_channel_manager.h2
-rw-r--r--content/common/gpu/gpu_messages.h8
-rw-r--r--ui/gl/gl_surface.cc4
-rw-r--r--ui/gl/gl_surface.h4
-rw-r--r--ui/gl/gl_surface_egl.cc74
-rw-r--r--ui/gl/gl_surface_egl.h1
-rw-r--r--ui/ozone/platform/dri/dri_gpu_platform_support.cc5
-rw-r--r--ui/ozone/platform/dri/dri_gpu_platform_support.h1
-rw-r--r--ui/ozone/public/gpu_platform_support.cc6
-rw-r--r--ui/ozone/public/gpu_platform_support.h3
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.