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

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

Issue 2749023011: Add DirectComposition overlay support. (Closed)
Patch Set: remove unused method Created 3 years, 9 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"
18 #include "ui/gfx/geometry/size_conversions.h"
12 #include "ui/gfx/native_widget_types.h" 19 #include "ui/gfx/native_widget_types.h"
20 #include "ui/gfx/transform.h"
21 #include "ui/gl/dc_renderer_layer_params.h"
13 #include "ui/gl/egl_util.h" 22 #include "ui/gl/egl_util.h"
14 #include "ui/gl/gl_angle_util_win.h" 23 #include "ui/gl/gl_angle_util_win.h"
15 #include "ui/gl/gl_context.h" 24 #include "ui/gl/gl_context.h"
25 #include "ui/gl/gl_image_dxgi.h"
16 #include "ui/gl/gl_surface_egl.h" 26 #include "ui/gl/gl_surface_egl.h"
17 #include "ui/gl/scoped_make_current.h" 27 #include "ui/gl/scoped_make_current.h"
18 28
19 #ifndef EGL_ANGLE_flexible_surface_compatibility 29 #ifndef EGL_ANGLE_flexible_surface_compatibility
20 #define EGL_ANGLE_flexible_surface_compatibility 1 30 #define EGL_ANGLE_flexible_surface_compatibility 1
21 #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6 31 #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
22 #endif /* EGL_ANGLE_flexible_surface_compatibility */ 32 #endif /* EGL_ANGLE_flexible_surface_compatibility */
23 33
24 #ifndef EGL_ANGLE_d3d_texture_client_buffer 34 #ifndef EGL_ANGLE_d3d_texture_client_buffer
25 #define EGL_ANGLE_d3d_texture_client_buffer 1 35 #define EGL_ANGLE_d3d_texture_client_buffer 1
(...skipping 14 matching lines...) Expand all
40 if (was_current) { 50 if (was_current) {
41 make_current_.emplace(current_context, this_surface); 51 make_current_.emplace(current_context, this_surface);
42 current_context->ReleaseCurrent(this_surface); 52 current_context->ReleaseCurrent(this_surface);
43 } 53 }
44 } 54 }
45 55
46 private: 56 private:
47 base::Optional<ui::ScopedMakeCurrent> make_current_; 57 base::Optional<ui::ScopedMakeCurrent> make_current_;
48 }; 58 };
49 59
60 bool SizeContains(const gfx::Size& a, const gfx::Size& b) {
61 return gfx::Rect(a).Contains(gfx::Rect(b));
62 }
50 // Only one DirectComposition surface can be rendered into at a time. Track 63 // Only one DirectComposition surface can be rendered into at a time. Track
51 // here which IDCompositionSurface is being rendered into. If another context 64 // here which IDCompositionSurface is being rendered into. If another context
52 // is made current, then this surface will be suspended. 65 // is made current, then this surface will be suspended.
53 IDCompositionSurface* g_current_surface; 66 IDCompositionSurface* g_current_surface;
54 67
55 } // namespace 68 } // namespace
56 69
70 class DCLayerTree {
71 public:
72 DCLayerTree(DirectCompositionSurfaceWin* surface,
73 const base::win::ScopedComPtr<ID3D11Device>& d3d11_device,
74 const base::win::ScopedComPtr<IDCompositionDevice2>& dcomp_device)
75 : surface_(surface),
76 d3d11_device_(d3d11_device),
77 dcomp_device_(dcomp_device) {}
78
79 bool Initialize(HWND window);
80 bool CommitAndClearPendingOverlays();
81 bool ScheduleDCLayer(const ui::DCRendererLayerParams& params);
82 void InitializeVideoProcessor(const gfx::Size& input_size,
83 const gfx::Size& output_size);
84
85 base::win::ScopedComPtr<ID3D11VideoProcessor> video_processor() {
sunnyps 2017/03/28 00:42:23 nit: const method and const ref return here and be
86 return video_processor_;
87 }
88 base::win::ScopedComPtr<ID3D11VideoProcessorEnumerator>
89 video_processor_enumerator() {
90 return video_processor_enumerator_;
91 }
92
93 private:
94 class SwapChainPresenter;
95
96 // This struct is used to cache information about what visuals are currently
97 // being presented so that properties that aren't changed aren't sent to
98 // DirectComposition.
99 struct VisualInfo {
100 base::win::ScopedComPtr<IDCompositionVisual2> visual;
sunnyps 2017/03/28 00:42:23 nit: content_visual?
101 base::win::ScopedComPtr<IDCompositionVisual2> clip_visual;
102
103 std::unique_ptr<SwapChainPresenter> swap_chain_presenter;
104 base::win::ScopedComPtr<IDXGISwapChain1> swap_chain;
105 base::win::ScopedComPtr<IDCompositionSurface> surface;
106
107 gfx::Rect bounds;
108 float swap_chain_scale_x = 0.0f;
109 float swap_chain_scale_y = 0.0f;
110 bool is_clipped = false;
111 gfx::Rect clip_rect;
112 gfx::Transform transform;
113 };
114
115 DirectCompositionSurfaceWin* surface_;
116 std::vector<std::unique_ptr<ui::DCRendererLayerParams>> pending_overlays_;
117
118 base::win::ScopedComPtr<ID3D11Device> d3d11_device_;
119 base::win::ScopedComPtr<IDCompositionDevice2> dcomp_device_;
120 base::win::ScopedComPtr<IDCompositionTarget> dcomp_target_;
121 base::win::ScopedComPtr<IDCompositionVisual2> root_visual_;
122
123 // The video processor is cached so SwapChains don't have to recreate it
124 // whenever they're created.
125 base::win::ScopedComPtr<ID3D11VideoDevice> video_device_;
126 base::win::ScopedComPtr<ID3D11VideoContext> video_context_;
127 base::win::ScopedComPtr<ID3D11VideoProcessor> video_processor_;
128 base::win::ScopedComPtr<ID3D11VideoProcessorEnumerator>
129 video_processor_enumerator_;
130 gfx::Size video_input_size_;
131 gfx::Size video_output_size_;
132
133 std::vector<VisualInfo> visual_info_;
134
135 DISALLOW_COPY_AND_ASSIGN(DCLayerTree);
136 };
137
138 class DCLayerTree::SwapChainPresenter {
139 public:
140 SwapChainPresenter(DCLayerTree* surface,
141 base::win::ScopedComPtr<ID3D11Device> d3d11_device);
142
143 ~SwapChainPresenter();
144
145 void PresentToSwapChain(const ui::DCRendererLayerParams& overlay);
146
147 float swap_chain_scale_x() const { return swap_chain_scale_x_; }
148 float swap_chain_scale_y() const { return swap_chain_scale_y_; }
149 const base::win::ScopedComPtr<IDXGISwapChain1> swap_chain() const {
150 return swap_chain_;
151 }
152
153 private:
154 using PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE =
155 HRESULT(WINAPI*)(DWORD, SECURITY_ATTRIBUTES*, HANDLE*);
156
157 // Returns true if the video processor changed.
158 bool InitializeVideoProcessor(const gfx::Size& in_size,
159 const gfx::Size& out_size);
160 void ReallocateSwapChain();
161
162 DCLayerTree* surface_;
163 PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE create_surface_handle_function_;
164
165 gfx::Size swap_chain_size_;
166 gfx::Size processor_input_size_;
167 gfx::Size processor_output_size_;
168
169 // This is the scale from the swapchain size to the size of the contents
170 // onscreen.
171 float swap_chain_scale_x_ = 0.0f;
172 float swap_chain_scale_y_ = 0.0f;
173
174 base::win::ScopedComPtr<ID3D11Device> d3d11_device_;
175 base::win::ScopedComPtr<IDXGISwapChain1> swap_chain_;
176 base::win::ScopedComPtr<ID3D11VideoProcessorOutputView> out_view_;
177 base::win::ScopedComPtr<ID3D11VideoProcessor> video_processor_;
178 base::win::ScopedComPtr<ID3D11VideoProcessorEnumerator>
179 video_processor_enumerator_;
180 base::win::ScopedComPtr<ID3D11VideoDevice> video_device_;
181 base::win::ScopedComPtr<ID3D11VideoContext> video_context_;
182
183 base::win::ScopedHandle swap_chain_handle_;
184
185 DISALLOW_COPY_AND_ASSIGN(SwapChainPresenter);
186 };
187
188 bool DCLayerTree::Initialize(HWND window) {
189 d3d11_device_.QueryInterface(video_device_.Receive());
190 base::win::ScopedComPtr<ID3D11DeviceContext> context;
191 d3d11_device_->GetImmediateContext(context.Receive());
192 context.QueryInterface(video_context_.Receive());
193
194 base::win::ScopedComPtr<IDCompositionDesktopDevice> desktop_device;
195 dcomp_device_.QueryInterface(desktop_device.Receive());
196
197 HRESULT hr = desktop_device->CreateTargetForHwnd(window, TRUE,
198 dcomp_target_.Receive());
199 if (FAILED(hr))
200 return false;
201
202 hr = dcomp_device_->CreateVisual(root_visual_.Receive());
203 if (FAILED(hr))
204 return false;
205
206 dcomp_target_->SetRoot(root_visual_.get());
207 return true;
208 }
209
210 void DCLayerTree::InitializeVideoProcessor(const gfx::Size& input_size,
211 const gfx::Size& output_size) {
212 if (SizeContains(video_input_size_, input_size) &&
213 SizeContains(video_output_size_, output_size))
214 return;
215 video_input_size_ = input_size;
216 video_output_size_ = output_size;
217
218 video_processor_.Release();
219 video_processor_enumerator_.Receive();
220 D3D11_VIDEO_PROCESSOR_CONTENT_DESC desc = {};
221 desc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
222 desc.InputFrameRate.Numerator = 60;
223 desc.InputFrameRate.Denominator = 1;
224 desc.InputWidth = input_size.width();
225 desc.InputHeight = input_size.height();
226 desc.OutputFrameRate.Numerator = 60;
227 desc.OutputFrameRate.Denominator = 1;
228 desc.OutputWidth = output_size.width();
229 desc.OutputHeight = output_size.height();
230 desc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;
231 HRESULT hr = video_device_->CreateVideoProcessorEnumerator(
232 &desc, video_processor_enumerator_.Receive());
233 CHECK(SUCCEEDED(hr));
234
235 D3D11_VIDEO_PROCESSOR_CAPS caps;
236 hr = video_processor_enumerator_->GetVideoProcessorCaps(&caps);
237 for (size_t i = 0; i < caps.RateConversionCapsCount; i++) {
sunnyps 2017/03/28 00:42:23 Why is this loop needed?
238 D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS rc_caps;
239 hr = video_processor_enumerator_->GetVideoProcessorRateConversionCaps(
240 (UINT)i, &rc_caps);
241 }
242
243 hr = video_device_->CreateVideoProcessor(video_processor_enumerator_.get(), 0,
244 video_processor_.Receive());
245 CHECK(SUCCEEDED(hr));
246 }
247
248 DCLayerTree::SwapChainPresenter::SwapChainPresenter(
249 DCLayerTree* surface,
250 base::win::ScopedComPtr<ID3D11Device> d3d11_device)
251 : surface_(surface), d3d11_device_(d3d11_device) {
252 d3d11_device_.QueryInterface(video_device_.Receive());
253 base::win::ScopedComPtr<ID3D11DeviceContext> context;
254 d3d11_device_->GetImmediateContext(context.Receive());
255 context.QueryInterface(video_context_.Receive());
256 HMODULE dcomp = ::GetModuleHandleA("dcomp.dll");
257 DCHECK(dcomp);
258 create_surface_handle_function_ =
sunnyps 2017/03/28 00:42:24 nit: should this be a CHECK?
sunnyps 2017/03/28 22:28:58 I actually meant the check for dcomp.dll.
259 reinterpret_cast<PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE>(
260 GetProcAddress(dcomp, "DCompositionCreateSurfaceHandle"));
261 }
262
263 DCLayerTree::SwapChainPresenter::~SwapChainPresenter() {}
264
265 void DCLayerTree::SwapChainPresenter::PresentToSwapChain(
266 const ui::DCRendererLayerParams& params) {
267 gl::GLImageDXGI* image_dxgi =
268 gl::GLImageDXGI::FromGLImage(params.image.get());
269 DCHECK(image_dxgi);
270
271 // Swap chain size is the minimum of the on-screen size and the source
272 // size so the video processor can do the minimal amount of work and
273 // the overlay has to read the minimal amount of data.
274 // DWM is also less likely to promote a surface to an overlay if it's
275 // much larger than its area on-screen.
276 gfx::Rect bounds_rect = params.rect;
277 gfx::Size ceiled_input_size = gfx::ToCeiledSize(params.contents_rect.size());
278 gfx::Size swap_chain_size = bounds_rect.size();
279 swap_chain_size.SetToMin(ceiled_input_size);
280
281 // YUY2 surfaces must have an even width.
282 if (swap_chain_size.width() % 2 == 1)
283 swap_chain_size.set_width(swap_chain_size.width() + 1);
284
285 if (InitializeVideoProcessor(ceiled_input_size, swap_chain_size))
286 out_view_.Release();
287
288 bool first_present = false;
289 if (!swap_chain_ || swap_chain_size_ != swap_chain_size) {
290 first_present = true;
291 swap_chain_size_ = swap_chain_size;
292 swap_chain_.Release();
293 ReallocateSwapChain();
294 }
295
296 if (!out_view_) {
297 base::win::ScopedComPtr<ID3D11Texture2D> texture;
298 swap_chain_->GetBuffer(0, IID_PPV_ARGS(texture.Receive()));
sunnyps 2017/03/28 00:42:24 Do we need to cycle through the back buffers of th
299 D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC out_desc = {};
300 out_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
301 out_desc.Texture2D.MipSlice = 0;
302 out_view_.Release();
sunnyps 2017/03/28 00:42:23 nit: out_view_.Release isn't needed here
303 HRESULT hr = video_device_->CreateVideoProcessorOutputView(
304 texture.get(), video_processor_enumerator_.get(), &out_desc,
305 out_view_.Receive());
306 CHECK(SUCCEEDED(hr));
307 }
308 {
309 D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC in_desc = {};
310 in_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
311 in_desc.Texture2D.ArraySlice = (UINT)image_dxgi->level();
312 base::win::ScopedComPtr<ID3D11VideoProcessorInputView> in_view;
313 HRESULT hr = video_device_->CreateVideoProcessorInputView(
314 image_dxgi->texture().get(), video_processor_enumerator_.get(),
315 &in_desc, in_view.Receive());
316 CHECK(SUCCEEDED(hr));
317
318 D3D11_VIDEO_PROCESSOR_STREAM stream = {};
319 stream.Enable = true;
320 stream.OutputIndex = 0;
321 stream.InputFrameOrField = 0;
322 stream.PastFrames = 0;
323 stream.FutureFrames = 0;
324 stream.pInputSurface = in_view.get();
325 RECT dest_rect = gfx::Rect(swap_chain_size).ToRECT();
326 video_context_->VideoProcessorSetOutputTargetRect(video_processor_.get(),
327 TRUE, &dest_rect);
328 video_context_->VideoProcessorSetStreamDestRect(video_processor_.get(), 0,
329 TRUE, &dest_rect);
330 RECT source_rect = gfx::Rect(ceiled_input_size).ToRECT();
331 video_context_->VideoProcessorSetStreamSourceRect(video_processor_.get(), 0,
332 TRUE, &source_rect);
333
334 video_context_->VideoProcessorSetStreamAutoProcessingMode(
335 video_processor_.get(), 0, FALSE);
336
337 hr = video_context_->VideoProcessorBlt(video_processor_.get(),
338 out_view_.get(), 0, 1, &stream);
339 CHECK(SUCCEEDED(hr));
340 }
341
342 swap_chain_scale_x_ = bounds_rect.width() * 1.0f / swap_chain_size.width();
343 swap_chain_scale_y_ = bounds_rect.height() * 1.0f / swap_chain_size.height();
344
345 swap_chain_->Present(first_present ? 0 : 1, 0);
346 }
347
348 bool DCLayerTree::SwapChainPresenter::InitializeVideoProcessor(
349 const gfx::Size& in_size,
350 const gfx::Size& out_size) {
351 if (video_processor_ && SizeContains(processor_input_size_, in_size) &&
352 SizeContains(processor_output_size_, out_size))
353 return false;
354 processor_input_size_ = in_size;
355 processor_output_size_ = out_size;
356 surface_->InitializeVideoProcessor(in_size, out_size);
357
358 video_processor_enumerator_ = surface_->video_processor_enumerator();
359 video_processor_ = surface_->video_processor();
360 return true;
361 }
362
363 void DCLayerTree::SwapChainPresenter::ReallocateSwapChain() {
364 TRACE_EVENT0("gpu", "DCLayerTree::SwapChainPresenter::ReallocateSwapChain");
365 DCHECK(!swap_chain_);
366
367 base::win::ScopedComPtr<IDXGIDevice> dxgi_device;
368 d3d11_device_.QueryInterface(dxgi_device.Receive());
369 base::win::ScopedComPtr<IDXGIAdapter> dxgi_adapter;
370 dxgi_device->GetAdapter(dxgi_adapter.Receive());
371 base::win::ScopedComPtr<IDXGIFactory2> dxgi_factory;
372 dxgi_adapter->GetParent(IID_PPV_ARGS(dxgi_factory.Receive()));
373
374 base::win::ScopedComPtr<IDXGIFactoryMedia> media_factory;
375 dxgi_factory.QueryInterface(media_factory.Receive());
376 DXGI_SWAP_CHAIN_DESC1 desc = {};
377 desc.Width = swap_chain_size_.width();
378 desc.Height = swap_chain_size_.height();
379 LOG(ERROR) << "Width " << desc.Width << " height " << desc.Height;
380 desc.Format = DXGI_FORMAT_YUY2;
381 desc.Stereo = FALSE;
382 desc.SampleDesc.Count = 1;
383 desc.BufferCount = 2;
384 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
385 desc.Scaling = DXGI_SCALING_STRETCH;
386 desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
387 desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
388 desc.Flags =
389 DXGI_SWAP_CHAIN_FLAG_YUV_VIDEO | DXGI_SWAP_CHAIN_FLAG_FULLSCREEN_VIDEO;
390
391 HANDLE handle;
392 create_surface_handle_function_(COMPOSITIONOBJECT_ALL_ACCESS, nullptr,
393 &handle);
394 swap_chain_handle_.Set(handle);
395
396 // The composition surface handle isn't actually used, but
397 // CreateSwapChainForComposition can't create YUY2 swapchains.
398 HRESULT hr = media_factory->CreateSwapChainForCompositionSurfaceHandle(
399 d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr,
400 swap_chain_.Receive());
401
402 if (FAILED(hr)) {
403 // This should be hit in production but is a simple fallback for
sunnyps 2017/03/28 00:42:24 nit: should not be hit?
404 // testing on systems without YUY2 swapchain support.
405 DLOG(ERROR) << "YUY2 creation failed with " << std::hex << hr
406 << ". Falling back to BGRA";
407 desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
408 desc.Flags = 0;
409 hr = media_factory->CreateSwapChainForCompositionSurfaceHandle(
410 d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr,
411 swap_chain_.Receive());
412 CHECK(SUCCEEDED(hr));
413 } else {
414 base::win::ScopedComPtr<IDXGISwapChain3> swap_chain3;
415 swap_chain_.QueryInterface(swap_chain3.Receive());
416 hr = swap_chain3->SetColorSpace1(
sunnyps 2017/03/28 00:42:24 What's the significance of setting the color space
417 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709);
418 CHECK(SUCCEEDED(hr));
419 }
420 out_view_.Release();
421 }
422
423 bool DCLayerTree::CommitAndClearPendingOverlays() {
424 TRACE_EVENT1("gpu", "DCLayerTree::CommitAndClearPendingOverlays", "size",
425 pending_overlays_.size());
426 // Add an overlay with z-order 0 representing the main plane.
427 gfx::Size surface_size = surface_->GetSize();
428 pending_overlays_.push_back(base::MakeUnique<ui::DCRendererLayerParams>(
429 false, gfx::Rect(), 0, gfx::Transform(), nullptr,
430 gfx::RectF(gfx::SizeF(surface_size)), gfx::Rect(surface_size), 0, 0, 1.0,
431 0));
432
433 // TODO(jbauman): Reuse swapchains that are switched between overlays and
434 // underlays.
435 std::sort(pending_overlays_.begin(), pending_overlays_.end(),
436 [](const auto& a, const auto& b) -> bool {
437 return a->z_order < b->z_order;
438 });
439
440 while (visual_info_.size() > pending_overlays_.size()) {
sunnyps 2017/03/28 00:42:23 I think it's OK to keep extra visual infos around
441 visual_info_.back().clip_visual->RemoveAllVisuals();
442 root_visual_->RemoveVisual(visual_info_.back().clip_visual.get());
443 visual_info_.pop_back();
444 }
445
446 visual_info_.resize(pending_overlays_.size());
447
448 for (size_t i = 0; i < pending_overlays_.size(); i++) {
sunnyps 2017/03/28 00:42:24 Can you add a comment saying what the visual tree
449 ui::DCRendererLayerParams& params = *pending_overlays_[i];
450 VisualInfo* visual_info = &visual_info_[i];
451
452 base::win::ScopedComPtr<IDCompositionVisual2> this_visual;
sunnyps 2017/03/28 00:42:23 nit: content_visual?
453
454 if (!visual_info->visual) {
sunnyps 2017/03/28 00:42:23 Can you factor this into InitVisual(VisualInfo*)?
455 dcomp_device_->CreateVisual(visual_info->clip_visual.Receive());
456 dcomp_device_->CreateVisual(this_visual.Receive());
457 visual_info->visual = this_visual;
458 visual_info->clip_visual->AddVisual(this_visual.get(), FALSE, nullptr);
459
460 IDCompositionVisual2* last_visual =
461 (i > 0) ? visual_info_[i - 1].clip_visual.get() : nullptr;
462 root_visual_->AddVisual(visual_info->clip_visual.get(), TRUE,
463 last_visual);
464 } else {
465 this_visual = visual_info->visual;
466 }
467
468 gfx::Rect bounds_rect = params.rect;
469
470 if (params.image &&
471 params.image->GetType() == gl::GLImage::Type::DXGI_IMAGE) {
sunnyps 2017/03/28 00:42:23 Can you factor the body of this into UpdateVisualF
472 visual_info->surface.Release();
473 if (!visual_info->swap_chain_presenter) {
474 visual_info->swap_chain_presenter =
475 base::MakeUnique<SwapChainPresenter>(this, d3d11_device_);
476 }
477 visual_info->swap_chain_presenter->PresentToSwapChain(params);
478 if (visual_info->swap_chain !=
479 visual_info->swap_chain_presenter->swap_chain()) {
480 visual_info->swap_chain =
481 visual_info->swap_chain_presenter->swap_chain();
482 this_visual->SetContent(visual_info->swap_chain.get());
483 }
484
485 if (visual_info->swap_chain_presenter->swap_chain_scale_x() !=
486 visual_info->swap_chain_scale_x ||
487 visual_info->swap_chain_presenter->swap_chain_scale_y() !=
488 visual_info->swap_chain_scale_y ||
489 params.transform != visual_info->transform ||
490 visual_info->bounds != bounds_rect) {
491 visual_info->swap_chain_scale_x =
492 visual_info->swap_chain_presenter->swap_chain_scale_x();
493 visual_info->swap_chain_scale_y =
494 visual_info->swap_chain_presenter->swap_chain_scale_y();
495 visual_info->transform = params.transform;
496 visual_info->bounds = bounds_rect;
497
498 gfx::Transform final_transform = params.transform;
499 gfx::Transform scale_transform;
500 scale_transform.Scale(
501 visual_info->swap_chain_presenter->swap_chain_scale_x(),
502 visual_info->swap_chain_presenter->swap_chain_scale_y());
503 final_transform.PreconcatTransform(scale_transform);
504 final_transform.Transpose();
505
506 this_visual->SetOffsetX(bounds_rect.x());
507 this_visual->SetOffsetY(bounds_rect.y());
508 base::win::ScopedComPtr<IDCompositionMatrixTransform> dcomp_transform;
509 dcomp_device_->CreateMatrixTransform(dcomp_transform.Receive());
510 D2D_MATRIX_3X2_F d2d_matrix = {{{final_transform.matrix().get(0, 0),
511 final_transform.matrix().get(0, 1),
512 final_transform.matrix().get(1, 0),
513 final_transform.matrix().get(1, 1),
514 final_transform.matrix().get(3, 0),
515 final_transform.matrix().get(3, 1)}}};
516 dcomp_transform->SetMatrix(d2d_matrix);
517 this_visual->SetTransform(dcomp_transform.get());
518 }
519 } else if (!params.image) {
520 // Main backbuffer.
sunnyps 2017/03/28 00:42:23 Can you factor this into UpdateVisualForBackbuffer
sunnyps 2017/03/28 00:42:23 If visual_info was used by a video overlay in the
521 if (visual_info->surface != surface_->dcomp_surface()) {
522 this_visual->SetContent(surface_->dcomp_surface().get());
523 visual_info->surface = surface_->dcomp_surface();
524 visual_info->swap_chain_presenter = nullptr;
525 visual_info->swap_chain.Release();
526 }
527 if (visual_info->swap_chain != surface_->swap_chain()) {
528 this_visual->SetContent(surface_->swap_chain().get());
529 visual_info->surface = nullptr;
530 visual_info->swap_chain_presenter = nullptr;
531 visual_info->swap_chain = surface_->swap_chain();
532 }
533 if (visual_info->bounds != bounds_rect ||
534 !visual_info->transform.IsIdentity()) {
535 this_visual->SetOffsetX(bounds_rect.x());
536 this_visual->SetOffsetY(bounds_rect.y());
537 visual_info->bounds = bounds_rect;
538 this_visual->SetTransform(nullptr);
539 visual_info->transform = gfx::Transform();
540 }
541 } else {
542 CHECK(false);
543 }
544 if (params.is_clipped != visual_info->is_clipped ||
sunnyps 2017/03/28 00:42:23 Can you factor this into UpdateVisualClip?
545 params.clip_rect != visual_info->clip_rect) {
546 // DirectComposition clips happen in the pre-transform visual
547 // space, while cc/ clips happen post-transform. So the clip needs
548 // to go on a separate parent visual that's untransformed.
549 visual_info->is_clipped = params.is_clipped;
550 visual_info->clip_rect = params.clip_rect;
551 if (params.is_clipped) {
552 base::win::ScopedComPtr<IDCompositionRectangleClip> clip;
553 dcomp_device_->CreateRectangleClip(clip.Receive());
554 gfx::Rect offset_clip = params.clip_rect;
555 clip->SetLeft(offset_clip.x());
556 clip->SetRight(offset_clip.right());
557 clip->SetBottom(offset_clip.bottom());
558 clip->SetTop(offset_clip.y());
559 visual_info->clip_visual->SetClip(clip.get());
560 } else {
561 visual_info->clip_visual->SetClip(nullptr);
562 }
563 }
564 }
565
566 HRESULT hr = dcomp_device_->Commit();
567 CHECK(SUCCEEDED(hr));
568
569 pending_overlays_.clear();
570 return true;
571 }
572
573 bool DCLayerTree::ScheduleDCLayer(const ui::DCRendererLayerParams& params) {
574 pending_overlays_.push_back(
sunnyps 2017/03/28 00:42:23 Is there a reason for heap allocating DCRendererLa
575 base::MakeUnique<ui::DCRendererLayerParams>(params));
576 return true;
577 }
578
57 DirectCompositionSurfaceWin::DirectCompositionSurfaceWin( 579 DirectCompositionSurfaceWin::DirectCompositionSurfaceWin(
58 base::WeakPtr<ImageTransportSurfaceDelegate> delegate, 580 base::WeakPtr<ImageTransportSurfaceDelegate> delegate,
59 HWND parent_window) 581 HWND parent_window)
60 : gl::GLSurfaceEGL(), child_window_(delegate, parent_window) {} 582 : gl::GLSurfaceEGL(), child_window_(delegate, parent_window) {}
61 583
62 DirectCompositionSurfaceWin::~DirectCompositionSurfaceWin() { 584 DirectCompositionSurfaceWin::~DirectCompositionSurfaceWin() {
63 Destroy(); 585 Destroy();
64 } 586 }
65 587
66 // static 588 // static
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 return false; 645 return false;
124 646
125 EGLDisplay display = GetDisplay(); 647 EGLDisplay display = GetDisplay();
126 if (!window_) { 648 if (!window_) {
127 if (!InitializeNativeWindow()) { 649 if (!InitializeNativeWindow()) {
128 DLOG(ERROR) << "Failed to initialize native window"; 650 DLOG(ERROR) << "Failed to initialize native window";
129 return false; 651 return false;
130 } 652 }
131 } 653 }
132 654
133 base::win::ScopedComPtr<IDCompositionDesktopDevice> desktop_device; 655 layer_tree_ =
134 dcomp_device_.QueryInterface(desktop_device.Receive()); 656 base::MakeUnique<DCLayerTree>(this, d3d11_device_, dcomp_device_);
135 657 if (!layer_tree_->Initialize(window_))
136 HRESULT hr = desktop_device->CreateTargetForHwnd(window_, TRUE,
137 dcomp_target_.Receive());
138 if (FAILED(hr))
139 return false; 658 return false;
140 659
141 hr = dcomp_device_->CreateVisual(visual_.Receive());
142 if (FAILED(hr))
143 return false;
144
145 dcomp_target_->SetRoot(visual_.get());
146
147 std::vector<EGLint> pbuffer_attribs; 660 std::vector<EGLint> pbuffer_attribs;
148 pbuffer_attribs.push_back(EGL_WIDTH); 661 pbuffer_attribs.push_back(EGL_WIDTH);
149 pbuffer_attribs.push_back(1); 662 pbuffer_attribs.push_back(1);
150 pbuffer_attribs.push_back(EGL_HEIGHT); 663 pbuffer_attribs.push_back(EGL_HEIGHT);
151 pbuffer_attribs.push_back(1); 664 pbuffer_attribs.push_back(1);
152 665
153 pbuffer_attribs.push_back(EGL_NONE); 666 pbuffer_attribs.push_back(EGL_NONE);
154 default_surface_ = 667 default_surface_ =
155 eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]); 668 eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]);
156 CHECK(!!default_surface_); 669 CHECK(!!default_surface_);
157 670
158 return true; 671 return true;
159 } 672 }
160 673
161 void DirectCompositionSurfaceWin::ReleaseCurrentSurface() { 674 void DirectCompositionSurfaceWin::ReleaseCurrentSurface() {
162 ReleaseDrawTexture(true); 675 ReleaseDrawTexture(true);
163 dcomp_surface_.Release(); 676 dcomp_surface_.Release();
164 swap_chain_.Release(); 677 swap_chain_.Release();
165 } 678 }
166 679
167 void DirectCompositionSurfaceWin::InitializeSurface() { 680 void DirectCompositionSurfaceWin::InitializeSurface() {
681 TRACE_EVENT1("gpu", "DirectCompositionSurfaceWin::InitializeSurface()",
682 "enable_dc_layers_", enable_dc_layers_);
168 DCHECK(!dcomp_surface_); 683 DCHECK(!dcomp_surface_);
169 DCHECK(!swap_chain_); 684 DCHECK(!swap_chain_);
170 if (enable_dc_layers_) { 685 if (enable_dc_layers_) {
171 HRESULT hr = dcomp_device_->CreateSurface( 686 HRESULT hr = dcomp_device_->CreateSurface(
172 size_.width(), size_.height(), DXGI_FORMAT_B8G8R8A8_UNORM, 687 size_.width(), size_.height(), DXGI_FORMAT_B8G8R8A8_UNORM,
173 DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.Receive()); 688 DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.Receive());
174 has_been_rendered_to_ = false; 689 has_been_rendered_to_ = false;
175 CHECK(SUCCEEDED(hr)); 690 CHECK(SUCCEEDED(hr));
176 } else { 691 } else {
177 base::win::ScopedComPtr<IDXGIDevice> dxgi_device; 692 base::win::ScopedComPtr<IDXGIDevice> dxgi_device;
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 // New surface will be initialized in SetDrawRectangle. 805 // New surface will be initialized in SetDrawRectangle.
291 ReleaseCurrentSurface(); 806 ReleaseCurrentSurface();
292 807
293 return true; 808 return true;
294 } 809 }
295 810
296 gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() { 811 gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() {
297 { 812 {
298 ScopedReleaseCurrent release_current(this); 813 ScopedReleaseCurrent release_current(this);
299 ReleaseDrawTexture(false); 814 ReleaseDrawTexture(false);
300 DCHECK(dcomp_surface_ || swap_chain_);
301 if (dcomp_surface_)
302 visual_->SetContent(dcomp_surface_.get());
303 else
304 visual_->SetContent(swap_chain_.get());
305 815
306 CommitAndClearPendingOverlays(); 816 layer_tree_->CommitAndClearPendingOverlays();
307 dcomp_device_->Commit();
308 } 817 }
309 child_window_.ClearInvalidContents(); 818 child_window_.ClearInvalidContents();
310 return gfx::SwapResult::SWAP_ACK; 819 return gfx::SwapResult::SWAP_ACK;
311 } 820 }
312 821
313 gfx::SwapResult DirectCompositionSurfaceWin::PostSubBuffer(int x, 822 gfx::SwapResult DirectCompositionSurfaceWin::PostSubBuffer(int x,
314 int y, 823 int y,
315 int width, 824 int width,
316 int height) { 825 int height) {
317 // The arguments are ignored because SetDrawRectangle specified the area to 826 // The arguments are ignored because SetDrawRectangle specified the area to
318 // be swapped. 827 // be swapped.
319 return SwapBuffers(); 828 return SwapBuffers();
320 } 829 }
321 830
322 gfx::VSyncProvider* DirectCompositionSurfaceWin::GetVSyncProvider() { 831 gfx::VSyncProvider* DirectCompositionSurfaceWin::GetVSyncProvider() {
323 return vsync_provider_.get(); 832 return vsync_provider_.get();
324 } 833 }
325 834
326 bool DirectCompositionSurfaceWin::ScheduleOverlayPlane( 835 bool DirectCompositionSurfaceWin::ScheduleDCLayer(
327 int z_order, 836 const ui::DCRendererLayerParams& params) {
328 gfx::OverlayTransform transform, 837 return layer_tree_->ScheduleDCLayer(params);
329 gl::GLImage* image,
330 const gfx::Rect& bounds_rect,
331 const gfx::RectF& crop_rect) {
332 pending_overlays_.push_back(
333 Overlay(z_order, transform, image, bounds_rect, crop_rect));
334 return true;
335 } 838 }
336 839
337 bool DirectCompositionSurfaceWin::SetEnableDCLayers(bool enable) { 840 bool DirectCompositionSurfaceWin::SetEnableDCLayers(bool enable) {
338 enable_dc_layers_ = enable; 841 enable_dc_layers_ = enable;
339 return true; 842 return true;
340 } 843 }
341 844
342 bool DirectCompositionSurfaceWin::CommitAndClearPendingOverlays() {
343 pending_overlays_.clear();
344 return true;
345 }
346 845
347 bool DirectCompositionSurfaceWin::FlipsVertically() const { 846 bool DirectCompositionSurfaceWin::FlipsVertically() const {
348 return true; 847 return true;
349 } 848 }
350 849
351 bool DirectCompositionSurfaceWin::SupportsPostSubBuffer() { 850 bool DirectCompositionSurfaceWin::SupportsPostSubBuffer() {
352 return true; 851 return true;
353 } 852 }
354 853
355 bool DirectCompositionSurfaceWin::OnMakeCurrent(gl::GLContext* context) { 854 bool DirectCompositionSurfaceWin::OnMakeCurrent(gl::GLContext* context) {
(...skipping 12 matching lines...) Expand all
368 return true; 867 return true;
369 } 868 }
370 869
371 bool DirectCompositionSurfaceWin::SupportsDCLayers() const { 870 bool DirectCompositionSurfaceWin::SupportsDCLayers() const {
372 return true; 871 return true;
373 } 872 }
374 873
375 bool DirectCompositionSurfaceWin::SetDrawRectangle(const gfx::Rect& rectangle) { 874 bool DirectCompositionSurfaceWin::SetDrawRectangle(const gfx::Rect& rectangle) {
376 if (draw_texture_) 875 if (draw_texture_)
377 return false; 876 return false;
378
379 DCHECK(!real_surface_); 877 DCHECK(!real_surface_);
380 ScopedReleaseCurrent release_current(this); 878 ScopedReleaseCurrent release_current(this);
381 879
382 if ((enable_dc_layers_ && !dcomp_surface_) || 880 if ((enable_dc_layers_ && !dcomp_surface_) ||
383 (!enable_dc_layers_ && !swap_chain_)) { 881 (!enable_dc_layers_ && !swap_chain_)) {
384 ReleaseCurrentSurface(); 882 ReleaseCurrentSurface();
385 InitializeSurface(); 883 InitializeSurface();
386 } 884 }
387 885
388 if (!gfx::Rect(size_).Contains(rectangle)) { 886 if (!gfx::Rect(size_).Contains(rectangle)) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 932
435 gfx::Vector2d DirectCompositionSurfaceWin::GetDrawOffset() const { 933 gfx::Vector2d DirectCompositionSurfaceWin::GetDrawOffset() const {
436 return draw_offset_; 934 return draw_offset_;
437 } 935 }
438 936
439 scoped_refptr<base::TaskRunner> 937 scoped_refptr<base::TaskRunner>
440 DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() { 938 DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() {
441 return child_window_.GetTaskRunnerForTesting(); 939 return child_window_.GetTaskRunnerForTesting();
442 } 940 }
443 941
444 DirectCompositionSurfaceWin::Overlay::Overlay(int z_order,
445 gfx::OverlayTransform transform,
446 scoped_refptr<gl::GLImage> image,
447 gfx::Rect bounds_rect,
448 gfx::RectF crop_rect)
449 : z_order(z_order),
450 transform(transform),
451 image(image),
452 bounds_rect(bounds_rect),
453 crop_rect(crop_rect) {}
454
455 DirectCompositionSurfaceWin::Overlay::Overlay(const Overlay& overlay) = default;
456
457 DirectCompositionSurfaceWin::Overlay::~Overlay() {}
458
459 } // namespace gpu 942 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698