diff --git a/build/win32/Cxbx.vcxproj b/build/win32/Cxbx.vcxproj index f2d5be566..e7b9e89bd 100644 --- a/build/win32/Cxbx.vcxproj +++ b/build/win32/Cxbx.vcxproj @@ -283,7 +283,6 @@ $(SOLUTIONDIR)Export.bat - @@ -544,7 +543,6 @@ $(SOLUTIONDIR)Export.bat %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) diff --git a/build/win32/Cxbx.vcxproj.filters b/build/win32/Cxbx.vcxproj.filters index 4f0b0415e..92ba99d11 100644 --- a/build/win32/Cxbx.vcxproj.filters +++ b/build/win32/Cxbx.vcxproj.filters @@ -199,9 +199,6 @@ GUI - - Emulator - @@ -552,9 +549,6 @@ GUI - - Emulator - diff --git a/src/CxbxKrnl/EmuD3D8.cpp b/src/CxbxKrnl/EmuD3D8.cpp index d26eddad4..f6912c6ab 100644 --- a/src/CxbxKrnl/EmuD3D8.cpp +++ b/src/CxbxKrnl/EmuD3D8.cpp @@ -53,7 +53,6 @@ namespace xboxkrnl #include "EmuAlloc.h" #include "MemoryManager.h" #include "EmuXTL.h" -#include "libyuv_extract.h" // for YUY2ToARGB #include #include @@ -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,69 +4277,17 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Present) ");\n", pSourceRect, pDestRect, pDummy1, pDummy2); - HRESULT hRet = S_OK; - - 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 ); - - hRet = g_pD3DDevice8->Present(pSourceRect, pDestRect, (HWND)pDummy1, (CONST RGNDATA*)pDummy2); - - // Put primitives per frame in the title - /*{ - char szString[64]; - - sprintf( szString, "Cxbx: PPF(%d)", g_dwPrimPerFrame ); - - SetWindowText( CxbxKrnl_hEmuParent, szString ); - - g_dwPrimPerFrame = 0; - }*/ - - // not really accurate because you definately dont always present on every vblank - g_VBData.Swap = g_VBData.VBlank; - - if(g_VBData.VBlank == g_VBLastSwap + 1) - g_VBData.Flags = 1; // D3DVBLANK_SWAPDONE - else - { - g_VBData.Flags = 2; // D3DVBLANK_SWAPMISSED - g_SwapData.MissedVBlanks++; - } - - // Handle Swap Callback function - { - g_SwapData.Swap++; - - if(g_pSwapCallback != NULL) - { - - g_pSwapCallback(&g_SwapData); - - } - } - - g_bHackUpdateSoftwareOverlay = FALSE; - - - - return hRet; + return EMUPATCH(D3DDevice_Swap)(CXBX_SWAP_PRESENT_FORWARD); // Xbox present ignores } // ****************************************************************** // * patch: D3DDevice_Swap // ****************************************************************** -HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Swap) +DWORD WINAPI XTL::EMUPATCH(D3DDevice_Swap) ( DWORD Flags ) { - - DbgPrintf("EmuD3D8: EmuD3DDevice_Swap\n" "(\n" " Flags : 0x%.08X\n" @@ -4348,7 +4296,8 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Swap) // TODO: Ensure this flag is always the same across library versions if(Flags != 0) - EmuWarning("XTL::EmuD3DDevice_Swap: Flags != 0"); + if (Flags != CXBX_SWAP_PRESENT_FORWARD) // Avoid a warning when forwarded + EmuWarning("XTL::EmuD3DDevice_Swap: Flags != 0"); CxbxReleaseBackBufferLock(); @@ -4358,7 +4307,33 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Swap) // g_pDD7->WaitForVerticalBlank( DDWAITVB_BLOCKEND, NULL ); // g_pDD7->WaitForVerticalBlank( DDWAITVB_BLOCKEND, NULL ); - HRESULT hRet = g_pD3DDevice8->Present(0, 0, 0, 0); + 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]; + + sprintf( szString, "Cxbx: PPF(%d)", g_dwPrimPerFrame ); + + SetWindowText( CxbxKrnl_hEmuParent, szString ); + + 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; + + if (g_VBData.VBlank == g_VBLastSwap + 1) + g_VBData.Flags = 1; // D3DVBLANK_SWAPDONE + else + { + g_VBData.Flags = 2; // D3DVBLANK_SWAPMISSED + g_SwapData.MissedVBlanks++; + } + } // Handle Swap Callback function { @@ -4374,9 +4349,13 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Swap) 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; + 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)) @@ -4858,20 +4834,27 @@ HRESULT WINAPI XTL::EMUPATCH(D3DResource_Register) pSrc += dwMipPitch; } } - else - { + else + { if (level == 0) pResource->Data = (DWORD)pSrc; if((DWORD)pSrc == 0x80000000) - { + { // 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,23 +4872,35 @@ 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) { - if ((DWORD)LockedRect.Pitch == dwMipPitch && dwMipPitch == dwMipWidth*dwBPP) + memcpy(pDest, pSrc + dwMipOffs, dwMipWidth*dwMipHeight*dwBPP); + } + else + { + for (DWORD v = 0; v < dwMipHeight; v++) { - memcpy(pDest, pSrc + dwMipOffs, dwMipWidth*dwMipHeight*dwBPP); - } - else - { - for (DWORD v = 0; v < dwMipHeight; v++) - { - memcpy(pDest, pSrc + dwMipOffs, dwMipWidth*dwBPP); + memcpy(pDest, pSrc + dwMipOffs, dwMipWidth*dwBPP); - pDest += LockedRect.Pitch; - pSrc += dwMipPitch; - } + pDest += LockedRect.Pitch; + pSrc += dwMipPitch; } } } @@ -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; - } - } + // 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) + RECT DestRect = { 0 }; + { + // If there's a destination rectangle given, copy that into our local variable : + if (DstRect != NULL) + DestRect = *DstRect; + + // Use our (bounded) copy when bounds exceed : + if (DestRect.right > BackBufferDesc.Width) { + DestRect.right = BackBufferDesc.Width; + DstRect = &DestRect; + } + + if (g_dwOverlayH > BackBufferDesc.Height) { + DestRect.bottom = BackBufferDesc.Height; + DstRect = &DestRect; } } - // 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 - } + uint08 *pYUY2Input = (uint08*)pSurface->Lock; // TODO : DxbxGetDataFromXboxResource(pSurface); - // 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); - - // full color conversion (YUY2->XRGB) - YUY2ToARGB(pYUY2Input, g_dwOverlayP, pARGBOutput, LockedRectDest.Pitch, W, H); - - pOverlayBufferSurface->UnlockRect(); // TODO : Could this be done after calling D3DXLoadSurfaceFromSurface (and would that improve performance)? - - 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( - /* pDestSurface = */ pBackBufferSurface, - /* pDestPalette = */ nullptr, // Palette not needed for YUY2 - DstRect, - /* pSrcSurface = */ pOverlayBufferSurface, - /* pSrcPalette = */ nullptr, // Palette not needed for YUY2 - SrcRect, - /* Filter = */ D3DX_FILTER_POINT, // Dxbx note : D3DX_FILTER_LINEAR gives a smoother image, but 'bleeds' across borders - /* ColorKey = */ ColorKey) != D3D_OK) { - DbgPrintf("EmuD3D8 : UpdateOverlay could not convert buffer!\n"); - } - } + // 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 + /* 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 + /* pSrcRect = */ &SourRect, + /* Filter = */ D3DX_FILTER_POINT, // Dxbx note : D3DX_FILTER_LINEAR gives a smoother image, but 'bleeds' across borders + /* 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 ); @@ -10487,4 +10446,4 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_GetMaterial)(D3DMATERIAL8* pMaterial) return S_OK; -} +} \ No newline at end of file diff --git a/src/CxbxKrnl/EmuD3D8.h b/src/CxbxKrnl/EmuD3D8.h index ed6819429..393bcc91e 100644 --- a/src/CxbxKrnl/EmuD3D8.h +++ b/src/CxbxKrnl/EmuD3D8.h @@ -669,7 +669,7 @@ HRESULT WINAPI EMUPATCH(D3DDevice_Present) // ****************************************************************** // * patch: D3DDevice_Swap // ****************************************************************** -HRESULT WINAPI EMUPATCH(D3DDevice_Swap) +DWORD WINAPI EMUPATCH(D3DDevice_Swap) ( DWORD Flags ); diff --git a/src/CxbxKrnl/libyuv_extract.cpp b/src/CxbxKrnl/libyuv_extract.cpp deleted file mode 100644 index aa46e04a5..000000000 --- a/src/CxbxKrnl/libyuv_extract.cpp +++ /dev/null @@ -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; -} diff --git a/src/CxbxKrnl/libyuv_extract.h b/src/CxbxKrnl/libyuv_extract.h deleted file mode 100644 index bafae1b69..000000000 --- a/src/CxbxKrnl/libyuv_extract.h +++ /dev/null @@ -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); \ No newline at end of file