1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "d3d12_context.h"
25bf215546Sopenharmony_ci#include "d3d12_screen.h"
26bf215546Sopenharmony_ci#include "d3d12_video_proc.h"
27bf215546Sopenharmony_ci#include "d3d12_residency.h"
28bf215546Sopenharmony_ci#include "d3d12_util.h"
29bf215546Sopenharmony_ci#include "d3d12_resource.h"
30bf215546Sopenharmony_ci#include "d3d12_video_buffer.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_civoid
33bf215546Sopenharmony_cid3d12_video_processor_begin_frame(struct pipe_video_codec * codec,
34bf215546Sopenharmony_ci                                struct pipe_video_buffer *target,
35bf215546Sopenharmony_ci                                struct pipe_picture_desc *picture)
36bf215546Sopenharmony_ci{
37bf215546Sopenharmony_ci    struct d3d12_video_processor * pD3D12Proc = (struct d3d12_video_processor *) codec;
38bf215546Sopenharmony_ci    debug_printf("[d3d12_video_processor] d3d12_video_processor_begin_frame - "
39bf215546Sopenharmony_ci                "fenceValue: %d\n",
40bf215546Sopenharmony_ci                pD3D12Proc->m_fenceValue);
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci    // Setup process frame arguments for output/target texture.
43bf215546Sopenharmony_ci    struct d3d12_video_buffer *pOutputVideoBuffer = (struct d3d12_video_buffer *) target;
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci    // Make the resources permanently resident for video use
46bf215546Sopenharmony_ci    d3d12_promote_to_permanent_residency(pD3D12Proc->m_pD3D12Screen, pOutputVideoBuffer->texture);
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci    ID3D12Resource *pDstD3D12Res = d3d12_resource_resource(pOutputVideoBuffer->texture);
49bf215546Sopenharmony_ci    auto dstDesc = GetDesc(pDstD3D12Res);
50bf215546Sopenharmony_ci    pD3D12Proc->m_OutputArguments = {
51bf215546Sopenharmony_ci        {
52bf215546Sopenharmony_ci            {
53bf215546Sopenharmony_ci                    pDstD3D12Res, // ID3D12Resource *pTexture2D;
54bf215546Sopenharmony_ci                    0, // UINT Subresource;
55bf215546Sopenharmony_ci            },
56bf215546Sopenharmony_ci            {
57bf215546Sopenharmony_ci                    NULL, // ID3D12Resource *pTexture2D;
58bf215546Sopenharmony_ci                    0 // UINT Subresource;
59bf215546Sopenharmony_ci            }
60bf215546Sopenharmony_ci        },
61bf215546Sopenharmony_ci        { 0, 0, (int) dstDesc.Width, (int) dstDesc.Height }
62bf215546Sopenharmony_ci    };
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci    debug_printf("d3d12_video_processor_begin_frame: Beginning new scene with Output ID3D12Resource: %p (%d %d)\n", pDstD3D12Res, (int) dstDesc.Width, (int) dstDesc.Height);
65bf215546Sopenharmony_ci}
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_civoid
68bf215546Sopenharmony_cid3d12_video_processor_end_frame(struct pipe_video_codec * codec,
69bf215546Sopenharmony_ci                              struct pipe_video_buffer *target,
70bf215546Sopenharmony_ci                              struct pipe_picture_desc *picture)
71bf215546Sopenharmony_ci{
72bf215546Sopenharmony_ci    struct d3d12_video_processor * pD3D12Proc = (struct d3d12_video_processor *) codec;
73bf215546Sopenharmony_ci    debug_printf("[d3d12_video_processor] d3d12_video_processor_end_frame - "
74bf215546Sopenharmony_ci                "fenceValue: %d\n",
75bf215546Sopenharmony_ci                pD3D12Proc->m_fenceValue);
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_ci    auto curOutputDesc = GetOutputStreamDesc(pD3D12Proc->m_spVideoProcessor.Get());
78bf215546Sopenharmony_ci    auto curOutputTexFmt = GetDesc(pD3D12Proc->m_OutputArguments.OutputStream[0].pTexture2D).Format;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci    bool inputFmtsMatch = pD3D12Proc->m_inputStreamDescs.size() == pD3D12Proc->m_ProcessInputs.size();
81bf215546Sopenharmony_ci    unsigned curInputIdx = 0;
82bf215546Sopenharmony_ci    while( (curInputIdx < pD3D12Proc->m_inputStreamDescs.size()) && inputFmtsMatch)
83bf215546Sopenharmony_ci    {
84bf215546Sopenharmony_ci        inputFmtsMatch = inputFmtsMatch && (pD3D12Proc->m_inputStreamDescs[curInputIdx].Format == GetDesc(pD3D12Proc->m_ProcessInputs[curInputIdx].InputStream[0].pTexture2D).Format);
85bf215546Sopenharmony_ci        curInputIdx++;
86bf215546Sopenharmony_ci    }
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci    bool inputCountMatches = (pD3D12Proc->m_ProcessInputs.size() == pD3D12Proc->m_spVideoProcessor->GetNumInputStreamDescs());
89bf215546Sopenharmony_ci    bool outputFmtMatches = (curOutputDesc.Format == curOutputTexFmt);
90bf215546Sopenharmony_ci    bool needsVPRecreation = (
91bf215546Sopenharmony_ci        !inputCountMatches // Requested batch has different number of Inputs to be blit'd
92bf215546Sopenharmony_ci        || !outputFmtMatches // output texture format different than vid proc object expects
93bf215546Sopenharmony_ci        || !inputFmtsMatch // inputs texture formats different than vid proc object expects
94bf215546Sopenharmony_ci    );
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci    if(needsVPRecreation) {
97bf215546Sopenharmony_ci        debug_printf("[d3d12_video_processor] d3d12_video_processor_end_frame - Attempting to re-create ID3D12VideoProcessor "
98bf215546Sopenharmony_ci                      "input count matches %d inputFmtsMatch: %d outputFmtsMatch %d \n", inputCountMatches, inputFmtsMatch, outputFmtMatches);
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci        DXGI_COLOR_SPACE_TYPE InputColorSpace = DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
101bf215546Sopenharmony_ci        DXGI_FORMAT OutputFormat = curOutputTexFmt;
102bf215546Sopenharmony_ci        DXGI_COLOR_SPACE_TYPE OutputColorSpace = DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci        std::vector<DXGI_FORMAT> InputFormats;
105bf215546Sopenharmony_ci        for(D3D12_VIDEO_PROCESS_INPUT_STREAM_ARGUMENTS1 curInput : pD3D12Proc->m_ProcessInputs)
106bf215546Sopenharmony_ci        {
107bf215546Sopenharmony_ci            InputFormats.push_back(GetDesc(curInput.InputStream[0].pTexture2D).Format);
108bf215546Sopenharmony_ci        }
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci        if(!d3d12_video_processor_check_caps_and_create_processor(pD3D12Proc, InputFormats, InputColorSpace, OutputFormat, OutputColorSpace))
111bf215546Sopenharmony_ci        {
112bf215546Sopenharmony_ci            debug_printf("[d3d12_video_processor] d3d12_video_processor_end_frame - Failure when "
113bf215546Sopenharmony_ci                      " trying to re-create the ID3D12VideoProcessor for current batch streams configuration\n");
114bf215546Sopenharmony_ci            assert(false);
115bf215546Sopenharmony_ci        }
116bf215546Sopenharmony_ci    }
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci    // Schedule barrier transitions
119bf215546Sopenharmony_ci    std::vector<D3D12_RESOURCE_BARRIER> barrier_transitions;
120bf215546Sopenharmony_ci    barrier_transitions.push_back(CD3DX12_RESOURCE_BARRIER::Transition(
121bf215546Sopenharmony_ci                                pD3D12Proc->m_OutputArguments.OutputStream[0].pTexture2D,
122bf215546Sopenharmony_ci                                D3D12_RESOURCE_STATE_COMMON,
123bf215546Sopenharmony_ci                                D3D12_RESOURCE_STATE_VIDEO_PROCESS_WRITE));
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci    for(D3D12_VIDEO_PROCESS_INPUT_STREAM_ARGUMENTS1 curInput : pD3D12Proc->m_ProcessInputs)
126bf215546Sopenharmony_ci        barrier_transitions.push_back(CD3DX12_RESOURCE_BARRIER::Transition(
127bf215546Sopenharmony_ci                                    curInput.InputStream[0].pTexture2D,
128bf215546Sopenharmony_ci                                    D3D12_RESOURCE_STATE_COMMON,
129bf215546Sopenharmony_ci                                    D3D12_RESOURCE_STATE_VIDEO_PROCESS_READ));
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci    pD3D12Proc->m_spCommandList->ResourceBarrier(static_cast<uint32_t>(barrier_transitions.size()), barrier_transitions.data());
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci    // Schedule process operation
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci    pD3D12Proc->m_spCommandList->ProcessFrames1(pD3D12Proc->m_spVideoProcessor.Get(), &pD3D12Proc->m_OutputArguments, pD3D12Proc->m_ProcessInputs.size(), pD3D12Proc->m_ProcessInputs.data());
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci    // Schedule reverse (back to common) transitions before command list closes for current frame
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ci    for (auto &BarrierDesc : barrier_transitions)
140bf215546Sopenharmony_ci        std::swap(BarrierDesc.Transition.StateBefore, BarrierDesc.Transition.StateAfter);
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci    pD3D12Proc->m_spCommandList->ResourceBarrier(static_cast<uint32_t>(barrier_transitions.size()), barrier_transitions.data());
143bf215546Sopenharmony_ci}
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_civoid
146bf215546Sopenharmony_cid3d12_video_processor_process_frame(struct pipe_video_codec *codec,
147bf215546Sopenharmony_ci                        struct pipe_video_buffer *input_texture,
148bf215546Sopenharmony_ci                        const struct pipe_vpp_desc *process_properties)
149bf215546Sopenharmony_ci{
150bf215546Sopenharmony_ci    struct d3d12_video_processor * pD3D12Proc = (struct d3d12_video_processor *) codec;
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci    // Get the underlying resources from the pipe_video_buffers
153bf215546Sopenharmony_ci    struct d3d12_video_buffer *pInputVideoBuffer = (struct d3d12_video_buffer *) input_texture;
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci    // Make the resources permanently resident for video use
156bf215546Sopenharmony_ci    d3d12_promote_to_permanent_residency(pD3D12Proc->m_pD3D12Screen, pInputVideoBuffer->texture);
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci    ID3D12Resource *pSrcD3D12Res = d3d12_resource_resource(pInputVideoBuffer->texture);
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_ci    // y0 = top
161bf215546Sopenharmony_ci    // x0 = left
162bf215546Sopenharmony_ci    // x1 = right
163bf215546Sopenharmony_ci    // y1 = bottom
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci    debug_printf("d3d12_video_processor_process_frame: Adding Input ID3D12Resource: %p to scene (Output target %p)\n", pSrcD3D12Res, pD3D12Proc->m_OutputArguments.OutputStream[0].pTexture2D);
166bf215546Sopenharmony_ci    debug_printf("d3d12_video_processor_process_frame: Input box: top: %d left: %d right: %d bottom: %d\n", process_properties->src_region.y0, process_properties->src_region.x0, process_properties->src_region.x1, process_properties->src_region.y1);
167bf215546Sopenharmony_ci    debug_printf("d3d12_video_processor_process_frame: Output box: top: %d left: %d right: %d bottom: %d\n", process_properties->dst_region.y0, process_properties->dst_region.x0, process_properties->dst_region.x1, process_properties->dst_region.y1);
168bf215546Sopenharmony_ci    debug_printf("d3d12_video_processor_process_frame: Requested alpha blend mode %d global alpha: %f \n", process_properties->blend.mode, process_properties->blend.global_alpha);
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci    // Setup process frame arguments for current input texture.
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci    unsigned curInputStreamIndex = pD3D12Proc->m_ProcessInputs.size();
173bf215546Sopenharmony_ci    D3D12_VIDEO_PROCESS_INPUT_STREAM_ARGUMENTS1 InputArguments = {
174bf215546Sopenharmony_ci        {
175bf215546Sopenharmony_ci        { // D3D12_VIDEO_PROCESS_INPUT_STREAM InputStream[0];
176bf215546Sopenharmony_ci                pSrcD3D12Res, // ID3D12Resource *pTexture2D;
177bf215546Sopenharmony_ci                0, // UINT Subresource
178bf215546Sopenharmony_ci                {//D3D12_VIDEO_PROCESS_REFERENCE_SET ReferenceSet;
179bf215546Sopenharmony_ci                    0, //UINT NumPastFrames;
180bf215546Sopenharmony_ci                    NULL, //ID3D12Resource **ppPastFrames;
181bf215546Sopenharmony_ci                    NULL, // UINT *pPastSubresources;
182bf215546Sopenharmony_ci                    0, //UINT NumFutureFrames;
183bf215546Sopenharmony_ci                    NULL, //ID3D12Resource **ppFutureFrames;
184bf215546Sopenharmony_ci                    NULL //UINT *pFutureSubresources;
185bf215546Sopenharmony_ci                }
186bf215546Sopenharmony_ci        },
187bf215546Sopenharmony_ci        { // D3D12_VIDEO_PROCESS_INPUT_STREAM InputStream[1];
188bf215546Sopenharmony_ci                NULL, //ID3D12Resource *pTexture2D;
189bf215546Sopenharmony_ci                0, //UINT Subresource;
190bf215546Sopenharmony_ci                {//D3D12_VIDEO_PROCESS_REFERENCE_SET ReferenceSet;
191bf215546Sopenharmony_ci                    0, //UINT NumPastFrames;
192bf215546Sopenharmony_ci                    NULL, //ID3D12Resource **ppPastFrames;
193bf215546Sopenharmony_ci                    NULL, // UINT *pPastSubresources;
194bf215546Sopenharmony_ci                    0, //UINT NumFutureFrames;
195bf215546Sopenharmony_ci                    NULL, //ID3D12Resource **ppFutureFrames;
196bf215546Sopenharmony_ci                    NULL //UINT *pFutureSubresources;
197bf215546Sopenharmony_ci                }
198bf215546Sopenharmony_ci        }
199bf215546Sopenharmony_ci        },
200bf215546Sopenharmony_ci        { // D3D12_VIDEO_PROCESS_TRANSFORM Transform;
201bf215546Sopenharmony_ci            // y0 = top
202bf215546Sopenharmony_ci            // x0 = left
203bf215546Sopenharmony_ci            // x1 = right
204bf215546Sopenharmony_ci            // y1 = bottom
205bf215546Sopenharmony_ci            // typedef struct _RECT
206bf215546Sopenharmony_ci            // {
207bf215546Sopenharmony_ci            //     int left;
208bf215546Sopenharmony_ci            //     int top;
209bf215546Sopenharmony_ci            //     int right;
210bf215546Sopenharmony_ci            //     int bottom;
211bf215546Sopenharmony_ci            // } RECT;
212bf215546Sopenharmony_ci            { process_properties->src_region.x0/*left*/, process_properties->src_region.y0/*top*/, process_properties->src_region.x1/*right*/, process_properties->src_region.y1/*bottom*/ },
213bf215546Sopenharmony_ci            { process_properties->dst_region.x0/*left*/, process_properties->dst_region.y0/*top*/, process_properties->dst_region.x1/*right*/, process_properties->dst_region.y1/*bottom*/ }, // D3D12_RECT DestinationRectangle;
214bf215546Sopenharmony_ci            pD3D12Proc->m_inputStreamDescs[curInputStreamIndex].EnableOrientation ? d3d12_video_processor_convert_pipe_rotation(process_properties->orientation) : D3D12_VIDEO_PROCESS_ORIENTATION_DEFAULT, // D3D12_VIDEO_PROCESS_ORIENTATION Orientation;
215bf215546Sopenharmony_ci        },
216bf215546Sopenharmony_ci        D3D12_VIDEO_PROCESS_INPUT_STREAM_FLAG_NONE,
217bf215546Sopenharmony_ci        { // D3D12_VIDEO_PROCESS_INPUT_STREAM_RATE RateInfo;
218bf215546Sopenharmony_ci            0,
219bf215546Sopenharmony_ci            0,
220bf215546Sopenharmony_ci        },
221bf215546Sopenharmony_ci        // INT                                    FilterLevels[32];
222bf215546Sopenharmony_ci        {
223bf215546Sopenharmony_ci            0, // Trailing zeroes on the rest
224bf215546Sopenharmony_ci        },
225bf215546Sopenharmony_ci        //D3D12_VIDEO_PROCESS_ALPHA_BLENDING;
226bf215546Sopenharmony_ci        {
227bf215546Sopenharmony_ci            (process_properties->blend.mode == PIPE_VIDEO_VPP_BLEND_MODE_GLOBAL_ALPHA),
228bf215546Sopenharmony_ci            process_properties->blend.global_alpha
229bf215546Sopenharmony_ci        },
230bf215546Sopenharmony_ci        // D3D12_VIDEO_FIELD_TYPE FieldType
231bf215546Sopenharmony_ci        D3D12_VIDEO_FIELD_TYPE_NONE,
232bf215546Sopenharmony_ci    };
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci    debug_printf("ProcessFrame InArgs Orientation %d \n\tSrc top: %d left: %d right: %d bottom: %d\n\tDst top: %d left: %d right: %d bottom: %d\n", InputArguments.Transform.Orientation,
235bf215546Sopenharmony_ci        InputArguments.Transform.SourceRectangle.top, InputArguments.Transform.SourceRectangle.left, InputArguments.Transform.SourceRectangle.right, InputArguments.Transform.SourceRectangle.bottom,
236bf215546Sopenharmony_ci        InputArguments.Transform.DestinationRectangle.top, InputArguments.Transform.DestinationRectangle.left, InputArguments.Transform.DestinationRectangle.right, InputArguments.Transform.DestinationRectangle.bottom);
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci    pD3D12Proc->m_ProcessInputs.push_back(InputArguments);
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_ci    ///
241bf215546Sopenharmony_ci    /// Flush work to the GPU and blocking wait until GPU finishes
242bf215546Sopenharmony_ci    ///
243bf215546Sopenharmony_ci    pD3D12Proc->m_needsGPUFlush = true;
244bf215546Sopenharmony_ci}
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_civoid
247bf215546Sopenharmony_cid3d12_video_processor_destroy(struct pipe_video_codec * codec)
248bf215546Sopenharmony_ci{
249bf215546Sopenharmony_ci    if (codec == nullptr) {
250bf215546Sopenharmony_ci        return;
251bf215546Sopenharmony_ci    }
252bf215546Sopenharmony_ci    d3d12_video_processor_flush(codec);   // Flush pending work before destroying.
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci    // Call dtor to make ComPtr work
255bf215546Sopenharmony_ci    struct d3d12_video_processor * pD3D12Proc = (struct d3d12_video_processor *) codec;
256bf215546Sopenharmony_ci    delete pD3D12Proc;
257bf215546Sopenharmony_ci}
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_civoid
260bf215546Sopenharmony_cid3d12_video_processor_flush(struct pipe_video_codec * codec)
261bf215546Sopenharmony_ci{
262bf215546Sopenharmony_ci    struct d3d12_video_processor * pD3D12Proc = (struct d3d12_video_processor *) codec;
263bf215546Sopenharmony_ci    assert(pD3D12Proc);
264bf215546Sopenharmony_ci    assert(pD3D12Proc->m_spD3D12VideoDevice);
265bf215546Sopenharmony_ci    assert(pD3D12Proc->m_spCommandQueue);
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci    // Flush buffer_subdata batch and Wait the m_spCommandQueue for GPU upload completion
268bf215546Sopenharmony_ci    // before executing the current batch below. Input objects coming from the pipe_context (ie. input texture) must be fully finished working with before processor can read them.
269bf215546Sopenharmony_ci    struct pipe_fence_handle *completion_fence = NULL;
270bf215546Sopenharmony_ci    debug_printf("[d3d12_video_processor] d3d12_video_processor_flush - Flushing pD3D12Proc->m_pD3D12Context->base. and GPU sync between Video/Context queues before flushing Video Process Queue.\n");
271bf215546Sopenharmony_ci    pD3D12Proc->m_pD3D12Context->base.flush(&pD3D12Proc->m_pD3D12Context->base, &completion_fence, PIPE_FLUSH_ASYNC | PIPE_FLUSH_HINT_FINISH);
272bf215546Sopenharmony_ci    assert(completion_fence);
273bf215546Sopenharmony_ci    struct d3d12_fence *casted_completion_fence = d3d12_fence(completion_fence);
274bf215546Sopenharmony_ci    pD3D12Proc->m_spCommandQueue->Wait(casted_completion_fence->cmdqueue_fence, casted_completion_fence->value);
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci    debug_printf("[d3d12_video_processor] d3d12_video_processor_flush started. Will flush video queue work and CPU wait on "
277bf215546Sopenharmony_ci                    "fenceValue: %d\n",
278bf215546Sopenharmony_ci                    pD3D12Proc->m_fenceValue);
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci    if (!pD3D12Proc->m_needsGPUFlush) {
281bf215546Sopenharmony_ci        debug_printf("[d3d12_video_processor] d3d12_video_processor_flush started. Nothing to flush, all up to date.\n");
282bf215546Sopenharmony_ci    } else {
283bf215546Sopenharmony_ci        HRESULT hr = pD3D12Proc->m_pD3D12Screen->dev->GetDeviceRemovedReason();
284bf215546Sopenharmony_ci        if (hr != S_OK) {
285bf215546Sopenharmony_ci            debug_printf("[d3d12_video_processor] d3d12_video_processor_flush"
286bf215546Sopenharmony_ci                            " - D3D12Device was removed BEFORE commandlist "
287bf215546Sopenharmony_ci                            "execution with HR %x.\n",
288bf215546Sopenharmony_ci                            hr);
289bf215546Sopenharmony_ci            goto flush_fail;
290bf215546Sopenharmony_ci        }
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci        // Close and execute command list and wait for idle on CPU blocking
293bf215546Sopenharmony_ci        // this method before resetting list and allocator for next submission.
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_ci        if (pD3D12Proc->m_transitionsBeforeCloseCmdList.size() > 0) {
296bf215546Sopenharmony_ci            pD3D12Proc->m_spCommandList->ResourceBarrier(pD3D12Proc->m_transitionsBeforeCloseCmdList.size(),
297bf215546Sopenharmony_ci                                                            pD3D12Proc->m_transitionsBeforeCloseCmdList.data());
298bf215546Sopenharmony_ci            pD3D12Proc->m_transitionsBeforeCloseCmdList.clear();
299bf215546Sopenharmony_ci        }
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci        hr = pD3D12Proc->m_spCommandList->Close();
302bf215546Sopenharmony_ci        if (FAILED(hr)) {
303bf215546Sopenharmony_ci            debug_printf("[d3d12_video_processor] d3d12_video_processor_flush - Can't close command list with HR %x\n", hr);
304bf215546Sopenharmony_ci            goto flush_fail;
305bf215546Sopenharmony_ci        }
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci        ID3D12CommandList *ppCommandLists[1] = { pD3D12Proc->m_spCommandList.Get() };
308bf215546Sopenharmony_ci        pD3D12Proc->m_spCommandQueue->ExecuteCommandLists(1, ppCommandLists);
309bf215546Sopenharmony_ci        pD3D12Proc->m_spCommandQueue->Signal(pD3D12Proc->m_spFence.Get(), pD3D12Proc->m_fenceValue);
310bf215546Sopenharmony_ci        pD3D12Proc->m_spFence->SetEventOnCompletion(pD3D12Proc->m_fenceValue, nullptr);
311bf215546Sopenharmony_ci        debug_printf("[d3d12_video_processor] d3d12_video_processor_flush - ExecuteCommandLists finished on signal with "
312bf215546Sopenharmony_ci                        "fenceValue: %d\n",
313bf215546Sopenharmony_ci                        pD3D12Proc->m_fenceValue);
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci        hr = pD3D12Proc->m_spCommandAllocator->Reset();
316bf215546Sopenharmony_ci        if (FAILED(hr)) {
317bf215546Sopenharmony_ci            debug_printf(
318bf215546Sopenharmony_ci                "[d3d12_video_processor] d3d12_video_processor_flush - resetting ID3D12CommandAllocator failed with HR %x\n",
319bf215546Sopenharmony_ci                hr);
320bf215546Sopenharmony_ci            goto flush_fail;
321bf215546Sopenharmony_ci        }
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci        hr = pD3D12Proc->m_spCommandList->Reset(pD3D12Proc->m_spCommandAllocator.Get());
324bf215546Sopenharmony_ci        if (FAILED(hr)) {
325bf215546Sopenharmony_ci            debug_printf(
326bf215546Sopenharmony_ci                "[d3d12_video_processor] d3d12_video_processor_flush - resetting ID3D12GraphicsCommandList failed with HR %x\n",
327bf215546Sopenharmony_ci                hr);
328bf215546Sopenharmony_ci            goto flush_fail;
329bf215546Sopenharmony_ci        }
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci        // Validate device was not removed
332bf215546Sopenharmony_ci        hr = pD3D12Proc->m_pD3D12Screen->dev->GetDeviceRemovedReason();
333bf215546Sopenharmony_ci        if (hr != S_OK) {
334bf215546Sopenharmony_ci            debug_printf("[d3d12_video_processor] d3d12_video_processor_flush"
335bf215546Sopenharmony_ci                            " - D3D12Device was removed AFTER commandlist "
336bf215546Sopenharmony_ci                            "execution with HR %x, but wasn't before.\n",
337bf215546Sopenharmony_ci                            hr);
338bf215546Sopenharmony_ci            goto flush_fail;
339bf215546Sopenharmony_ci        }
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci        debug_printf(
342bf215546Sopenharmony_ci            "[d3d12_video_processor] d3d12_video_processor_flush - GPU signaled execution finalized for fenceValue: %d\n",
343bf215546Sopenharmony_ci            pD3D12Proc->m_fenceValue);
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci        pD3D12Proc->m_fenceValue++;
346bf215546Sopenharmony_ci        pD3D12Proc->m_needsGPUFlush = false;
347bf215546Sopenharmony_ci    }
348bf215546Sopenharmony_ci    pD3D12Proc->m_ProcessInputs.clear();
349bf215546Sopenharmony_ci    // Free the fence after completion finished
350bf215546Sopenharmony_ci    if(completion_fence)
351bf215546Sopenharmony_ci        pD3D12Proc->m_pD3D12Screen->base.fence_reference(&pD3D12Proc->m_pD3D12Screen->base, &completion_fence, NULL);
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ci    return;
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ciflush_fail:
356bf215546Sopenharmony_ci    debug_printf("[d3d12_video_processor] d3d12_video_processor_flush failed for fenceValue: %d\n", pD3D12Proc->m_fenceValue);
357bf215546Sopenharmony_ci    assert(false);
358bf215546Sopenharmony_ci}
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_cistruct pipe_video_codec *
361bf215546Sopenharmony_cid3d12_video_processor_create(struct pipe_context *context, const struct pipe_video_codec *codec)
362bf215546Sopenharmony_ci{
363bf215546Sopenharmony_ci   ///
364bf215546Sopenharmony_ci   /// Initialize d3d12_video_processor
365bf215546Sopenharmony_ci   ///
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   // Not using new doesn't call ctor and the initializations in the class declaration are lost
368bf215546Sopenharmony_ci   struct d3d12_video_processor *pD3D12Proc = new d3d12_video_processor;
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci   pD3D12Proc->base = *codec;
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci   pD3D12Proc->base.context = context;
373bf215546Sopenharmony_ci   pD3D12Proc->base.width = codec->width;
374bf215546Sopenharmony_ci   pD3D12Proc->base.height = codec->height;
375bf215546Sopenharmony_ci   pD3D12Proc->base.destroy = d3d12_video_processor_destroy;
376bf215546Sopenharmony_ci   pD3D12Proc->base.begin_frame = d3d12_video_processor_begin_frame;
377bf215546Sopenharmony_ci   pD3D12Proc->base.process_frame = d3d12_video_processor_process_frame;
378bf215546Sopenharmony_ci   pD3D12Proc->base.end_frame = d3d12_video_processor_end_frame;
379bf215546Sopenharmony_ci   pD3D12Proc->base.flush = d3d12_video_processor_flush;
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci   ///
382bf215546Sopenharmony_ci
383bf215546Sopenharmony_ci   ///
384bf215546Sopenharmony_ci   /// Try initializing D3D12 Video device and check for device caps
385bf215546Sopenharmony_ci   ///
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_ci   struct d3d12_context *pD3D12Ctx = (struct d3d12_context *) context;
388bf215546Sopenharmony_ci   pD3D12Proc->m_pD3D12Context = pD3D12Ctx;
389bf215546Sopenharmony_ci   pD3D12Proc->m_pD3D12Screen = d3d12_screen(pD3D12Ctx->base.screen);
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci    // Assume defaults for now, can re-create if necessary when d3d12_video_processor_end_frame kicks off the processing
392bf215546Sopenharmony_ci    DXGI_COLOR_SPACE_TYPE InputColorSpace = DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
393bf215546Sopenharmony_ci    std::vector<DXGI_FORMAT> InputFormats = { DXGI_FORMAT_NV12 };
394bf215546Sopenharmony_ci    DXGI_FORMAT OutputFormat = DXGI_FORMAT_NV12;
395bf215546Sopenharmony_ci    DXGI_COLOR_SPACE_TYPE OutputColorSpace = DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
396bf215546Sopenharmony_ci
397bf215546Sopenharmony_ci   ///
398bf215546Sopenharmony_ci   /// Create processor objects
399bf215546Sopenharmony_ci   ///
400bf215546Sopenharmony_ci   if (FAILED(pD3D12Proc->m_pD3D12Screen->dev->QueryInterface(
401bf215546Sopenharmony_ci          IID_PPV_ARGS(pD3D12Proc->m_spD3D12VideoDevice.GetAddressOf())))) {
402bf215546Sopenharmony_ci      debug_printf("[d3d12_video_processor] d3d12_video_create_processor - D3D12 Device has no Video support\n");
403bf215546Sopenharmony_ci      goto failed;
404bf215546Sopenharmony_ci   }
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_ci   if (!d3d12_video_processor_check_caps_and_create_processor(pD3D12Proc, InputFormats, InputColorSpace, OutputFormat, OutputColorSpace)) {
407bf215546Sopenharmony_ci      debug_printf("[d3d12_video_processor] d3d12_video_create_processor - Failure on "
408bf215546Sopenharmony_ci                      "d3d12_video_processor_check_caps_and_create_processor\n");
409bf215546Sopenharmony_ci      goto failed;
410bf215546Sopenharmony_ci   }
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci   if (!d3d12_video_processor_create_command_objects(pD3D12Proc)) {
413bf215546Sopenharmony_ci      debug_printf(
414bf215546Sopenharmony_ci         "[d3d12_video_processor] d3d12_video_create_processor - Failure on d3d12_video_processor_create_command_objects\n");
415bf215546Sopenharmony_ci      goto failed;
416bf215546Sopenharmony_ci   }
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_ci    debug_printf("[d3d12_video_processor] d3d12_video_create_processor - Created successfully!\n");
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_ci   return &pD3D12Proc->base;
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_cifailed:
423bf215546Sopenharmony_ci   if (pD3D12Proc != nullptr) {
424bf215546Sopenharmony_ci      d3d12_video_processor_destroy(&pD3D12Proc->base);
425bf215546Sopenharmony_ci   }
426bf215546Sopenharmony_ci
427bf215546Sopenharmony_ci   return nullptr;
428bf215546Sopenharmony_ci}
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_cibool
431bf215546Sopenharmony_cid3d12_video_processor_check_caps_and_create_processor(struct d3d12_video_processor *pD3D12Proc,
432bf215546Sopenharmony_ci                                                        std::vector<DXGI_FORMAT> InputFormats,
433bf215546Sopenharmony_ci                                                        DXGI_COLOR_SPACE_TYPE InputColorSpace,
434bf215546Sopenharmony_ci                                                        DXGI_FORMAT OutputFormat,
435bf215546Sopenharmony_ci                                                        DXGI_COLOR_SPACE_TYPE OutputColorSpace)
436bf215546Sopenharmony_ci{
437bf215546Sopenharmony_ci    HRESULT hr = S_OK;
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_ci    D3D12_VIDEO_FIELD_TYPE FieldType = D3D12_VIDEO_FIELD_TYPE_NONE;
440bf215546Sopenharmony_ci    D3D12_VIDEO_FRAME_STEREO_FORMAT StereoFormat = D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE;
441bf215546Sopenharmony_ci    DXGI_RATIONAL FrameRate = { 30, 1 };
442bf215546Sopenharmony_ci    DXGI_RATIONAL AspectRatio = { 1, 1 };
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci    struct ResolStruct {
445bf215546Sopenharmony_ci        uint Width;
446bf215546Sopenharmony_ci        uint Height;
447bf215546Sopenharmony_ci    };
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci    ResolStruct resolutionsList[] = {
450bf215546Sopenharmony_ci        { 8192, 8192 },   // 8k
451bf215546Sopenharmony_ci        { 8192, 4320 },   // 8k - alternative
452bf215546Sopenharmony_ci        { 7680, 4800 },   // 8k - alternative
453bf215546Sopenharmony_ci        { 7680, 4320 },   // 8k - alternative
454bf215546Sopenharmony_ci        { 4096, 2304 },   // 2160p (4K)
455bf215546Sopenharmony_ci        { 4096, 2160 },   // 2160p (4K) - alternative
456bf215546Sopenharmony_ci        { 2560, 1440 },   // 1440p
457bf215546Sopenharmony_ci        { 1920, 1200 },   // 1200p
458bf215546Sopenharmony_ci        { 1920, 1080 },   // 1080p
459bf215546Sopenharmony_ci        { 1280, 720 },    // 720p
460bf215546Sopenharmony_ci        { 800, 600 },
461bf215546Sopenharmony_ci    };
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_ci    pD3D12Proc->m_SupportCaps =
464bf215546Sopenharmony_ci    {
465bf215546Sopenharmony_ci        0, // NodeIndex
466bf215546Sopenharmony_ci        { resolutionsList[0].Width, resolutionsList[0].Height, { InputFormats[0], InputColorSpace } },
467bf215546Sopenharmony_ci        FieldType,
468bf215546Sopenharmony_ci        StereoFormat,
469bf215546Sopenharmony_ci        FrameRate,
470bf215546Sopenharmony_ci        { OutputFormat, OutputColorSpace },
471bf215546Sopenharmony_ci        StereoFormat,
472bf215546Sopenharmony_ci        FrameRate,
473bf215546Sopenharmony_ci    };
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_ci    uint32_t idxResol = 0;
476bf215546Sopenharmony_ci    bool bSupportsAny = false;
477bf215546Sopenharmony_ci    while ((idxResol < ARRAY_SIZE(resolutionsList)) && !bSupportsAny) {
478bf215546Sopenharmony_ci        pD3D12Proc->m_SupportCaps.InputSample.Width = resolutionsList[idxResol].Width;
479bf215546Sopenharmony_ci        pD3D12Proc->m_SupportCaps.InputSample.Height = resolutionsList[idxResol].Height;
480bf215546Sopenharmony_ci        if (SUCCEEDED(pD3D12Proc->m_spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_PROCESS_SUPPORT, &pD3D12Proc->m_SupportCaps, sizeof(pD3D12Proc->m_SupportCaps)))) {
481bf215546Sopenharmony_ci            bSupportsAny = ((pD3D12Proc->m_SupportCaps.SupportFlags & D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED) != 0);
482bf215546Sopenharmony_ci        }
483bf215546Sopenharmony_ci        idxResol++;
484bf215546Sopenharmony_ci    }
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci    if ((pD3D12Proc->m_SupportCaps.SupportFlags & D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED) != D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED)
487bf215546Sopenharmony_ci    {
488bf215546Sopenharmony_ci        if((pD3D12Proc->m_SupportCaps.SupportFlags & D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED) != D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED) {
489bf215546Sopenharmony_ci        debug_printf("[d3d12_video_processor] d3d12_video_processor_check_caps_and_create_processor - D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED not returned by driver. "
490bf215546Sopenharmony_ci                            "failed with SupportFlags %x\n",
491bf215546Sopenharmony_ci                            pD3D12Proc->m_SupportCaps.SupportFlags);
492bf215546Sopenharmony_ci        }
493bf215546Sopenharmony_ci    }
494bf215546Sopenharmony_ci
495bf215546Sopenharmony_ci    D3D12_VIDEO_PROCESS_FILTER_FLAGS enabledFilterFlags = D3D12_VIDEO_PROCESS_FILTER_FLAG_NONE;
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci    bool enableOrientation = (
498bf215546Sopenharmony_ci        ((pD3D12Proc->m_SupportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_ROTATION) != 0)
499bf215546Sopenharmony_ci        || ((pD3D12Proc->m_SupportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_FLIP) != 0)
500bf215546Sopenharmony_ci    );
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_ci    D3D12_VIDEO_PROCESS_INPUT_STREAM_DESC inputStreamDesc = {
503bf215546Sopenharmony_ci        InputFormats[0],
504bf215546Sopenharmony_ci        InputColorSpace,
505bf215546Sopenharmony_ci        AspectRatio,                            // SourceAspectRatio;
506bf215546Sopenharmony_ci        AspectRatio,                            // DestinationAspectRatio;
507bf215546Sopenharmony_ci        FrameRate,                              // FrameRate
508bf215546Sopenharmony_ci        pD3D12Proc->m_SupportCaps.ScaleSupport.OutputSizeRange, // SourceSizeRange
509bf215546Sopenharmony_ci        pD3D12Proc->m_SupportCaps.ScaleSupport.OutputSizeRange, // DestinationSizeRange
510bf215546Sopenharmony_ci        enableOrientation,
511bf215546Sopenharmony_ci        enabledFilterFlags,
512bf215546Sopenharmony_ci        StereoFormat,
513bf215546Sopenharmony_ci        FieldType,
514bf215546Sopenharmony_ci        D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_NONE,
515bf215546Sopenharmony_ci        ((pD3D12Proc->m_SupportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_ALPHA_BLENDING) != 0)
516bf215546Sopenharmony_ci        && ((pD3D12Proc->m_SupportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_ALPHA_FILL) != 0), // EnableAlphaBlending
517bf215546Sopenharmony_ci        {},                                     // LumaKey
518bf215546Sopenharmony_ci        0,                                      // NumPastFrames
519bf215546Sopenharmony_ci        0,                                      // NumFutureFrames
520bf215546Sopenharmony_ci        FALSE                                   // EnableAutoProcessing
521bf215546Sopenharmony_ci    };
522bf215546Sopenharmony_ci
523bf215546Sopenharmony_ci    D3D12_VIDEO_PROCESS_OUTPUT_STREAM_DESC outputStreamDesc =
524bf215546Sopenharmony_ci    {
525bf215546Sopenharmony_ci        pD3D12Proc->m_SupportCaps.OutputFormat.Format,
526bf215546Sopenharmony_ci        OutputColorSpace,
527bf215546Sopenharmony_ci        D3D12_VIDEO_PROCESS_ALPHA_FILL_MODE_OPAQUE, // AlphaFillMode
528bf215546Sopenharmony_ci        0u,                                         // AlphaFillModeSourceStreamIndex
529bf215546Sopenharmony_ci        {0, 0, 0, 0},                               // BackgroundColor
530bf215546Sopenharmony_ci        FrameRate,                                  // FrameRate
531bf215546Sopenharmony_ci        FALSE                                       // EnableStereo
532bf215546Sopenharmony_ci    };
533bf215546Sopenharmony_ci
534bf215546Sopenharmony_ci    // gets the required past/future frames for VP creation
535bf215546Sopenharmony_ci    {
536bf215546Sopenharmony_ci        D3D12_FEATURE_DATA_VIDEO_PROCESS_REFERENCE_INFO referenceInfo = {};
537bf215546Sopenharmony_ci        referenceInfo.NodeIndex = 0;
538bf215546Sopenharmony_ci        D3D12_VIDEO_PROCESS_FEATURE_FLAGS featureFlags = D3D12_VIDEO_PROCESS_FEATURE_FLAG_NONE;
539bf215546Sopenharmony_ci        featureFlags |= outputStreamDesc.AlphaFillMode ? D3D12_VIDEO_PROCESS_FEATURE_FLAG_ALPHA_FILL : D3D12_VIDEO_PROCESS_FEATURE_FLAG_NONE;
540bf215546Sopenharmony_ci        featureFlags |= inputStreamDesc.LumaKey.Enable ? D3D12_VIDEO_PROCESS_FEATURE_FLAG_LUMA_KEY : D3D12_VIDEO_PROCESS_FEATURE_FLAG_NONE;
541bf215546Sopenharmony_ci        featureFlags |= (inputStreamDesc.StereoFormat != D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE || outputStreamDesc.EnableStereo) ? D3D12_VIDEO_PROCESS_FEATURE_FLAG_STEREO : D3D12_VIDEO_PROCESS_FEATURE_FLAG_NONE;
542bf215546Sopenharmony_ci        featureFlags |= inputStreamDesc.EnableOrientation ? D3D12_VIDEO_PROCESS_FEATURE_FLAG_ROTATION | D3D12_VIDEO_PROCESS_FEATURE_FLAG_FLIP : D3D12_VIDEO_PROCESS_FEATURE_FLAG_NONE;
543bf215546Sopenharmony_ci        featureFlags |= inputStreamDesc.EnableAlphaBlending ? D3D12_VIDEO_PROCESS_FEATURE_FLAG_ALPHA_BLENDING : D3D12_VIDEO_PROCESS_FEATURE_FLAG_NONE;
544bf215546Sopenharmony_ci
545bf215546Sopenharmony_ci        referenceInfo.DeinterlaceMode = inputStreamDesc.DeinterlaceMode;
546bf215546Sopenharmony_ci        referenceInfo.Filters = inputStreamDesc.FilterFlags;
547bf215546Sopenharmony_ci        referenceInfo.FeatureSupport = featureFlags;
548bf215546Sopenharmony_ci        referenceInfo.InputFrameRate = inputStreamDesc.FrameRate;
549bf215546Sopenharmony_ci        referenceInfo.OutputFrameRate = outputStreamDesc.FrameRate;
550bf215546Sopenharmony_ci        referenceInfo.EnableAutoProcessing = inputStreamDesc.EnableAutoProcessing;
551bf215546Sopenharmony_ci
552bf215546Sopenharmony_ci        hr = pD3D12Proc->m_spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_PROCESS_REFERENCE_INFO, &referenceInfo, sizeof(referenceInfo));
553bf215546Sopenharmony_ci        if (FAILED(hr)) {
554bf215546Sopenharmony_ci        debug_printf("[d3d12_video_processor] d3d12_video_processor_check_caps_and_create_processor - CheckFeatureSupport "
555bf215546Sopenharmony_ci                        "failed with HR %x\n",
556bf215546Sopenharmony_ci                        hr);
557bf215546Sopenharmony_ci        return false;
558bf215546Sopenharmony_ci        }
559bf215546Sopenharmony_ci
560bf215546Sopenharmony_ci        inputStreamDesc.NumPastFrames = referenceInfo.PastFrames;
561bf215546Sopenharmony_ci        inputStreamDesc.NumFutureFrames = referenceInfo.FutureFrames;
562bf215546Sopenharmony_ci    }
563bf215546Sopenharmony_ci
564bf215546Sopenharmony_ci    pD3D12Proc->m_outputStreamDesc = outputStreamDesc;
565bf215546Sopenharmony_ci
566bf215546Sopenharmony_ci    debug_printf("[d3d12_video_processor]\t Creating Video Processor\n");
567bf215546Sopenharmony_ci    debug_printf("[d3d12_video_processor]\t NumInputs: %d\n", (int) InputFormats.size());
568bf215546Sopenharmony_ci
569bf215546Sopenharmony_ci    pD3D12Proc->m_inputStreamDescs.clear();
570bf215546Sopenharmony_ci    for (unsigned i = 0; i < InputFormats.size(); i++)
571bf215546Sopenharmony_ci    {
572bf215546Sopenharmony_ci        inputStreamDesc.Format = InputFormats[i];
573bf215546Sopenharmony_ci        pD3D12Proc->m_inputStreamDescs.push_back(inputStreamDesc);
574bf215546Sopenharmony_ci        debug_printf("[d3d12_video_processor]\t Input Stream #%d Format: %d\n", i, inputStreamDesc.Format);
575bf215546Sopenharmony_ci    }
576bf215546Sopenharmony_ci    debug_printf("[d3d12_video_processor]\t Output Stream Format: %d\n", pD3D12Proc->m_outputStreamDesc.Format);
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_ci    hr = pD3D12Proc->m_spD3D12VideoDevice->CreateVideoProcessor(pD3D12Proc->m_NodeMask,
579bf215546Sopenharmony_ci                                                            &pD3D12Proc->m_outputStreamDesc,
580bf215546Sopenharmony_ci                                                            pD3D12Proc->m_inputStreamDescs.size(),
581bf215546Sopenharmony_ci                                                            pD3D12Proc->m_inputStreamDescs.data(),
582bf215546Sopenharmony_ci                                                            IID_PPV_ARGS(pD3D12Proc->m_spVideoProcessor.GetAddressOf()));
583bf215546Sopenharmony_ci    if (FAILED(hr)) {
584bf215546Sopenharmony_ci        debug_printf("[d3d12_video_processor] d3d12_video_processor_check_caps_and_create_processor - CreateVideoProcessor "
585bf215546Sopenharmony_ci                    "failed with HR %x\n",
586bf215546Sopenharmony_ci                    hr);
587bf215546Sopenharmony_ci        return false;
588bf215546Sopenharmony_ci    }
589bf215546Sopenharmony_ci
590bf215546Sopenharmony_ci   return true;
591bf215546Sopenharmony_ci}
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_cibool
594bf215546Sopenharmony_cid3d12_video_processor_create_command_objects(struct d3d12_video_processor *pD3D12Proc)
595bf215546Sopenharmony_ci{
596bf215546Sopenharmony_ci    assert(pD3D12Proc->m_spD3D12VideoDevice);
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci    D3D12_COMMAND_QUEUE_DESC commandQueueDesc = { D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS };
599bf215546Sopenharmony_ci    HRESULT hr = pD3D12Proc->m_pD3D12Screen->dev->CreateCommandQueue(
600bf215546Sopenharmony_ci                &commandQueueDesc,
601bf215546Sopenharmony_ci                IID_PPV_ARGS(pD3D12Proc->m_spCommandQueue.GetAddressOf()));
602bf215546Sopenharmony_ci
603bf215546Sopenharmony_ci    if (FAILED(hr)) {
604bf215546Sopenharmony_ci        debug_printf("[d3d12_video_processor] d3d12_video_processor_create_command_objects - Call to CreateCommandQueue "
605bf215546Sopenharmony_ci                        "failed with HR %x\n",
606bf215546Sopenharmony_ci                        hr);
607bf215546Sopenharmony_ci        return false;
608bf215546Sopenharmony_ci    }
609bf215546Sopenharmony_ci
610bf215546Sopenharmony_ci    hr = pD3D12Proc->m_pD3D12Screen->dev->CreateFence(0,
611bf215546Sopenharmony_ci         D3D12_FENCE_FLAG_NONE,
612bf215546Sopenharmony_ci         IID_PPV_ARGS(&pD3D12Proc->m_spFence));
613bf215546Sopenharmony_ci
614bf215546Sopenharmony_ci    if (FAILED(hr)) {
615bf215546Sopenharmony_ci        debug_printf(
616bf215546Sopenharmony_ci            "[d3d12_video_processor] d3d12_video_processor_create_command_objects - Call to CreateFence failed with HR %x\n",
617bf215546Sopenharmony_ci            hr);
618bf215546Sopenharmony_ci        return false;
619bf215546Sopenharmony_ci    }
620bf215546Sopenharmony_ci
621bf215546Sopenharmony_ci    hr = pD3D12Proc->m_pD3D12Screen->dev->CreateCommandAllocator(
622bf215546Sopenharmony_ci        D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
623bf215546Sopenharmony_ci        IID_PPV_ARGS(pD3D12Proc->m_spCommandAllocator.GetAddressOf()));
624bf215546Sopenharmony_ci
625bf215546Sopenharmony_ci    if (FAILED(hr)) {
626bf215546Sopenharmony_ci        debug_printf("[d3d12_video_processor] d3d12_video_processor_create_command_objects - Call to "
627bf215546Sopenharmony_ci                        "CreateCommandAllocator failed with HR %x\n",
628bf215546Sopenharmony_ci                        hr);
629bf215546Sopenharmony_ci        return false;
630bf215546Sopenharmony_ci    }
631bf215546Sopenharmony_ci
632bf215546Sopenharmony_ci    hr = pD3D12Proc->m_pD3D12Screen->dev->CreateCommandList(0,
633bf215546Sopenharmony_ci        D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
634bf215546Sopenharmony_ci        pD3D12Proc->m_spCommandAllocator.Get(),
635bf215546Sopenharmony_ci        nullptr,
636bf215546Sopenharmony_ci        IID_PPV_ARGS(pD3D12Proc->m_spCommandList.GetAddressOf()));
637bf215546Sopenharmony_ci
638bf215546Sopenharmony_ci    if (FAILED(hr)) {
639bf215546Sopenharmony_ci        debug_printf("[d3d12_video_processor] d3d12_video_processor_create_command_objects - Call to CreateCommandList "
640bf215546Sopenharmony_ci                        "failed with HR %x\n",
641bf215546Sopenharmony_ci                        hr);
642bf215546Sopenharmony_ci        return false;
643bf215546Sopenharmony_ci    }
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci    return true;
646bf215546Sopenharmony_ci}
647bf215546Sopenharmony_ci
648bf215546Sopenharmony_ciD3D12_VIDEO_PROCESS_ORIENTATION
649bf215546Sopenharmony_cid3d12_video_processor_convert_pipe_rotation(enum pipe_video_vpp_orientation orientation_flags)
650bf215546Sopenharmony_ci{
651bf215546Sopenharmony_ci    D3D12_VIDEO_PROCESS_ORIENTATION result = D3D12_VIDEO_PROCESS_ORIENTATION_DEFAULT;
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_ci    if(orientation_flags & PIPE_VIDEO_VPP_ROTATION_90)
654bf215546Sopenharmony_ci    {
655bf215546Sopenharmony_ci        result = (orientation_flags & PIPE_VIDEO_VPP_FLIP_HORIZONTAL) ? D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_90_FLIP_HORIZONTAL : D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_90;
656bf215546Sopenharmony_ci        debug_printf("d3d12_video_processor_process_frame: Orientation Mode: %s\n", (orientation_flags & PIPE_VIDEO_VPP_FLIP_HORIZONTAL) ? "D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_90_FLIP_HORIZONTAL" : "D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_90");
657bf215546Sopenharmony_ci    }
658bf215546Sopenharmony_ci    else if(orientation_flags & PIPE_VIDEO_VPP_ROTATION_180)
659bf215546Sopenharmony_ci    {
660bf215546Sopenharmony_ci        result = D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_180;
661bf215546Sopenharmony_ci        debug_printf("d3d12_video_processor_process_frame: Orientation Mode: D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_180\n");
662bf215546Sopenharmony_ci    }
663bf215546Sopenharmony_ci    else if(orientation_flags & PIPE_VIDEO_VPP_ROTATION_270)
664bf215546Sopenharmony_ci    {
665bf215546Sopenharmony_ci        result = (orientation_flags & PIPE_VIDEO_VPP_FLIP_HORIZONTAL) ? D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_270_FLIP_HORIZONTAL : D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_270;
666bf215546Sopenharmony_ci        debug_printf("d3d12_video_processor_process_frame: Orientation Mode: %s\n", (orientation_flags & PIPE_VIDEO_VPP_FLIP_HORIZONTAL) ? "D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_270_FLIP_HORIZONTAL" : "D3D12_VIDEO_PROCESS_ORIENTATION_CLOCKWISE_270");
667bf215546Sopenharmony_ci    }
668bf215546Sopenharmony_ci    else if(orientation_flags & PIPE_VIDEO_VPP_FLIP_HORIZONTAL)
669bf215546Sopenharmony_ci    {
670bf215546Sopenharmony_ci        result = D3D12_VIDEO_PROCESS_ORIENTATION_FLIP_HORIZONTAL;
671bf215546Sopenharmony_ci        debug_printf("d3d12_video_processor_process_frame: Orientation Mode: D3D12_VIDEO_PROCESS_ORIENTATION_FLIP_HORIZONTAL\n");
672bf215546Sopenharmony_ci    }
673bf215546Sopenharmony_ci    else if(orientation_flags & PIPE_VIDEO_VPP_FLIP_VERTICAL)
674bf215546Sopenharmony_ci    {
675bf215546Sopenharmony_ci        result = D3D12_VIDEO_PROCESS_ORIENTATION_FLIP_VERTICAL;
676bf215546Sopenharmony_ci        debug_printf("d3d12_video_processor_process_frame: Orientation Mode: D3D12_VIDEO_PROCESS_ORIENTATION_FLIP_VERTICAL\n");
677bf215546Sopenharmony_ci    }
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_ci    return result;
680bf215546Sopenharmony_ci}
681