OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |