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

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

Issue 2646243002: Use IDCompositionSurface to implement DirectCompositionSurfaceWin. (Closed)
Patch Set: more changes 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 2017 The Chromium Authors. All rights reserved. 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 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/direct_composition_surface_win.h" 5 #include "gpu/ipc/service/direct_composition_surface_win.h"
6 6
7 #include "base/optional.h"
7 #include "gpu/ipc/service/gpu_channel_manager.h" 8 #include "gpu/ipc/service/gpu_channel_manager.h"
8 #include "gpu/ipc/service/gpu_channel_manager_delegate.h" 9 #include "gpu/ipc/service/gpu_channel_manager_delegate.h"
9 #include "ui/gfx/native_widget_types.h" 10 #include "ui/gfx/native_widget_types.h"
10 #include "ui/gl/egl_util.h" 11 #include "ui/gl/egl_util.h"
12 #include "ui/gl/gl_angle_util_win.h"
11 #include "ui/gl/gl_context.h" 13 #include "ui/gl/gl_context.h"
12 #include "ui/gl/gl_surface_egl.h" 14 #include "ui/gl/gl_surface_egl.h"
15 #include "ui/gl/scoped_make_current.h"
16
17 #ifndef EGL_ANGLE_flexible_surface_compatibility
18 #define EGL_ANGLE_flexible_surface_compatibility 1
19 #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
20 #endif /* EGL_ANGLE_flexible_surface_compatibility */
21
22 #ifndef EGL_ANGLE_d3d_texture_client_buffer
23 #define EGL_ANGLE_d3d_texture_client_buffer 1
24 #define EGL_D3D_TEXTURE_ANGLE 0x33A3
25 #endif /* EGL_ANGLE_d3d_texture_client_buffer */
13 26
14 namespace gpu { 27 namespace gpu {
28 namespace {
29
30 // This class is used to make sure a specified surface isn't current, and upon
31 // destruction it will make the surface current again if it had been before.
32 class ScopedReleaseCurrent {
33 public:
34 explicit ScopedReleaseCurrent(gl::GLSurface* this_surface) {
35 gl::GLContext* current_context = gl::GLContext::GetCurrent();
36 bool was_current =
37 current_context && current_context->IsCurrent(this_surface);
sunnyps 2017/01/28 01:33:59 nit: DCHECK(current_context->IsCurrent(this_surfac
38 if (was_current) {
39 make_current_.emplace(current_context, this_surface);
40 current_context->ReleaseCurrent(this_surface);
41 }
42 }
43
44 private:
45 base::Optional<ui::ScopedMakeCurrent> make_current_;
46 };
47
48 // Only one DirectComposition surface can be rendered into at a time. Track
49 // here which IDCompositionSurface is being rendered into. If another context
50 // is made current, then this surface will be suspended.
51 IDCompositionSurface* g_current_surface;
52
53 } // namespace
15 54
16 DirectCompositionSurfaceWin::DirectCompositionSurfaceWin( 55 DirectCompositionSurfaceWin::DirectCompositionSurfaceWin(
17 base::WeakPtr<ImageTransportSurfaceDelegate> delegate, 56 base::WeakPtr<ImageTransportSurfaceDelegate> delegate,
18 HWND parent_window) 57 HWND parent_window)
19 : gl::GLSurfaceEGL(), 58 : gl::GLSurfaceEGL(),
20 child_window_(delegate, parent_window), 59 child_window_(delegate, parent_window),
21 window_(nullptr), 60 window_(nullptr),
22 surface_(0), 61 default_surface_(0),
62 real_surface_(0),
63 size_(1, 1),
23 first_swap_(true) {} 64 first_swap_(true) {}
24 65
25 bool DirectCompositionSurfaceWin::InitializeNativeWindow() { 66 bool DirectCompositionSurfaceWin::InitializeNativeWindow() {
26 if (window_) 67 if (window_)
27 return true; 68 return true;
28 69
29 bool result = child_window_.Initialize(); 70 bool result = child_window_.Initialize();
30 window_ = child_window_.window(); 71 window_ = child_window_.window();
31 return result; 72 return result;
32 } 73 }
33 74
34 bool DirectCompositionSurfaceWin::Initialize(gl::GLSurfaceFormat format) { 75 bool DirectCompositionSurfaceWin::Initialize(gl::GLSurfaceFormat format) {
76 d3d11_device_ = gl::QueryD3D11DeviceObjectFromANGLE();
77 dcomp_device_ = gl::QueryDirectCompositionDevice(d3d11_device_);
78 if (!dcomp_device_)
79 return false;
80
35 EGLDisplay display = GetDisplay(); 81 EGLDisplay display = GetDisplay();
36 if (!window_) { 82 if (!window_) {
37 if (!InitializeNativeWindow()) { 83 if (!InitializeNativeWindow()) {
38 LOG(ERROR) << "Failed to initialize native window"; 84 LOG(ERROR) << "Failed to initialize native window";
39 return false; 85 return false;
40 } 86 }
41 } 87 }
88
89 base::win::ScopedComPtr<IDCompositionDesktopDevice> desktop_device;
90 dcomp_device_.QueryInterface(desktop_device.Receive());
91
92 HRESULT hr = desktop_device->CreateTargetForHwnd(window_, TRUE,
93 dcomp_target_.Receive());
94 if (FAILED(hr))
95 return false;
96
97 hr = dcomp_device_->CreateVisual(visual_.Receive());
98 if (FAILED(hr))
99 return false;
100
101 dcomp_target_->SetRoot(visual_.get());
102
42 std::vector<EGLint> pbuffer_attribs; 103 std::vector<EGLint> pbuffer_attribs;
43 pbuffer_attribs.push_back(EGL_WIDTH); 104 pbuffer_attribs.push_back(EGL_WIDTH);
44 pbuffer_attribs.push_back(1); 105 pbuffer_attribs.push_back(1);
45 pbuffer_attribs.push_back(EGL_HEIGHT); 106 pbuffer_attribs.push_back(EGL_HEIGHT);
46 pbuffer_attribs.push_back(1); 107 pbuffer_attribs.push_back(1);
47 108
48 pbuffer_attribs.push_back(EGL_NONE); 109 pbuffer_attribs.push_back(EGL_NONE);
49 surface_ = eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]); 110 default_surface_ =
50 CHECK(!!surface_); 111 eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]);
112 CHECK(!!default_surface_);
113
114 InitializeSurface();
51 115
52 return true; 116 return true;
53 } 117 }
54 118
55 void DirectCompositionSurfaceWin::Destroy() { 119 void DirectCompositionSurfaceWin::Destroy() {
56 if (surface_) { 120 if (default_surface_) {
57 if (!eglDestroySurface(GetDisplay(), surface_)) { 121 if (!eglDestroySurface(GetDisplay(), default_surface_)) {
58 LOG(ERROR) << "eglDestroySurface failed with error " 122 LOG(ERROR) << "eglDestroySurface failed with error "
59 << ui::GetLastEGLErrorString(); 123 << ui::GetLastEGLErrorString();
60 } 124 }
61 surface_ = NULL; 125 default_surface_ = NULL;
62 } 126 }
127 if (real_surface_) {
128 if (!eglDestroySurface(GetDisplay(), real_surface_)) {
129 LOG(ERROR) << "eglDestroySurface failed with error "
130 << ui::GetLastEGLErrorString();
131 }
132 real_surface_ = NULL;
133 }
134 if (dcomp_surface_ == g_current_surface)
135 g_current_surface = nullptr;
136 draw_texture_.Release();
137 dcomp_surface_.Release();
63 } 138 }
64 139
65 gfx::Size DirectCompositionSurfaceWin::GetSize() { 140 gfx::Size DirectCompositionSurfaceWin::GetSize() {
66 return size_; 141 return size_;
67 } 142 }
68 143
69 bool DirectCompositionSurfaceWin::IsOffscreen() { 144 bool DirectCompositionSurfaceWin::IsOffscreen() {
70 return false; 145 return false;
71 } 146 }
72 147
73 void* DirectCompositionSurfaceWin::GetHandle() { 148 void* DirectCompositionSurfaceWin::GetHandle() {
74 return surface_; 149 return real_surface_ ? real_surface_ : default_surface_;
75 } 150 }
76 151
77 bool DirectCompositionSurfaceWin::Resize(const gfx::Size& size, 152 bool DirectCompositionSurfaceWin::Resize(const gfx::Size& size,
78 float scale_factor, 153 float scale_factor,
79 bool has_alpha) { 154 bool has_alpha) {
80 if (size == GetSize()) 155 if (size == GetSize())
81 return true; 156 return true;
82 157
83 // Force a resize and redraw (but not a move, activate, etc.). 158 // Force a resize and redraw (but not a move, activate, etc.).
84 if (!SetWindowPos(window_, nullptr, 0, 0, size.width(), size.height(), 159 if (!SetWindowPos(window_, nullptr, 0, 0, size.width(), size.height(),
85 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS | 160 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS |
86 SWP_NOOWNERZORDER | SWP_NOZORDER)) { 161 SWP_NOOWNERZORDER | SWP_NOZORDER)) {
87 return false; 162 return false;
88 } 163 }
89 size_ = size; 164 size_ = size;
165 InitializeSurface();
166
90 return true; 167 return true;
91 } 168 }
92 169
93 gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() { 170 gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() {
94 CommitAndClearPendingOverlays(); 171 {
172 ScopedReleaseCurrent release_current(this);
173 ReleaseDrawTexture();
174 visual_->SetContent(dcomp_surface_.get());
175
176 CommitAndClearPendingOverlays();
177 dcomp_device_->Commit();
178 }
95 // Force the driver to finish drawing before clearing the contents to 179 // Force the driver to finish drawing before clearing the contents to
96 // transparent, to reduce or eliminate the period of time where the contents 180 // transparent, to reduce or eliminate the period of time where the contents
97 // have flashed black. 181 // have flashed black.
98 if (first_swap_) { 182 if (first_swap_) {
99 glFinish(); 183 glFinish();
100 first_swap_ = false; 184 first_swap_ = false;
101 } 185 }
102 child_window_.ClearInvalidContents(); 186 child_window_.ClearInvalidContents();
103 return gfx::SwapResult::SWAP_ACK; 187 return gfx::SwapResult::SWAP_ACK;
104 } 188 }
105 189
106 gfx::SwapResult DirectCompositionSurfaceWin::PostSubBuffer(int x, 190 gfx::SwapResult DirectCompositionSurfaceWin::PostSubBuffer(int x,
107 int y, 191 int y,
108 int width, 192 int width,
109 int height) { 193 int height) {
194 ScopedReleaseCurrent release_current(this);
195 ReleaseDrawTexture();
196 visual_->SetContent(dcomp_surface_.get());
110 CommitAndClearPendingOverlays(); 197 CommitAndClearPendingOverlays();
198 dcomp_device_->Commit();
111 child_window_.ClearInvalidContents(); 199 child_window_.ClearInvalidContents();
112 return gfx::SwapResult::SWAP_ACK; 200 return gfx::SwapResult::SWAP_ACK;
113 } 201 }
114 202
115 gfx::VSyncProvider* DirectCompositionSurfaceWin::GetVSyncProvider() { 203 gfx::VSyncProvider* DirectCompositionSurfaceWin::GetVSyncProvider() {
116 return vsync_provider_.get(); 204 return vsync_provider_.get();
117 } 205 }
118 206
119 bool DirectCompositionSurfaceWin::Initialize( 207 bool DirectCompositionSurfaceWin::Initialize(
120 std::unique_ptr<gfx::VSyncProvider> vsync_provider) { 208 std::unique_ptr<gfx::VSyncProvider> vsync_provider) {
121 vsync_provider_ = std::move(vsync_provider); 209 vsync_provider_ = std::move(vsync_provider);
122 return Initialize(gl::GLSurfaceFormat()); 210 return Initialize(gl::GLSurfaceFormat());
123 } 211 }
124 212
125 bool DirectCompositionSurfaceWin::ScheduleOverlayPlane( 213 bool DirectCompositionSurfaceWin::ScheduleOverlayPlane(
126 int z_order, 214 int z_order,
127 gfx::OverlayTransform transform, 215 gfx::OverlayTransform transform,
128 gl::GLImage* image, 216 gl::GLImage* image,
129 const gfx::Rect& bounds_rect, 217 const gfx::Rect& bounds_rect,
130 const gfx::RectF& crop_rect) { 218 const gfx::RectF& crop_rect) {
131 pending_overlays_.push_back( 219 pending_overlays_.push_back(
132 Overlay(z_order, transform, image, bounds_rect, crop_rect)); 220 Overlay(z_order, transform, image, bounds_rect, crop_rect));
133 return true; 221 return true;
134 } 222 }
135 223
224 bool DirectCompositionSurfaceWin::FlipsVertically() const {
225 return true;
226 }
227
136 bool DirectCompositionSurfaceWin::SupportsPostSubBuffer() { 228 bool DirectCompositionSurfaceWin::SupportsPostSubBuffer() {
137 return true; 229 return true;
138 } 230 }
139 231
232 bool DirectCompositionSurfaceWin::OnMakeCurrent(gl::GLContext* context) {
233 if (g_current_surface != dcomp_surface_) {
234 if (g_current_surface) {
235 HRESULT hr = g_current_surface->SuspendDraw();
236 CHECK(SUCCEEDED(hr));
237 g_current_surface = nullptr;
238 }
239 if (draw_texture_) {
240 HRESULT hr = dcomp_surface_->ResumeDraw();
241 CHECK(SUCCEEDED(hr));
242 g_current_surface = dcomp_surface_.get();
243 }
244 }
245 return true;
246 }
247
248 bool DirectCompositionSurfaceWin::SupportsSetDrawRectangle() const {
249 return true;
250 }
251
252 bool DirectCompositionSurfaceWin::SetDrawRectangle(const gfx::Rect& rectangle) {
253 if (draw_texture_)
254 return false;
255 if (!gfx::Rect(size_).Contains(rectangle)) {
256 LOG(ERROR) << "Draw rectangle must be contained within size of surface";
257 return false;
258 }
259 if (gfx::Rect(size_) != rectangle && !has_been_rendered_to_) {
260 LOG(ERROR) << "First draw to surface must draw to everything";
261 return false;
262 }
263
264 DCHECK(!real_surface_);
265 CHECK(!g_current_surface);
266 ScopedReleaseCurrent release_current(this);
267
268 RECT rect = rectangle.ToRECT();
269 // TODO(jbauman): Use update_offset
270 POINT update_offset;
271
272 HRESULT hr = dcomp_surface_->BeginDraw(
273 &rect, IID_PPV_ARGS(draw_texture_.Receive()), &update_offset);
274 CHECK(SUCCEEDED(hr));
275 has_been_rendered_to_ = true;
276
277 g_current_surface = dcomp_surface_.get();
278
279 std::vector<EGLint> pbuffer_attribs;
280 pbuffer_attribs.push_back(EGL_WIDTH);
281 pbuffer_attribs.push_back(size_.width());
282 pbuffer_attribs.push_back(EGL_HEIGHT);
283 pbuffer_attribs.push_back(size_.height());
284 pbuffer_attribs.push_back(EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE);
285 pbuffer_attribs.push_back(EGL_TRUE);
286 pbuffer_attribs.push_back(EGL_NONE);
287
288 EGLClientBuffer buffer =
289 reinterpret_cast<EGLClientBuffer>(draw_texture_.get());
290 real_surface_ = eglCreatePbufferFromClientBuffer(
291 GetDisplay(), EGL_D3D_TEXTURE_ANGLE, buffer, GetConfig(),
292 &pbuffer_attribs[0]);
293
294 return true;
295 }
296
140 DirectCompositionSurfaceWin::Overlay::Overlay(int z_order, 297 DirectCompositionSurfaceWin::Overlay::Overlay(int z_order,
141 gfx::OverlayTransform transform, 298 gfx::OverlayTransform transform,
142 scoped_refptr<gl::GLImage> image, 299 scoped_refptr<gl::GLImage> image,
143 gfx::Rect bounds_rect, 300 gfx::Rect bounds_rect,
144 gfx::RectF crop_rect) 301 gfx::RectF crop_rect)
145 : z_order(z_order), 302 : z_order(z_order),
146 transform(transform), 303 transform(transform),
147 image(image), 304 image(image),
148 bounds_rect(bounds_rect), 305 bounds_rect(bounds_rect),
149 crop_rect(crop_rect) {} 306 crop_rect(crop_rect) {}
150 307
151 DirectCompositionSurfaceWin::Overlay::Overlay(const Overlay& overlay) = default; 308 DirectCompositionSurfaceWin::Overlay::Overlay(const Overlay& overlay) = default;
152 309
153 DirectCompositionSurfaceWin::Overlay::~Overlay() {} 310 DirectCompositionSurfaceWin::Overlay::~Overlay() {}
154 311
155 bool DirectCompositionSurfaceWin::CommitAndClearPendingOverlays() { 312 bool DirectCompositionSurfaceWin::CommitAndClearPendingOverlays() {
sunnyps 2017/01/28 01:33:58 nit: Can you move this next to ScheduleOverlayPlan
156 pending_overlays_.clear(); 313 pending_overlays_.clear();
157 return true; 314 return true;
158 } 315 }
159 316
160 DirectCompositionSurfaceWin::~DirectCompositionSurfaceWin() {} 317 void DirectCompositionSurfaceWin::InitializeSurface() {
sunnyps 2017/01/28 01:33:59 nit: can you move this and ReleaseDrawTexture next
318 ScopedReleaseCurrent release_current(this);
319 ReleaseDrawTexture();
320 dcomp_surface_.Release();
321 HRESULT hr = dcomp_device_->CreateSurface(
322 size_.width(), size_.height(), DXGI_FORMAT_B8G8R8A8_UNORM,
323 DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.Receive());
324 has_been_rendered_to_ = false;
325
326 CHECK(SUCCEEDED(hr));
327 }
328
329 void DirectCompositionSurfaceWin::ReleaseDrawTexture() {
330 if (real_surface_) {
331 eglDestroySurface(GetDisplay(), real_surface_);
332 real_surface_ = nullptr;
333 }
334 if (draw_texture_) {
335 draw_texture_.Release();
336 HRESULT hr = dcomp_surface_->EndDraw();
337 CHECK(SUCCEEDED(hr));
338 }
339 if (dcomp_surface_ == g_current_surface)
340 g_current_surface = nullptr;
341 }
342
343 DirectCompositionSurfaceWin::~DirectCompositionSurfaceWin() {
sunnyps 2017/01/28 01:33:59 nit: can you move this next to the ctor?
344 Destroy();
345 }
161 346
162 } // namespace gpu 347 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698