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

Side by Side Diff: webrtc/modules/desktop_capture/win/dxgi_texture_staging.cc

Issue 2099123002: [Chromoting] Improve DirectX capturer to support multiple outputs (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Fix several lint errors Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/desktop_capture/win/dxgi_texture_staging.h"
12
13 #include <comdef.h>
14 #include <unknwn.h>
15 #include <DXGI.h>
16 #include <DXGI1_2.h>
17
18 #include "webrtc/base/checks.h"
19 #include "webrtc/system_wrappers/include/logging.h"
20
21 using Microsoft::WRL::ComPtr;
22
23 namespace webrtc {
24
25 DxgiTextureStaging::DxgiTextureStaging(const DesktopRect& desktop_rect,
26 const D3dDevice& device)
27 : DxgiTexture(desktop_rect), device_(device) {}
28
29 DxgiTextureStaging::~DxgiTextureStaging() = default;
30
31 bool DxgiTextureStaging::InitializeStage(ID3D11Texture2D* texture) {
32 RTC_DCHECK(texture);
33 D3D11_TEXTURE2D_DESC desc = {0};
34 texture->GetDesc(&desc);
35 if (static_cast<int>(desc.Width) != desktop_rect().width() ||
36 static_cast<int>(desc.Height) != desktop_rect().height()) {
37 LOG(LS_ERROR) << "Texture size is not consistent with current DxgiTexture.";
38 return false;
39 }
40
41 desc.BindFlags = 0;
42 desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
43 desc.MiscFlags = 0;
44 desc.Usage = D3D11_USAGE_STAGING;
45 if (stage_) {
46 AssertStageAndSurfaceAreSameObject();
47 D3D11_TEXTURE2D_DESC current_desc;
48 stage_->GetDesc(&current_desc);
49 if (memcmp(&desc, &current_desc, sizeof(D3D11_TEXTURE2D_DESC)) == 0) {
50 return true;
51 }
52
53 // The descriptions are not consistent, we need to create a new
54 // ID3D11Texture2D instance.
55 stage_.Reset();
56 surface_.Reset();
57 } else {
58 RTC_DCHECK(!surface_);
59 }
60
61 _com_error error = _com_error(device_.d3d_device()->CreateTexture2D(
62 &desc, nullptr, stage_.GetAddressOf()));
63 if (error.Error() != S_OK || !stage_) {
64 LOG(LS_ERROR) << "Failed to create a new ID3D11Texture2D as stage, error "
65 << error.ErrorMessage() << ", code " << error.Error();
66 return false;
67 }
68
69 error = _com_error(stage_.As(&surface_));
70 if (error.Error() != S_OK || !surface_) {
71 LOG(LS_ERROR) << "Failed to convert ID3D11Texture2D to IDXGISurface, error "
72 << error.ErrorMessage() << ", code " << error.Error();
73 return false;
74 }
75
76 return true;
77 }
78
79 void DxgiTextureStaging::AssertStageAndSurfaceAreSameObject() {
80 ComPtr<IUnknown> left;
81 ComPtr<IUnknown> right;
82 bool left_result = SUCCEEDED(stage_.As(&left));
83 bool right_result = SUCCEEDED(surface_.As(&right));
84 RTC_DCHECK(left_result);
85 RTC_DCHECK(right_result);
86 RTC_DCHECK(left.Get() == right.Get());
87 }
88
89 bool DxgiTextureStaging::CopyFrom(const DXGI_OUTDUPL_FRAME_INFO& frame_info,
90 IDXGIResource* resource,
91 const DesktopRegion& region) {
92 RTC_DCHECK(resource && frame_info.AccumulatedFrames > 0);
93 ComPtr<ID3D11Texture2D> texture;
94 _com_error error = resource->QueryInterface(
95 __uuidof(ID3D11Texture2D),
96 reinterpret_cast<void**>(texture.GetAddressOf()));
97 if (error.Error() != S_OK || !texture) {
98 LOG(LS_ERROR) << "Failed to convert IDXGIResource to ID3D11Texture2D, "
99 "error "
100 << error.ErrorMessage() << ", code " << error.Error();
101 return false;
102 }
103
104 // AcquireNextFrame returns a CPU inaccessible IDXGIResource, so we need to
105 // copy it to a CPU accessible staging ID3D11Texture2D.
106 if (!InitializeStage(texture.Get())) {
107 return false;
108 }
109
110 for (DesktopRegion::Iterator it(region); !it.IsAtEnd(); it.Advance()) {
111 DesktopRect rect(it.rect());
112 rect.Translate(-desktop_rect().left(), -desktop_rect().top());
113 D3D11_BOX box;
114 box.left = rect.left();
115 box.top = rect.top();
116 box.right = rect.right();
117 box.bottom = rect.bottom();
118 box.front = 0;
119 box.back = 1;
120 device_.context()->CopySubresourceRegion(
121 static_cast<ID3D11Resource*>(stage_.Get()), 0, rect.left(), rect.top(),
122 0, static_cast<ID3D11Resource*>(texture.Get()), 0, &box);
123 }
124
125 rect_ = {0};
126 error = _com_error(surface_->Map(&rect_, DXGI_MAP_READ));
127 if (error.Error() != S_OK) {
128 rect_ = {0};
129 LOG(LS_ERROR) << "Failed to map the IDXGISurface to a bitmap, error "
130 << error.ErrorMessage() << ", code " << error.Error();
131 return false;
132 }
133
134 return true;
135 }
136
137 bool DxgiTextureStaging::DoRelease() {
138 _com_error error = _com_error(surface_->Unmap());
139 if (error.Error() != S_OK) {
140 stage_.Reset();
141 surface_.Reset();
142 }
143 // If using staging mode, we only need to recreate ID3D11Texture2D instance.
144 // This will happen during next CopyFrom call. So this function always returns
145 // true.
146 return true;
147 }
148
149 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698