OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "gpu/ipc/service/child_window_surface_win.h" | |
6 | |
7 #include <memory> | |
8 | |
9 #include "base/compiler_specific.h" | |
10 #include "base/memory/ptr_util.h" | |
11 #include "gpu/ipc/common/gpu_messages.h" | |
12 #include "gpu/ipc/service/gpu_channel_manager.h" | |
13 #include "gpu/ipc/service/gpu_channel_manager_delegate.h" | |
14 #include "ui/display/display_switches.h" | |
15 #include "ui/gfx/native_widget_types.h" | |
16 #include "ui/gl/egl_util.h" | |
17 #include "ui/gl/gl_context.h" | |
18 #include "ui/gl/gl_surface_egl.h" | |
19 #include "ui/gl/scoped_make_current.h" | |
20 | |
21 namespace gpu { | |
22 | |
23 ChildWindowSurfaceWin::ChildWindowSurfaceWin( | |
24 std::unique_ptr<gfx::VSyncProvider> vsync_provider, | |
25 base::WeakPtr<ImageTransportSurfaceDelegate> delegate, | |
26 HWND parent_window) | |
27 : gl::NativeViewGLSurfaceEGL(0, std::move(vsync_provider)), | |
28 child_window_(delegate, parent_window), | |
29 alpha_(true), | |
30 first_swap_(true) { | |
31 // Don't use EGL_ANGLE_window_fixed_size so that we can avoid recreating the | |
32 // window surface, which can cause flicker on DirectComposition. | |
33 enable_fixed_size_angle_ = false; | |
34 } | |
35 | |
36 EGLConfig ChildWindowSurfaceWin::GetConfig() { | |
37 if (!config_) { | |
38 int alpha_size = alpha_ ? 8 : EGL_DONT_CARE; | |
39 int bits_per_channel = | |
40 base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableHDR) | |
41 ? 16 | |
42 : 8; | |
43 | |
44 EGLint config_attribs[] = {EGL_ALPHA_SIZE, | |
45 alpha_size, | |
46 EGL_BLUE_SIZE, | |
47 bits_per_channel, | |
48 EGL_GREEN_SIZE, | |
49 bits_per_channel, | |
50 EGL_RED_SIZE, | |
51 bits_per_channel, | |
52 EGL_RENDERABLE_TYPE, | |
53 EGL_OPENGL_ES2_BIT, | |
54 EGL_SURFACE_TYPE, | |
55 EGL_WINDOW_BIT | EGL_PBUFFER_BIT, | |
56 EGL_NONE}; | |
57 | |
58 EGLDisplay display = GetHardwareDisplay(); | |
59 EGLint num_configs; | |
60 if (!eglChooseConfig(display, config_attribs, NULL, 0, &num_configs)) { | |
61 LOG(ERROR) << "eglChooseConfig failed with error " | |
62 << ui::GetLastEGLErrorString(); | |
63 return NULL; | |
64 } | |
65 std::vector<EGLConfig> configs(num_configs); | |
66 if (!eglChooseConfig(display, config_attribs, configs.data(), num_configs, | |
67 &num_configs)) { | |
68 LOG(ERROR) << "eglChooseConfig failed with error " | |
69 << ui::GetLastEGLErrorString(); | |
70 return NULL; | |
71 } | |
72 config_ = configs[0]; | |
73 for (int i = 0; i < num_configs; i++) { | |
74 EGLint red_bits; | |
75 eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &red_bits); | |
76 // Try to pick a configuration with the right number of bits rather | |
77 // than one that just has enough bits. | |
78 if (red_bits == bits_per_channel) { | |
79 config_ = configs[i]; | |
80 break; | |
81 } | |
82 } | |
83 } | |
84 | |
85 return config_; | |
86 } | |
87 | |
88 bool ChildWindowSurfaceWin::InitializeNativeWindow() { | |
89 if (window_) | |
90 return true; | |
91 | |
92 bool result = child_window_.Initialize(); | |
93 window_ = child_window_.window(); | |
94 return result; | |
95 } | |
96 | |
97 bool ChildWindowSurfaceWin::Resize(const gfx::Size& size, | |
98 float scale_factor, | |
99 bool has_alpha) { | |
100 if (!SupportsPostSubBuffer()) { | |
101 if (!MoveWindow(window_, 0, 0, size.width(), size.height(), FALSE)) { | |
102 return false; | |
103 } | |
104 alpha_ = has_alpha; | |
105 return gl::NativeViewGLSurfaceEGL::Resize(size, scale_factor, has_alpha); | |
106 } else { | |
107 if (size == GetSize() && has_alpha == alpha_) | |
108 return true; | |
109 | |
110 // Force a resize and redraw (but not a move, activate, etc.). | |
111 if (!SetWindowPos(window_, nullptr, 0, 0, size.width(), size.height(), | |
112 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS | | |
113 SWP_NOOWNERZORDER | SWP_NOZORDER)) { | |
114 return false; | |
115 } | |
116 size_ = size; | |
117 if (has_alpha == alpha_) { | |
118 // A 0-size PostSubBuffer doesn't swap but forces the swap chain to resize | |
119 // to match the window. | |
120 PostSubBuffer(0, 0, 0, 0); | |
121 } else { | |
122 alpha_ = has_alpha; | |
123 config_ = nullptr; | |
124 | |
125 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current; | |
126 gl::GLContext* current_context = gl::GLContext::GetCurrent(); | |
127 bool was_current = current_context && current_context->IsCurrent(this); | |
128 if (was_current) { | |
129 scoped_make_current.reset( | |
130 new ui::ScopedMakeCurrent(current_context, this)); | |
131 current_context->ReleaseCurrent(this); | |
132 } | |
133 | |
134 Destroy(); | |
135 | |
136 if (!Initialize()) { | |
137 LOG(ERROR) << "Failed to resize window."; | |
138 return false; | |
139 } | |
140 } | |
141 return true; | |
142 } | |
143 } | |
144 | |
145 gfx::SwapResult ChildWindowSurfaceWin::SwapBuffers() { | |
146 gfx::SwapResult result = NativeViewGLSurfaceEGL::SwapBuffers(); | |
147 // Force the driver to finish drawing before clearing the contents to | |
148 // transparent, to reduce or eliminate the period of time where the contents | |
149 // have flashed black. | |
150 if (first_swap_) { | |
151 glFinish(); | |
152 first_swap_ = false; | |
153 } | |
154 child_window_.ClearInvalidContents(); | |
155 return result; | |
156 } | |
157 | |
158 gfx::SwapResult ChildWindowSurfaceWin::PostSubBuffer(int x, | |
159 int y, | |
160 int width, | |
161 int height) { | |
162 gfx::SwapResult result = | |
163 NativeViewGLSurfaceEGL::PostSubBuffer(x, y, width, height); | |
164 child_window_.ClearInvalidContents(); | |
165 return result; | |
166 } | |
167 | |
168 void ChildWindowSurfaceWin::WaitForSnapshotRendering() { | |
169 DCHECK(gl::GLContext::GetCurrent()->IsCurrent(this)); | |
170 glFinish(); | |
171 } | |
172 | |
173 ChildWindowSurfaceWin::~ChildWindowSurfaceWin() { | |
174 } | |
175 | |
176 } // namespace gpu | |
OLD | NEW |