From c990b725b4a44e689b09224969e562f510a464f2 Mon Sep 17 00:00:00 2001 From: Justin Miller Date: Wed, 28 Jan 2026 22:28:43 -0800 Subject: [PATCH] [WIN32SS] Remove NATIVE_REACTX check - reenable Oleg's code (#8554) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [REACTX] Simple Non-AGP ddraw allocator * [WIN32SS] remove NATIVE_REACTX check - reenable oleg's code JIRA issue: CORE-19142 Co-authored-by: Hermès BÉLUSCA - MAÏTO --- win32ss/CMakeLists.txt | 4 - win32ss/gdi/eng/pdevobj.c | 16 --- win32ss/reactx/dxg/CMakeLists.txt | 1 + win32ss/reactx/dxg/ddraw.c | 43 +++++++ win32ss/reactx/dxg/dxg_driver.h | 16 +-- win32ss/reactx/dxg/dxgallocator.c | 207 ++++++++++++++++++++++++++++++ 6 files changed, 257 insertions(+), 30 deletions(-) create mode 100644 win32ss/reactx/dxg/dxgallocator.c diff --git a/win32ss/CMakeLists.txt b/win32ss/CMakeLists.txt index d82cc51e31c..b1afc451614 100644 --- a/win32ss/CMakeLists.txt +++ b/win32ss/CMakeLists.txt @@ -4,10 +4,6 @@ set(USE_DIBLIB FALSE) # Give WIN32 subsystem its own project. PROJECT(WIN32SS) -if (NATIVE_REACTX) - add_definitions(-DNATIVE_REACTX) -endif() - add_subdirectory(drivers) if(USE_DIBLIB) diff --git a/win32ss/gdi/eng/pdevobj.c b/win32ss/gdi/eng/pdevobj.c index ae22bb2851c..9bc2f88684e 100644 --- a/win32ss/gdi/eng/pdevobj.c +++ b/win32ss/gdi/eng/pdevobj.c @@ -337,7 +337,6 @@ PDEVOBJ_pSurface( return ppdev->pSurface; } -#ifdef NATIVE_REACTX BOOL PDEVOBJ_bEnableDirectDraw( _Inout_ PPDEVOBJ ppdev) @@ -386,7 +385,6 @@ PDEVOBJ_vSwitchDirectDraw( TRACE("DxDdDynamicModeChange(ppdev %p, ppdev2 %p)\n", ppdev, ppdev2); pfnDdDynamicModeChange((HDEV)ppdev, (HDEV)ppdev2, 0); } -#endif VOID PDEVOBJ_vEnableDisplay( @@ -417,9 +415,7 @@ PDEVOBJ_bDisableDisplay( if (ppdev->flFlags & PDEV_DISABLED) return TRUE; -#ifdef NATIVE_REACTX PDEVOBJ_vSuspendDirectDraw(ppdev); -#endif TRACE("DrvAssertMode(dhpdev %p, FALSE)\n", ppdev->dhpdev); assertVal = ppdev->pfn.AssertMode(ppdev->dhpdev, FALSE); @@ -604,7 +600,6 @@ PDEVOBJ_Create( return NULL; } -#ifdef NATIVE_REACTX /* Enable DirectDraw */ if (!PDEVOBJ_bEnableDirectDraw(ppdev)) { @@ -613,7 +608,6 @@ PDEVOBJ_Create( EngUnloadImage(pldev); return NULL; } -#endif /* Remove some acceleration capabilities from driver */ PDEVOBJ_vFilterDriverHooks(ppdev); @@ -698,10 +692,8 @@ PDEVOBJ_bDynamicModeChange( ppdev->pfn.CompletePDEV(ppdev->dhpdev, (HDEV)ppdev); ppdev2->pfn.CompletePDEV(ppdev2->dhpdev, (HDEV)ppdev2); -#ifdef NATIVE_REACTX /* Switch DirectDraw mode */ PDEVOBJ_vSwitchDirectDraw(ppdev, ppdev2); -#endif return TRUE; } @@ -732,10 +724,8 @@ PDEVOBJ_bSwitchMode( if (!PDEVOBJ_bDisableDisplay(ppdev)) { DPRINT1("PDEVOBJ_bDisableDisplay() failed\n"); -#ifdef NATIVE_REACTX /* Resume DirectDraw in case of failure */ PDEVOBJ_vResumeDirectDraw(ppdev); -#endif goto leave; } @@ -756,11 +746,9 @@ PDEVOBJ_bSwitchMode( goto leave2; } -#ifdef NATIVE_REACTX /* 4. Temporarily suspend DirectDraw for mode change */ PDEVOBJ_vSuspendDirectDraw(ppdev); PDEVOBJ_vSuspendDirectDraw(ppdevTmp); -#endif /* 5. Switch the PDEVs */ if (!PDEVOBJ_bDynamicModeChange(ppdev, ppdevTmp)) @@ -770,20 +758,16 @@ PDEVOBJ_bSwitchMode( goto leave2; } -#ifdef NATIVE_REACTX /* 6. Resume DirectDraw */ PDEVOBJ_vResumeDirectDraw(ppdev); PDEVOBJ_vResumeDirectDraw(ppdevTmp); -#endif /* Release temp PDEV */ PDEVOBJ_vRelease(ppdevTmp); -#ifdef NATIVE_REACTX /* Re-initialize DirectDraw data */ ppdev->pEDDgpl->hDev = (HDEV)ppdev; ppdev->pEDDgpl->dhpdev = ppdev->dhpdev; -#endif /* Update primary display capabilities */ if (ppdev == gpmdev->ppdevGlobal) diff --git a/win32ss/reactx/dxg/CMakeLists.txt b/win32ss/reactx/dxg/CMakeLists.txt index b83056b7f14..bac0a9dd239 100644 --- a/win32ss/reactx/dxg/CMakeLists.txt +++ b/win32ss/reactx/dxg/CMakeLists.txt @@ -8,6 +8,7 @@ list(APPEND SOURCE dd.c ddraw.c ddsurf.c + dxgallocator.c eng.c historic.c dxg_int.h) diff --git a/win32ss/reactx/dxg/ddraw.c b/win32ss/reactx/dxg/ddraw.c index 12ed339367d..c220c3af39a 100644 --- a/win32ss/reactx/dxg/ddraw.c +++ b/win32ss/reactx/dxg/ddraw.c @@ -189,6 +189,49 @@ VOID intDdEnableDriver(PEDD_DIRECTDRAW_GLOBAL peDdGl) intDdGetAllDriverInfo(peDdGl); + /* + * Initialize video memory heaps for surface allocation. + * This is done specifically for vmware, nothing else is likely to use it yet. + * But it's done well enough that native ddraw.dll seems happy. + */ + if (peDdGl->pvmList && peDdGl->dwNumHeaps > 0) + { + VIDEOMEMORY *VidMemEntry; + LPVMEMHEAP HeapStruct; + DWORD HeapIndex; + DWORD DisplayPitch = peDdGl->ddHalInfo.vmiData.lDisplayPitch; + + for (HeapIndex = 0, VidMemEntry = peDdGl->pvmList; + HeapIndex < peDdGl->dwNumHeaps; + HeapIndex++, VidMemEntry++) + { + if (VidMemEntry->dwFlags & (VIDMEM_ISHEAP | VIDMEM_HEAPDISABLED)) + continue; + + HeapStruct = (LPVMEMHEAP)EngAllocMem(FL_ZERO_MEMORY, sizeof(*HeapStruct), TAG_GDDV); + if (!HeapStruct) + { + VidMemEntry->dwFlags |= VIDMEM_HEAPDISABLED; + continue; + } + + if (VidMemEntry->dwFlags & VIDMEM_ISLINEAR) + { + HeapStruct->dwFlags = VMEMHEAP_LINEAR; + HeapStruct->dwTotalSize = VidMemEntry->fpEnd - VidMemEntry->fpStart + 1; + } + else + { + HeapStruct->dwFlags = VMEMHEAP_RECTANGULAR; + HeapStruct->stride = DisplayPitch ? DisplayPitch : VidMemEntry->dwWidth; + HeapStruct->dwTotalSize = HeapStruct->stride * VidMemEntry->dwHeight; + } + + VidMemEntry->lpHeap = HeapStruct; + VidMemEntry->dwFlags |= VIDMEM_ISHEAP; + } + } + // enable DirectDraw acceleration peDdGl->fl |= 1; } diff --git a/win32ss/reactx/dxg/dxg_driver.h b/win32ss/reactx/dxg/dxg_driver.h index 3bab32833d8..bf9482b945a 100644 --- a/win32ss/reactx/dxg/dxg_driver.h +++ b/win32ss/reactx/dxg/dxg_driver.h @@ -631,18 +631,14 @@ DxDvpReleaseNotification( return 0; } -DWORD +FLATPTR NTAPI DxDdHeapVidMemAllocAligned( - PVOID p1, - PVOID p2, - PVOID p3, - PVOID p4, - PVOID p5) -{ - TRACE(); - return 0; -} + LPVIDMEM DdrawVidMem, + DWORD Width, + DWORD Height, + LPSURFACEALIGNMENT Alignment, + LPDWORD ResolvedPitch); DWORD NTAPI diff --git a/win32ss/reactx/dxg/dxgallocator.c b/win32ss/reactx/dxg/dxgallocator.c new file mode 100644 index 00000000000..e8909130009 --- /dev/null +++ b/win32ss/reactx/dxg/dxgallocator.c @@ -0,0 +1,207 @@ +/* + * PROJECT: ReactX Graphics Legacy Kernel + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: DirectDraw video memory allocator + * COPYRIGHT: Copyright 2026 Justin Miller + */ + +#include + +FLATPTR +WINAPI +DdrawMemAlloc( + _In_ LPVMEMHEAP pvmh, + _In_ DWORD Width, + _In_ DWORD Height, + _Out_opt_ LPDWORD AllocSize, + _In_opt_ LPSURFACEALIGNMENT Alignment, + _Out_opt_ LPDWORD ResolvedPitch) +{ + FLATPTR MemPtr; + DWORD RequiredBytes; + DWORD CurrentPos; + + if (!pvmh) + { + if (AllocSize) + *AllocSize = 0; + return (FLATPTR)NULL; + } + + /* Retrieve memory boundaries from temporary storage */ + FLATPTR MemBase = (FLATPTR)pvmh->freeList; + FLATPTR MemLimit = (FLATPTR)pvmh->allocList; + + if (!MemBase || !MemLimit || MemLimit <= MemBase) + { + DbgPrint("No valid video memory range\n"); + if (AllocSize) + *AllocSize = 0; + return (FLATPTR)NULL; + } + + CurrentPos = pvmh->dwCommitedSize; + CurrentPos = ALIGN_UP(CurrentPos, sizeof(ULONG)); + + if (pvmh->dwFlags & VMEMHEAP_LINEAR) + { + /* Handle linear memory allocation */ + RequiredBytes = Width; + } + else + { + /* Handle rectangular memory allocation */ + Width = pvmh->stride ? pvmh->stride : Width; + RequiredBytes = Width * Height; + } + MemPtr = MemBase + CurrentPos; + + if (MemPtr + RequiredBytes > MemLimit) + { + DbgPrint("Out of memory\n"); + if (AllocSize) + *AllocSize = 0; + return (FLATPTR)NULL; + } + + pvmh->dwCommitedSize = CurrentPos + RequiredBytes; + + if (ResolvedPitch) + *ResolvedPitch = (LONG)Width; + if (AllocSize) + *AllocSize = RequiredBytes; + + return MemPtr; +} + +/* + * Allocates memory from a DirectDraw video memory heap + */ +FLATPTR +WINAPI +DxDdHeapDdrawMemAlloc( + _In_ LPVIDMEM DdrawVidMem, + _In_ DWORD Width, + _In_ DWORD Height, + _In_opt_ LPSURFACEALIGNMENT Alignment, + _Out_opt_ LPDWORD ResolvedPitch, + _Out_ PDWORD AllocSize) +{ + FLATPTR Result; + DWORD ActualSize = 0; + + if (!DdrawVidMem || !DdrawVidMem->lpHeap) + { + if (AllocSize) + *AllocSize = 0; + return (FLATPTR)NULL; + } + + if ((DdrawVidMem->dwFlags & VIDMEM_ISNONLOCAL) && + !DdrawVidMem->lpHeap->pvPhysRsrv) + { + if (AllocSize) + *AllocSize = 0; + return (FLATPTR)NULL; + } + + /* Determine memory region boundaries */ + FLATPTR MemBegin = DdrawVidMem->fpStart; + FLATPTR MemEnd; + + if (DdrawVidMem->dwFlags & VIDMEM_ISLINEAR) + { + MemEnd = DdrawVidMem->fpEnd; + } + else if (DdrawVidMem->dwFlags & VIDMEM_ISRECTANGULAR) + { + MemEnd = MemBegin + (DdrawVidMem->dwWidth * DdrawVidMem->dwHeight); + } + else + { + MemEnd = DdrawVidMem->fpEnd; + } + + if (!MemBegin) + { + if (AllocSize) + *AllocSize = 0; + return (FLATPTR)NULL; + } + + /* Fallback to heap size if end address is invalid */ + if (!MemEnd || MemEnd <= MemBegin) + { + if (DdrawVidMem->lpHeap && DdrawVidMem->lpHeap->dwTotalSize > 0) + { + MemEnd = MemBegin + DdrawVidMem->lpHeap->dwTotalSize; + } + else + { + if (AllocSize) + *AllocSize = 0; + return (FLATPTR)NULL; + } + } + + /* + * In DxgKrnl we are given APIs to allocate ranges for DMA. + * In Vista this is used for trying to deal with ddraw on a dedicated surface + * outside of DWMs... control. + * + * In legacy DirectX these ranges are passed from the driver as valid areas to do + * allocation from, depending on this dxg driver to do the tracking. + * We don't care much to replicate ALL of this yet. + */ + FLATPTR SavedBegin = (FLATPTR)DdrawVidMem->lpHeap->freeList; + FLATPTR SavedEnd = (FLATPTR)DdrawVidMem->lpHeap->allocList; + DdrawVidMem->lpHeap->freeList = (LPVOID)MemBegin; + DdrawVidMem->lpHeap->allocList = (LPVOID)MemEnd; + + Result = DdrawMemAlloc(DdrawVidMem->lpHeap, Width, Height, &ActualSize, + Alignment, ResolvedPitch); + + if (!Result) + { + if (AllocSize) + *AllocSize = 0; + return Result; + } + + DdrawVidMem->lpHeap->freeList = (LPVOID)SavedBegin; + DdrawVidMem->lpHeap->allocList = (LPVOID)SavedEnd; + + if (AllocSize) + *AllocSize = ActualSize; + + return Result; +} + +FLATPTR +NTAPI +DxDdHeapVidMemAllocAligned( + LPVIDMEM DdrawVidMem, + DWORD Width, + DWORD Height, + LPSURFACEALIGNMENT Alignment, + LPDWORD ResolvedPitch) +{ + DWORD SizeOut = 0; + + if (!DdrawVidMem || !DdrawVidMem->lpHeap || + (DdrawVidMem->dwFlags & VIDMEM_HEAPDISABLED)) + { + return (FLATPTR)NULL; + } + + if (DdrawVidMem->dwFlags & VIDMEM_ISNONLOCAL) + { + if (!DdrawVidMem->lpHeap->pvPhysRsrv) + return (FLATPTR)NULL; + DbgPrint("AGP memory not supported\n"); + return (FLATPTR)NULL; + } + + return DxDdHeapDdrawMemAlloc(DdrawVidMem, Width, Height, + Alignment, ResolvedPitch, &SizeOut); +}