Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwindowsd3d11planesplitter.cpp
Go to the documentation of this file.
1
// Copyright (C) 2026 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4
#
include
"qwindowsd3d11planesplitter_p.h"
5
#
include
"qwindowsd3d11planesplitter_shaders_p.h"
6
7
#
include
<
QtMultimedia
/
private
/
qvideotexturehelper_p
.
h
>
8
9
#
include
<
QtCore
/
qloggingcategory
.
h
>
10
#
include
<
QtCore
/
private
/
qsystemerror_p
.
h
>
11
12
QT_BEGIN_NAMESPACE
13
14
namespace
QtMultimediaPrivate
{
15
16
namespace
{
17
18
Q_LOGGING_CATEGORY(lcD3D11PlaneSplitter,
"qt.multimedia.windows.d3d11planesplitter"
);
19
20
DXGI_FORMAT toPlaneViewFormat(QVideoTextureHelper::TextureDescription::TextureFormat format)
21
{
22
switch
(format) {
23
case
QVideoTextureHelper::TextureDescription::Red_8:
24
return
DXGI_FORMAT_R8_UNORM;
25
case
QVideoTextureHelper::TextureDescription::RG_8:
26
return
DXGI_FORMAT_R8G8_UNORM;
27
case
QVideoTextureHelper::TextureDescription::Red_16:
28
return
DXGI_FORMAT_R16_UNORM;
29
case
QVideoTextureHelper::TextureDescription::RG_16:
30
return
DXGI_FORMAT_R16G16_UNORM;
31
default
:
32
return
DXGI_FORMAT_UNKNOWN;
33
}
34
}
35
36
}
// namespace
37
38
QWindowsD3D11PlaneSplitter
::
QWindowsD3D11PlaneSplitter
() =
default
;
39
QWindowsD3D11PlaneSplitter
::~
QWindowsD3D11PlaneSplitter
() =
default
;
40
41
bool
QWindowsD3D11PlaneSplitter
::
isPixelFormatSupported
(
QVideoFrameFormat
::
PixelFormat
pixelFormat
)
42
{
43
// Matches the D3D11VA surface formats in FFmpeg's hwcontext_d3d11va supported_formats[].
44
switch
(
pixelFormat
) {
45
case
QVideoFrameFormat
::
Format_NV12
:
46
case
QVideoFrameFormat
::
Format_P010
:
47
return
true
;
48
default
:
49
return
false
;
50
}
51
}
52
53
std
::
unique_ptr
<
QWindowsD3D11PlaneSplitter
>
QWindowsD3D11PlaneSplitter
::
create
(
ID3D11Device
*
device
)
54
{
55
Q_ASSERT
(
device
);
56
auto
splitter
=
std
::
unique_ptr
<
QWindowsD3D11PlaneSplitter
>(
new
QWindowsD3D11PlaneSplitter
());
57
if
(!
splitter
->
createPipeline
(
device
))
58
return
nullptr
;
59
return
splitter
;
60
}
61
62
bool
QWindowsD3D11PlaneSplitter
::
createPipeline
(
ID3D11Device
*
device
)
63
{
64
Q_ASSERT
(
device
);
65
Q_ASSERT
(!
m_shaderDevice
);
66
67
if
(
const
HRESULT
hr
=
68
device
->
CreateVertexShader
(
g_planeSplitVS
,
sizeof
(
g_planeSplitVS
),
nullptr
, &
m_vs
);
69
FAILED
(
hr
)) {
70
qCWarning
(
lcD3D11PlaneSplitter
)
71
<<
"CreateVertexShader failed:"
<<
QSystemError
::
windowsComString
(
hr
);
72
return
false
;
73
}
74
75
if
(
const
HRESULT
hr
=
76
device
->
CreatePixelShader
(
g_planeSplitPS
,
sizeof
(
g_planeSplitPS
),
nullptr
, &
m_ps
);
77
FAILED
(
hr
)) {
78
qCWarning
(
lcD3D11PlaneSplitter
)
79
<<
"CreatePixelShader failed:"
<<
QSystemError
::
windowsComString
(
hr
);
80
m_vs
.
Reset
();
81
return
false
;
82
}
83
84
m_shaderDevice
=
device
;
85
return
true
;
86
}
87
88
std
::
pair
<
ComPtr
<
ID3D11Texture2D
>,
UINT
>
QWindowsD3D11PlaneSplitter
::
shaderReadableTexture
(
89
ID3D11Device
*
device
,
ID3D11DeviceContext
*
context
,
const
ComPtr
<
ID3D11Texture2D
> &
texture
,
90
UINT
subresourceIndex
)
91
{
92
D3D11_TEXTURE2D_DESC
srcDesc
{};
93
texture
->
GetDesc
(&
srcDesc
);
94
if
(
srcDesc
.
BindFlags
&
D3D11_BIND_SHADER_RESOURCE
)
95
return
{
texture
,
subresourceIndex
};
96
97
bool
needRecreate
= !
m_shaderReadableCopy
;
98
if
(
m_shaderReadableCopy
) {
99
ComPtr
<
ID3D11Device
>
copyDevice
;
100
m_shaderReadableCopy
->
GetDevice
(&
copyDevice
);
101
D3D11_TEXTURE2D_DESC
copyDesc
{};
102
m_shaderReadableCopy
->
GetDesc
(&
copyDesc
);
103
needRecreate
=
copyDevice
.
Get
() !=
device
||
copyDesc
.
Format
!=
srcDesc
.
Format
104
||
copyDesc
.
Width
!=
srcDesc
.
Width
||
copyDesc
.
Height
!=
srcDesc
.
Height
;
105
}
106
107
if
(
needRecreate
) {
108
D3D11_TEXTURE2D_DESC
copyDesc
{};
109
copyDesc
.
Width
=
srcDesc
.
Width
;
110
copyDesc
.
Height
=
srcDesc
.
Height
;
111
copyDesc
.
MipLevels
= 1;
112
copyDesc
.
ArraySize
= 1;
113
copyDesc
.
Format
=
srcDesc
.
Format
;
114
copyDesc
.
SampleDesc
.
Count
= 1;
115
copyDesc
.
Usage
=
D3D11_USAGE_DEFAULT
;
116
copyDesc
.
BindFlags
=
D3D11_BIND_SHADER_RESOURCE
;
117
118
if
(
const
HRESULT
hr
=
device
->
CreateTexture2D
(
119
&
copyDesc
,
nullptr
,
m_shaderReadableCopy
.
ReleaseAndGetAddressOf
());
120
FAILED
(
hr
)) {
121
qCWarning
(
lcD3D11PlaneSplitter
) <<
"CreateTexture2D failed for shader-readable copy:"
122
<<
QSystemError
::
windowsComString
(
hr
);
123
return
{};
124
}
125
}
126
127
context
->
CopySubresourceRegion
(
m_shaderReadableCopy
.
Get
(), 0, 0, 0, 0,
texture
.
Get
(),
128
subresourceIndex
,
nullptr
);
129
return
{
m_shaderReadableCopy
, 0 };
130
}
131
132
std
::
optional
<
std
::
vector
<
QWindowsD3D11PlaneSplitter
::
Plane
>>
QWindowsD3D11PlaneSplitter
::
split
(
133
ID3D11Device
*
device
,
ID3D11DeviceContext
*
context
,
const
ComPtr
<
ID3D11Texture2D
> &
texture
,
134
UINT
subresourceIndex
,
const
QSize
&
frameSize
,
QVideoFrameFormat
::
PixelFormat
pixelFormat
)
135
{
136
Q_ASSERT
(
device
);
137
Q_ASSERT
(
context
);
138
Q_ASSERT
(
texture
);
139
Q_ASSERT
(
m_shaderDevice
.
Get
() ==
device
);
140
Q_ASSERT
(
m_vs
&&
m_ps
);
141
Q_ASSERT
(
isPixelFormatSupported
(
pixelFormat
));
142
143
const
auto
*
desc
=
QVideoTextureHelper
::
textureDescription
(
pixelFormat
);
144
Q_ASSERT
(
desc
&&
desc
->
nplanes
== 2);
145
146
const
auto
[
sourceTexture
,
sourceSlice
] =
147
shaderReadableTexture
(
device
,
context
,
texture
,
subresourceIndex
);
148
if
(!
sourceTexture
)
149
return
std
::
nullopt
;
150
151
std
::
vector
<
Plane
>
result
;
152
result
.
reserve
(
desc
->
nplanes
);
153
154
context
->
IASetInputLayout
(
nullptr
);
155
context
->
IASetPrimitiveTopology
(
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
);
156
context
->
VSSetShader
(
m_vs
.
Get
(),
nullptr
, 0);
157
context
->
PSSetShader
(
m_ps
.
Get
(),
nullptr
, 0);
158
159
for
(
int
plane
= 0;
plane
<
desc
->
nplanes
; ++
plane
) {
160
const
DXGI_FORMAT
viewFormat
=
toPlaneViewFormat
(
desc
->
textureFormat
[
plane
]);
161
if
(
viewFormat
==
DXGI_FORMAT_UNKNOWN
) {
162
qCWarning
(
lcD3D11PlaneSplitter
) <<
"Unsupported plane texture format for pixel format"
163
<<
pixelFormat
<<
"plane"
<<
plane
;
164
return
std
::
nullopt
;
165
}
166
167
const
QSize
planeSize
{
desc
->
widthForPlane
(
frameSize
.
width
(),
plane
),
168
desc
->
heightForPlane
(
frameSize
.
height
(),
plane
) };
169
170
D3D11_SHADER_RESOURCE_VIEW_DESC
srvDesc
{};
171
srvDesc
.
Format
=
viewFormat
;
172
srvDesc
.
ViewDimension
=
D3D11_SRV_DIMENSION_TEXTURE2DARRAY
;
173
srvDesc
.
Texture2DArray
.
MostDetailedMip
= 0;
174
srvDesc
.
Texture2DArray
.
MipLevels
= 1;
175
srvDesc
.
Texture2DArray
.
FirstArraySlice
=
sourceSlice
;
176
srvDesc
.
Texture2DArray
.
ArraySize
= 1;
177
178
ComPtr
<
ID3D11ShaderResourceView
>
srv
;
179
if
(
const
HRESULT
hr
=
180
device
->
CreateShaderResourceView
(
sourceTexture
.
Get
(), &
srvDesc
, &
srv
);
181
FAILED
(
hr
)) {
182
qCWarning
(
lcD3D11PlaneSplitter
) <<
"CreateShaderResourceView failed for plane"
<<
plane
183
<<
":"
<<
QSystemError
::
windowsComString
(
hr
);
184
return
std
::
nullopt
;
185
}
186
187
D3D11_TEXTURE2D_DESC
rtDesc
{};
188
rtDesc
.
Width
=
static_cast
<
UINT
>(
planeSize
.
width
());
189
rtDesc
.
Height
=
static_cast
<
UINT
>(
planeSize
.
height
());
190
rtDesc
.
MipLevels
= 1;
191
rtDesc
.
ArraySize
= 1;
192
rtDesc
.
Format
=
viewFormat
;
193
rtDesc
.
SampleDesc
.
Count
= 1;
194
rtDesc
.
Usage
=
D3D11_USAGE_DEFAULT
;
195
rtDesc
.
BindFlags
=
D3D11_BIND_RENDER_TARGET
;
196
197
ComPtr
<
ID3D11Texture2D
>
planeTex
;
198
if
(
const
HRESULT
hr
=
device
->
CreateTexture2D
(&
rtDesc
,
nullptr
, &
planeTex
);
FAILED
(
hr
)) {
199
qCWarning
(
lcD3D11PlaneSplitter
) <<
"CreateTexture2D failed for plane"
<<
plane
<<
":"
200
<<
QSystemError
::
windowsComString
(
hr
);
201
return
std
::
nullopt
;
202
}
203
204
ComPtr
<
ID3D11RenderTargetView
>
rtv
;
205
if
(
const
HRESULT
hr
=
device
->
CreateRenderTargetView
(
planeTex
.
Get
(),
nullptr
, &
rtv
);
206
FAILED
(
hr
)) {
207
qCWarning
(
lcD3D11PlaneSplitter
) <<
"CreateRenderTargetView failed for plane"
<<
plane
208
<<
":"
<<
QSystemError
::
windowsComString
(
hr
);
209
return
std
::
nullopt
;
210
}
211
212
const
D3D11_VIEWPORT
viewport
{
213
0.0f, 0.0f,
float
(
planeSize
.
width
()),
float
(
planeSize
.
height
()), 0.0f, 1.0f
214
};
215
context
->
RSSetViewports
(1, &
viewport
);
216
ID3D11RenderTargetView
*
rtvs
[] = {
rtv
.
Get
() };
217
context
->
OMSetRenderTargets
(1,
rtvs
,
nullptr
);
218
ID3D11ShaderResourceView
*
srvs
[] = {
srv
.
Get
() };
219
context
->
PSSetShaderResources
(0, 1,
srvs
);
220
context
->
Draw
(3, 0);
221
222
result
.
push_back
({
std
::
move
(
planeTex
),
planeSize
});
223
}
224
225
ID3D11ShaderResourceView
*
nullSrvs
[] = {
nullptr
};
226
context
->
PSSetShaderResources
(0, 1,
nullSrvs
);
227
ID3D11RenderTargetView
*
nullRtvs
[] = {
nullptr
};
228
context
->
OMSetRenderTargets
(1,
nullRtvs
,
nullptr
);
229
230
return
result
;
231
}
232
233
}
// namespace QtMultimediaPrivate
234
235
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
QtMultimediaPrivate::impl
Definition
qaudiosystem_p.h:257
qtmultimedia
src
multimedia
windows
qwindowsd3d11planesplitter.cpp
Generated on
for Qt by
1.16.1