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

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

Issue 2926763002: Split DirectCompositionSurfaceWin into two parts. (Closed)
Patch Set: add disallow copy and assign Created 3 years, 6 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
(Empty)
1 // Copyright 2017 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/direct_composition_child_surface_win.h"
6
7 #include <d3d11_1.h>
8 #include <dcomptypes.h>
9
10 #include "base/memory/ptr_util.h"
11 #include "base/metrics/histogram_macros.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/trace_event/trace_event.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_angle_util_win.h"
18 #include "ui/gl/gl_context.h"
19 #include "ui/gl/gl_surface_egl.h"
20 #include "ui/gl/scoped_make_current.h"
21
22 #ifndef EGL_ANGLE_flexible_surface_compatibility
23 #define EGL_ANGLE_flexible_surface_compatibility 1
24 #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
25 #endif /* EGL_ANGLE_flexible_surface_compatibility */
26
27 #ifndef EGL_ANGLE_d3d_texture_client_buffer
28 #define EGL_ANGLE_d3d_texture_client_buffer 1
29 #define EGL_D3D_TEXTURE_ANGLE 0x33A3
30 #endif /* EGL_ANGLE_d3d_texture_client_buffer */
31
32 namespace gpu {
33
34 namespace {
35 // Only one DirectComposition surface can be rendered into at a time. Track
36 // here which IDCompositionSurface is being rendered into. If another context
37 // is made current, then this surface will be suspended.
38 IDCompositionSurface* g_current_surface;
39 }
40
41 DirectCompositionChildSurfaceWin::DirectCompositionChildSurfaceWin(
42 const gfx::Size& size,
43 bool has_alpha,
44 bool enable_dc_layers)
45 : gl::GLSurfaceEGL(),
46 size_(size),
47 has_alpha_(has_alpha),
48 enable_dc_layers_(enable_dc_layers) {}
49
50 DirectCompositionChildSurfaceWin::~DirectCompositionChildSurfaceWin() {
51 Destroy();
52 }
53
54 bool DirectCompositionChildSurfaceWin::Initialize(gl::GLSurfaceFormat format) {
55 d3d11_device_ = gl::QueryD3D11DeviceObjectFromANGLE();
56 dcomp_device_ = gl::QueryDirectCompositionDevice(d3d11_device_);
57 if (!dcomp_device_)
58 return false;
59
60 EGLDisplay display = GetDisplay();
61
62 std::vector<EGLint> pbuffer_attribs;
63 pbuffer_attribs.push_back(EGL_WIDTH);
64 pbuffer_attribs.push_back(1);
65 pbuffer_attribs.push_back(EGL_HEIGHT);
66 pbuffer_attribs.push_back(1);
67
68 pbuffer_attribs.push_back(EGL_NONE);
69 default_surface_ =
70 eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]);
71 CHECK(!!default_surface_);
72
73 return true;
74 }
75
76 void DirectCompositionChildSurfaceWin::ReleaseCurrentSurface() {
77 ReleaseDrawTexture(true);
78 dcomp_surface_.Reset();
79 swap_chain_.Reset();
80 }
81
82 void DirectCompositionChildSurfaceWin::InitializeSurface() {
83 TRACE_EVENT1("gpu", "DirectCompositionChildSurfaceWin::InitializeSurface()",
84 "enable_dc_layers_", enable_dc_layers_);
85 DCHECK(!dcomp_surface_);
86 DCHECK(!swap_chain_);
87 DXGI_FORMAT output_format =
88 base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableHDR)
89 ? DXGI_FORMAT_R16G16B16A16_FLOAT
90 : DXGI_FORMAT_B8G8R8A8_UNORM;
91 if (enable_dc_layers_) {
92 // Always treat as premultiplied, because an underlay could cause it to
93 // become transparent.
94 HRESULT hr = dcomp_device_->CreateSurface(
95 size_.width(), size_.height(), output_format,
96 DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.GetAddressOf());
97 has_been_rendered_to_ = false;
98 CHECK(SUCCEEDED(hr));
99 } else {
100 DXGI_ALPHA_MODE alpha_mode =
101 has_alpha_ ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE;
102 base::win::ScopedComPtr<IDXGIDevice> dxgi_device;
103 d3d11_device_.CopyTo(dxgi_device.GetAddressOf());
104 base::win::ScopedComPtr<IDXGIAdapter> dxgi_adapter;
105 dxgi_device->GetAdapter(dxgi_adapter.GetAddressOf());
106 base::win::ScopedComPtr<IDXGIFactory2> dxgi_factory;
107 dxgi_adapter->GetParent(IID_PPV_ARGS(dxgi_factory.GetAddressOf()));
108
109 DXGI_SWAP_CHAIN_DESC1 desc = {};
110 desc.Width = size_.width();
111 desc.Height = size_.height();
112 desc.Format = output_format;
113 desc.Stereo = FALSE;
114 desc.SampleDesc.Count = 1;
115 desc.BufferCount = 2;
116 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
117 desc.Scaling = DXGI_SCALING_STRETCH;
118 desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
119 desc.AlphaMode = alpha_mode;
120 desc.Flags = 0;
121 HRESULT hr = dxgi_factory->CreateSwapChainForComposition(
122 d3d11_device_.Get(), &desc, nullptr, swap_chain_.GetAddressOf());
123 has_been_rendered_to_ = false;
124 first_swap_ = true;
125 CHECK(SUCCEEDED(hr));
126 }
127 }
128
129 void DirectCompositionChildSurfaceWin::ReleaseDrawTexture(bool will_discard) {
130 if (real_surface_) {
131 eglDestroySurface(GetDisplay(), real_surface_);
132 real_surface_ = nullptr;
133 }
134 if (draw_texture_) {
135 draw_texture_.Reset();
136 if (dcomp_surface_) {
137 HRESULT hr = dcomp_surface_->EndDraw();
138 CHECK(SUCCEEDED(hr));
139 } else if (!will_discard) {
140 DXGI_PRESENT_PARAMETERS params = {};
141 RECT dirty_rect = swap_rect_.ToRECT();
142 params.DirtyRectsCount = 1;
143 params.pDirtyRects = &dirty_rect;
144 swap_chain_->Present1(first_swap_ ? 0 : 1, 0, &params);
145 if (first_swap_) {
146 // Wait for the GPU to finish executing its commands before
147 // committing the DirectComposition tree, or else the swapchain
148 // may flicker black when it's first presented.
149 base::win::ScopedComPtr<IDXGIDevice2> dxgi_device2;
150 HRESULT hr = d3d11_device_.CopyTo(dxgi_device2.GetAddressOf());
151 DCHECK(SUCCEEDED(hr));
152 base::WaitableEvent event(
153 base::WaitableEvent::ResetPolicy::AUTOMATIC,
154 base::WaitableEvent::InitialState::NOT_SIGNALED);
155 dxgi_device2->EnqueueSetEvent(event.handle());
156 event.Wait();
157 first_swap_ = false;
158 }
159 }
160 }
161 if (dcomp_surface_ == g_current_surface)
162 g_current_surface = nullptr;
163 }
164
165 void DirectCompositionChildSurfaceWin::Destroy() {
166 if (default_surface_) {
167 if (!eglDestroySurface(GetDisplay(), default_surface_)) {
168 DLOG(ERROR) << "eglDestroySurface failed with error "
169 << ui::GetLastEGLErrorString();
170 }
171 default_surface_ = nullptr;
172 }
173 if (real_surface_) {
174 if (!eglDestroySurface(GetDisplay(), real_surface_)) {
175 DLOG(ERROR) << "eglDestroySurface failed with error "
176 << ui::GetLastEGLErrorString();
177 }
178 real_surface_ = nullptr;
179 }
180 if (dcomp_surface_ && (dcomp_surface_ == g_current_surface)) {
181 HRESULT hr = dcomp_surface_->EndDraw();
182 CHECK(SUCCEEDED(hr));
183 g_current_surface = nullptr;
184 }
185 draw_texture_.Reset();
186 dcomp_surface_.Reset();
187 }
188
189 gfx::Size DirectCompositionChildSurfaceWin::GetSize() {
190 return size_;
191 }
192
193 bool DirectCompositionChildSurfaceWin::IsOffscreen() {
194 return false;
195 }
196
197 void* DirectCompositionChildSurfaceWin::GetHandle() {
198 return real_surface_ ? real_surface_ : default_surface_;
199 }
200
201 gfx::SwapResult DirectCompositionChildSurfaceWin::SwapBuffers() {
202 ReleaseDrawTexture(false);
203 return gfx::SwapResult::SWAP_ACK;
204 }
205
206 bool DirectCompositionChildSurfaceWin::FlipsVertically() const {
207 return true;
208 }
209
210 bool DirectCompositionChildSurfaceWin::SupportsPostSubBuffer() {
211 return true;
212 }
213
214 bool DirectCompositionChildSurfaceWin::OnMakeCurrent(gl::GLContext* context) {
215 if (g_current_surface != dcomp_surface_) {
216 if (g_current_surface) {
217 HRESULT hr = g_current_surface->SuspendDraw();
218 CHECK(SUCCEEDED(hr));
219 g_current_surface = nullptr;
220 }
221 if (draw_texture_) {
222 HRESULT hr = dcomp_surface_->ResumeDraw();
223 CHECK(SUCCEEDED(hr));
224 g_current_surface = dcomp_surface_.Get();
225 }
226 }
227 return true;
228 }
229
230 bool DirectCompositionChildSurfaceWin::SupportsDCLayers() const {
231 return true;
232 }
233
234 bool DirectCompositionChildSurfaceWin::SetDrawRectangle(
235 const gfx::Rect& rectangle) {
236 if (draw_texture_)
237 return false;
238 DCHECK(!real_surface_);
239 ui::ScopedReleaseCurrent release_current(this);
240
241 if ((enable_dc_layers_ && !dcomp_surface_) ||
242 (!enable_dc_layers_ && !swap_chain_)) {
243 ReleaseCurrentSurface();
244 InitializeSurface();
245 }
246
247 if (!gfx::Rect(size_).Contains(rectangle)) {
248 DLOG(ERROR) << "Draw rectangle must be contained within size of surface";
249 return false;
250 }
251 if (gfx::Rect(size_) != rectangle && !has_been_rendered_to_) {
252 DLOG(ERROR) << "First draw to surface must draw to everything";
253 return false;
254 }
255
256 CHECK(!g_current_surface);
257
258 RECT rect = rectangle.ToRECT();
259 if (dcomp_surface_) {
260 POINT update_offset;
261 HRESULT hr = dcomp_surface_->BeginDraw(
262 &rect, IID_PPV_ARGS(draw_texture_.GetAddressOf()), &update_offset);
263 draw_offset_ = gfx::Point(update_offset) - gfx::Rect(rect).origin();
264 CHECK(SUCCEEDED(hr));
265 } else {
266 HRESULT hr =
267 swap_chain_->GetBuffer(0, IID_PPV_ARGS(draw_texture_.GetAddressOf()));
268 swap_rect_ = rectangle;
269 draw_offset_ = gfx::Vector2d();
270 CHECK(SUCCEEDED(hr));
271 }
272 has_been_rendered_to_ = true;
273
274 g_current_surface = dcomp_surface_.Get();
275
276 std::vector<EGLint> pbuffer_attribs{
277 EGL_WIDTH,
278 size_.width(),
279 EGL_HEIGHT,
280 size_.height(),
281 EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE,
282 EGL_TRUE,
283 EGL_NONE};
284
285 EGLClientBuffer buffer =
286 reinterpret_cast<EGLClientBuffer>(draw_texture_.Get());
287 real_surface_ = eglCreatePbufferFromClientBuffer(
288 GetDisplay(), EGL_D3D_TEXTURE_ANGLE, buffer, GetConfig(),
289 &pbuffer_attribs[0]);
290
291 return true;
292 }
293
294 gfx::Vector2d DirectCompositionChildSurfaceWin::GetDrawOffset() const {
295 return draw_offset_;
296 }
297
298 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/ipc/service/direct_composition_child_surface_win.h ('k') | gpu/ipc/service/direct_composition_surface_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698