Merge pull request #289 from PatrickvL/master
UpdateOverlay improvements
This commit is contained in:
commit
0e63d5055f
|
@ -366,6 +366,20 @@ VOID CxbxSetPixelContainerHeader
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID CxbxReleaseBackBufferLock()
|
||||||
|
{
|
||||||
|
XTL::IDirect3DSurface8 *pBackBuffer = nullptr;
|
||||||
|
|
||||||
|
if (D3D_OK == g_pD3DDevice8->GetBackBuffer(0, XTL::D3DBACKBUFFER_TYPE_MONO, &pBackBuffer))
|
||||||
|
{
|
||||||
|
// TODO : assert(pBackBuffer != nullptr);
|
||||||
|
|
||||||
|
pBackBuffer->UnlockRect();
|
||||||
|
pBackBuffer->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Direct3D initialization (called before emulation begins)
|
// Direct3D initialization (called before emulation begins)
|
||||||
VOID XTL::EmuD3DInit()
|
VOID XTL::EmuD3DInit()
|
||||||
{
|
{
|
||||||
|
@ -4273,14 +4287,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Present)
|
||||||
|
|
||||||
HRESULT hRet = S_OK;
|
HRESULT hRet = S_OK;
|
||||||
|
|
||||||
// release back buffer lock
|
CxbxReleaseBackBufferLock();
|
||||||
{
|
|
||||||
IDirect3DSurface8 *pBackBuffer;
|
|
||||||
|
|
||||||
g_pD3DDevice8->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
|
|
||||||
|
|
||||||
pBackBuffer->UnlockRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make a video option to wait for VBlank before calling Present.
|
// 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
|
// Makes syncing to 30fps easier (which is the native frame rate for Azurik
|
||||||
|
@ -4351,14 +4358,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Swap)
|
||||||
if(Flags != 0)
|
if(Flags != 0)
|
||||||
EmuWarning("XTL::EmuD3DDevice_Swap: Flags != 0");
|
EmuWarning("XTL::EmuD3DDevice_Swap: Flags != 0");
|
||||||
|
|
||||||
// release back buffer lock
|
CxbxReleaseBackBufferLock();
|
||||||
{
|
|
||||||
IDirect3DSurface8 *pBackBuffer;
|
|
||||||
|
|
||||||
g_pD3DDevice8->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
|
|
||||||
|
|
||||||
if(pBackBuffer) pBackBuffer->UnlockRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make a video option to wait for VBlank before calling Present.
|
// 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
|
// Makes syncing to 30fps easier (which is the native frame rate for Azurik
|
||||||
|
@ -6010,6 +6010,13 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_EnableOverlay)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Based on http://codereview.stackexchange.com/questions/6502/fastest-way-to-clamp-an-integer-to-the-range-0-255
|
||||||
|
inline uint08 ClampIntToByte(int x)
|
||||||
|
{
|
||||||
|
int r = x > 255 ? 255 : x;
|
||||||
|
return r < 0 ? 0 : (uint08)r;
|
||||||
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * patch: D3DDevice_UpdateOverlay
|
// * patch: D3DDevice_UpdateOverlay
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -6042,12 +6049,10 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_UpdateOverlay)
|
||||||
DDSURFACEDESC2 ddsd2;
|
DDSURFACEDESC2 ddsd2;
|
||||||
|
|
||||||
ZeroMemory(&ddsd2, sizeof(ddsd2));
|
ZeroMemory(&ddsd2, sizeof(ddsd2));
|
||||||
|
|
||||||
ddsd2.dwSize = sizeof(ddsd2);
|
ddsd2.dwSize = sizeof(ddsd2);
|
||||||
|
|
||||||
if(FAILED(g_pDDSOverlay7->Lock(NULL, &ddsd2, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL)))
|
if(FAILED(g_pDDSOverlay7->Lock(NULL, &ddsd2, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL)))
|
||||||
EmuWarning("Unable to lock overlay surface!");
|
EmuWarning("Unable to lock overlay surface!");
|
||||||
|
else
|
||||||
// copy data
|
// copy data
|
||||||
{
|
{
|
||||||
char *pDest = (char*)ddsd2.lpSurface;
|
char *pDest = (char*)ddsd2.lpSurface;
|
||||||
|
@ -6069,9 +6074,9 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_UpdateOverlay)
|
||||||
pSour += g_dwOverlayP;
|
pSour += g_dwOverlayP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
g_pDDSOverlay7->Unlock(NULL);
|
g_pDDSOverlay7->Unlock(NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update overlay!
|
// update overlay!
|
||||||
|
@ -6102,7 +6107,6 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_UpdateOverlay)
|
||||||
DDOVERLAYFX ddofx;
|
DDOVERLAYFX ddofx;
|
||||||
|
|
||||||
ZeroMemory(&ddofx, sizeof(ddofx));
|
ZeroMemory(&ddofx, sizeof(ddofx));
|
||||||
|
|
||||||
ddofx.dwSize = sizeof(DDOVERLAYFX);
|
ddofx.dwSize = sizeof(DDOVERLAYFX);
|
||||||
ddofx.dckDestColorkey.dwColorSpaceLowValue = 0;
|
ddofx.dckDestColorkey.dwColorSpaceLowValue = 0;
|
||||||
ddofx.dckDestColorkey.dwColorSpaceHighValue = 0;
|
ddofx.dckDestColorkey.dwColorSpaceHighValue = 0;
|
||||||
|
@ -6114,87 +6118,109 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_UpdateOverlay)
|
||||||
// TODO: dont assume X8R8G8B8 ?
|
// TODO: dont assume X8R8G8B8 ?
|
||||||
D3DLOCKED_RECT LockedRectDest;
|
D3DLOCKED_RECT LockedRectDest;
|
||||||
|
|
||||||
IDirect3DSurface8 *pBackBuffer=0;
|
IDirect3DSurface8 *pBackBuffer = 0;
|
||||||
|
|
||||||
HRESULT hRet = g_pD3DDevice8->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
|
HRESULT hRet = g_pD3DDevice8->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
|
||||||
|
|
||||||
// if we obtained the backbuffer, manually translate the YUY2 into the backbuffer format
|
// if we obtained the backbuffer, manually translate the YUY2 into the backbuffer format
|
||||||
if(hRet == D3D_OK && pBackBuffer->LockRect(&LockedRectDest, NULL, NULL) == D3D_OK)
|
if (hRet == D3D_OK && pBackBuffer->LockRect(&LockedRectDest, NULL, NULL) == D3D_OK)
|
||||||
{
|
{
|
||||||
uint08 *pCurByte = (uint08*)pSurface->Lock;
|
uint08 *pbSource = (uint08*)pSurface->Lock;
|
||||||
|
uint08 *pbDest = (uint08*)LockedRectDest.pBits;
|
||||||
uint08 *pDest = (uint08*)LockedRectDest.pBits;
|
uint32 dx = 0, dy = 0;
|
||||||
|
|
||||||
uint32 dx=0, dy=0;
|
|
||||||
|
|
||||||
uint32 dwImageSize = g_dwOverlayP*g_dwOverlayH;
|
uint32 dwImageSize = g_dwOverlayP*g_dwOverlayH;
|
||||||
|
|
||||||
// grayscale
|
// Get backbuffer dimenions; TODO : remember this once, at creation/resize time
|
||||||
|
D3DSURFACE_DESC BackBufferDesc;
|
||||||
|
pBackBuffer->GetDesc(&BackBufferDesc);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// grayscale - TODO : Either remove or make configurable
|
||||||
if(false)
|
if(false)
|
||||||
{
|
{
|
||||||
for(uint32 y=0;y<g_dwOverlayH;y++)
|
// Clip to backbuffer height :
|
||||||
|
for(uint32 y=0;y<H;y++)
|
||||||
{
|
{
|
||||||
uint32 stop = g_dwOverlayW*4;
|
uint32 stop = g_dwOverlayW *4;
|
||||||
for(uint32 x=0;x<stop;x+=4)
|
for(uint32 x=0;x<stop;x+=4)
|
||||||
{
|
{
|
||||||
uint08 Y = *pCurByte;
|
uint08 Y = *pbSource;
|
||||||
|
|
||||||
pDest[x+0] = Y;
|
// Clip to backbuffer width :
|
||||||
pDest[x+1] = Y;
|
if (x / 4 < W)
|
||||||
pDest[x+2] = Y;
|
{
|
||||||
pDest[x+3] = 0xFF;
|
pbDest[x + 0] = Y;
|
||||||
|
pbDest[x + 1] = Y;
|
||||||
|
pbDest[x + 2] = Y;
|
||||||
|
pbDest[x + 3] = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
pCurByte+=2;
|
pbSource += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
pDest += LockedRectDest.Pitch;
|
pbDest += LockedRectDest.Pitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// full color conversion (YUY2->XRGB)
|
// full color conversion (YUY2->XRGB)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// The following is a combination of https://pastebin.com/mDcwqJV3 and
|
||||||
|
// https://en.wikipedia.org/wiki/YUV#Y.E2.80.B2UV422_to_RGB888_conversion
|
||||||
|
const int K1 = int(1.402f * (1 << 16));
|
||||||
|
const int K2 = int(0.334f * (1 << 16));
|
||||||
|
const int K3 = int(0.714f * (1 << 16));
|
||||||
|
const int K4 = int(1.772f * (1 << 16));
|
||||||
|
|
||||||
for(uint32 v=0;v<dwImageSize;v+=4)
|
for(uint32 v=0;v<dwImageSize;v+=4)
|
||||||
{
|
{
|
||||||
float Y[2], U, V;
|
// Clip to backbuffer width :
|
||||||
|
if (dx < W)
|
||||||
Y[0] = *pCurByte++;
|
|
||||||
U = *pCurByte++;
|
|
||||||
Y[1] = *pCurByte++;
|
|
||||||
V = *pCurByte++;
|
|
||||||
|
|
||||||
int a=0;
|
|
||||||
for(int x=0;x<2;x++)
|
|
||||||
{
|
{
|
||||||
float R = Y[a] + 1.402f*(V-128);
|
uint8_t Y0 = pbSource[0];
|
||||||
float G = Y[a] - 0.344f*(U-128) - 0.714f*(V-128);
|
uint8_t Cb = pbSource[1];
|
||||||
float B = Y[a] + 1.772f*(U-128);
|
uint8_t Y1 = pbSource[2];
|
||||||
|
uint8_t Cr = pbSource[3];
|
||||||
|
|
||||||
R = (R < 0) ? 0 : ((R > 255) ? 255 : R);
|
int nCb = Cb - 128;
|
||||||
G = (G < 0) ? 0 : ((G > 255) ? 255 : G);
|
int nCr = Cr - 128;
|
||||||
B = (B < 0) ? 0 : ((B > 255) ? 255 : B);
|
|
||||||
|
|
||||||
uint32 i = (dy*LockedRectDest.Pitch+(dx+x)*4);
|
int Rd = (K1 * nCr) >> 16;
|
||||||
|
int Gd = ((K2 * nCb) + (K3 * nCr)) >> 16;
|
||||||
|
int Bd = (K4 * nCb) >> 16;
|
||||||
|
|
||||||
pDest[i+0] = (uint08)B;
|
uint32 i = (dy * LockedRectDest.Pitch) + (dx * 4);
|
||||||
pDest[i+1] = (uint08)G;
|
|
||||||
pDest[i+2] = (uint08)R;
|
|
||||||
pDest[i+3] = 0xFF;
|
|
||||||
|
|
||||||
a++;
|
pbDest[i + 0] = ClampIntToByte((int)Y0 + Bd);
|
||||||
|
pbDest[i + 1] = ClampIntToByte((int)Y0 - Gd);
|
||||||
|
pbDest[i + 2] = ClampIntToByte((int)Y0 + Rd);
|
||||||
|
pbDest[i + 3] = 0xFF;
|
||||||
|
|
||||||
|
pbDest[i + 4] = ClampIntToByte((int)Y1 + Bd);
|
||||||
|
pbDest[i + 5] = ClampIntToByte((int)Y1 - Gd);
|
||||||
|
pbDest[i + 6] = ClampIntToByte((int)Y1 + Rd);
|
||||||
|
pbDest[i + 7] = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
dx+=2;
|
pbSource += 4;
|
||||||
|
dx += 2;
|
||||||
if((dx % g_dwOverlayW) == 0)
|
if ((dx % g_dwOverlayW) == 0)
|
||||||
{
|
{
|
||||||
dy++;
|
dy++;
|
||||||
dx=0;
|
// Clip to backbuffer height :
|
||||||
|
if (dy >= H)
|
||||||
|
break;
|
||||||
|
|
||||||
|
dx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pBackBuffer->UnlockRect();
|
pBackBuffer->UnlockRect();
|
||||||
|
pBackBuffer->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update overlay if present was not called since the last call to
|
// Update overlay if present was not called since the last call to
|
||||||
|
|
Loading…
Reference in New Issue