├── .github ├── issue_template.md └── workflows │ └── main.yml ├── .gitignore ├── .gitmodules ├── Include ├── FilterInterfaces.h ├── FilterInterfacesImpl.h ├── ID3DFullscreenControl.h ├── ID3DVideoMemoryConfiguration.h ├── IMediaSideData.h ├── ISubRender.h ├── ISubRender11.h ├── SubRenderIntf.h └── Version.h ├── LICENSE.txt ├── MpcVideoRenderer.sln ├── Readme.md ├── Shaders ├── Shaders.vcxproj ├── Shaders.vcxproj.filters ├── compile_shaders.cmd ├── convert │ ├── colorspace_gamut_conversion.hlsl │ ├── conv_matrix.hlsl │ ├── hdr_tone_mapping.hlsl │ ├── hlg.hlsl │ └── st2084.hlsl ├── d3d11 │ ├── ps_TEST.hlsl │ ├── ps_convert_biplanar.hlsl │ ├── ps_convert_bitmap_to_pq.hlsl │ ├── ps_convert_color.hlsl │ ├── ps_convert_hlg_to_pq.hlsl │ ├── ps_convert_planar.hlsl │ ├── ps_convert_planar_yv.hlsl │ ├── ps_convert_pq_to_sdr.hlsl │ ├── ps_convolution.hlsl │ ├── ps_final_pass.hlsl │ ├── ps_fix_bt2020.hlsl │ ├── ps_fix_ycgco.hlsl │ ├── ps_fixconvert_hlg_to_sdr.hlsl │ ├── ps_fixconvert_pq_to_sdr.hlsl │ ├── ps_font.hlsl │ ├── ps_geometry.hlsl │ ├── ps_halfoverunder_to_interlace.hlsl │ ├── ps_interpolation_lanczos2.hlsl │ ├── ps_interpolation_lanczos3.hlsl │ ├── ps_interpolation_spline4.hlsl │ ├── ps_simple.hlsl │ ├── vs_geometry.hlsl │ └── vs_simple.hlsl ├── d3d9 │ ├── convert_biplanar.hlsl │ ├── convert_color.hlsl │ ├── convert_planar.hlsl │ ├── convert_planar_yv.hlsl │ ├── convolution.hlsl │ ├── final_pass.hlsl │ ├── fix_bt2020.hlsl │ ├── fix_ycgco.hlsl │ ├── fixconvert_hlg_to_sdr.hlsl │ ├── fixconvert_pq_to_sdr.hlsl │ ├── halfoverunder_to_interlace.hlsl │ ├── interpolation_lanczos2.hlsl │ ├── interpolation_lanczos3.hlsl │ └── interpolation_spline4.hlsl ├── examples │ ├── ps_mpv.hlsl │ ├── ps_resize_onepass_bilinear.hlsl │ ├── ps_resize_onepass_catmull4.hlsl │ ├── ps_resize_onepass_jinc2.hlsl │ ├── ps_vlc.hlsl │ ├── resizer_onepass_jinc2.hlsl │ ├── vs_mpv.hlsl │ └── vs_vlc.hlsl └── resize │ └── convolution_filters.hlsl ├── Source ├── CustomAllocator.cpp ├── CustomAllocator.h ├── D3D11VP.cpp ├── D3D11VP.h ├── D3DUtil │ ├── D3D11Font.cpp │ ├── D3D11Font.h │ ├── D3D11Geometry.cpp │ ├── D3D11Geometry.h │ ├── D3D9Font.cpp │ ├── D3D9Font.h │ ├── D3D9Geometry.cpp │ ├── D3D9Geometry.h │ ├── D3DCommon.h │ └── FontBitmap.h ├── DX11Helper.cpp ├── DX11Helper.h ├── DX11VideoProcessor.cpp ├── DX11VideoProcessor.h ├── DX9Helper.cpp ├── DX9Helper.h ├── DX9VideoProcessor.cpp ├── DX9VideoProcessor.h ├── DXVA2VP.cpp ├── DXVA2VP.h ├── DisplayConfig.cpp ├── DisplayConfig.h ├── FrameStats.h ├── Helper.cpp ├── Helper.h ├── IVideoRenderer.h ├── MediaSampleSideData.cpp ├── MediaSampleSideData.h ├── MpcVideoRenderer.def ├── MpcVideoRenderer.rc ├── MpcVideoRenderer.vcxproj ├── MpcVideoRenderer.vcxproj.filters ├── PropPage.cpp ├── PropPage.h ├── Shaders.cpp ├── Shaders.h ├── SubPic │ ├── DX11SubPic.cpp │ ├── DX11SubPic.h │ ├── DX9SubPic.cpp │ ├── DX9SubPic.h │ ├── ISubPic.h │ ├── SubPicImpl.cpp │ ├── SubPicImpl.h │ ├── SubPicQueueImpl.cpp │ ├── SubPicQueueImpl.h │ ├── XySubPicProvider.cpp │ ├── XySubPicProvider.h │ ├── XySubPicQueueImpl.cpp │ └── XySubPicQueueImpl.h ├── Times.cpp ├── Times.h ├── Utils │ ├── CPUInfo.cpp │ ├── CPUInfo.h │ ├── StringUtil.cpp │ ├── StringUtil.h │ ├── Util.cpp │ ├── Util.h │ └── gpu_memcpy_sse4.h ├── VideoProcessor.cpp ├── VideoProcessor.h ├── VideoRenderer.cpp ├── VideoRenderer.h ├── VideoRendererInputPin.cpp ├── VideoRendererInputPin.h ├── csputils.cpp ├── csputils.h ├── dllmain.cpp ├── renbase2.cpp ├── renbase2.h ├── res │ ├── MpcVideoRenderer.rc2 │ └── dither32x32float16.bin ├── resource.h ├── stdafx.cpp └── stdafx.h ├── build_mpcvr.cmd ├── common.props ├── distrib ├── Install_MPCVR_32.cmd ├── Install_MPCVR_64.cmd ├── Reset_Settings.cmd ├── Uninstall_MPCVR_32.cmd └── Uninstall_MPCVR_64.cmd ├── external ├── BaseClasses.vcxproj ├── BaseClasses.vcxproj.filters ├── minhook.vcxproj └── minhook.vcxproj.filters ├── history.txt ├── platform.props ├── sign.cmd ├── update_revision.cmd └── update_submodules.cmd /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | ### Prerequisites 2 | 3 | * [ ] Are you running the [latest version](https://github.com/Aleksoid1978/VideoRenderer/releases/latest)? 4 | * [ ] Are you running the [latest "nightly" builds](https://github.com/qwerttvv/Player/releases)? 5 | * [ ] Have you read [Known Issues](Known-Issues)? 6 | 7 | 8 | ### Description 9 | 10 | [Description of the bug or feature] 11 | 12 | 13 | ### Steps to Reproduce the Problem 14 | 15 | 1. 16 | 1. 17 | 1. 18 | 19 | ### Video files for testing 20 | 21 | [Link to video file to reproduce the problem] 22 | 23 | 24 | ### Specifications 25 | 26 | - Version of MPC Video Renderer: 27 | - Player version: 28 | - Windows version: 29 | - Name of the graphics adapter: 30 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build VideoRenderer 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - .github/workflows/main.yml 7 | - '**.txt' 8 | - '**.md' 9 | - '**.cmd' 10 | - '**.vcxproj.filters' 11 | pull_request: 12 | paths-ignore: 13 | - .github/workflows/main.yml 14 | - '**.txt' 15 | - '**.md' 16 | - '**.cmd' 17 | - '**.vcxproj.filters' 18 | 19 | jobs: 20 | build: 21 | runs-on: windows-2019 22 | 23 | steps: 24 | - name: Checkout repository 25 | uses: actions/checkout@v4 26 | with: 27 | fetch-depth: 0 28 | submodules: recursive 29 | 30 | - name: Select Windows SDK 10.0.22621.0 31 | run: | 32 | (Get-Content .\\platform.props) | ForEach-Object { $_ -replace ">10.0<", ">10.0.22621.0<" } | Set-Content .\\platform.props 33 | shell: pwsh 34 | 35 | - name: Build VideoRenderer 36 | run: | 37 | .\\build_mpcvr.cmd NoWait 38 | shell: pwsh 39 | 40 | - name: Upload build artifacts 41 | uses: actions/upload-artifact@v4 42 | with: 43 | name: "MPC Video Renderer" 44 | path: _bin/MpcVideoRenderer*.zip 45 | compression-level: 0 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.user 2 | *.aps 3 | *.bak 4 | /.vs 5 | /_bin 6 | /revision.h 7 | /signinfo.txt 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/BaseClasses"] 2 | path = external/BaseClasses 3 | url = https://github.com/v0lt/BaseClasses.git 4 | [submodule "external/minhook"] 5 | path = external/minhook 6 | url = https://github.com/TsudaKageyu/minhook.git 7 | -------------------------------------------------------------------------------- /Include/FilterInterfaces.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2017-2024 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | interface __declspec(uuid("3F56FEBC-633C-4C76-8455-0787FC62C8F8")) IExFilterInfo : public IUnknown 24 | { 25 | // The memory for strings and binary data is allocated by the callee 26 | // by using LocalAlloc. It is the caller's responsibility to release the 27 | // memory by calling LocalFree. 28 | STDMETHOD(GetPropertyInt )(LPCSTR field, int *value) PURE; 29 | STDMETHOD(GetPropertyString)(LPCSTR field, LPWSTR *value, unsigned *chars) PURE; 30 | STDMETHOD(GetPropertyBin )(LPCSTR field, LPVOID *value, unsigned *size ) PURE; 31 | }; 32 | // return values: 33 | // E_NOTIMPL - method not implemented, any parameters will be ignored. 34 | // E_POINTER - invalid pointer 35 | // E_INVALIDARG - wrong name or type of field 36 | // E_ABORT - field is correct, but the value is undefined 37 | // S_OK - operation successful 38 | // 39 | // available info fields: 40 | // name type filter valid values 41 | // VIDEO_PROFILE int MatroskaSplitter 42 | // VIDEO_PIXEL_FORMAT int MatroskaSplitter 43 | // VIDEO_INTERLACED int MatroskaSplitter,MP4Splitter,RawVideoSplitter 0-progressive, 1-tff, 2-bff 44 | // VIDEO_FLAG_ONLY_DTS int MatroskaSplitter,MP4Splitter 0-no, 1-yes 45 | // VIDEO_DELAY int MP4Splitter 46 | // PALETTE bin MP4Splitter 47 | // VIDEO_COLOR_SPACE bin MatroskaSplitter 48 | // HDR_MASTERING_METADATA bin MatroskaSplitter 49 | // HDR_CONTENT_LIGHT_LEVEL bin MatroskaSplitter 50 | 51 | interface __declspec(uuid("37CBDF10-D65E-4E5A-8F37-40E0C8EA1695")) IExFilterConfig : public IUnknown 52 | { 53 | // The memory for strings and binary data is allocated by the callee 54 | // by using LocalAlloc. It is the caller's responsibility to release the 55 | // memory by calling LocalFree. 56 | STDMETHOD(Flt_GetBool )(LPCSTR field, bool *value) PURE; 57 | STDMETHOD(Flt_GetInt )(LPCSTR field, int *value) PURE; 58 | STDMETHOD(Flt_GetInt64 )(LPCSTR field, __int64 *value) PURE; 59 | STDMETHOD(Flt_GetDouble)(LPCSTR field, double *value) PURE; 60 | STDMETHOD(Flt_GetString)(LPCSTR field, LPWSTR *value, unsigned *chars) PURE; 61 | STDMETHOD(Flt_GetBin )(LPCSTR field, LPVOID *value, unsigned *size ) PURE; 62 | 63 | STDMETHOD(Flt_SetBool )(LPCSTR field, bool value) PURE; 64 | STDMETHOD(Flt_SetInt )(LPCSTR field, int value) PURE; 65 | STDMETHOD(Flt_SetInt64 )(LPCSTR field, __int64 value) PURE; 66 | STDMETHOD(Flt_SetDouble)(LPCSTR field, double value) PURE; 67 | STDMETHOD(Flt_SetString)(LPCSTR field, LPWSTR value, int chars) PURE; 68 | STDMETHOD(Flt_SetBin )(LPCSTR field, LPVOID value, int size ) PURE; 69 | }; 70 | // available settings: 71 | // name type filter mode valid values 72 | // stereodownmix bool MpaDecFilter set true/false 73 | // queueDuration int BaseSplitter set/get 100...15000 milliseconds 74 | // networkTimeout int BaseSplitter set/get 2000...20000 milliseconds (reserved) 75 | // version int64 MpcVideoRenderer get 0.3.3.886 or newer 76 | // statsEnable bool MpcVideoRenderer set/get true/false 77 | // cmd_redraw bool MpcVideoRenderer set true 78 | // playbackState int MpcVideoRenderer get 0-State_Stopped, 1-State_Paused, 2-State_Running 79 | // rotation int MpcVideoRenderer get 0, 90, 180, 270 (reserved) 80 | -------------------------------------------------------------------------------- /Include/FilterInterfacesImpl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2017-2024 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "FilterInterfaces.h" 24 | 25 | class CExFilterInfoImpl : public IExFilterInfo 26 | { 27 | STDMETHODIMP GetPropertyInt (LPCSTR field, int *value) { return E_NOTIMPL; }; 28 | STDMETHODIMP GetPropertyString(LPCSTR field, LPWSTR *value, unsigned *chars) { return E_NOTIMPL; }; 29 | STDMETHODIMP GetPropertyBin (LPCSTR field, LPVOID *value, unsigned *size ) { return E_NOTIMPL; }; 30 | }; 31 | 32 | class CExFilterConfigImpl : public IExFilterConfig 33 | { 34 | STDMETHODIMP Flt_GetBool (LPCSTR field, bool *value) { return E_NOTIMPL; }; 35 | STDMETHODIMP Flt_GetInt (LPCSTR field, int *value) { return E_NOTIMPL; }; 36 | STDMETHODIMP Flt_GetInt64 (LPCSTR field, __int64 *value) { return E_NOTIMPL; }; 37 | STDMETHODIMP Flt_GetDouble(LPCSTR field, double *value) { return E_NOTIMPL; }; 38 | STDMETHODIMP Flt_GetString(LPCSTR field, LPWSTR *value, unsigned *chars) { return E_NOTIMPL; }; 39 | STDMETHODIMP Flt_GetBin (LPCSTR field, LPVOID *value, unsigned *size ) { return E_NOTIMPL; }; 40 | 41 | STDMETHODIMP Flt_SetBool (LPCSTR field, bool value) { return E_NOTIMPL; }; 42 | STDMETHODIMP Flt_SetInt (LPCSTR field, int value) { return E_NOTIMPL; }; 43 | STDMETHODIMP Flt_SetInt64 (LPCSTR field, __int64 value) { return E_NOTIMPL; }; 44 | STDMETHODIMP Flt_SetDouble(LPCSTR field, double value) { return E_NOTIMPL; }; 45 | STDMETHODIMP Flt_SetString(LPCSTR field, LPWSTR value, int chars) { return E_NOTIMPL; }; 46 | STDMETHODIMP Flt_SetBin (LPCSTR field, LPVOID value, int size ) { return E_NOTIMPL; }; 47 | }; 48 | -------------------------------------------------------------------------------- /Include/ID3DFullscreenControl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2021 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | // Set and query D3DFullscreen mode. 24 | interface __declspec(uuid("8EA1E899-B77D-4777-9F0E-66421BEA50F8")) 25 | ID3DFullscreenControl : 26 | public IUnknown { 27 | STDMETHOD(SetD3DFullscreen)(bool fEnabled) PURE; 28 | STDMETHOD(GetD3DFullscreen)(bool * pfEnabled) PURE; 29 | }; 30 | -------------------------------------------------------------------------------- /Include/ID3DVideoMemoryConfiguration.h: -------------------------------------------------------------------------------- 1 | // ----------------------------------------------------------------- 2 | // ID3DVideoMemoryConfiguration interface and data structure definitions 3 | // ----------------------------------------------------------------- 4 | #pragma once 5 | 6 | // ----------------------------------------------------------------- 7 | // Control D3D11 Hardware Decoding between decoder and renderer 8 | // ----------------------------------------------------------------- 9 | // A video renderer can implement this interface on its input pin 10 | // to signal to a decoder that its capable of accepting D3D11 texture 11 | // samples directly, without copying to system memory. 12 | // 13 | // The decoder will create the D3D11 device and a mutex to protect it, 14 | // and share it with the renderer in this interface. 15 | // 16 | // To facilitate dynamic switching of the adapter used for decoding, the 17 | // renderer should disconnect the decoder and re-connect it. At that 18 | // point the decoder should query GetD3D11AdapterIndex() again and 19 | // create a new decoder on the new device, as appropriate. 20 | interface __declspec(uuid("2BB66002-46B7-4F13-9036-7053328742BE")) ID3D11DecoderConfiguration : public IUnknown 21 | { 22 | // Set the surface format the decoder is going to send. 23 | // If the renderer is not ready to accept this format, an error will be returned. 24 | virtual HRESULT STDMETHODCALLTYPE ActivateD3D11Decoding(ID3D11Device *pDevice, ID3D11DeviceContext *pContext, HANDLE hMutex, UINT nFlags) = 0; 25 | 26 | // Get the currently preferred D3D11 adapter index (to be used with IDXGIFactory1::EnumAdapters1) 27 | virtual UINT STDMETHODCALLTYPE GetD3D11AdapterIndex() = 0; 28 | }; 29 | 30 | // ----------------------------------------------------------------- 31 | // Media Sample to hold a D3D11 texture 32 | // ----------------------------------------------------------------- 33 | // D3D11 textures used for decoding are typically array-textures, 34 | // a single ID3D11Texture2D object containing an array of textures 35 | // individually addressable by the ArraySlice index. 36 | // 37 | // The texture lifetime is bound to the media samples lifetime. The 38 | // media sample can only be released when the texture is no longer in 39 | // use, otherwise the texture will be re-used by the decoder. 40 | // 41 | // The texture is AddRef'ed when retrieved through this interface, 42 | // and should be Released when no longer needed. 43 | interface __declspec(uuid("BC8753F5-0AC8-4806-8E5F-A12B2AFE153E")) IMediaSampleD3D11 : public IUnknown 44 | { 45 | // Get the D3D11 texture for the specified view. 46 | // 2D images with only one view always use view 0. For 3D, view 0 specifies the base view, view 1 the extension view. 47 | virtual HRESULT STDMETHODCALLTYPE GetD3D11Texture(int nView, ID3D11Texture2D **ppTexture, UINT *pArraySlice) = 0; 48 | }; 49 | -------------------------------------------------------------------------------- /Include/ISubRender.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2003-2006 Gabest 3 | * (C) 2006-2016 see Authors.txt 4 | * 5 | * This file is part of MPC-BE. 6 | * 7 | * MPC-BE is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * MPC-BE is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | interface IDirect3DDevice9; 28 | 29 | DECLARE_INTERFACE_IID_(ISubRenderCallback, IUnknown, "CD6D2AA5-20D3-4ebe-A8A9-34D3B00CC253") 30 | { 31 | // NULL means release current device, textures and other resources 32 | STDMETHOD(SetDevice)(IDirect3DDevice9* dev) PURE; 33 | 34 | // destination video rectangle, will be inside (0, 0)-(width, height) 35 | // width,height is the size of the entire output window 36 | STDMETHOD(Render)(REFERENCE_TIME rtStart, 37 | int left, int top, int right, int bottom, 38 | int width, int height) PURE; 39 | }; 40 | 41 | DECLARE_INTERFACE_IID_(ISubRenderCallback2, ISubRenderCallback, "E602585E-C05A-4828-AC69-AF92997F2E0C") 42 | { 43 | STDMETHOD(RenderEx)(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, 44 | REFERENCE_TIME avgTimePerFrame, 45 | int left, int top, int right, int bottom, 46 | int width, int height) PURE; 47 | }; 48 | 49 | DECLARE_INTERFACE_IID_(ISubRenderCallback3, ISubRenderCallback2, "BAC4273A-3EAD-47F5-9710-8488E52AC618") 50 | { 51 | STDMETHOD(RenderEx2)(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, 52 | REFERENCE_TIME avgTimePerFrame, RECT croppedVideoRect, 53 | RECT originalVideoRect, RECT viewportRect, 54 | const double videoStretchFactor = 1.0) PURE; 55 | }; 56 | 57 | DECLARE_INTERFACE_IID_(ISubRenderCallback4, ISubRenderCallback3, "C89CF1D4-29C5-4A96-8AAC-528EC6F7AF1E") 58 | { 59 | STDMETHOD(RenderEx3)(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, 60 | REFERENCE_TIME avgTimePerFrame, RECT croppedVideoRect, 61 | RECT originalVideoRect, RECT viewportRect, 62 | const double videoStretchFactor = 1.0, 63 | int xOffsetInPixels = 0, DWORD flags = 0) PURE; 64 | }; 65 | 66 | DECLARE_INTERFACE_IID_(ISubRender, IUnknown, "9CC7F9F7-3ED1-493c-AF65-527EA1D9947F") 67 | { 68 | STDMETHOD(SetCallback)(ISubRenderCallback* cb) PURE; 69 | }; 70 | -------------------------------------------------------------------------------- /Include/ISubRender11.h: -------------------------------------------------------------------------------- 1 | // EXPERIMENTAL! 2 | 3 | /* 4 | * (C) 2022 see Authors.txt 5 | * 6 | * This file is part of MPC-BE. 7 | * 8 | * MPC-BE is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * MPC-BE is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | #pragma once 24 | 25 | #include 26 | #include 27 | 28 | interface ID3D11DeviceContext1; 29 | 30 | DECLARE_INTERFACE_IID_(ISubRender11Callback, IUnknown, "1B430F17-4CB2-4C6B-A850-1847F9677C75") 31 | { 32 | // NULL means release current device, textures and other resources 33 | STDMETHOD(SetDevice11)(ID3D11Device* dev) PURE; 34 | 35 | // destination video rectangle, will be inside (0, 0)-(width, height) 36 | // width,height is the size of the entire output window 37 | STDMETHOD(Render11)(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, 38 | REFERENCE_TIME avgTimePerFrame, RECT croppedVideoRect, 39 | RECT originalVideoRect, RECT viewportRect, 40 | const double videoStretchFactor = 1.0, 41 | int xOffsetInPixels = 0, DWORD flags = 0) PURE; 42 | }; 43 | 44 | DECLARE_INTERFACE_IID_(ISubRender11, IUnknown, "524FA4AC-35CF-402B-9015-300FBC432563") 45 | { 46 | STDMETHOD(SetCallback11)(ISubRender11Callback* cb) PURE; 47 | }; 48 | -------------------------------------------------------------------------------- /Include/Version.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../revision.h" 4 | 5 | #ifndef REV_DATE 6 | #define REV_DATE 0 7 | #endif 8 | 9 | #ifndef REV_HASH 10 | #define REV_HASH 0 11 | #endif 12 | 13 | #ifndef REV_NUM 14 | #define REV_NUM 0 15 | #endif 16 | 17 | #ifndef REV_BRANCH 18 | #define REV_BRANCH LOCAL 19 | #endif 20 | 21 | #define DO_MAKE_STR(x) #x 22 | #define MAKE_STR(x) DO_MAKE_STR(x) 23 | 24 | #define VER_RELEASE 0 25 | 26 | #define VER_MAJOR 0 27 | #define VER_MINOR 9 28 | #define VER_BUILD 8 29 | 30 | #define VERSION_NUM VER_MAJOR,VER_MINOR,VER_BUILD,REV_NUM 31 | #define VERSION_STR MAKE_STR(VER_MAJOR) "." MAKE_STR(VER_MINOR) "." MAKE_STR(VER_BUILD) "." MAKE_STR(REV_NUM) 32 | 33 | #define BRANCH_STR MAKE_STR(REV_BRANCH) 34 | -------------------------------------------------------------------------------- /MpcVideoRenderer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.8.34525.116 5 | MinimumVisualStudioVersion = 15.0.27130.2036 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MpcVideoRenderer", "Source\MpcVideoRenderer.vcxproj", "{C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F} = {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F} 9 | EndProjectSection 10 | EndProject 11 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Include", "Include", "{C7CAE27C-03BC-45F2-BF8E-DEE05DBF37B8}" 12 | ProjectSection(SolutionItems) = preProject 13 | Include\FilterInterfaces.h = Include\FilterInterfaces.h 14 | Include\FilterInterfacesImpl.h = Include\FilterInterfacesImpl.h 15 | Include\ID3DFullscreenControl.h = Include\ID3DFullscreenControl.h 16 | Include\ID3DVideoMemoryConfiguration.h = Include\ID3DVideoMemoryConfiguration.h 17 | Include\IMediaSideData.h = Include\IMediaSideData.h 18 | Include\ISubRender.h = Include\ISubRender.h 19 | Include\ISubRender11.h = Include\ISubRender11.h 20 | Include\SubRenderIntf.h = Include\SubRenderIntf.h 21 | Include\Version.h = Include\Version.h 22 | EndProjectSection 23 | EndProject 24 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Shaders", "Shaders\Shaders.vcxproj", "{3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}" 25 | EndProject 26 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BaseClasses", "external\BaseClasses.vcxproj", "{E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}" 27 | EndProject 28 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minhook", "external\minhook.vcxproj", "{303B855A-137D-45E9-AF6D-B7241C6E66D6}" 29 | EndProject 30 | Global 31 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 32 | Debug|x64 = Debug|x64 33 | Debug|x86 = Debug|x86 34 | Release|x64 = Release|x64 35 | Release|x86 = Release|x86 36 | EndGlobalSection 37 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 38 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Debug|x64.ActiveCfg = Debug|x64 39 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Debug|x64.Build.0 = Debug|x64 40 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Debug|x86.ActiveCfg = Debug|Win32 41 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Debug|x86.Build.0 = Debug|Win32 42 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Release|x64.ActiveCfg = Release|x64 43 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Release|x64.Build.0 = Release|x64 44 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Release|x86.ActiveCfg = Release|Win32 45 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Release|x86.Build.0 = Release|Win32 46 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Debug|x64.ActiveCfg = Debug|x64 47 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Debug|x64.Build.0 = Debug|x64 48 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Debug|x86.ActiveCfg = Debug|Win32 49 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Debug|x86.Build.0 = Debug|Win32 50 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Release|x64.ActiveCfg = Release|x64 51 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Release|x64.Build.0 = Release|x64 52 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Release|x86.ActiveCfg = Release|Win32 53 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Release|x86.Build.0 = Release|Win32 54 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.ActiveCfg = Debug|x64 55 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.Build.0 = Debug|x64 56 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x86.ActiveCfg = Debug|Win32 57 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x86.Build.0 = Debug|Win32 58 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.ActiveCfg = Release|x64 59 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.Build.0 = Release|x64 60 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x86.ActiveCfg = Release|Win32 61 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x86.Build.0 = Release|Win32 62 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Debug|x64.ActiveCfg = Debug|x64 63 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Debug|x64.Build.0 = Debug|x64 64 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Debug|x86.ActiveCfg = Debug|Win32 65 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Debug|x86.Build.0 = Debug|Win32 66 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Release|x64.ActiveCfg = Release|x64 67 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Release|x64.Build.0 = Release|x64 68 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Release|x86.ActiveCfg = Release|Win32 69 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Release|x86.Build.0 = Release|Win32 70 | EndGlobalSection 71 | GlobalSection(SolutionProperties) = preSolution 72 | HideSolutionNode = FALSE 73 | EndGlobalSection 74 | GlobalSection(ExtensibilityGlobals) = postSolution 75 | SolutionGuid = {5D7781ED-53B1-4197-9C68-D2EDD94EC59B} 76 | EndGlobalSection 77 | EndGlobal 78 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # MPC Video Renderer 2 | 3 | MPC Video Renderer is a free and open-source video renderer for DirectShow. The renderer can potentially work with any DirectShow player, but full support is available only in the MPC-BE. Recommended MPC-BE 1.8.2.136 or newer. 4 | 5 | ## Key features 6 | 7 | * Can work with DXVA2 and Direct3D 11 hardware decoder. 8 | * DVXA2 and Direct3D11 Video Processor with hardware de-interlacing for NV12, YUY2, P010 formats. 9 | * Shader video processor for various YUV, RGB and grayscale formats. 10 | * Various frame resizing algorithms, including Super Resolution. 11 | * Subtitle and OSD display. 12 | * Rotation and flip of the video frame. 13 | * Dithering when the final color depth is reduced from 10/16 bits to 8 bits. 14 | * HDR video support (HDR10, HLG and partially Dolby Vision). 15 | * Automatic HDR to SDR conversion. 16 | * Transferring HDR10 data to the display. 17 | 18 | ## Minimum system requirements 19 | 20 | * An SSE2-capable CPU 21 | * Windows 7¹ or newer 22 | * DirectX 9.0c video card 23 | 24 | ¹For Windows 7, you must have D3DCompiler_47.dll file. It can be installed via update KB4019990. 25 | 26 | ## Recommended system requirements 27 | 28 | * An SSE2-capable CPU 29 | * Windows 10 or newer 30 | * DirectX 10/11 video card 31 | 32 | ## License 33 | 34 | MPC Video Renderer's code is licensed under [GPL v3]. 35 | 36 | ## Links 37 | 38 | [Nightly builds](https://github.com/Aleksoid1978/VideoRenderer/wiki/Nightly-builds) 39 | 40 | [Topic in MPC-BE forum (Russian)](https://mpc-be.org/forum/index.php?topic=381) 41 | 42 | [MPC-BE](https://github.com/Aleksoid1978/MPC-BE) 43 | 44 | ## Donate 45 | 46 | 47 | -------------------------------------------------------------------------------- /Shaders/convert/colorspace_gamut_conversion.hlsl: -------------------------------------------------------------------------------- 1 | // using code from zimg - https://github.com/sekrit-twc/zimg 2 | 3 | #pragma warning(disable: 4122) // disable warning X4122: sum of ... cannot be represented accurately in double precision. 4 | 5 | static const float REC_709_PRIMARIES[3][2] = { { 0.640, 0.330 }, { 0.300, 0.600 }, { 0.150, 0.060 } }; 6 | static const float REC_2020_PRIMARIES[3][2] = { { 0.708, 0.292 }, { 0.170, 0.797 }, { 0.131, 0.046 } }; 7 | 8 | static const float ILLUMINANT_D65[2] = { 0.3127, 0.3290 }; 9 | 10 | const float det2(const float a00, const float a01, const float a10, const float a11) 11 | { 12 | return a00 * a11 - a01 * a10; 13 | } 14 | 15 | const float determinant(const float3x3 m) 16 | { 17 | float det = 0; 18 | 19 | det += m[0][0] * det2(m[1][1], m[1][2], m[2][1], m[2][2]); 20 | det -= m[0][1] * det2(m[1][0], m[1][2], m[2][0], m[2][2]); 21 | det += m[0][2] * det2(m[1][0], m[1][1], m[2][0], m[2][1]); 22 | 23 | return det; 24 | } 25 | 26 | const float3x3 inverse(const float3x3 m) 27 | { 28 | float3x3 ret; 29 | const float det = determinant(m); 30 | 31 | ret[0][0] = det2(m[1][1], m[1][2], m[2][1], m[2][2]) / det; 32 | ret[0][1] = det2(m[0][2], m[0][1], m[2][2], m[2][1]) / det; 33 | ret[0][2] = det2(m[0][1], m[0][2], m[1][1], m[1][2]) / det; 34 | ret[1][0] = det2(m[1][2], m[1][0], m[2][2], m[2][0]) / det; 35 | ret[1][1] = det2(m[0][0], m[0][2], m[2][0], m[2][2]) / det; 36 | ret[1][2] = det2(m[0][2], m[0][0], m[1][2], m[1][0]) / det; 37 | ret[2][0] = det2(m[1][0], m[1][1], m[2][0], m[2][1]) / det; 38 | ret[2][1] = det2(m[0][1], m[0][0], m[2][1], m[2][0]) / det; 39 | ret[2][2] = det2(m[0][0], m[0][1], m[1][0], m[1][1]) / det; 40 | 41 | return ret; 42 | } 43 | 44 | const float3 xy_to_xyz(const float x, const float y) 45 | { 46 | float3 ret; 47 | 48 | ret[0] = x / y; 49 | ret[1] = 1.0; 50 | ret[2] = (1.0 - x - y) / y; 51 | 52 | return ret; 53 | } 54 | 55 | const float3 get_d65_xyz() 56 | { 57 | return xy_to_xyz(ILLUMINANT_D65[0], ILLUMINANT_D65[1]); 58 | } 59 | 60 | const float3x3 get_primaries_xyz(const float primaries_xy[3][2]) 61 | { 62 | // Columns: R G B 63 | // Rows: X Y Z 64 | float3x3 ret; 65 | 66 | ret[0] = xy_to_xyz(primaries_xy[0][0], primaries_xy[0][1]); 67 | ret[1] = xy_to_xyz(primaries_xy[1][0], primaries_xy[1][1]); 68 | ret[2] = xy_to_xyz(primaries_xy[2][0], primaries_xy[2][1]); 69 | 70 | return transpose(ret); 71 | } 72 | 73 | const float3x3 gamut_rgb_to_xyz_matrix(const float primaries_xy[3][2]) 74 | { 75 | const float3x3 xyz_matrix = get_primaries_xyz(primaries_xy); 76 | const float3 white_xyz = get_d65_xyz(); 77 | 78 | const float3 s = mul(inverse(xyz_matrix), white_xyz); 79 | const float3x3 m = { xyz_matrix[0] * s, xyz_matrix[1] * s, xyz_matrix[2] * s }; 80 | 81 | return m; 82 | } 83 | 84 | static const float3x3 gamut_xyz_color_matrix_2020 = gamut_rgb_to_xyz_matrix(REC_2020_PRIMARIES); 85 | static const float3x3 gamut_xyz_color_matrix_709 = gamut_rgb_to_xyz_matrix(REC_709_PRIMARIES); 86 | static const float3x3 convert_matrix_2020_to_709 = mul(inverse(gamut_xyz_color_matrix_709), gamut_xyz_color_matrix_2020); 87 | 88 | float3 Colorspace_Gamut_Conversion_2020_to_709(const float3 rgb) 89 | { 90 | return mul(convert_matrix_2020_to_709, rgb); 91 | } 92 | -------------------------------------------------------------------------------- /Shaders/convert/conv_matrix.hlsl: -------------------------------------------------------------------------------- 1 | static float4x4 rgb_ycbcr709 = { 2 | 0.2126, 0.7152, 0.0722, 0.0, 3 | -0.114572, -0.385428, 0.5, 0.0, 4 | 0.5, -0.454153, -0.045847, 0.0, 5 | 0.0, 0.0, 0.0, 0.0 6 | }; 7 | 8 | static float4x4 ycbcr2020nc_rgb = { 9 | 1.0, 0.0, 1.4746, 0.0, 10 | 1.0, -0.164553, -0.571353, 0.0, 11 | 1.0, 1.8814, 0.0, 0.0, 12 | 0.0, 0.0, 0.0, 0.0 13 | }; 14 | 15 | static float4x4 ycgco_rgb = { 16 | 1.0, -1.0, 1.0, 0.0, 17 | 1.0, 1.0, 0.0, 0.0, 18 | 1.0, -1.0, -1.0, 0.0, 19 | 0.0, 0.0, 0.0, 0.0 20 | }; 21 | -------------------------------------------------------------------------------- /Shaders/convert/hdr_tone_mapping.hlsl: -------------------------------------------------------------------------------- 1 | inline float3 hable(float3 x) 2 | { 3 | const float A = 0.15, B = 0.50, C = 0.10, D = 0.20, E = 0.02, F = 0.30; 4 | 5 | return ((x * (A * x + (C * B)) + (D * E)) / (x * (A * x + B) + (D * F))) - E / F; 6 | } 7 | 8 | float3 ToneMappingHable(const float3 rgb) 9 | { 10 | static const float3 HABLE_DIV = hable(4.8); 11 | 12 | return hable(rgb) / HABLE_DIV; 13 | } 14 | -------------------------------------------------------------------------------- /Shaders/convert/hlg.hlsl: -------------------------------------------------------------------------------- 1 | inline float3 inverse_HLG(float3 rgb) 2 | { 3 | const float B67_a = 0.17883277; 4 | const float B67_b = 0.28466892; 5 | const float B67_c = 0.55991073; 6 | const float B67_inv_r2 = 4.0; 7 | rgb = (rgb <= 0.5) 8 | ? rgb * rgb * B67_inv_r2 9 | : exp((rgb - B67_c) / B67_a) + B67_b; 10 | return rgb; 11 | } 12 | 13 | inline float3 HLGtoLinear(float3 rgb) 14 | { 15 | rgb = inverse_HLG(rgb); 16 | float3 ootf_2020 = float3(0.2627, 0.6780, 0.0593); 17 | float ootf_ys = 2000.0f * dot(ootf_2020, rgb); 18 | rgb *= pow(ootf_ys, 0.2f); 19 | return rgb; 20 | } 21 | -------------------------------------------------------------------------------- /Shaders/convert/st2084.hlsl: -------------------------------------------------------------------------------- 1 | static const float ST2084_m1 = 2610.0f / (4096.0f * 4.0f); 2 | static const float ST2084_m2 = (2523.0f / 4096.0f) * 128.0f; 3 | static const float ST2084_c1 = 3424.0f / 4096.0f; 4 | static const float ST2084_c2 = (2413.0f / 4096.0f) * 32.0f; 5 | static const float ST2084_c3 = (2392.0f / 4096.0f) * 32.0f; 6 | 7 | #pragma warning(disable: 3571) 8 | 9 | inline float4 ST2084ToLinear(float4 rgb, float factor) 10 | { 11 | rgb = pow(rgb, 1.0 / ST2084_m2); 12 | rgb = max(rgb - ST2084_c1, 0.0) / (ST2084_c2 - ST2084_c3 * rgb); 13 | rgb = pow(rgb, 1.0 / ST2084_m1); 14 | rgb *= factor; 15 | return rgb; 16 | } 17 | 18 | inline float4 LinearToST2084(float4 rgb, float divider) 19 | { 20 | rgb /= divider; 21 | rgb = pow(rgb, ST2084_m1); 22 | rgb = (ST2084_c1 + ST2084_c2 * rgb) / (1.0f + ST2084_c3 * rgb); 23 | rgb = pow(rgb, ST2084_m2); 24 | return rgb; 25 | } 26 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_TEST.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D tex : register(t0); 2 | SamplerState samp : register(s0); 3 | 4 | struct PS_INPUT 5 | { 6 | float4 Pos : SV_POSITION; 7 | float2 Tex : TEXCOORD; 8 | }; 9 | 10 | float4 main(PS_INPUT input) : SV_Target 11 | { 12 | float4 pixel = tex.Sample(samp, input.Tex); 13 | 14 | // write test code here 15 | 16 | return pixel; 17 | } 18 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_convert_biplanar.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D texY : register(t0); 2 | Texture2D texUV : register(t1); 3 | SamplerState samp : register(s0); 4 | SamplerState sampL : register(s1); 5 | 6 | cbuffer PS_COLOR_TRANSFORM : register(b0) 7 | { 8 | float3 cm_r; 9 | float3 cm_g; 10 | float3 cm_b; 11 | float3 cm_c; 12 | // NB: sizeof(float3) == sizeof(float4) 13 | }; 14 | 15 | struct PS_INPUT 16 | { 17 | float4 Pos : SV_POSITION; 18 | float2 Tex : TEXCOORD; 19 | }; 20 | 21 | float4 main(PS_INPUT input) : SV_Target 22 | { 23 | float colorY = texY.Sample(samp, input.Tex).r; 24 | float2 colorUV = texUV.Sample(sampL, input.Tex).rg; 25 | 26 | float4 color = float4(colorY, colorUV, 0); 27 | 28 | color.rgb = float3(mul(cm_r, color.rgb), mul(cm_g, color.rgb), mul(cm_b, color.rgb)) + cm_c; 29 | 30 | return color; 31 | } 32 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_convert_bitmap_to_pq.hlsl: -------------------------------------------------------------------------------- 1 | #ifndef SDR_PEAK_LUM 2 | #define SDR_PEAK_LUM 100 3 | #endif 4 | 5 | Texture2D tex : register(t0); 6 | SamplerState samp : register(s0); 7 | 8 | struct PS_INPUT 9 | { 10 | float4 Pos : SV_POSITION; 11 | float2 Tex : TEXCOORD; 12 | }; 13 | 14 | #pragma warning(disable: 3571) // fix warning X3571 in pow(). 15 | 16 | // https://github.com/thexai/xbmc/blob/master/system/shaders/guishader_common.hlsl 17 | inline float3 transferPQ(float3 x) 18 | { 19 | static const float ST2084_m1 = 2610.0f / (4096.0f * 4.0f); 20 | static const float ST2084_m2 = (2523.0f / 4096.0f) * 128.0f; 21 | static const float ST2084_c1 = 3424.0f / 4096.0f; 22 | static const float ST2084_c2 = (2413.0f / 4096.0f) * 32.0f; 23 | static const float ST2084_c3 = (2392.0f / 4096.0f) * 32.0f; 24 | static const float SDR_peak_lum = SDR_PEAK_LUM; 25 | static const float3x3 matx = { 26 | 0.627402, 0.329292, 0.043306, 27 | 0.069095, 0.919544, 0.011360, 28 | 0.016394, 0.088028, 0.895578 29 | }; 30 | // REC.709 to linear 31 | x = pow(x, 1.0f / 0.45f); 32 | // REC.709 to BT.2020 33 | x = mul(matx, x); 34 | // linear to PQ 35 | x = pow(x / SDR_peak_lum, ST2084_m1); 36 | x = (ST2084_c1 + ST2084_c2 * x) / (1.0f + ST2084_c3 * x); 37 | x = pow(x, ST2084_m2); 38 | return x; 39 | } 40 | 41 | float4 main(PS_INPUT input) : SV_Target 42 | { 43 | float4 color = tex.Sample(samp, input.Tex); // original pixel 44 | 45 | return float4(transferPQ(color.rgb), color.a); 46 | } 47 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_convert_color.hlsl: -------------------------------------------------------------------------------- 1 | #ifndef C_YUY2 2 | #define C_YUY2 0 3 | #endif 4 | 5 | Texture2D tex : register(t0); 6 | SamplerState samp : register(s0); 7 | 8 | cbuffer PS_COLOR_TRANSFORM : register(b0) 9 | { 10 | float3 cm_r; 11 | float3 cm_g; 12 | float3 cm_b; 13 | float3 cm_c; 14 | // NB: sizeof(float3) == sizeof(float4) 15 | }; 16 | #if C_YUY2 17 | cbuffer PS_TEX_DIMENSIONS : register(b4) 18 | { 19 | float width; 20 | float height; 21 | float dx; 22 | float dy; 23 | }; 24 | #endif 25 | 26 | struct PS_INPUT 27 | { 28 | float4 Pos : SV_POSITION; 29 | float2 Tex : TEXCOORD; 30 | }; 31 | 32 | float4 main(PS_INPUT input) : SV_Target 33 | { 34 | float4 color = tex.Sample(samp, input.Tex); // original pixel 35 | #if C_YUY2 36 | if (fmod(input.Tex.x*width, 2) < 1.0) { 37 | color = float4(color[0], color[1], color[3], 0); 38 | } else { 39 | #if (C_YUY2 == 1) // nearest neighbor 40 | color = float4(color[2], color[1], color[3], 0); 41 | #elif (C_YUY2 == 2) // linear 42 | float2 chroma0 = color.yw; 43 | float2 chroma1 = tex.Sample(samp, input.Tex + float2(dx, 0)).yw; 44 | float2 chroma = (chroma0 + chroma1) * 0.5; 45 | color = float4(color[2], chroma, 0); 46 | #elif (C_YUY2 == 3) // cubic 47 | float2 chroma0 = tex.Sample(samp, input.Tex + float2(-dx, 0)).yw; 48 | float2 chroma1 = color.yw; 49 | float2 chroma2 = tex.Sample(samp, input.Tex + float2(dx, 0)).yw; 50 | float2 chroma3 = tex.Sample(samp, input.Tex + float2(2*dx, 0)).yw; 51 | float2 chroma = (9 * (chroma1 + chroma2) - (chroma0 + chroma3)) * 0.0625; 52 | color = float4(color[2], chroma, 0); 53 | #endif 54 | } 55 | #endif 56 | 57 | color.rgb = float3(mul(cm_r, color.rgb), mul(cm_g, color.rgb), mul(cm_b, color.rgb)) + cm_c; 58 | 59 | return color; 60 | } 61 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_convert_hlg_to_pq.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D tex : register(t0); 2 | SamplerState samp : register(s0); 3 | 4 | #include "../convert/hlg.hlsl" 5 | #include "../convert/st2084.hlsl" 6 | 7 | struct PS_INPUT 8 | { 9 | float4 Pos : SV_POSITION; 10 | float2 Tex : TEXCOORD; 11 | }; 12 | 13 | float4 main(PS_INPUT input) : SV_Target 14 | { 15 | float4 color = tex.Sample(samp, input.Tex); // original pixel 16 | 17 | color = saturate(color); // use saturate(), because pow() can not take negative values 18 | color.rgb = HLGtoLinear(color.rgb); 19 | color = LinearToST2084(color, 1000.0); 20 | 21 | return color; 22 | } 23 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_convert_planar.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D texY : register(t0); 2 | Texture2D texU : register(t1); 3 | Texture2D texV : register(t2); 4 | SamplerState samp : register(s0); 5 | SamplerState sampL : register(s1); 6 | 7 | cbuffer PS_COLOR_TRANSFORM : register(b0) 8 | { 9 | float3 cm_r; 10 | float3 cm_g; 11 | float3 cm_b; 12 | float3 cm_c; 13 | // NB: sizeof(float3) == sizeof(float4) 14 | }; 15 | 16 | struct PS_INPUT 17 | { 18 | float4 Pos : SV_POSITION; 19 | float2 Tex : TEXCOORD; 20 | }; 21 | 22 | float4 main(PS_INPUT input) : SV_Target 23 | { 24 | float colorY = texY.Sample(samp, input.Tex).r; 25 | float colorU = texU.Sample(sampL, input.Tex).r; 26 | float colorV = texV.Sample(sampL, input.Tex).r; 27 | 28 | float4 color = float4(colorY, colorU, colorV, 0); 29 | 30 | color.rgb = float3(mul(cm_r, color.rgb), mul(cm_g, color.rgb), mul(cm_b, color.rgb)) + cm_c; 31 | 32 | return color; 33 | } 34 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_convert_planar_yv.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D texY : register(t0); 2 | Texture2D texV : register(t1); 3 | Texture2D texU : register(t2); 4 | SamplerState samp : register(s0); 5 | SamplerState sampL : register(s1); 6 | 7 | cbuffer PS_COLOR_TRANSFORM : register(b0) 8 | { 9 | float3 cm_r; 10 | float3 cm_g; 11 | float3 cm_b; 12 | float3 cm_c; 13 | // NB: sizeof(float3) == sizeof(float4) 14 | }; 15 | 16 | struct PS_INPUT 17 | { 18 | float4 Pos : SV_POSITION; 19 | float2 Tex : TEXCOORD; 20 | }; 21 | 22 | float4 main(PS_INPUT input) : SV_Target 23 | { 24 | float colorY = texY.Sample(samp, input.Tex).r; 25 | float colorU = texU.Sample(sampL, input.Tex).r; 26 | float colorV = texV.Sample(sampL, input.Tex).r; 27 | 28 | float4 color = float4(colorY, colorU, colorV, 0); 29 | 30 | color.rgb = float3(mul(cm_r, color.rgb), mul(cm_g, color.rgb), mul(cm_b, color.rgb)) + cm_c; 31 | 32 | return color; 33 | } 34 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_convert_pq_to_sdr.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D tex : register(t0); 2 | SamplerState samp : register(s0); 3 | 4 | cbuffer PS_PARAMETERS : register(b0) 5 | { 6 | float LuminanceScale; 7 | float param2; 8 | }; 9 | 10 | #include "../convert/conv_matrix.hlsl" 11 | #include "../convert/st2084.hlsl" 12 | #include "../convert/hdr_tone_mapping.hlsl" 13 | #include "../convert/colorspace_gamut_conversion.hlsl" 14 | 15 | struct PS_INPUT 16 | { 17 | float4 Pos : SV_POSITION; 18 | float2 Tex : TEXCOORD; 19 | }; 20 | 21 | float4 main(PS_INPUT input) : SV_Target 22 | { 23 | float4 color = tex.Sample(samp, input.Tex); // original pixel 24 | 25 | // PQ to Linear 26 | color = saturate(color); 27 | color = ST2084ToLinear(color, LuminanceScale); 28 | 29 | color.rgb = ToneMappingHable(color.rgb); 30 | color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb); 31 | 32 | // Linear to sRGB 33 | color = saturate(color); 34 | color = pow(color, 1.0 / 2.2); 35 | 36 | return color; 37 | } 38 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_convolution.hlsl: -------------------------------------------------------------------------------- 1 | #ifndef AXIS 2 | #define AXIS 0 3 | #endif 4 | 5 | #include "../resize/convolution_filters.hlsl" 6 | 7 | Texture2D tex : register(t0); 8 | SamplerState samp : register(s0); 9 | 10 | cbuffer PS_CONSTANTS : register(b0) 11 | { 12 | float2 wh; 13 | float2 dxdy; 14 | float2 scale; 15 | }; 16 | 17 | struct PS_INPUT 18 | { 19 | float4 Pos : SV_POSITION; 20 | float2 Tex : TEXCOORD; 21 | }; 22 | 23 | static const float support = filter_support * scale[AXIS]; 24 | static const float ss = 1.0 / scale[AXIS]; 25 | 26 | #pragma warning(disable: 3595) // disable warning X3595: gradient instruction used in a loop with varying iteration; partial derivatives may have undefined value 27 | 28 | float4 main(PS_INPUT input) : SV_Target 29 | { 30 | float pos = input.Tex[AXIS] * wh[AXIS] + 0.5; 31 | 32 | int low = (int)floor(pos - support); 33 | int high = (int)ceil(pos + support); 34 | 35 | float ww = 0.0; 36 | float4 avg = 0; 37 | 38 | [loop] for (int n = low; n < high; n++) { 39 | float w = filter((n - pos + 0.5) * ss); 40 | ww += w; 41 | #if (AXIS == 0) 42 | avg += w * tex.Sample(samp, float2((n + 0.5) * dxdy.x, input.Tex.y)); 43 | #else 44 | avg += w * tex.Sample(samp, float2(input.Tex.x, (n + 0.5) * dxdy.y)); 45 | #endif 46 | } 47 | avg /= ww; 48 | 49 | return avg; 50 | } 51 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_final_pass.hlsl: -------------------------------------------------------------------------------- 1 | 2 | #ifndef QUANTIZATION 3 | // 255 or 1023 (Maximum quantized integer value) 4 | #define QUANTIZATION 255 5 | #endif 6 | 7 | Texture2D tex : register(t0); 8 | Texture2D texDither : register(t1); 9 | SamplerState samp : register(s0); 10 | SamplerState sampDither : register(s1); 11 | 12 | cbuffer PS_CONSTANTS : register(b0) 13 | { 14 | float2 ditherCoordScale; 15 | }; 16 | 17 | struct PS_INPUT 18 | { 19 | float4 Pos : SV_POSITION; 20 | float2 Tex : TEXCOORD; 21 | }; 22 | 23 | float4 main(PS_INPUT input) : SV_Target 24 | { 25 | float4 pixel = tex.Sample(samp, input.Tex); 26 | 27 | float4 ditherValue = texDither.Sample(sampDither, input.Tex * ditherCoordScale); 28 | pixel = floor(pixel * QUANTIZATION + ditherValue) / QUANTIZATION; 29 | 30 | return pixel; 31 | }; 32 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_fix_bt2020.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D tex : register(t0); 2 | SamplerState samp : register(s0); 3 | 4 | #include "../convert/conv_matrix.hlsl" 5 | #include "../convert/colorspace_gamut_conversion.hlsl" 6 | 7 | static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709); 8 | 9 | struct PS_INPUT 10 | { 11 | float4 Pos : SV_POSITION; 12 | float2 Tex : TEXCOORD; 13 | }; 14 | 15 | float4 main(PS_INPUT input) : SV_Target 16 | { 17 | float4 color = tex.Sample(samp, input.Tex); 18 | 19 | // Fix incorrect (unsupported) conversion from YCbCr BT.2020 to RGB in D3D11 VP 20 | color = mul(fix_bt2020_matrix, color); 21 | 22 | // sRGB to Linear 23 | color = saturate(color); 24 | color = pow(color, 2.2); 25 | 26 | color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb); 27 | 28 | // Linear to sRGB 29 | color = saturate(color); 30 | color = pow(color, 1.0 / 2.2); 31 | 32 | return color; 33 | } 34 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_fix_ycgco.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D tex : register(t0); 2 | SamplerState samp : register(s0); 3 | 4 | #include "../convert/conv_matrix.hlsl" 5 | 6 | static const float4x4 fix_ycgco_matrix = mul(ycgco_rgb, rgb_ycbcr709); 7 | 8 | struct PS_INPUT 9 | { 10 | float4 Pos : SV_POSITION; 11 | float2 Tex : TEXCOORD; 12 | }; 13 | 14 | float4 main(PS_INPUT input) : SV_Target 15 | { 16 | float4 pixel = tex.Sample(samp, input.Tex); // original pixel 17 | 18 | // Fix incorrect (unsupported) conversion from YCgCo to RGB in D3D11 VP 19 | pixel = mul(fix_ycgco_matrix, pixel); 20 | 21 | return pixel; 22 | } 23 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_fixconvert_hlg_to_sdr.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D tex : register(t0); 2 | SamplerState samp : register(s0); 3 | 4 | #include "../convert/conv_matrix.hlsl" 5 | #include "../convert/hlg.hlsl" 6 | #include "../convert/st2084.hlsl" 7 | #include "../convert/hdr_tone_mapping.hlsl" 8 | #include "../convert/colorspace_gamut_conversion.hlsl" 9 | 10 | static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709); 11 | 12 | cbuffer PS_PARAMETERS : register(b0) 13 | { 14 | float LuminanceScale; 15 | float param2; 16 | }; 17 | 18 | struct PS_INPUT 19 | { 20 | float4 Pos : SV_POSITION; 21 | float2 Tex : TEXCOORD; 22 | }; 23 | 24 | float4 main(PS_INPUT input) : SV_Target 25 | { 26 | float4 color = tex.Sample(samp, input.Tex); // original pixel 27 | 28 | // Fix incorrect (unsupported) conversion from YCbCr BT.2020 to RGB in D3D11 VP 29 | color = mul(fix_bt2020_matrix, color); 30 | 31 | // HLG to PQ 32 | color = saturate(color); 33 | color.rgb = HLGtoLinear(color.rgb); 34 | color = LinearToST2084(color, 1000.0); 35 | 36 | // PQ to Linear 37 | color = saturate(color); 38 | color = ST2084ToLinear(color, LuminanceScale); 39 | 40 | color.rgb = ToneMappingHable(color.rgb); 41 | color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb); 42 | 43 | // Linear to sRGB 44 | color = saturate(color); 45 | color = pow(color, 1.0 / 2.2); 46 | 47 | return color; 48 | } 49 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_fixconvert_pq_to_sdr.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D tex : register(t0); 2 | SamplerState samp : register(s0); 3 | 4 | cbuffer PS_PARAMETERS : register(b0) 5 | { 6 | float LuminanceScale; 7 | float param2; 8 | }; 9 | 10 | #include "../convert/conv_matrix.hlsl" 11 | #include "../convert/st2084.hlsl" 12 | #include "../convert/hdr_tone_mapping.hlsl" 13 | #include "../convert/colorspace_gamut_conversion.hlsl" 14 | 15 | static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709); 16 | 17 | struct PS_INPUT 18 | { 19 | float4 Pos : SV_POSITION; 20 | float2 Tex : TEXCOORD; 21 | }; 22 | 23 | float4 main(PS_INPUT input) : SV_Target 24 | { 25 | float4 color = tex.Sample(samp, input.Tex); // original pixel 26 | 27 | // Fix incorrect (unsupported) conversion from YCbCr BT.2020 to RGB in D3D11 VP 28 | color = mul(fix_bt2020_matrix, color); 29 | 30 | // PQ to Linear 31 | color = saturate(color); 32 | color = ST2084ToLinear(color, LuminanceScale); 33 | 34 | color.rgb = ToneMappingHable(color.rgb); 35 | color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb); 36 | 37 | // Linear to sRGB 38 | color = saturate(color); 39 | color = pow(color, 1.0 / 2.2); 40 | 41 | return color; 42 | } 43 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_font.hlsl: -------------------------------------------------------------------------------- 1 | // pixel shader for D3D11Font 2 | Texture2D shaderTexture; 3 | SamplerState SampleType; 4 | 5 | cbuffer PS_COLOR 6 | { 7 | float4 pixelColor; 8 | }; 9 | 10 | struct PS_INPUT 11 | { 12 | float4 pos : SV_POSITION; 13 | float2 tex : TEXCOORD; 14 | }; 15 | 16 | float4 main(PS_INPUT input) : SV_Target 17 | { 18 | return shaderTexture.Sample(SampleType, input.tex) * pixelColor; 19 | } 20 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_geometry.hlsl: -------------------------------------------------------------------------------- 1 | // pixel shader for D3D11Geometry 2 | struct PS_INPUT 3 | { 4 | float4 position : SV_POSITION; 5 | float4 color : COLOR; 6 | }; 7 | 8 | float4 main(PS_INPUT input) : SV_Target 9 | { 10 | return input.color; 11 | } 12 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_halfoverunder_to_interlace.hlsl: -------------------------------------------------------------------------------- 1 | // convert Half OverUnder to Interlace 2 | 3 | Texture2D tex : register(t0); 4 | SamplerState samp : register(s0); 5 | 6 | cbuffer PS_CONSTANTS : register(b0) 7 | { 8 | float height; 9 | float none; 10 | float dtop; 11 | float dbottom; 12 | }; 13 | 14 | struct PS_INPUT 15 | { 16 | float4 Pos : SV_POSITION; 17 | float2 Tex : TEXCOORD; 18 | }; 19 | 20 | float4 main(PS_INPUT input) : SV_Target 21 | { 22 | float2 pos = input.Tex; 23 | 24 | if (pos.y >= dbottom) { 25 | return float4(0.0, 0.0, 0.0, 1.0); 26 | } 27 | 28 | if (fmod((pos.y - dtop) * height, 2) < 1.0) { 29 | // even 30 | pos.y = (dtop + pos.y) / 2; 31 | } else { 32 | // odd 33 | pos.y = (dbottom + pos.y) / 2; 34 | } 35 | 36 | return tex.Sample(samp, pos); 37 | } 38 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_interpolation_lanczos2.hlsl: -------------------------------------------------------------------------------- 1 | #ifndef AXIS 2 | #define AXIS 0 3 | #endif 4 | 5 | #define PI acos(-1.) 6 | 7 | Texture2D tex : register(t0); 8 | SamplerState samp : register(s0); 9 | 10 | cbuffer PS_CONSTANTS : register(b0) 11 | { 12 | float2 wh; 13 | float2 dxdy; 14 | float2 scale; 15 | }; 16 | 17 | struct PS_INPUT 18 | { 19 | float4 Pos : SV_POSITION; 20 | float2 Tex : TEXCOORD; 21 | }; 22 | 23 | float4 main(PS_INPUT input) : SV_Target 24 | { 25 | float pos = input.Tex[AXIS] * wh[AXIS] - 0.5; 26 | float t = frac(pos); // calculate the difference between the output pixel and the original surrounding two pixels 27 | pos = pos - t; 28 | 29 | #if (AXIS == 0) 30 | float4 Q1 = tex.Sample(samp, float2((pos + 0.5) * dxdy.x, input.Tex.y)); // nearest original pixel to the left 31 | if (t) { 32 | // original pixels 33 | float4 Q0 = tex.Sample(samp, float2((pos - 0.5) * dxdy.x, input.Tex.y)); 34 | float4 Q2 = tex.Sample(samp, float2((pos + 1.5) * dxdy.x, input.Tex.y)); 35 | float4 Q3 = tex.Sample(samp, float2((pos + 2.5) * dxdy.x, input.Tex.y)); 36 | #elif (AXIS == 1) 37 | float4 Q1 = tex.Sample(samp, float2(input.Tex.x, (pos + 0.5) * dxdy.y)); 38 | if (t) { 39 | // original pixels 40 | float4 Q0 = tex.Sample(samp, float2(input.Tex.x, (pos - 0.5) * dxdy.y)); 41 | float4 Q2 = tex.Sample(samp, float2(input.Tex.x, (pos + 1.5) * dxdy.y)); 42 | float4 Q3 = tex.Sample(samp, float2(input.Tex.x, (pos + 2.5) * dxdy.y)); 43 | #else 44 | #error ERROR: incorrect AXIS. 45 | #endif 46 | float4 wset = float3(0., 1., 2.).yxyz + float2(t, -t).xxyy; 47 | float4 w = sin(wset * PI) * sin(wset * PI * .5) / (wset * wset * PI * PI * .5); 48 | 49 | float wc = 1. - dot(1., w); // compensate truncated window factor by bilinear factoring on the two nearest samples 50 | w.y += wc * (1. - t); 51 | w.z += wc * t; 52 | 53 | return w.x * Q0 + w.y * Q1 + w.z * Q2 + w.w * Q3; // interpolation output 54 | } 55 | 56 | return Q1; // case t == 0. is required to return sample Q1, because of a possible division by 0. 57 | } 58 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_interpolation_lanczos3.hlsl: -------------------------------------------------------------------------------- 1 | #ifndef AXIS 2 | #define AXIS 0 3 | #endif 4 | 5 | #define PI acos(-1.) 6 | 7 | Texture2D tex : register(t0); 8 | SamplerState samp : register(s0); 9 | 10 | cbuffer PS_CONSTANTS : register(b0) 11 | { 12 | float2 wh; 13 | float2 dxdy; 14 | float2 scale; 15 | }; 16 | 17 | struct PS_INPUT 18 | { 19 | float4 Pos : SV_POSITION; 20 | float2 Tex : TEXCOORD; 21 | }; 22 | 23 | float4 main(PS_INPUT input) : SV_Target 24 | { 25 | float pos = input.Tex[AXIS] * wh[AXIS] - 0.5; 26 | float t = frac(pos); // calculate the difference between the output pixel and the original surrounding two pixels 27 | pos = pos - t; 28 | 29 | #if (AXIS == 0) 30 | float4 Q2 = tex.Sample(samp, float2((pos + 0.5) * dxdy.x, input.Tex.y)); // nearest original pixel to the left 31 | if (t) { 32 | // original pixels 33 | float4 Q0 = tex.Sample(samp, float2((pos - 1.5) * dxdy.x, input.Tex.y)); 34 | float4 Q1 = tex.Sample(samp, float2((pos - 1.5) * dxdy.x, input.Tex.y)); 35 | float4 Q3 = tex.Sample(samp, float2((pos + 1.5) * dxdy.x, input.Tex.y)); 36 | float4 Q4 = tex.Sample(samp, float2((pos + 2.5) * dxdy.x, input.Tex.y)); 37 | float4 Q5 = tex.Sample(samp, float2((pos + 3.5) * dxdy.x, input.Tex.y)); 38 | #elif (AXIS == 1) 39 | float4 Q2 = tex.Sample(samp, float2(input.Tex.x, (pos + 0.5) * dxdy.y)); 40 | if (t) { 41 | // original pixels 42 | float4 Q0 = tex.Sample(samp, float2(input.Tex.x, (pos - 1.5) * dxdy.y)); 43 | float4 Q1 = tex.Sample(samp, float2(input.Tex.x, (pos - 1.5) * dxdy.y)); 44 | float4 Q3 = tex.Sample(samp, float2(input.Tex.x, (pos + 1.5) * dxdy.y)); 45 | float4 Q4 = tex.Sample(samp, float2(input.Tex.x, (pos + 2.5) * dxdy.y)); 46 | float4 Q5 = tex.Sample(samp, float2(input.Tex.x, (pos + 3.5) * dxdy.y)); 47 | #else 48 | #error ERROR: incorrect AXIS. 49 | #endif 50 | float3 wset0 = float3(2., 1., 0.) * PI + t * PI; 51 | float3 wset1 = float3(1., 2., 3.) * PI - t * PI; 52 | float3 wset0s = wset0 * .5; 53 | float3 wset1s = wset1 * .5; 54 | float3 w0 = sin(wset0) * sin(wset0s) / (wset0 * wset0s); 55 | float3 w1 = sin(wset1) * sin(wset1s) / (wset1 * wset1s); 56 | 57 | float wc = 1. - dot(1., w0 + w1); // compensate truncated window factor by linear factoring on the two nearest samples 58 | w0.z += wc * (1. - t); 59 | w1.x += wc * t; 60 | 61 | return w0.x * Q0 + w0.y * Q1 + w0.z * Q2 + w1.x * Q3 + w1.y * Q4 + w1.z * Q5; // interpolation output 62 | } 63 | 64 | return Q2; // case t == 0. is required to return sample Q2, because of a possible division by 0. 65 | } 66 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_interpolation_spline4.hlsl: -------------------------------------------------------------------------------- 1 | #ifndef AXIS 2 | #define AXIS 0 3 | #endif 4 | 5 | #ifndef METHOD 6 | #define METHOD 1 7 | #endif 8 | 9 | Texture2D tex : register(t0); 10 | SamplerState samp : register(s0); 11 | 12 | cbuffer PS_CONSTANTS : register(b0) 13 | { 14 | float2 wh; 15 | float2 dxdy; 16 | float2 scale; 17 | }; 18 | 19 | struct PS_INPUT 20 | { 21 | float4 Pos : SV_POSITION; 22 | float2 Tex : TEXCOORD; 23 | }; 24 | 25 | float4 main(PS_INPUT input) : SV_Target 26 | { 27 | float pos = input.Tex[AXIS] * wh[AXIS] - 0.5; 28 | float t = frac(pos); // calculate the difference between the output pixel and the original surrounding two pixels 29 | pos = pos - t; 30 | 31 | #if (AXIS == 0) 32 | // original pixels 33 | float4 Q0 = tex.Sample(samp, float2((pos - 0.5) * dxdy.x, input.Tex.y)); 34 | float4 Q1 = tex.Sample(samp, float2((pos + 0.5) * dxdy.x, input.Tex.y)); 35 | float4 Q2 = tex.Sample(samp, float2((pos + 1.5) * dxdy.x, input.Tex.y)); 36 | float4 Q3 = tex.Sample(samp, float2((pos + 2.5) * dxdy.x, input.Tex.y)); 37 | #elif (AXIS == 1) 38 | // original pixels 39 | float4 Q0 = tex.Sample(samp, float2(input.Tex.x, (pos - 0.5) * dxdy.y)); 40 | float4 Q1 = tex.Sample(samp, float2(input.Tex.x, (pos + 0.5) * dxdy.y)); 41 | float4 Q2 = tex.Sample(samp, float2(input.Tex.x, (pos + 1.5) * dxdy.y)); 42 | float4 Q3 = tex.Sample(samp, float2(input.Tex.x, (pos + 2.5) * dxdy.y)); 43 | #else 44 | #error ERROR: incorrect AXIS. 45 | #endif 46 | 47 | // calculate weights 48 | float t2 = t * t; 49 | float t3 = t * t2; 50 | #if (METHOD == 0) // Mitchell-Netravali spline4 51 | float4 w0123 = float4(1., 16., 1., 0.)/18.+float4(-.5, 0., .5, 0.)*t+float4(5., -12., 9., -2.)/6.*t2+float4(-7., 21., -21., 7.)/18.*t3; 52 | #elif (METHOD == 1) // Catmull-Rom spline4 53 | float4 w0123 = float4(-.5, 0., .5, 0.)*t+float4(1., -2.5, 2., -.5)*t2+float4(-.5, 1.5, -1.5, .5)*t3; 54 | w0123.y += 1.; 55 | #else 56 | #error ERROR: incorrect METHOD. 57 | #endif 58 | 59 | return w0123[0] * Q0 + w0123[1] * Q1 + w0123[2] * Q2 + w0123[3] * Q3; // interpolation output 60 | } 61 | -------------------------------------------------------------------------------- /Shaders/d3d11/ps_simple.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D tex : register(t0); 2 | SamplerState samp : register(s0); 3 | 4 | struct PS_INPUT 5 | { 6 | float4 Pos : SV_POSITION; 7 | float2 Tex : TEXCOORD; 8 | }; 9 | 10 | float4 main(PS_INPUT input) : SV_Target 11 | { 12 | return tex.Sample(samp, input.Tex); 13 | } 14 | -------------------------------------------------------------------------------- /Shaders/d3d11/vs_geometry.hlsl: -------------------------------------------------------------------------------- 1 | // vertex shader for D3D11Geometry 2 | struct VS_INPUT 3 | { 4 | float4 position : POSITION; 5 | float4 color : COLOR; 6 | }; 7 | 8 | struct VS_OUTPUT 9 | { 10 | float4 position : SV_POSITION; 11 | float4 color : COLOR; 12 | }; 13 | 14 | VS_OUTPUT main(VS_INPUT input) 15 | { 16 | return input; 17 | } 18 | -------------------------------------------------------------------------------- /Shaders/d3d11/vs_simple.hlsl: -------------------------------------------------------------------------------- 1 | struct VS_INPUT 2 | { 3 | float4 Pos : POSITION; 4 | float2 Tex : TEXCOORD; 5 | }; 6 | 7 | struct VS_OUTPUT 8 | { 9 | float4 Pos : SV_POSITION; 10 | float2 Tex : TEXCOORD; 11 | }; 12 | 13 | VS_OUTPUT main(VS_INPUT input) 14 | { 15 | return input; 16 | } 17 | -------------------------------------------------------------------------------- /Shaders/d3d9/convert_biplanar.hlsl: -------------------------------------------------------------------------------- 1 | sampler sY : register(s0); 2 | sampler sUV : register(s1); 3 | 4 | float4 cm_r : register(c0); 5 | float4 cm_g : register(c1); 6 | float4 cm_b : register(c2); 7 | float3 cm_c : register(c3); 8 | 9 | float4 main(float2 tex : TEXCOORD0) : COLOR 10 | { 11 | float colorY = tex2D(sY, tex).r; 12 | float3 colorUV = tex2D(sUV, tex).rga; // for D3DFMT_G16R16 and D3DFMT_A8L8 variants 13 | 14 | float4 color = float4(colorY, colorUV); 15 | 16 | color.rgb = float3(mul(cm_r, color), mul(cm_g, color), mul(cm_b, color)) + cm_c; 17 | 18 | return color; 19 | } 20 | -------------------------------------------------------------------------------- /Shaders/d3d9/convert_color.hlsl: -------------------------------------------------------------------------------- 1 | #ifndef C_YUY2 2 | #define C_YUY2 0 3 | #endif 4 | 5 | sampler s0 : register(s0); 6 | 7 | float3 cm_r : register(c0); 8 | float3 cm_g : register(c1); 9 | float3 cm_b : register(c2); 10 | float3 cm_c : register(c3); 11 | 12 | #if C_YUY2 13 | float4 p4 : register(c4); 14 | #define width (p4[0]) 15 | #define height (p4[1]) 16 | #define dx (p4[2]) 17 | #define dy (p4[3]) 18 | #endif 19 | 20 | float4 main(float2 tex : TEXCOORD0) : COLOR 21 | { 22 | float4 color = tex2D(s0, tex); // original pixel 23 | 24 | #if C_YUY2 25 | if (fmod(tex.x*width, 2) < 1.0) { 26 | // used D3DFMT_A8R8G8B8 is used because D3DFMT_A8B8G8R8 cannot be used on some video cards 27 | color = float4(color[2], color[1], color[3], 0); 28 | } else { 29 | #if (C_YUY2 == 1) // nearest neighbor 30 | color = float4(color[0], color[1], color[3], 0); 31 | #elif (C_YUY2 == 2) // linear 32 | float2 chroma0 = color.yw; 33 | float2 chroma1 = tex2D(s0, tex + float2(dx, 0)).yw; 34 | float2 chroma = (chroma0 + chroma1) * 0.5; 35 | color = float4(color[0], chroma, 0); 36 | #elif (C_YUY2 == 3) // cubic 37 | float2 chroma0 = tex2D(s0, tex + float2(-dx, 0)).yw; 38 | float2 chroma1 = color.yw; 39 | float2 chroma2 = tex2D(s0, tex + float2(dx, 0)).yw; 40 | float2 chroma3 = tex2D(s0, tex + float2(2*dx, 0)).yw; 41 | float2 chroma = (9 * (chroma1 + chroma2) - (chroma0 + chroma3)) * 0.0625; 42 | color = float4(color[0], chroma, 0); 43 | #endif 44 | } 45 | #endif 46 | 47 | color.rgb = float3(mul(cm_r, color.rgb), mul(cm_g, color.rgb), mul(cm_b, color.rgb)) + cm_c; 48 | 49 | return color; 50 | } 51 | -------------------------------------------------------------------------------- /Shaders/d3d9/convert_planar.hlsl: -------------------------------------------------------------------------------- 1 | sampler sY : register(s0); 2 | sampler sU : register(s1); 3 | sampler sV : register(s2); 4 | 5 | float4 cm_r : register(c0); 6 | float4 cm_g : register(c1); 7 | float4 cm_b : register(c2); 8 | float3 cm_c : register(c3); 9 | 10 | float4 main(float2 tex : TEXCOORD0) : COLOR 11 | { 12 | float colorY = tex2D(sY, tex).r; 13 | float colorU = tex2D(sU, tex).r; 14 | float colorV = tex2D(sV, tex).r; 15 | 16 | float4 color = float4(colorY, colorU, colorV, 0); 17 | 18 | color.rgb = float3(mul(cm_r, color), mul(cm_g, color), mul(cm_b, color)) + cm_c; 19 | 20 | return color; 21 | } 22 | -------------------------------------------------------------------------------- /Shaders/d3d9/convert_planar_yv.hlsl: -------------------------------------------------------------------------------- 1 | sampler sY : register(s0); 2 | sampler sV : register(s1); 3 | sampler sU : register(s2); 4 | 5 | float4 cm_r : register(c0); 6 | float4 cm_g : register(c1); 7 | float4 cm_b : register(c2); 8 | float3 cm_c : register(c3); 9 | 10 | float4 main(float2 tex : TEXCOORD0) : COLOR 11 | { 12 | float colorY = tex2D(sY, tex).r; 13 | float colorU = tex2D(sU, tex).r; 14 | float colorV = tex2D(sV, tex).r; 15 | 16 | float4 color = float4(colorY, colorU, colorV, 0); 17 | 18 | color.rgb = float3(mul(cm_r, color), mul(cm_g, color), mul(cm_b, color)) + cm_c; 19 | 20 | return color; 21 | } 22 | -------------------------------------------------------------------------------- /Shaders/d3d9/convolution.hlsl: -------------------------------------------------------------------------------- 1 | 2 | sampler s0 : register(s0); // input texture 3 | float2 dxdy : register(c0); 4 | float2 scale : register(c1); 5 | 6 | #include "../resize/convolution_filters.hlsl" 7 | 8 | #ifndef AXIS 9 | #define AXIS 0 10 | #endif 11 | 12 | static const float support = filter_support * scale[AXIS]; 13 | static const float ss = 1.0 / scale[AXIS]; 14 | 15 | float4 main ( float2 tex : TEXCOORD0 ) : COLOR 16 | { 17 | tex += 0.5; 18 | 19 | int low = (int)floor(tex[AXIS] - support); 20 | int high = (int)ceil(tex[AXIS] + support); 21 | 22 | float ww = 0.0; 23 | float4 avg = 0; 24 | 25 | [loop] for (int n = low; n < high; n++) { 26 | float w = filter((n - tex[AXIS] + 0.5) * ss); 27 | ww += w; 28 | #if (AXIS == 0) 29 | avg += w * tex2D(s0, (tex + float2(n - tex[AXIS] + 0.5, 0)) * dxdy, 0, 0); 30 | #else 31 | avg += w * tex2D(s0, (tex + float2(0, n - tex[AXIS] + 0.5)) * dxdy, 0, 0); 32 | #endif 33 | } 34 | avg /= ww; 35 | 36 | return avg; 37 | } 38 | -------------------------------------------------------------------------------- /Shaders/d3d9/final_pass.hlsl: -------------------------------------------------------------------------------- 1 | 2 | #ifndef QUANTIZATION 3 | // 255 or 1023 (Maximum quantized integer value) 4 | #define QUANTIZATION 255 5 | #endif 6 | 7 | sampler image : register(s0); 8 | sampler ditherMatrix : register(s1); 9 | float2 ditherMatrixCoordScale : register(c0); 10 | 11 | float4 main(float2 imageCoord : TEXCOORD0) : COLOR 12 | { 13 | float4 pixel = tex2D(image, imageCoord); 14 | 15 | float4 ditherValue = tex2D(ditherMatrix, imageCoord * ditherMatrixCoordScale); 16 | pixel = floor(pixel * QUANTIZATION + ditherValue) / QUANTIZATION; 17 | 18 | return pixel; 19 | }; 20 | -------------------------------------------------------------------------------- /Shaders/d3d9/fix_bt2020.hlsl: -------------------------------------------------------------------------------- 1 | sampler s0 : register(s0); 2 | 3 | #include "../convert/conv_matrix.hlsl" 4 | #include "../convert/colorspace_gamut_conversion.hlsl" 5 | 6 | static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709); 7 | 8 | float4 main(float2 tex : TEXCOORD0) : COLOR 9 | { 10 | float4 color = tex2D(s0, tex); 11 | 12 | // Fix incorrect (unsupported) conversion from YCbCr BT.2020 to RGB in DXVA2 VP 13 | color = mul(fix_bt2020_matrix, color); 14 | 15 | // sRGB to Linear 16 | color = saturate(color); 17 | color = pow(color, 2.2); 18 | 19 | color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb); 20 | 21 | // Linear to sRGB 22 | color = saturate(color); 23 | color = pow(color, 1.0 / 2.2); 24 | 25 | return color; 26 | } 27 | -------------------------------------------------------------------------------- /Shaders/d3d9/fix_ycgco.hlsl: -------------------------------------------------------------------------------- 1 | sampler s0 : register(s0); 2 | 3 | #include "../convert/conv_matrix.hlsl" 4 | 5 | static const float4x4 fix_ycgco_matrix = mul(ycgco_rgb, rgb_ycbcr709); 6 | 7 | float4 main(float2 tex : TEXCOORD0) : COLOR 8 | { 9 | float4 pixel = tex2D(s0, tex); // original pixel 10 | 11 | // Fix incorrect (unsupported) conversion from YCgCo to RGB in DXVA2 VP 12 | pixel = mul(fix_ycgco_matrix, pixel); 13 | 14 | return pixel; 15 | } 16 | -------------------------------------------------------------------------------- /Shaders/d3d9/fixconvert_hlg_to_sdr.hlsl: -------------------------------------------------------------------------------- 1 | sampler s0 : register(s0); 2 | float4 parameters : register(c0); 3 | #define LuminanceScale parameters[0] 4 | #define param2 parameters[1] 5 | 6 | #include "../convert/conv_matrix.hlsl" 7 | #include "../convert/hlg.hlsl" 8 | #include "../convert/st2084.hlsl" 9 | #include "../convert/hdr_tone_mapping.hlsl" 10 | #include "../convert/colorspace_gamut_conversion.hlsl" 11 | 12 | static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709); 13 | 14 | float4 main(float2 tex : TEXCOORD0) : COLOR 15 | { 16 | float4 color = tex2D(s0, tex); // original pixel 17 | 18 | // Fix incorrect (unsupported) conversion from YCbCr BT.2020 to RGB in DXVA2 VP 19 | color = mul(fix_bt2020_matrix, color); 20 | 21 | // HLG to PQ 22 | color = saturate(color); 23 | color.rgb = HLGtoLinear(color.rgb); 24 | color = LinearToST2084(color, 1000.0); 25 | 26 | // PQ to Linear 27 | color = saturate(color); 28 | color = ST2084ToLinear(color, LuminanceScale); 29 | 30 | color.rgb = ToneMappingHable(color.rgb); 31 | color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb); 32 | 33 | // Linear to sRGB 34 | color = saturate(color); 35 | color = pow(color, 1.0 / 2.2); 36 | 37 | return color; 38 | } 39 | -------------------------------------------------------------------------------- /Shaders/d3d9/fixconvert_pq_to_sdr.hlsl: -------------------------------------------------------------------------------- 1 | sampler s0 : register(s0); 2 | float4 parameters : register(c0); 3 | #define LuminanceScale parameters[0] 4 | #define param2 parameters[1] 5 | 6 | #include "../convert/conv_matrix.hlsl" 7 | #include "../convert/st2084.hlsl" 8 | #include "../convert/hdr_tone_mapping.hlsl" 9 | #include "../convert/colorspace_gamut_conversion.hlsl" 10 | 11 | static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709); 12 | 13 | float4 main(float2 tex : TEXCOORD0) : COLOR 14 | { 15 | float4 color = tex2D(s0, tex); // original pixel 16 | 17 | // Fix incorrect (unsupported) conversion from YCbCr BT.2020 to RGB in DXVA2 VP 18 | color = mul(fix_bt2020_matrix, color); 19 | 20 | // PQ to Linear 21 | color = saturate(color); 22 | color = ST2084ToLinear(color, LuminanceScale); 23 | 24 | color.rgb = ToneMappingHable(color.rgb); 25 | color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb); 26 | 27 | // Linear to sRGB 28 | color = saturate(color); 29 | color = pow(color, 1.0 / 2.2); 30 | 31 | return color; 32 | } 33 | -------------------------------------------------------------------------------- /Shaders/d3d9/halfoverunder_to_interlace.hlsl: -------------------------------------------------------------------------------- 1 | // convert Half OverUnder to Interlace 2 | 3 | sampler s0 : register(s0); 4 | float4 p0 : register(c0); 5 | 6 | #define height (p0[0]) 7 | #define dtop (p0[2]) 8 | #define dbottom (p0[3]) 9 | 10 | float4 main(float2 tex : TEXCOORD0) : COLOR 11 | { 12 | if (tex.y >= dbottom) { 13 | return float4(0.0, 0.0, 0.0, 1.0); 14 | } 15 | 16 | if (fmod((tex.y - dtop) * height, 2) < 1.0) { 17 | // even 18 | tex.y = (dtop + tex.y) / 2; 19 | } else { 20 | // odd 21 | tex.y = (dbottom + tex.y) / 2; 22 | } 23 | 24 | return tex2D(s0, tex); 25 | } 26 | -------------------------------------------------------------------------------- /Shaders/d3d9/interpolation_lanczos2.hlsl: -------------------------------------------------------------------------------- 1 | // compensated Lanczos2 2 | 3 | #ifndef AXIS 4 | #define AXIS 0 5 | #endif 6 | 7 | #define PI acos(-1.) 8 | 9 | sampler s0 : register(s0); 10 | float2 dxdy : register(c0); 11 | 12 | float4 main(float2 tex : TEXCOORD0) : COLOR 13 | { 14 | float t = frac(tex[AXIS]); 15 | #if (AXIS == 0) 16 | float2 pos = tex-float2(t, 0.); 17 | #elif (AXIS == 1) 18 | float2 pos = tex-float2(0., t); 19 | #else 20 | #error ERROR: incorrect AXIS. 21 | #endif 22 | 23 | float4 Q1 = tex2D(s0, (pos+.5)*dxdy); // nearest original pixel to the left 24 | if(t) { 25 | // original pixels 26 | #if (AXIS == 0) 27 | float4 Q0 = tex2D(s0, (pos+float2(-.5, .5))*dxdy); 28 | float4 Q2 = tex2D(s0, (pos+float2(1.5, .5))*dxdy); 29 | float4 Q3 = tex2D(s0, (pos+float2(2.5, .5))*dxdy); 30 | #elif (AXIS == 1) 31 | float4 Q0 = tex2D(s0, (pos+float2(.5, -.5))*dxdy); 32 | float4 Q2 = tex2D(s0, (pos+float2(.5, 1.5))*dxdy); 33 | float4 Q3 = tex2D(s0, (pos+float2(.5, 2.5))*dxdy); 34 | #endif 35 | float4 wset = float3(0., 1., 2.).yxyz+float2(t, -t).xxyy; 36 | float4 w = sin(wset*PI)*sin(wset*PI*.5)/(wset*wset*PI*PI*.5); 37 | 38 | float wc = 1.-dot(1., w); // compensate truncated window factor by bilinear factoring on the two nearest samples 39 | w.y += wc*(1.-t); 40 | w.z += wc*t; 41 | 42 | return w.x*Q0+w.y*Q1+w.z*Q2+w.w*Q3; // interpolation output 43 | } 44 | 45 | return Q1; // case t == 0. is required to return sample Q1, because of a possible division by 0. 46 | } 47 | -------------------------------------------------------------------------------- /Shaders/d3d9/interpolation_lanczos3.hlsl: -------------------------------------------------------------------------------- 1 | // compensated Lanczos3 2 | 3 | #ifndef AXIS 4 | #define AXIS 0 5 | #endif 6 | 7 | #define PI acos(-1.) 8 | 9 | sampler s0 : register(s0); 10 | float2 dxdy : register(c0); 11 | 12 | float4 main(float2 tex : TEXCOORD0) : COLOR 13 | { 14 | float t = frac(tex[AXIS]); 15 | #if (AXIS == 0) 16 | float2 pos = tex - float2(t, 0.); 17 | #elif (AXIS == 1) 18 | float2 pos = tex-float2(0., t); 19 | #else 20 | #error ERROR: incorrect AXIS. 21 | #endif 22 | 23 | float4 Q2 = tex2D(s0, (pos+.5)*dxdy); // nearest original pixel to the left 24 | if(!t) return Q2; // case t == 0. is required to return sample Q2, because of a possible division by 0. 25 | else { 26 | // original pixels 27 | #if (AXIS == 0) 28 | float4 Q0 = tex2D(s0, (pos+float2(-1.5, .5))*dxdy); 29 | float4 Q1 = tex2D(s0, (pos+float2(-.5, .5))*dxdy); 30 | float4 Q3 = tex2D(s0, (pos+float2(1.5, .5))*dxdy); 31 | float4 Q4 = tex2D(s0, (pos+float2(2.5, .5))*dxdy); 32 | float4 Q5 = tex2D(s0, (pos+float2(3.5, .5))*dxdy); 33 | #elif (AXIS == 1) 34 | float4 Q0 = tex2D(s0, (pos+float2(.5, -1.5))*dxdy); 35 | float4 Q1 = tex2D(s0, (pos+float2(.5, -.5))*dxdy); 36 | float4 Q3 = tex2D(s0, (pos+float2(.5, 1.5))*dxdy); 37 | float4 Q4 = tex2D(s0, (pos+float2(.5, 2.5))*dxdy); 38 | float4 Q5 = tex2D(s0, (pos+float2(.5, 3.5))*dxdy); 39 | #endif 40 | float3 wset0 = float3(2., 1., 0.)*PI+t*PI; 41 | float3 wset1 = float3(1., 2., 3.)*PI-t*PI; 42 | float3 wset0s = wset0*.5; 43 | float3 wset1s = wset1*.5; 44 | float3 w0 = sin(wset0)*sin(wset0s)/(wset0*wset0s); 45 | float3 w1 = sin(wset1)*sin(wset1s)/(wset1*wset1s); 46 | 47 | float wc = 1.-dot(1., w0+w1); // compensate truncated window factor by linear factoring on the two nearest samples 48 | w0.z += wc*(1.-t); 49 | w1.x += wc*t; 50 | 51 | return w0.x*Q0+w0.y*Q1+w0.z*Q2+w1.x*Q3+w1.y*Q4+w1.z*Q5; // interpolation output 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Shaders/d3d9/interpolation_spline4.hlsl: -------------------------------------------------------------------------------- 1 | #ifndef AXIS 2 | #define AXIS 0 3 | #endif 4 | 5 | #ifndef METHOD 6 | #define METHOD 1 7 | #endif 8 | 9 | sampler s0 : register(s0); 10 | float2 dxdy : register(c0); 11 | 12 | float4 main(float2 tex : TEXCOORD0) : COLOR 13 | { 14 | float t = frac(tex[AXIS]); 15 | #if (AXIS == 0) 16 | float2 pos = tex-float2(t, 0.); 17 | // original pixels 18 | float4 Q0 = tex2D(s0, (pos+float2(-.5, .5))*dxdy); 19 | float4 Q1 = tex2D(s0, (pos+.5)*dxdy); 20 | float4 Q2 = tex2D(s0, (pos+float2(1.5, .5))*dxdy); 21 | float4 Q3 = tex2D(s0, (pos+float2(2.5, .5))*dxdy); 22 | #elif (AXIS == 1) 23 | float2 pos = tex-float2(0., t); 24 | // original pixels 25 | float4 Q0 = tex2D(s0, (pos+float2(.5, -.5))*dxdy); 26 | float4 Q1 = tex2D(s0, (pos+.5)*dxdy); 27 | float4 Q2 = tex2D(s0, (pos+float2(.5, 1.5))*dxdy); 28 | float4 Q3 = tex2D(s0, (pos+float2(.5, 2.5))*dxdy); 29 | #else 30 | #error ERROR: incorrect AXIS. 31 | #endif 32 | 33 | // calculate weights 34 | float t2 = t * t; 35 | float t3 = t * t2; 36 | #if (METHOD == 0) // Mitchell-Netravali spline4 37 | float4 w0123 = float4(1., 16., 1., 0.)/18.+float4(-.5, 0., .5, 0.)*t+float4(5., -12., 9., -2.)/6.*t2+float4(-7., 21., -21., 7.)/18.*t3; 38 | #elif (METHOD == 1) // Catmull-Rom spline4 39 | float4 w0123 = float4(-.5, 0., .5, 0.)*t+float4(1., -2.5, 2., -.5)*t2+float4(-.5, 1.5, -1.5, .5)*t3; 40 | w0123.y += 1.; 41 | #else 42 | #error ERROR: incorrect METHOD. 43 | #endif 44 | 45 | return w0123[0] * Q0 + w0123[1] * Q1 + w0123[2] * Q2 + w0123[3] * Q3; // interpolation output 46 | } 47 | -------------------------------------------------------------------------------- /Shaders/examples/ps_mpv.hlsl: -------------------------------------------------------------------------------- 1 | // based on blit_float_ps from code of mpv 2 | // also see 3 | // static void pass_convert_yuv 4 | // void pass_color_map 5 | 6 | Texture2D tex : register(t0); 7 | SamplerState samp : register(s0); 8 | 9 | float4 main(float4 pos : SV_Position, float2 coord : TEXCOORD0) : SV_Target 10 | { 11 | return tex.Sample(samp, coord); 12 | } 13 | -------------------------------------------------------------------------------- /Shaders/examples/ps_resize_onepass_bilinear.hlsl: -------------------------------------------------------------------------------- 1 | // Bilinear 2 | 3 | Texture2D tex : register(t0); 4 | SamplerState samp : register(s0); 5 | 6 | cbuffer PS_WH : register(b0) 7 | { 8 | float2 wh; 9 | float2 dxdy; 10 | }; 11 | 12 | struct PS_INPUT 13 | { 14 | float4 Pos : SV_POSITION; 15 | float2 Tex : TEXCOORD; 16 | }; 17 | 18 | float4 main(PS_INPUT input) : SV_Target 19 | { 20 | float2 pos = (input.Tex) * wh - 0.5; 21 | float2 t = frac(pos); 22 | pos = (pos - t + 0.5) * dxdy; 23 | 24 | float4 c00 = tex.Sample(samp, pos); 25 | float4 c01 = tex.Sample(samp, pos + dxdy * float2(0, 1)); 26 | float4 c10 = tex.Sample(samp, pos + dxdy * float2(1, 0)); 27 | float4 c11 = tex.Sample(samp, pos + dxdy); 28 | 29 | return lerp( 30 | lerp(c00, c10, t.x), 31 | lerp(c01, c11, t.x), 32 | t.y); // interpolate and output 33 | } 34 | -------------------------------------------------------------------------------- /Shaders/examples/ps_resize_onepass_catmull4.hlsl: -------------------------------------------------------------------------------- 1 | // Catmull-Rom spline4 2 | 3 | Texture2D tex : register(t0); 4 | SamplerState samp : register(s0); 5 | 6 | cbuffer PS_WH : register(b0) 7 | { 8 | float2 wh; 9 | float2 dxdy; 10 | }; 11 | 12 | struct PS_INPUT 13 | { 14 | float4 Pos : SV_POSITION; 15 | float2 Tex : TEXCOORD; 16 | }; 17 | 18 | #define sp(a, b, c) float4 a = tex.Sample(samp, pos + dxdy*float2(b, c)) 19 | 20 | float4 main(PS_INPUT input) : SV_Target 21 | { 22 | float2 pos = (input.Tex) * wh - 0.5; 23 | float2 t = frac(pos); // calculate the difference between the output pixel and the original surrounding two pixels 24 | pos = (pos - t + 0.5) * dxdy; // adjust sampling matrix to put the output pixel in the interval [Q1, Q2) 25 | 26 | // weights 27 | float2 t2 = t * t; 28 | float2 t3 = t * t2; 29 | float2 w0 = t2 - (t3 + t) / 2; 30 | float2 w1 = t3 * 1.5 + 1 - t2 * 2.5; 31 | float2 w2 = t2 * 2 + t / 2 - t3 * 1.5; 32 | float2 w3 = (t3 - t2) / 2; 33 | 34 | // original pixels 35 | sp(M0, -1, -1); sp(M1, -1, 0); sp(M2, -1, 1); sp(M3, -1, 2); 36 | sp(L0, 0, -1); sp(L1, 0, 0); sp(L2, 0, 1); sp(L3, 0, 2); 37 | sp(K0, 1, -1); sp(K1, 1, 0); sp(K2, 1, 1); sp(K3, 1, 2); 38 | sp(J0, 2, -1); sp(J1, 2, 0); sp(J2, 2, 1); sp(J3, 2, 2); 39 | 40 | // vertical interpolation 41 | float4 Q0 = M0 * w0.y + M1 * w1.y + M2 * w2.y + M3 * w3.y; 42 | float4 Q1 = L0 * w0.y + L1 * w1.y + L2 * w2.y + L3 * w3.y; 43 | float4 Q2 = K0 * w0.y + K1 * w1.y + K2 * w2.y + K3 * w3.y; 44 | float4 Q3 = J0 * w0.y + J1 * w1.y + J2 * w2.y + J3 * w3.y; 45 | 46 | return Q0 * w0.x + Q1 * w1.x + Q2 * w2.x + Q3 * w3.x; // horizontal interpolation and output 47 | } 48 | -------------------------------------------------------------------------------- /Shaders/examples/ps_resize_onepass_jinc2.hlsl: -------------------------------------------------------------------------------- 1 | // jinc 2 2 | 3 | Texture2D tex : register(t0); 4 | SamplerState samp : register(s0); 5 | 6 | cbuffer PS_WH : register(b0) 7 | { 8 | float2 wh; 9 | float2 dxdy; 10 | }; 11 | 12 | struct PS_INPUT 13 | { 14 | float4 Pos : SV_POSITION; 15 | float2 Tex : TEXCOORD; 16 | }; 17 | 18 | #define JINC2_WINDOW_SINC 0.416 19 | #define JINC2_SINC 0.985 20 | #define JINC2_AR_STRENGTH 0.8 21 | #define JINC2_AR_ENABLE 1 22 | 23 | static const float pi = acos(-1); 24 | static const float wa = JINC2_WINDOW_SINC * pi; 25 | static const float wb = JINC2_SINC * pi; 26 | 27 | #define min4(a, b, c, d) min(min(min(a, b), c), d) 28 | #define max4(a, b, c, d) max(max(max(a, b), c), d) 29 | 30 | // Calculates the distance between two points 31 | float d(float2 pt1, float2 pt2) 32 | { 33 | float2 v = pt2 - pt1; 34 | return sqrt(dot(v, v)); 35 | } 36 | 37 | float4 resampler(float4 x) 38 | { 39 | return (x == float4(0, 0, 0, 0)) 40 | ? float4(wa * wb, wa * wb, wa * wb, wa * wb) 41 | : sin(x * wa) * sin(x * wb) / (x * x); 42 | } 43 | 44 | float4 main(PS_INPUT input) : SV_Target 45 | { 46 | float2 dx = float2(1, 0); 47 | float2 dy = float2(0, 1); 48 | 49 | float2 pc = input.Tex * wh; 50 | float2 tc = floor(pc - 0.5) + 0.5; 51 | 52 | float4x4 weights = { 53 | resampler(float4(d(pc, tc - dx - dy ), d(pc, tc - dy ), d(pc, tc + dx - dy ), d(pc, tc + 2*dx - dy ))), 54 | resampler(float4(d(pc, tc - dx ), d(pc, tc ), d(pc, tc + dx ), d(pc, tc + 2*dx ))), 55 | resampler(float4(d(pc, tc - dx + dy ), d(pc, tc + dy ), d(pc, tc + dx + dy ), d(pc, tc + 2*dx + dy ))), 56 | resampler(float4(d(pc, tc - dx + 2*dy), d(pc, tc + 2*dy), d(pc, tc + dx + 2*dy), d(pc, tc + 2*dx + 2*dy))) 57 | }; 58 | 59 | dx *= dxdy; 60 | dy *= dxdy; 61 | tc *= dxdy; 62 | 63 | // reading the texels 64 | // [ c00, c10, c20, c30 ] 65 | // [ c01, c11, c21, c31 ] 66 | // [ c02, c12, c22, c32 ] 67 | // [ c03, c13, c23, c33 ] 68 | float3 c00 = tex.Sample(samp, tc - dx - dy ).rgb; 69 | float3 c10 = tex.Sample(samp, tc - dy ).rgb; 70 | float3 c20 = tex.Sample(samp, tc + dx - dy ).rgb; 71 | float3 c30 = tex.Sample(samp, tc + 2*dx - dy ).rgb; 72 | float3 c01 = tex.Sample(samp, tc - dx ).rgb; 73 | float3 c11 = tex.Sample(samp, tc ).rgb; 74 | float3 c21 = tex.Sample(samp, tc + dx ).rgb; 75 | float3 c31 = tex.Sample(samp, tc + 2*dx ).rgb; 76 | float3 c02 = tex.Sample(samp, tc - dx + dy ).rgb; 77 | float3 c12 = tex.Sample(samp, tc + dy ).rgb; 78 | float3 c22 = tex.Sample(samp, tc + dx + dy ).rgb; 79 | float3 c32 = tex.Sample(samp, tc + 2*dx + dy ).rgb; 80 | float3 c03 = tex.Sample(samp, tc - dx + 2*dy).rgb; 81 | float3 c13 = tex.Sample(samp, tc + 2*dy).rgb; 82 | float3 c23 = tex.Sample(samp, tc + dx + 2*dy).rgb; 83 | float3 c33 = tex.Sample(samp, tc + 2*dx + 2*dy).rgb; 84 | 85 | float3 color = mul(weights[0], float4x3(c00, c10, c20, c30)); 86 | color += mul(weights[1], float4x3(c01, c11, c21, c31)); 87 | color += mul(weights[2], float4x3(c02, c12, c22, c32)); 88 | color += mul(weights[3], float4x3(c03, c13, c23, c33)); 89 | color /= dot(mul(weights, float4(1, 1, 1, 1)), 1); 90 | 91 | #if JINC2_AR_ENABLE 92 | // calc min/max samples 93 | float3 min_sample = min4(c11, c21, c12, c22); 94 | float3 max_sample = max4(c11, c21, c12, c22); 95 | 96 | // Anti-ringing 97 | color = lerp(color, clamp(color, min_sample, max_sample), JINC2_AR_STRENGTH); 98 | #endif 99 | 100 | return float4(color, 1); 101 | } 102 | -------------------------------------------------------------------------------- /Shaders/examples/ps_vlc.hlsl: -------------------------------------------------------------------------------- 1 | // based on globPixelShaderDefault from code of VLC 2 | 3 | #define LEGACY_SHADER_MODE 1 4 | 5 | cbuffer PS_CONSTANT_BUFFER : register(b0) 6 | { 7 | float Opacity; 8 | float BoundaryX; 9 | float BoundaryY; 10 | float LuminanceScale; 11 | }; 12 | cbuffer PS_COLOR_TRANSFORM : register(b1) 13 | { 14 | float4x4 WhitePoint; 15 | float4x4 Colorspace; 16 | float4x4 Primaries; 17 | }; 18 | #if LEGACY_SHADER_MODE 19 | Texture2D shaderTexture[4]; 20 | #else 21 | Texture2DArray shaderTexture[4]; 22 | #endif 23 | SamplerState SamplerStates[2]; 24 | 25 | struct PS_INPUT 26 | { 27 | float4 Position : SV_POSITION; 28 | float3 Texture : TEXCOORD0; 29 | }; 30 | 31 | /* see http://filmicworlds.com/blog/filmic-tonemapping-operators/ */ 32 | inline float4 hable(float4 x) { 33 | const float A = 0.15, B = 0.50, C = 0.10, D = 0.20, E = 0.02, F = 0.30; 34 | return ((x * (A*x + (C*B))+(D*E))/(x * (A*x + B) + (D*F))) - E/F; 35 | } 36 | 37 | /* https://en.wikipedia.org/wiki/Hybrid_Log-Gamma#Technical_details */ 38 | inline float inverse_HLG(float x){ 39 | const float B67_a = 0.17883277; 40 | const float B67_b = 0.28466892; 41 | const float B67_c = 0.55991073; 42 | const float B67_inv_r2 = 4.0; /* 1/0.5² */ 43 | if (x <= 0.5) 44 | x = x * x * B67_inv_r2; 45 | else 46 | x = exp((x - B67_c) / B67_a) + B67_b; 47 | return x; 48 | } 49 | 50 | inline float4 sourceToLinear(float4 rgb) { 51 | return rgb; 52 | } 53 | 54 | inline float4 linearToDisplay(float4 rgb) { 55 | return rgb; 56 | } 57 | 58 | inline float4 transformPrimaries(float4 rgb) { 59 | return rgb; 60 | } 61 | 62 | inline float4 toneMapping(float4 rgb) { 63 | return rgb; 64 | } 65 | 66 | inline float4 adjustRange(float4 rgb) { 67 | return rgb; 68 | } 69 | 70 | inline float4 sampleTexture(SamplerState samplerState, float3 coords) { 71 | float4 sample; 72 | #if LEGACY_SHADER_MODE 73 | sample = shaderTexture[0].Sample(samplerState, coords.xy); /* sampling routine in sample */ 74 | #else 75 | sample = shaderTexture[0].Sample(samplerState, coords); /* sampling routine in sample */ 76 | #endif 77 | return sample; 78 | } 79 | 80 | float4 main( PS_INPUT In ) : SV_TARGET 81 | { 82 | float4 sample; 83 | 84 | if (In.Texture.x > BoundaryX || In.Texture.y > BoundaryY) 85 | sample = sampleTexture( SamplerStates[1], In.Texture ); 86 | else 87 | sample = sampleTexture( SamplerStates[0], In.Texture ); 88 | float4 rgba = max(mul(mul(sample, WhitePoint), Colorspace),0); 89 | float opacity = rgba.a * Opacity; 90 | float4 rgb = rgba; rgb.a = 0; 91 | rgb = sourceToLinear(rgb); 92 | rgb = transformPrimaries(rgb); 93 | rgb = toneMapping(rgb); 94 | rgb = linearToDisplay(rgb); 95 | rgb = adjustRange(rgb); 96 | return float4(rgb.rgb, saturate(opacity)); 97 | } 98 | -------------------------------------------------------------------------------- /Shaders/examples/resizer_onepass_jinc2.hlsl: -------------------------------------------------------------------------------- 1 | // jinc 2 2 | 3 | sampler s0 : register(s0); // input texture 4 | float2 dxdy : register(c0); 5 | 6 | #define JINC2_WINDOW_SINC 0.416 7 | #define JINC2_SINC 0.985 8 | #define JINC2_AR_STRENGTH 0.8 9 | #define JINC2_AR_ENABLE 1 10 | 11 | static const float pi = acos(-1); 12 | static const float wa = JINC2_WINDOW_SINC * pi; 13 | static const float wb = JINC2_SINC * pi; 14 | 15 | #define min4(a, b, c, d) min(min(min(a, b), c), d) 16 | #define max4(a, b, c, d) max(max(max(a, b), c), d) 17 | 18 | // Calculates the distance between two points 19 | float d(float2 pt1, float2 pt2) 20 | { 21 | float2 v = pt2 - pt1; 22 | return sqrt(dot(v, v)); 23 | } 24 | 25 | float4 resampler(float4 x) 26 | { 27 | return (x == float4(0, 0, 0, 0)) 28 | ? float4(wa * wb, wa * wb, wa * wb, wa * wb) 29 | : sin(x * wa) * sin(x * wb) / (x * x); 30 | } 31 | 32 | float4 main(float2 tex : TEXCOORD0) : COLOR 33 | { 34 | float2 dx = float2(1, 0); 35 | float2 dy = float2(0, 1); 36 | 37 | float2 pc = tex+0.5; 38 | float2 tc = floor(tex) + 0.5; 39 | 40 | float4x4 weights = { 41 | resampler(float4(d(pc, tc - dx - dy ), d(pc, tc - dy ), d(pc, tc + dx - dy ), d(pc, tc + 2*dx - dy ))), 42 | resampler(float4(d(pc, tc - dx ), d(pc, tc ), d(pc, tc + dx ), d(pc, tc + 2*dx ))), 43 | resampler(float4(d(pc, tc - dx + dy ), d(pc, tc + dy ), d(pc, tc + dx + dy ), d(pc, tc + 2*dx + dy ))), 44 | resampler(float4(d(pc, tc - dx + 2*dy), d(pc, tc + 2*dy), d(pc, tc + dx + 2*dy), d(pc, tc + 2*dx + 2*dy))) 45 | }; 46 | 47 | dx *= dxdy; 48 | dy *= dxdy; 49 | tc *= dxdy; 50 | 51 | // reading the texels 52 | // [ c00, c10, c20, c30 ] 53 | // [ c01, c11, c21, c31 ] 54 | // [ c02, c12, c22, c32 ] 55 | // [ c03, c13, c23, c33 ] 56 | float3 c00 = tex2D(s0, tc - dx - dy ).rgb; 57 | float3 c10 = tex2D(s0, tc - dy ).rgb; 58 | float3 c20 = tex2D(s0, tc + dx - dy ).rgb; 59 | float3 c30 = tex2D(s0, tc + 2*dx - dy ).rgb; 60 | float3 c01 = tex2D(s0, tc - dx ).rgb; 61 | float3 c11 = tex2D(s0, tc ).rgb; 62 | float3 c21 = tex2D(s0, tc + dx ).rgb; 63 | float3 c31 = tex2D(s0, tc + 2*dx ).rgb; 64 | float3 c02 = tex2D(s0, tc - dx + dy ).rgb; 65 | float3 c12 = tex2D(s0, tc + dy ).rgb; 66 | float3 c22 = tex2D(s0, tc + dx + dy ).rgb; 67 | float3 c32 = tex2D(s0, tc + 2*dx + dy ).rgb; 68 | float3 c03 = tex2D(s0, tc - dx + 2*dy).rgb; 69 | float3 c13 = tex2D(s0, tc + 2*dy).rgb; 70 | float3 c23 = tex2D(s0, tc + dx + 2*dy).rgb; 71 | float3 c33 = tex2D(s0, tc + 2*dx + 2*dy).rgb; 72 | 73 | float3 color = mul(weights[0], float4x3(c00, c10, c20, c30)); 74 | color += mul(weights[1], float4x3(c01, c11, c21, c31)); 75 | color += mul(weights[2], float4x3(c02, c12, c22, c32)); 76 | color += mul(weights[3], float4x3(c03, c13, c23, c33)); 77 | color /= dot(mul(weights, float4(1, 1, 1, 1)), 1); 78 | 79 | #if JINC2_AR_ENABLE 80 | // calc min/max samples 81 | float3 min_sample = min4(c11, c21, c12, c22); 82 | float3 max_sample = max4(c11, c21, c12, c22); 83 | 84 | // Anti-ringing 85 | color = lerp(color, clamp(color, min_sample, max_sample), JINC2_AR_STRENGTH); 86 | #endif 87 | 88 | return float4(color, 1); 89 | } 90 | -------------------------------------------------------------------------------- /Shaders/examples/vs_mpv.hlsl: -------------------------------------------------------------------------------- 1 | // based on blit_vs from code of mpv 2 | 3 | void main(float2 pos : POSITION, float2 coord : TEXCOORD0, 4 | out float4 out_pos : SV_Position, out float2 out_coord : TEXCOORD0) 5 | { 6 | out_pos = float4(pos, 0.0, 1.0); 7 | out_coord = coord; 8 | } 9 | -------------------------------------------------------------------------------- /Shaders/examples/vs_vlc.hlsl: -------------------------------------------------------------------------------- 1 | // based on globVertexShaderFlat from code of VLC 2 | 3 | struct VS_INPUT 4 | { 5 | float4 Position : POSITION; 6 | float4 Texture : TEXCOORD0; 7 | }; 8 | 9 | struct VS_OUTPUT 10 | { 11 | float4 Position : SV_POSITION; 12 | float4 Texture : TEXCOORD0; 13 | }; 14 | 15 | VS_OUTPUT main( VS_INPUT In ) 16 | { 17 | return In; 18 | } 19 | -------------------------------------------------------------------------------- /Shaders/resize/convolution_filters.hlsl: -------------------------------------------------------------------------------- 1 | #define PI acos(-1.) 2 | 3 | #ifndef FILTER 4 | #define FILTER 2 5 | #endif 6 | 7 | #if (FILTER == 0) 8 | 9 | // box 10 | #define filter_support (0.5) 11 | inline float filter(float x) 12 | { 13 | if (x >= -0.5 && x < 0.5) 14 | return 1.0; 15 | return 0.0; 16 | } 17 | 18 | #elif (FILTER == 1) 19 | 20 | // bilinear 21 | #define filter_support (1.0) 22 | inline float filter(float x) 23 | { 24 | if (x < 0.0) 25 | x = -x; 26 | if (x < 1.0) 27 | return 1.0 - x; 28 | return 0.0; 29 | } 30 | 31 | #elif (FILTER == 2) 32 | 33 | // hamming 34 | #define filter_support (1.0) 35 | inline float filter(float x) 36 | { 37 | if (x < 0.0) 38 | x = -x; 39 | if (x == 0.0) 40 | return 1.0; 41 | if (x >= 1.0) 42 | return 0.0; 43 | x *= PI; 44 | return sin(x) / x * (0.54 + 0.46 * cos(x)); 45 | } 46 | 47 | #elif (FILTER == 3) 48 | 49 | // bicubic 50 | // https://en.wikipedia.org/wiki/Bicubic_interpolation#Bicubic_convolution_algorithm 51 | #ifndef A 52 | #define A -0.5 53 | #endif 54 | #define filter_support (2.0) 55 | inline float filter(float x) 56 | { 57 | if (x < 0.0) 58 | x = -x; 59 | if (x < 1.0) 60 | return ((A + 2.0) * x - (A + 3.0)) * x*x + 1; 61 | if (x < 2.0) 62 | return (((x - 5) * x + 8) * x - 4) * A; 63 | return 0.0; 64 | } 65 | #undef A 66 | 67 | #elif (FILTER == 4) 68 | 69 | // lanczos 70 | #define filter_support (3.0) 71 | inline float sinc_filter(float x) 72 | { 73 | if (x == 0.0) 74 | return 1.0; 75 | x *= PI; 76 | return sin(x) / x; 77 | } 78 | inline float filter(float x) 79 | { 80 | /* truncated sinc */ 81 | if (-3.0 <= x && x < 3.0) 82 | return sinc_filter(x) * sinc_filter(x/3); 83 | return 0.0; 84 | } 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /Source/CustomAllocator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2018-2024 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include "MediaSampleSideData.h" 25 | 26 | class CVideoRendererInputPin; 27 | 28 | class CCustomMediaSample : public CMediaSampleSideData 29 | { 30 | public: 31 | CCustomMediaSample(LPCTSTR pName, CBaseAllocator *pAllocator, HRESULT *phr, LPBYTE pBuffer, LONG length); 32 | ~CCustomMediaSample() = default; 33 | 34 | STDMETHODIMP_(ULONG) AddRef() { return __super::AddRef(); } 35 | }; 36 | 37 | class CCustomAllocator : public CMemAllocator 38 | { 39 | protected: 40 | HRESULT Alloc(); 41 | 42 | CVideoRendererInputPin* m_pVideoRendererInputPin = nullptr; 43 | std::unique_ptr m_pNewMT; 44 | long m_cbBuffer = 0; 45 | 46 | public: 47 | CCustomAllocator(LPCTSTR pName, LPUNKNOWN pUnk, CVideoRendererInputPin* pVideoRendererInputPin, HRESULT *phr); 48 | ~CCustomAllocator(); 49 | 50 | STDMETHODIMP SetProperties(__in ALLOCATOR_PROPERTIES* pRequest, __out ALLOCATOR_PROPERTIES* pActual); 51 | STDMETHODIMP GetBuffer(IMediaSample** ppBuffer, REFERENCE_TIME* pStartTime, REFERENCE_TIME* pEndTime, DWORD dwFlags); 52 | 53 | void SetNewMediaType(const CMediaType& mt); 54 | void ClearNewMediaType(); 55 | }; 56 | -------------------------------------------------------------------------------- /Source/D3DUtil/D3D11Font.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2019-2021 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include "D3DCommon.h" 25 | 26 | class CD3D11Font 27 | { 28 | // Font properties 29 | std::wstring m_strFontName; 30 | UINT m_fontHeight = 0; 31 | UINT m_fontFlags = 0; 32 | 33 | WCHAR m_Characters[128]; 34 | FloatRect m_fTexCoords[128] = {}; 35 | SIZE m_MaxCharMetric = {}; 36 | 37 | D3DCOLOR m_Color = D3DCOLOR_XRGB(255, 255, 255); 38 | 39 | ID3D11Device* m_pDevice = nullptr; 40 | ID3D11DeviceContext* m_pDeviceContext = nullptr; 41 | 42 | ID3D11InputLayout* m_pInputLayout = nullptr; 43 | ID3D11VertexShader* m_pVertexShader = nullptr; 44 | ID3D11PixelShader* m_pPixelShader = nullptr; 45 | ID3D11Texture2D* m_pTexture = nullptr; 46 | ID3D11ShaderResourceView* m_pShaderResource = nullptr; 47 | ID3D11Buffer* m_pVertexBuffer = nullptr; 48 | //ID3D11Buffer* m_pIndexBuffer = nullptr; 49 | ID3D11Buffer* m_pPixelBuffer = nullptr; 50 | ID3D11SamplerState* m_pSamplerState = nullptr; 51 | ID3D11BlendState* m_pBlendState = nullptr; 52 | 53 | UINT m_uTexWidth = 0; // Texture dimensions 54 | UINT m_uTexHeight = 0; 55 | 56 | public: 57 | // Constructor / destructor 58 | CD3D11Font(); 59 | ~CD3D11Font(); 60 | 61 | // Initializing and destroying device-dependent objects 62 | HRESULT InitDeviceObjects(ID3D11Device* pDevice, ID3D11DeviceContext* pDeviceContext); 63 | void InvalidateDeviceObjects(); 64 | 65 | HRESULT CreateFontBitmap(const WCHAR* strFontName, const UINT fontHeight, const UINT fontFlags); 66 | 67 | SIZE GetMaxCharMetric(); 68 | 69 | // Function to get extent of text 70 | HRESULT GetTextExtent(const WCHAR* strText, SIZE* pSize); 71 | 72 | // 2D text drawing function 73 | HRESULT Draw2DText(ID3D11RenderTargetView* pRenderTargetView, const SIZE& rtSize, float sx, float sy, D3DCOLOR color, const WCHAR* strText); 74 | }; 75 | -------------------------------------------------------------------------------- /Source/D3DUtil/D3D11Geometry.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2019-2020 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | struct POINTVERTEX11 { 24 | DirectX::XMFLOAT3 Pos; 25 | DirectX::XMFLOAT4 Color; 26 | }; 27 | 28 | // CD3D11Quadrilateral 29 | 30 | class CD3D11Quadrilateral 31 | { 32 | protected: 33 | ID3D11Device* m_pDevice = nullptr; 34 | ID3D11DeviceContext* m_pDeviceContext = nullptr; 35 | 36 | bool m_bAlphaBlend = false; 37 | ID3D11BlendState* m_pBlendState = nullptr; 38 | 39 | POINTVERTEX11 m_Vertices[4] = {}; 40 | ID3D11Buffer* m_pVertexBuffer = nullptr; 41 | ID3D11InputLayout* m_pInputLayout = nullptr; 42 | 43 | ID3D11VertexShader* m_pVertexShader = nullptr; 44 | ID3D11PixelShader* m_pPixelShader = nullptr; 45 | 46 | public: 47 | ~CD3D11Quadrilateral(); 48 | 49 | HRESULT InitDeviceObjects(ID3D11Device* pDevice, ID3D11DeviceContext* pDeviceContext); 50 | void InvalidateDeviceObjects(); 51 | 52 | HRESULT Set(const float x1, const float y1, const float x2, const float y2, const float x3, const float y3, const float x4, const float y4, const D3DCOLOR color); 53 | HRESULT Draw(ID3D11RenderTargetView* pRenderTargetView, const SIZE& rtSize); 54 | }; 55 | 56 | // CD3D11Rectangle 57 | 58 | class CD3D11Rectangle : public CD3D11Quadrilateral 59 | { 60 | private: 61 | using CD3D11Quadrilateral::Set; 62 | 63 | public: 64 | HRESULT Set(const RECT& rect, const SIZE& rtSize, const D3DCOLOR color); 65 | }; 66 | 67 | // CD3D11Stripe 68 | 69 | class CD3D11Stripe : public CD3D11Quadrilateral 70 | { 71 | private: 72 | using CD3D11Quadrilateral::Set; 73 | 74 | public: 75 | HRESULT Set(const int x1, const int y1, const int x2, const int y2, const int thickness, const D3DCOLOR color); 76 | }; 77 | 78 | // CD3D11Dots 79 | 80 | class CD3D11Dots 81 | { 82 | protected: 83 | ID3D11Device* m_pDevice = nullptr; 84 | ID3D11DeviceContext* m_pDeviceContext = nullptr; 85 | 86 | ID3D11InputLayout* m_pInputLayout = nullptr; 87 | ID3D11VertexShader* m_pVertexShader = nullptr; 88 | ID3D11PixelShader* m_pPixelShader = nullptr; 89 | 90 | ID3D11Buffer* m_pVertexBuffer = nullptr; 91 | 92 | SIZE m_RTSize = {}; 93 | bool m_bAlphaBlend = false; 94 | std::vector m_Vertices; 95 | 96 | virtual inline bool CheckNumPoints(const UINT num) 97 | { 98 | return (num > 0); 99 | } 100 | 101 | virtual inline void DrawPrimitive() 102 | { 103 | m_pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); 104 | m_pDeviceContext->Draw(m_Vertices.size(), 0); 105 | } 106 | 107 | public: 108 | ~CD3D11Dots(); 109 | 110 | HRESULT InitDeviceObjects(ID3D11Device* pDevice, ID3D11DeviceContext* pDeviceContext); 111 | void InvalidateDeviceObjects(); 112 | 113 | void ClearPoints(SIZE& newRTSize); 114 | bool AddPoints(POINT* poins, const UINT size, const D3DCOLOR color); 115 | bool AddGFPoints( 116 | int Xstart, int Xstep, 117 | int Yaxis, int Yscale, 118 | int* Ydata, UINT Yoffset, 119 | const UINT size, const D3DCOLOR color); 120 | 121 | HRESULT UpdateVertexBuffer(); 122 | void Draw(); 123 | }; 124 | 125 | // CD3D11Lines 126 | 127 | class CD3D11Lines : public CD3D11Dots 128 | { 129 | private: 130 | using CD3D11Dots::AddGFPoints; 131 | 132 | protected: 133 | inline bool CheckNumPoints(const UINT num) override 134 | { 135 | return (num >= 2 && !(num & 1)); 136 | } 137 | 138 | inline void DrawPrimitive() override 139 | { 140 | m_pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); 141 | m_pDeviceContext->Draw(m_Vertices.size(), 0); 142 | } 143 | }; 144 | 145 | // CD3D9Polyline 146 | 147 | class CD3D11Polyline : public CD3D11Dots 148 | { 149 | protected: 150 | inline bool CheckNumPoints(const UINT num) override 151 | { 152 | return (num >= 2 || m_Vertices.size() && num > 0); 153 | } 154 | 155 | inline void DrawPrimitive() override 156 | { 157 | m_pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP); 158 | m_pDeviceContext->Draw(m_Vertices.size(), 0); 159 | } 160 | }; 161 | -------------------------------------------------------------------------------- /Source/D3DUtil/D3D9Font.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2019-2021 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "D3DCommon.h" 24 | 25 | // Font rendering flags 26 | #define D3DFONT_CENTERED_X 0x0001 27 | #define D3DFONT_CENTERED_Y 0x0002 28 | 29 | class CD3D9Font 30 | { 31 | // Font properties 32 | std::wstring m_strFontName; 33 | UINT m_fontHeight = 0; 34 | UINT m_fontFlags = 0; 35 | 36 | WCHAR m_Characters[128]; 37 | FloatRect m_fTexCoords[128] = {}; 38 | SIZE m_MaxCharMetric = {}; 39 | 40 | IDirect3DDevice9* m_pd3dDevice = nullptr; // A D3DDevice used for rendering 41 | IDirect3DTexture9* m_pTexture = nullptr; // The d3d texture for this font 42 | IDirect3DVertexBuffer9* m_pVertexBuffer = nullptr; // VertexBuffer for rendering text 43 | D3DCAPS9 m_D3DCaps = {}; 44 | UINT m_uTexWidth = 0; // Texture dimensions 45 | UINT m_uTexHeight = 0; 46 | 47 | // Stateblocks for setting and restoring render states 48 | IDirect3DStateBlock9* m_pStateBlockSaved = nullptr; 49 | IDirect3DStateBlock9* m_pStateBlockDrawText = nullptr; 50 | HRESULT CreateStateBlocks(); 51 | 52 | public: 53 | // Constructor / destructor 54 | CD3D9Font(); 55 | ~CD3D9Font(); 56 | 57 | // Initializing and destroying device-dependent objects 58 | HRESULT InitDeviceObjects(IDirect3DDevice9* pd3dDevice); 59 | void InvalidateDeviceObjects(); 60 | 61 | HRESULT CreateFontBitmap(const WCHAR* strFontName, const UINT fontHeight, const UINT fontFlags); 62 | 63 | SIZE GetMaxCharMetric(); 64 | 65 | // Function to get extent of text 66 | HRESULT GetTextExtent(const WCHAR* strText, SIZE* pSize); 67 | 68 | // 2D text drawing function 69 | HRESULT Draw2DText(float sx, float sy, const D3DCOLOR color, const WCHAR* strText, const UINT flags=0L); 70 | }; 71 | -------------------------------------------------------------------------------- /Source/D3DUtil/D3D9Geometry.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2019-2020 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | struct POINTVERTEX9 { 24 | DirectX::XMFLOAT4 pos; 25 | DWORD color; 26 | }; 27 | 28 | // CD3D9Quadrilateral 29 | 30 | class CD3D9Quadrilateral 31 | { 32 | protected: 33 | IDirect3DDevice9* m_pDevice = nullptr; 34 | IDirect3DVertexBuffer9* m_pVertexBuffer = nullptr; 35 | 36 | bool m_bAlphaBlend = false; 37 | POINTVERTEX9 m_Vertices[6] = {}; 38 | 39 | public: 40 | ~CD3D9Quadrilateral(); 41 | 42 | HRESULT InitDeviceObjects(IDirect3DDevice9* pDevice); 43 | void InvalidateDeviceObjects(); 44 | 45 | HRESULT Set( 46 | const float x1, const float y1, 47 | const float x2, const float y2, 48 | const float x3, const float y3, 49 | const float x4, const float y4, 50 | const D3DCOLOR color); 51 | 52 | HRESULT Draw(); 53 | }; 54 | 55 | // CD3D9Rectangle 56 | 57 | class CD3D9Rectangle : public CD3D9Quadrilateral 58 | { 59 | private: 60 | using CD3D9Quadrilateral::Set; 61 | 62 | public: 63 | HRESULT Set(const RECT& rect, const D3DCOLOR color); 64 | }; 65 | 66 | // CD3D9Stripe 67 | 68 | class CD3D9Stripe : public CD3D9Quadrilateral 69 | { 70 | private: 71 | using CD3D9Quadrilateral::Set; 72 | 73 | public: 74 | HRESULT Set(const int x1, const int y1, const int x2, const int y2, const int thickness, const D3DCOLOR color); 75 | }; 76 | 77 | // CD3D9Dots 78 | 79 | class CD3D9Dots 80 | { 81 | protected: 82 | IDirect3DDevice9* m_pDevice = nullptr; 83 | IDirect3DVertexBuffer9* m_pVertexBuffer = nullptr; 84 | 85 | bool m_bAlphaBlend = false; 86 | std::vector m_Vertices; 87 | 88 | virtual inline bool CheckNumPoints(const UINT num) 89 | { 90 | return (num > 0); 91 | } 92 | 93 | virtual inline HRESULT DrawPrimitive() 94 | { 95 | return m_pDevice->DrawPrimitive(D3DPT_POINTLIST, 0, m_Vertices.size()); 96 | } 97 | 98 | public: 99 | ~CD3D9Dots(); 100 | 101 | HRESULT InitDeviceObjects(IDirect3DDevice9* pDevice); 102 | void InvalidateDeviceObjects(); 103 | 104 | void ClearPoints(); 105 | bool AddPoints(POINT* poins, const UINT size, const D3DCOLOR color); 106 | bool AddGFPoints( 107 | int Xstart, int Xstep, 108 | int Yaxis, int Yscale, 109 | int* Ydata, UINT Yoffset, 110 | const UINT size, const D3DCOLOR color); 111 | 112 | HRESULT UpdateVertexBuffer(); 113 | HRESULT Draw(); 114 | }; 115 | 116 | // CD3D9Lines 117 | 118 | class CD3D9Lines : public CD3D9Dots 119 | { 120 | private: 121 | using CD3D9Dots::AddGFPoints; 122 | 123 | protected: 124 | inline bool CheckNumPoints(const UINT num) override 125 | { 126 | return (num >= 2 && !(num & 1)); 127 | } 128 | 129 | inline HRESULT DrawPrimitive() override 130 | { 131 | return m_pDevice->DrawPrimitive(D3DPT_LINELIST, 0, m_Vertices.size() / 2); 132 | } 133 | }; 134 | 135 | // CD3D9Polyline 136 | 137 | class CD3D9Polyline : public CD3D9Dots 138 | { 139 | protected: 140 | inline bool CheckNumPoints(const UINT num) override 141 | { 142 | return (num >= 2 || m_Vertices.size() && num > 0); 143 | } 144 | 145 | inline HRESULT DrawPrimitive() override 146 | { 147 | return m_pDevice->DrawPrimitive(D3DPT_LINESTRIP, 0, m_Vertices.size()-1); 148 | } 149 | }; 150 | -------------------------------------------------------------------------------- /Source/D3DUtil/D3DCommon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2019 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | // Font creation flags 24 | #define D3DFONT_BOLD 0x0001 25 | #define D3DFONT_ITALIC 0x0002 26 | 27 | struct FloatRect 28 | { 29 | float left; 30 | float top; 31 | float right; 32 | float bottom; 33 | }; 34 | -------------------------------------------------------------------------------- /Source/DX9Helper.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2019-2024 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #include "stdafx.h" 22 | #include 23 | #include "Helper.h" 24 | #include "DX9Helper.h" 25 | 26 | UINT GetAdapter(HWND hWnd, IDirect3D9Ex* pD3D) 27 | { 28 | CheckPointer(hWnd, D3DADAPTER_DEFAULT); 29 | CheckPointer(pD3D, D3DADAPTER_DEFAULT); 30 | 31 | const HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST); 32 | CheckPointer(hMonitor, D3DADAPTER_DEFAULT); 33 | 34 | const UINT adapterCount = pD3D->GetAdapterCount(); 35 | for (UINT adapter = 0; adapter < adapterCount; ++adapter) { 36 | const HMONITOR hAdapterMonitor = pD3D->GetAdapterMonitor(adapter); 37 | if (hAdapterMonitor == hMonitor) { 38 | return adapter; 39 | } 40 | } 41 | 42 | return D3DADAPTER_DEFAULT; 43 | } 44 | 45 | HRESULT Dump4ByteSurface(IDirect3DSurface9* pSurface, const wchar_t* filename) 46 | { 47 | D3DSURFACE_DESC desc; 48 | HRESULT hr = pSurface->GetDesc(&desc); 49 | 50 | if (SUCCEEDED(hr) && (desc.Format == D3DFMT_A8R8G8B8 || desc.Format == D3DFMT_X8R8G8B8 || desc.Format == D3DFMT_AYUV)) { 51 | CComPtr pSurfaceShared; 52 | 53 | if (desc.Pool == D3DPOOL_DEFAULT) { 54 | IDirect3DDevice9* pDevice; 55 | pSurface->GetDevice(&pDevice); 56 | hr = pDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pSurfaceShared, nullptr); 57 | if (SUCCEEDED(hr)) { 58 | hr = pDevice->GetRenderTargetData(pSurface, pSurfaceShared); 59 | } 60 | pDevice->Release(); 61 | } else { 62 | pSurfaceShared = pSurface; 63 | } 64 | 65 | if (SUCCEEDED(hr)) { 66 | D3DLOCKED_RECT lr; 67 | hr = pSurfaceShared->LockRect(&lr, nullptr, D3DLOCK_READONLY); 68 | 69 | if (SUCCEEDED(hr)) { 70 | hr = SaveToBMP((BYTE*)lr.pBits, lr.Pitch, desc.Width, desc.Height, 32, filename); 71 | pSurfaceShared->UnlockRect(); 72 | } 73 | } 74 | 75 | return hr; 76 | } 77 | 78 | return E_FAIL; 79 | } 80 | 81 | HRESULT DumpDX9Surface(IDirect3DSurface9* pSurface, const wchar_t* filename) 82 | { 83 | CheckPointer(pSurface, E_POINTER); 84 | 85 | HRESULT hr = S_OK; 86 | 87 | D3DSURFACE_DESC desc = {}; 88 | hr = pSurface->GetDesc(&desc); 89 | if (FAILED(hr)) { 90 | return hr; 91 | }; 92 | 93 | CComPtr pDevice; 94 | hr = pSurface->GetDevice(&pDevice); 95 | if (FAILED(hr)) { 96 | return hr; 97 | }; 98 | 99 | CComPtr pTarget; 100 | hr = pDevice->CreateRenderTarget(desc.Width, desc.Height, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pTarget, nullptr); 101 | if (FAILED(hr)) { 102 | return hr; 103 | }; 104 | 105 | hr = pDevice->StretchRect(pSurface, nullptr, pTarget, nullptr, D3DTEXF_NONE); 106 | if (FAILED(hr)) { 107 | return hr; 108 | }; 109 | 110 | const UINT dib_bitdepth = 32; 111 | const UINT dib_pitch = CalcDibRowPitch(desc.Width, dib_bitdepth); 112 | const UINT dib_size = dib_pitch * desc.Height; 113 | 114 | std::unique_ptr dib(new(std::nothrow) BYTE[sizeof(BITMAPINFOHEADER) + dib_size]); 115 | if (!dib) { 116 | return E_OUTOFMEMORY; 117 | } 118 | 119 | BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)dib.get(); 120 | ZeroMemory(bih, sizeof(BITMAPINFOHEADER)); 121 | bih->biSize = sizeof(BITMAPINFOHEADER); 122 | bih->biWidth = desc.Width; 123 | bih->biHeight = -(LONG)desc.Height; // top-down RGB bitmap 124 | bih->biBitCount = dib_bitdepth; 125 | bih->biPlanes = 1; 126 | bih->biSizeImage = dib_size; 127 | 128 | D3DLOCKED_RECT r; 129 | hr = pTarget->LockRect(&r, nullptr, D3DLOCK_READONLY); 130 | if (FAILED(hr)) { 131 | return hr; 132 | } 133 | 134 | CopyPlaneAsIs(desc.Height, (BYTE*)(bih + 1), dib_pitch, (BYTE*)r.pBits, r.Pitch); 135 | 136 | pTarget->UnlockRect(); 137 | 138 | BITMAPFILEHEADER bfh; 139 | bfh.bfType = 0x4d42; 140 | bfh.bfOffBits = sizeof(bfh) + sizeof(BITMAPINFOHEADER); 141 | bfh.bfSize = bfh.bfOffBits + dib_size; 142 | bfh.bfReserved1 = bfh.bfReserved2 = 0; 143 | 144 | FILE* fp; 145 | if (_wfopen_s(&fp, filename, L"wb") == 0) { 146 | fwrite(&bfh, sizeof(bfh), 1, fp); 147 | fwrite(dib.get(), sizeof(BITMAPINFOHEADER) + dib_size, 1, fp); 148 | fclose(fp); 149 | } else { 150 | hr = E_ACCESSDENIED; 151 | } 152 | 153 | return hr; 154 | } 155 | -------------------------------------------------------------------------------- /Source/DX9Helper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2019-2022 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | struct Tex_t 24 | { 25 | CComPtr pTexture; 26 | CComPtr pSurface; 27 | D3DFORMAT Format = D3DFMT_UNKNOWN; 28 | UINT Width = 0; 29 | UINT Height = 0; 30 | 31 | 32 | HRESULT CheckCreate(IDirect3DDevice9Ex* pDevice, const D3DFORMAT format, const UINT width, const UINT height, DWORD usage) { 33 | if (format == Format && width == Width && height == Height) { 34 | return S_OK; 35 | } 36 | 37 | return Create(pDevice, format, width, height, usage); 38 | } 39 | 40 | HRESULT Create(IDirect3DDevice9Ex* pDevice, const D3DFORMAT format, const UINT width, const UINT height, DWORD usage) { 41 | Release(); 42 | 43 | HRESULT hr = pDevice->CreateTexture(width, height, 1, usage, format, D3DPOOL_DEFAULT, &pTexture, nullptr); 44 | if (S_OK == hr) { 45 | hr = pTexture->GetSurfaceLevel(0, &pSurface); 46 | if (S_OK == hr) { 47 | D3DSURFACE_DESC desc = {}; 48 | EXECUTE_ASSERT(S_OK == pSurface->GetDesc(&desc)); 49 | Format = desc.Format; 50 | Width = desc.Width; 51 | Height = desc.Height; 52 | } else { 53 | ASSERT(FALSE); 54 | pTexture.Release(); 55 | } 56 | } 57 | 58 | return hr; 59 | } 60 | 61 | virtual void Release() { 62 | pSurface.Release(); 63 | pTexture.Release(); 64 | Format = D3DFMT_UNKNOWN; 65 | Width = 0; 66 | Height = 0; 67 | } 68 | }; 69 | 70 | struct Tex9Video_t : Tex_t 71 | { 72 | Tex_t Plane2; 73 | Tex_t Plane3; 74 | 75 | HRESULT CreateEx(IDirect3DDevice9Ex* pDevice, const D3DFORMAT format, const DX9PlaneConfig* pPlanes, UINT width, const UINT height, DWORD usage) { 76 | Release(); 77 | 78 | HRESULT hr; 79 | 80 | if (pPlanes) { 81 | if (format == D3DFMT_YUY2) { 82 | width /= 2; 83 | } 84 | hr = Create(pDevice, pPlanes->FmtPlane1, width, height, usage); 85 | 86 | if (S_OK == hr && pPlanes->FmtPlane2) { 87 | const UINT chromaWidth = width / pPlanes->div_chroma_w; 88 | const UINT chromaHeight = height / pPlanes->div_chroma_h; 89 | hr = Plane2.Create(pDevice, pPlanes->FmtPlane2, chromaWidth, chromaHeight, usage); 90 | 91 | if (S_OK == hr && pPlanes->FmtPlane3) { 92 | hr = Plane3.Create(pDevice, pPlanes->FmtPlane3, chromaWidth, chromaHeight, usage); 93 | } 94 | } 95 | } 96 | else { 97 | hr = Create(pDevice, format, width, height, usage); 98 | } 99 | 100 | if (FAILED(hr)) { 101 | Release(); 102 | } 103 | 104 | return hr; 105 | } 106 | 107 | void Release() override { 108 | Plane3.Release(); 109 | Plane2.Release(); 110 | Tex_t::Release(); 111 | } 112 | }; 113 | 114 | class CTexRing 115 | { 116 | Tex_t Texs[2]; 117 | int index = 0; 118 | UINT size = 0; 119 | 120 | public: 121 | HRESULT CheckCreate(IDirect3DDevice9Ex* pDevice, const D3DFORMAT format, const UINT width, const UINT height, const UINT num) { 122 | HRESULT hr = S_FALSE; 123 | if (num == 0) { 124 | Release(); 125 | return hr; 126 | } 127 | 128 | index = 0; 129 | size = 0; 130 | hr = Texs[0].CheckCreate(pDevice, format, width, height, D3DUSAGE_RENDERTARGET); 131 | size++; 132 | if (S_OK == hr && num >= 2) { 133 | hr = Texs[1].CheckCreate(pDevice, format, width, height, D3DUSAGE_RENDERTARGET); 134 | size++; 135 | } else { 136 | Texs[1].Release(); 137 | } 138 | return hr; 139 | } 140 | 141 | HRESULT Create(IDirect3DDevice9Ex* pDevice, const D3DFORMAT format, const UINT width, const UINT height, const UINT num) { 142 | Release(); 143 | HRESULT hr = S_FALSE; 144 | if (num >= 1) { 145 | hr = Texs[0].Create(pDevice, format, width, height, D3DUSAGE_RENDERTARGET); 146 | size++; 147 | if (S_OK == hr && num >= 2) { 148 | hr = Texs[1].Create(pDevice, format, width, height, D3DUSAGE_RENDERTARGET); 149 | size++; 150 | } 151 | } 152 | return hr; 153 | } 154 | 155 | UINT Size() { 156 | return size; 157 | } 158 | 159 | void Release() { 160 | Texs[0].Release(); 161 | Texs[1].Release(); 162 | index = 0; 163 | size = 0; 164 | } 165 | 166 | Tex_t* GetFirstTex() { 167 | index = 0; 168 | return &Texs[0]; 169 | } 170 | 171 | Tex_t* GetNextTex() { 172 | index = (index + 1) & 1; 173 | return &Texs[index]; 174 | } 175 | }; 176 | 177 | struct ExternalPixelShader9_t 178 | { 179 | std::wstring name; 180 | CComPtr shader; 181 | }; 182 | 183 | UINT GetAdapter(HWND hWnd, IDirect3D9Ex* pD3D); 184 | 185 | HRESULT Dump4ByteSurface(IDirect3DSurface9* pSurface, const wchar_t* filename); 186 | 187 | HRESULT DumpDX9Surface(IDirect3DSurface9* pSurface, const wchar_t* filename); 188 | -------------------------------------------------------------------------------- /Source/DisplayConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2020-2025 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #if !defined(NTDDI_WIN11_GE) 26 | enum { 27 | DISPLAYCONFIG_DEVICE_INFO_SET_RESERVED1 = 14, 28 | DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2 = 15, 29 | DISPLAYCONFIG_DEVICE_INFO_SET_HDR_STATE = 16, 30 | DISPLAYCONFIG_DEVICE_INFO_SET_WCG_STATE = 17, 31 | }; 32 | #endif 33 | 34 | #if !defined(NTDDI_WIN11_GA) || (NTDDI_VERSION < NTDDI_WIN11_GA) 35 | typedef enum _DISPLAYCONFIG_ADVANCED_COLOR_MODE { 36 | DISPLAYCONFIG_ADVANCED_COLOR_MODE_SDR, 37 | DISPLAYCONFIG_ADVANCED_COLOR_MODE_WCG, 38 | DISPLAYCONFIG_ADVANCED_COLOR_MODE_HDR 39 | } DISPLAYCONFIG_ADVANCED_COLOR_MODE; 40 | 41 | typedef struct _DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2 { 42 | DISPLAYCONFIG_DEVICE_INFO_HEADER header; 43 | union { 44 | struct { 45 | UINT32 advancedColorSupported : 1; 46 | UINT32 advancedColorActive : 1; 47 | UINT32 reserved1 : 1; 48 | UINT32 advancedColorLimitedByPolicy : 1; 49 | UINT32 highDynamicRangeSupported : 1; 50 | UINT32 highDynamicRangeUserEnabled : 1; 51 | UINT32 wideColorSupported : 1; 52 | UINT32 wideColorUserEnabled : 1; 53 | UINT32 reserved : 24; 54 | }; 55 | UINT32 value; 56 | }; 57 | DISPLAYCONFIG_COLOR_ENCODING colorEncoding; 58 | UINT32 bitsPerColorChannel; 59 | DISPLAYCONFIG_ADVANCED_COLOR_MODE activeColorMode; 60 | } DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2; 61 | 62 | typedef struct _DISPLAYCONFIG_SET_HDR_STATE { 63 | DISPLAYCONFIG_DEVICE_INFO_HEADER header; 64 | union { 65 | struct { 66 | UINT32 enableHdr : 1; 67 | UINT32 reserved : 31; 68 | }; 69 | UINT32 value; 70 | }; 71 | } DISPLAYCONFIG_SET_HDR_STATE; 72 | #endif 73 | 74 | struct DisplayConfig_t { 75 | union { 76 | struct { 77 | UINT32 advancedColorSupported : 1; // A type of advanced color is supported 78 | UINT32 advancedColorEnabled : 1; // A type of advanced color is enabled 79 | UINT32 wideColorEnforced : 1; // Wide color gamut is enabled 80 | UINT32 advancedColorForceDisabled : 1; // Advanced color is force disabled due to system/OS policy 81 | UINT32 reserved : 28; 82 | }; 83 | UINT32 value; 84 | } advancedColor; 85 | 86 | struct { 87 | union { 88 | struct { 89 | UINT32 advancedColorSupported : 1; 90 | UINT32 advancedColorActive : 1; 91 | UINT32 reserved1 : 1; 92 | UINT32 advancedColorLimitedByPolicy : 1; 93 | UINT32 highDynamicRangeSupported : 1; 94 | UINT32 highDynamicRangeUserEnabled : 1; 95 | UINT32 wideColorSupported : 1; 96 | UINT32 wideColorUserEnabled : 1; 97 | UINT32 reserved : 24; 98 | }; 99 | UINT32 value; 100 | }; 101 | 102 | DISPLAYCONFIG_ADVANCED_COLOR_MODE activeColorMode; 103 | } windows1124H2Colors; 104 | 105 | UINT32 width; 106 | UINT32 height; 107 | UINT32 bitsPerChannel; 108 | DISPLAYCONFIG_COLOR_ENCODING colorEncoding; 109 | DISPLAYCONFIG_RATIONAL refreshRate; 110 | DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering; 111 | DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology; 112 | WCHAR displayName[CCHDEVICENAME]; 113 | WCHAR monitorName[64]; 114 | DISPLAYCONFIG_MODE_INFO modeTarget; 115 | 116 | bool HDRSupported() const { 117 | if (IsWindows11_24H2OrGreater()) { 118 | return windows1124H2Colors.highDynamicRangeSupported; 119 | } 120 | 121 | return advancedColor.advancedColorSupported && !advancedColor.wideColorEnforced && !advancedColor.advancedColorForceDisabled; 122 | } 123 | bool HDREnabled() const { 124 | if (IsWindows11_24H2OrGreater()) { 125 | return windows1124H2Colors.highDynamicRangeSupported && windows1124H2Colors.activeColorMode == DISPLAYCONFIG_ADVANCED_COLOR_MODE::DISPLAYCONFIG_ADVANCED_COLOR_MODE_HDR; 126 | } 127 | 128 | return advancedColor.advancedColorEnabled && !advancedColor.wideColorEnforced && !advancedColor.advancedColorForceDisabled; 129 | } 130 | bool ACMEnabled() const { 131 | if (IsWindows11_24H2OrGreater()) { 132 | return windows1124H2Colors.wideColorSupported && windows1124H2Colors.wideColorUserEnabled; 133 | } 134 | 135 | return false; 136 | } 137 | }; 138 | 139 | double GetRefreshRate(const wchar_t* displayName); 140 | 141 | bool GetDisplayConfig(const wchar_t* displayName, DisplayConfig_t& displayConfig); 142 | 143 | bool GetDisplayConfigs(std::vector& displayConfigs); 144 | 145 | const wchar_t* ColorEncodingToString(DISPLAYCONFIG_COLOR_ENCODING colorEncoding); 146 | const wchar_t* OutputTechnologyToString(DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology); 147 | 148 | std::wstring DisplayConfigToString(const DisplayConfig_t& dc); 149 | 150 | std::wstring D3DDisplayModeToString(const D3DDISPLAYMODEEX& dm); 151 | -------------------------------------------------------------------------------- /Source/IVideoRenderer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2018-2024 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | enum :int { 26 | TEXFMT_AUTOINT = 0, 27 | TEXFMT_8INT = 8, 28 | TEXFMT_10INT = 10, 29 | TEXFMT_16FLOAT = 16, 30 | }; 31 | 32 | enum :int { 33 | SUPERRES_Disable = 0, 34 | SUPERRES_SD, 35 | SUPERRES_720p, 36 | SUPERRES_1080p, 37 | SUPERRES_1440p, 38 | SUPERRES_COUNT 39 | }; 40 | 41 | enum :int { 42 | CHROMA_Nearest = 0, 43 | CHROMA_Bilinear, 44 | CHROMA_CatmullRom, 45 | CHROMA_COUNT 46 | }; 47 | 48 | enum :int { 49 | UPSCALE_Nearest = 0, 50 | UPSCALE_Mitchell, 51 | UPSCALE_CatmullRom, 52 | UPSCALE_Lanczos2, 53 | UPSCALE_Lanczos3, 54 | UPSCALE_Jinc2, 55 | UPSCALE_COUNT 56 | }; 57 | 58 | enum :int { 59 | DOWNSCALE_Box = 0, 60 | DOWNSCALE_Bilinear, 61 | DOWNSCALE_Hamming, 62 | DOWNSCALE_Bicubic, 63 | DOWNSCALE_BicubicSharp, 64 | DOWNSCALE_Lanczos, 65 | DOWNSCALE_COUNT 66 | }; 67 | 68 | enum :int { 69 | SWAPEFFECT_Discard = 0, 70 | SWAPEFFECT_Flip, 71 | SWAPEFFECT_COUNT 72 | }; 73 | 74 | enum :int { 75 | HDRTD_Disabled = 0, 76 | HDRTD_On_Fullscreen, 77 | HDRTD_On, 78 | HDRTD_OnOff_Fullscreen, 79 | HDRTD_OnOff 80 | }; 81 | 82 | #define SDR_NITS_DEF 125 83 | #define SDR_NITS_MIN 25 84 | #define SDR_NITS_MAX 400 85 | #define SDR_NITS_STEP 5 86 | 87 | struct VPEnableFormats_t { 88 | bool bNV12; 89 | bool bP01x; 90 | bool bYUY2; 91 | bool bOther; 92 | }; 93 | 94 | struct Settings_t { 95 | bool bUseD3D11; 96 | bool bShowStats; 97 | int iResizeStats; 98 | int iTexFormat; 99 | VPEnableFormats_t VPFmts; 100 | bool bDeintDouble; 101 | bool bVPScaling; 102 | int iVPSuperRes; 103 | bool bVPRTXVideoHDR; 104 | int iChromaScaling; 105 | int iUpscaling; 106 | int iDownscaling; 107 | bool bInterpolateAt50pct; 108 | bool bUseDither; 109 | bool bDeintBlend; 110 | int iSwapEffect; 111 | bool bExclusiveFS; 112 | bool bVBlankBeforePresent; 113 | bool bAdjustPresentTime; 114 | bool bReinitByDisplay; 115 | bool bHdrPreferDoVi; 116 | bool bHdrPassthrough; 117 | int iHdrToggleDisplay; 118 | int iHdrOsdBrightness; 119 | bool bConvertToSdr; 120 | int iSDRDisplayNits; 121 | 122 | Settings_t() { 123 | SetDefault(); 124 | } 125 | 126 | void SetDefault() { 127 | if (IsWindows8OrGreater()) { 128 | bUseD3D11 = true; 129 | } else { 130 | bUseD3D11 = false; 131 | } 132 | bShowStats = false; 133 | iResizeStats = 0; 134 | iTexFormat = TEXFMT_AUTOINT; 135 | VPFmts.bNV12 = true; 136 | VPFmts.bP01x = true; 137 | VPFmts.bYUY2 = true; 138 | VPFmts.bOther = true; 139 | bDeintDouble = true; 140 | bVPScaling = true; 141 | iVPSuperRes = SUPERRES_Disable; 142 | bVPRTXVideoHDR = false; 143 | iChromaScaling = CHROMA_Bilinear; 144 | iUpscaling = UPSCALE_CatmullRom; 145 | iDownscaling = DOWNSCALE_Hamming; 146 | bInterpolateAt50pct = true; 147 | bUseDither = true; 148 | bDeintBlend = false; 149 | iSwapEffect = SWAPEFFECT_Flip; 150 | bExclusiveFS = false; 151 | bVBlankBeforePresent = false; 152 | bAdjustPresentTime = true; 153 | bReinitByDisplay = false; 154 | bHdrPreferDoVi = false; 155 | if (IsWindows10OrGreater()) { 156 | bHdrPassthrough = true; 157 | } else { 158 | bHdrPassthrough = false; 159 | } 160 | iHdrToggleDisplay = HDRTD_Disabled; 161 | bConvertToSdr = true; 162 | iHdrOsdBrightness = 0; 163 | iSDRDisplayNits = SDR_NITS_DEF; 164 | } 165 | }; 166 | 167 | interface __declspec(uuid("1AB00F10-5F55-42AC-B53F-38649F11BE3E")) 168 | IVideoRenderer : public IUnknown { 169 | STDMETHOD(GetVideoProcessorInfo) (std::wstring& str) PURE; 170 | STDMETHOD_(bool, GetActive()) PURE; 171 | 172 | STDMETHOD_(void, GetSettings(Settings_t& setings)) PURE; 173 | STDMETHOD_(void, SetSettings(const Settings_t& setings)) PURE; 174 | 175 | STDMETHOD(SaveSettings()) PURE; 176 | }; 177 | -------------------------------------------------------------------------------- /Source/MediaSampleSideData.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010-2017 Hendrik Leppkes 3 | * http://www.1f0.de 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 | */ 19 | 20 | #include "stdafx.h" 21 | #include "MediaSampleSideData.h" 22 | 23 | CMediaSampleSideData::CMediaSampleSideData(LPCTSTR pName, CBaseAllocator *pAllocator, HRESULT *phr, LPBYTE pBuffer, LONG length) 24 | : CMediaSample(pName, pAllocator, phr, pBuffer, length) 25 | { 26 | } 27 | 28 | CMediaSampleSideData::~CMediaSampleSideData() 29 | { 30 | ReleaseSideData(); 31 | } 32 | 33 | STDMETHODIMP CMediaSampleSideData::QueryInterface(REFIID riid, __deref_out void **ppv) 34 | { 35 | CheckPointer(ppv, E_POINTER); 36 | ValidateReadWritePtr(ppv, sizeof(PVOID)); 37 | 38 | if (riid == __uuidof(IMediaSideData)) { 39 | return GetInterface((IMediaSideData*) this, ppv); 40 | } 41 | else { 42 | return __super::QueryInterface(riid, ppv); 43 | } 44 | } 45 | 46 | STDMETHODIMP_(ULONG) CMediaSampleSideData::Release() 47 | { 48 | /* Decrement our own private reference count */ 49 | LONG lRef; 50 | if (m_cRef == 1) { 51 | lRef = 0; 52 | m_cRef = 0; 53 | } 54 | else { 55 | lRef = InterlockedDecrement(&m_cRef); 56 | } 57 | ASSERT(lRef >= 0); 58 | 59 | /* Did we release our final reference count */ 60 | if (lRef == 0) { 61 | /* Free all resources */ 62 | if (m_dwFlags & Sample_TypeChanged) { 63 | SetMediaType(NULL); 64 | } 65 | ASSERT(m_pMediaType == NULL); 66 | m_dwFlags = 0; 67 | m_dwTypeSpecificFlags = 0; 68 | m_dwStreamId = AM_STREAM_MEDIA; 69 | 70 | ReleaseSideData(); 71 | 72 | /* This may cause us to be deleted */ 73 | // Our refcount is reliably 0 thus no-one will mess with us 74 | m_pAllocator->ReleaseBuffer(this); 75 | } 76 | return (ULONG)lRef; 77 | } 78 | 79 | void CMediaSampleSideData::ReleaseSideData() 80 | { 81 | CAutoLock Lock(&m_csSideData); 82 | 83 | for (auto& [guid, sd] : m_SideData) { 84 | _aligned_free(sd.pData); 85 | } 86 | 87 | m_SideData.clear(); 88 | } 89 | 90 | // IMediaSideData 91 | STDMETHODIMP CMediaSampleSideData::SetSideData(GUID guidType, const BYTE *pData, size_t size) 92 | { 93 | if (!pData || !size) 94 | return E_POINTER; 95 | 96 | CAutoLock Lock(&m_csSideData); 97 | 98 | auto it = m_SideData.find(guidType); 99 | if (it != m_SideData.end()) 100 | { 101 | SideDataEntry *sd = &(it->second); 102 | BYTE *newData = (BYTE *)_aligned_realloc(sd->pData, size, 16); 103 | if (newData) { 104 | sd->size = size; 105 | sd->pData = newData; 106 | memcpy(newData, pData, size); 107 | } 108 | else 109 | { 110 | return E_OUTOFMEMORY; 111 | } 112 | } 113 | else 114 | { 115 | SideDataEntry sd; 116 | sd.pData = (BYTE *)_aligned_malloc(size, 16); 117 | if (sd.pData) { 118 | sd.size = size; 119 | memcpy(sd.pData, pData, size); 120 | } 121 | else 122 | { 123 | return E_OUTOFMEMORY; 124 | } 125 | 126 | m_SideData[guidType] = sd; 127 | } 128 | 129 | return S_OK; 130 | } 131 | 132 | STDMETHODIMP CMediaSampleSideData::GetSideData(GUID guidType, const BYTE **pData, size_t *pSize) 133 | { 134 | if (!pData || !pSize) 135 | return E_POINTER; 136 | 137 | CAutoLock Lock(&m_csSideData); 138 | 139 | auto it = m_SideData.find(guidType); 140 | if (it != m_SideData.end()) 141 | { 142 | *pData = it->second.pData; 143 | *pSize = it->second.size; 144 | 145 | return S_OK; 146 | } 147 | 148 | return E_FAIL; 149 | } 150 | -------------------------------------------------------------------------------- /Source/MediaSampleSideData.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010-2017 Hendrik Leppkes 3 | * http://www.1f0.de 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "../Include/IMediaSideData.h" 23 | #include 24 | 25 | struct SideDataGUIDComparer 26 | { 27 | bool operator()(const GUID & Left, const GUID & Right) const 28 | { 29 | // comparison logic goes here 30 | return memcmp(&Left, &Right, sizeof(Right)) < 0; 31 | } 32 | }; 33 | 34 | class CMediaSampleSideData : public CMediaSample, public IMediaSideData 35 | { 36 | public: 37 | CMediaSampleSideData(LPCTSTR pName, CBaseAllocator *pAllocator, HRESULT *phr, LPBYTE pBuffer, LONG length); 38 | virtual ~CMediaSampleSideData(); 39 | 40 | STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv); 41 | STDMETHODIMP_(ULONG) Release(); 42 | 43 | // IMediaSideData 44 | STDMETHODIMP SetSideData(GUID guidType, const BYTE *pData, size_t size); 45 | STDMETHODIMP GetSideData(GUID guidType, const BYTE **pData, size_t *pSize); 46 | 47 | private: 48 | void ReleaseSideData(); 49 | 50 | struct SideDataEntry { 51 | BYTE *pData; 52 | size_t size; 53 | }; 54 | 55 | CCritSec m_csSideData; 56 | std::map m_SideData; 57 | }; 58 | -------------------------------------------------------------------------------- /Source/MpcVideoRenderer.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | DllCanUnloadNow PRIVATE 3 | DllGetClassObject PRIVATE 4 | DllRegisterServer PRIVATE 5 | DllUnregisterServer PRIVATE 6 | OpenConfiguration PRIVATE 7 | -------------------------------------------------------------------------------- /Source/PropPage.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2018-2024 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "IVideoRenderer.h" 24 | 25 | // CVRMainPPage 26 | 27 | class __declspec(uuid("DA46D181-07D6-441D-B314-019AEB10148A")) 28 | CVRMainPPage : public CBasePropertyPage, public CWindow 29 | { 30 | CComQIPtr m_pVideoRenderer; 31 | 32 | Settings_t m_SetsPP; 33 | 34 | int m_oldSDRDisplayNits = SDR_NITS_DEF; 35 | 36 | public: 37 | CVRMainPPage(LPUNKNOWN lpunk, HRESULT* phr); 38 | ~CVRMainPPage(); 39 | 40 | private: 41 | void SetControls(); 42 | void EnableControls(); 43 | 44 | HRESULT OnConnect(IUnknown* pUnknown) override; 45 | HRESULT OnDisconnect() override; 46 | HRESULT OnActivate() override; 47 | void SetDirty() 48 | { 49 | m_bDirty = TRUE; 50 | if (m_pPageSite) { 51 | m_pPageSite->OnStatusChange(PROPPAGESTATUS_DIRTY); 52 | } 53 | } 54 | INT_PTR OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override; 55 | HRESULT OnApplyChanges() override; 56 | }; 57 | 58 | // CVRInfoPPage 59 | 60 | class __declspec(uuid("D697132B-FCA4-4401-8869-D3B39D0750DB")) 61 | CVRInfoPPage : public CBasePropertyPage, public CWindow 62 | { 63 | HFONT m_hMonoFont = nullptr; 64 | CComQIPtr m_pVideoRenderer; 65 | 66 | public: 67 | CVRInfoPPage(LPUNKNOWN lpunk, HRESULT* phr); 68 | ~CVRInfoPPage(); 69 | 70 | private: 71 | HRESULT OnConnect(IUnknown* pUnknown) override; 72 | HRESULT OnDisconnect() override; 73 | HRESULT OnActivate() override; 74 | }; 75 | -------------------------------------------------------------------------------- /Source/Shaders.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2019-2024 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | struct PS_COLOR_TRANSFORM { 26 | DirectX::XMFLOAT4 cm_r; 27 | DirectX::XMFLOAT4 cm_g; 28 | DirectX::XMFLOAT4 cm_b; 29 | DirectX::XMFLOAT4 cm_c; 30 | }; 31 | 32 | struct PS_DOVI_POLY_CURVE { 33 | DirectX::XMFLOAT4 pivots_data[7]; 34 | DirectX::XMFLOAT4 coeffs_data[8]; 35 | }; 36 | 37 | #define PS_RESHAPE_POLY 1 38 | #define PS_RESHAPE_MMR 2 39 | 40 | struct PS_DOVI_CURVE { 41 | DirectX::XMFLOAT4 pivots_data[7]; 42 | DirectX::XMFLOAT4 coeffs_data[8]; 43 | DirectX::XMFLOAT4 mmr_data[8 * 6]; 44 | struct { 45 | uint32_t methods; 46 | uint32_t mmr_single; 47 | uint32_t min_order; 48 | uint32_t max_order; 49 | } params; 50 | }; 51 | 52 | static_assert(sizeof(PS_DOVI_CURVE) % 16 == 0); 53 | 54 | enum :int { 55 | SHADER_CONVERT_NONE = 0, 56 | SHADER_CONVERT_TO_SDR, 57 | SHADER_CONVERT_TO_PQ, 58 | }; 59 | 60 | HRESULT CompileShader(const std::string& srcCode, const D3D_SHADER_MACRO* pDefines, LPCSTR pTarget, ID3DBlob** ppCode); 61 | 62 | HRESULT GetShaderConvertColor( 63 | const bool bDX11, 64 | const UINT width, 65 | const long texW, long texH, 66 | const RECT rect, 67 | const FmtConvParams_t& fmtParams, 68 | const DXVA2_ExtendedFormat exFmt, 69 | const MediaSideDataDOVIMetadata* const pDoviMetadata, 70 | const int chromaScaling, 71 | const int convertType, 72 | const bool blendDeinterlace, 73 | ID3DBlob** ppCode); 74 | -------------------------------------------------------------------------------- /Source/SubPic/DX11SubPic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2022-2024 see Authors.txt 3 | * This file is part of MPC-BE. 4 | * 5 | * MPC-BE is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MPC-BE is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "SubPicImpl.h" 23 | #include 24 | #include 25 | 26 | // CDX11SubPic 27 | 28 | 29 | class CDX11SubPicAllocator; 30 | 31 | struct MemPic_t { 32 | std::unique_ptr data; 33 | UINT w = 0; 34 | UINT h = 0; 35 | }; 36 | 37 | class CDX11SubPic : public CSubPicImpl 38 | { 39 | MemPic_t m_MemPic; 40 | 41 | protected: 42 | STDMETHODIMP_(void*) GetObject() override; // returns MemPic_t* 43 | 44 | public: 45 | CDX11SubPicAllocator *m_pAllocator; 46 | 47 | CDX11SubPic(MemPic_t&& pMemPic, CDX11SubPicAllocator *pAllocator); 48 | ~CDX11SubPic(); 49 | 50 | // ISubPic 51 | STDMETHODIMP GetDesc(SubPicDesc& spd) override; 52 | STDMETHODIMP CopyTo(ISubPic* pSubPic) override; 53 | STDMETHODIMP ClearDirtyRect() override; 54 | STDMETHODIMP Lock(SubPicDesc& spd) override; 55 | STDMETHODIMP Unlock(RECT* pDirtyRect) override; 56 | STDMETHODIMP AlphaBlt(RECT* pSrc, RECT* pDst, SubPicDesc* pTarget) override; 57 | STDMETHODIMP_(bool) IsNeedAlloc() override; 58 | }; 59 | 60 | // CDX11SubPicAllocator 61 | 62 | class CDX11SubPicAllocator : public CSubPicAllocatorImpl, public CCritSec 63 | { 64 | CComPtr m_pDevice; 65 | CSize m_maxsize; 66 | 67 | CComPtr m_pOutputTexture; 68 | CComPtr m_pOutputShaderResource; 69 | CComPtr m_pAlphaBlendState; 70 | CComPtr m_pVertexBuffer; 71 | CComPtr m_pSamplerPoint; 72 | CComPtr m_pSamplerLinear; 73 | 74 | bool Alloc(bool fStatic, ISubPic** ppSubPic) override; 75 | 76 | HRESULT CreateOutputTex(); 77 | void CreateBlendState(); 78 | void CreateOtherStates(); 79 | void ReleaseAllStates(); 80 | 81 | public: 82 | inline static CCritSec ms_SurfaceQueueLock; 83 | std::deque m_FreeSurfaces; 84 | std::deque m_AllocatedSurfaces; 85 | 86 | HRESULT Render(const MemPic_t& memPic, const CRect& dirtyRect, const CRect& srcRect, const CRect& dstRect); 87 | 88 | void GetStats(int& _nFree, int& _nAlloc); 89 | 90 | CDX11SubPicAllocator(ID3D11Device* pDevice, SIZE maxsize); 91 | ~CDX11SubPicAllocator(); 92 | void ClearCache(); 93 | 94 | // ISubPicAllocator 95 | STDMETHODIMP ChangeDevice(IUnknown* pDev) override; 96 | STDMETHODIMP SetMaxTextureSize(SIZE MaxTextureSize) override; 97 | STDMETHODIMP_(void) SetInverseAlpha(bool bInverted) override; 98 | }; 99 | -------------------------------------------------------------------------------- /Source/SubPic/DX9SubPic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2003-2006 Gabest 3 | * (C) 2006-2024 see Authors.txt 4 | * 5 | * This file is part of MPC-BE. 6 | * 7 | * MPC-BE is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * MPC-BE is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #include "SubPicImpl.h" 25 | #include 26 | 27 | // CDX9SubPic 28 | 29 | 30 | class CDX9SubPicAllocator; 31 | class CDX9SubPic : public CSubPicImpl 32 | { 33 | CComPtr m_pSurface; 34 | const bool m_bExternalRenderer; 35 | 36 | public: 37 | CDX9SubPicAllocator *m_pAllocator; 38 | 39 | CDX9SubPic(IDirect3DSurface9* pSurface, CDX9SubPicAllocator *pAllocator, bool bExternalRenderer); 40 | ~CDX9SubPic(); 41 | 42 | // ISubPic 43 | protected: 44 | STDMETHODIMP_(void*) GetObject() override; // returns IDirect3DTexture9* 45 | public: 46 | STDMETHODIMP GetDesc(SubPicDesc& spd) override; 47 | STDMETHODIMP CopyTo(ISubPic* pSubPic) override; 48 | STDMETHODIMP ClearDirtyRect() override; 49 | STDMETHODIMP Lock(SubPicDesc& spd) override; 50 | STDMETHODIMP Unlock(RECT* pDirtyRect) override; 51 | STDMETHODIMP AlphaBlt(RECT* pSrc, RECT* pDst, SubPicDesc* pTarget) override; 52 | }; 53 | 54 | // CDX9SubPicAllocator 55 | 56 | class CDX9SubPicAllocator : public CSubPicAllocatorImpl, public CCritSec 57 | { 58 | CComPtr m_pDevice; 59 | CSize m_maxsize; 60 | const bool m_bExternalRenderer; 61 | 62 | // CSubPicAllocatorImpl 63 | bool Alloc(bool fStatic, ISubPic** ppSubPic) override; 64 | 65 | public: 66 | inline static CCritSec ms_SurfaceQueueLock; 67 | std::deque > m_FreeSurfaces; 68 | std::deque m_AllocatedSurfaces; 69 | 70 | CDX9SubPicAllocator(IDirect3DDevice9* pDevice, SIZE maxsize, bool bExternalRenderer); 71 | ~CDX9SubPicAllocator(); 72 | 73 | void GetStats(int &_nFree, int &_nAlloc); 74 | void ClearCache(); 75 | 76 | // ISubPicAllocator 77 | STDMETHODIMP ChangeDevice(IUnknown* pDev) override; 78 | STDMETHODIMP SetMaxTextureSize(SIZE MaxTextureSize) override; 79 | }; 80 | -------------------------------------------------------------------------------- /Source/SubPic/XySubPicProvider.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2006-2018 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #include "stdafx.h" 22 | #include "Utils/Util.h" 23 | #include "XySubPicProvider.h" 24 | 25 | CXySubPicProvider::CXySubPicProvider(ISubRenderProvider* provider) 26 | : CUnknown(L"CXySubPicProvider", NULL) 27 | , m_pSubRenderProvider(provider) 28 | , m_pSubFrame(NULL) 29 | , m_rtStart(0) 30 | , m_rtStop(0) 31 | { 32 | m_hEvtDelivered = CreateEventW(NULL, false, false, NULL); 33 | } 34 | 35 | CXySubPicProvider::~CXySubPicProvider() 36 | { 37 | CloseHandle(m_hEvtDelivered); 38 | } 39 | 40 | STDMETHODIMP CXySubPicProvider::NonDelegatingQueryInterface(REFIID riid, void** ppv) 41 | { 42 | return 43 | QI(ISubPicProvider) 44 | QI(IXyCompatProvider) 45 | __super::NonDelegatingQueryInterface(riid, ppv); 46 | } 47 | 48 | // IXyCompatProvider 49 | 50 | STDMETHODIMP CXySubPicProvider::DeliverFrame(REFERENCE_TIME start, REFERENCE_TIME stop, LPVOID context, ISubRenderFrame* subtitleFrame) 51 | { 52 | m_rtStart = start; 53 | m_rtStop = stop; 54 | m_pSubFrame = subtitleFrame; 55 | 56 | SetEvent(m_hEvtDelivered); 57 | return S_OK; 58 | } 59 | 60 | STDMETHODIMP CXySubPicProvider::RequestFrame(REFERENCE_TIME start, REFERENCE_TIME stop, DWORD timeout) 61 | { 62 | HRESULT hr = E_FAIL; 63 | 64 | if (FAILED(hr = m_pSubRenderProvider->RequestFrame(start, stop, NULL))) { 65 | return hr; 66 | } 67 | 68 | if (WaitForSingleObject(m_hEvtDelivered, timeout) == WAIT_TIMEOUT) { 69 | return E_ABORT; 70 | } 71 | 72 | return S_OK; 73 | } 74 | 75 | STDMETHODIMP CXySubPicProvider::GetID(ULONGLONG* id) 76 | { 77 | return m_pSubFrame ? m_pSubFrame->GetBitmap(0, id, NULL, NULL, NULL, NULL) : E_FAIL; 78 | } 79 | 80 | // ISubPicProvider 81 | 82 | STDMETHODIMP CXySubPicProvider::Lock() 83 | { 84 | m_csSubRenderProvider.Lock(); 85 | return S_OK; 86 | } 87 | 88 | STDMETHODIMP CXySubPicProvider::Unlock() 89 | { 90 | m_csSubRenderProvider.Unlock(); 91 | return S_OK; 92 | } 93 | 94 | STDMETHODIMP CXySubPicProvider::Render(SubPicDesc& spd, REFERENCE_TIME rt, double fps, RECT& bbox) 95 | { 96 | if (spd.bpp != 32) { 97 | ASSERT(FALSE); 98 | return E_INVALIDARG; 99 | } 100 | 101 | if (!m_pSubFrame || (m_rtStart > rt || rt >= m_rtStop)) { 102 | return E_FAIL; 103 | } 104 | 105 | POINT p; 106 | SIZE sz; 107 | BYTE* s; 108 | int pitch; 109 | HRESULT hr = m_pSubFrame->GetBitmap(0, NULL, &p, &sz, (LPCVOID*)(&s), &pitch); 110 | if (FAILED(hr)) { 111 | return hr; 112 | } 113 | 114 | CRect rcDirty; 115 | rcDirty.IntersectRect(CRect(p, sz), CRect(0, 0, spd.w, spd.h)); 116 | int w = rcDirty.Width(), h = rcDirty.Height(); 117 | BYTE* d = spd.bits + spd.pitch * rcDirty.top + rcDirty.left * 4; // move pointer to dirty rect 118 | for (ptrdiff_t j = 0; j < h; j++, s += pitch, d += spd.pitch) { 119 | memcpy(d, s, w * 4); 120 | } 121 | 122 | bbox = rcDirty; 123 | return S_OK; 124 | } 125 | 126 | STDMETHODIMP CXySubPicProvider::GetTextureSize(POSITION pos, SIZE& MaxTextureSize, SIZE& VirtualSize, POINT& VirtualTopLeft) 127 | { 128 | CRect outputRect, clipRect; 129 | if (m_pSubFrame && SUCCEEDED(m_pSubFrame->GetOutputRect(&outputRect)) && SUCCEEDED(m_pSubFrame->GetClipRect(&clipRect))) { 130 | MaxTextureSize = outputRect.Size(); 131 | VirtualSize = clipRect.Size(); 132 | VirtualTopLeft = clipRect.TopLeft(); 133 | return S_OK; 134 | } 135 | return E_FAIL; 136 | } 137 | -------------------------------------------------------------------------------- /Source/SubPic/XySubPicProvider.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2015-2025 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "ISubPic.h" 24 | #include "../Include/SubRenderIntf.h" 25 | 26 | 27 | interface __declspec(uuid("63679E0A-93AB-4656-AF40-589E4E985991")) 28 | IXyCompatProvider : 29 | public IUnknown { 30 | STDMETHOD(RequestFrame)(REFERENCE_TIME start, REFERENCE_TIME stop, DWORD timeout) PURE; 31 | STDMETHOD(DeliverFrame)(REFERENCE_TIME start, REFERENCE_TIME stop, LPVOID context, ISubRenderFrame * subtitleFrame) PURE; 32 | STDMETHOD(GetID)(ULONGLONG * id) PURE; 33 | }; 34 | 35 | class CXySubPicProvider 36 | : public CUnknown 37 | , public ISubPicProvider 38 | , public IXyCompatProvider 39 | { 40 | CComPtr m_pSubRenderProvider; 41 | CComPtr m_pSubFrame; 42 | CCritSec m_csSubRenderProvider; 43 | 44 | REFERENCE_TIME m_rtStart; 45 | REFERENCE_TIME m_rtStop; 46 | 47 | HANDLE m_hEvtDelivered; 48 | public: 49 | CXySubPicProvider(ISubRenderProvider* provider); 50 | virtual ~CXySubPicProvider(); 51 | 52 | DECLARE_IUNKNOWN; 53 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv); 54 | 55 | // IXyCompatProvider 56 | 57 | STDMETHODIMP DeliverFrame(REFERENCE_TIME start, REFERENCE_TIME stop, LPVOID context, ISubRenderFrame* subtitleFrame); 58 | STDMETHODIMP RequestFrame(REFERENCE_TIME start, REFERENCE_TIME stop, DWORD timeout); 59 | STDMETHODIMP GetID(ULONGLONG* id); 60 | 61 | // ISubPicProvider 62 | 63 | STDMETHODIMP Lock(); 64 | STDMETHODIMP Unlock(); 65 | 66 | STDMETHODIMP_(POSITION) GetStartPosition(REFERENCE_TIME rt, double fps, bool CleanOld = false) { return NULL; } 67 | STDMETHODIMP_(POSITION) GetNext(POSITION pos) { return NULL; } 68 | 69 | STDMETHODIMP_(REFERENCE_TIME) GetStart(POSITION pos, double fps) { return 0; } 70 | STDMETHODIMP_(REFERENCE_TIME) GetStop(POSITION pos, double fps) { return 0; } 71 | 72 | STDMETHODIMP_(bool) IsAnimated(POSITION pos) { return true; } 73 | 74 | STDMETHODIMP Render(SubPicDesc& spd, REFERENCE_TIME rt, double fps, RECT& bbox); 75 | STDMETHODIMP GetTextureSize(POSITION pos, SIZE& MaxTextureSize, SIZE& VirtualSize, POINT& VirtualTopLeft); 76 | 77 | STDMETHODIMP_(SUBTITLE_TYPE) GetType() { return ST_XYSUBPIC; }; 78 | }; 79 | -------------------------------------------------------------------------------- /Source/SubPic/XySubPicQueueImpl.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2003-2006 Gabest 3 | * (C) 2006-2024 see Authors.txt 4 | * 5 | * This file is part of MPC-BE. 6 | * 7 | * MPC-BE is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * MPC-BE is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #include "stdafx.h" 23 | #include "XySubPicQueueImpl.h" 24 | #include "XySubPicProvider.h" 25 | 26 | // 27 | // CXySubPicQueueNoThread 28 | // 29 | 30 | CXySubPicQueueNoThread::CXySubPicQueueNoThread(ISubPicAllocator* pAllocator, HRESULT* phr) 31 | : CSubPicQueueNoThread(false, pAllocator, phr) 32 | , m_llSubId(0) 33 | { 34 | } 35 | 36 | CXySubPicQueueNoThread::~CXySubPicQueueNoThread() 37 | { 38 | } 39 | 40 | // ISubPicQueue 41 | 42 | STDMETHODIMP CXySubPicQueueNoThread::Invalidate(REFERENCE_TIME rtInvalidate) 43 | { 44 | m_llSubId = 0; 45 | return __super::Invalidate(rtInvalidate); 46 | } 47 | 48 | STDMETHODIMP_(bool) CXySubPicQueueNoThread::LookupSubPic(REFERENCE_TIME rtNow, CComPtr& ppSubPic) 49 | { 50 | // CXySubPicQueueNoThread is always blocking so bAdviseBlocking doesn't matter anyway 51 | return LookupSubPic(rtNow, true, ppSubPic); 52 | } 53 | 54 | STDMETHODIMP_(bool) CXySubPicQueueNoThread::LookupSubPic(REFERENCE_TIME rtNow, bool /*bAdviseBlocking*/, CComPtr& ppSubPic) 55 | { 56 | // CXySubPicQueueNoThread is always blocking so we ignore bAdviseBlocking 57 | 58 | CComPtr pSubPic; 59 | CComPtr pSubPicProvider; 60 | GetSubPicProvider(&pSubPicProvider); 61 | CComQIPtr pXySubPicProvider(pSubPicProvider); 62 | 63 | { 64 | CAutoLock cAutoLock(&m_csLock); 65 | 66 | pSubPic = m_pSubPic; 67 | } 68 | 69 | if (pXySubPicProvider) { 70 | double fps = m_fps; 71 | REFERENCE_TIME rtTimePerFrame = static_cast(10000000.0 / fps); 72 | 73 | REFERENCE_TIME rtStart = rtNow; 74 | REFERENCE_TIME rtStop = rtNow + rtTimePerFrame; 75 | 76 | HRESULT hr = pXySubPicProvider->RequestFrame(rtStart, rtStop, (DWORD)(1000.0 / fps)); 77 | if (SUCCEEDED(hr)) { 78 | ULONGLONG id; 79 | hr = pXySubPicProvider->GetID(&id); 80 | if (SUCCEEDED(hr)) { 81 | bool bAllocSubPic = !pSubPic; 82 | SIZE MaxTextureSize, VirtualSize; 83 | POINT VirtualTopLeft; 84 | HRESULT hr2; 85 | if (SUCCEEDED(hr2 = pSubPicProvider->GetTextureSize(0, MaxTextureSize, VirtualSize, VirtualTopLeft))) { 86 | m_pAllocator->SetMaxTextureSize(MaxTextureSize); 87 | if (!bAllocSubPic) { 88 | // Ensure the previously allocated subpic is big enough to hold the subtitle to be rendered 89 | SIZE maxSize; 90 | bAllocSubPic = FAILED(pSubPic->GetMaxSize(&maxSize)) || maxSize.cx < MaxTextureSize.cx || maxSize.cy < MaxTextureSize.cy; 91 | 92 | if (!bAllocSubPic) { 93 | bAllocSubPic = pSubPic->IsNeedAlloc(); 94 | } 95 | } 96 | } 97 | 98 | SUBTITLE_TYPE sType = pSubPicProvider->GetType(); 99 | 100 | if (bAllocSubPic) { 101 | CAutoLock cAutoLock(&m_csLock); 102 | 103 | m_pSubPic.Release(); 104 | 105 | if (FAILED(m_pAllocator->AllocDynamic(&m_pSubPic))) { 106 | return false; 107 | } 108 | 109 | pSubPic = m_pSubPic; 110 | } 111 | 112 | if (!bAllocSubPic && m_llSubId == id) { // same subtitle as last time 113 | pSubPic->SetStop(rtStop); 114 | ppSubPic = pSubPic; 115 | } 116 | else if (m_pAllocator->IsDynamicWriteOnly()) { 117 | CComPtr pStatic; 118 | hr = m_pAllocator->GetStatic(&pStatic); 119 | if (SUCCEEDED(hr)) { 120 | hr = RenderTo(pStatic, rtStart, rtStop, fps, true); 121 | } 122 | if (SUCCEEDED(hr)) { 123 | hr = pStatic->CopyTo(pSubPic); 124 | } 125 | if (SUCCEEDED(hr)) { 126 | ppSubPic = pSubPic; 127 | m_llSubId = id; 128 | } 129 | } 130 | else if (SUCCEEDED(RenderTo(pSubPic, rtStart, rtStop, fps, true))) { 131 | ppSubPic = pSubPic; 132 | m_llSubId = id; 133 | } 134 | 135 | if (ppSubPic) { 136 | if (SUCCEEDED(hr2)) { 137 | ppSubPic->SetVirtualTextureSize(VirtualSize, VirtualTopLeft); 138 | } 139 | 140 | pSubPic->SetType(sType); 141 | } 142 | } 143 | } 144 | } 145 | 146 | return !!ppSubPic; 147 | } 148 | -------------------------------------------------------------------------------- /Source/SubPic/XySubPicQueueImpl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2003-2006 Gabest 3 | * (C) 2006-2015 see Authors.txt 4 | * 5 | * This file is part of MPC-BE. 6 | * 7 | * MPC-BE is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * MPC-BE is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #include "SubPicQueueImpl.h" 25 | #include "XySubPicProvider.h" 26 | 27 | class CXySubPicQueueNoThread : public CSubPicQueueNoThread 28 | { 29 | ULONGLONG m_llSubId; 30 | 31 | public: 32 | CXySubPicQueueNoThread(ISubPicAllocator* pAllocator, HRESULT* phr); 33 | virtual ~CXySubPicQueueNoThread(); 34 | 35 | // ISubPicQueue 36 | 37 | STDMETHODIMP Invalidate(REFERENCE_TIME rtInvalidate = -1); 38 | STDMETHODIMP_(bool) LookupSubPic(REFERENCE_TIME rtNow, CComPtr& pSubPic); 39 | STDMETHODIMP_(bool) LookupSubPic(REFERENCE_TIME rtNow, bool, CComPtr& pSubPic); 40 | }; 41 | -------------------------------------------------------------------------------- /Source/Times.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2018 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #include "stdafx.h" 22 | #include "Times.h" 23 | 24 | // code from VirtualDub\system\source\time.cpp 25 | 26 | uint64_t GetPreciseTick() 27 | { 28 | LARGE_INTEGER li; 29 | QueryPerformanceCounter(&li); 30 | return li.QuadPart; 31 | } 32 | 33 | namespace { 34 | uint64_t GetPreciseTicksPerSecondNowI() 35 | { 36 | LARGE_INTEGER freq; 37 | QueryPerformanceFrequency(&freq); 38 | return freq.QuadPart; 39 | } 40 | 41 | double GetPreciseTicksPerSecondNow() 42 | { 43 | LARGE_INTEGER freq; 44 | QueryPerformanceFrequency(&freq); 45 | return (double)freq.QuadPart; 46 | } 47 | } 48 | 49 | uint64_t GetPreciseTicksPerSecondI() 50 | { 51 | static uint64_t ticksPerSecond = GetPreciseTicksPerSecondNowI(); 52 | 53 | return ticksPerSecond; 54 | } 55 | 56 | double GetPreciseTicksPerSecond() 57 | { 58 | static double ticksPerSecond = GetPreciseTicksPerSecondNow(); 59 | 60 | return ticksPerSecond; 61 | } 62 | 63 | double GetPreciseSecondsPerTick() 64 | { 65 | static double secondsPerTick = 1.0 / GetPreciseTicksPerSecondNow(); 66 | 67 | return secondsPerTick; 68 | } 69 | -------------------------------------------------------------------------------- /Source/Times.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2018 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | uint64_t GetPreciseTick(); 24 | uint64_t GetPreciseTicksPerSecondI(); 25 | double GetPreciseTicksPerSecond(); 26 | double GetPreciseSecondsPerTick(); 27 | -------------------------------------------------------------------------------- /Source/Utils/CPUInfo.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020-2024 v0lt, Aleksoid 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include "stdafx.h" 22 | #include 23 | #include "CPUInfo.h" 24 | 25 | 26 | 27 | static int nCPUType = CPUInfo::PROCESSOR_UNKNOWN; 28 | 29 | #ifdef _WIN32 30 | // Windows 31 | #define cpuid(info, x) __cpuidex(info, x, 0) 32 | #else 33 | // GCC Intrinsics 34 | #include 35 | void cpuid(int info[4], int InfoType) { 36 | __cpuid_count(InfoType, 0, info[0], info[1], info[2], info[3]); 37 | } 38 | #endif 39 | 40 | static int GetCPUInfo() 41 | { 42 | // based on 43 | // https://stackoverflow.com/a/7495023 44 | // https://gist.github.com/hi2p-perim/7855506 45 | // https://github.com/FFmpeg/FFmpeg/blob/master/libavutil/x86/cpu.c 46 | 47 | // SSE2 is a basic instruction set for modern compilers and Windows. 48 | // MMX is no longer relevant. 49 | // 3DNow! is not relevant and is not supported by modern processors. 50 | // XOP is not supported by modern processors. 51 | 52 | // SIMD: 128-bit 53 | bool HW_SSE = false; 54 | bool HW_SSE2 = false; 55 | bool HW_SSE3 = false; 56 | bool HW_SSSE3 = false; 57 | bool HW_SSE41 = false; 58 | bool HW_SSE42 = false; 59 | bool HW_SSE4a = false; 60 | bool HW_AES = false; 61 | 62 | // SIMD: 256-bit 63 | bool HW_AVX = false; 64 | bool HW_XOP = false; 65 | bool HW_FMA3 = false; 66 | bool HW_FMA4 = false; 67 | bool HW_AVX2 = false; 68 | 69 | int info[4]; 70 | cpuid(info, 0); 71 | int nIds = info[0]; 72 | 73 | { 74 | __declspec(align(4)) char vendor[0x20] = {}; 75 | *reinterpret_cast(vendor) = info[1]; 76 | *reinterpret_cast(vendor + 4) = info[3]; 77 | *reinterpret_cast(vendor + 8) = info[2]; 78 | 79 | if (strcmp(vendor, "GenuineIntel") == 0) { 80 | nCPUType = CPUInfo::PROCESSOR_INTEL; 81 | } else if (strcmp(vendor, "AuthenticAMD") == 0) { 82 | nCPUType = CPUInfo::PROCESSOR_AMD; 83 | } 84 | } 85 | 86 | cpuid(info, 0x80000000); 87 | unsigned nExIds = info[0]; 88 | 89 | // Detect Features 90 | if (nIds >= 0x00000001) { 91 | cpuid(info, 0x00000001); 92 | HW_SSE = (info[3] & ((int)1 << 25)) != 0; 93 | HW_SSE2 = (info[3] & ((int)1 << 26)) != 0; 94 | HW_SSE3 = (info[2] & ((int)1 << 0)) != 0; 95 | 96 | HW_SSSE3 = (info[2] & ((int)1 << 9)) != 0; 97 | HW_SSE41 = (info[2] & ((int)1 << 19)) != 0; 98 | HW_SSE42 = (info[2] & ((int)1 << 20)) != 0; 99 | HW_AES = (info[2] & ((int)1 << 25)) != 0; 100 | 101 | bool osUsesXSAVE_XRSTORE = (info[2] & ((int)1 << 27)) != 0; 102 | bool cpuAVXSuport = (info[2] & ((int)1 << 28)) != 0; 103 | 104 | if (osUsesXSAVE_XRSTORE && cpuAVXSuport) { 105 | unsigned __int64 xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); 106 | HW_AVX = (xcrFeatureMask & 0x6) == 0x6; 107 | HW_FMA3 = (info[2] & ((int)1 << 12)) != 0; 108 | } 109 | } 110 | if (nIds >= 0x00000007) { 111 | cpuid(info, 0x00000007); 112 | if (HW_AVX) { 113 | HW_AVX2 = (info[1] & ((int)1 << 5)) != 0; 114 | } 115 | } 116 | if (nExIds >= 0x80000001) { 117 | cpuid(info, 0x80000001); 118 | HW_SSE4a = (info[2] & ((int)1 << 6)) != 0; 119 | if (HW_AVX) { 120 | HW_FMA4 = (info[2] & ((int)1 << 16)) != 0; 121 | HW_XOP = (info[2] & ((int)1 << 11)) != 0; 122 | } 123 | } 124 | 125 | int features = 0; 126 | if (HW_SSE) {features |= CPUInfo::CPU_SSE; } 127 | if (HW_SSE2) {features |= CPUInfo::CPU_SSE2; } 128 | if (HW_SSE3) {features |= CPUInfo::CPU_SSE3; } 129 | if (HW_SSSE3) {features |= CPUInfo::CPU_SSSE3;} 130 | if (HW_SSE41) {features |= CPUInfo::CPU_SSE41;} 131 | if (HW_SSE42) {features |= CPUInfo::CPU_SSE42;} 132 | if (HW_AVX) {features |= CPUInfo::CPU_AVX; } 133 | if (HW_AVX2) {features |= CPUInfo::CPU_AVX2; } 134 | 135 | return features; 136 | } 137 | 138 | static const int nCPUFeatures = GetCPUInfo(); 139 | static const bool bSSSE3 = !!(nCPUFeatures & CPUInfo::CPU_SSSE3); 140 | static const bool bSSE41 = !!(nCPUFeatures & CPUInfo::CPU_SSE41); 141 | static const bool bSSE42 = !!(nCPUFeatures & CPUInfo::CPU_SSE42); 142 | static const bool bAVX = !!(nCPUFeatures & CPUInfo::CPU_AVX2); 143 | static const bool bAVX2 = !!(nCPUFeatures & CPUInfo::CPU_AVX2); 144 | 145 | static DWORD GetProcessorNumber() 146 | { 147 | SYSTEM_INFO SystemInfo = { 0 }; 148 | GetSystemInfo(&SystemInfo); 149 | 150 | return SystemInfo.dwNumberOfProcessors; 151 | } 152 | static const DWORD dwNumberOfProcessors = GetProcessorNumber(); 153 | 154 | namespace CPUInfo { 155 | const int GetType() { return nCPUType; } 156 | const int GetFeatures() { return nCPUFeatures; } 157 | const DWORD GetProcessorNumber() { return dwNumberOfProcessors; } 158 | 159 | const bool HaveSSSE3() { return bSSSE3; } 160 | const bool HaveSSE41() { return bSSE41; } 161 | const bool HaveSSE42() { return bSSE42; } 162 | const bool HaveAVX() { return bAVX; } 163 | const bool HaveAVX2() { return bAVX2; } 164 | } // namespace CPUInfo 165 | -------------------------------------------------------------------------------- /Source/Utils/CPUInfo.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020-2024 v0lt, Aleksoid 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | namespace CPUInfo { 24 | enum PROCESSOR_TYPE { 25 | PROCESSOR_UNKNOWN = 0, 26 | PROCESSOR_INTEL, 27 | PROCESSOR_AMD, 28 | }; 29 | 30 | enum PROCESSOR_FEATURES { 31 | CPU_SSE = (1 << 0), 32 | CPU_SSE2 = (1 << 1), 33 | CPU_SSE3 = (1 << 2), 34 | CPU_SSSE3 = (1 << 3), 35 | CPU_SSE41 = (1 << 4), 36 | CPU_SSE42 = (1 << 5), 37 | CPU_AVX = (1 << 6), 38 | CPU_AVX2 = (1 << 7), 39 | }; 40 | 41 | const int GetType(); 42 | const int GetFeatures(); 43 | const DWORD GetProcessorNumber(); 44 | 45 | const bool HaveSSSE3(); 46 | const bool HaveSSE41(); 47 | const bool HaveSSE42(); 48 | const bool HaveAVX(); 49 | const bool HaveAVX2(); 50 | } // namespace CPUInfo 51 | -------------------------------------------------------------------------------- /Source/Utils/StringUtil.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020-2024 v0lt, Aleksoid 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #include "stdafx.h" 22 | #include 23 | #include "StringUtil.h" 24 | 25 | void str_split(const std::string& str, std::vector& tokens, char delim) 26 | { 27 | std::istringstream iss(str); 28 | std::string tmp; 29 | while (std::getline(iss, tmp, delim)) { 30 | if (tmp.size()) { 31 | tokens.push_back(tmp); 32 | } 33 | } 34 | } 35 | 36 | void str_split(const std::wstring& wstr, std::vector& tokens, wchar_t delim) 37 | { 38 | std::wistringstream iss(wstr); 39 | std::wstring tmp; 40 | while (std::getline(iss, tmp, delim)) { 41 | if (tmp.size()) { 42 | tokens.push_back(tmp); 43 | } 44 | } 45 | } 46 | 47 | void str_replace(std::string& s, const std::string_view from, const std::string_view to) 48 | { 49 | std::string str; 50 | size_t pos = 0; 51 | size_t pf = 0; 52 | while ((pf = s.find(from, pos)) < s.size()) { 53 | str.append(s, pos, pf - pos); 54 | str.append(to); 55 | pos = pf + from.size(); 56 | } 57 | if (str.size()) { 58 | str.append(s, pos); 59 | s = str; 60 | } 61 | } 62 | 63 | void str_replace(std::wstring& s, const std::wstring_view from, const std::wstring_view to) 64 | { 65 | std::wstring str; 66 | size_t pos = 0; 67 | size_t pf = 0; 68 | while ((pf = s.find(from, pos)) < s.size()) { 69 | str.append(s, pos, pf - pos); 70 | str.append(to); 71 | pos = pf + from.size(); 72 | } 73 | if (str.size()) { 74 | str.append(s, pos); 75 | s = str; 76 | } 77 | } 78 | 79 | // 80 | // converting strings of different formats 81 | // 82 | 83 | std::wstring ConvertAnsiToWide(const std::string_view sv) 84 | { 85 | int count = MultiByteToWideChar(CP_ACP, 0, sv.data(), (int)sv.length(), nullptr, 0); 86 | std::wstring wstr(count, 0); 87 | MultiByteToWideChar(CP_ACP, 0, sv.data(), (int)sv.length(), &wstr[0], count); 88 | return wstr; 89 | } 90 | 91 | std::wstring ConvertUtf8ToWide(const std::string_view sv) 92 | { 93 | int count = MultiByteToWideChar(CP_UTF8, 0, sv.data(), (int)sv.length(), nullptr, 0); 94 | std::wstring wstr(count, 0); 95 | MultiByteToWideChar(CP_UTF8, 0, sv.data(), (int)sv.length(), &wstr[0], count); 96 | return wstr; 97 | } 98 | 99 | std::string ConvertWideToANSI(const std::wstring_view wsv) 100 | { 101 | int count = WideCharToMultiByte(CP_ACP, 0, wsv.data(), (int)wsv.length(), nullptr, 0, nullptr, nullptr); 102 | std::string str(count, 0); 103 | WideCharToMultiByte(CP_ACP, 0, wsv.data(), -1, &str[0], count, nullptr, nullptr); 104 | return str; 105 | } 106 | 107 | std::string ConvertWideToUtf8(const std::wstring_view wsv) 108 | { 109 | int count = WideCharToMultiByte(CP_UTF8, 0, wsv.data(), (int)wsv.length(), nullptr, 0, nullptr, nullptr); 110 | std::string str(count, 0); 111 | WideCharToMultiByte(CP_UTF8, 0, wsv.data(), -1, &str[0], count, nullptr, nullptr); 112 | return str; 113 | } 114 | -------------------------------------------------------------------------------- /Source/Utils/StringUtil.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020-2024 v0lt, Aleksoid 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | 26 | // 27 | // convert string to lower or upper case 28 | // 29 | 30 | inline void str_tolower(std::string& s) 31 | { 32 | std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return std::tolower(c); } ); 33 | // char for std::tolower should be converted to unsigned char 34 | } 35 | 36 | inline void str_toupper(std::string& s) 37 | { 38 | std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return std::toupper(c); } ); 39 | // char for std::toupper should be converted to unsigned char 40 | } 41 | 42 | inline void str_tolower(std::wstring& s) 43 | { 44 | std::transform(s.begin(), s.end(), s.begin(), ::tolower); 45 | } 46 | 47 | inline void str_toupper(std::wstring& s) 48 | { 49 | std::transform(s.begin(), s.end(), s.begin(), ::toupper); 50 | } 51 | 52 | inline void str_tolower_all(std::wstring& s) 53 | { 54 | const std::ctype& f = std::use_facet>(std::locale()); 55 | std::ignore = f.tolower(&s[0], &s[0] + s.size()); 56 | } 57 | 58 | inline void str_toupper_all(std::wstring& s) 59 | { 60 | const std::ctype& f = std::use_facet>(std::locale()); 61 | std::ignore = f.toupper(&s[0], &s[0] + s.size()); 62 | } 63 | 64 | // 65 | // split a string using char delimiter 66 | // 67 | 68 | void str_split(const std::string& str, std::vector& tokens, char delim); 69 | 70 | void str_split(const std::wstring& wstr, std::vector& tokens, wchar_t delim); 71 | 72 | // 73 | // trimming whitespace 74 | // 75 | 76 | inline std::string str_trim(const std::string_view sv) 77 | { 78 | auto sfront = std::find_if_not(sv.begin(), sv.end(), [](int c) {return isspace(c); }); 79 | auto sback = std::find_if_not(sv.rbegin(), sv.rend(), [](int c) {return isspace(c); }).base(); 80 | return (sback <= sfront ? std::string() : std::string(sfront, sback)); 81 | } 82 | 83 | inline std::wstring str_trim(const std::wstring_view sv) 84 | { 85 | auto sfront = std::find_if_not(sv.begin(), sv.end(), [](int c) {return iswspace(c); }); 86 | auto sback = std::find_if_not(sv.rbegin(), sv.rend(), [](int c) {return iswspace(c); }).base(); 87 | return (sback <= sfront ? std::wstring() : std::wstring(sfront, sback)); 88 | } 89 | 90 | // 91 | // trimming a character at the end 92 | // 93 | 94 | inline void str_trim_end(std::string& s, const char ch) 95 | { 96 | s.erase(s.find_last_not_of(ch) + 1); 97 | } 98 | 99 | inline void str_trim_end(std::wstring& s, const wchar_t ch) 100 | { 101 | s.erase(s.find_last_not_of(ch) + 1); 102 | } 103 | 104 | // 105 | // truncate after a null character 106 | // 107 | 108 | inline void str_truncate_after_null(std::string& s) 109 | { 110 | s.erase(std::find(s.begin(), s.end(), '\0'), s.end()); 111 | } 112 | 113 | inline void str_truncate_after_null(std::wstring& s) 114 | { 115 | s.erase(std::find(s.begin(), s.end(), '\0'), s.end()); 116 | } 117 | 118 | // 119 | // replace substring 120 | // 121 | 122 | void str_replace(std::string& s, const std::string_view from, const std::string_view to); 123 | void str_replace(std::wstring& s, const std::wstring_view from, const std::wstring_view to); 124 | 125 | // 126 | // simple convert ANSI string to wide character string 127 | // 128 | 129 | inline std::wstring A2WStr(const std::string_view sv) 130 | { 131 | return std::wstring(sv.begin(), sv.end()); 132 | } 133 | 134 | // 135 | // converting strings of different formats 136 | // 137 | 138 | std::wstring ConvertAnsiToWide(const std::string_view sv); 139 | 140 | std::wstring ConvertUtf8ToWide(const std::string_view sv); 141 | 142 | std::string ConvertWideToANSI(const std::wstring_view wsv); 143 | 144 | std::string ConvertWideToUtf8(const std::wstring_view wsv); 145 | -------------------------------------------------------------------------------- /Source/Utils/Util.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020-2024 v0lt, Aleksoid 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #pragma once 22 | 23 | #ifndef FCC 24 | #define FCC(ch4) ((((DWORD)(ch4) & 0xFF) << 24) | \ 25 | (((DWORD)(ch4) & 0xFF00) << 8) | \ 26 | (((DWORD)(ch4) & 0xFF0000) >> 8) | \ 27 | (((DWORD)(ch4) & 0xFF000000) >> 24)) 28 | #endif 29 | 30 | #ifndef DEFINE_MEDIATYPE_GUID 31 | #define DEFINE_MEDIATYPE_GUID(name, format) \ 32 | DEFINE_GUID(name, \ 33 | format, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 34 | #endif 35 | 36 | template 37 | inline void DebugLogFmt(std::wstring_view format, Args&& ...args) 38 | { 39 | DbgLogInfo(LOG_TRACE, 3, std::vformat(format, std::make_wformat_args(args...)).c_str()); 40 | } 41 | 42 | #ifdef _DEBUG 43 | #define DLog(...) DebugLogFmt(__VA_ARGS__) 44 | #define DLogIf(f,...) {if (f) DebugLogFmt(__VA_ARGS__);} 45 | #else 46 | #define DLog(...) __noop 47 | #define DLogIf(f,...) __noop 48 | #endif 49 | 50 | #define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = nullptr; } } 51 | #define SAFE_CLOSE_HANDLE(p) { if (p) { if ((p) != INVALID_HANDLE_VALUE) ASSERT(CloseHandle(p)); (p) = nullptr; } } 52 | #define SAFE_DELETE(p) { if (p) { delete (p); (p) = nullptr; } } 53 | 54 | #define QI(i) (riid == __uuidof(i)) ? GetInterface((i*)this, ppv) : 55 | #define IFQIRETURN(i) if (riid == __uuidof(i)) { return GetInterface((i*)this, ppv); } 56 | 57 | #define ALIGN(x, a) __ALIGN_MASK(x,(decltype(x))(a)-1) 58 | #define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) 59 | 60 | // Media subtypes 61 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y8, 0x20203859); 62 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y800, 0x30303859); 63 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y16, 0x10003159); // Y1[0][16] 64 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_YV16, 0x36315659); 65 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_YV24, 0x34325659); 66 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_I420, 0x30323449); // from "wmcodecdsp.h" 67 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y42B, 0x42323459); 68 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_444P, 0x50343434); 69 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y210, 0x30313259); 70 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y216, 0x36313259); 71 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y410, 0x30313459); 72 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y416, 0x36313459); 73 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_YUV444P16, 0x10003359); // Y3[0][16] 74 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_RGB48, 0x30424752); // RGB[48] (RGB0) 75 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_BGR48, 0x30524742); // BGR[48] (BGR0) 76 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_BGRA64, 0x40415242); // BRA[64] (BRA@) 77 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_b48r, 0x72383462); 78 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_b64a, 0x61343662); 79 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_r210, 0x30313272); 80 | DEFINE_GUID(MEDIASUBTYPE_LAV_RAWVIDEO, 0xd80fa03c, 0x35c1, 0x4fa1, 0x8c, 0x8e, 0x37, 0x5c, 0x86, 0x67, 0x16, 0x6e); 81 | 82 | // non-standard values for Transfer Matrix 83 | #define VIDEOTRANSFERMATRIX_FCC 6 84 | #define VIDEOTRANSFERMATRIX_YCgCo 7 85 | 86 | template 87 | // If the specified value is out of range, set to default values. 88 | inline T discard(T const& val, T const& def, T const& lo, T const& hi) 89 | { 90 | return (val > hi || val < lo) ? def : val; 91 | } 92 | 93 | template 94 | inline T round_pow2(T number, T pow2) 95 | { 96 | ASSERT(pow2 > 0); 97 | ASSERT(!(pow2 & (pow2 - 1))); 98 | --pow2; 99 | if (number < 0) { 100 | return (number - pow2) & ~pow2; 101 | } else { 102 | return (number + pow2) & ~pow2; 103 | } 104 | } 105 | 106 | [[nodiscard]] bool IsWindows11_24H2OrGreater(); 107 | LPCWSTR GetWindowsVersion(); 108 | 109 | inline std::wstring GUIDtoWString(const GUID& guid) 110 | { 111 | std::wstring str(39, 0); 112 | int ret = StringFromGUID2(guid, &str[0], 39); 113 | if (ret) { 114 | str.resize(ret - 1); 115 | } else { 116 | str.clear(); 117 | } 118 | return str; 119 | } 120 | 121 | std::wstring HR2Str(const HRESULT hr); 122 | 123 | HRESULT GetDataFromResource(LPVOID& data, DWORD& size, UINT resid); 124 | 125 | // Usage: SetThreadName ((DWORD)-1, "MainThread"); 126 | void SetThreadName(DWORD dwThreadID, const char* threadName); 127 | -------------------------------------------------------------------------------- /Source/Utils/gpu_memcpy_sse4.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2019 Hendrik Leppkes 3 | * http://www.1f0.de 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 | * 19 | * Taken from the QuickSync decoder by Eric Gur 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | // gpu_memcpy is a memcpy style function that copied data very fast from a 26 | // GPU tiled memory (write back) 27 | // Performance tip: page offset (12 lsb) of both addresses should be different 28 | // optimally use a 2K offset between them. 29 | inline void *gpu_memcpy(void *d, const void *s, size_t size) 30 | { 31 | static const size_t regsInLoop = sizeof(size_t) * 2; // 8 or 16 32 | 33 | if (d == nullptr || s == nullptr) 34 | return nullptr; 35 | 36 | // If memory is not aligned, use memcpy 37 | bool isAligned = (((size_t)(s) | (size_t)(d)) & 0xF) == 0; 38 | if (!isAligned) 39 | { 40 | return memcpy(d, s, size); 41 | } 42 | 43 | __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7; 44 | #ifdef _M_X64 45 | __m128i xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15; 46 | #endif 47 | 48 | size_t remainder = size & (regsInLoop * sizeof(xmm0) - 1); // Copy 128 or 256 bytes every loop 49 | size_t end = 0; 50 | 51 | __m128i *pTrg = (__m128i *)d; 52 | __m128i *pTrgEnd = pTrg + ((size - remainder) >> 4); 53 | __m128i *pSrc = (__m128i *)s; 54 | 55 | // Make sure source is synced - doesn't hurt if not needed. 56 | _mm_sfence(); 57 | 58 | while (pTrg < pTrgEnd) 59 | { 60 | // _mm_stream_load_si128 emits the Streaming SIMD Extensions 4 (SSE4.1) instruction MOVNTDQA 61 | // Fastest method for copying GPU RAM. Available since Penryn (45nm Core 2 Duo/Quad) 62 | xmm0 = _mm_stream_load_si128(pSrc); 63 | xmm1 = _mm_stream_load_si128(pSrc + 1); 64 | xmm2 = _mm_stream_load_si128(pSrc + 2); 65 | xmm3 = _mm_stream_load_si128(pSrc + 3); 66 | xmm4 = _mm_stream_load_si128(pSrc + 4); 67 | xmm5 = _mm_stream_load_si128(pSrc + 5); 68 | xmm6 = _mm_stream_load_si128(pSrc + 6); 69 | xmm7 = _mm_stream_load_si128(pSrc + 7); 70 | #ifdef _M_X64 // Use all 16 xmm registers 71 | xmm8 = _mm_stream_load_si128(pSrc + 8); 72 | xmm9 = _mm_stream_load_si128(pSrc + 9); 73 | xmm10 = _mm_stream_load_si128(pSrc + 10); 74 | xmm11 = _mm_stream_load_si128(pSrc + 11); 75 | xmm12 = _mm_stream_load_si128(pSrc + 12); 76 | xmm13 = _mm_stream_load_si128(pSrc + 13); 77 | xmm14 = _mm_stream_load_si128(pSrc + 14); 78 | xmm15 = _mm_stream_load_si128(pSrc + 15); 79 | #endif 80 | 81 | _ReadWriteBarrier(); 82 | 83 | // _mm_store_si128 emit the SSE2 intruction MOVDQA (aligned store) 84 | _mm_store_si128(pTrg, xmm0); 85 | _mm_store_si128(pTrg + 1, xmm1); 86 | _mm_store_si128(pTrg + 2, xmm2); 87 | _mm_store_si128(pTrg + 3, xmm3); 88 | _mm_store_si128(pTrg + 4, xmm4); 89 | _mm_store_si128(pTrg + 5, xmm5); 90 | _mm_store_si128(pTrg + 6, xmm6); 91 | _mm_store_si128(pTrg + 7, xmm7); 92 | #ifdef _M_X64 // Use all 16 xmm registers 93 | _mm_store_si128(pTrg + 8, xmm8); 94 | _mm_store_si128(pTrg + 9, xmm9); 95 | _mm_store_si128(pTrg + 10, xmm10); 96 | _mm_store_si128(pTrg + 11, xmm11); 97 | _mm_store_si128(pTrg + 12, xmm12); 98 | _mm_store_si128(pTrg + 13, xmm13); 99 | _mm_store_si128(pTrg + 14, xmm14); 100 | _mm_store_si128(pTrg + 15, xmm15); 101 | #endif 102 | pSrc += regsInLoop; 103 | pTrg += regsInLoop; 104 | } 105 | 106 | // Copy in 16 byte steps 107 | if (remainder >= 16) 108 | { 109 | size = remainder; 110 | remainder = size & 15; 111 | end = size >> 4; 112 | for (size_t i = 0; i < end; ++i) 113 | { 114 | pTrg[i] = _mm_stream_load_si128(pSrc + i); 115 | } 116 | } 117 | 118 | // Copy last bytes - shouldn't happen as strides are modulu 16 119 | if (remainder) 120 | { 121 | __m128i temp = _mm_stream_load_si128(pSrc + end); 122 | 123 | char *ps = (char *)(&temp); 124 | char *pt = (char *)(pTrg + end); 125 | 126 | for (size_t i = 0; i < remainder; ++i) 127 | { 128 | pt[i] = ps[i]; 129 | } 130 | } 131 | 132 | return d; 133 | } 134 | -------------------------------------------------------------------------------- /Source/VideoRendererInputPin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2018-2025 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | #include 26 | #include "../Include/ID3DVideoMemoryConfiguration.h" 27 | 28 | class CMpcVideoRenderer; 29 | class CCustomAllocator; 30 | 31 | class CVideoRendererInputPin 32 | : public CRendererInputPin 33 | , public IMFGetService 34 | , public IDirectXVideoMemoryConfiguration 35 | , public ID3D11DecoderConfiguration 36 | { 37 | private: 38 | friend class CCustomAllocator; 39 | 40 | CMpcVideoRenderer* m_pBaseRenderer; 41 | bool m_bDXVA = false; 42 | bool m_bD3D11 = false; 43 | 44 | CCustomAllocator* m_pCustomAllocator = nullptr; 45 | std::unique_ptr m_pNewMT; 46 | 47 | CCritSec m_csReceive; 48 | 49 | public: 50 | CVideoRendererInputPin(CBaseRenderer *pRenderer, HRESULT *phr, LPCWSTR Name, CMpcVideoRenderer* pBaseRenderer); 51 | ~CVideoRendererInputPin() = default; 52 | 53 | bool FrameInVideoMem() { return m_bDXVA || m_bD3D11; } 54 | 55 | // CUnknown 56 | DECLARE_IUNKNOWN 57 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv); 58 | 59 | // CBaseInputPin 60 | STDMETHODIMP GetAllocator(IMemAllocator **ppAllocator); 61 | STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES* pProps); 62 | STDMETHODIMP ReceiveConnection(IPin* pConnector, const AM_MEDIA_TYPE* pmt); 63 | 64 | STDMETHODIMP NewSegment(REFERENCE_TIME startTime, REFERENCE_TIME stopTime, double rate) override; 65 | STDMETHODIMP BeginFlush() override; 66 | 67 | // IMFGetService 68 | STDMETHODIMP GetService(REFGUID guidService, REFIID riid, LPVOID *ppvObject); 69 | 70 | // IDirectXVideoMemoryConfiguration 71 | STDMETHODIMP GetAvailableSurfaceTypeByIndex(DWORD dwTypeIndex, DXVA2_SurfaceType *pdwType); 72 | STDMETHODIMP SetSurfaceType(DXVA2_SurfaceType dwType); 73 | 74 | // ID3D11DecoderConfiguration 75 | STDMETHODIMP ActivateD3D11Decoding(ID3D11Device *pDevice, ID3D11DeviceContext *pContext, HANDLE hMutex, UINT nFlags); 76 | UINT STDMETHODCALLTYPE GetD3D11AdapterIndex(); 77 | 78 | void SetNewMediaType(const CMediaType& mt); 79 | void ClearNewMediaType(); 80 | }; 81 | -------------------------------------------------------------------------------- /Source/csputils.h: -------------------------------------------------------------------------------- 1 | // Used code from project mpv 2 | // https://github.com/mpv-player/mpv/blob/master/video/csputils.h 3 | 4 | #pragma once 5 | 6 | /* NOTE: the csp and levels AUTO values are converted to specific ones 7 | * above vf/vo level. At least vf_scale relies on all valid settings being 8 | * nonzero at vf/vo level. 9 | */ 10 | 11 | enum mp_csp { 12 | MP_CSP_AUTO, 13 | MP_CSP_BT_601, 14 | MP_CSP_BT_709, 15 | MP_CSP_SMPTE_240M, 16 | MP_CSP_BT_2020_NC, 17 | MP_CSP_BT_2020_C, 18 | MP_CSP_RGB, 19 | MP_CSP_XYZ, 20 | MP_CSP_YCGCO, 21 | MP_CSP_COUNT 22 | }; 23 | 24 | enum mp_csp_levels { 25 | MP_CSP_LEVELS_AUTO, 26 | MP_CSP_LEVELS_TV, 27 | MP_CSP_LEVELS_PC, 28 | MP_CSP_LEVELS_COUNT, 29 | }; 30 | 31 | enum mp_csp_prim { 32 | MP_CSP_PRIM_AUTO, 33 | MP_CSP_PRIM_BT_601_525, 34 | MP_CSP_PRIM_BT_601_625, 35 | MP_CSP_PRIM_BT_709, 36 | MP_CSP_PRIM_BT_2020, 37 | MP_CSP_PRIM_BT_470M, 38 | MP_CSP_PRIM_APPLE, 39 | MP_CSP_PRIM_ADOBE, 40 | MP_CSP_PRIM_PRO_PHOTO, 41 | MP_CSP_PRIM_CIE_1931, 42 | MP_CSP_PRIM_DCI_P3, 43 | MP_CSP_PRIM_DISPLAY_P3, 44 | MP_CSP_PRIM_V_GAMUT, 45 | MP_CSP_PRIM_S_GAMUT, 46 | MP_CSP_PRIM_EBU_3213, 47 | MP_CSP_PRIM_FILM_C, 48 | MP_CSP_PRIM_ACES_AP0, 49 | MP_CSP_PRIM_ACES_AP1, 50 | MP_CSP_PRIM_COUNT 51 | }; 52 | 53 | enum mp_csp_trc { 54 | MP_CSP_TRC_AUTO, 55 | MP_CSP_TRC_BT_1886, 56 | MP_CSP_TRC_SRGB, 57 | MP_CSP_TRC_LINEAR, 58 | MP_CSP_TRC_GAMMA18, 59 | MP_CSP_TRC_GAMMA20, 60 | MP_CSP_TRC_GAMMA22, 61 | MP_CSP_TRC_GAMMA24, 62 | MP_CSP_TRC_GAMMA26, 63 | MP_CSP_TRC_GAMMA28, 64 | MP_CSP_TRC_PRO_PHOTO, 65 | MP_CSP_TRC_PQ, 66 | MP_CSP_TRC_HLG, 67 | MP_CSP_TRC_V_LOG, 68 | MP_CSP_TRC_S_LOG1, 69 | MP_CSP_TRC_S_LOG2, 70 | MP_CSP_TRC_ST428, 71 | MP_CSP_TRC_COUNT 72 | }; 73 | 74 | enum mp_csp_light { 75 | MP_CSP_LIGHT_AUTO, 76 | MP_CSP_LIGHT_DISPLAY, 77 | MP_CSP_LIGHT_SCENE_HLG, 78 | MP_CSP_LIGHT_SCENE_709_1886, 79 | MP_CSP_LIGHT_SCENE_1_2, 80 | MP_CSP_LIGHT_COUNT 81 | }; 82 | 83 | // These constants are based on the ICC specification (Table 23) and match 84 | // up with the API of LittleCMS, which treats them as integers. 85 | enum mp_render_intent { 86 | MP_INTENT_PERCEPTUAL = 0, 87 | MP_INTENT_RELATIVE_COLORIMETRIC = 1, 88 | MP_INTENT_SATURATION = 2, 89 | MP_INTENT_ABSOLUTE_COLORIMETRIC = 3 90 | }; 91 | 92 | struct mp_colorspace { 93 | enum mp_csp space; 94 | enum mp_csp_levels levels; 95 | enum mp_csp_prim primaries; 96 | enum mp_csp_trc gamma; 97 | enum mp_csp_light light; 98 | //struct pl_hdr_metadata hdr; 99 | }; 100 | 101 | // For many colorspace conversions, in particular those involving HDR, an 102 | // implicit reference white level is needed. Since this magic constant shows up 103 | // a lot, give it an explicit name. The value of 203 cd/m^2 comes from ITU-R 104 | // Report BT.2408, and the value for HLG comes from the cited HLG 75% level 105 | // (transferred to scene space). 106 | #define MP_REF_WHITE 203.0 107 | #define MP_REF_WHITE_HLG 3.17955 108 | 109 | struct mp_csp_params { 110 | struct mp_colorspace color = {MP_CSP_BT_709, MP_CSP_LEVELS_TV}; // input colorspace 111 | enum mp_csp_levels levels_out = MP_CSP_LEVELS_PC; // output device 112 | float brightness = 0; // -1..0..1 113 | float contrast = 1; // 0..1..2 114 | float hue = 0; // -pi..0..pi 115 | float saturation = 1; // 0..1..2 116 | float gamma = 1; // 0.125..1..8 117 | // discard U/V components 118 | bool gray = false; 119 | // input is already centered and range-expanded 120 | bool is_float = false;; 121 | // texture_bits/input_bits is for rescaling fixed point input to range [0,1] 122 | int texture_bits = 8; 123 | int input_bits = 8; 124 | }; 125 | 126 | struct mp_csp_col_xy { 127 | float x, y; 128 | }; 129 | 130 | static inline float mp_xy_X(struct mp_csp_col_xy xy) { 131 | return xy.x / xy.y; 132 | } 133 | 134 | static inline float mp_xy_Z(struct mp_csp_col_xy xy) { 135 | return (1 - xy.x - xy.y) / xy.y; 136 | } 137 | 138 | struct mp_csp_primaries { 139 | struct mp_csp_col_xy red, green, blue, white; 140 | }; 141 | 142 | struct mp_csp_primaries mp_get_csp_primaries(enum mp_csp_prim csp); 143 | float mp_trc_nom_peak(enum mp_csp_trc trc); 144 | bool mp_trc_is_hdr(enum mp_csp_trc trc); 145 | 146 | /* Color conversion matrix: RGB = m * YUV + c 147 | * m is in row-major matrix, with m[row][col], e.g.: 148 | * [ a11 a12 a13 ] float m[3][3] = { { a11, a12, a13 }, 149 | * [ a21 a22 a23 ] { a21, a22, a23 }, 150 | * [ a31 a32 a33 ] { a31, a32, a33 } }; 151 | * This is accessed as e.g.: m[2-1][1-1] = a21 152 | * In particular, each row contains all the coefficients for one of R, G, B, 153 | * while each column contains all the coefficients for one of Y, U, V: 154 | * m[r,g,b][y,u,v] = ... 155 | * The matrix could also be viewed as group of 3 vectors, e.g. the 1st column 156 | * is the Y vector (1, 1, 1), the 2nd is the U vector, the 3rd the V vector. 157 | * The matrix might also be used for other conversions and colorspaces. 158 | */ 159 | struct mp_cmat { 160 | float m[3][3]; 161 | float c[3]; 162 | }; 163 | 164 | void mp_get_rgb2xyz_matrix(struct mp_csp_primaries space, float m[3][3]); 165 | 166 | double mp_get_csp_mul(enum mp_csp csp, int input_bits, int texture_bits); 167 | void mp_get_csp_matrix(struct mp_csp_params *params, struct mp_cmat *out); 168 | 169 | void mp_invert_matrix3x3(float m[3][3]); 170 | void mp_invert_cmat(struct mp_cmat *out, struct mp_cmat *in); 171 | 172 | 173 | ///////////////////// 174 | // additional code // 175 | ///////////////////// 176 | void mul_matrix3x3(float(&c)[3][3], const float(&a)[3][3], const float(&b)[3][3]); 177 | void transpose_matrix3x3(float(&t)[3][3], const float(&m)[3][3]); 178 | 179 | void GetColorspaceGamutConversionMatrix(float matrix[3][3], mp_csp_prim csp_in, mp_csp_prim csp_out); 180 | -------------------------------------------------------------------------------- /Source/dllmain.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2018-2023 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #include "stdafx.h" 22 | #include 23 | #include "VideoRenderer.h" 24 | #include "PropPage.h" 25 | 26 | #include "../external/minhook/include/MinHook.h" 27 | 28 | template 29 | static CUnknown* WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT* phr) 30 | { 31 | *phr = S_OK; 32 | CUnknown* punk = new(std::nothrow) T(lpunk, phr); 33 | if (punk == nullptr) { 34 | *phr = E_OUTOFMEMORY; 35 | } 36 | return punk; 37 | } 38 | 39 | const AMOVIESETUP_PIN sudpPins[] = { 40 | {(LPWSTR)L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, nullptr, (UINT)std::size(sudPinTypesIn), sudPinTypesIn}, 41 | }; 42 | 43 | const AMOVIESETUP_FILTER sudFilter[] = { 44 | {&__uuidof(CMpcVideoRenderer), L"MPC Video Renderer", MERIT_DO_NOT_USE, (UINT)std::size(sudpPins), sudpPins, CLSID_LegacyAmFilterCategory}, 45 | }; 46 | 47 | CFactoryTemplate g_Templates[] = { 48 | {sudFilter[0].strName, &__uuidof(CMpcVideoRenderer), CreateInstance, nullptr, &sudFilter[0]}, 49 | {L"MainProp", &__uuidof(CVRMainPPage), CreateInstance, nullptr, nullptr}, 50 | {L"InfoProp", &__uuidof(CVRInfoPPage), CreateInstance, nullptr, nullptr} 51 | }; 52 | 53 | int g_cTemplates = (int)std::size(g_Templates); 54 | 55 | STDAPI DllRegisterServer() 56 | { 57 | return AMovieDllRegisterServer2(TRUE); 58 | } 59 | 60 | STDAPI DllUnregisterServer() 61 | { 62 | return AMovieDllRegisterServer2(FALSE); 63 | } 64 | 65 | extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID); 66 | 67 | BOOL WINAPI DllMain(HINSTANCE hDllHandle, DWORD dwReason, LPVOID pReserved) 68 | { 69 | switch (dwReason) { 70 | case DLL_PROCESS_ATTACH: 71 | MH_Initialize(); 72 | break; 73 | case DLL_PROCESS_DETACH: 74 | MH_Uninitialize(); 75 | break; 76 | } 77 | return DllEntryPoint(hDllHandle, dwReason, pReserved); 78 | } 79 | 80 | void CALLBACK OpenConfiguration(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) 81 | { 82 | HRESULT hr = S_OK; 83 | CUnknown *pInstance = CreateInstance(nullptr, &hr); 84 | IBaseFilter *pFilter = nullptr; 85 | pInstance->NonDelegatingQueryInterface(IID_IBaseFilter, (void **)&pFilter); 86 | if (pFilter) { 87 | pFilter->AddRef(); 88 | 89 | hr = CoInitialize(nullptr); 90 | 91 | // Get PropertyPages interface 92 | ISpecifyPropertyPages *pProp = nullptr; 93 | hr = pFilter->QueryInterface(&pProp); 94 | if (SUCCEEDED(hr) && pProp) 95 | { 96 | // Get the filter's name and IUnknown pointer. 97 | FILTER_INFO FilterInfo; 98 | hr = pFilter->QueryFilterInfo(&FilterInfo); 99 | // We don't need the graph, so don't sit on a ref to it 100 | if (FilterInfo.pGraph) 101 | FilterInfo.pGraph->Release(); 102 | 103 | IUnknown *pFilterUnk = nullptr; 104 | pFilter->QueryInterface(&pFilterUnk); 105 | 106 | // Show the page. 107 | CAUUID caGUID; 108 | pProp->GetPages(&caGUID); 109 | pProp->Release(); 110 | hr = OleCreatePropertyFrame( 111 | nullptr, // Parent window 112 | 0, 0, // Reserved 113 | FilterInfo.achName, // Caption for the dialog box 114 | 1, // Number of objects (just the filter) 115 | &pFilterUnk, // Array of object pointers. 116 | caGUID.cElems, // Number of property pages 117 | caGUID.pElems, // Array of property page CLSIDs 118 | 0, // Locale identifier 119 | 0, nullptr // Reserved 120 | ); 121 | 122 | // Clean up. 123 | pFilterUnk->Release(); 124 | CoTaskMemFree(caGUID.pElems); 125 | 126 | hr = S_OK; 127 | } 128 | CoUninitialize(); 129 | } 130 | delete pInstance; 131 | } 132 | -------------------------------------------------------------------------------- /Source/res/dither32x32float16.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aleksoid1978/VideoRenderer/b5a8725c3d56aaf3dce5c5e0408e622f6406c4d8/Source/res/dither32x32float16.bin -------------------------------------------------------------------------------- /Source/stdafx.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2018-2021 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #include "stdafx.h" 22 | 23 | #pragma comment(lib, "winmm.lib") 24 | #pragma comment(lib, "d3d9.lib") 25 | #pragma comment(lib, "dxva2.lib") 26 | #pragma comment(lib, "d2d1.lib") 27 | #pragma comment(lib, "dwrite.lib") 28 | #pragma comment(lib, "windowscodecs.lib") 29 | #pragma comment(lib, "dxgi.lib") 30 | #pragma comment(lib, "d3d11.lib") 31 | 32 | //#pragma comment(lib, "dwmapi.lib") 33 | -------------------------------------------------------------------------------- /Source/stdafx.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2018-2023 see Authors.txt 3 | * 4 | * This file is part of MPC-BE. 5 | * 6 | * MPC-BE is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * MPC-BE is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | */ 20 | 21 | #pragma once 22 | // support Visual Styles 6.0 23 | #pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 24 | 25 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 26 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers 27 | 28 | #ifdef _DEBUG 29 | #define D3D_DEBUG_INFO 30 | #endif 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #include "../external/BaseClasses/streams.h" 49 | -------------------------------------------------------------------------------- /common.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)_bin\obj\$(Configuration)_$(PlatformShortName)\$(ProjectName)\ 5 | $(SolutionDir)_bin\lib\$(Configuration)_$(PlatformShortName)\ 6 | $(SolutionDir)_bin\Filter_$(PlatformShortName)_Debug\ 7 | $(SolutionDir)_bin\Filter_$(PlatformShortName)\ 8 | true 9 | false 10 | 11 | 12 | 13 | /Zo /Zc:throwingNew /Zc:rvalueCast %(AdditionalOptions) 14 | true 15 | 4244; 4838; 26451; 26812 16 | 4267;%(DisableSpecificWarnings) 17 | Sync 18 | true 19 | stdcpp20 20 | true 21 | _WINDOWS;WINDOWS;WINVER=0x0601;_WIN32_WINNT=0x0601;_USRDLL;__STDC_CONSTANT_MACROS;%(PreprocessorDefinitions) 22 | NOMINMAX;%(PreprocessorDefinitions) 23 | WIN32;%(PreprocessorDefinitions) 24 | _WIN64;WIN64;%(PreprocessorDefinitions) 25 | Level3 26 | 27 | 28 | MachineX86 29 | MachineX64 30 | 31 | 32 | true 33 | Debug 34 | true 35 | Windows 36 | MachineX86 37 | MachineX64 38 | 39 | 40 | 0x0409 41 | WIN32;%(PreprocessorDefinitions) 42 | _WIN64;%(PreprocessorDefinitions) 43 | 44 | 45 | 46 | 47 | EnableFastChecks 48 | EditAndContinue 49 | ProgramDatabase 50 | Disabled 51 | MultiThreadedDebug 52 | 53 | 54 | _DEBUG;%(PreprocessorDefinitions) 55 | 56 | 57 | false 58 | DebugFastLink 59 | 60 | 61 | 62 | 63 | /Zc:inline %(AdditionalOptions) 64 | ProgramDatabase 65 | AnySuitable 66 | true 67 | Speed 68 | false 69 | MaxSpeed 70 | _CRT_SECURE_NO_WARNINGS;NDEBUG;%(PreprocessorDefinitions) 71 | MultiThreaded 72 | true 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | true 80 | true 81 | UseFastLinkTimeCodeGeneration 82 | .rdata=.text 83 | true 84 | true 85 | 86 | 87 | NDEBUG;%(PreprocessorDefinitions) 88 | 89 | 90 | -------------------------------------------------------------------------------- /distrib/Install_MPCVR_32.cmd: -------------------------------------------------------------------------------- 1 | @cd /d "%~dp0" 2 | @regsvr32.exe MpcVideoRenderer.ax /s 3 | @if %errorlevel% NEQ 0 goto error 4 | :success 5 | @echo. 6 | @echo. 7 | @echo Installation succeeded. 8 | @echo. 9 | @echo Please do not delete the MpcVideoRenderer.ax file. 10 | @echo The installer has not copied the files anywhere. 11 | @echo. 12 | @goto done 13 | :error 14 | @echo. 15 | @echo. 16 | @echo Installation failed. 17 | @echo. 18 | @echo You need to right click "Install_MPCVR_32.cmd" and choose "run as admin". 19 | @echo. 20 | :done 21 | @pause >NUL 22 | -------------------------------------------------------------------------------- /distrib/Install_MPCVR_64.cmd: -------------------------------------------------------------------------------- 1 | @cd /d "%~dp0" 2 | @regsvr32.exe MpcVideoRenderer64.ax /s 3 | @if %errorlevel% NEQ 0 goto error 4 | :success 5 | @echo. 6 | @echo. 7 | @echo Installation succeeded. 8 | @echo. 9 | @echo Please do not delete the MpcVideoRenderer64.ax file. 10 | @echo The installer has not copied the files anywhere. 11 | @echo. 12 | @goto done 13 | :error 14 | @echo. 15 | @echo. 16 | @echo Installation failed. 17 | @echo. 18 | @echo You need to right click "Install_MPCVR_64.cmd" and choose "run as admin". 19 | @echo. 20 | :done 21 | @pause >NUL 22 | -------------------------------------------------------------------------------- /distrib/Reset_Settings.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo. 3 | echo. 4 | title Restore MPC Video Renderer default settings... 5 | start /min reg delete "HKEY_CURRENT_USER\Software\MPC-BE Filters\MPC Video Renderer" /f 6 | echo settings were reset to default 7 | echo. 8 | pause >NUL 9 | -------------------------------------------------------------------------------- /distrib/Uninstall_MPCVR_32.cmd: -------------------------------------------------------------------------------- 1 | @cd /d "%~dp0" 2 | @regsvr32.exe MpcVideoRenderer.ax /u /s 3 | @if %errorlevel% NEQ 0 goto error 4 | :success 5 | @echo. 6 | @echo. 7 | @echo Uninstallation succeeded. 8 | @echo. 9 | @goto done 10 | :error 11 | @echo. 12 | @echo. 13 | @echo Uninstallation failed. 14 | @echo. 15 | @echo You need to right click "Uninstall_MPCVR_32.cmd" and choose "run as admin". 16 | @echo. 17 | :done 18 | @pause >NUL 19 | -------------------------------------------------------------------------------- /distrib/Uninstall_MPCVR_64.cmd: -------------------------------------------------------------------------------- 1 | @cd /d "%~dp0" 2 | @regsvr32.exe MpcVideoRenderer64.ax /u /s 3 | @if %errorlevel% NEQ 0 goto error 4 | :success 5 | @echo. 6 | @echo. 7 | @echo Uninstallation succeeded. 8 | @echo. 9 | @goto done 10 | :error 11 | @echo. 12 | @echo. 13 | @echo Uninstallation failed. 14 | @echo. 15 | @echo You need to right click "Uninstall_MPCVR_64.cmd" and choose "run as admin". 16 | @echo. 17 | :done 18 | @pause >NUL 19 | -------------------------------------------------------------------------------- /external/minhook.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | {303B855A-137D-45E9-AF6D-B7241C6E66D6} 40 | minhook 41 | Win32Proj 42 | minhook 43 | 44 | 45 | 46 | 47 | StaticLibrary 48 | Unicode 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | _LIB;%(PreprocessorDefinitions) 60 | NotUsing 61 | $(ProjectDir)minhook\include 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /external/minhook.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | src\hde 6 | 7 | 8 | src\hde 9 | 10 | 11 | src\hde 12 | 13 | 14 | src\hde 15 | 16 | 17 | src\hde 18 | 19 | 20 | include 21 | 22 | 23 | src 24 | 25 | 26 | src 27 | 28 | 29 | 30 | 31 | src\hde 32 | 33 | 34 | src\hde 35 | 36 | 37 | src 38 | 39 | 40 | src 41 | 42 | 43 | src 44 | 45 | 46 | 47 | 48 | {5cad8c56-69e5-4b4c-9d29-8eea07239082} 49 | 50 | 51 | {1bdeafec-c29c-4af1-bc19-72b155cee890} 52 | 53 | 54 | {4806bee5-3f51-4a47-a4a6-57e1f31a5fa3} 55 | 56 | 57 | -------------------------------------------------------------------------------- /platform.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 10.0 5 | v142 6 | 7 | 8 | 10.0 9 | v143 10 | 11 | -------------------------------------------------------------------------------- /sign.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | REM (C) 2015-2021 see Authors.txt 3 | REM 4 | REM This file is part of MPC-BE. 5 | REM 6 | REM MPC-BE is free software; you can redistribute it and/or modify 7 | REM it under the terms of the GNU General Public License as published by 8 | REM the Free Software Foundation; either version 3 of the License, or 9 | REM (at your option) any later version. 10 | REM 11 | REM MPC-BE is distributed in the hope that it will be useful, 12 | REM but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | REM GNU General Public License for more details. 15 | REM 16 | REM You should have received a copy of the GNU General Public License 17 | REM along with this program. If not, see . 18 | 19 | SETLOCAL 20 | 21 | IF "%~1" == "" ( 22 | ECHO %~nx0: No input file specified! 23 | GOTO END 24 | ) 25 | 26 | IF NOT EXIST "%~dp0signinfo.txt" ( 27 | ECHO %~nx0: %~dp0signinfo.txt is not present! 28 | GOTO END 29 | ) 30 | 31 | IF NOT DEFINED VCVARS ( 32 | FOR /f "delims=" %%A IN ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -property installationPath -requires Microsoft.Component.MSBuild Microsoft.VisualStudio.Component.VC.ATLMFC Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -latest') DO SET "VCVARS=%%A\Common7\Tools\vsdevcmd.bat" 33 | ) 34 | 35 | IF NOT EXIST "%VCVARS%" ( 36 | ECHO ERROR: "Visual Studio environment variable(s) is missing - possible it's not installed on your PC" 37 | GOTO END 38 | ) 39 | 40 | CALL "%VCVARS%" -no_logo -arch=x86 41 | 42 | TITLE Signing "%*"... 43 | ECHO. & ECHO Signing "%*"... 44 | 45 | FOR /F "delims=" %%A IN (%~dp0signinfo.txt) DO ( 46 | SET "SIGN_CMD=%%A" 47 | CALL :SIGN %* 48 | ) 49 | 50 | :END 51 | ENDLOCAL 52 | EXIT /B %ERRORLEVEL% 53 | 54 | :SIGN 55 | FOR /L %%i IN (1,1,5) DO ( 56 | IF %%i GTR 1 ECHO %%i attempt 57 | signtool.exe sign %SIGN_CMD% %* 58 | IF %ERRORLEVEL% EQU 0 EXIT /B %ERRORLEVEL% 59 | ) 60 | -------------------------------------------------------------------------------- /update_revision.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | SETLOCAL 3 | CD /D %~dp0 4 | 5 | ECHO #pragma once > revision.h 6 | 7 | SET gitexe="git.exe" 8 | %gitexe% --version 9 | IF /I %ERRORLEVEL%==0 GOTO :GitOK 10 | 11 | SET gitexe="c:\Program Files\Git\cmd\git.exe" 12 | IF NOT EXIST %gitexe% set gitexe="c:\Program Files\Git\bin\git.exe" 13 | IF NOT EXIST %gitexe% GOTO :END 14 | 15 | :GitOK 16 | 17 | %gitexe% log -1 --date=format:%%Y.%%m.%%d --pretty=format:"#define REV_DATE %%ad%%n" >> revision.h 18 | %gitexe% log -1 --pretty=format:"#define REV_HASH %%h%%n" >> revision.h 19 | 20 | > revision.h 21 | %gitexe% symbolic-ref --short HEAD >> revision.h 22 | IF %ERRORLEVEL% NEQ 0 ( 23 | ECHO LOCAL >> revision.h 24 | ) 25 | 26 | > revision.h 27 | %gitexe% rev-list --count HEAD >> revision.h 28 | IF %ERRORLEVEL% NEQ 0 ( 29 | ECHO 0 >> revision.h 30 | ) 31 | 32 | :END 33 | ENDLOCAL 34 | EXIT /B 35 | -------------------------------------------------------------------------------- /update_submodules.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | SETLOCAL 3 | CD /D %~dp0 4 | 5 | SET gitexe="git.exe" 6 | %gitexe% --version 7 | IF /I %ERRORLEVEL%==0 GOTO :GitOK 8 | 9 | SET gitexe="c:\Program Files\Git\cmd\git.exe" 10 | IF NOT EXIST %gitexe% set gitexe="c:\Program Files\Git\bin\git.exe" 11 | IF NOT EXIST %gitexe% ( 12 | ECHO ERROR: Git not found! 13 | GOTO :END 14 | ) 15 | 16 | :GitOK 17 | 18 | %gitexe% submodule update --init --recursive --progress 19 | IF %ERRORLEVEL%==0 ( 20 | ECHO Submodule update completed successfully. 21 | ) ELSE ( 22 | ECHO ERROR: %errorlevel%! 23 | ) 24 | :END 25 | TIMEOUT /T 3 26 | ENDLOCAL 27 | EXIT /B 28 | --------------------------------------------------------------------------------