Merge pull request #289 from PatrickvL/master

UpdateOverlay improvements
This commit is contained in:
Luke Usher 2017-03-30 13:06:11 +01:00 committed by GitHub
commit 0e63d5055f
1 changed files with 93 additions and 67 deletions

View File

@ -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)
VOID XTL::EmuD3DInit()
{
@ -4273,14 +4287,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Present)
HRESULT hRet = S_OK;
// release back buffer lock
{
IDirect3DSurface8 *pBackBuffer;
g_pD3DDevice8->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
pBackBuffer->UnlockRect();
}
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
@ -4351,14 +4358,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Swap)
if(Flags != 0)
EmuWarning("XTL::EmuD3DDevice_Swap: Flags != 0");
// release back buffer lock
{
IDirect3DSurface8 *pBackBuffer;
g_pD3DDevice8->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
if(pBackBuffer) pBackBuffer->UnlockRect();
}
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
@ -6010,6 +6010,13 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_EnableOverlay)
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
// ******************************************************************
@ -6042,12 +6049,10 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_UpdateOverlay)
DDSURFACEDESC2 ddsd2;
ZeroMemory(&ddsd2, sizeof(ddsd2));
ddsd2.dwSize = sizeof(ddsd2);
if(FAILED(g_pDDSOverlay7->Lock(NULL, &ddsd2, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL)))
EmuWarning("Unable to lock overlay surface!");
else
// copy data
{
char *pDest = (char*)ddsd2.lpSurface;
@ -6069,10 +6074,10 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_UpdateOverlay)
pSour += g_dwOverlayP;
}
}
}
g_pDDSOverlay7->Unlock(NULL);
}
}
// update overlay!
if(g_bSupportsYUY2)
@ -6102,7 +6107,6 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_UpdateOverlay)
DDOVERLAYFX ddofx;
ZeroMemory(&ddofx, sizeof(ddofx));
ddofx.dwSize = sizeof(DDOVERLAYFX);
ddofx.dckDestColorkey.dwColorSpaceLowValue = 0;
ddofx.dckDestColorkey.dwColorSpaceHighValue = 0;
@ -6115,79 +6119,100 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_UpdateOverlay)
D3DLOCKED_RECT LockedRectDest;
IDirect3DSurface8 *pBackBuffer = 0;
HRESULT hRet = g_pD3DDevice8->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
// if we obtained the backbuffer, manually translate the YUY2 into the backbuffer format
if (hRet == D3D_OK && pBackBuffer->LockRect(&LockedRectDest, NULL, NULL) == D3D_OK)
{
uint08 *pCurByte = (uint08*)pSurface->Lock;
uint08 *pDest = (uint08*)LockedRectDest.pBits;
uint08 *pbSource = (uint08*)pSurface->Lock;
uint08 *pbDest = (uint08*)LockedRectDest.pBits;
uint32 dx = 0, dy = 0;
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)
{
for(uint32 y=0;y<g_dwOverlayH;y++)
// Clip to backbuffer height :
for(uint32 y=0;y<H;y++)
{
uint32 stop = g_dwOverlayW *4;
for(uint32 x=0;x<stop;x+=4)
{
uint08 Y = *pCurByte;
uint08 Y = *pbSource;
pDest[x+0] = Y;
pDest[x+1] = Y;
pDest[x+2] = Y;
pDest[x+3] = 0xFF;
pCurByte+=2;
// Clip to backbuffer width :
if (x / 4 < W)
{
pbDest[x + 0] = Y;
pbDest[x + 1] = Y;
pbDest[x + 2] = Y;
pbDest[x + 3] = 0xFF;
}
pDest += LockedRectDest.Pitch;
pbSource += 2;
}
pbDest += LockedRectDest.Pitch;
}
}
// full color conversion (YUY2->XRGB)
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)
{
float Y[2], U, V;
Y[0] = *pCurByte++;
U = *pCurByte++;
Y[1] = *pCurByte++;
V = *pCurByte++;
int a=0;
for(int x=0;x<2;x++)
// Clip to backbuffer width :
if (dx < W)
{
float R = Y[a] + 1.402f*(V-128);
float G = Y[a] - 0.344f*(U-128) - 0.714f*(V-128);
float B = Y[a] + 1.772f*(U-128);
uint8_t Y0 = pbSource[0];
uint8_t Cb = pbSource[1];
uint8_t Y1 = pbSource[2];
uint8_t Cr = pbSource[3];
R = (R < 0) ? 0 : ((R > 255) ? 255 : R);
G = (G < 0) ? 0 : ((G > 255) ? 255 : G);
B = (B < 0) ? 0 : ((B > 255) ? 255 : B);
int nCb = Cb - 128;
int nCr = Cr - 128;
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;
pDest[i+1] = (uint08)G;
pDest[i+2] = (uint08)R;
pDest[i+3] = 0xFF;
uint32 i = (dy * LockedRectDest.Pitch) + (dx * 4);
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;
}
pbSource += 4;
dx += 2;
if ((dx % g_dwOverlayW) == 0)
{
dy++;
// Clip to backbuffer height :
if (dy >= H)
break;
dx = 0;
}
@ -6195,6 +6220,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_UpdateOverlay)
}
pBackBuffer->UnlockRect();
pBackBuffer->Release();
}
// Update overlay if present was not called since the last call to