summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjbauman <jbauman@chromium.org>2016-01-08 14:48:53 -0800
committerCommit bot <commit-bot@chromium.org>2016-01-08 22:50:01 +0000
commit278b2ccf77a0e32fba6322278b2b4e1afd893da1 (patch)
tree1ce5f3683555da4bdf8c6de1206f9cb4b93e70c9
parent141756c27f6422ccb966cb2b2d5889288524b9a6 (diff)
downloadchromium_src-278b2ccf77a0e32fba6322278b2b4e1afd893da1.zip
chromium_src-278b2ccf77a0e32fba6322278b2b4e1afd893da1.tar.gz
chromium_src-278b2ccf77a0e32fba6322278b2b4e1afd893da1.tar.bz2
Create child window in GPU process for DirectComposition
When the new --use-direct-composition command-line flag is specified the GPU process will create a new child window to present into. This will be necessary when using DirectComposition because DirectComposition can only render into windows created by the same process. The sandbox prevents the GPU process from directly doing SetParent of its child window to the browser window, so a new IPC is added to allow that. BUG=524838,545203 Review URL: https://codereview.chromium.org/1538803004 Cr-Commit-Position: refs/heads/master@{#368450}
-rw-r--r--content/browser/browser_child_process_host_impl.cc6
-rw-r--r--content/browser/browser_child_process_host_impl.h4
-rw-r--r--content/browser/gpu/gpu_process_host.cc34
-rw-r--r--content/browser/gpu/gpu_process_host.h6
-rw-r--r--content/common/gpu/child_window_surface_win.cc122
-rw-r--r--content/common/gpu/child_window_surface_win.h37
-rw-r--r--content/common/gpu/gpu_messages.h6
-rw-r--r--content/common/gpu/image_transport_surface_win.cc16
-rw-r--r--content/content_common.gypi2
-rw-r--r--ui/gl/gl_surface_egl.cc13
-rw-r--r--ui/gl/gl_surface_egl.h4
-rw-r--r--ui/gl/gl_switches.cc4
-rw-r--r--ui/gl/gl_switches.h1
13 files changed, 247 insertions, 8 deletions
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc
index f2b4f80..9461b62 100644
--- a/content/browser/browser_child_process_host_impl.cc
+++ b/content/browser/browser_child_process_host_impl.cc
@@ -312,13 +312,17 @@ void BrowserChildProcessHostImpl::OnChannelError() {
void BrowserChildProcessHostImpl::OnBadMessageReceived(
const IPC::Message& message) {
+ TerminateOnBadMessageReceived(message.type());
+}
+
+void BrowserChildProcessHostImpl::TerminateOnBadMessageReceived(uint32_t type) {
HistogramBadMessageTerminated(data_.process_type);
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableKillAfterBadIPC)) {
return;
}
LOG(ERROR) << "Terminating child process for bad IPC message of type "
- << message.type();
+ << type;
// Create a memory dump. This will contain enough stack frames to work out
// what the bad message was.
diff --git a/content/browser/browser_child_process_host_impl.h b/content/browser/browser_child_process_host_impl.h
index 6b89e7f..a5f3b6d 100644
--- a/content/browser/browser_child_process_host_impl.h
+++ b/content/browser/browser_child_process_host_impl.h
@@ -76,6 +76,10 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
void OnChannelError() override;
void OnBadMessageReceived(const IPC::Message& message) override;
+ // Terminates the process and logs an error after a bad message was received
+ // from the child process.
+ void TerminateOnBadMessageReceived(uint32_t type);
+
// Removes this host from the host list. Calls ChildProcessHost::ForceShutdown
void ForceShutdown();
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 913d7e1..b970578 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -617,6 +617,10 @@ bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
OnDestroyChannel)
IPC_MESSAGE_HANDLER(GpuHostMsg_CacheShader,
OnCacheShader)
+#if defined(OS_WIN)
+ IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceCreatedChildWindow,
+ OnAcceleratedSurfaceCreatedChildWindow)
+#endif
IPC_MESSAGE_UNHANDLED(RouteOnUIThread(message))
IPC_END_MESSAGE_MAP()
@@ -624,6 +628,36 @@ bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
return true;
}
+#if defined(OS_WIN)
+void GpuProcessHost::OnAcceleratedSurfaceCreatedChildWindow(
+ const gfx::PluginWindowHandle& parent_handle,
+ const gfx::PluginWindowHandle& window_handle) {
+ DCHECK(process_);
+ {
+ DWORD process_id = 0;
+ DWORD thread_id = GetWindowThreadProcessId(parent_handle, &process_id);
+
+ if (!thread_id || process_id != ::GetCurrentProcessId()) {
+ process_->TerminateOnBadMessageReceived(
+ GpuHostMsg_AcceleratedSurfaceCreatedChildWindow::ID);
+ return;
+ }
+ }
+ {
+ DWORD process_id = 0;
+ DWORD thread_id = GetWindowThreadProcessId(window_handle, &process_id);
+
+ if (!thread_id || process_id != process_->GetProcess().Pid()) {
+ process_->TerminateOnBadMessageReceived(
+ GpuHostMsg_AcceleratedSurfaceCreatedChildWindow::ID);
+ return;
+ }
+ }
+
+ ::SetParent(window_handle, parent_handle);
+}
+#endif
+
void GpuProcessHost::OnChannelConnected(int32_t peer_pid) {
TRACE_EVENT0("gpu", "GpuProcessHost::OnChannelConnected");
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h
index 60001e6..3df8067 100644
--- a/content/browser/gpu/gpu_process_host.h
+++ b/content/browser/gpu/gpu_process_host.h
@@ -206,6 +206,12 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
void OnAcceleratedSurfaceBuffersSwapped(const IPC::Message& message);
#endif
+#if defined(OS_WIN)
+ void OnAcceleratedSurfaceCreatedChildWindow(
+ const gfx::PluginWindowHandle& parent_handle,
+ const gfx::PluginWindowHandle& window_handle);
+#endif
+
void CreateChannelCache(int32_t client_id);
void OnDestroyChannel(int32_t client_id);
void OnCacheShader(int32_t client_id,
diff --git a/content/common/gpu/child_window_surface_win.cc b/content/common/gpu/child_window_surface_win.cc
new file mode 100644
index 0000000..c49a1ab
--- /dev/null
+++ b/content/common/gpu/child_window_surface_win.cc
@@ -0,0 +1,122 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/child_window_surface_win.h"
+
+#include "base/compiler_specific.h"
+#include "base/win/wrapped_window_proc.h"
+#include "content/common/gpu/gpu_channel_manager.h"
+#include "content/common/gpu/gpu_messages.h"
+#include "ui/base/win/hidden_window.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gl/gl_surface_egl.h"
+
+namespace content {
+
+namespace {
+
+ATOM g_window_class;
+
+LRESULT CALLBACK IntermediateWindowProc(HWND window,
+ UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ switch (message) {
+ case WM_ERASEBKGND:
+ // Prevent windows from erasing the background.
+ return 1;
+ case WM_PAINT:
+ // Do not paint anything.
+ PAINTSTRUCT paint;
+ if (BeginPaint(window, &paint)) {
+ // DirectComposition composites with the contents under the SwapChain,
+ // so ensure that's cleared.
+ if (!IsRectEmpty(&paint.rcPaint)) {
+ FillRect(paint.hdc, &paint.rcPaint,
+ (HBRUSH)GetStockObject(BLACK_BRUSH));
+ }
+ EndPaint(window, &paint);
+ }
+ return 0;
+ default:
+ return DefWindowProc(window, message, w_param, l_param);
+ }
+}
+
+void InitializeWindowClass() {
+ if (g_window_class)
+ return;
+
+ WNDCLASSEX intermediate_class;
+ base::win::InitializeWindowClass(
+ L"Intermediate D3D Window",
+ &base::win::WrappedWindowProc<IntermediateWindowProc>, CS_OWNDC, 0, 0,
+ nullptr, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)), nullptr,
+ nullptr, nullptr, &intermediate_class);
+ g_window_class = RegisterClassEx(&intermediate_class);
+ if (!g_window_class) {
+ LOG(ERROR) << "RegisterClass failed.";
+ return;
+ }
+}
+}
+
+ChildWindowSurfaceWin::ChildWindowSurfaceWin(GpuChannelManager* manager,
+ HWND parent_window)
+ : gfx::NativeViewGLSurfaceEGL(0),
+ parent_window_(parent_window),
+ manager_(manager) {
+ // Don't use EGL_ANGLE_window_fixed_size so that we can avoid recreating the
+ // window surface, which can cause flicker on DirectComposition.
+ enable_fixed_size_angle_ = false;
+}
+
+bool ChildWindowSurfaceWin::InitializeNativeWindow() {
+ if (window_)
+ return true;
+ InitializeWindowClass();
+ DCHECK(g_window_class);
+
+ RECT windowRect;
+ GetClientRect(parent_window_, &windowRect);
+
+ window_ = CreateWindowEx(
+ WS_EX_NOPARENTNOTIFY, reinterpret_cast<wchar_t*>(g_window_class), L"",
+ WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE, 0, 0,
+ windowRect.right - windowRect.left, windowRect.bottom - windowRect.top,
+ ui::GetHiddenWindow(), NULL, NULL, NULL);
+ manager_->Send(new GpuHostMsg_AcceleratedSurfaceCreatedChildWindow(
+ parent_window_, window_));
+ return true;
+}
+
+bool ChildWindowSurfaceWin::Resize(const gfx::Size& size,
+ float scale_factor,
+ bool has_alpha) {
+ if (!SupportsPostSubBuffer()) {
+ if (!MoveWindow(window_, 0, 0, size.width(), size.height(), FALSE)) {
+ return false;
+ }
+ return gfx::NativeViewGLSurfaceEGL::Resize(size, scale_factor, has_alpha);
+ } else {
+ if (size == GetSize() && has_alpha == alpha_)
+ return true;
+
+ alpha_ = has_alpha;
+ size_ = size;
+ if (!MoveWindow(window_, 0, 0, size.width(), size.height(), FALSE)) {
+ return false;
+ }
+ // A 0-size PostSubBuffer doesn't swap but forces the swap chain to resize
+ // to match the window.
+ PostSubBuffer(0, 0, 0, 0);
+ return true;
+ }
+}
+
+ChildWindowSurfaceWin::~ChildWindowSurfaceWin() {
+ DestroyWindow(window_);
+}
+
+} // namespace content
diff --git a/content/common/gpu/child_window_surface_win.h b/content/common/gpu/child_window_surface_win.h
new file mode 100644
index 0000000..cb021ff
--- /dev/null
+++ b/content/common/gpu/child_window_surface_win.h
@@ -0,0 +1,37 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_GPU_CHILD_WINDOW_SURFACE_WIN_H_
+#define CONTENT_COMMON_GPU_CHILD_WINDOW_SURFACE_WIN_H_
+#include "ui/gl/gl_surface_egl.h"
+
+#include <windows.h>
+
+namespace content {
+
+class GpuChannelManager;
+
+class ChildWindowSurfaceWin : public gfx::NativeViewGLSurfaceEGL {
+ public:
+ ChildWindowSurfaceWin(GpuChannelManager* manager, HWND parent_window);
+
+ // GLSurface implementation.
+ bool Resize(const gfx::Size& size,
+ float scale_factor,
+ bool has_alpha) override;
+ bool InitializeNativeWindow() override;
+
+ protected:
+ ~ChildWindowSurfaceWin() override;
+
+ private:
+ HWND parent_window_;
+ GpuChannelManager* manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChildWindowSurfaceWin);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_CHILD_WINDOW_SURFACE_WIN_H_
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h
index 961c33f..24664df 100644
--- a/content/common/gpu/gpu_messages.h
+++ b/content/common/gpu/gpu_messages.h
@@ -481,6 +481,12 @@ IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params)
#endif
+#if defined(OS_WIN)
+IPC_MESSAGE_CONTROL2(GpuHostMsg_AcceleratedSurfaceCreatedChildWindow,
+ gfx::PluginWindowHandle /* parent_window */,
+ gfx::PluginWindowHandle /* child_window */)
+#endif
+
IPC_MESSAGE_CONTROL1(GpuHostMsg_DidCreateOffscreenContext,
GURL /* url */)
diff --git a/content/common/gpu/image_transport_surface_win.cc b/content/common/gpu/image_transport_surface_win.cc
index 597a472..0607325 100644
--- a/content/common/gpu/image_transport_surface_win.cc
+++ b/content/common/gpu/image_transport_surface_win.cc
@@ -10,6 +10,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/win/windows_version.h"
+#include "content/common/gpu/child_window_surface_win.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/public/common/content_switches.h"
#include "ui/gfx/native_widget_types.h"
@@ -27,10 +28,17 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
const gfx::GLSurfaceHandle& handle) {
DCHECK(handle.handle);
DCHECK_EQ(handle.transport_type, gfx::NATIVE_DIRECT);
- scoped_refptr<gfx::GLSurface> surface =
- gfx::GLSurface::CreateViewGLSurface(handle.handle);
- if (!surface.get())
- return surface;
+
+ scoped_refptr<gfx::GLSurface> surface;
+ if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
+ gfx::GLSurfaceEGL::IsDirectCompositionSupported()) {
+ surface = new ChildWindowSurfaceWin(manager, handle.handle);
+ if (!surface->Initialize())
+ return nullptr;
+ } else {
+ surface = gfx::GLSurface::CreateViewGLSurface(handle.handle);
+ }
+
return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface(
manager, stub, surface.get()));
}
diff --git a/content/content_common.gypi b/content/content_common.gypi
index 5509c88..5567be5 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -320,6 +320,8 @@
'common/gpu/client/grcontext_for_webgraphicscontext3d.h',
'common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc',
'common/gpu/client/webgraphicscontext3d_command_buffer_impl.h',
+ 'common/gpu/child_window_surface_win.cc',
+ 'common/gpu/child_window_surface_win.h',
'common/gpu/gpu_channel.cc',
'common/gpu/gpu_channel.h',
'common/gpu/gpu_channel_manager.cc',
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc
index 5dd8637..2d1882e 100644
--- a/ui/gl/gl_surface_egl.cc
+++ b/ui/gl/gl_surface_egl.cc
@@ -116,6 +116,7 @@ bool g_egl_sync_control_supported = false;
bool g_egl_window_fixed_size_supported = false;
bool g_egl_surfaceless_context_supported = false;
bool g_egl_surface_orientation_supported = false;
+bool g_use_direct_composition = false;
class EGLSyncControlVSyncProvider
: public gfx::SyncControlVSyncProvider {
@@ -376,6 +377,9 @@ bool GLSurfaceEGL::InitializeOneOff() {
g_egl_surface_orientation_supported =
HasEGLExtension("EGL_ANGLE_surface_orientation");
+ g_use_direct_composition = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kUseDirectComposition);
+
// 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,
@@ -438,6 +442,10 @@ bool GLSurfaceEGL::IsEGLSurfacelessContextSupported() {
return g_egl_surfaceless_context_supported;
}
+bool GLSurfaceEGL::IsDirectCompositionSupported() {
+ return g_use_direct_composition;
+}
+
GLSurfaceEGL::~GLSurfaceEGL() {}
// InitializeDisplay is necessary because the static binding code
@@ -500,9 +508,10 @@ NativeViewGLSurfaceEGL::NativeViewGLSurfaceEGL(EGLNativeWindowType window)
: window_(window),
config_(NULL),
size_(1, 1),
+ alpha_(true),
+ enable_fixed_size_angle_(false),
surface_(NULL),
supports_post_sub_buffer_(false),
- alpha_(true),
flips_vertically_(false),
swap_interval_(1) {
#if defined(OS_ANDROID)
@@ -541,7 +550,7 @@ bool NativeViewGLSurfaceEGL::Initialize(
std::vector<EGLint> egl_window_attributes;
- if (g_egl_window_fixed_size_supported) {
+ if (g_egl_window_fixed_size_supported && enable_fixed_size_angle_) {
egl_window_attributes.push_back(EGL_FIXED_SIZE_ANGLE);
egl_window_attributes.push_back(EGL_TRUE);
egl_window_attributes.push_back(EGL_WIDTH);
diff --git a/ui/gl/gl_surface_egl.h b/ui/gl/gl_surface_egl.h
index 1c99fae..45396d4 100644
--- a/ui/gl/gl_surface_egl.h
+++ b/ui/gl/gl_surface_egl.h
@@ -65,6 +65,7 @@ class GL_EXPORT GLSurfaceEGL : public GLSurface {
static bool HasEGLExtension(const char* name);
static bool IsCreateContextRobustnessSupported();
static bool IsEGLSurfacelessContextSupported();
+ static bool IsDirectCompositionSupported();
protected:
~GLSurfaceEGL() override;
@@ -115,6 +116,8 @@ class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL {
EGLNativeWindowType window_;
EGLConfig config_;
gfx::Size size_;
+ bool alpha_;
+ bool enable_fixed_size_angle_;
void OnSetSwapInterval(int interval) override;
@@ -125,7 +128,6 @@ class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL {
EGLSurface surface_;
bool supports_post_sub_buffer_;
- bool alpha_;
bool flips_vertically_;
scoped_ptr<VSyncProvider> vsync_provider_;
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc
index 1b51531..5327dd5 100644
--- a/ui/gl/gl_switches.cc
+++ b/ui/gl/gl_switches.cc
@@ -66,6 +66,9 @@ const char kSwiftShaderPath[] = "swiftshader-path";
// context will never be lost in any situations, say, a GPU reset.
const char kGpuNoContextLost[] = "gpu-no-context-lost";
+// Turns on the use of DirectComposition to draw to the screen.
+const char kUseDirectComposition[] = "use-direct-composition";
+
// Indicates whether the dual GPU switching is supported or not.
const char kSupportsDualGpus[] = "supports-dual-gpus";
@@ -103,6 +106,7 @@ const char* kGLSwitchesCopiedFromGpuProcessHost[] = {
kDisableGLDrawingForTests,
kOverrideUseGLWithOSMesaForTests,
kUseANGLE,
+ kUseDirectComposition,
};
const int kGLSwitchesCopiedFromGpuProcessHostNumSwitches =
arraysize(kGLSwitchesCopiedFromGpuProcessHost);
diff --git a/ui/gl/gl_switches.h b/ui/gl/gl_switches.h
index 05767db..ca317a2 100644
--- a/ui/gl/gl_switches.h
+++ b/ui/gl/gl_switches.h
@@ -35,6 +35,7 @@ GL_EXPORT extern const char kDisableGpuVsync[];
GL_EXPORT extern const char kEnableGPUServiceLogging[];
GL_EXPORT extern const char kEnableGPUServiceTracing[];
GL_EXPORT extern const char kGpuNoContextLost[];
+GL_EXPORT extern const char kUseDirectComposition[];
GL_EXPORT extern const char kSupportsDualGpus[];