Reactos
at master 207 lines 5.1 kB view raw
1/* 2 * PROJECT: ReactX Graphics Legacy Kernel 3 * LICENSE: MIT (https://spdx.org/licenses/MIT) 4 * PURPOSE: DirectDraw video memory allocator 5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org> 6 */ 7 8#include <dxg_int.h> 9 10FLATPTR 11WINAPI 12DdrawMemAlloc( 13 _In_ LPVMEMHEAP pvmh, 14 _In_ DWORD Width, 15 _In_ DWORD Height, 16 _Out_opt_ LPDWORD AllocSize, 17 _In_opt_ LPSURFACEALIGNMENT Alignment, 18 _Out_opt_ LPDWORD ResolvedPitch) 19{ 20 FLATPTR MemPtr; 21 DWORD RequiredBytes; 22 DWORD CurrentPos; 23 24 if (!pvmh) 25 { 26 if (AllocSize) 27 *AllocSize = 0; 28 return (FLATPTR)NULL; 29 } 30 31 /* Retrieve memory boundaries from temporary storage */ 32 FLATPTR MemBase = (FLATPTR)pvmh->freeList; 33 FLATPTR MemLimit = (FLATPTR)pvmh->allocList; 34 35 if (!MemBase || !MemLimit || MemLimit <= MemBase) 36 { 37 DbgPrint("No valid video memory range\n"); 38 if (AllocSize) 39 *AllocSize = 0; 40 return (FLATPTR)NULL; 41 } 42 43 CurrentPos = pvmh->dwCommitedSize; 44 CurrentPos = ALIGN_UP(CurrentPos, sizeof(ULONG)); 45 46 if (pvmh->dwFlags & VMEMHEAP_LINEAR) 47 { 48 /* Handle linear memory allocation */ 49 RequiredBytes = Width; 50 } 51 else 52 { 53 /* Handle rectangular memory allocation */ 54 Width = pvmh->stride ? pvmh->stride : Width; 55 RequiredBytes = Width * Height; 56 } 57 MemPtr = MemBase + CurrentPos; 58 59 if (MemPtr + RequiredBytes > MemLimit) 60 { 61 DbgPrint("Out of memory\n"); 62 if (AllocSize) 63 *AllocSize = 0; 64 return (FLATPTR)NULL; 65 } 66 67 pvmh->dwCommitedSize = CurrentPos + RequiredBytes; 68 69 if (ResolvedPitch) 70 *ResolvedPitch = (LONG)Width; 71 if (AllocSize) 72 *AllocSize = RequiredBytes; 73 74 return MemPtr; 75} 76 77/* 78 * Allocates memory from a DirectDraw video memory heap 79 */ 80FLATPTR 81WINAPI 82DxDdHeapDdrawMemAlloc( 83 _In_ LPVIDMEM DdrawVidMem, 84 _In_ DWORD Width, 85 _In_ DWORD Height, 86 _In_opt_ LPSURFACEALIGNMENT Alignment, 87 _Out_opt_ LPDWORD ResolvedPitch, 88 _Out_ PDWORD AllocSize) 89{ 90 FLATPTR Result; 91 DWORD ActualSize = 0; 92 93 if (!DdrawVidMem || !DdrawVidMem->lpHeap) 94 { 95 if (AllocSize) 96 *AllocSize = 0; 97 return (FLATPTR)NULL; 98 } 99 100 if ((DdrawVidMem->dwFlags & VIDMEM_ISNONLOCAL) && 101 !DdrawVidMem->lpHeap->pvPhysRsrv) 102 { 103 if (AllocSize) 104 *AllocSize = 0; 105 return (FLATPTR)NULL; 106 } 107 108 /* Determine memory region boundaries */ 109 FLATPTR MemBegin = DdrawVidMem->fpStart; 110 FLATPTR MemEnd; 111 112 if (DdrawVidMem->dwFlags & VIDMEM_ISLINEAR) 113 { 114 MemEnd = DdrawVidMem->fpEnd; 115 } 116 else if (DdrawVidMem->dwFlags & VIDMEM_ISRECTANGULAR) 117 { 118 MemEnd = MemBegin + (DdrawVidMem->dwWidth * DdrawVidMem->dwHeight); 119 } 120 else 121 { 122 MemEnd = DdrawVidMem->fpEnd; 123 } 124 125 if (!MemBegin) 126 { 127 if (AllocSize) 128 *AllocSize = 0; 129 return (FLATPTR)NULL; 130 } 131 132 /* Fallback to heap size if end address is invalid */ 133 if (!MemEnd || MemEnd <= MemBegin) 134 { 135 if (DdrawVidMem->lpHeap && DdrawVidMem->lpHeap->dwTotalSize > 0) 136 { 137 MemEnd = MemBegin + DdrawVidMem->lpHeap->dwTotalSize; 138 } 139 else 140 { 141 if (AllocSize) 142 *AllocSize = 0; 143 return (FLATPTR)NULL; 144 } 145 } 146 147 /* 148 * In DxgKrnl we are given APIs to allocate ranges for DMA. 149 * In Vista this is used for trying to deal with ddraw on a dedicated surface 150 * outside of DWMs... control. 151 * 152 * In legacy DirectX these ranges are passed from the driver as valid areas to do 153 * allocation from, depending on this dxg driver to do the tracking. 154 * We don't care much to replicate ALL of this yet. 155 */ 156 FLATPTR SavedBegin = (FLATPTR)DdrawVidMem->lpHeap->freeList; 157 FLATPTR SavedEnd = (FLATPTR)DdrawVidMem->lpHeap->allocList; 158 DdrawVidMem->lpHeap->freeList = (LPVOID)MemBegin; 159 DdrawVidMem->lpHeap->allocList = (LPVOID)MemEnd; 160 161 Result = DdrawMemAlloc(DdrawVidMem->lpHeap, Width, Height, &ActualSize, 162 Alignment, ResolvedPitch); 163 164 if (!Result) 165 { 166 if (AllocSize) 167 *AllocSize = 0; 168 return Result; 169 } 170 171 DdrawVidMem->lpHeap->freeList = (LPVOID)SavedBegin; 172 DdrawVidMem->lpHeap->allocList = (LPVOID)SavedEnd; 173 174 if (AllocSize) 175 *AllocSize = ActualSize; 176 177 return Result; 178} 179 180FLATPTR 181NTAPI 182DxDdHeapVidMemAllocAligned( 183 LPVIDMEM DdrawVidMem, 184 DWORD Width, 185 DWORD Height, 186 LPSURFACEALIGNMENT Alignment, 187 LPDWORD ResolvedPitch) 188{ 189 DWORD SizeOut = 0; 190 191 if (!DdrawVidMem || !DdrawVidMem->lpHeap || 192 (DdrawVidMem->dwFlags & VIDMEM_HEAPDISABLED)) 193 { 194 return (FLATPTR)NULL; 195 } 196 197 if (DdrawVidMem->dwFlags & VIDMEM_ISNONLOCAL) 198 { 199 if (!DdrawVidMem->lpHeap->pvPhysRsrv) 200 return (FLATPTR)NULL; 201 DbgPrint("AGP memory not supported\n"); 202 return (FLATPTR)NULL; 203 } 204 205 return DxDdHeapDdrawMemAlloc(DdrawVidMem, Width, Height, 206 Alignment, ResolvedPitch, &SizeOut); 207}