Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(785)

Side by Side Diff: gpu/ipc/service/child_window_surface_win.cc

Issue 2623763003: Split out ChildWindowWin (Closed)
Patch Set: initialize window_ Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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" 10 #include "base/memory/ptr_util.h"
11 #include "base/threading/thread.h"
12 #include "base/win/scoped_hdc.h"
13 #include "base/win/wrapped_window_proc.h"
14 #include "gpu/ipc/common/gpu_messages.h" 11 #include "gpu/ipc/common/gpu_messages.h"
15 #include "gpu/ipc/service/gpu_channel_manager.h" 12 #include "gpu/ipc/service/gpu_channel_manager.h"
16 #include "gpu/ipc/service/gpu_channel_manager_delegate.h" 13 #include "gpu/ipc/service/gpu_channel_manager_delegate.h"
17 #include "ui/gfx/native_widget_types.h" 14 #include "ui/gfx/native_widget_types.h"
18 #include "ui/gfx/win/hwnd_util.h"
19 #include "ui/gfx/win/window_impl.h"
20 #include "ui/gl/egl_util.h" 15 #include "ui/gl/egl_util.h"
21 #include "ui/gl/gl_context.h" 16 #include "ui/gl/gl_context.h"
22 #include "ui/gl/gl_surface_egl.h" 17 #include "ui/gl/gl_surface_egl.h"
23 #include "ui/gl/scoped_make_current.h" 18 #include "ui/gl/scoped_make_current.h"
24 19
25 namespace gpu { 20 namespace gpu {
26 21
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
37 namespace {
38
39 ATOM g_window_class;
40
41 // This runs on the window owner thread.
42 LRESULT CALLBACK IntermediateWindowProc(HWND window,
43 UINT message,
44 WPARAM w_param,
45 LPARAM l_param) {
46 switch (message) {
47 case WM_ERASEBKGND:
48 // Prevent windows from erasing the background.
49 return 1;
50 case WM_PAINT:
51 PAINTSTRUCT paint;
52 if (BeginPaint(window, &paint)) {
53 SharedData* shared_data =
54 reinterpret_cast<SharedData*>(gfx::GetWindowUserData(window));
55 DCHECK(shared_data);
56 {
57 base::AutoLock lock(shared_data->rect_lock);
58 shared_data->rect_to_clear.Union(gfx::Rect(paint.rcPaint));
59 }
60
61 EndPaint(window, &paint);
62 }
63 return 0;
64 default:
65 return DefWindowProc(window, message, w_param, l_param);
66 }
67 }
68
69 // This runs on the window owner thread.
70 void InitializeWindowClass() {
71 if (g_window_class)
72 return;
73
74 WNDCLASSEX intermediate_class;
75 base::win::InitializeWindowClass(
76 L"Intermediate D3D Window",
77 &base::win::WrappedWindowProc<IntermediateWindowProc>, CS_OWNDC, 0, 0,
78 nullptr, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)), nullptr,
79 nullptr, nullptr, &intermediate_class);
80 g_window_class = RegisterClassEx(&intermediate_class);
81 if (!g_window_class) {
82 LOG(ERROR) << "RegisterClass failed.";
83 return;
84 }
85 }
86
87 // Hidden popup window used as a parent for the child surface window.
88 // Must be created and destroyed on the thread.
89 class HiddenPopupWindow : public gfx::WindowImpl {
90 public:
91 static HWND Create() {
92 gfx::WindowImpl* window = new HiddenPopupWindow;
93
94 window->set_window_style(WS_POPUP);
95 window->set_window_ex_style(WS_EX_TOOLWINDOW);
96 window->Init(GetDesktopWindow(), gfx::Rect());
97 EnableWindow(window->hwnd(), FALSE);
98 // The |window| instance is now owned by the window user data.
99 DCHECK_EQ(window, gfx::GetWindowUserData(window->hwnd()));
100 return window->hwnd();
101 }
102
103 static void Destroy(HWND window) {
104 // This uses the fact that the window user data contains a pointer
105 // to gfx::WindowImpl instance.
106 gfx::WindowImpl* window_data =
107 reinterpret_cast<gfx::WindowImpl*>(gfx::GetWindowUserData(window));
108 DCHECK_EQ(window, window_data->hwnd());
109 DestroyWindow(window);
110 delete window_data;
111 }
112
113 private:
114 // Explicitly do nothing in Close. We do this as some external apps may get a
115 // handle to this window and attempt to close it.
116 void OnClose() {}
117
118 CR_BEGIN_MSG_MAP_EX(HiddenPopupWindow)
119 CR_MSG_WM_CLOSE(OnClose)
120 CR_END_MSG_MAP()
121 };
122
123 // This runs on the window owner thread.
124 void CreateWindowsOnThread(const gfx::Size& size,
125 base::WaitableEvent* event,
126 SharedData* shared_data,
127 HWND* child_window,
128 HWND* parent_window) {
129 InitializeWindowClass();
130 DCHECK(g_window_class);
131
132 // Create hidden parent window on the current thread.
133 *parent_window = HiddenPopupWindow::Create();
134 // Create child window.
135 HWND window = CreateWindowEx(
136 WS_EX_NOPARENTNOTIFY, reinterpret_cast<wchar_t*>(g_window_class), L"",
137 WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE, 0, 0, size.width(),
138 size.height(), *parent_window, NULL, NULL, NULL);
139 CHECK(window);
140 *child_window = window;
141 gfx::SetWindowUserData(window, shared_data);
142 event->Signal();
143 }
144
145 // This runs on the main thread after the window was destroyed on window owner
146 // thread.
147 void DestroySharedData(std::unique_ptr<SharedData> shared_data) {
148 shared_data->thread.Stop();
149 }
150
151 // This runs on the window owner thread.
152 void DestroyWindowsOnThread(HWND child_window, HWND hidden_popup_window) {
153 DestroyWindow(child_window);
154 HiddenPopupWindow::Destroy(hidden_popup_window);
155 }
156
157 } // namespace
158
159 ChildWindowSurfaceWin::ChildWindowSurfaceWin( 22 ChildWindowSurfaceWin::ChildWindowSurfaceWin(
160 base::WeakPtr<ImageTransportSurfaceDelegate> delegate, 23 base::WeakPtr<ImageTransportSurfaceDelegate> delegate,
161 HWND parent_window) 24 HWND parent_window)
162 : gl::NativeViewGLSurfaceEGL(0), 25 : gl::NativeViewGLSurfaceEGL(0),
163 parent_window_(parent_window), 26 child_window_(delegate, parent_window),
164 delegate_(delegate),
165 alpha_(true), 27 alpha_(true),
166 first_swap_(true) { 28 first_swap_(true) {
167 // Don't use EGL_ANGLE_window_fixed_size so that we can avoid recreating the 29 // Don't use EGL_ANGLE_window_fixed_size so that we can avoid recreating the
168 // window surface, which can cause flicker on DirectComposition. 30 // window surface, which can cause flicker on DirectComposition.
169 enable_fixed_size_angle_ = false; 31 enable_fixed_size_angle_ = false;
170 } 32 }
171 33
172 EGLConfig ChildWindowSurfaceWin::GetConfig() { 34 EGLConfig ChildWindowSurfaceWin::GetConfig() {
173 if (!config_) { 35 if (!config_) {
174 int alpha_size = alpha_ ? 8 : EGL_DONT_CARE; 36 int alpha_size = alpha_ ? 8 : EGL_DONT_CARE;
(...skipping 21 matching lines...) Expand all
196 } 58 }
197 } 59 }
198 60
199 return config_; 61 return config_;
200 } 62 }
201 63
202 bool ChildWindowSurfaceWin::InitializeNativeWindow() { 64 bool ChildWindowSurfaceWin::InitializeNativeWindow() {
203 if (window_) 65 if (window_)
204 return true; 66 return true;
205 67
206 shared_data_ = base::MakeUnique<SharedData>(); 68 bool result = child_window_.Initialize();
207 69 window_ = child_window_.window();
stanisc 2017/01/10 20:54:57 Could you just use child_window_.window() instead
208 base::Thread::Options options(base::MessageLoop::TYPE_UI, 0); 70 return result;
209 shared_data_->thread.StartWithOptions(options);
210
211 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
212 base::WaitableEvent::InitialState::NOT_SIGNALED);
213
214 RECT window_rect;
215 GetClientRect(parent_window_, &window_rect);
216
217 shared_data_->thread.task_runner()->PostTask(
218 FROM_HERE,
219 base::Bind(&CreateWindowsOnThread, gfx::Rect(window_rect).size(), &event,
220 shared_data_.get(), &window_, &initial_parent_window_));
221 event.Wait();
222
223 delegate_->DidCreateAcceleratedSurfaceChildWindow(parent_window_, window_);
224 return true;
225 } 71 }
226 72
227 bool ChildWindowSurfaceWin::Resize(const gfx::Size& size, 73 bool ChildWindowSurfaceWin::Resize(const gfx::Size& size,
228 float scale_factor, 74 float scale_factor,
229 bool has_alpha) { 75 bool has_alpha) {
230 if (!SupportsPostSubBuffer()) { 76 if (!SupportsPostSubBuffer()) {
231 if (!MoveWindow(window_, 0, 0, size.width(), size.height(), FALSE)) { 77 if (!MoveWindow(window_, 0, 0, size.width(), size.height(), FALSE)) {
232 return false; 78 return false;
233 } 79 }
234 alpha_ = has_alpha; 80 alpha_ = has_alpha;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 120
275 gfx::SwapResult ChildWindowSurfaceWin::SwapBuffers() { 121 gfx::SwapResult ChildWindowSurfaceWin::SwapBuffers() {
276 gfx::SwapResult result = NativeViewGLSurfaceEGL::SwapBuffers(); 122 gfx::SwapResult result = NativeViewGLSurfaceEGL::SwapBuffers();
277 // Force the driver to finish drawing before clearing the contents to 123 // Force the driver to finish drawing before clearing the contents to
278 // transparent, to reduce or eliminate the period of time where the contents 124 // transparent, to reduce or eliminate the period of time where the contents
279 // have flashed black. 125 // have flashed black.
280 if (first_swap_) { 126 if (first_swap_) {
281 glFinish(); 127 glFinish();
282 first_swap_ = false; 128 first_swap_ = false;
283 } 129 }
284 ClearInvalidContents(); 130 child_window_.ClearInvalidContents();
285 return result; 131 return result;
286 } 132 }
287 133
288 gfx::SwapResult ChildWindowSurfaceWin::PostSubBuffer(int x, 134 gfx::SwapResult ChildWindowSurfaceWin::PostSubBuffer(int x,
289 int y, 135 int y,
290 int width, 136 int width,
291 int height) { 137 int height) {
292 gfx::SwapResult result = 138 gfx::SwapResult result =
293 NativeViewGLSurfaceEGL::PostSubBuffer(x, y, width, height); 139 NativeViewGLSurfaceEGL::PostSubBuffer(x, y, width, height);
294 ClearInvalidContents(); 140 child_window_.ClearInvalidContents();
295 return result; 141 return result;
296 } 142 }
297 143
298 void ChildWindowSurfaceWin::ClearInvalidContents() {
299 base::AutoLock lock(shared_data_->rect_lock);
300 if (!shared_data_->rect_to_clear.IsEmpty()) {
301 base::win::ScopedGetDC dc(window_);
302
303 RECT rect = shared_data_->rect_to_clear.ToRECT();
304
305 // DirectComposition composites with the contents under the SwapChain,
306 // so ensure that's cleared. GDI treats black as transparent.
307 FillRect(dc, &rect, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
308 shared_data_->rect_to_clear = gfx::Rect();
309 }
310 }
311
312 ChildWindowSurfaceWin::~ChildWindowSurfaceWin() { 144 ChildWindowSurfaceWin::~ChildWindowSurfaceWin() {
313 if (shared_data_) {
314 scoped_refptr<base::TaskRunner> task_runner =
315 shared_data_->thread.task_runner();
316 task_runner->PostTaskAndReply(
317 FROM_HERE,
318 base::Bind(&DestroyWindowsOnThread, window_, initial_parent_window_),
319 base::Bind(&DestroySharedData, base::Passed(std::move(shared_data_))));
320 }
321 } 145 }
322 146
323 } // namespace gpu 147 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698