Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "gpu/ipc/service/child_window_surface_win.h" | 5 #include "gpu/ipc/service/child_window_surface_win.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/memory/ptr_util.h" | |
| 11 #include "base/threading/thread.h" | |
| 10 #include "base/win/scoped_hdc.h" | 12 #include "base/win/scoped_hdc.h" |
| 11 #include "base/win/wrapped_window_proc.h" | 13 #include "base/win/wrapped_window_proc.h" |
| 12 #include "gpu/ipc/common/gpu_messages.h" | 14 #include "gpu/ipc/common/gpu_messages.h" |
| 13 #include "gpu/ipc/service/gpu_channel_manager.h" | 15 #include "gpu/ipc/service/gpu_channel_manager.h" |
| 14 #include "gpu/ipc/service/gpu_channel_manager_delegate.h" | 16 #include "gpu/ipc/service/gpu_channel_manager_delegate.h" |
| 15 #include "ui/base/win/hidden_window.h" | 17 #include "ui/base/win/hidden_window.h" |
| 16 #include "ui/gfx/native_widget_types.h" | 18 #include "ui/gfx/native_widget_types.h" |
| 17 #include "ui/gfx/win/hwnd_util.h" | 19 #include "ui/gfx/win/hwnd_util.h" |
| 18 #include "ui/gl/egl_util.h" | 20 #include "ui/gl/egl_util.h" |
| 19 #include "ui/gl/gl_context.h" | 21 #include "ui/gl/gl_context.h" |
| 20 #include "ui/gl/gl_surface_egl.h" | 22 #include "ui/gl/gl_surface_egl.h" |
| 21 #include "ui/gl/scoped_make_current.h" | 23 #include "ui/gl/scoped_make_current.h" |
| 22 | 24 |
| 23 namespace gpu { | 25 namespace gpu { |
| 24 | 26 |
| 27 // This owns the thread and contains data that's shared between the threads. | |
| 28 struct SharedData { | |
| 29 SharedData() : thread("Window owner thread") {} | |
| 30 | |
| 31 base::Lock rect_lock; | |
| 32 gfx::Rect rect_to_clear; | |
| 33 | |
| 34 base::Thread thread; | |
| 35 }; | |
| 36 | |
| 25 namespace { | 37 namespace { |
| 26 | 38 |
| 27 ATOM g_window_class; | 39 ATOM g_window_class; |
| 28 | 40 |
| 29 LRESULT CALLBACK IntermediateWindowProc(HWND window, | 41 LRESULT CALLBACK IntermediateWindowProc(HWND window, |
| 30 UINT message, | 42 UINT message, |
| 31 WPARAM w_param, | 43 WPARAM w_param, |
| 32 LPARAM l_param) { | 44 LPARAM l_param) { |
| 33 switch (message) { | 45 switch (message) { |
| 34 case WM_ERASEBKGND: | 46 case WM_ERASEBKGND: |
| 35 // Prevent windows from erasing the background. | 47 // Prevent windows from erasing the background. |
| 36 return 1; | 48 return 1; |
| 37 case WM_PAINT: | 49 case WM_PAINT: |
| 38 PAINTSTRUCT paint; | 50 PAINTSTRUCT paint; |
| 39 if (BeginPaint(window, &paint)) { | 51 if (BeginPaint(window, &paint)) { |
| 40 ChildWindowSurfaceWin* window_surface = | 52 SharedData* shared_data = |
| 41 reinterpret_cast<ChildWindowSurfaceWin*>( | 53 reinterpret_cast<SharedData*>(gfx::GetWindowUserData(window)); |
| 42 gfx::GetWindowUserData(window)); | 54 DCHECK(shared_data); |
| 43 DCHECK(window_surface); | |
| 44 | 55 |
| 45 // Wait to clear the contents until a GL draw occurs, as otherwise an | 56 base::AutoLock lock(shared_data->rect_lock); |
| 46 // unsightly black flash may happen if the GL contents are still | 57 shared_data->rect_to_clear.Union(gfx::Rect(paint.rcPaint)); |
|
stanisc
2016/08/04 02:03:35
Should the lock scope end after this line?
jbauman
2016/08/04 20:45:51
Done.
| |
| 47 // transparent. | 58 |
| 48 window_surface->InvalidateWindowRect(gfx::Rect(paint.rcPaint)); | |
| 49 EndPaint(window, &paint); | 59 EndPaint(window, &paint); |
| 50 } | 60 } |
| 51 return 0; | 61 return 0; |
| 52 default: | 62 default: |
| 53 return DefWindowProc(window, message, w_param, l_param); | 63 return DefWindowProc(window, message, w_param, l_param); |
| 54 } | 64 } |
| 55 } | 65 } |
| 56 | 66 |
| 57 void InitializeWindowClass() { | 67 void InitializeWindowClass() { |
| 58 if (g_window_class) | 68 if (g_window_class) |
| 59 return; | 69 return; |
| 60 | 70 |
| 61 WNDCLASSEX intermediate_class; | 71 WNDCLASSEX intermediate_class; |
| 62 base::win::InitializeWindowClass( | 72 base::win::InitializeWindowClass( |
| 63 L"Intermediate D3D Window", | 73 L"Intermediate D3D Window", |
| 64 &base::win::WrappedWindowProc<IntermediateWindowProc>, CS_OWNDC, 0, 0, | 74 &base::win::WrappedWindowProc<IntermediateWindowProc>, CS_OWNDC, 0, 0, |
| 65 nullptr, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)), nullptr, | 75 nullptr, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)), nullptr, |
| 66 nullptr, nullptr, &intermediate_class); | 76 nullptr, nullptr, &intermediate_class); |
| 67 g_window_class = RegisterClassEx(&intermediate_class); | 77 g_window_class = RegisterClassEx(&intermediate_class); |
| 68 if (!g_window_class) { | 78 if (!g_window_class) { |
| 69 LOG(ERROR) << "RegisterClass failed."; | 79 LOG(ERROR) << "RegisterClass failed."; |
| 70 return; | 80 return; |
| 71 } | 81 } |
| 72 } | 82 } |
| 83 | |
| 84 void CreateChildWindow(HWND parent, | |
|
stanisc
2016/08/04 02:03:35
It would be good to indicate in comments which thr
jbauman
2016/08/04 20:45:51
Done.
| |
| 85 base::WaitableEvent* event, | |
| 86 SharedData* shared_data, | |
|
stanisc
2016/08/04 02:03:35
Should this be const pointer?
jbauman
2016/08/04 20:45:51
No, SetWindowUserData takes a non-const pointer.
| |
| 87 HWND* result) { | |
| 88 InitializeWindowClass(); | |
| 89 DCHECK(g_window_class); | |
| 90 | |
| 91 RECT windowRect; | |
| 92 GetClientRect(parent, &windowRect); | |
| 93 | |
| 94 HWND window = CreateWindowEx( | |
| 95 WS_EX_NOPARENTNOTIFY, reinterpret_cast<wchar_t*>(g_window_class), L"", | |
| 96 WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE, 0, 0, | |
| 97 windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, | |
| 98 ui::GetHiddenWindow(), NULL, NULL, NULL); | |
| 99 *result = window; | |
| 100 gfx::SetWindowUserData(window, shared_data); | |
| 101 event->Signal(); | |
| 102 } | |
| 103 | |
| 104 void DestroySharedData(std::unique_ptr<SharedData> shared_data) { | |
| 105 shared_data->thread.Stop(); | |
| 106 } | |
| 107 | |
| 108 void DestroyWindowOnThread(HWND window) { | |
| 109 DestroyWindow(window); | |
| 110 } | |
| 73 } | 111 } |
|
stanisc
2016/08/04 02:03:35
Add // namespace
jbauman
2016/08/04 20:45:51
Done.
| |
| 74 | 112 |
| 75 ChildWindowSurfaceWin::ChildWindowSurfaceWin(GpuChannelManager* manager, | 113 ChildWindowSurfaceWin::ChildWindowSurfaceWin(GpuChannelManager* manager, |
| 76 HWND parent_window) | 114 HWND parent_window) |
| 77 : gl::NativeViewGLSurfaceEGL(0), | 115 : gl::NativeViewGLSurfaceEGL(0), |
| 78 parent_window_(parent_window), | 116 parent_window_(parent_window), |
| 79 manager_(manager), | 117 manager_(manager), |
| 80 alpha_(true), | 118 alpha_(true), |
| 81 first_swap_(true) { | 119 first_swap_(true) { |
| 82 // Don't use EGL_ANGLE_window_fixed_size so that we can avoid recreating the | 120 // Don't use EGL_ANGLE_window_fixed_size so that we can avoid recreating the |
| 83 // window surface, which can cause flicker on DirectComposition. | 121 // window surface, which can cause flicker on DirectComposition. |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 110 return NULL; | 148 return NULL; |
| 111 } | 149 } |
| 112 } | 150 } |
| 113 | 151 |
| 114 return config_; | 152 return config_; |
| 115 } | 153 } |
| 116 | 154 |
| 117 bool ChildWindowSurfaceWin::InitializeNativeWindow() { | 155 bool ChildWindowSurfaceWin::InitializeNativeWindow() { |
| 118 if (window_) | 156 if (window_) |
| 119 return true; | 157 return true; |
| 120 InitializeWindowClass(); | |
| 121 DCHECK(g_window_class); | |
| 122 | 158 |
| 123 RECT windowRect; | 159 shared_data_ = base::MakeUnique<SharedData>(); |
| 124 GetClientRect(parent_window_, &windowRect); | |
| 125 | 160 |
| 126 window_ = CreateWindowEx( | 161 base::Thread::Options options(base::MessageLoop::TYPE_UI, 0); |
| 127 WS_EX_NOPARENTNOTIFY, reinterpret_cast<wchar_t*>(g_window_class), L"", | 162 shared_data_->thread.StartWithOptions(options); |
| 128 WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE, 0, 0, | 163 |
| 129 windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, | 164 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| 130 ui::GetHiddenWindow(), NULL, NULL, NULL); | 165 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 131 gfx::SetWindowUserData(window_, this); | 166 shared_data_->thread.task_runner()->PostTask( |
| 167 FROM_HERE, base::Bind(&CreateChildWindow, parent_window_, &event, | |
| 168 shared_data_.get(), &window_)); | |
| 169 event.Wait(); | |
| 170 | |
| 132 manager_->delegate()->SendAcceleratedSurfaceCreatedChildWindow(parent_window_, | 171 manager_->delegate()->SendAcceleratedSurfaceCreatedChildWindow(parent_window_, |
| 133 window_); | 172 window_); |
| 134 return true; | 173 return true; |
| 135 } | 174 } |
| 136 | 175 |
| 137 bool ChildWindowSurfaceWin::Resize(const gfx::Size& size, | 176 bool ChildWindowSurfaceWin::Resize(const gfx::Size& size, |
| 138 float scale_factor, | 177 float scale_factor, |
| 139 bool has_alpha) { | 178 bool has_alpha) { |
| 140 if (!SupportsPostSubBuffer()) { | 179 if (!SupportsPostSubBuffer()) { |
| 141 if (!MoveWindow(window_, 0, 0, size.width(), size.height(), FALSE)) { | 180 if (!MoveWindow(window_, 0, 0, size.width(), size.height(), FALSE)) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 198 gfx::SwapResult ChildWindowSurfaceWin::PostSubBuffer(int x, | 237 gfx::SwapResult ChildWindowSurfaceWin::PostSubBuffer(int x, |
| 199 int y, | 238 int y, |
| 200 int width, | 239 int width, |
| 201 int height) { | 240 int height) { |
| 202 gfx::SwapResult result = | 241 gfx::SwapResult result = |
| 203 NativeViewGLSurfaceEGL::PostSubBuffer(x, y, width, height); | 242 NativeViewGLSurfaceEGL::PostSubBuffer(x, y, width, height); |
| 204 ClearInvalidContents(); | 243 ClearInvalidContents(); |
| 205 return result; | 244 return result; |
| 206 } | 245 } |
| 207 | 246 |
| 208 void ChildWindowSurfaceWin::InvalidateWindowRect(const gfx::Rect& rect) { | |
| 209 rect_to_clear_.Union(rect); | |
| 210 } | |
| 211 | |
| 212 void ChildWindowSurfaceWin::ClearInvalidContents() { | 247 void ChildWindowSurfaceWin::ClearInvalidContents() { |
| 213 if (!rect_to_clear_.IsEmpty()) { | 248 base::AutoLock lock(shared_data_->rect_lock); |
| 249 if (!shared_data_->rect_to_clear.IsEmpty()) { | |
| 214 base::win::ScopedGetDC dc(window_); | 250 base::win::ScopedGetDC dc(window_); |
|
stanisc
2016/08/04 02:03:35
Is this running on the main thread?
Is it safe to
jbauman
2016/08/04 20:45:51
Yeah, it's fine to do GetDC on any thread (or even
| |
| 215 | 251 |
| 216 RECT rect = rect_to_clear_.ToRECT(); | 252 RECT rect = shared_data_->rect_to_clear.ToRECT(); |
| 217 | 253 |
| 218 // DirectComposition composites with the contents under the SwapChain, | 254 // DirectComposition composites with the contents under the SwapChain, |
| 219 // so ensure that's cleared. GDI treats black as transparent. | 255 // so ensure that's cleared. GDI treats black as transparent. |
| 220 FillRect(dc, &rect, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH))); | 256 FillRect(dc, &rect, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH))); |
| 221 rect_to_clear_ = gfx::Rect(); | 257 shared_data_->rect_to_clear = gfx::Rect(); |
| 222 } | 258 } |
| 223 } | 259 } |
| 224 | 260 |
| 225 ChildWindowSurfaceWin::~ChildWindowSurfaceWin() { | 261 ChildWindowSurfaceWin::~ChildWindowSurfaceWin() { |
| 226 gfx::SetWindowUserData(window_, nullptr); | 262 if (shared_data_) { |
| 227 DestroyWindow(window_); | 263 scoped_refptr<base::TaskRunner> task_runner = |
| 264 shared_data_->thread.task_runner(); | |
| 265 task_runner->PostTaskAndReply( | |
| 266 FROM_HERE, base::Bind(&DestroyWindowOnThread, window_), | |
| 267 base::Bind(&DestroySharedData, base::Passed(std::move(shared_data_)))); | |
|
stanisc
2016/08/04 02:03:35
Clever solution!
| |
| 268 } | |
| 228 } | 269 } |
| 229 | 270 |
| 230 } // namespace gpu | 271 } // namespace gpu |
| OLD | NEW |