Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • Thrillseekr/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
400 results
Show changes
Commits on Source (9)
......@@ -6,7 +6,10 @@ Decoders:
- Fix some ASS subtitle rendering issues
Video Output:
* Super Resolution scaling with AMD GPUs
- Super Resolution scaling with AMD GPUs
- Add D3D11 option to use NVIDIA TrueHDR to generate HDR from SDR sources
- The D3D11 HDR option can also turn on/off HDR for all sources regardless of
the display
Audio Output:
- Fix regression on macOS causing crashes when using audio devices
......
......@@ -144,6 +144,20 @@ const d3d_format_t *FindD3D11Format(vlc_object_t *,
#define FindD3D11Format(a,b,c,d,e,f,g,h,i) \
FindD3D11Format(VLC_OBJECT(a),b,c,d,e,f,g,h,i)
static inline const d3d_format_t *D3D11_RenderFormat(DXGI_FORMAT opaque, bool gpu_based)
{
for (const d3d_format_t *output_format = GetRenderFormatList();
output_format->name != NULL; ++output_format)
{
if (output_format->formatTexture == opaque &&
is_d3d11_opaque(output_format->fourcc) == gpu_based)
{
return output_format;
}
}
return NULL;
}
int AllocateTextures(vlc_object_t *, d3d11_device_t *, const d3d_format_t *,
const video_format_t *, unsigned pool_size, ID3D11Texture2D *textures[]);
#define AllocateTextures(a,b,c,d,e,f) AllocateTextures(VLC_OBJECT(a),b,c,d,e,f)
......
......@@ -284,7 +284,8 @@ libdirect3d11_plugin_la_SOURCES = video_output/win32/direct3d11.c \
video_output/win32/d3d11_quad.c video_output/win32/d3d11_quad.h \
video_output/win32/d3d11_shaders.c video_output/win32/d3d11_shaders.h \
video_output/win32/common.c video_output/win32/common.h \
video_output/win32/d3d11_scaler.cpp video_output/win32/d3d11_scaler.h
video_output/win32/d3d11_scaler.cpp video_output/win32/d3d11_scaler.h \
video_output/win32/d3d11_tonemap.cpp video_output/win32/d3d11_tonemap.h
libdirect3d11_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
-DMODULE_NAME_IS_direct3d11
libdirect3d11_plugin_la_LIBADD = libchroma_copy.la libd3d11_common.la $(LIBCOM) -luuid
......
// SPDX-License-Identifier: LGPL-2.1-or-later
/*****************************************************************************
* d3d11_tonemap: Direct3D11 VideoProcessor to handle tonemapping
*****************************************************************************
* Copyright © 2024 Videolabs, VLC authors and VideoLAN
*
* Authors: Steve Lhomme <robux4@videolabs.io>
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "d3d11_tonemap.h"
#include <cassert>
#include <wrl/client.h>
using Microsoft::WRL::ComPtr;
struct d3d11_tonemapper
{
ComPtr<ID3D11VideoDevice> d3dviddev;
ComPtr<ID3D11VideoContext> d3dvidctx;
ComPtr<ID3D11VideoProcessorEnumerator> enumerator;
ComPtr<ID3D11VideoProcessor> processor;
ComPtr<ID3D11VideoProcessorOutputView> outputView;
ComPtr<ID3D11ShaderResourceView> SRV;
picture_sys_t picsys{};
};
d3d11_tonemapper *D3D11_TonemapperCreate(vlc_object_t *vd, d3d11_device_t *d3d_dev,
const video_format_t *in)
{
if (!is_d3d11_opaque(in->i_chroma))
{
msg_Dbg(vd, "VideoProcessor tone mapping not supported by CPU formats");
return nullptr;
}
if (in->transfer == TRANSFER_FUNC_SMPTE_ST2084 ||
in->transfer == TRANSFER_FUNC_HLG)
{
return nullptr; // the source is already in HDR
}
ComPtr<ID3D11Texture2D> texture;
ID3D11Texture2D *_texture[D3D11_MAX_SHADER_VIEW] = {};
D3D11_TEXTURE2D_DESC texDesc { };
D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC outDesc{ };
d3d11_tonemapper *tonemapProc = new d3d11_tonemapper();
const auto d3d_fmt = D3D11_RenderFormat(DXGI_FORMAT_R10G10B10A2_UNORM, false);
assert(d3d_fmt != nullptr);
HRESULT hr;
hr = d3d_dev->d3ddevice->QueryInterface(IID_GRAPHICS_PPV_ARGS(&tonemapProc->d3dviddev));
if (unlikely(FAILED(hr)))
{
msg_Err(vd, "Could not Query ID3D11VideoDevice Interface. (hr=0x%lX)", hr);
goto error;
}
hr = d3d_dev->d3dcontext->QueryInterface(IID_GRAPHICS_PPV_ARGS(&tonemapProc->d3dvidctx));
if (unlikely(FAILED(hr)))
{
msg_Err(vd, "Could not Query ID3D11VideoContext Interface. (hr=0x%lX)", hr);
goto error;
}
{
D3D11_VIDEO_PROCESSOR_CONTENT_DESC processorDesc{};
processorDesc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
processorDesc.InputFrameRate = {
in->i_frame_rate, in->i_frame_rate_base,
};
processorDesc.InputWidth = in->i_width;
processorDesc.InputHeight = in->i_height;
processorDesc.OutputWidth = in->i_width;
processorDesc.OutputHeight = in->i_height;
processorDesc.OutputFrameRate = {
in->i_frame_rate, in->i_frame_rate_base,
};
processorDesc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;
hr = tonemapProc->d3dviddev->CreateVideoProcessorEnumerator(&processorDesc, &tonemapProc->enumerator);
if (FAILED(hr))
{
msg_Dbg(vd, "Can't get a video processor for the video (error 0x%lx).", hr);
goto error;
}
hr = tonemapProc->d3dviddev->CreateVideoProcessor(tonemapProc->enumerator.Get(), 0,
&tonemapProc->processor);
if (FAILED(hr))
{
msg_Dbg(vd, "failed to create the processor (error 0x%lx).", hr);
goto error;
}
}
// we can only use this filter with the NVIDIA extension as the VideoProcessor
// doesn't provide a proper API to set the input and output colorimetry
// NVIDIA 545+ driver
if (d3d_dev->adapterDesc.VendorId != GPU_MANUFACTURER_NVIDIA ||
(d3d_dev->WDDM.revision * 10000 + d3d_dev->WDDM.build) < 154500)
goto error;
{
constexpr GUID kNvidiaTrueHDRInterfaceGUID{ 0xfdd62bb4, 0x620b, 0x4fd7, {0x9a, 0xb3, 0x1e, 0x59, 0xd0, 0xd5, 0x44, 0xb3} };
UINT available = 0;
d3d11_device_lock(d3d_dev);
hr = tonemapProc->d3dvidctx->VideoProcessorGetStreamExtension(tonemapProc->processor.Get(),
0, &kNvidiaTrueHDRInterfaceGUID, sizeof(available), &available);
if (!available)
{
d3d11_device_unlock(d3d_dev);
goto error;
}
constexpr UINT kStreamExtensionMethodTrueHDR = 0x3;
constexpr UINT TrueHDRVersion4 = 4;
struct {
UINT version;
UINT method;
UINT enable : 1;
UINT reserved : 31;
} stream_extension_info = {TrueHDRVersion4,
kStreamExtensionMethodTrueHDR,
1u,
0u};
hr = tonemapProc->d3dvidctx->VideoProcessorSetStreamExtension(
tonemapProc->processor.Get(),
0, &kNvidiaTrueHDRInterfaceGUID,
sizeof(stream_extension_info), &stream_extension_info);
if (unlikely(FAILED(hr)))
{
msg_Warn(vd, "Failed to enable NVIDIA True HDR");
}
d3d11_device_unlock(d3d_dev);
}
// we need a texture that will receive the upscale version
texDesc.MipLevels = 1;
texDesc.SampleDesc.Count = 1;
texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.CPUAccessFlags = 0;
texDesc.ArraySize = 1;
texDesc.Format = d3d_fmt->formatTexture;
texDesc.Width = in->i_width;
texDesc.Height = in->i_height;
texDesc.MiscFlags = 0;
hr = d3d_dev->d3ddevice->CreateTexture2D(&texDesc, nullptr, texture.GetAddressOf());
if (FAILED(hr))
{
msg_Err(vd, "Failed to create the tonemap texture. (hr=0x%lX)", hr);
goto error;
}
outDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
outDesc.Texture2D.MipSlice = 0;
hr = tonemapProc->d3dviddev->CreateVideoProcessorOutputView(
texture.Get(),
tonemapProc->enumerator.Get(),
&outDesc,
tonemapProc->outputView.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
msg_Dbg(vd,"Failed to create processor output. (hr=0x%lX)", hr);
goto error;
}
_texture[0] = texture.Get();
_texture[1] = texture.Get();
_texture[2] = texture.Get();
_texture[3] = texture.Get();
if ((D3D11_AllocateShaderView)(vd, d3d_dev->d3ddevice, d3d_fmt,
_texture, 0, tonemapProc->SRV.GetAddressOf()) != VLC_SUCCESS)
goto error;
{
RECT srcRect;
srcRect.left = 0;
srcRect.top = 0;
srcRect.right = texDesc.Width;
srcRect.bottom = texDesc.Height;
RECT dstRect = srcRect;
d3d11_device_lock(d3d_dev);
tonemapProc->d3dvidctx->VideoProcessorSetStreamSourceRect(tonemapProc->processor.Get(),
0, TRUE, &srcRect);
tonemapProc->d3dvidctx->VideoProcessorSetStreamDestRect(tonemapProc->processor.Get(),
0, TRUE, &dstRect);
d3d11_device_unlock(d3d_dev);
}
tonemapProc->picsys.texture[0] = texture.Get();
tonemapProc->picsys.resourceView[0] = tonemapProc->SRV.Get();
tonemapProc->picsys.formatTexture = texDesc.Format;
return tonemapProc;
error:
delete tonemapProc;
return nullptr;
}
void D3D11_TonemapperDestroy(d3d11_tonemapper *tonemapProc)
{
delete tonemapProc;
}
picture_sys_t *D3D11_TonemapperGetOutput(d3d11_tonemapper *tonemapProc)
{
return &tonemapProc->picsys;
}
static HRESULT assert_ProcessorInput(vlc_object_t *vd, d3d11_tonemapper *tonemapProc, picture_sys_t *p_sys_src)
{
if (!p_sys_src->processorInput)
{
D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC inDesc{};
inDesc.FourCC = 0;
inDesc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
inDesc.Texture2D.MipSlice = 0;
inDesc.Texture2D.ArraySlice = p_sys_src->slice_index;
HRESULT hr;
hr = tonemapProc->d3dviddev->CreateVideoProcessorInputView(
p_sys_src->resource[KNOWN_DXGI_INDEX],
tonemapProc->enumerator.Get(),
&inDesc,
&p_sys_src->processorInput);
if (FAILED(hr))
{
#ifndef NDEBUG
msg_Dbg(vd,"Failed to create processor input for slice %d. (hr=0x%lX)", p_sys_src->slice_index, hr);
#endif
return hr;
}
}
return S_OK;
}
HRESULT D3D11_TonemapperProcess(vlc_object_t *vd, d3d11_tonemapper *tonemapProc, picture_sys_t *in)
{
HRESULT hr = assert_ProcessorInput(vd, tonemapProc, in);
if (FAILED(hr))
return hr;
D3D11_VIDEO_PROCESSOR_STREAM stream{};
stream.Enable = TRUE;
stream.pInputSurface = in->processorInput;
hr = tonemapProc->d3dvidctx->VideoProcessorBlt(tonemapProc->processor.Get(),
tonemapProc->outputView.Get(),
0, 1, &stream);
if (FAILED(hr))
msg_Err(vd, "Failed to render the texture. (hr=0x%lX)", hr);
return hr;
}
// SPDX-License-Identifier: LGPL-2.1-or-later
/*****************************************************************************
* d3d11_tonemap: Direct3D11 VideoProcessor to handle tonemapping
*****************************************************************************
* Copyright © 2024 Videolabs, VLC authors and VideoLAN
*
* Authors: Steve Lhomme <robux4@videolabs.io>
*****************************************************************************/
#ifndef VLC_D3D11_TONEMAP_H
#define VLC_D3D11_TONEMAP_H
#include "d3d11_quad.h"
#include "../../video_chroma/d3d11_fmt.h"
#include <vlc_vout_display.h>
#ifdef __cplusplus
extern "C" {
#endif
struct d3d11_tonemapper;
struct d3d11_tonemapper *D3D11_TonemapperCreate(vlc_object_t *, d3d11_device_t *,
const video_format_t * in);
void D3D11_TonemapperDestroy(struct d3d11_tonemapper *);
HRESULT D3D11_TonemapperProcess(vlc_object_t *, struct d3d11_tonemapper *, picture_sys_t *);
struct picture_sys_t *D3D11_TonemapperGetOutput(struct d3d11_tonemapper *);
#ifdef __cplusplus
}
#endif
#endif // VLC_D3D11_TONEMAP_H
......@@ -56,6 +56,7 @@
#include "d3d11_quad.h"
#include "d3d11_shaders.h"
#include "d3d11_scaler.h"
#include "d3d11_tonemap.h"
#include "common.h"
......@@ -78,6 +79,14 @@ static const char *const ppsz_upscale_mode[] = {
static const char *const ppsz_upscale_mode_text[] = {
N_("Linear Sampler"), N_("Point Sampler"), N_("Video Processor"), N_("Super Resolution") };
#define HDR_MODE_TEXT N_("HDR Output Mode")
#define HDR_MODE_LONGTEXT N_("Use HDR output even if the source is SDR.")
static const char *const ppsz_hdr_mode[] = {
"auto", "never", "always", "generate" };
static const char *const ppsz_hdr_mode_text[] = {
N_("Auto"), N_("Never out HDR"), N_("Always output HDR"), N_("Generate HDR from SDR") };
vlc_module_begin ()
set_shortname("Direct3D11")
set_description(N_("Direct3D11 video output"))
......@@ -95,6 +104,9 @@ vlc_module_begin ()
add_string("d3d11-upscale-mode", "linear", UPSCALE_MODE_TEXT, UPSCALE_MODE_LONGTEXT, false)
change_string_list(ppsz_upscale_mode, ppsz_upscale_mode_text)
add_string("d3d11-hdr-mode", "auto", HDR_MODE_TEXT, HDR_MODE_LONGTEXT, false)
change_string_list(ppsz_hdr_mode, ppsz_hdr_mode_text)
set_capability("vout display", 300)
add_shortcut("direct3d11")
set_callbacks(Open, Close)
......@@ -108,6 +120,14 @@ enum d3d11_upscale
upscale_SuperResolution,
};
enum d3d11_hdr
{
hdr_Auto,
hdr_Never,
hdr_Always,
hdr_Fake,
};
struct vout_display_sys_t
{
vout_display_sys_win32_t sys;
......@@ -157,6 +177,10 @@ struct vout_display_sys_t
// upscaling
enum d3d11_upscale upscaleMode;
struct d3d11_scaler *scaleProc;
// HDR mode
enum d3d11_hdr hdrMode;
struct d3d11_tonemapper *tonemapProc;
};
#define RECTWidth(r) (int)((r).right - (r).left)
......@@ -172,7 +196,7 @@ static void Direct3D11Destroy(vout_display_t *);
static int Direct3D11Open (vout_display_t *, bool external_device);
static void Direct3D11Close(vout_display_t *);
static int SetupOutputFormat(vout_display_t *, video_format_t *);
static int SetupOutputFormat(vout_display_t *, video_format_t *decoder, video_format_t *quad);
static int Direct3D11CreateFormatResources (vout_display_t *, const video_format_t *);
static int Direct3D11CreateGenericResources(vout_display_t *);
static void Direct3D11DestroyResources(vout_display_t *);
......@@ -513,6 +537,7 @@ static void DestroyDisplayPoolPicture(picture_t *picture)
#if !VLC_WINSTORE_APP
static void FillSwapChainDesc(vout_display_t *vd, DXGI_SWAP_CHAIN_DESC1 *out)
{
vout_display_sys_t *sys = vd->sys;
ZeroMemory(out, sizeof(*out));
out->BufferCount = 3;
out->BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
......@@ -520,14 +545,15 @@ static void FillSwapChainDesc(vout_display_t *vd, DXGI_SWAP_CHAIN_DESC1 *out)
out->SampleDesc.Quality = 0;
out->Width = vd->source.i_visible_width;
out->Height = vd->source.i_visible_height;
switch(vd->source.i_chroma)
{
case VLC_CODEC_D3D11_OPAQUE_10B:
out->Format = DXGI_FORMAT_R8G8B8A8_UNORM; /* TODO: use DXGI_FORMAT_NV12 */
if (sys->hdrMode == hdr_Always || sys->hdrMode == hdr_Fake)
out->Format = DXGI_FORMAT_R10G10B10A2_UNORM;
break;
default:
out->Format = DXGI_FORMAT_R8G8B8A8_UNORM; /* TODO: use DXGI_FORMAT_NV12 */
break;
else if (sys->hdrMode == hdr_Auto)
{
if ( vd->source.i_chroma == VLC_CODEC_D3D11_OPAQUE_10B ||
vd->source.transfer == TRANSFER_FUNC_SMPTE_ST2084 ||
vd->source.transfer == TRANSFER_FUNC_HLG)
out->Format = DXGI_FORMAT_R10G10B10A2_UNORM;
}
//out->Flags = 512; // DXGI_SWAP_CHAIN_FLAG_YUV_VIDEO;
......@@ -1026,7 +1052,13 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
if (is_d3d11_opaque(picture->format.i_chroma))
d3d11_device_lock( &sys->d3d_dev );
if (sys->scaleProc && D3D11_UpscalerUsed(sys->scaleProc))
if (sys->tonemapProc)
{
if (FAILED(D3D11_TonemapperProcess(VLC_OBJECT(vd), sys->tonemapProc, p_sys)))
return;
p_sys = D3D11_TonemapperGetOutput(sys->tonemapProc);
}
else if (sys->scaleProc && D3D11_UpscalerUsed(sys->scaleProc))
{
if (D3D11_UpscalerScale(VLC_OBJECT(vd), sys->scaleProc, p_sys) != VLC_SUCCESS)
return;
......@@ -1132,7 +1164,11 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
}
else
{
picture_sys_t *p_sys = ActivePictureSys(picture);
picture_sys_t *p_sys;
if (sys->tonemapProc)
p_sys = D3D11_TonemapperGetOutput(sys->tonemapProc);
else
p_sys = ActivePictureSys(picture);
D3D11_RenderQuad(&sys->d3d_dev, &sys->picQuad, p_sys->resourceView, sys->d3drenderTargetView);
}
......@@ -1272,10 +1308,26 @@ static void D3D11SetColorSpace(vout_display_t *vd)
goto done;
}
bool src_full_range = vd->source.b_color_range_full ||
video_format_t match_source = vd->source;
if (sys->hdrMode == hdr_Never)
{
match_source.primaries = COLOR_PRIMARIES_BT709;
match_source.transfer = TRANSFER_FUNC_BT709;
match_source.space = COLOR_SPACE_BT709;
}
else if (sys->hdrMode == hdr_Always || sys->hdrMode == hdr_Fake)
{
match_source.primaries = COLOR_PRIMARIES_BT2020;
match_source.transfer = TRANSFER_FUNC_SMPTE_ST2084;
match_source.space = COLOR_SPACE_BT2020;
if (sys->hdrMode == hdr_Fake) // the video processor keeps the source range
match_source.i_chroma = VLC_CODEC_RGBA10;
}
bool src_full_range = match_source.b_color_range_full ||
/* the YUV->RGB conversion already output full range */
is_d3d11_opaque(vd->source.i_chroma) ||
vlc_fourcc_IsYUV(vd->source.i_chroma);
is_d3d11_opaque(match_source.i_chroma) ||
vlc_fourcc_IsYUV(match_source.i_chroma);
/* pick the best output based on color support and transfer */
/* TODO support YUV output later */
......@@ -1285,13 +1337,13 @@ static void D3D11SetColorSpace(vout_display_t *vd)
if (SUCCEEDED(hr) && support) {
msg_Dbg(vd, "supports colorspace %s", color_spaces[i].name);
score = 0;
if (color_spaces[i].primaries == vd->source.primaries)
if (color_spaces[i].primaries == match_source.primaries)
score++;
if (color_spaces[i].color == vd->source.space)
if (color_spaces[i].color == match_source.space)
score += 2; /* we don't want to translate color spaces */
if (color_spaces[i].transfer == vd->source.transfer ||
if (color_spaces[i].transfer == match_source.transfer ||
/* favor 2084 output for HLG source */
(color_spaces[i].transfer == TRANSFER_FUNC_SMPTE_ST2084 && vd->source.transfer == TRANSFER_FUNC_HLG))
(color_spaces[i].transfer == TRANSFER_FUNC_SMPTE_ST2084 && match_source.transfer == TRANSFER_FUNC_HLG))
score++;
if (color_spaces[i].b_full_range == src_full_range)
score++;
......@@ -1309,6 +1361,7 @@ static void D3D11SetColorSpace(vout_display_t *vd)
}
#ifdef HAVE_DXGI1_6_H
if (sys->hdrMode == hdr_Auto) // match the screen
if (SUCCEEDED(IDXGISwapChain_GetContainingOutput( sys->dxgiswapChain, &dxgiOutput )))
{
IDXGIOutput6 *dxgiOutput6 = NULL;
......@@ -1457,6 +1510,38 @@ static bool BogusZeroCopy(const vout_display_t *vd)
}
}
static enum d3d11_hdr HdrModeFromString(vlc_object_t *logger, const char *psz_hdr)
{
if (strcmp("auto", psz_hdr) == 0)
return hdr_Auto;
if (strcmp("never", psz_hdr) == 0)
return hdr_Never;
if (strcmp("always", psz_hdr) == 0)
return hdr_Always;
if (strcmp("generate", psz_hdr) == 0)
return hdr_Fake;
msg_Warn(logger, "unknown HDR mode %s, using auto mode", psz_hdr);
return hdr_Auto;
}
static void InitTonemapProcessor(vout_display_t *vd, const video_format_t *fmt_in)
{
vout_display_sys_t *sys = vd->sys;
if (sys->hdrMode != hdr_Fake)
return;
sys->tonemapProc = D3D11_TonemapperCreate(VLC_OBJECT(vd), &sys->d3d_dev, fmt_in);
if (sys->tonemapProc == NULL)
{
sys->hdrMode = hdr_Auto;
msg_Dbg(vd, "failed to create the tone mapper, using default HDR mode");
return;
}
msg_Dbg(vd, "Using tonemapper");
}
static void InitScaleProcessor(vout_display_t *vd)
{
vout_display_sys_t *sys = vd->sys;
......@@ -1477,13 +1562,16 @@ static int Direct3D11Open(vout_display_t *vd, bool external_device)
vout_display_sys_t *sys = vd->sys;
IDXGIFactory2 *dxgifactory;
char *psz_hdr = var_InheritString(vd, "d3d11-hdr-mode");
sys->hdrMode = HdrModeFromString(VLC_OBJECT(vd), psz_hdr);
free(psz_hdr);
if (!external_device)
{
#if !VLC_WINSTORE_APP
HRESULT hr = S_OK;
DXGI_SWAP_CHAIN_DESC1 scd;
FillSwapChainDesc(vd, &scd);
hr = D3D11_CreateDevice(vd, &sys->hd3d,
is_d3d11_opaque(vd->source.i_chroma),
......@@ -1499,6 +1587,8 @@ static int Direct3D11Open(vout_display_t *vd, bool external_device)
return VLC_EGENERIC;
}
InitTonemapProcessor(vd, &vd->source);
hr = IDXGIAdapter_GetParent(dxgiadapter, &IID_IDXGIFactory2, (void **)&dxgifactory);
IDXGIAdapter_Release(dxgiadapter);
if (FAILED(hr)) {
......@@ -1506,6 +1596,8 @@ static int Direct3D11Open(vout_display_t *vd, bool external_device)
return VLC_EGENERIC;
}
FillSwapChainDesc(vd, &scd);
hr = IDXGIFactory2_CreateSwapChainForHwnd(dxgifactory, (IUnknown *)sys->d3d_dev.d3ddevice,
sys->sys.hvideownd, &scd, NULL, NULL, &sys->dxgiswapChain);
if (hr == DXGI_ERROR_INVALID_CALL && scd.Format == DXGI_FORMAT_R10G10B10A2_UNORM)
......@@ -1543,9 +1635,9 @@ static int Direct3D11Open(vout_display_t *vd, bool external_device)
}
free(psz_upscale);
video_format_t fmt;
video_format_Copy(&fmt, &vd->source);
int err = SetupOutputFormat(vd, &fmt);
video_format_Copy(&sys->pool_fmt, &vd->source);
video_format_Copy(&sys->quad_fmt, &vd->source);
int err = SetupOutputFormat(vd, &sys->pool_fmt, &sys->quad_fmt);
if (err != VLC_SUCCESS)
{
if (!is_d3d11_opaque(vd->source.i_chroma)
......@@ -1558,10 +1650,10 @@ static int Direct3D11Open(vout_display_t *vd, bool external_device)
vlc_fourcc_GetYUVFallback(vd->source.i_chroma) :
vlc_fourcc_GetRGBFallback(vd->source.i_chroma);
for (unsigned i = 0; list[i] != 0; i++) {
fmt.i_chroma = list[i];
if (fmt.i_chroma == vd->source.i_chroma)
sys->pool_fmt.i_chroma = list[i];
if (sys->pool_fmt.i_chroma == vd->source.i_chroma)
continue;
err = SetupOutputFormat(vd, &fmt);
err = SetupOutputFormat(vd, &sys->pool_fmt, &sys->quad_fmt);
if (err == VLC_SUCCESS)
break;
}
......@@ -1570,13 +1662,9 @@ static int Direct3D11Open(vout_display_t *vd, bool external_device)
return err;
}
video_format_Init(&sys->quad_fmt, vd->source.i_chroma);
video_format_Copy(&sys->quad_fmt, &vd->source);
if (sys->upscaleMode == upscale_VideoProcessor || sys->upscaleMode == upscale_SuperResolution)
sys->sys.src_fmt = &sys->quad_fmt;
video_format_Copy(&sys->pool_fmt, &fmt);
if ( sys->picQuad.formatInfo->formatTexture != DXGI_FORMAT_R8G8B8A8_UNORM &&
sys->picQuad.formatInfo->formatTexture != DXGI_FORMAT_B5G6R5_UNORM )
{
......@@ -1590,93 +1678,127 @@ static int Direct3D11Open(vout_display_t *vd, bool external_device)
}
video_format_Clean(&vd->fmt);
vd->fmt = fmt;
vd->fmt = sys->pool_fmt;
sys->log_level = var_InheritInteger(vd, "verbose");
return VLC_SUCCESS;
}
static int SetupOutputFormat(vout_display_t *vd, video_format_t *fmt)
static const d3d_format_t *SelectClosestOutput(vout_display_t *vd, vlc_fourcc_t i_chroma,
bool from_processor)
{
vout_display_sys_t *sys = vd->sys;
// look for the requested pixel format first
sys->picQuad.formatInfo = GetDirectRenderingFormat(vd, fmt->i_chroma);
const d3d_format_t *res = NULL;
// look for any pixel format that we can handle with enough pixels per channel
const d3d_format_t *decoder_format = NULL;
if ( !sys->picQuad.formatInfo )
uint8_t bits_per_channel;
uint8_t widthDenominator, heightDenominator;
switch (i_chroma)
{
uint8_t bits_per_channel;
uint8_t widthDenominator, heightDenominator;
switch (fmt->i_chroma)
case VLC_CODEC_D3D11_OPAQUE:
bits_per_channel = 8;
widthDenominator = heightDenominator = 2;
break;
case VLC_CODEC_D3D11_OPAQUE_10B:
bits_per_channel = 10;
widthDenominator = heightDenominator = 2;
break;
default:
{
case VLC_CODEC_D3D11_OPAQUE:
bits_per_channel = 8;
widthDenominator = heightDenominator = 2;
break;
case VLC_CODEC_D3D11_OPAQUE_10B:
bits_per_channel = 10;
widthDenominator = heightDenominator = 2;
break;
default:
const vlc_chroma_description_t *p_format = vlc_fourcc_GetChromaDescription(i_chroma);
if (p_format == NULL)
{
const vlc_chroma_description_t *p_format = vlc_fourcc_GetChromaDescription(fmt->i_chroma);
if (p_format == NULL)
{
bits_per_channel = 8;
widthDenominator = heightDenominator = 2;
}
else
bits_per_channel = 8;
widthDenominator = heightDenominator = 2;
}
else
{
bits_per_channel = p_format->pixel_bits == 0 ? 8 : p_format->pixel_bits /
(p_format->plane_count==1 ? p_format->pixel_size : 1);
widthDenominator = heightDenominator = 1;
for (size_t i=0; i<p_format->plane_count; i++)
{
bits_per_channel = p_format->pixel_bits == 0 ? 8 : p_format->pixel_bits /
(p_format->plane_count==1 ? p_format->pixel_size : 1);
widthDenominator = heightDenominator = 1;
for (size_t i=0; i<p_format->plane_count; i++)
{
if (widthDenominator < p_format->p[i].w.den)
widthDenominator = p_format->p[i].w.den;
if (heightDenominator < p_format->p[i].h.den)
heightDenominator = p_format->p[1].h.den;
}
if (widthDenominator < p_format->p[i].w.den)
widthDenominator = p_format->p[i].w.den;
if (heightDenominator < p_format->p[i].h.den)
heightDenominator = p_format->p[1].h.den;
}
}
break;
}
/* look for a decoder format that can be decoded but not used in shaders */
if ( is_d3d11_opaque(fmt->i_chroma) )
decoder_format = GetDirectDecoderFormat(vd, fmt->i_chroma);
else
decoder_format = sys->picQuad.formatInfo;
bool is_rgb = !vlc_fourcc_IsYUV(fmt->i_chroma);
sys->picQuad.formatInfo = GetDisplayFormatByDepth(vd, bits_per_channel,
widthDenominator,
heightDenominator,
decoder_format!=NULL, is_rgb);
if (!sys->picQuad.formatInfo && is_rgb)
sys->picQuad.formatInfo = GetDisplayFormatByDepth(vd, bits_per_channel,
widthDenominator,
heightDenominator,
decoder_format!=NULL, false);
break;
}
bool is_rgb = !vlc_fourcc_IsYUV(i_chroma);
res = GetDisplayFormatByDepth(vd, bits_per_channel,
widthDenominator,
heightDenominator,
from_processor, is_rgb);
if (res != NULL)
return res;
if (is_rgb)
res = GetDisplayFormatByDepth(vd, bits_per_channel,
widthDenominator,
heightDenominator,
from_processor, false);
if (res != NULL)
return res;
// look for any pixel format that we can handle
if ( !sys->picQuad.formatInfo )
sys->picQuad.formatInfo = GetDisplayFormatByDepth(vd, 0, 0, 0, false, false);
res = GetDisplayFormatByDepth(vd, 0, 0, 0, false, false);
return res;
}
static const d3d_format_t *SelectOutputFormat(vout_display_t *vd, const video_format_t *fmt,
const d3d_format_t ** decoder_format)
{
const d3d_format_t *res = NULL;
// look for the requested pixel format first
res = GetDirectRenderingFormat(vd, fmt->i_chroma);
if (res != NULL)
return res;
/* look for a decoder format that can be decoded but not used in shaders */
if ( is_d3d11_opaque(fmt->i_chroma) )
*decoder_format = GetDirectDecoderFormat(vd, fmt->i_chroma);
res = SelectClosestOutput(vd, fmt->i_chroma, *decoder_format!=NULL);
return res;
}
static int SetupOutputFormat(vout_display_t *vd, video_format_t *fmt, video_format_t *quad_fmt)
{
vout_display_sys_t *sys = vd->sys;
// look for the requested pixel format first
const d3d_format_t *decoder_format = NULL;
if (sys->hdrMode == hdr_Fake)
{
quad_fmt->i_chroma = VLC_CODEC_RGBA10;
quad_fmt->primaries = sys->display.colorspace->primaries;
quad_fmt->transfer = sys->display.colorspace->transfer;
quad_fmt->space = sys->display.colorspace->color;
quad_fmt->b_color_range_full = sys->display.colorspace->b_full_range;
// request an input format that can be input of a VideoProcessor
UINT supportFlags = D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_INPUT;
if (is_d3d11_opaque(fmt->i_chroma))
supportFlags |= D3D11_FORMAT_SUPPORT_DECODER_OUTPUT;
decoder_format = FindD3D11Format( vd, &sys->d3d_dev, fmt->i_chroma, false, 0, 0, 0,
is_d3d11_opaque(fmt->i_chroma), supportFlags );
}
sys->picQuad.formatInfo = SelectOutputFormat(vd, quad_fmt, &decoder_format);
if ( !sys->picQuad.formatInfo )
{
msg_Err(vd, "Could not get a suitable texture pixel format");
return VLC_EGENERIC;
}
sys->pool_d3dfmt = sys->picQuad.formatInfo;
sys->pool_d3dfmt = decoder_format ? decoder_format : sys->picQuad.formatInfo;
msg_Dbg( vd, "Using pixel format %s for chroma %4.4s", sys->picQuad.formatInfo->name,
msg_Dbg( vd, "Using pixel format %s for chroma %4.4s", sys->pool_d3dfmt->name,
(char *)&fmt->i_chroma );
fmt->i_chroma = decoder_format ? decoder_format->fourcc : sys->picQuad.formatInfo->fourcc;
fmt->i_chroma = sys->pool_d3dfmt->fourcc;
DxgiFormatMask( sys->picQuad.formatInfo->formatTexture, fmt );
/* check the region pixel format */
......@@ -1690,10 +1812,11 @@ static int SetupOutputFormat(vout_display_t *vd, video_format_t *fmt)
(sys->scaleProc == NULL && !CanUseTextureArray(vd)) ||
BogusZeroCopy(vd);
if (Direct3D11CreateFormatResources(vd, fmt)) {
if (Direct3D11CreateFormatResources(vd, quad_fmt)) {
msg_Err(vd, "Failed to allocate format resources");
return VLC_EGENERIC;
}
vd->info.is_slow = !is_d3d11_opaque(fmt->i_chroma) && sys->picQuad.formatInfo->formatTexture != DXGI_FORMAT_UNKNOWN;
return VLC_SUCCESS;
}
......@@ -1788,7 +1911,6 @@ static int Direct3D11CreateFormatResources(vout_display_t *vd, const video_forma
}
#endif
vd->info.is_slow = !is_d3d11_opaque(fmt->i_chroma) && sys->picQuad.formatInfo->formatTexture != DXGI_FORMAT_UNKNOWN;
return VLC_SUCCESS;
}
......@@ -1983,6 +2105,11 @@ static void Direct3D11DestroyResources(vout_display_t *vd)
ReleasePictureSys(&sys->stagingSys);
if (sys->tonemapProc != NULL)
{
D3D11_TonemapperDestroy(sys->tonemapProc);
sys->tonemapProc = NULL;
}
if (sys->scaleProc != NULL)
{
D3D11_UpscalerDestroy(sys->scaleProc);
......@@ -2189,7 +2316,7 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
place_cfg.display.width = RECTWidth(sys->sys.rect_dest_clipped);
place_cfg.display.height = RECTHeight(sys->sys.rect_dest_clipped);
}
vout_display_place_t place;
vout_display_PlacePicture(&place, &vd->source, &place_cfg, false);
......