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

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

Issue 2749023011: Add DirectComposition overlay support. (Closed)
Patch Set: post-review changes Created 3 years, 8 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 <d3d11_1.h>
8 #include <dcomptypes.h>
9
10 #include "base/memory/ptr_util.h"
7 #include "base/optional.h" 11 #include "base/optional.h"
8 #include "base/synchronization/waitable_event.h" 12 #include "base/synchronization/waitable_event.h"
13 #include "base/trace_event/trace_event.h"
14 #include "base/win/scoped_handle.h"
9 #include "gpu/ipc/service/gpu_channel_manager.h" 15 #include "gpu/ipc/service/gpu_channel_manager.h"
10 #include "gpu/ipc/service/gpu_channel_manager_delegate.h" 16 #include "gpu/ipc/service/gpu_channel_manager_delegate.h"
11 #include "gpu/ipc/service/switches.h" 17 #include "gpu/ipc/service/switches.h"
12 #include "ui/display/display_switches.h" 18 #include "ui/display/display_switches.h"
19 #include "ui/gfx/geometry/size_conversions.h"
13 #include "ui/gfx/native_widget_types.h" 20 #include "ui/gfx/native_widget_types.h"
21 #include "ui/gfx/transform.h"
22 #include "ui/gl/dc_renderer_layer_params.h"
14 #include "ui/gl/egl_util.h" 23 #include "ui/gl/egl_util.h"
15 #include "ui/gl/gl_angle_util_win.h" 24 #include "ui/gl/gl_angle_util_win.h"
16 #include "ui/gl/gl_context.h" 25 #include "ui/gl/gl_context.h"
26 #include "ui/gl/gl_image_dxgi.h"
17 #include "ui/gl/gl_surface_egl.h" 27 #include "ui/gl/gl_surface_egl.h"
18 #include "ui/gl/scoped_make_current.h" 28 #include "ui/gl/scoped_make_current.h"
19 29
20 #ifndef EGL_ANGLE_flexible_surface_compatibility 30 #ifndef EGL_ANGLE_flexible_surface_compatibility
21 #define EGL_ANGLE_flexible_surface_compatibility 1 31 #define EGL_ANGLE_flexible_surface_compatibility 1
22 #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6 32 #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
23 #endif /* EGL_ANGLE_flexible_surface_compatibility */ 33 #endif /* EGL_ANGLE_flexible_surface_compatibility */
24 34
25 #ifndef EGL_ANGLE_d3d_texture_client_buffer 35 #ifndef EGL_ANGLE_d3d_texture_client_buffer
26 #define EGL_ANGLE_d3d_texture_client_buffer 1 36 #define EGL_ANGLE_d3d_texture_client_buffer 1
(...skipping 14 matching lines...) Expand all
41 if (was_current) { 51 if (was_current) {
42 make_current_.emplace(current_context, this_surface); 52 make_current_.emplace(current_context, this_surface);
43 current_context->ReleaseCurrent(this_surface); 53 current_context->ReleaseCurrent(this_surface);
44 } 54 }
45 } 55 }
46 56
47 private: 57 private:
48 base::Optional<ui::ScopedMakeCurrent> make_current_; 58 base::Optional<ui::ScopedMakeCurrent> make_current_;
49 }; 59 };
50 60
61 bool SizeContains(const gfx::Size& a, const gfx::Size& b) {
62 return gfx::Rect(a).Contains(gfx::Rect(b));
63 }
64
51 // Only one DirectComposition surface can be rendered into at a time. Track 65 // Only one DirectComposition surface can be rendered into at a time. Track
52 // here which IDCompositionSurface is being rendered into. If another context 66 // here which IDCompositionSurface is being rendered into. If another context
53 // is made current, then this surface will be suspended. 67 // is made current, then this surface will be suspended.
54 IDCompositionSurface* g_current_surface; 68 IDCompositionSurface* g_current_surface;
55 69
56 } // namespace 70 } // namespace
57 71
72 class DCLayerTree {
73 public:
74 DCLayerTree(DirectCompositionSurfaceWin* surface,
75 const base::win::ScopedComPtr<ID3D11Device>& d3d11_device,
76 const base::win::ScopedComPtr<IDCompositionDevice2>& dcomp_device)
77 : surface_(surface),
78 d3d11_device_(d3d11_device),
79 dcomp_device_(dcomp_device) {}
80
81 bool Initialize(HWND window);
82 bool CommitAndClearPendingOverlays();
83 bool ScheduleDCLayer(const ui::DCRendererLayerParams& params);
84 void InitializeVideoProcessor(const gfx::Size& input_size,
85 const gfx::Size& output_size);
86
87 const base::win::ScopedComPtr<ID3D11VideoProcessor>& video_processor() const {
88 return video_processor_;
89 }
90 const base::win::ScopedComPtr<ID3D11VideoProcessorEnumerator>&
91 video_processor_enumerator() const {
92 return video_processor_enumerator_;
93 }
94
95 private:
96 class SwapChainPresenter;
97
98 // This struct is used to cache information about what visuals are currently
99 // being presented so that properties that aren't changed aren't sent to
100 // DirectComposition.
101 struct VisualInfo {
102 base::win::ScopedComPtr<IDCompositionVisual2> content_visual;
103 base::win::ScopedComPtr<IDCompositionVisual2> clip_visual;
104
105 std::unique_ptr<SwapChainPresenter> swap_chain_presenter;
106 base::win::ScopedComPtr<IDXGISwapChain1> swap_chain;
107 base::win::ScopedComPtr<IDCompositionSurface> surface;
108
109 gfx::Rect bounds;
110 float swap_chain_scale_x = 0.0f;
111 float swap_chain_scale_y = 0.0f;
112 bool is_clipped = false;
113 gfx::Rect clip_rect;
114 gfx::Transform transform;
115 };
116
117 void InitVisual(size_t i);
118 void UpdateVisualForVideo(VisualInfo* visual_info,
119 const ui::DCRendererLayerParams& params);
120 void UpdateVisualForBackbuffer(VisualInfo* visual_info,
121 const ui::DCRendererLayerParams& params);
122 void UpdateVisualClip(VisualInfo* visual_info,
123 const ui::DCRendererLayerParams& params);
124
125 DirectCompositionSurfaceWin* surface_;
126 std::vector<std::unique_ptr<ui::DCRendererLayerParams>> pending_overlays_;
127
128 base::win::ScopedComPtr<ID3D11Device> d3d11_device_;
129 base::win::ScopedComPtr<IDCompositionDevice2> dcomp_device_;
130 base::win::ScopedComPtr<IDCompositionTarget> dcomp_target_;
131 base::win::ScopedComPtr<IDCompositionVisual2> root_visual_;
132
133 // The video processor is cached so SwapChains don't have to recreate it
134 // whenever they're created.
135 base::win::ScopedComPtr<ID3D11VideoDevice> video_device_;
136 base::win::ScopedComPtr<ID3D11VideoContext> video_context_;
137 base::win::ScopedComPtr<ID3D11VideoProcessor> video_processor_;
138 base::win::ScopedComPtr<ID3D11VideoProcessorEnumerator>
139 video_processor_enumerator_;
140 gfx::Size video_input_size_;
141 gfx::Size video_output_size_;
142
143 std::vector<VisualInfo> visual_info_;
144
145 DISALLOW_COPY_AND_ASSIGN(DCLayerTree);
146 };
147
148 class DCLayerTree::SwapChainPresenter {
149 public:
150 SwapChainPresenter(DCLayerTree* surface,
151 base::win::ScopedComPtr<ID3D11Device> d3d11_device);
152
153 ~SwapChainPresenter();
154
155 void PresentToSwapChain(const ui::DCRendererLayerParams& overlay);
156
157 float swap_chain_scale_x() const { return swap_chain_scale_x_; }
158 float swap_chain_scale_y() const { return swap_chain_scale_y_; }
159 const base::win::ScopedComPtr<IDXGISwapChain1>& swap_chain() const {
160 return swap_chain_;
161 }
162
163 private:
164 using PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE =
165 HRESULT(WINAPI*)(DWORD, SECURITY_ATTRIBUTES*, HANDLE*);
166
167 // Returns true if the video processor changed.
168 bool InitializeVideoProcessor(const gfx::Size& in_size,
169 const gfx::Size& out_size);
170 void ReallocateSwapChain();
171
172 DCLayerTree* surface_;
173 PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE create_surface_handle_function_;
174
175 gfx::Size swap_chain_size_;
176 gfx::Size processor_input_size_;
177 gfx::Size processor_output_size_;
178
179 // This is the scale from the swapchain size to the size of the contents
180 // onscreen.
181 float swap_chain_scale_x_ = 0.0f;
182 float swap_chain_scale_y_ = 0.0f;
183
184 base::win::ScopedComPtr<ID3D11Device> d3d11_device_;
185 base::win::ScopedComPtr<IDXGISwapChain1> swap_chain_;
186 base::win::ScopedComPtr<ID3D11VideoProcessorOutputView> out_view_;
187 base::win::ScopedComPtr<ID3D11VideoProcessor> video_processor_;
188 base::win::ScopedComPtr<ID3D11VideoProcessorEnumerator>
189 video_processor_enumerator_;
190 base::win::ScopedComPtr<ID3D11VideoDevice> video_device_;
191 base::win::ScopedComPtr<ID3D11VideoContext> video_context_;
192
193 base::win::ScopedHandle swap_chain_handle_;
194
195 DISALLOW_COPY_AND_ASSIGN(SwapChainPresenter);
196 };
197
198 bool DCLayerTree::Initialize(HWND window) {
199 d3d11_device_.QueryInterface(video_device_.Receive());
200 base::win::ScopedComPtr<ID3D11DeviceContext> context;
201 d3d11_device_->GetImmediateContext(context.Receive());
202 context.QueryInterface(video_context_.Receive());
203
204 base::win::ScopedComPtr<IDCompositionDesktopDevice> desktop_device;
205 dcomp_device_.QueryInterface(desktop_device.Receive());
206
207 HRESULT hr = desktop_device->CreateTargetForHwnd(window, TRUE,
208 dcomp_target_.Receive());
209 if (FAILED(hr))
210 return false;
211
212 hr = dcomp_device_->CreateVisual(root_visual_.Receive());
213 if (FAILED(hr))
214 return false;
215
216 dcomp_target_->SetRoot(root_visual_.get());
217 return true;
218 }
219
220 void DCLayerTree::InitializeVideoProcessor(const gfx::Size& input_size,
221 const gfx::Size& output_size) {
222 if (SizeContains(video_input_size_, input_size) &&
223 SizeContains(video_output_size_, output_size))
224 return;
225 video_input_size_ = input_size;
226 video_output_size_ = output_size;
227
228 video_processor_.Release();
229 video_processor_enumerator_.Receive();
230 D3D11_VIDEO_PROCESSOR_CONTENT_DESC desc = {};
231 desc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
232 desc.InputFrameRate.Numerator = 60;
233 desc.InputFrameRate.Denominator = 1;
234 desc.InputWidth = input_size.width();
235 desc.InputHeight = input_size.height();
236 desc.OutputFrameRate.Numerator = 60;
237 desc.OutputFrameRate.Denominator = 1;
238 desc.OutputWidth = output_size.width();
239 desc.OutputHeight = output_size.height();
240 desc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;
241 HRESULT hr = video_device_->CreateVideoProcessorEnumerator(
242 &desc, video_processor_enumerator_.Receive());
243 CHECK(SUCCEEDED(hr));
244
245 hr = video_device_->CreateVideoProcessor(video_processor_enumerator_.get(), 0,
246 video_processor_.Receive());
247 CHECK(SUCCEEDED(hr));
248 }
249
250 DCLayerTree::SwapChainPresenter::SwapChainPresenter(
251 DCLayerTree* surface,
252 base::win::ScopedComPtr<ID3D11Device> d3d11_device)
253 : surface_(surface), d3d11_device_(d3d11_device) {
254 d3d11_device_.QueryInterface(video_device_.Receive());
255 base::win::ScopedComPtr<ID3D11DeviceContext> context;
256 d3d11_device_->GetImmediateContext(context.Receive());
257 context.QueryInterface(video_context_.Receive());
258 HMODULE dcomp = ::GetModuleHandleA("dcomp.dll");
259 CHECK(dcomp);
260 create_surface_handle_function_ =
261 reinterpret_cast<PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE>(
262 GetProcAddress(dcomp, "DCompositionCreateSurfaceHandle"));
263 DCHECK(create_surface_handle_function_);
sunnyps 2017/03/28 23:05:02 nit: should this also be a CHECK?
264 }
265
266 DCLayerTree::SwapChainPresenter::~SwapChainPresenter() {}
267
268 void DCLayerTree::SwapChainPresenter::PresentToSwapChain(
269 const ui::DCRendererLayerParams& params) {
270 gl::GLImageDXGI* image_dxgi =
271 gl::GLImageDXGI::FromGLImage(params.image.get());
272 DCHECK(image_dxgi);
273
274 // Swap chain size is the minimum of the on-screen size and the source
275 // size so the video processor can do the minimal amount of work and
276 // the overlay has to read the minimal amount of data.
277 // DWM is also less likely to promote a surface to an overlay if it's
278 // much larger than its area on-screen.
279 gfx::Rect bounds_rect = params.rect;
280 gfx::Size ceiled_input_size = gfx::ToCeiledSize(params.contents_rect.size());
281 gfx::Size swap_chain_size = bounds_rect.size();
282 swap_chain_size.SetToMin(ceiled_input_size);
283
284 // YUY2 surfaces must have an even width.
285 if (swap_chain_size.width() % 2 == 1)
286 swap_chain_size.set_width(swap_chain_size.width() + 1);
287
288 InitializeVideoProcessor(ceiled_input_size, swap_chain_size);
289
290 bool first_present = false;
291 if (!swap_chain_ || swap_chain_size_ != swap_chain_size) {
292 first_present = true;
293 swap_chain_size_ = swap_chain_size;
294 swap_chain_.Release();
295 ReallocateSwapChain();
296 }
297
298 if (!out_view_) {
299 base::win::ScopedComPtr<ID3D11Texture2D> texture;
300 swap_chain_->GetBuffer(0, IID_PPV_ARGS(texture.Receive()));
301 D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC out_desc = {};
302 out_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
303 out_desc.Texture2D.MipSlice = 0;
304 HRESULT hr = video_device_->CreateVideoProcessorOutputView(
305 texture.get(), video_processor_enumerator_.get(), &out_desc,
306 out_view_.Receive());
307 CHECK(SUCCEEDED(hr));
308 }
309 {
310 D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC in_desc = {};
311 in_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
312 in_desc.Texture2D.ArraySlice = (UINT)image_dxgi->level();
313 base::win::ScopedComPtr<ID3D11VideoProcessorInputView> in_view;
314 HRESULT hr = video_device_->CreateVideoProcessorInputView(
315 image_dxgi->texture().get(), video_processor_enumerator_.get(),
316 &in_desc, in_view.Receive());
317 CHECK(SUCCEEDED(hr));
318
319 D3D11_VIDEO_PROCESSOR_STREAM stream = {};
320 stream.Enable = true;
321 stream.OutputIndex = 0;
322 stream.InputFrameOrField = 0;
323 stream.PastFrames = 0;
324 stream.FutureFrames = 0;
325 stream.pInputSurface = in_view.get();
326 RECT dest_rect = gfx::Rect(swap_chain_size).ToRECT();
327 video_context_->VideoProcessorSetOutputTargetRect(video_processor_.get(),
328 TRUE, &dest_rect);
329 video_context_->VideoProcessorSetStreamDestRect(video_processor_.get(), 0,
330 TRUE, &dest_rect);
331 RECT source_rect = gfx::Rect(ceiled_input_size).ToRECT();
332 video_context_->VideoProcessorSetStreamSourceRect(video_processor_.get(), 0,
333 TRUE, &source_rect);
334
335 video_context_->VideoProcessorSetStreamAutoProcessingMode(
336 video_processor_.get(), 0, FALSE);
337
338 hr = video_context_->VideoProcessorBlt(video_processor_.get(),
339 out_view_.get(), 0, 1, &stream);
340 CHECK(SUCCEEDED(hr));
341 }
342
343 swap_chain_scale_x_ = bounds_rect.width() * 1.0f / swap_chain_size.width();
344 swap_chain_scale_y_ = bounds_rect.height() * 1.0f / swap_chain_size.height();
345
346 swap_chain_->Present(first_present ? 0 : 1, 0);
347 }
348
349 bool DCLayerTree::SwapChainPresenter::InitializeVideoProcessor(
350 const gfx::Size& in_size,
351 const gfx::Size& out_size) {
352 if (video_processor_ && SizeContains(processor_input_size_, in_size) &&
353 SizeContains(processor_output_size_, out_size))
354 return false;
355 processor_input_size_ = in_size;
356 processor_output_size_ = out_size;
357 surface_->InitializeVideoProcessor(in_size, out_size);
358
359 video_processor_enumerator_ = surface_->video_processor_enumerator();
360 video_processor_ = surface_->video_processor();
361 // out_view_ depends on video_processor_enumerator_, so ensure it's
362 // recreated if the enumerator is.
363 out_view_.Release();
364 return true;
365 }
366
367 void DCLayerTree::SwapChainPresenter::ReallocateSwapChain() {
368 TRACE_EVENT0("gpu", "DCLayerTree::SwapChainPresenter::ReallocateSwapChain");
369 DCHECK(!swap_chain_);
370
371 base::win::ScopedComPtr<IDXGIDevice> dxgi_device;
372 d3d11_device_.QueryInterface(dxgi_device.Receive());
373 base::win::ScopedComPtr<IDXGIAdapter> dxgi_adapter;
374 dxgi_device->GetAdapter(dxgi_adapter.Receive());
375 base::win::ScopedComPtr<IDXGIFactory2> dxgi_factory;
376 dxgi_adapter->GetParent(IID_PPV_ARGS(dxgi_factory.Receive()));
377
378 base::win::ScopedComPtr<IDXGIFactoryMedia> media_factory;
379 dxgi_factory.QueryInterface(media_factory.Receive());
380 DXGI_SWAP_CHAIN_DESC1 desc = {};
381 desc.Width = swap_chain_size_.width();
382 desc.Height = swap_chain_size_.height();
383 desc.Format = DXGI_FORMAT_YUY2;
384 desc.Stereo = FALSE;
385 desc.SampleDesc.Count = 1;
386 desc.BufferCount = 2;
387 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
388 desc.Scaling = DXGI_SCALING_STRETCH;
389 desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
390 desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
391 desc.Flags =
392 DXGI_SWAP_CHAIN_FLAG_YUV_VIDEO | DXGI_SWAP_CHAIN_FLAG_FULLSCREEN_VIDEO;
393
394 HANDLE handle;
395 create_surface_handle_function_(COMPOSITIONOBJECT_ALL_ACCESS, nullptr,
396 &handle);
397 swap_chain_handle_.Set(handle);
398
399 // The composition surface handle isn't actually used, but
400 // CreateSwapChainForComposition can't create YUY2 swapchains.
401 HRESULT hr = media_factory->CreateSwapChainForCompositionSurfaceHandle(
402 d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr,
403 swap_chain_.Receive());
404
405 if (FAILED(hr)) {
406 // This should not be hit in production but is a simple fallback for
407 // testing on systems without YUY2 swapchain support.
408 DLOG(ERROR) << "YUY2 creation failed with " << std::hex << hr
409 << ". Falling back to BGRA";
410 desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
411 desc.Flags = 0;
412 hr = media_factory->CreateSwapChainForCompositionSurfaceHandle(
413 d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr,
414 swap_chain_.Receive());
415 CHECK(SUCCEEDED(hr));
416 } else {
417 // This is a sensible default colorspace for most videos.
418 // TODO(jbauman): Use correct colorspace.
419 base::win::ScopedComPtr<IDXGISwapChain3> swap_chain3;
420 swap_chain_.QueryInterface(swap_chain3.Receive());
421 hr = swap_chain3->SetColorSpace1(
422 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709);
423 CHECK(SUCCEEDED(hr));
424 }
425 out_view_.Release();
426 }
427
428 void DCLayerTree::InitVisual(size_t i) {
429 DCHECK_GT(visual_info_.size(), i);
430 VisualInfo* visual_info = &visual_info_[i];
431 if (visual_info->content_visual)
432 return;
433 DCHECK(!visual_info->clip_visual);
434 base::win::ScopedComPtr<IDCompositionVisual2> visual;
435 dcomp_device_->CreateVisual(visual_info->clip_visual.Receive());
436 dcomp_device_->CreateVisual(visual.Receive());
437 visual_info->content_visual = visual;
438 visual_info->clip_visual->AddVisual(visual.get(), FALSE, nullptr);
439
440 IDCompositionVisual2* last_visual =
441 (i > 0) ? visual_info_[i - 1].clip_visual.get() : nullptr;
442 root_visual_->AddVisual(visual_info->clip_visual.get(), TRUE, last_visual);
443 }
444
445 void DCLayerTree::UpdateVisualForVideo(
446 VisualInfo* visual_info,
447 const ui::DCRendererLayerParams& params) {
448 base::win::ScopedComPtr<IDCompositionVisual2> dc_visual =
449 visual_info->content_visual;
450
451 gfx::Rect bounds_rect = params.rect;
452 visual_info->surface.Release();
453 if (!visual_info->swap_chain_presenter) {
454 visual_info->swap_chain_presenter =
455 base::MakeUnique<SwapChainPresenter>(this, d3d11_device_);
456 }
457 visual_info->swap_chain_presenter->PresentToSwapChain(params);
458 if (visual_info->swap_chain !=
459 visual_info->swap_chain_presenter->swap_chain()) {
460 visual_info->swap_chain = visual_info->swap_chain_presenter->swap_chain();
461 dc_visual->SetContent(visual_info->swap_chain.get());
462 }
463
464 if (visual_info->swap_chain_presenter->swap_chain_scale_x() !=
465 visual_info->swap_chain_scale_x ||
466 visual_info->swap_chain_presenter->swap_chain_scale_y() !=
467 visual_info->swap_chain_scale_y ||
468 params.transform != visual_info->transform ||
469 visual_info->bounds != bounds_rect) {
470 visual_info->swap_chain_scale_x =
471 visual_info->swap_chain_presenter->swap_chain_scale_x();
472 visual_info->swap_chain_scale_y =
473 visual_info->swap_chain_presenter->swap_chain_scale_y();
474 visual_info->transform = params.transform;
475 visual_info->bounds = bounds_rect;
476
477 gfx::Transform final_transform = params.transform;
478 gfx::Transform scale_transform;
479 scale_transform.Scale(
480 visual_info->swap_chain_presenter->swap_chain_scale_x(),
481 visual_info->swap_chain_presenter->swap_chain_scale_y());
482 final_transform.PreconcatTransform(scale_transform);
483 final_transform.Transpose();
484
485 dc_visual->SetOffsetX(bounds_rect.x());
486 dc_visual->SetOffsetY(bounds_rect.y());
487 base::win::ScopedComPtr<IDCompositionMatrixTransform> dcomp_transform;
488 dcomp_device_->CreateMatrixTransform(dcomp_transform.Receive());
489 D2D_MATRIX_3X2_F d2d_matrix = {{{final_transform.matrix().get(0, 0),
490 final_transform.matrix().get(0, 1),
491 final_transform.matrix().get(1, 0),
492 final_transform.matrix().get(1, 1),
493 final_transform.matrix().get(3, 0),
494 final_transform.matrix().get(3, 1)}}};
495 dcomp_transform->SetMatrix(d2d_matrix);
496 dc_visual->SetTransform(dcomp_transform.get());
497 }
498 }
499
500 void DCLayerTree::UpdateVisualForBackbuffer(
501 VisualInfo* visual_info,
502 const ui::DCRendererLayerParams& params) {
503 base::win::ScopedComPtr<IDCompositionVisual2> dc_visual =
504 visual_info->content_visual;
505
506 visual_info->swap_chain_presenter = nullptr;
507 if ((visual_info->surface != surface_->dcomp_surface()) ||
508 (visual_info->swap_chain != surface_->swap_chain())) {
509 visual_info->surface = surface_->dcomp_surface();
510 visual_info->swap_chain = surface_->swap_chain();
511 if (visual_info->surface) {
512 dc_visual->SetContent(visual_info->surface.get());
513 } else if (visual_info->swap_chain) {
514 dc_visual->SetContent(visual_info->swap_chain.get());
515 } else {
516 dc_visual->SetContent(nullptr);
517 }
518 }
519
520 gfx::Rect bounds_rect = params.rect;
521 if (visual_info->bounds != bounds_rect ||
522 !visual_info->transform.IsIdentity()) {
523 dc_visual->SetOffsetX(bounds_rect.x());
524 dc_visual->SetOffsetY(bounds_rect.y());
525 visual_info->bounds = bounds_rect;
526 dc_visual->SetTransform(nullptr);
527 visual_info->transform = gfx::Transform();
528 }
529 }
530
531 void DCLayerTree::UpdateVisualClip(VisualInfo* visual_info,
532 const ui::DCRendererLayerParams& params) {
533 if (params.is_clipped != visual_info->is_clipped ||
534 params.clip_rect != visual_info->clip_rect) {
535 // DirectComposition clips happen in the pre-transform visual
536 // space, while cc/ clips happen post-transform. So the clip needs
537 // to go on a separate parent visual that's untransformed.
538 visual_info->is_clipped = params.is_clipped;
539 visual_info->clip_rect = params.clip_rect;
540 if (params.is_clipped) {
541 base::win::ScopedComPtr<IDCompositionRectangleClip> clip;
542 dcomp_device_->CreateRectangleClip(clip.Receive());
543 gfx::Rect offset_clip = params.clip_rect;
544 clip->SetLeft(offset_clip.x());
545 clip->SetRight(offset_clip.right());
546 clip->SetBottom(offset_clip.bottom());
547 clip->SetTop(offset_clip.y());
548 visual_info->clip_visual->SetClip(clip.get());
549 } else {
550 visual_info->clip_visual->SetClip(nullptr);
551 }
552 }
553 }
554
555 bool DCLayerTree::CommitAndClearPendingOverlays() {
556 TRACE_EVENT1("gpu", "DCLayerTree::CommitAndClearPendingOverlays", "size",
557 pending_overlays_.size());
558 // Add an overlay with z-order 0 representing the main plane.
559 gfx::Size surface_size = surface_->GetSize();
560 pending_overlays_.push_back(base::MakeUnique<ui::DCRendererLayerParams>(
561 false, gfx::Rect(), 0, gfx::Transform(), nullptr,
562 gfx::RectF(gfx::SizeF(surface_size)), gfx::Rect(surface_size), 0, 0, 1.0,
563 0));
564
565 // TODO(jbauman): Reuse swapchains that are switched between overlays and
566 // underlays.
567 std::sort(pending_overlays_.begin(), pending_overlays_.end(),
568 [](const auto& a, const auto& b) -> bool {
569 return a->z_order < b->z_order;
570 });
571
572 while (visual_info_.size() > pending_overlays_.size()) {
573 visual_info_.back().clip_visual->RemoveAllVisuals();
574 root_visual_->RemoveVisual(visual_info_.back().clip_visual.get());
575 visual_info_.pop_back();
576 }
577
578 visual_info_.resize(pending_overlays_.size());
579
580 // The overall visual tree has one clip visual for every overlay (including
581 // the main plane). The clip visuals are in z_order and are all children of
582 // a root visual. Each clip visual has a child visual that has the actual
583 // plane content.
584
585 for (size_t i = 0; i < pending_overlays_.size(); i++) {
586 ui::DCRendererLayerParams& params = *pending_overlays_[i];
587 VisualInfo* visual_info = &visual_info_[i];
588
589 InitVisual(i);
590 if (params.image &&
591 params.image->GetType() == gl::GLImage::Type::DXGI_IMAGE) {
592 UpdateVisualForVideo(visual_info, params);
593 } else if (!params.image) {
594 UpdateVisualForBackbuffer(visual_info, params);
595 } else {
596 CHECK(false);
597 }
598 UpdateVisualClip(visual_info, params);
599 }
600
601 HRESULT hr = dcomp_device_->Commit();
602 CHECK(SUCCEEDED(hr));
603
604 pending_overlays_.clear();
605 return true;
606 }
607
608 bool DCLayerTree::ScheduleDCLayer(const ui::DCRendererLayerParams& params) {
609 pending_overlays_.push_back(
610 base::MakeUnique<ui::DCRendererLayerParams>(params));
611 return true;
612 }
613
58 DirectCompositionSurfaceWin::DirectCompositionSurfaceWin( 614 DirectCompositionSurfaceWin::DirectCompositionSurfaceWin(
59 base::WeakPtr<ImageTransportSurfaceDelegate> delegate, 615 base::WeakPtr<ImageTransportSurfaceDelegate> delegate,
60 HWND parent_window) 616 HWND parent_window)
61 : gl::GLSurfaceEGL(), child_window_(delegate, parent_window) {} 617 : gl::GLSurfaceEGL(), child_window_(delegate, parent_window) {}
62 618
63 DirectCompositionSurfaceWin::~DirectCompositionSurfaceWin() { 619 DirectCompositionSurfaceWin::~DirectCompositionSurfaceWin() {
64 Destroy(); 620 Destroy();
65 } 621 }
66 622
67 // static 623 // static
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 return false; 680 return false;
125 681
126 EGLDisplay display = GetDisplay(); 682 EGLDisplay display = GetDisplay();
127 if (!window_) { 683 if (!window_) {
128 if (!InitializeNativeWindow()) { 684 if (!InitializeNativeWindow()) {
129 DLOG(ERROR) << "Failed to initialize native window"; 685 DLOG(ERROR) << "Failed to initialize native window";
130 return false; 686 return false;
131 } 687 }
132 } 688 }
133 689
134 base::win::ScopedComPtr<IDCompositionDesktopDevice> desktop_device; 690 layer_tree_ =
135 dcomp_device_.QueryInterface(desktop_device.Receive()); 691 base::MakeUnique<DCLayerTree>(this, d3d11_device_, dcomp_device_);
136 692 if (!layer_tree_->Initialize(window_))
137 HRESULT hr = desktop_device->CreateTargetForHwnd(window_, TRUE,
138 dcomp_target_.Receive());
139 if (FAILED(hr))
140 return false; 693 return false;
141 694
142 hr = dcomp_device_->CreateVisual(visual_.Receive());
143 if (FAILED(hr))
144 return false;
145
146 dcomp_target_->SetRoot(visual_.get());
147
148 std::vector<EGLint> pbuffer_attribs; 695 std::vector<EGLint> pbuffer_attribs;
149 pbuffer_attribs.push_back(EGL_WIDTH); 696 pbuffer_attribs.push_back(EGL_WIDTH);
150 pbuffer_attribs.push_back(1); 697 pbuffer_attribs.push_back(1);
151 pbuffer_attribs.push_back(EGL_HEIGHT); 698 pbuffer_attribs.push_back(EGL_HEIGHT);
152 pbuffer_attribs.push_back(1); 699 pbuffer_attribs.push_back(1);
153 700
154 pbuffer_attribs.push_back(EGL_NONE); 701 pbuffer_attribs.push_back(EGL_NONE);
155 default_surface_ = 702 default_surface_ =
156 eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]); 703 eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]);
157 CHECK(!!default_surface_); 704 CHECK(!!default_surface_);
158 705
159 return true; 706 return true;
160 } 707 }
161 708
162 void DirectCompositionSurfaceWin::ReleaseCurrentSurface() { 709 void DirectCompositionSurfaceWin::ReleaseCurrentSurface() {
163 ReleaseDrawTexture(true); 710 ReleaseDrawTexture(true);
164 dcomp_surface_.Release(); 711 dcomp_surface_.Release();
165 swap_chain_.Release(); 712 swap_chain_.Release();
166 } 713 }
167 714
168 void DirectCompositionSurfaceWin::InitializeSurface() { 715 void DirectCompositionSurfaceWin::InitializeSurface() {
716 TRACE_EVENT1("gpu", "DirectCompositionSurfaceWin::InitializeSurface()",
717 "enable_dc_layers_", enable_dc_layers_);
169 DCHECK(!dcomp_surface_); 718 DCHECK(!dcomp_surface_);
170 DCHECK(!swap_chain_); 719 DCHECK(!swap_chain_);
171 DXGI_FORMAT output_format = 720 DXGI_FORMAT output_format =
172 base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableHDR) 721 base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableHDR)
173 ? DXGI_FORMAT_R16G16B16A16_FLOAT 722 ? DXGI_FORMAT_R16G16B16A16_FLOAT
174 : DXGI_FORMAT_B8G8R8A8_UNORM; 723 : DXGI_FORMAT_B8G8R8A8_UNORM;
175 if (enable_dc_layers_) { 724 if (enable_dc_layers_) {
176 HRESULT hr = dcomp_device_->CreateSurface( 725 HRESULT hr = dcomp_device_->CreateSurface(
177 size_.width(), size_.height(), output_format, 726 size_.width(), size_.height(), output_format,
178 DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.Receive()); 727 DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.Receive());
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 // New surface will be initialized in SetDrawRectangle. 844 // New surface will be initialized in SetDrawRectangle.
296 ReleaseCurrentSurface(); 845 ReleaseCurrentSurface();
297 846
298 return true; 847 return true;
299 } 848 }
300 849
301 gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() { 850 gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() {
302 { 851 {
303 ScopedReleaseCurrent release_current(this); 852 ScopedReleaseCurrent release_current(this);
304 ReleaseDrawTexture(false); 853 ReleaseDrawTexture(false);
305 DCHECK(dcomp_surface_ || swap_chain_);
306 if (dcomp_surface_)
307 visual_->SetContent(dcomp_surface_.get());
308 else
309 visual_->SetContent(swap_chain_.get());
310 854
311 CommitAndClearPendingOverlays(); 855 // This surface's backbuffer doesn't have to be scheduled with
sunnyps 2017/03/28 23:05:02 nit: Can you move this comment to the include file
312 dcomp_device_->Commit(); 856 // ScheduleDCLayer. It's automatically placed in the layer tree at z-order
857 // 0.
858 layer_tree_->CommitAndClearPendingOverlays();
313 } 859 }
314 child_window_.ClearInvalidContents(); 860 child_window_.ClearInvalidContents();
315 return gfx::SwapResult::SWAP_ACK; 861 return gfx::SwapResult::SWAP_ACK;
316 } 862 }
317 863
318 gfx::SwapResult DirectCompositionSurfaceWin::PostSubBuffer(int x, 864 gfx::SwapResult DirectCompositionSurfaceWin::PostSubBuffer(int x,
319 int y, 865 int y,
320 int width, 866 int width,
321 int height) { 867 int height) {
322 // The arguments are ignored because SetDrawRectangle specified the area to 868 // The arguments are ignored because SetDrawRectangle specified the area to
323 // be swapped. 869 // be swapped.
324 return SwapBuffers(); 870 return SwapBuffers();
325 } 871 }
326 872
327 gfx::VSyncProvider* DirectCompositionSurfaceWin::GetVSyncProvider() { 873 gfx::VSyncProvider* DirectCompositionSurfaceWin::GetVSyncProvider() {
328 return vsync_provider_.get(); 874 return vsync_provider_.get();
329 } 875 }
330 876
331 bool DirectCompositionSurfaceWin::ScheduleOverlayPlane( 877 bool DirectCompositionSurfaceWin::ScheduleDCLayer(
332 int z_order, 878 const ui::DCRendererLayerParams& params) {
333 gfx::OverlayTransform transform, 879 return layer_tree_->ScheduleDCLayer(params);
334 gl::GLImage* image,
335 const gfx::Rect& bounds_rect,
336 const gfx::RectF& crop_rect) {
337 pending_overlays_.push_back(
338 Overlay(z_order, transform, image, bounds_rect, crop_rect));
339 return true;
340 } 880 }
341 881
342 bool DirectCompositionSurfaceWin::SetEnableDCLayers(bool enable) { 882 bool DirectCompositionSurfaceWin::SetEnableDCLayers(bool enable) {
343 enable_dc_layers_ = enable; 883 enable_dc_layers_ = enable;
344 return true; 884 return true;
345 } 885 }
346 886
347 bool DirectCompositionSurfaceWin::CommitAndClearPendingOverlays() {
348 pending_overlays_.clear();
349 return true;
350 }
351 887
352 bool DirectCompositionSurfaceWin::FlipsVertically() const { 888 bool DirectCompositionSurfaceWin::FlipsVertically() const {
353 return true; 889 return true;
354 } 890 }
355 891
356 bool DirectCompositionSurfaceWin::SupportsPostSubBuffer() { 892 bool DirectCompositionSurfaceWin::SupportsPostSubBuffer() {
357 return true; 893 return true;
358 } 894 }
359 895
360 bool DirectCompositionSurfaceWin::OnMakeCurrent(gl::GLContext* context) { 896 bool DirectCompositionSurfaceWin::OnMakeCurrent(gl::GLContext* context) {
(...skipping 12 matching lines...) Expand all
373 return true; 909 return true;
374 } 910 }
375 911
376 bool DirectCompositionSurfaceWin::SupportsDCLayers() const { 912 bool DirectCompositionSurfaceWin::SupportsDCLayers() const {
377 return true; 913 return true;
378 } 914 }
379 915
380 bool DirectCompositionSurfaceWin::SetDrawRectangle(const gfx::Rect& rectangle) { 916 bool DirectCompositionSurfaceWin::SetDrawRectangle(const gfx::Rect& rectangle) {
381 if (draw_texture_) 917 if (draw_texture_)
382 return false; 918 return false;
383
384 DCHECK(!real_surface_); 919 DCHECK(!real_surface_);
385 ScopedReleaseCurrent release_current(this); 920 ScopedReleaseCurrent release_current(this);
386 921
387 if ((enable_dc_layers_ && !dcomp_surface_) || 922 if ((enable_dc_layers_ && !dcomp_surface_) ||
388 (!enable_dc_layers_ && !swap_chain_)) { 923 (!enable_dc_layers_ && !swap_chain_)) {
389 ReleaseCurrentSurface(); 924 ReleaseCurrentSurface();
390 InitializeSurface(); 925 InitializeSurface();
391 } 926 }
392 927
393 if (!gfx::Rect(size_).Contains(rectangle)) { 928 if (!gfx::Rect(size_).Contains(rectangle)) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 974
440 gfx::Vector2d DirectCompositionSurfaceWin::GetDrawOffset() const { 975 gfx::Vector2d DirectCompositionSurfaceWin::GetDrawOffset() const {
441 return draw_offset_; 976 return draw_offset_;
442 } 977 }
443 978
444 scoped_refptr<base::TaskRunner> 979 scoped_refptr<base::TaskRunner>
445 DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() { 980 DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() {
446 return child_window_.GetTaskRunnerForTesting(); 981 return child_window_.GetTaskRunnerForTesting();
447 } 982 }
448 983
449 DirectCompositionSurfaceWin::Overlay::Overlay(int z_order,
450 gfx::OverlayTransform transform,
451 scoped_refptr<gl::GLImage> image,
452 gfx::Rect bounds_rect,
453 gfx::RectF crop_rect)
454 : z_order(z_order),
455 transform(transform),
456 image(image),
457 bounds_rect(bounds_rect),
458 crop_rect(crop_rect) {}
459
460 DirectCompositionSurfaceWin::Overlay::Overlay(const Overlay& overlay) = default;
461
462 DirectCompositionSurfaceWin::Overlay::~Overlay() {}
463
464 } // namespace gpu 984 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/ipc/service/direct_composition_surface_win.h ('k') | gpu/ipc/service/direct_composition_surface_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698