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_screen.h" 25bf215546Sopenharmony_ci#include "d3d12_video_screen.h" 26bf215546Sopenharmony_ci#include "d3d12_format.h" 27bf215546Sopenharmony_ci#include "util/u_video.h" 28bf215546Sopenharmony_ci#include <directx/d3d12video.h> 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include <wrl/client.h> 31bf215546Sopenharmony_ciusing Microsoft::WRL::ComPtr; 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include "d3d12_video_types.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_cistatic bool 36bf215546Sopenharmony_cid3d12_video_buffer_is_format_supported(struct pipe_screen *screen, 37bf215546Sopenharmony_ci enum pipe_format format, 38bf215546Sopenharmony_ci enum pipe_video_profile profile, 39bf215546Sopenharmony_ci enum pipe_video_entrypoint entrypoint) 40bf215546Sopenharmony_ci{ 41bf215546Sopenharmony_ci return (format == PIPE_FORMAT_NV12); 42bf215546Sopenharmony_ci} 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_cistruct d3d12_video_resolution_to_level_mapping_entry 46bf215546Sopenharmony_ci{ 47bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC resolution; 48bf215546Sopenharmony_ci uint32_t level; 49bf215546Sopenharmony_ci}; 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_cistatic d3d12_video_resolution_to_level_mapping_entry 52bf215546Sopenharmony_ciget_max_level_resolution_video_decode_support(D3D12_VIDEO_DECODE_CONFIGURATION decoderConfig, 53bf215546Sopenharmony_ci DXGI_FORMAT format, 54bf215546Sopenharmony_ci struct pipe_screen *pscreen, 55bf215546Sopenharmony_ci bool &outSupportAny, 56bf215546Sopenharmony_ci D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT &outSupportedConfig) 57bf215546Sopenharmony_ci{ 58bf215546Sopenharmony_ci d3d12_video_resolution_to_level_mapping_entry supportedResult = {}; 59bf215546Sopenharmony_ci outSupportAny = false; 60bf215546Sopenharmony_ci outSupportedConfig = {}; 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci ComPtr<ID3D12VideoDevice> spD3D12VideoDevice; 63bf215546Sopenharmony_ci struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) pscreen; 64bf215546Sopenharmony_ci if (FAILED(pD3D12Screen->dev->QueryInterface(IID_PPV_ARGS(spD3D12VideoDevice.GetAddressOf())))) { 65bf215546Sopenharmony_ci // No video support in underlying d3d12 device (decode needs ID3D12VideoDevice) 66bf215546Sopenharmony_ci return supportedResult; 67bf215546Sopenharmony_ci } 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci d3d12_video_resolution_to_level_mapping_entry resolutionsLevelList[] = { 70bf215546Sopenharmony_ci { { 8192, 4320 }, 61 }, // 8k 71bf215546Sopenharmony_ci { { 7680, 4800 }, 61 }, // 8k - alternative 72bf215546Sopenharmony_ci { { 7680, 4320 }, 61 }, // 8k - alternative 73bf215546Sopenharmony_ci { { 4096, 2304 }, 52 }, // 2160p (4K) 74bf215546Sopenharmony_ci { { 4096, 2160 }, 52 }, // 2160p (4K) - alternative 75bf215546Sopenharmony_ci { { 2560, 1440 }, 51 }, // 1440p 76bf215546Sopenharmony_ci { { 1920, 1200 }, 5 }, // 1200p 77bf215546Sopenharmony_ci { { 1920, 1080 }, 42 }, // 1080p 78bf215546Sopenharmony_ci { { 1280, 720 }, 4 }, // 720p 79bf215546Sopenharmony_ci { { 800, 600 }, 31 }, 80bf215546Sopenharmony_ci }; 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT decodeSupport = {}; 83bf215546Sopenharmony_ci decodeSupport.Configuration = decoderConfig; 84bf215546Sopenharmony_ci decodeSupport.DecodeFormat = format; 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci uint32_t idxResol = 0; 87bf215546Sopenharmony_ci while ((idxResol < ARRAY_SIZE(resolutionsLevelList)) && !outSupportAny) { 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci decodeSupport.Width = resolutionsLevelList[idxResol].resolution.Width; 90bf215546Sopenharmony_ci decodeSupport.Height = resolutionsLevelList[idxResol].resolution.Height; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci if (SUCCEEDED(spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_DECODE_SUPPORT, 93bf215546Sopenharmony_ci &decodeSupport, 94bf215546Sopenharmony_ci sizeof(decodeSupport)))) { 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci if (((decodeSupport.SupportFlags & D3D12_VIDEO_DECODE_SUPPORT_FLAG_SUPPORTED) != 0) || 97bf215546Sopenharmony_ci decodeSupport.DecodeTier > D3D12_VIDEO_DECODE_TIER_NOT_SUPPORTED) { 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci outSupportAny = true; 100bf215546Sopenharmony_ci outSupportedConfig = decodeSupport; 101bf215546Sopenharmony_ci supportedResult = resolutionsLevelList[idxResol]; 102bf215546Sopenharmony_ci } 103bf215546Sopenharmony_ci } 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci idxResol++; 106bf215546Sopenharmony_ci } 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci return supportedResult; 109bf215546Sopenharmony_ci} 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_cistatic bool 112bf215546Sopenharmony_cid3d12_has_video_decode_support(struct pipe_screen *pscreen, enum pipe_video_profile profile) 113bf215546Sopenharmony_ci{ 114bf215546Sopenharmony_ci ComPtr<ID3D12VideoDevice> spD3D12VideoDevice; 115bf215546Sopenharmony_ci struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) pscreen; 116bf215546Sopenharmony_ci if (FAILED(pD3D12Screen->dev->QueryInterface(IID_PPV_ARGS(spD3D12VideoDevice.GetAddressOf())))) { 117bf215546Sopenharmony_ci // No video support in underlying d3d12 device (needs ID3D12VideoDevice) 118bf215546Sopenharmony_ci return 0; 119bf215546Sopenharmony_ci } 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci D3D12_FEATURE_DATA_VIDEO_FEATURE_AREA_SUPPORT VideoFeatureAreaSupport = {}; 122bf215546Sopenharmony_ci if (FAILED(spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_FEATURE_AREA_SUPPORT, 123bf215546Sopenharmony_ci &VideoFeatureAreaSupport, 124bf215546Sopenharmony_ci sizeof(VideoFeatureAreaSupport)))) { 125bf215546Sopenharmony_ci return false; 126bf215546Sopenharmony_ci } 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci // Supported profiles below 129bf215546Sopenharmony_ci bool supportsProfile = false; 130bf215546Sopenharmony_ci switch (profile) { 131bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: 132bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED: 133bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE: 134bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: 135bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: 136bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10: 137bf215546Sopenharmony_ci { 138bf215546Sopenharmony_ci supportsProfile = true; 139bf215546Sopenharmony_ci } break; 140bf215546Sopenharmony_ci default: 141bf215546Sopenharmony_ci supportsProfile = false; 142bf215546Sopenharmony_ci } 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci return VideoFeatureAreaSupport.VideoDecodeSupport && supportsProfile; 145bf215546Sopenharmony_ci} 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_cistatic bool 148bf215546Sopenharmony_cid3d12_video_encode_max_supported_level_for_profile(const D3D12_VIDEO_ENCODER_CODEC &argCodec, 149bf215546Sopenharmony_ci const D3D12_VIDEO_ENCODER_PROFILE_DESC &argTargetProfile, 150bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_LEVEL_SETTING &minLvl, 151bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_LEVEL_SETTING &maxLvl, 152bf215546Sopenharmony_ci ID3D12VideoDevice3 *pD3D12VideoDevice) 153bf215546Sopenharmony_ci{ 154bf215546Sopenharmony_ci D3D12_FEATURE_DATA_VIDEO_ENCODER_PROFILE_LEVEL capLevelData = {}; 155bf215546Sopenharmony_ci capLevelData.NodeIndex = 0; 156bf215546Sopenharmony_ci capLevelData.Codec = argCodec; 157bf215546Sopenharmony_ci capLevelData.Profile = argTargetProfile; 158bf215546Sopenharmony_ci capLevelData.MinSupportedLevel = minLvl; 159bf215546Sopenharmony_ci capLevelData.MaxSupportedLevel = maxLvl; 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci if (FAILED(pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_PROFILE_LEVEL, 162bf215546Sopenharmony_ci &capLevelData, 163bf215546Sopenharmony_ci sizeof(capLevelData)))) { 164bf215546Sopenharmony_ci return false; 165bf215546Sopenharmony_ci } 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci return capLevelData.IsSupported; 168bf215546Sopenharmony_ci} 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_cistatic bool 171bf215546Sopenharmony_cid3d12_video_encode_max_supported_resolution(const D3D12_VIDEO_ENCODER_CODEC &argTargetCodec, 172bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC &maxResolution, 173bf215546Sopenharmony_ci ID3D12VideoDevice3 *pD3D12VideoDevice) 174bf215546Sopenharmony_ci{ 175bf215546Sopenharmony_ci D3D12_FEATURE_DATA_VIDEO_ENCODER_OUTPUT_RESOLUTION_RATIOS_COUNT capResRatiosCountData = { 0, argTargetCodec, 0 }; 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci if (FAILED(pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_OUTPUT_RESOLUTION_RATIOS_COUNT, 178bf215546Sopenharmony_ci &capResRatiosCountData, 179bf215546Sopenharmony_ci sizeof(capResRatiosCountData)))) { 180bf215546Sopenharmony_ci return false; 181bf215546Sopenharmony_ci } 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci D3D12_FEATURE_DATA_VIDEO_ENCODER_OUTPUT_RESOLUTION capOutputResolutionData = {}; 184bf215546Sopenharmony_ci capOutputResolutionData.NodeIndex = 0; 185bf215546Sopenharmony_ci capOutputResolutionData.Codec = argTargetCodec; 186bf215546Sopenharmony_ci capOutputResolutionData.ResolutionRatiosCount = capResRatiosCountData.ResolutionRatiosCount; 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci std::vector<D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_RATIO_DESC> ratiosTmpOutput; 189bf215546Sopenharmony_ci if (capResRatiosCountData.ResolutionRatiosCount > 0) { 190bf215546Sopenharmony_ci ratiosTmpOutput.resize(capResRatiosCountData.ResolutionRatiosCount); 191bf215546Sopenharmony_ci capOutputResolutionData.pResolutionRatios = ratiosTmpOutput.data(); 192bf215546Sopenharmony_ci } else { 193bf215546Sopenharmony_ci capOutputResolutionData.pResolutionRatios = nullptr; 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci if (FAILED(pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_OUTPUT_RESOLUTION, 197bf215546Sopenharmony_ci &capOutputResolutionData, 198bf215546Sopenharmony_ci sizeof(capOutputResolutionData))) || 199bf215546Sopenharmony_ci !capOutputResolutionData.IsSupported) { 200bf215546Sopenharmony_ci return false; 201bf215546Sopenharmony_ci } 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci maxResolution = capOutputResolutionData.MaxResolutionSupported; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci return true; 206bf215546Sopenharmony_ci} 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_cistatic uint32_t 209bf215546Sopenharmony_cid3d12_video_encode_supported_references_per_frame_structures(const D3D12_VIDEO_ENCODER_CODEC &codec, 210bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_PROFILE_H264 profile, 211bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_LEVELS_H264 level, 212bf215546Sopenharmony_ci ID3D12VideoDevice3 *pD3D12VideoDevice) 213bf215546Sopenharmony_ci{ 214bf215546Sopenharmony_ci uint32_t supportedMaxRefFrames = 0u; 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_H264 h264PictureControl = {}; 217bf215546Sopenharmony_ci D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT capPictureControlData = {}; 218bf215546Sopenharmony_ci capPictureControlData.NodeIndex = 0; 219bf215546Sopenharmony_ci capPictureControlData.Codec = codec; 220bf215546Sopenharmony_ci capPictureControlData.Profile.pH264Profile = &profile; 221bf215546Sopenharmony_ci capPictureControlData.Profile.DataSize = sizeof(profile); 222bf215546Sopenharmony_ci capPictureControlData.PictureSupport.pH264Support = &h264PictureControl; 223bf215546Sopenharmony_ci capPictureControlData.PictureSupport.DataSize = sizeof(h264PictureControl); 224bf215546Sopenharmony_ci HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT, 225bf215546Sopenharmony_ci &capPictureControlData, 226bf215546Sopenharmony_ci sizeof(capPictureControlData)); 227bf215546Sopenharmony_ci if (FAILED(hr)) { 228bf215546Sopenharmony_ci debug_printf("CheckFeatureSupport failed with HR %x\n", hr); 229bf215546Sopenharmony_ci } 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci if (capPictureControlData.IsSupported) { 232bf215546Sopenharmony_ci /* This attribute determines the maximum number of reference 233bf215546Sopenharmony_ci * frames supported for encoding. 234bf215546Sopenharmony_ci * 235bf215546Sopenharmony_ci * Note: for H.264 encoding, the value represents the maximum number 236bf215546Sopenharmony_ci * of reference frames for both the reference picture list 0 (bottom 237bf215546Sopenharmony_ci * 16 bits) and the reference picture list 1 (top 16 bits). 238bf215546Sopenharmony_ci */ 239bf215546Sopenharmony_ci uint32_t maxRefForL0 = std::min(capPictureControlData.PictureSupport.pH264Support->MaxL0ReferencesForP, 240bf215546Sopenharmony_ci capPictureControlData.PictureSupport.pH264Support->MaxL0ReferencesForB); 241bf215546Sopenharmony_ci uint32_t maxRefForL1 = capPictureControlData.PictureSupport.pH264Support->MaxL1ReferencesForB; 242bf215546Sopenharmony_ci supportedMaxRefFrames = (maxRefForL0 & 0xffff) | ((maxRefForL1 & 0xffff) << 16); 243bf215546Sopenharmony_ci } 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci return supportedMaxRefFrames; 246bf215546Sopenharmony_ci} 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_cistatic uint32_t 249bf215546Sopenharmony_cid3d12_video_encode_supported_slice_structures(const D3D12_VIDEO_ENCODER_CODEC &codec, 250bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_PROFILE_H264 profile, 251bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_LEVELS_H264 level, 252bf215546Sopenharmony_ci ID3D12VideoDevice3 *pD3D12VideoDevice) 253bf215546Sopenharmony_ci{ 254bf215546Sopenharmony_ci uint32_t supportedSliceStructuresBitMask = PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE; 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci D3D12_FEATURE_DATA_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE capDataSubregionLayout = {}; 257bf215546Sopenharmony_ci capDataSubregionLayout.NodeIndex = 0; 258bf215546Sopenharmony_ci capDataSubregionLayout.Codec = codec; 259bf215546Sopenharmony_ci capDataSubregionLayout.Profile.pH264Profile = &profile; 260bf215546Sopenharmony_ci capDataSubregionLayout.Profile.DataSize = sizeof(profile); 261bf215546Sopenharmony_ci capDataSubregionLayout.Level.pH264LevelSetting = &level; 262bf215546Sopenharmony_ci capDataSubregionLayout.Level.DataSize = sizeof(level); 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci /** 265bf215546Sopenharmony_ci * pipe_video_cap_slice_structure 266bf215546Sopenharmony_ci * 267bf215546Sopenharmony_ci * This attribute determines slice structures supported by the 268bf215546Sopenharmony_ci * driver for encoding. This attribute is a hint to the user so 269bf215546Sopenharmony_ci * that he can choose a suitable surface size and how to arrange 270bf215546Sopenharmony_ci * the encoding process of multiple slices per frame. 271bf215546Sopenharmony_ci * 272bf215546Sopenharmony_ci * More specifically, for H.264 encoding, this attribute 273bf215546Sopenharmony_ci * determines the range of accepted values to 274bf215546Sopenharmony_ci * h264_slice_descriptor::macroblock_address and 275bf215546Sopenharmony_ci * h264_slice_descriptor::num_macroblocks. 276bf215546Sopenharmony_ci */ 277bf215546Sopenharmony_ci capDataSubregionLayout.SubregionMode = 278bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME; 279bf215546Sopenharmony_ci HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE, 280bf215546Sopenharmony_ci &capDataSubregionLayout, 281bf215546Sopenharmony_ci sizeof(capDataSubregionLayout)); 282bf215546Sopenharmony_ci if (FAILED(hr)) { 283bf215546Sopenharmony_ci debug_printf("CheckFeatureSupport failed with HR %x\n", hr); 284bf215546Sopenharmony_ci } else if (capDataSubregionLayout.IsSupported) { 285bf215546Sopenharmony_ci /* This would be setting N subregions per frame in this D3D12 mode where N = (height/blocksize) / K */ 286bf215546Sopenharmony_ci supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_MULTI_ROWS; 287bf215546Sopenharmony_ci /* Assuming height/blocksize >= max_supported_slices, which is reported 288bf215546Sopenharmony_ci in PIPE_VIDEO_CAP_ENC_MAX_SLICES_PER_FRAME and should be checked by the client*/ 289bf215546Sopenharmony_ci /* This would be setting N subregions per frame in this D3D12 mode where N = (height/blocksize) */ 290bf215546Sopenharmony_ci supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_ROWS; 291bf215546Sopenharmony_ci /* This is ok, would be setting K rows per subregions in this D3D12 mode (and rounding the last one) */ 292bf215546Sopenharmony_ci supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_POWER_OF_TWO_ROWS; 293bf215546Sopenharmony_ci } 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci capDataSubregionLayout.SubregionMode = 296bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_ROWS_PER_SUBREGION; 297bf215546Sopenharmony_ci hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE, 298bf215546Sopenharmony_ci &capDataSubregionLayout, 299bf215546Sopenharmony_ci sizeof(capDataSubregionLayout)); 300bf215546Sopenharmony_ci if (FAILED(hr)) { 301bf215546Sopenharmony_ci debug_printf("CheckFeatureSupport failed with HR %x\n", hr); 302bf215546Sopenharmony_ci } else if (capDataSubregionLayout.IsSupported) { 303bf215546Sopenharmony_ci /* This would be setting K rows per subregions in this D3D12 mode */ 304bf215546Sopenharmony_ci supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_MULTI_ROWS; 305bf215546Sopenharmony_ci /* Assuming height/blocksize >= max_supported_slices, which is reported 306bf215546Sopenharmony_ci in PIPE_VIDEO_CAP_ENC_MAX_SLICES_PER_FRAME and should be checked by the client*/ 307bf215546Sopenharmony_ci /* This would be setting 1 row per subregion in this D3D12 mode */ 308bf215546Sopenharmony_ci supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_ROWS; 309bf215546Sopenharmony_ci /* This is ok, would be setting K rows per subregions in this D3D12 mode (and rounding the last one) */ 310bf215546Sopenharmony_ci supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_POWER_OF_TWO_ROWS; 311bf215546Sopenharmony_ci } 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci /* Needs more work in VA frontend to support VAEncMiscParameterMaxSliceSize 314bf215546Sopenharmony_ci and the driver potentially reporting back status in VACodedBufferSegment */ 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci /*capDataSubregionLayout.SubregionMode = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_BYTES_PER_SUBREGION; 317bf215546Sopenharmony_ci hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE, 318bf215546Sopenharmony_ci &capDataSubregionLayout, 319bf215546Sopenharmony_ci sizeof(capDataSubregionLayout)); 320bf215546Sopenharmony_ci if (FAILED(hr)) { 321bf215546Sopenharmony_ci debug_printf("CheckFeatureSupport failed with HR %x\n", hr); 322bf215546Sopenharmony_ci } else if (capDataSubregionLayout.IsSupported) { 323bf215546Sopenharmony_ci supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_MAX_SLICE_SIZE; 324bf215546Sopenharmony_ci }*/ 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci return supportedSliceStructuresBitMask; 327bf215546Sopenharmony_ci} 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_cistatic bool 330bf215546Sopenharmony_cid3d12_video_encode_max_supported_slices(const D3D12_VIDEO_ENCODER_CODEC &argTargetCodec, 331bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC maxResolution, 332bf215546Sopenharmony_ci DXGI_FORMAT encodeFormat, 333bf215546Sopenharmony_ci uint32_t &outMaxSlices, 334bf215546Sopenharmony_ci ID3D12VideoDevice3 *pD3D12VideoDevice) 335bf215546Sopenharmony_ci{ 336bf215546Sopenharmony_ci D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT capEncoderSupportData = {}; 337bf215546Sopenharmony_ci capEncoderSupportData.NodeIndex = 0; 338bf215546Sopenharmony_ci capEncoderSupportData.Codec = argTargetCodec; 339bf215546Sopenharmony_ci capEncoderSupportData.InputFormat = encodeFormat; 340bf215546Sopenharmony_ci capEncoderSupportData.RateControl = {}; 341bf215546Sopenharmony_ci capEncoderSupportData.RateControl.Mode = D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP; 342bf215546Sopenharmony_ci capEncoderSupportData.RateControl.TargetFrameRate.Numerator = 60; 343bf215546Sopenharmony_ci capEncoderSupportData.RateControl.TargetFrameRate.Denominator = 1; 344bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP rcCqp = { 25, 25, 25 }; 345bf215546Sopenharmony_ci capEncoderSupportData.RateControl.ConfigParams.pConfiguration_CQP = &rcCqp; 346bf215546Sopenharmony_ci capEncoderSupportData.RateControl.ConfigParams.DataSize = sizeof(rcCqp); 347bf215546Sopenharmony_ci capEncoderSupportData.IntraRefresh = D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE; 348bf215546Sopenharmony_ci capEncoderSupportData.ResolutionsListCount = 1; 349bf215546Sopenharmony_ci capEncoderSupportData.pResolutionList = &maxResolution; 350bf215546Sopenharmony_ci capEncoderSupportData.MaxReferenceFramesInDPB = 1; 351bf215546Sopenharmony_ci capEncoderSupportData.SubregionFrameEncoding = 352bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME; 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_PROFILE_H264 h264prof = {}; 355bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_LEVELS_H264 h264lvl = {}; 356bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE_H264 h264Gop = { 1, 0, 0, 0, 0 }; 357bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264 h264Config = {}; 358bf215546Sopenharmony_ci switch (argTargetCodec) { 359bf215546Sopenharmony_ci case D3D12_VIDEO_ENCODER_CODEC_H264: 360bf215546Sopenharmony_ci { 361bf215546Sopenharmony_ci capEncoderSupportData.SuggestedProfile.pH264Profile = &h264prof; 362bf215546Sopenharmony_ci capEncoderSupportData.SuggestedProfile.DataSize = sizeof(h264prof); 363bf215546Sopenharmony_ci capEncoderSupportData.SuggestedLevel.pH264LevelSetting = &h264lvl; 364bf215546Sopenharmony_ci capEncoderSupportData.SuggestedLevel.DataSize = sizeof(h264lvl); 365bf215546Sopenharmony_ci capEncoderSupportData.CodecGopSequence.pH264GroupOfPictures = &h264Gop; 366bf215546Sopenharmony_ci capEncoderSupportData.CodecGopSequence.DataSize = sizeof(h264Gop); 367bf215546Sopenharmony_ci capEncoderSupportData.CodecConfiguration.DataSize = sizeof(h264Config); 368bf215546Sopenharmony_ci capEncoderSupportData.CodecConfiguration.pH264Config = &h264Config; 369bf215546Sopenharmony_ci } break; 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci default: 372bf215546Sopenharmony_ci { 373bf215546Sopenharmony_ci unreachable("Unsupported D3D12_VIDEO_ENCODER_CODEC"); 374bf215546Sopenharmony_ci } break; 375bf215546Sopenharmony_ci } 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci // prepare inout storage for the resolution dependent result. 378bf215546Sopenharmony_ci D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOLUTION_SUPPORT_LIMITS resolutionDepCaps = {}; 379bf215546Sopenharmony_ci capEncoderSupportData.pResolutionDependentSupport = &resolutionDepCaps; 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_SUPPORT, 382bf215546Sopenharmony_ci &capEncoderSupportData, 383bf215546Sopenharmony_ci sizeof(capEncoderSupportData)); 384bf215546Sopenharmony_ci if (FAILED(hr)) { 385bf215546Sopenharmony_ci debug_printf("CheckFeatureSupport failed with HR %x\n", hr); 386bf215546Sopenharmony_ci return false; 387bf215546Sopenharmony_ci } else { 388bf215546Sopenharmony_ci bool configSupported = 389bf215546Sopenharmony_ci (((capEncoderSupportData.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_GENERAL_SUPPORT_OK) != 0) && 390bf215546Sopenharmony_ci (capEncoderSupportData.ValidationFlags == D3D12_VIDEO_ENCODER_VALIDATION_FLAG_NONE)); 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci outMaxSlices = resolutionDepCaps.MaxSubregionsNumber; 393bf215546Sopenharmony_ci return configSupported; 394bf215546Sopenharmony_ci } 395bf215546Sopenharmony_ci} 396bf215546Sopenharmony_ci 397bf215546Sopenharmony_cistatic bool 398bf215546Sopenharmony_cid3d12_has_video_encode_support(struct pipe_screen *pscreen, 399bf215546Sopenharmony_ci enum pipe_video_profile profile, 400bf215546Sopenharmony_ci uint32_t &maxLvlSpec, 401bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC &maxRes, 402bf215546Sopenharmony_ci uint32_t &maxSlices, 403bf215546Sopenharmony_ci uint32_t &supportedSliceStructures, 404bf215546Sopenharmony_ci uint32_t &maxReferencesPerFrame) 405bf215546Sopenharmony_ci{ 406bf215546Sopenharmony_ci ComPtr<ID3D12VideoDevice3> spD3D12VideoDevice; 407bf215546Sopenharmony_ci struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) pscreen; 408bf215546Sopenharmony_ci if (FAILED(pD3D12Screen->dev->QueryInterface(IID_PPV_ARGS(spD3D12VideoDevice.GetAddressOf())))) { 409bf215546Sopenharmony_ci // No video encode support in underlying d3d12 device (needs ID3D12VideoDevice3) 410bf215546Sopenharmony_ci return 0; 411bf215546Sopenharmony_ci } 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_ci D3D12_FEATURE_DATA_VIDEO_FEATURE_AREA_SUPPORT VideoFeatureAreaSupport = {}; 414bf215546Sopenharmony_ci if (FAILED(spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_FEATURE_AREA_SUPPORT, 415bf215546Sopenharmony_ci &VideoFeatureAreaSupport, 416bf215546Sopenharmony_ci sizeof(VideoFeatureAreaSupport)))) { 417bf215546Sopenharmony_ci return false; 418bf215546Sopenharmony_ci } 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_ci bool supportsProfile = false; 421bf215546Sopenharmony_ci switch (profile) { 422bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE: 423bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: 424bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: 425bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: 426bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10: 427bf215546Sopenharmony_ci { 428bf215546Sopenharmony_ci supportsProfile = true; 429bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_PROFILE_DESC profDesc = {}; 430bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_PROFILE_H264 profH264 = 431bf215546Sopenharmony_ci d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_h264(profile); 432bf215546Sopenharmony_ci profDesc.DataSize = sizeof(profH264); 433bf215546Sopenharmony_ci profDesc.pH264Profile = &profH264; 434bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_CODEC codecDesc = d3d12_video_encoder_convert_codec_to_d3d12_enc_codec(profile); 435bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_LEVELS_H264 minLvlSettingH264 = static_cast<D3D12_VIDEO_ENCODER_LEVELS_H264>(0); 436bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_LEVELS_H264 maxLvlSettingH264 = static_cast<D3D12_VIDEO_ENCODER_LEVELS_H264>(0); 437bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_LEVEL_SETTING minLvl = {}; 438bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_LEVEL_SETTING maxLvl = {}; 439bf215546Sopenharmony_ci minLvl.pH264LevelSetting = &minLvlSettingH264; 440bf215546Sopenharmony_ci minLvl.DataSize = sizeof(minLvlSettingH264); 441bf215546Sopenharmony_ci maxLvl.pH264LevelSetting = &maxLvlSettingH264; 442bf215546Sopenharmony_ci maxLvl.DataSize = sizeof(maxLvlSettingH264); 443bf215546Sopenharmony_ci if (d3d12_video_encode_max_supported_level_for_profile(codecDesc, 444bf215546Sopenharmony_ci profDesc, 445bf215546Sopenharmony_ci minLvl, 446bf215546Sopenharmony_ci maxLvl, 447bf215546Sopenharmony_ci spD3D12VideoDevice.Get())) { 448bf215546Sopenharmony_ci uint32_t constraintset3flag = false; 449bf215546Sopenharmony_ci d3d12_video_encoder_convert_from_d3d12_level_h264(maxLvlSettingH264, maxLvlSpec, constraintset3flag); 450bf215546Sopenharmony_ci supportsProfile = true; 451bf215546Sopenharmony_ci } 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci if (supportsProfile) { 454bf215546Sopenharmony_ci DXGI_FORMAT encodeFormat = d3d12_convert_pipe_video_profile_to_dxgi_format(profile); 455bf215546Sopenharmony_ci supportsProfile = supportsProfile && 456bf215546Sopenharmony_ci d3d12_video_encode_max_supported_resolution(codecDesc, maxRes, spD3D12VideoDevice.Get()); 457bf215546Sopenharmony_ci supportsProfile = supportsProfile && d3d12_video_encode_max_supported_slices(codecDesc, 458bf215546Sopenharmony_ci maxRes, 459bf215546Sopenharmony_ci encodeFormat, 460bf215546Sopenharmony_ci maxSlices, 461bf215546Sopenharmony_ci spD3D12VideoDevice.Get()); 462bf215546Sopenharmony_ci supportedSliceStructures = d3d12_video_encode_supported_slice_structures(codecDesc, 463bf215546Sopenharmony_ci profH264, 464bf215546Sopenharmony_ci maxLvlSettingH264, 465bf215546Sopenharmony_ci spD3D12VideoDevice.Get()); 466bf215546Sopenharmony_ci maxReferencesPerFrame = 467bf215546Sopenharmony_ci d3d12_video_encode_supported_references_per_frame_structures(codecDesc, 468bf215546Sopenharmony_ci profH264, 469bf215546Sopenharmony_ci maxLvlSettingH264, 470bf215546Sopenharmony_ci spD3D12VideoDevice.Get()); 471bf215546Sopenharmony_ci } 472bf215546Sopenharmony_ci } break; 473bf215546Sopenharmony_ci default: 474bf215546Sopenharmony_ci supportsProfile = false; 475bf215546Sopenharmony_ci } 476bf215546Sopenharmony_ci 477bf215546Sopenharmony_ci return VideoFeatureAreaSupport.VideoEncodeSupport && supportsProfile; 478bf215546Sopenharmony_ci} 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_cistatic int 481bf215546Sopenharmony_cid3d12_screen_get_video_param_decode(struct pipe_screen *pscreen, 482bf215546Sopenharmony_ci enum pipe_video_profile profile, 483bf215546Sopenharmony_ci enum pipe_video_entrypoint entrypoint, 484bf215546Sopenharmony_ci enum pipe_video_cap param) 485bf215546Sopenharmony_ci{ 486bf215546Sopenharmony_ci switch (param) { 487bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_NPOT_TEXTURES: 488bf215546Sopenharmony_ci return 1; 489bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_WIDTH: 490bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_HEIGHT: 491bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_LEVEL: 492bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTED: 493bf215546Sopenharmony_ci { 494bf215546Sopenharmony_ci if (d3d12_has_video_decode_support(pscreen, profile)) { 495bf215546Sopenharmony_ci DXGI_FORMAT format = d3d12_convert_pipe_video_profile_to_dxgi_format(profile); 496bf215546Sopenharmony_ci auto pipeFmt = d3d12_get_pipe_format(format); 497bf215546Sopenharmony_ci bool formatSupported = pscreen->is_video_format_supported(pscreen, pipeFmt, profile, entrypoint); 498bf215546Sopenharmony_ci if (formatSupported) { 499bf215546Sopenharmony_ci GUID decodeGUID = d3d12_video_decoder_convert_pipe_video_profile_to_d3d12_profile(profile); 500bf215546Sopenharmony_ci GUID emptyGUID = {}; 501bf215546Sopenharmony_ci if (decodeGUID != emptyGUID) { 502bf215546Sopenharmony_ci bool supportAny = false; 503bf215546Sopenharmony_ci D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT outSupportedConfig = {}; 504bf215546Sopenharmony_ci D3D12_VIDEO_DECODE_CONFIGURATION decoderConfig = { decodeGUID, 505bf215546Sopenharmony_ci D3D12_BITSTREAM_ENCRYPTION_TYPE_NONE, 506bf215546Sopenharmony_ci D3D12_VIDEO_FRAME_CODED_INTERLACE_TYPE_NONE }; 507bf215546Sopenharmony_ci 508bf215546Sopenharmony_ci d3d12_video_resolution_to_level_mapping_entry bestSupportedConfig = 509bf215546Sopenharmony_ci get_max_level_resolution_video_decode_support(decoderConfig, 510bf215546Sopenharmony_ci format, 511bf215546Sopenharmony_ci pscreen, 512bf215546Sopenharmony_ci supportAny, 513bf215546Sopenharmony_ci outSupportedConfig); 514bf215546Sopenharmony_ci if (supportAny) { 515bf215546Sopenharmony_ci if (param == PIPE_VIDEO_CAP_MAX_WIDTH) { 516bf215546Sopenharmony_ci return bestSupportedConfig.resolution.Width; 517bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_MAX_HEIGHT) { 518bf215546Sopenharmony_ci return bestSupportedConfig.resolution.Height; 519bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_MAX_LEVEL) { 520bf215546Sopenharmony_ci return bestSupportedConfig.level; 521bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_SUPPORTED) { 522bf215546Sopenharmony_ci return 1; 523bf215546Sopenharmony_ci } 524bf215546Sopenharmony_ci } 525bf215546Sopenharmony_ci } 526bf215546Sopenharmony_ci } 527bf215546Sopenharmony_ci } 528bf215546Sopenharmony_ci return 0; 529bf215546Sopenharmony_ci } break; 530bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_PREFERED_FORMAT: 531bf215546Sopenharmony_ci return PIPE_FORMAT_NV12; 532bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_PREFERS_INTERLACED: 533bf215546Sopenharmony_ci return false; 534bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: 535bf215546Sopenharmony_ci return true; 536bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE: 537bf215546Sopenharmony_ci return true; 538bf215546Sopenharmony_ci case PIPE_VIDEO_SUPPORTS_CONTIGUOUS_PLANES_MAP: 539bf215546Sopenharmony_ci return true; 540bf215546Sopenharmony_ci break; 541bf215546Sopenharmony_ci default: 542bf215546Sopenharmony_ci debug_printf("[d3d12_screen_get_video_param] unknown video param: %d\n", param); 543bf215546Sopenharmony_ci return 0; 544bf215546Sopenharmony_ci } 545bf215546Sopenharmony_ci} 546bf215546Sopenharmony_ci 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_cistatic bool 549bf215546Sopenharmony_cid3d12_has_video_process_support(struct pipe_screen *pscreen, D3D12_FEATURE_DATA_VIDEO_PROCESS_SUPPORT &supportCaps) 550bf215546Sopenharmony_ci{ 551bf215546Sopenharmony_ci ComPtr<ID3D12VideoDevice2> spD3D12VideoDevice; 552bf215546Sopenharmony_ci struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) pscreen; 553bf215546Sopenharmony_ci if (FAILED(pD3D12Screen->dev->QueryInterface(IID_PPV_ARGS(spD3D12VideoDevice.GetAddressOf())))) { 554bf215546Sopenharmony_ci // No video encode support in underlying d3d12 device (needs ID3D12VideoDevice2) 555bf215546Sopenharmony_ci return false; 556bf215546Sopenharmony_ci } 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci D3D12_FEATURE_DATA_VIDEO_FEATURE_AREA_SUPPORT VideoFeatureAreaSupport = {}; 559bf215546Sopenharmony_ci if (FAILED(spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_FEATURE_AREA_SUPPORT, 560bf215546Sopenharmony_ci &VideoFeatureAreaSupport, 561bf215546Sopenharmony_ci sizeof(VideoFeatureAreaSupport)))) { 562bf215546Sopenharmony_ci return false; 563bf215546Sopenharmony_ci } 564bf215546Sopenharmony_ci 565bf215546Sopenharmony_ci struct ResolStruct { 566bf215546Sopenharmony_ci uint Width; 567bf215546Sopenharmony_ci uint Height; 568bf215546Sopenharmony_ci }; 569bf215546Sopenharmony_ci 570bf215546Sopenharmony_ci ResolStruct resolutionsList[] = { 571bf215546Sopenharmony_ci { 8192, 8192 }, // 8k 572bf215546Sopenharmony_ci { 8192, 4320 }, // 8k - alternative 573bf215546Sopenharmony_ci { 7680, 4800 }, // 8k - alternative 574bf215546Sopenharmony_ci { 7680, 4320 }, // 8k - alternative 575bf215546Sopenharmony_ci { 4096, 2304 }, // 2160p (4K) 576bf215546Sopenharmony_ci { 4096, 2160 }, // 2160p (4K) - alternative 577bf215546Sopenharmony_ci { 2560, 1440 }, // 1440p 578bf215546Sopenharmony_ci { 1920, 1200 }, // 1200p 579bf215546Sopenharmony_ci { 1920, 1080 }, // 1080p 580bf215546Sopenharmony_ci { 1280, 720 }, // 720p 581bf215546Sopenharmony_ci { 800, 600 }, 582bf215546Sopenharmony_ci }; 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci uint32_t idxResol = 0; 585bf215546Sopenharmony_ci bool bSupportsAny = false; 586bf215546Sopenharmony_ci while ((idxResol < ARRAY_SIZE(resolutionsList)) && !bSupportsAny) { 587bf215546Sopenharmony_ci supportCaps.InputSample.Width = resolutionsList[idxResol].Width; 588bf215546Sopenharmony_ci supportCaps.InputSample.Height = resolutionsList[idxResol].Height; 589bf215546Sopenharmony_ci if (SUCCEEDED(spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_PROCESS_SUPPORT, &supportCaps, sizeof(supportCaps)))) { 590bf215546Sopenharmony_ci bSupportsAny = ((supportCaps.SupportFlags & D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED) != 0) ; 591bf215546Sopenharmony_ci } 592bf215546Sopenharmony_ci idxResol++; 593bf215546Sopenharmony_ci } 594bf215546Sopenharmony_ci 595bf215546Sopenharmony_ci return VideoFeatureAreaSupport.VideoProcessSupport && bSupportsAny; 596bf215546Sopenharmony_ci} 597bf215546Sopenharmony_ci 598bf215546Sopenharmony_cistatic int 599bf215546Sopenharmony_cid3d12_screen_get_video_param_postproc(struct pipe_screen *pscreen, 600bf215546Sopenharmony_ci enum pipe_video_profile profile, 601bf215546Sopenharmony_ci enum pipe_video_entrypoint entrypoint, 602bf215546Sopenharmony_ci enum pipe_video_cap param) 603bf215546Sopenharmony_ci{ 604bf215546Sopenharmony_ci switch (param) { 605bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_NPOT_TEXTURES: 606bf215546Sopenharmony_ci return 1; 607bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_WIDTH: 608bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_HEIGHT: 609bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTED: 610bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_PREFERED_FORMAT: 611bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: 612bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE: 613bf215546Sopenharmony_ci case PIPE_VIDEO_SUPPORTS_CONTIGUOUS_PLANES_MAP: 614bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_VPP_MAX_INPUT_WIDTH: 615bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_VPP_MAX_INPUT_HEIGHT: 616bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_VPP_MIN_INPUT_WIDTH: 617bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_VPP_MIN_INPUT_HEIGHT: 618bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_VPP_MAX_OUTPUT_WIDTH: 619bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_VPP_MAX_OUTPUT_HEIGHT: 620bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_VPP_MIN_OUTPUT_WIDTH: 621bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_VPP_MIN_OUTPUT_HEIGHT: 622bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_VPP_ORIENTATION_MODES: 623bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_VPP_BLEND_MODES: 624bf215546Sopenharmony_ci { 625bf215546Sopenharmony_ci // Assume defaults for now, we don't have the input args passed by get_video_param to be accurate here. 626bf215546Sopenharmony_ci const D3D12_VIDEO_FIELD_TYPE FieldType = D3D12_VIDEO_FIELD_TYPE_NONE; 627bf215546Sopenharmony_ci const D3D12_VIDEO_FRAME_STEREO_FORMAT StereoFormat = D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE; 628bf215546Sopenharmony_ci const DXGI_RATIONAL FrameRate = { 30, 1 }; 629bf215546Sopenharmony_ci const DXGI_FORMAT InputFormat = DXGI_FORMAT_NV12; 630bf215546Sopenharmony_ci const DXGI_COLOR_SPACE_TYPE InputColorSpace = DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709; 631bf215546Sopenharmony_ci const DXGI_FORMAT OutputFormat = DXGI_FORMAT_NV12; 632bf215546Sopenharmony_ci const DXGI_COLOR_SPACE_TYPE OutputColorSpace = DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709; 633bf215546Sopenharmony_ci const UINT Width = 1280; 634bf215546Sopenharmony_ci const UINT Height = 720; 635bf215546Sopenharmony_ci D3D12_FEATURE_DATA_VIDEO_PROCESS_SUPPORT supportCaps = 636bf215546Sopenharmony_ci { 637bf215546Sopenharmony_ci 0, // NodeIndex 638bf215546Sopenharmony_ci { Width, Height, { InputFormat, InputColorSpace } }, 639bf215546Sopenharmony_ci FieldType, 640bf215546Sopenharmony_ci StereoFormat, 641bf215546Sopenharmony_ci FrameRate, 642bf215546Sopenharmony_ci { OutputFormat, OutputColorSpace }, 643bf215546Sopenharmony_ci StereoFormat, 644bf215546Sopenharmony_ci FrameRate, 645bf215546Sopenharmony_ci }; 646bf215546Sopenharmony_ci 647bf215546Sopenharmony_ci if (d3d12_has_video_process_support(pscreen, supportCaps)) { 648bf215546Sopenharmony_ci if (param == PIPE_VIDEO_CAP_SUPPORTED) { 649bf215546Sopenharmony_ci return true; 650bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_PREFERED_FORMAT) { 651bf215546Sopenharmony_ci return PIPE_FORMAT_NV12; 652bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_SUPPORTS_INTERLACED) { 653bf215546Sopenharmony_ci return false; 654bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_MAX_WIDTH) { 655bf215546Sopenharmony_ci return supportCaps.InputSample.Width; 656bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_MAX_HEIGHT) { 657bf215546Sopenharmony_ci return supportCaps.InputSample.Height; 658bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_SUPPORTS_CONTIGUOUS_PLANES_MAP) { 659bf215546Sopenharmony_ci return true; 660bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE) { 661bf215546Sopenharmony_ci return true; 662bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_VPP_MAX_INPUT_WIDTH) { 663bf215546Sopenharmony_ci return supportCaps.ScaleSupport.OutputSizeRange.MaxWidth; 664bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_VPP_MAX_INPUT_HEIGHT) { 665bf215546Sopenharmony_ci return supportCaps.ScaleSupport.OutputSizeRange.MaxHeight; 666bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_VPP_MIN_INPUT_WIDTH) { 667bf215546Sopenharmony_ci return supportCaps.ScaleSupport.OutputSizeRange.MinWidth; 668bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_VPP_MIN_INPUT_HEIGHT) { 669bf215546Sopenharmony_ci return supportCaps.ScaleSupport.OutputSizeRange.MinHeight; 670bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_VPP_MAX_OUTPUT_WIDTH) { 671bf215546Sopenharmony_ci return supportCaps.ScaleSupport.OutputSizeRange.MaxWidth; 672bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_VPP_MAX_OUTPUT_HEIGHT) { 673bf215546Sopenharmony_ci return supportCaps.ScaleSupport.OutputSizeRange.MaxHeight; 674bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_VPP_MIN_OUTPUT_WIDTH) { 675bf215546Sopenharmony_ci return supportCaps.ScaleSupport.OutputSizeRange.MinWidth; 676bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_VPP_MIN_OUTPUT_HEIGHT) { 677bf215546Sopenharmony_ci return supportCaps.ScaleSupport.OutputSizeRange.MinHeight; 678bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_VPP_BLEND_MODES) { 679bf215546Sopenharmony_ci uint32_t blend_modes = PIPE_VIDEO_VPP_BLEND_MODE_NONE; 680bf215546Sopenharmony_ci if (((supportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_ALPHA_BLENDING) != 0) 681bf215546Sopenharmony_ci && ((supportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_ALPHA_FILL) != 0)) 682bf215546Sopenharmony_ci { 683bf215546Sopenharmony_ci blend_modes |= PIPE_VIDEO_VPP_BLEND_MODE_GLOBAL_ALPHA; 684bf215546Sopenharmony_ci } 685bf215546Sopenharmony_ci return blend_modes; 686bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_VPP_ORIENTATION_MODES) { 687bf215546Sopenharmony_ci uint32_t orientation_modes = PIPE_VIDEO_VPP_ORIENTATION_DEFAULT; 688bf215546Sopenharmony_ci if((supportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_FLIP) != 0) { 689bf215546Sopenharmony_ci orientation_modes |= PIPE_VIDEO_VPP_FLIP_HORIZONTAL; 690bf215546Sopenharmony_ci orientation_modes |= PIPE_VIDEO_VPP_FLIP_VERTICAL; 691bf215546Sopenharmony_ci } 692bf215546Sopenharmony_ci 693bf215546Sopenharmony_ci if((supportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_ROTATION) != 0) { 694bf215546Sopenharmony_ci orientation_modes |= PIPE_VIDEO_VPP_ROTATION_90; 695bf215546Sopenharmony_ci orientation_modes |= PIPE_VIDEO_VPP_ROTATION_180; 696bf215546Sopenharmony_ci orientation_modes |= PIPE_VIDEO_VPP_ROTATION_270; 697bf215546Sopenharmony_ci } 698bf215546Sopenharmony_ci return orientation_modes; 699bf215546Sopenharmony_ci } 700bf215546Sopenharmony_ci } 701bf215546Sopenharmony_ci return 0; 702bf215546Sopenharmony_ci } break; 703bf215546Sopenharmony_ci default: 704bf215546Sopenharmony_ci return 0; 705bf215546Sopenharmony_ci } 706bf215546Sopenharmony_ci} 707bf215546Sopenharmony_ci 708bf215546Sopenharmony_cistatic int 709bf215546Sopenharmony_cid3d12_screen_get_video_param_encode(struct pipe_screen *pscreen, 710bf215546Sopenharmony_ci enum pipe_video_profile profile, 711bf215546Sopenharmony_ci enum pipe_video_entrypoint entrypoint, 712bf215546Sopenharmony_ci enum pipe_video_cap param) 713bf215546Sopenharmony_ci{ 714bf215546Sopenharmony_ci uint32_t maxLvlEncode = 0u; 715bf215546Sopenharmony_ci D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC maxResEncode = {}; 716bf215546Sopenharmony_ci uint32_t maxSlices = 0u; 717bf215546Sopenharmony_ci uint32_t supportedSliceStructures = 0u; 718bf215546Sopenharmony_ci uint32_t maxReferencesPerFrame = 0u; 719bf215546Sopenharmony_ci switch (param) { 720bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_NPOT_TEXTURES: 721bf215546Sopenharmony_ci return 1; 722bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_WIDTH: 723bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_HEIGHT: 724bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_LEVEL: 725bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTED: 726bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_ENC_MAX_SLICES_PER_FRAME: 727bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_ENC_SLICES_STRUCTURE: 728bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_ENC_MAX_REFERENCES_PER_FRAME: 729bf215546Sopenharmony_ci { 730bf215546Sopenharmony_ci if (d3d12_has_video_encode_support(pscreen, 731bf215546Sopenharmony_ci profile, 732bf215546Sopenharmony_ci maxLvlEncode, 733bf215546Sopenharmony_ci maxResEncode, 734bf215546Sopenharmony_ci maxSlices, 735bf215546Sopenharmony_ci supportedSliceStructures, 736bf215546Sopenharmony_ci maxReferencesPerFrame)) { 737bf215546Sopenharmony_ci if (param == PIPE_VIDEO_CAP_MAX_WIDTH) { 738bf215546Sopenharmony_ci return maxResEncode.Width; 739bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_MAX_HEIGHT) { 740bf215546Sopenharmony_ci return maxResEncode.Height; 741bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_MAX_LEVEL) { 742bf215546Sopenharmony_ci return maxLvlEncode; 743bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_SUPPORTED) { 744bf215546Sopenharmony_ci return 1; 745bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_ENC_MAX_SLICES_PER_FRAME) { 746bf215546Sopenharmony_ci return maxSlices; 747bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_ENC_SLICES_STRUCTURE) { 748bf215546Sopenharmony_ci return supportedSliceStructures; 749bf215546Sopenharmony_ci } else if (param == PIPE_VIDEO_CAP_ENC_MAX_REFERENCES_PER_FRAME) { 750bf215546Sopenharmony_ci return maxReferencesPerFrame; 751bf215546Sopenharmony_ci } 752bf215546Sopenharmony_ci } 753bf215546Sopenharmony_ci return 0; 754bf215546Sopenharmony_ci } break; 755bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_PREFERED_FORMAT: 756bf215546Sopenharmony_ci return PIPE_FORMAT_NV12; 757bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_PREFERS_INTERLACED: 758bf215546Sopenharmony_ci return false; 759bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: 760bf215546Sopenharmony_ci return false; 761bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE: 762bf215546Sopenharmony_ci return true; 763bf215546Sopenharmony_ci case PIPE_VIDEO_SUPPORTS_CONTIGUOUS_PLANES_MAP: 764bf215546Sopenharmony_ci return true; 765bf215546Sopenharmony_ci default: 766bf215546Sopenharmony_ci debug_printf("[d3d12_screen_get_video_param] unknown video param: %d\n", param); 767bf215546Sopenharmony_ci return 0; 768bf215546Sopenharmony_ci } 769bf215546Sopenharmony_ci} 770bf215546Sopenharmony_ci 771bf215546Sopenharmony_cistatic int 772bf215546Sopenharmony_cid3d12_screen_get_video_param(struct pipe_screen *pscreen, 773bf215546Sopenharmony_ci enum pipe_video_profile profile, 774bf215546Sopenharmony_ci enum pipe_video_entrypoint entrypoint, 775bf215546Sopenharmony_ci enum pipe_video_cap param) 776bf215546Sopenharmony_ci{ 777bf215546Sopenharmony_ci if (entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) { 778bf215546Sopenharmony_ci return d3d12_screen_get_video_param_decode(pscreen, profile, entrypoint, param); 779bf215546Sopenharmony_ci } else if (entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 780bf215546Sopenharmony_ci return d3d12_screen_get_video_param_encode(pscreen, profile, entrypoint, param); 781bf215546Sopenharmony_ci } else if (entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING) { 782bf215546Sopenharmony_ci return d3d12_screen_get_video_param_postproc(pscreen, profile, entrypoint, param); 783bf215546Sopenharmony_ci } 784bf215546Sopenharmony_ci return 0; 785bf215546Sopenharmony_ci} 786bf215546Sopenharmony_ci 787bf215546Sopenharmony_civoid 788bf215546Sopenharmony_cid3d12_screen_video_init(struct pipe_screen *pscreen) 789bf215546Sopenharmony_ci{ 790bf215546Sopenharmony_ci pscreen->get_video_param = d3d12_screen_get_video_param; 791bf215546Sopenharmony_ci pscreen->is_video_format_supported = d3d12_video_buffer_is_format_supported; 792bf215546Sopenharmony_ci} 793