mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-03 08:15:37 +00:00
Replace D3DX9 with SDL_ttf for overlay rendering
This commit is contained in:
parent
d58837421f
commit
1e7cb7f13e
@ -34,7 +34,6 @@ You can follow development on our [Discord server](https://moonlight-stream.org/
|
|||||||
* Windows 7 or later
|
* Windows 7 or later
|
||||||
* [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) (Community edition is fine)
|
* [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) (Community edition is fine)
|
||||||
* Select **MSVC 2019** option during Qt installation. MinGW is not supported.
|
* Select **MSVC 2019** option during Qt installation. MinGW is not supported.
|
||||||
* [DirectX SDK](https://www.microsoft.com/en-us/download/details.aspx?id=6812)
|
|
||||||
* [7-Zip](https://www.7-zip.org/) (only if building installers for non-development PCs)
|
* [7-Zip](https://www.7-zip.org/) (only if building installers for non-development PCs)
|
||||||
* [WiX Toolset](https://wixtoolset.org/releases/) v3.11 or later (only if building installers for non-development PCs)
|
* [WiX Toolset](https://wixtoolset.org/releases/) v3.11 or later (only if building installers for non-development PCs)
|
||||||
|
|
||||||
|
@ -36,16 +36,10 @@ win32 {
|
|||||||
INCLUDEPATH += $$PWD/../libs/windows/include
|
INCLUDEPATH += $$PWD/../libs/windows/include
|
||||||
|
|
||||||
contains(QT_ARCH, i386) {
|
contains(QT_ARCH, i386) {
|
||||||
INCLUDEPATH += $$(DXSDK_DIR)/Include
|
|
||||||
LIBS += -L$$PWD/../libs/windows/lib/x86
|
LIBS += -L$$PWD/../libs/windows/lib/x86
|
||||||
LIBS += -L$$(DXSDK_DIR)/Lib/x86 -ld3dx9
|
|
||||||
DEFINES += HAS_D3DX9
|
|
||||||
}
|
}
|
||||||
contains(QT_ARCH, x86_64) {
|
contains(QT_ARCH, x86_64) {
|
||||||
INCLUDEPATH += $$(DXSDK_DIR)/Include
|
|
||||||
LIBS += -L$$PWD/../libs/windows/lib/x64
|
LIBS += -L$$PWD/../libs/windows/lib/x64
|
||||||
LIBS += -L$$(DXSDK_DIR)/Lib/x64 -ld3dx9
|
|
||||||
DEFINES += HAS_D3DX9
|
|
||||||
}
|
}
|
||||||
contains(QT_ARCH, arm64) {
|
contains(QT_ARCH, arm64) {
|
||||||
LIBS += -L$$PWD/../libs/windows/lib/arm64
|
LIBS += -L$$PWD/../libs/windows/lib/arm64
|
||||||
|
@ -21,6 +21,12 @@ DEFINE_GUID(DXVADDI_Intel_ModeH264_E, 0x604F8E68,0x4951,0x4C54,0x88,0xFE,0xAB,0x
|
|||||||
|
|
||||||
#define SAFE_COM_RELEASE(x) if (x) { (x)->Release(); }
|
#define SAFE_COM_RELEASE(x) if (x) { (x)->Release(); }
|
||||||
|
|
||||||
|
typedef struct _VERTEX
|
||||||
|
{
|
||||||
|
float x, y, z, rhw;
|
||||||
|
float tu, tv;
|
||||||
|
} VERTEX, *PVERTEX;
|
||||||
|
|
||||||
DXVA2Renderer::DXVA2Renderer() :
|
DXVA2Renderer::DXVA2Renderer() :
|
||||||
m_DecService(nullptr),
|
m_DecService(nullptr),
|
||||||
m_Decoder(nullptr),
|
m_Decoder(nullptr),
|
||||||
@ -31,15 +37,14 @@ DXVA2Renderer::DXVA2Renderer() :
|
|||||||
m_ProcService(nullptr),
|
m_ProcService(nullptr),
|
||||||
m_Processor(nullptr),
|
m_Processor(nullptr),
|
||||||
m_FrameIndex(0),
|
m_FrameIndex(0),
|
||||||
#ifdef HAS_D3DX9
|
|
||||||
m_DebugOverlayFont(nullptr),
|
|
||||||
m_StatusOverlayFont(nullptr),
|
|
||||||
#endif
|
|
||||||
m_BlockingPresent(false)
|
m_BlockingPresent(false)
|
||||||
{
|
{
|
||||||
RtlZeroMemory(m_DecSurfaces, sizeof(m_DecSurfaces));
|
RtlZeroMemory(m_DecSurfaces, sizeof(m_DecSurfaces));
|
||||||
RtlZeroMemory(&m_DXVAContext, sizeof(m_DXVAContext));
|
RtlZeroMemory(&m_DXVAContext, sizeof(m_DXVAContext));
|
||||||
|
|
||||||
|
RtlZeroMemory(m_OverlaySurfaces, sizeof(m_OverlaySurfaces));
|
||||||
|
RtlZeroMemory(m_OverlayTextures, sizeof(m_OverlayTextures));
|
||||||
|
|
||||||
// Use MMCSS scheduling for lower scheduling latency while we're streaming
|
// Use MMCSS scheduling for lower scheduling latency while we're streaming
|
||||||
DwmEnableMMCSS(TRUE);
|
DwmEnableMMCSS(TRUE);
|
||||||
}
|
}
|
||||||
@ -55,10 +60,15 @@ DXVA2Renderer::~DXVA2Renderer()
|
|||||||
SAFE_COM_RELEASE(m_ProcService);
|
SAFE_COM_RELEASE(m_ProcService);
|
||||||
SAFE_COM_RELEASE(m_Processor);
|
SAFE_COM_RELEASE(m_Processor);
|
||||||
|
|
||||||
#ifdef HAS_D3DX9
|
for (int i = 0; i < ARRAYSIZE(m_OverlaySurfaces); i++) {
|
||||||
SAFE_COM_RELEASE(m_DebugOverlayFont);
|
if (m_OverlaySurfaces[i] != nullptr) {
|
||||||
SAFE_COM_RELEASE(m_StatusOverlayFont);
|
SDL_FreeSurface(m_OverlaySurfaces[i]);
|
||||||
#endif
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAYSIZE(m_OverlayTextures); i++) {
|
||||||
|
SAFE_COM_RELEASE(m_OverlayTextures[i]);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < ARRAYSIZE(m_DecSurfaces); i++) {
|
for (int i = 0; i < ARRAYSIZE(m_DecSurfaces); i++) {
|
||||||
SAFE_COM_RELEASE(m_DecSurfaces[i]);
|
SAFE_COM_RELEASE(m_DecSurfaces[i]);
|
||||||
@ -332,6 +342,20 @@ bool DXVA2Renderer::initializeRenderer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_Device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
|
||||||
|
m_Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||||
|
m_Device->SetRenderState(D3DRS_LIGHTING, FALSE);
|
||||||
|
|
||||||
|
m_Device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||||
|
m_Device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||||
|
m_Device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||||
|
|
||||||
|
m_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||||
|
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||||
|
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||||
|
|
||||||
|
m_Device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,64 +773,127 @@ bool DXVA2Renderer::initialize(PDECODER_PARAMETERS params)
|
|||||||
|
|
||||||
void DXVA2Renderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
void DXVA2Renderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||||
{
|
{
|
||||||
#ifdef HAS_D3DX9
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
switch (type)
|
SDL_Surface* newSurface = Session::get()->getOverlayManager().getUpdatedOverlaySurface(type);
|
||||||
|
if (newSurface == nullptr && Session::get()->getOverlayManager().isOverlayEnabled(type)) {
|
||||||
|
// The overlay is enabled and there is no new surface. Leave the old texture alone.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We must free the old texture first because it references the memory stored in the old surface.
|
||||||
|
IDirect3DTexture9* oldTexture = (IDirect3DTexture9*)SDL_AtomicSetPtr((void**)&m_OverlayTextures[type], nullptr);
|
||||||
|
SAFE_COM_RELEASE(oldTexture);
|
||||||
|
|
||||||
|
SDL_Surface* oldSurface = (SDL_Surface*)SDL_AtomicSetPtr((void**)&m_OverlaySurfaces[type], nullptr);
|
||||||
|
if (oldSurface != nullptr) {
|
||||||
|
SDL_FreeSurface(oldSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the overlay is disabled, we're done
|
||||||
|
if (!Session::get()->getOverlayManager().isOverlayEnabled(type)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a dynamic texture to populate with our pixel data
|
||||||
|
SDL_assert(!SDL_MUSTLOCK(newSurface));
|
||||||
|
IDirect3DTexture9* newTexture = nullptr;
|
||||||
|
hr = m_Device->CreateTexture(newSurface->w,
|
||||||
|
newSurface->h,
|
||||||
|
1,
|
||||||
|
D3DUSAGE_DYNAMIC,
|
||||||
|
D3DFMT_A8R8G8B8,
|
||||||
|
D3DPOOL_DEFAULT,
|
||||||
|
&newTexture,
|
||||||
|
nullptr);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"CreateTexture() failed: %x",
|
||||||
|
hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DLOCKED_RECT lockedRect;
|
||||||
|
hr = newTexture->LockRect(0, &lockedRect, nullptr, D3DLOCK_DISCARD);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"LockRect() failed: %x",
|
||||||
|
hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newSurface->pitch == lockedRect.Pitch) {
|
||||||
|
// If the pitch matches, we can take the fast path and use a single copy to transfer the pixels
|
||||||
|
RtlCopyMemory(lockedRect.pBits, newSurface->pixels, newSurface->pitch * newSurface->h);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// If the pitch doesn't match, we'll need to copy each row separately
|
||||||
|
int pitch = SDL_min(newSurface->pitch, lockedRect.Pitch);
|
||||||
|
for (int i = 0; i < newSurface->h; i++) {
|
||||||
|
RtlCopyMemory(((PUCHAR)lockedRect.pBits) + (lockedRect.Pitch * i),
|
||||||
|
((PUCHAR)newSurface->pixels) + (newSurface->pitch * i),
|
||||||
|
pitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newTexture->UnlockRect(0);
|
||||||
|
|
||||||
|
SDL_AtomicSetPtr((void**)&m_OverlaySurfaces[type], newSurface);
|
||||||
|
SDL_AtomicSetPtr((void**)&m_OverlayTextures[type], newTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DXVA2Renderer::renderOverlay(Overlay::OverlayType type)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
if (!Session::get()->getOverlayManager().isOverlayEnabled(type)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IDirect3DTexture9* overlayTexture = (IDirect3DTexture9*)SDL_AtomicGetPtr((void**)&m_OverlayTextures[type]);
|
||||||
|
SDL_Surface* overlaySurface = (SDL_Surface*)SDL_AtomicGetPtr((void**)&m_OverlaySurfaces[type]);
|
||||||
|
|
||||||
|
if (overlayTexture != nullptr && overlaySurface != nullptr) {
|
||||||
|
hr = m_Device->SetTexture(0, overlayTexture);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"SetTexture() failed: %x",
|
||||||
|
hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FRect renderRect = {};
|
||||||
|
|
||||||
|
if (type == Overlay::OverlayStatusUpdate) {
|
||||||
|
// Bottom Left
|
||||||
|
renderRect.x = 0;
|
||||||
|
renderRect.y = m_DisplayHeight - overlaySurface->h;
|
||||||
|
}
|
||||||
|
else if (type == Overlay::OverlayDebug) {
|
||||||
|
// Top left
|
||||||
|
renderRect.x = 0;
|
||||||
|
renderRect.y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderRect.w = overlaySurface->w;
|
||||||
|
renderRect.h = overlaySurface->h;
|
||||||
|
|
||||||
|
VERTEX verts[] =
|
||||||
{
|
{
|
||||||
case Overlay::OverlayDebug:
|
{renderRect.x, renderRect.y, 0, 1, 0, 0},
|
||||||
if (m_DebugOverlayFont == nullptr) {
|
{renderRect.x, renderRect.y+renderRect.h, 0, 1, 0, 1},
|
||||||
hr = D3DXCreateFontA(m_Device,
|
{renderRect.x+renderRect.w, renderRect.y+renderRect.h, 0, 1, 1, 1},
|
||||||
Session::get()->getOverlayManager().getOverlayFontSize(Overlay::OverlayDebug),
|
{renderRect.x+renderRect.w, renderRect.y, 0, 1, 1, 0}
|
||||||
0,
|
};
|
||||||
FW_HEAVY,
|
|
||||||
1,
|
hr = m_Device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(VERTEX));
|
||||||
false,
|
|
||||||
ANSI_CHARSET,
|
|
||||||
OUT_DEFAULT_PRECIS,
|
|
||||||
DEFAULT_QUALITY,
|
|
||||||
DEFAULT_PITCH | FF_DONTCARE,
|
|
||||||
"",
|
|
||||||
&m_DebugOverlayFont);
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"D3DXCreateFontA() failed: %x",
|
"DrawPrimitiveUP() failed: %x",
|
||||||
hr);
|
hr);
|
||||||
m_DebugOverlayFont = nullptr;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case Overlay::OverlayStatusUpdate:
|
|
||||||
if (m_StatusOverlayFont == nullptr) {
|
|
||||||
hr = D3DXCreateFontA(m_Device,
|
|
||||||
Session::get()->getOverlayManager().getOverlayFontSize(Overlay::OverlayStatusUpdate),
|
|
||||||
0,
|
|
||||||
FW_HEAVY,
|
|
||||||
1,
|
|
||||||
false,
|
|
||||||
ANSI_CHARSET,
|
|
||||||
OUT_DEFAULT_PRECIS,
|
|
||||||
DEFAULT_QUALITY,
|
|
||||||
DEFAULT_PITCH | FF_DONTCARE,
|
|
||||||
"",
|
|
||||||
&m_StatusOverlayFont);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"D3DXCreateFontA() failed: %x",
|
|
||||||
hr);
|
|
||||||
m_StatusOverlayFont = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
SDL_assert(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
Q_UNUSED(type);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int DXVA2Renderer::getDecoderColorspace()
|
int DXVA2Renderer::getDecoderColorspace()
|
||||||
@ -1011,31 +1098,10 @@ void DXVA2Renderer::renderFrame(AVFrame *frame)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_D3DX9
|
// Render overlays on top of the video stream
|
||||||
if (m_DebugOverlayFont != nullptr) {
|
for (int i = 0; i < Overlay::OverlayMax; i++) {
|
||||||
if (Session::get()->getOverlayManager().isOverlayEnabled(Overlay::OverlayDebug)) {
|
renderOverlay((Overlay::OverlayType)i);
|
||||||
SDL_Color color = Session::get()->getOverlayManager().getOverlayColor(Overlay::OverlayDebug);
|
|
||||||
m_DebugOverlayFont->DrawTextA(nullptr,
|
|
||||||
Session::get()->getOverlayManager().getOverlayText(Overlay::OverlayDebug),
|
|
||||||
-1,
|
|
||||||
&sample.DstRect,
|
|
||||||
DT_LEFT | DT_NOCLIP,
|
|
||||||
D3DCOLOR_ARGB(color.a, color.r, color.g, color.b));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (m_StatusOverlayFont != nullptr) {
|
|
||||||
if (Session::get()->getOverlayManager().isOverlayEnabled(Overlay::OverlayStatusUpdate)) {
|
|
||||||
SDL_Color color = Session::get()->getOverlayManager().getOverlayColor(Overlay::OverlayStatusUpdate);
|
|
||||||
m_StatusOverlayFont->DrawTextA(nullptr,
|
|
||||||
Session::get()->getOverlayManager().getOverlayText(Overlay::OverlayStatusUpdate),
|
|
||||||
-1,
|
|
||||||
&sample.DstRect,
|
|
||||||
DT_RIGHT | DT_NOCLIP,
|
|
||||||
D3DCOLOR_ARGB(color.a, color.r, color.g, color.b));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
hr = m_Device->EndScene();
|
hr = m_Device->EndScene();
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -6,10 +6,6 @@
|
|||||||
#include <d3d9.h>
|
#include <d3d9.h>
|
||||||
#include <dxva2api.h>
|
#include <dxva2api.h>
|
||||||
|
|
||||||
#ifdef HAS_D3DX9
|
|
||||||
#include <d3dx9.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <libavcodec/dxva2.h>
|
#include <libavcodec/dxva2.h>
|
||||||
}
|
}
|
||||||
@ -22,7 +18,7 @@ public:
|
|||||||
virtual bool initialize(PDECODER_PARAMETERS params) override;
|
virtual bool initialize(PDECODER_PARAMETERS params) override;
|
||||||
virtual bool prepareDecoderContext(AVCodecContext* context, AVDictionary** options) override;
|
virtual bool prepareDecoderContext(AVCodecContext* context, AVDictionary** options) override;
|
||||||
virtual void renderFrame(AVFrame* frame) override;
|
virtual void renderFrame(AVFrame* frame) override;
|
||||||
virtual void notifyOverlayUpdated(Overlay::OverlayType) override;
|
virtual void notifyOverlayUpdated(Overlay::OverlayType type) override;
|
||||||
virtual int getDecoderColorspace() override;
|
virtual int getDecoderColorspace() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -31,6 +27,7 @@ private:
|
|||||||
bool initializeDevice(SDL_Window* window, bool enableVsync);
|
bool initializeDevice(SDL_Window* window, bool enableVsync);
|
||||||
bool isDecoderBlacklisted();
|
bool isDecoderBlacklisted();
|
||||||
bool isDXVideoProcessorAPIBlacklisted();
|
bool isDXVideoProcessorAPIBlacklisted();
|
||||||
|
void renderOverlay(Overlay::OverlayType type);
|
||||||
|
|
||||||
static
|
static
|
||||||
AVBufferRef* ffPoolAlloc(void* opaque, int size);
|
AVBufferRef* ffPoolAlloc(void* opaque, int size);
|
||||||
@ -56,6 +53,9 @@ private:
|
|||||||
int m_SurfacesUsed;
|
int m_SurfacesUsed;
|
||||||
AVBufferPool* m_Pool;
|
AVBufferPool* m_Pool;
|
||||||
|
|
||||||
|
SDL_Surface* m_OverlaySurfaces[Overlay::OverlayMax];
|
||||||
|
IDirect3DTexture9* m_OverlayTextures[Overlay::OverlayMax];
|
||||||
|
|
||||||
IDirect3DDevice9Ex* m_Device;
|
IDirect3DDevice9Ex* m_Device;
|
||||||
IDirect3DSurface9* m_RenderTarget;
|
IDirect3DSurface9* m_RenderTarget;
|
||||||
IDirectXVideoProcessorService* m_ProcService;
|
IDirectXVideoProcessorService* m_ProcService;
|
||||||
@ -66,9 +66,5 @@ private:
|
|||||||
DXVA2_ValueRange m_SaturationRange;
|
DXVA2_ValueRange m_SaturationRange;
|
||||||
DXVA2_VideoDesc m_Desc;
|
DXVA2_VideoDesc m_Desc;
|
||||||
REFERENCE_TIME m_FrameIndex;
|
REFERENCE_TIME m_FrameIndex;
|
||||||
#ifdef HAS_D3DX9
|
|
||||||
LPD3DXFONT m_DebugOverlayFont;
|
|
||||||
LPD3DXFONT m_StatusOverlayFont;
|
|
||||||
#endif
|
|
||||||
bool m_BlockingPresent;
|
bool m_BlockingPresent;
|
||||||
};
|
};
|
||||||
|
@ -140,10 +140,6 @@ if /I "%ARCH%" NEQ "ARM64" (
|
|||||||
echo Copying AntiHooking.dll
|
echo Copying AntiHooking.dll
|
||||||
copy %BUILD_FOLDER%\AntiHooking\%BUILD_CONFIG%\AntiHooking.dll %DEPLOY_FOLDER%
|
copy %BUILD_FOLDER%\AntiHooking\%BUILD_CONFIG%\AntiHooking.dll %DEPLOY_FOLDER%
|
||||||
if !ERRORLEVEL! NEQ 0 goto Error
|
if !ERRORLEVEL! NEQ 0 goto Error
|
||||||
|
|
||||||
echo Copying d3dx9_43.dll from DirectX SDK
|
|
||||||
expand "%DXSDK_DIR%\Redist\Jun2010_d3dx9_43_%ARCH%.cab" -F:d3dx9_43.dll %DEPLOY_FOLDER%
|
|
||||||
if !ERRORLEVEL! NEQ 0 goto Error
|
|
||||||
)
|
)
|
||||||
|
|
||||||
echo Copying GC mapping list
|
echo Copying GC mapping list
|
||||||
|
Loading…
x
Reference in New Issue
Block a user