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)
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue