Merge pull request #375 from PatrickvL/master
Simpler overlay conversion and other tidbits
This commit is contained in:
commit
aac42a9af6
|
@ -283,7 +283,6 @@ $(SOLUTIONDIR)Export.bat</Command>
|
|||
<ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase\XOnline.1.0.5849.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\HLEIntercept.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\LibRc4.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\libyuv_extract.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\MemoryManager.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\nv2a_int.h" />
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\OOVPA.h" />
|
||||
|
@ -544,7 +543,6 @@ $(SOLUTIONDIR)Export.bat</Command>
|
|||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\CxbxKrnl\LibRc4.cpp" />
|
||||
<ClCompile Include="..\..\src\CxbxKrnl\libyuv_extract.cpp" />
|
||||
<ClCompile Include="..\..\src\CxbxKrnl\MemoryManager.cpp" />
|
||||
<ClCompile Include="..\..\src\CxbxKrnl\ResourceTracker.cpp">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
|
|
|
@ -199,9 +199,6 @@
|
|||
<ClCompile Include="..\..\src\Cxbx\DlgAbout.cpp">
|
||||
<Filter>GUI</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\CxbxKrnl\libyuv_extract.cpp">
|
||||
<Filter>Emulator</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\Cxbx\DlgControllerConfig.h">
|
||||
|
@ -552,9 +549,6 @@
|
|||
<ClInclude Include="..\..\src\Cxbx\DlgAbout.h">
|
||||
<Filter>GUI</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\CxbxKrnl\libyuv_extract.h">
|
||||
<Filter>Emulator</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\resource\About.jpg">
|
||||
|
|
|
@ -53,7 +53,6 @@ namespace xboxkrnl
|
|||
#include "EmuAlloc.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "EmuXTL.h"
|
||||
#include "libyuv_extract.h" // for YUY2ToARGB
|
||||
|
||||
#include <assert.h>
|
||||
#include <process.h>
|
||||
|
@ -1324,7 +1323,7 @@ static void EmuUnswizzleTextureStages()
|
|||
// break;
|
||||
//CxbxKrnlCleanup("Temporarily unsupported format for active texture unswizzle (0x%.08X)", SurfaceDesc.Format);
|
||||
|
||||
hRet = pTexture->LockRect(v, &LockedRect, NULL, NULL);
|
||||
hRet = pTexture->LockRect(v, &LockedRect, NULL, 0);
|
||||
|
||||
if(FAILED(hRet))
|
||||
continue;
|
||||
|
@ -1336,7 +1335,7 @@ static void EmuUnswizzleTextureStages()
|
|||
RECT iRect = {0,0,0,0};
|
||||
POINT iPoint = {0,0};
|
||||
|
||||
void *pTemp = malloc(dwHeight*dwPitch);
|
||||
void *pTemp = malloc(dwPitch*dwHeight);
|
||||
|
||||
XTL::EmuUnswizzleRect
|
||||
(
|
||||
|
@ -3210,7 +3209,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreateTexture)
|
|||
*/
|
||||
D3DLOCKED_RECT LockedRect;
|
||||
|
||||
pTexture->EmuTexture8->LockRect(0, &LockedRect, NULL, NULL);
|
||||
pTexture->EmuTexture8->LockRect(0, &LockedRect, NULL, D3DLOCK_READONLY);
|
||||
Texture_Data = (DWORD)LockedRect.pBits;
|
||||
g_DataToTexture.insert(Texture_Data, pTexture);
|
||||
pTexture->EmuTexture8->UnlockRect(0);
|
||||
|
@ -4255,6 +4254,8 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Clear)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define CXBX_SWAP_PRESENT_FORWARD (256 + 4 + 1) // = CxbxPresentForwardMarker + D3DSWAP_FINISH + D3DSWAP_COPY
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: D3DDevice_Present
|
||||
// ******************************************************************
|
||||
|
@ -4266,8 +4267,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Present)
|
|||
PVOID pDummy2
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
// LOG_FORWARD("D3DDevice_Swap");
|
||||
DbgPrintf("EmuD3D8: EmuD3DDevice_Present\n"
|
||||
"(\n"
|
||||
" pSourceRect : 0x%.08X\n"
|
||||
|
@ -4277,7 +4277,27 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Present)
|
|||
");\n",
|
||||
pSourceRect, pDestRect, pDummy1, pDummy2);
|
||||
|
||||
HRESULT hRet = S_OK;
|
||||
return EMUPATCH(D3DDevice_Swap)(CXBX_SWAP_PRESENT_FORWARD); // Xbox present ignores
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: D3DDevice_Swap
|
||||
// ******************************************************************
|
||||
DWORD WINAPI XTL::EMUPATCH(D3DDevice_Swap)
|
||||
(
|
||||
DWORD Flags
|
||||
)
|
||||
{
|
||||
DbgPrintf("EmuD3D8: EmuD3DDevice_Swap\n"
|
||||
"(\n"
|
||||
" Flags : 0x%.08X\n"
|
||||
");\n",
|
||||
Flags);
|
||||
|
||||
// TODO: Ensure this flag is always the same across library versions
|
||||
if(Flags != 0)
|
||||
if (Flags != CXBX_SWAP_PRESENT_FORWARD) // Avoid a warning when forwarded
|
||||
EmuWarning("XTL::EmuD3DDevice_Swap: Flags != 0");
|
||||
|
||||
CxbxReleaseBackBufferLock();
|
||||
|
||||
|
@ -4287,8 +4307,10 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Present)
|
|||
// g_pDD7->WaitForVerticalBlank( DDWAITVB_BLOCKEND, NULL );
|
||||
// g_pDD7->WaitForVerticalBlank( DDWAITVB_BLOCKEND, NULL );
|
||||
|
||||
hRet = g_pD3DDevice8->Present(pSourceRect, pDestRect, (HWND)pDummy1, (CONST RGNDATA*)pDummy2);
|
||||
g_pD3DDevice8->Present(0, 0, 0, 0);
|
||||
|
||||
if (Flags == CXBX_SWAP_PRESENT_FORWARD) // Only do this when forwarded from Present
|
||||
{
|
||||
// Put primitives per frame in the title
|
||||
/*{
|
||||
char szString[64];
|
||||
|
@ -4300,6 +4322,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Present)
|
|||
g_dwPrimPerFrame = 0;
|
||||
}*/
|
||||
|
||||
// TODO : Check if this should be done at Swap-not-Present-time too :
|
||||
// not really accurate because you definately dont always present on every vblank
|
||||
g_VBData.Swap = g_VBData.VBlank;
|
||||
|
||||
|
@ -4310,6 +4333,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Present)
|
|||
g_VBData.Flags = 2; // D3DVBLANK_SWAPMISSED
|
||||
g_SwapData.MissedVBlanks++;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Swap Callback function
|
||||
{
|
||||
|
@ -4325,58 +4349,13 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Present)
|
|||
|
||||
g_bHackUpdateSoftwareOverlay = FALSE;
|
||||
|
||||
DWORD result;
|
||||
if (Flags == CXBX_SWAP_PRESENT_FORWARD) // Only do this when forwarded from Present
|
||||
result = S_OK; // Present always returns success
|
||||
else
|
||||
result = g_SwapData.Swap; // Swap returns number of swaps
|
||||
|
||||
|
||||
return hRet;
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: D3DDevice_Swap
|
||||
// ******************************************************************
|
||||
HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Swap)
|
||||
(
|
||||
DWORD Flags
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
DbgPrintf("EmuD3D8: EmuD3DDevice_Swap\n"
|
||||
"(\n"
|
||||
" Flags : 0x%.08X\n"
|
||||
");\n",
|
||||
Flags);
|
||||
|
||||
// TODO: Ensure this flag is always the same across library versions
|
||||
if(Flags != 0)
|
||||
EmuWarning("XTL::EmuD3DDevice_Swap: Flags != 0");
|
||||
|
||||
CxbxReleaseBackBufferLock();
|
||||
|
||||
// TODO: Make a video option to wait for VBlank before calling Present.
|
||||
// Makes syncing to 30fps easier (which is the native frame rate for Azurik
|
||||
// and Halo).
|
||||
// g_pDD7->WaitForVerticalBlank( DDWAITVB_BLOCKEND, NULL );
|
||||
// g_pDD7->WaitForVerticalBlank( DDWAITVB_BLOCKEND, NULL );
|
||||
|
||||
HRESULT hRet = g_pD3DDevice8->Present(0, 0, 0, 0);
|
||||
|
||||
// Handle Swap Callback function
|
||||
{
|
||||
g_SwapData.Swap++;
|
||||
|
||||
if(g_pSwapCallback != NULL)
|
||||
{
|
||||
|
||||
g_pSwapCallback(&g_SwapData);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
g_bHackUpdateSoftwareOverlay = FALSE;
|
||||
|
||||
|
||||
|
||||
return hRet;
|
||||
return result;
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -4838,10 +4817,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DResource_Register)
|
|||
}
|
||||
}
|
||||
|
||||
RECT iRect = {0,0,0,0};
|
||||
POINT iPoint = {0,0};
|
||||
|
||||
BYTE *pSrc = (BYTE*)pBase;
|
||||
BYTE *pSrc = (BYTE*)pBase; // TODO : Fix (look at Dxbx) this, as it gives cube textures identical sides
|
||||
|
||||
if(( pResource->Data == X_D3DRESOURCE_DATA_BACK_BUFFER)
|
||||
||( (DWORD)pBase == X_D3DRESOURCE_DATA_BACK_BUFFER))
|
||||
|
@ -4868,10 +4844,17 @@ HRESULT WINAPI XTL::EMUPATCH(D3DResource_Register)
|
|||
// TODO: Fix or handle this situation..?
|
||||
// This is probably an unallocated resource, mapped into contiguous memory (0x80000000)
|
||||
}
|
||||
else if (pSrc == nullptr)
|
||||
{
|
||||
// TODO: Fix or handle this situation..?
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bSwizzled)
|
||||
{
|
||||
RECT iRect = { 0,0,0,0 };
|
||||
POINT iPoint = { 0,0 };
|
||||
|
||||
// First we need to unswizzle the texture data
|
||||
XTL::EmuUnswizzleRect
|
||||
(
|
||||
|
@ -4889,10 +4872,23 @@ HRESULT WINAPI XTL::EMUPATCH(D3DResource_Register)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* TODO : // Let DirectX convert the surface (including palette formats) :
|
||||
if(!EmuXBFormatRequiresConversionToARGB) {
|
||||
D3DXLoadSurfaceFromMemory(
|
||||
pResource->EmuSurface8,
|
||||
nullptr, // no destination palette
|
||||
&destRect,
|
||||
pSrc, // Source buffer
|
||||
dwMipPitch, // Source pitch
|
||||
pCurrentPalette,
|
||||
&SrcRect,
|
||||
D3DX_DEFAULT, // D3DX_FILTER_NONE,
|
||||
0 // No ColorKey?
|
||||
);
|
||||
} else {
|
||||
*/
|
||||
BYTE *pDest = (BYTE*)LockedRect.pBits;
|
||||
|
||||
if (pSrc)
|
||||
{
|
||||
if ((DWORD)LockedRect.Pitch == dwMipPitch && dwMipPitch == dwMipWidth*dwBPP)
|
||||
{
|
||||
memcpy(pDest, pSrc + dwMipOffs, dwMipWidth*dwMipHeight*dwBPP);
|
||||
|
@ -4908,7 +4904,6 @@ HRESULT WINAPI XTL::EMUPATCH(D3DResource_Register)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CacheFormat != 0) // Do we need to convert to ARGB?
|
||||
{
|
||||
|
@ -6040,27 +6035,6 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_EnableOverlay)
|
|||
return;
|
||||
}
|
||||
|
||||
XTL::IDirect3DSurface8 *ExtraXRGBSurface = nullptr; // this is our pointer to the memory location containing our copy of the front buffer
|
||||
|
||||
void AssureExtraXRGBSurface(XTL::IDirect3DSurface8 *pBackBufferSurface, std::string Caller)
|
||||
{
|
||||
XTL::D3DSURFACE_DESC SurfaceDesc;
|
||||
HRESULT aResult;
|
||||
|
||||
// Assure we have a reusable surface (in the correct format) which the back buffer can be converted into :
|
||||
if (ExtraXRGBSurface == nullptr) {
|
||||
pBackBufferSurface->GetDesc(&SurfaceDesc);
|
||||
aResult = g_pD3DDevice8->CreateImageSurface(
|
||||
SurfaceDesc.Width,
|
||||
SurfaceDesc.Height,
|
||||
XTL::D3DFMT_A8R8G8B8, // This format is supported by D3DXSaveSurfaceToFile (D3DFMT_X8R8G8B8 works too)
|
||||
&ExtraXRGBSurface);
|
||||
if FAILED(aResult) {
|
||||
// DbgPrintf("EmuD3D8 : %s could not create a extra buffer!\n", DxbxD3DErrorString(aResult), Caller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: D3DDevice_UpdateOverlay
|
||||
// ******************************************************************
|
||||
|
@ -6129,10 +6103,14 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_UpdateOverlay)
|
|||
}
|
||||
}
|
||||
|
||||
RECT SourRect = { 0, 0, (LONG)g_dwOverlayW, (LONG)g_dwOverlayH };
|
||||
if (SrcRect != NULL)
|
||||
SourRect = *SrcRect;
|
||||
|
||||
// update overlay!
|
||||
if(g_bSupportsYUY2)
|
||||
{
|
||||
RECT SourRect = {0, 0, (LONG)g_dwOverlayW, (LONG)g_dwOverlayH}, DestRect;
|
||||
RECT DestRect;
|
||||
MONITORINFO MonitorInfo = {0};
|
||||
|
||||
int nTitleHeight = 0;//GetSystemMetrics(SM_CYCAPTION);
|
||||
|
@ -6167,72 +6145,53 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_UpdateOverlay)
|
|||
{
|
||||
IDirect3DSurface8 *pBackBufferSurface = nullptr;
|
||||
HRESULT hRet = g_pD3DDevice8->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBufferSurface);
|
||||
// if we obtained the backbuffer, manually translate the YUY2 into the backbuffer format
|
||||
// if we obtained the backbuffer, load the YUY2 into the backbuffer
|
||||
if (hRet == D3D_OK) {
|
||||
IDirect3DSurface8 *pOverlayBufferSurface = nullptr;
|
||||
D3DLOCKED_RECT LockedRectDest;
|
||||
|
||||
// Get backbuffer dimenions; TODO : remember this once, at creation/resize time
|
||||
D3DSURFACE_DESC BackBufferDesc;
|
||||
pBackBufferSurface->GetDesc(&BackBufferDesc);
|
||||
|
||||
// Determine if the overlay can be written directly to the backbuffer :
|
||||
bool CanWriteToBackbuffer = false;
|
||||
if ((BackBufferDesc.Format == D3DFMT_A8R8G8B8) || (BackBufferDesc.Format == D3DFMT_X8R8G8B8)) {
|
||||
if (DstRect == SrcRect) {
|
||||
CanWriteToBackbuffer = true;
|
||||
} else {
|
||||
if (DstRect != nullptr && SrcRect != nullptr) {
|
||||
if ((DstRect->left == SrcRect->left)
|
||||
&& (DstRect->right == SrcRect->right)
|
||||
&& (DstRect->top == SrcRect->top)
|
||||
&& (DstRect->bottom == SrcRect->bottom)) {
|
||||
CanWriteToBackbuffer = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we can write to the back buffer, work with that, else use the screenshotbuffer as temporary surface :
|
||||
if (CanWriteToBackbuffer) {
|
||||
pOverlayBufferSurface = pBackBufferSurface;
|
||||
} else {
|
||||
AssureExtraXRGBSurface(pBackBufferSurface, "EmuD3DDevice_UpdateOverlay");
|
||||
pOverlayBufferSurface = ExtraXRGBSurface; // Note : This surface is always in ARGB format
|
||||
}
|
||||
|
||||
// Manually translate the YUY2 formatted input surface into the RGB buffer of the pre-determined output surface :
|
||||
if (pOverlayBufferSurface->LockRect(&LockedRectDest, DstRect, 0) == D3D_OK) {
|
||||
// Determine the start of the Xbox overlay buffer and Native destination buffer :
|
||||
uint08 *pYUY2Input = (uint08*)pSurface->Lock; // TODO : DxbxGetDataFromXboxResource(pSurface);
|
||||
uint08 *pARGBOutput = (uint08*)LockedRectDest.pBits;
|
||||
|
||||
// Limit the width and height of the output to the backbuffer dimensions.
|
||||
// This will (hopefully) prevent exceptions in Blinx - The Time Sweeper
|
||||
// (see https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/issues/285)
|
||||
uint32 W = min(g_dwOverlayW, BackBufferDesc.Width);
|
||||
uint32 H = min(g_dwOverlayH, BackBufferDesc.Height);
|
||||
RECT DestRect = { 0 };
|
||||
{
|
||||
// If there's a destination rectangle given, copy that into our local variable :
|
||||
if (DstRect != NULL)
|
||||
DestRect = *DstRect;
|
||||
|
||||
// full color conversion (YUY2->XRGB)
|
||||
YUY2ToARGB(pYUY2Input, g_dwOverlayP, pARGBOutput, LockedRectDest.Pitch, W, H);
|
||||
// Use our (bounded) copy when bounds exceed :
|
||||
if (DestRect.right > BackBufferDesc.Width) {
|
||||
DestRect.right = BackBufferDesc.Width;
|
||||
DstRect = &DestRect;
|
||||
}
|
||||
|
||||
pOverlayBufferSurface->UnlockRect(); // TODO : Could this be done after calling D3DXLoadSurfaceFromSurface (and would that improve performance)?
|
||||
if (g_dwOverlayH > BackBufferDesc.Height) {
|
||||
DestRect.bottom = BackBufferDesc.Height;
|
||||
DstRect = &DestRect;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CanWriteToBackbuffer) {
|
||||
// When the overlay could not directly be converted into the back buffer,
|
||||
// we now have to stretch-copy there (this also does a format-conversion, if needed) :
|
||||
if (D3DXLoadSurfaceFromSurface(
|
||||
uint08 *pYUY2Input = (uint08*)pSurface->Lock; // TODO : DxbxGetDataFromXboxResource(pSurface);
|
||||
|
||||
// Use D3DXLoadSurfaceFromMemory() to do conversion, stretching and filtering
|
||||
// avoiding the need for YUY2toARGB() (might become relevant when porting to D3D9 or OpenGL)
|
||||
// see https://msdn.microsoft.com/en-us/library/windows/desktop/bb172902(v=vs.85).aspx
|
||||
hRet = D3DXLoadSurfaceFromMemory(
|
||||
/* pDestSurface = */ pBackBufferSurface,
|
||||
/* pDestPalette = */ nullptr, // Palette not needed for YUY2
|
||||
DstRect,
|
||||
/* pSrcSurface = */ pOverlayBufferSurface,
|
||||
/* pDestRect = */DstRect, // Either the unmodified original (can be NULL) or a pointer to our local variable
|
||||
/* pSrcMemory = */ pYUY2Input, // Source buffer
|
||||
/* SrcFormat = */ D3DFMT_YUY2,
|
||||
/* SrcPitch = */ g_dwOverlayP,
|
||||
/* pSrcPalette = */ nullptr, // Palette not needed for YUY2
|
||||
SrcRect,
|
||||
/* pSrcRect = */ &SourRect,
|
||||
/* Filter = */ D3DX_FILTER_POINT, // Dxbx note : D3DX_FILTER_LINEAR gives a smoother image, but 'bleeds' across borders
|
||||
/* ColorKey = */ ColorKey) != D3D_OK) {
|
||||
/* ColorKey = */ EnableColorKey ? ColorKey : 0);
|
||||
if (hRet != D3D_OK) {
|
||||
DbgPrintf("EmuD3D8 : UpdateOverlay could not convert buffer!\n");
|
||||
}
|
||||
}
|
||||
//DbgPrintf("EmuD3D8 : Error: %s error description: %s\n",
|
||||
// DXGetErrorString(hRet), DXGetErrorDescription(hRet));
|
||||
}
|
||||
|
||||
pBackBufferSurface->Release();
|
||||
|
@ -9702,7 +9661,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_PersistDisplay)()
|
|||
{
|
||||
void* ptr = g_MemoryManager.Allocate( BackBufferDesc.Width * BackBufferDesc.Height * dwBytesPerPixel );
|
||||
|
||||
if( SUCCEEDED( pBackBuffer->LockRect( &LockedRect, NULL, 0 ) ) )
|
||||
if( SUCCEEDED( pBackBuffer->LockRect( &LockedRect, NULL, D3DLOCK_READONLY ) ) )
|
||||
{
|
||||
CopyMemory( ptr, LockedRect.pBits, BackBufferDesc.Width * BackBufferDesc.Height * dwBytesPerPixel );
|
||||
|
||||
|
|
|
@ -669,7 +669,7 @@ HRESULT WINAPI EMUPATCH(D3DDevice_Present)
|
|||
// ******************************************************************
|
||||
// * patch: D3DDevice_Swap
|
||||
// ******************************************************************
|
||||
HRESULT WINAPI EMUPATCH(D3DDevice_Swap)
|
||||
DWORD WINAPI EMUPATCH(D3DDevice_Swap)
|
||||
(
|
||||
DWORD Flags
|
||||
);
|
||||
|
|
|
@ -1,226 +0,0 @@
|
|||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
#include "libyuv_extract.h"
|
||||
|
||||
// The following code is an extract of libyuv to keep code size low (this may be revisited later).
|
||||
// Source : https://github.com/lemenkov/libyuv/commit/7e936044d154b9fe159a67f9562e10b1ef1cb590
|
||||
|
||||
/* From libyuv\README.chromium :
|
||||
Name: libyuv
|
||||
URL: http://code.google.com/p/libyuv/
|
||||
Version: 1514
|
||||
License: BSD
|
||||
License File: LICENSE
|
||||
|
||||
Description:
|
||||
libyuv is an open source project that includes YUV conversion and scaling functionality.
|
||||
*/
|
||||
|
||||
// From libyuv\include\libyuv\row.h :
|
||||
|
||||
// This struct is for Intel color conversion.
|
||||
struct YuvConstants {
|
||||
int8 kUVToB[32];
|
||||
int8 kUVToG[32];
|
||||
int8 kUVToR[32];
|
||||
int16 kUVBiasB[16];
|
||||
int16 kUVBiasG[16];
|
||||
int16 kUVBiasR[16];
|
||||
int16 kYToRgb[16];
|
||||
};
|
||||
|
||||
// From libyuv\include\libyuv\row.h :
|
||||
|
||||
#if defined(VISUALC_HAS_AVX2)
|
||||
#define SIMD_ALIGNED(var) __declspec(align(32)) var
|
||||
#else
|
||||
#define SIMD_ALIGNED(var) __declspec(align(16)) var
|
||||
#endif
|
||||
|
||||
// From libyuv\source\row_common.cc :
|
||||
|
||||
// llvm x86 is poor at ternary operator, so use branchless min/max.
|
||||
#define USE_BRANCHLESS 1
|
||||
#if USE_BRANCHLESS
|
||||
static __inline int32 clamp0(int32 v) {
|
||||
return ((-(v) >> 31) & (v));
|
||||
}
|
||||
|
||||
static __inline int32 clamp255(int32 v) {
|
||||
return (((255 - (v)) >> 31) | (v)) & 255;
|
||||
}
|
||||
|
||||
static __inline uint32 Clamp(int32 val) {
|
||||
int v = clamp0(val);
|
||||
return (uint32)(clamp255(v));
|
||||
}
|
||||
|
||||
static __inline uint32 Abs(int32 v) {
|
||||
int m = v >> 31;
|
||||
return (v + m) ^ m;
|
||||
}
|
||||
#else // USE_BRANCHLESS
|
||||
static __inline int32 clamp0(int32 v) {
|
||||
return (v < 0) ? 0 : v;
|
||||
}
|
||||
|
||||
static __inline int32 clamp255(int32 v) {
|
||||
return (v > 255) ? 255 : v;
|
||||
}
|
||||
|
||||
static __inline uint32 Clamp(int32 val) {
|
||||
int v = clamp0(val);
|
||||
return (uint32)(clamp255(v));
|
||||
}
|
||||
|
||||
static __inline uint32 Abs(int32 v) {
|
||||
return (v < 0) ? -v : v;
|
||||
}
|
||||
#endif // USE_BRANCHLESS
|
||||
|
||||
// From libyuv\source\row_common.cc :
|
||||
|
||||
// BT.601 YUV to RGB reference
|
||||
// R = (Y - 16) * 1.164 - V * -1.596
|
||||
// G = (Y - 16) * 1.164 - U * 0.391 - V * 0.813
|
||||
// B = (Y - 16) * 1.164 - U * -2.018
|
||||
|
||||
// Y contribution to R,G,B. Scale and bias.
|
||||
#define YG 18997 /* round(1.164 * 64 * 256 * 256 / 257) */
|
||||
#define YGB -1160 /* 1.164 * 64 * -16 + 64 / 2 */
|
||||
|
||||
// U and V contributions to R,G,B.
|
||||
#define UB -128 /* max(-128, round(-2.018 * 64)) */
|
||||
#define UG 25 /* round(0.391 * 64) */
|
||||
#define VG 52 /* round(0.813 * 64) */
|
||||
#define VR -102 /* round(-1.596 * 64) */
|
||||
|
||||
// Bias values to subtract 16 from Y and 128 from U and V.
|
||||
#define BB (UB * 128 + YGB)
|
||||
#define BG (UG * 128 + VG * 128 + YGB)
|
||||
#define BR (VR * 128 + YGB)
|
||||
|
||||
const struct YuvConstants SIMD_ALIGNED(kYuvI601Constants) = {
|
||||
{ UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0,
|
||||
UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0 },
|
||||
{ UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG,
|
||||
UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG },
|
||||
{ 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR,
|
||||
0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR },
|
||||
{ BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB },
|
||||
{ BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG },
|
||||
{ BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR },
|
||||
{ YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG } };
|
||||
|
||||
// C reference code that mimics the YUV assembly.
|
||||
static __inline void YuvPixel(uint8 y,
|
||||
uint8 u,
|
||||
uint8 v,
|
||||
uint8* b,
|
||||
uint8* g,
|
||||
uint8* r,
|
||||
const struct YuvConstants* yuvconstants) {
|
||||
int ub = yuvconstants->kUVToB[0];
|
||||
int ug = yuvconstants->kUVToG[0];
|
||||
int vg = yuvconstants->kUVToG[1];
|
||||
int vr = yuvconstants->kUVToR[1];
|
||||
int bb = yuvconstants->kUVBiasB[0];
|
||||
int bg = yuvconstants->kUVBiasG[0];
|
||||
int br = yuvconstants->kUVBiasR[0];
|
||||
int yg = yuvconstants->kYToRgb[0];
|
||||
|
||||
uint32 y1 = (uint32)(y * 0x0101 * yg) >> 16;
|
||||
*b = Clamp((int32)(-(u * ub) + y1 + bb) >> 6);
|
||||
*g = Clamp((int32)(-(u * ug + v * vg) + y1 + bg) >> 6);
|
||||
*r = Clamp((int32)(-(v * vr) + y1 + br) >> 6);
|
||||
}
|
||||
|
||||
void YUY2ToARGBRow_C(const uint8* src_yuy2,
|
||||
uint8* rgb_buf,
|
||||
const struct YuvConstants* yuvconstants,
|
||||
int width) {
|
||||
int x;
|
||||
for (x = 0; x < width - 1; x += 2) {
|
||||
YuvPixel(src_yuy2[0], src_yuy2[1], src_yuy2[3], rgb_buf + 0, rgb_buf + 1,
|
||||
rgb_buf + 2, yuvconstants);
|
||||
rgb_buf[3] = 255;
|
||||
YuvPixel(src_yuy2[2], src_yuy2[1], src_yuy2[3], rgb_buf + 4, rgb_buf + 5,
|
||||
rgb_buf + 6, yuvconstants);
|
||||
rgb_buf[7] = 255;
|
||||
src_yuy2 += 4;
|
||||
rgb_buf += 8; // Advance 2 pixels.
|
||||
}
|
||||
if (width & 1) {
|
||||
YuvPixel(src_yuy2[0], src_yuy2[1], src_yuy2[3], rgb_buf + 0, rgb_buf + 1,
|
||||
rgb_buf + 2, yuvconstants);
|
||||
rgb_buf[3] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert YUY2 to ARGB.
|
||||
LIBYUV_API
|
||||
int YUY2ToARGB(const uint8* src_yuy2,
|
||||
int src_stride_yuy2,
|
||||
uint8* dst_argb,
|
||||
int dst_stride_argb,
|
||||
int width,
|
||||
int height) {
|
||||
int y;
|
||||
void(*YUY2ToARGBRow)(const uint8* src_yuy2, uint8* dst_argb,
|
||||
const struct YuvConstants* yuvconstants, int width) =
|
||||
YUY2ToARGBRow_C;
|
||||
if (!src_yuy2 || !dst_argb || width <= 0 || height == 0) {
|
||||
return -1;
|
||||
}
|
||||
// Negative height means invert the image.
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
|
||||
src_stride_yuy2 = -src_stride_yuy2;
|
||||
}
|
||||
// Coalesce rows.
|
||||
if (src_stride_yuy2 == width * 2 && dst_stride_argb == width * 4) {
|
||||
width *= height;
|
||||
height = 1;
|
||||
src_stride_yuy2 = dst_stride_argb = 0;
|
||||
}
|
||||
#if defined(HAS_YUY2TOARGBROW_SSSE3)
|
||||
if (TestCpuFlag(kCpuHasSSSE3)) {
|
||||
YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_YUY2TOARGBROW_AVX2)
|
||||
if (TestCpuFlag(kCpuHasAVX2)) {
|
||||
YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2;
|
||||
if (IS_ALIGNED(width, 32)) {
|
||||
YUY2ToARGBRow = YUY2ToARGBRow_AVX2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_YUY2TOARGBROW_NEON)
|
||||
if (TestCpuFlag(kCpuHasNEON)) {
|
||||
YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
|
||||
if (IS_ALIGNED(width, 8)) {
|
||||
YUY2ToARGBRow = YUY2ToARGBRow_NEON;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_YUY2TOARGBROW_MSA)
|
||||
if (TestCpuFlag(kCpuHasMSA)) {
|
||||
YUY2ToARGBRow = YUY2ToARGBRow_Any_MSA;
|
||||
if (IS_ALIGNED(width, 8)) {
|
||||
YUY2ToARGBRow = YUY2ToARGBRow_MSA;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (y = 0; y < height; ++y) {
|
||||
YUY2ToARGBRow(src_yuy2, dst_argb, &kYuvI601Constants, width);
|
||||
src_yuy2 += src_stride_yuy2;
|
||||
dst_argb += dst_stride_argb;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
#include "Cxbx.h"
|
||||
|
||||
typedef int08 int8;
|
||||
typedef uint08 uint8;
|
||||
|
||||
// From libyuv\include\libyuv\basic_types.h :
|
||||
#define LIBYUV_API
|
||||
|
||||
LIBYUV_API
|
||||
int YUY2ToARGB(const uint8* src_yuy2,
|
||||
int src_stride_yuy2,
|
||||
uint8* dst_argb,
|
||||
int dst_stride_argb,
|
||||
int width,
|
||||
int height);
|
Loading…
Reference in New Issue