1c2c66affSColin Finck /*
2c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
3c2c66affSColin Finck * PROJECT: ReactOS kernel
4c2c66affSColin Finck * PURPOSE: Native driver for dxg implementation
5c2c66affSColin Finck * FILE: win32ss/reactx/dxg/ddhmg.c
6c2c66affSColin Finck * PROGRAMER: Magnus olsen (magnus@greatlord.com)
7c2c66affSColin Finck * Sebastian Gasiorek (sebastian.gasiorek@reactos.org)
8c2c66affSColin Finck * REVISION HISTORY:
9c2c66affSColin Finck * 30/12-2007 Magnus Olsen
10c2c66affSColin Finck */
11c2c66affSColin Finck
12c2c66affSColin Finck #include <dxg_int.h>
13c2c66affSColin Finck
14c2c66affSColin Finck /* The DdHmgr manger stuff */
15c2c66affSColin Finck ULONG gcSizeDdHmgr = 1024;
16c2c66affSColin Finck PDD_ENTRY gpentDdHmgr = NULL;
17c2c66affSColin Finck
18c2c66affSColin Finck ULONG gcMaxDdHmgr = 0;
19c2c66affSColin Finck PDD_ENTRY gpentDdHmgrLast = NULL;
20c2c66affSColin Finck
21c2c66affSColin Finck /* next free ddhmg handle number available to reuse */
22c2c66affSColin Finck ULONG ghFreeDdHmgr = 0;
23c2c66affSColin Finck HSEMAPHORE ghsemHmgr = NULL;
24c2c66affSColin Finck
25c2c66affSColin Finck BOOL
26c2c66affSColin Finck FASTCALL
VerifyObjectOwner(PDD_ENTRY pEntry)27c2c66affSColin Finck VerifyObjectOwner(PDD_ENTRY pEntry)
28c2c66affSColin Finck {
29c2c66affSColin Finck DWORD Pid = (DWORD)(DWORD_PTR)PsGetCurrentProcessId() & 0xFFFFFFFC;
30*2a5e2a2aSTimo Kreuzer DWORD check = (DWORD_PTR)pEntry->Pid & 0xFFFFFFFE;
31c2c66affSColin Finck return ( (check == Pid) || (!check));
32c2c66affSColin Finck }
33c2c66affSColin Finck
34c2c66affSColin Finck /*++
35c2c66affSColin Finck * @name DdHmgCreate
36c2c66affSColin Finck * @implemented
37c2c66affSColin Finck *
38c2c66affSColin Finck * The function DdHmgCreate is used internally in dxg.sys
39c2c66affSColin Finck * It creates all DX kernel objects that are need it for creation of DX objects.
40c2c66affSColin Finck *
41c2c66affSColin Finck * @return
42c2c66affSColin Finck * Return FALSE for failure and TRUE for success in creating the DX object
43c2c66affSColin Finck *
44c2c66affSColin Finck * @remarks.
45c2c66affSColin Finck * Only used internally in dxg.sys
46c2c66affSColin Finck *--*/
47c2c66affSColin Finck BOOL
48c2c66affSColin Finck FASTCALL
DdHmgCreate(VOID)49c2c66affSColin Finck DdHmgCreate(VOID)
50c2c66affSColin Finck {
51c2c66affSColin Finck gpentDdHmgr = EngAllocMem(FL_ZERO_MEMORY, gcSizeDdHmgr * sizeof(DD_ENTRY), TAG_THDD);
52c2c66affSColin Finck ghFreeDdHmgr = 0;
53c2c66affSColin Finck gcMaxDdHmgr = 1;
54c2c66affSColin Finck
55c2c66affSColin Finck if (gpentDdHmgr)
56c2c66affSColin Finck {
57c2c66affSColin Finck ghsemHmgr = EngCreateSemaphore();
58c2c66affSColin Finck
59c2c66affSColin Finck if (ghsemHmgr)
60c2c66affSColin Finck {
61c2c66affSColin Finck gpLockShortDelay = EngAllocMem(FL_ZERO_MEMORY | FL_NONPAGED_MEMORY, sizeof(LARGE_INTEGER), TAG_GINI);
62c2c66affSColin Finck
63c2c66affSColin Finck if (gpLockShortDelay)
64c2c66affSColin Finck {
65c2c66affSColin Finck gpLockShortDelay->HighPart = -1;
66c2c66affSColin Finck return TRUE;
67c2c66affSColin Finck }
68c2c66affSColin Finck
69c2c66affSColin Finck EngDeleteSemaphore(ghsemHmgr);
70c2c66affSColin Finck ghsemHmgr = NULL;
71c2c66affSColin Finck }
72c2c66affSColin Finck
73c2c66affSColin Finck EngFreeMem(gpentDdHmgr);
74c2c66affSColin Finck gpentDdHmgr = NULL;
75c2c66affSColin Finck }
76c2c66affSColin Finck
77c2c66affSColin Finck return FALSE;
78c2c66affSColin Finck }
79c2c66affSColin Finck
80c2c66affSColin Finck /*++
81c2c66affSColin Finck * @name DdHmgDestroy
82c2c66affSColin Finck * @implemented
83c2c66affSColin Finck *
84c2c66affSColin Finck * The function DdHmgDestroy is used internally in dxg.sys
85c2c66affSColin Finck * It destroys all DX kernel objects
86c2c66affSColin Finck *
87c2c66affSColin Finck * @return
88c2c66affSColin Finck * Always returns true, as a failure here would result in a BSOD.
89c2c66affSColin Finck *
90c2c66affSColin Finck * @remarks.
91c2c66affSColin Finck * Only used internally in dxg.sys
92c2c66affSColin Finck *--*/
93c2c66affSColin Finck BOOL
94c2c66affSColin Finck FASTCALL
DdHmgDestroy(VOID)95c2c66affSColin Finck DdHmgDestroy(VOID)
96c2c66affSColin Finck {
97c2c66affSColin Finck gcMaxDdHmgr = 0;
98c2c66affSColin Finck gcSizeDdHmgr = 0;
99c2c66affSColin Finck ghFreeDdHmgr = 0;
100c2c66affSColin Finck gpentDdHmgrLast = NULL;
101c2c66affSColin Finck
102c2c66affSColin Finck if (gpentDdHmgr)
103c2c66affSColin Finck {
104c2c66affSColin Finck EngFreeMem(gpentDdHmgr);
105c2c66affSColin Finck gpentDdHmgr = NULL;
106c2c66affSColin Finck }
107c2c66affSColin Finck
108c2c66affSColin Finck if (ghsemHmgr)
109c2c66affSColin Finck {
110c2c66affSColin Finck EngDeleteSemaphore(ghsemHmgr);
111c2c66affSColin Finck ghsemHmgr = NULL;
112c2c66affSColin Finck }
113c2c66affSColin Finck
114c2c66affSColin Finck return TRUE;
115c2c66affSColin Finck }
116c2c66affSColin Finck
117c2c66affSColin Finck /*++
118c2c66affSColin Finck * @name DdHmgLock
119c2c66affSColin Finck * @implemented
120c2c66affSColin Finck *
121c2c66affSColin Finck * The function DdHmgLock is used internally in dxg.sys
122c2c66affSColin Finck * It locks a DX kernel object
123c2c66affSColin Finck *
124c2c66affSColin Finck * @param HANDLE DdHandle
125c2c66affSColin Finck * The handle we want locked
126c2c66affSColin Finck *
127c2c66affSColin Finck * @param UCHAR ObjectType
128c2c66affSColin Finck * The type of the object we expected the handle to contain
129c2c66affSColin Finck * value 0 is for ?
130c2c66affSColin Finck * value 1 is for EDD_DIRECTDRAW_LOCAL
131c2c66affSColin Finck * value 2 is for EDD_SURFACE
132c2c66affSColin Finck * value 3 is for ?
133c2c66affSColin Finck * value 4 is for EDD_VIDEOPORT
134c2c66affSColin Finck * value 5 is for EDD_MOTIONCOMP
135c2c66affSColin Finck
136c2c66affSColin Finck * @param BOOLEAN LockOwned
137c2c66affSColin Finck * If it needs to call EngAcquireSemaphore or not
138c2c66affSColin Finck *
139c2c66affSColin Finck * @return
140c2c66affSColin Finck * Returns an EDD_* object, or NULL if it fails
141c2c66affSColin Finck *
142c2c66affSColin Finck * @remarks.
143c2c66affSColin Finck * Only used internally in dxg.sys
144c2c66affSColin Finck *--*/
145c2c66affSColin Finck PVOID
146c2c66affSColin Finck FASTCALL
DdHmgLock(HANDLE DdHandle,UCHAR ObjectType,BOOLEAN LockOwned)147c2c66affSColin Finck DdHmgLock(HANDLE DdHandle, UCHAR ObjectType, BOOLEAN LockOwned)
148c2c66affSColin Finck {
149c2c66affSColin Finck DWORD Index = DDHMG_HTOI(DdHandle);
150c2c66affSColin Finck
151c2c66affSColin Finck PDD_ENTRY pEntry = NULL;
152c2c66affSColin Finck PVOID Object = NULL;
153c2c66affSColin Finck
154c2c66affSColin Finck if ( !LockOwned )
155c2c66affSColin Finck {
156c2c66affSColin Finck EngAcquireSemaphore(ghsemHmgr);
157c2c66affSColin Finck }
158c2c66affSColin Finck
159c2c66affSColin Finck if ( Index < gcMaxDdHmgr )
160c2c66affSColin Finck {
161c2c66affSColin Finck pEntry = (PDD_ENTRY)((PBYTE)gpentDdHmgr + (sizeof(DD_ENTRY) * Index));
162c2c66affSColin Finck
163c2c66affSColin Finck if ( VerifyObjectOwner(pEntry) )
164c2c66affSColin Finck {
165c2c66affSColin Finck if ( ( pEntry->Objt == ObjectType ) &&
166*2a5e2a2aSTimo Kreuzer ( pEntry->FullUnique == (((ULONG_PTR)DdHandle >> 21) & 0x7FF) ) &&
167c2c66affSColin Finck ( !pEntry->pobj->cExclusiveLock ) )
168c2c66affSColin Finck {
169c2c66affSColin Finck InterlockedIncrement((VOID*)&pEntry->pobj->cExclusiveLock);
170c2c66affSColin Finck pEntry->pobj->Tid = KeGetCurrentThread();
171c2c66affSColin Finck Object = pEntry->pobj;
172c2c66affSColin Finck }
173c2c66affSColin Finck }
174c2c66affSColin Finck }
175c2c66affSColin Finck
176c2c66affSColin Finck if ( !LockOwned )
177c2c66affSColin Finck {
178c2c66affSColin Finck EngReleaseSemaphore(ghsemHmgr);
179c2c66affSColin Finck }
180c2c66affSColin Finck
181c2c66affSColin Finck return Object;
182c2c66affSColin Finck }
183c2c66affSColin Finck
184c2c66affSColin Finck /*++
185c2c66affSColin Finck * @name DdAllocateObject
186c2c66affSColin Finck * @implemented
187c2c66affSColin Finck *
188c2c66affSColin Finck * The function DdAllocateObject is used internally in dxg.sys
189c2c66affSColin Finck * It allocates memory for a DX kernel object
190c2c66affSColin Finck *
191c2c66affSColin Finck * @param UINT32 oSize
192c2c66affSColin Finck * Size of memory to be allocated
193c2c66affSColin Finck * @param UCHAR oType
194c2c66affSColin Finck * Object type
195c2c66affSColin Finck * @param BOOLEAN oZeroMemory
196c2c66affSColin Finck * Zero memory
197c2c66affSColin Finck *
198c2c66affSColin Finck * @remarks.
199c2c66affSColin Finck * Only used internally in dxg.sys
200c2c66affSColin Finck */
201c2c66affSColin Finck PVOID
202c2c66affSColin Finck FASTCALL
DdAllocateObject(ULONG objSize,UCHAR objType,BOOLEAN objZeroMemory)203c2c66affSColin Finck DdAllocateObject(ULONG objSize, UCHAR objType, BOOLEAN objZeroMemory)
204c2c66affSColin Finck {
205c2c66affSColin Finck PVOID pObject = NULL;
206c2c66affSColin Finck
207c2c66affSColin Finck if (objZeroMemory)
208c2c66affSColin Finck pObject = EngAllocMem(FL_ZERO_MEMORY, objSize, ((ULONG)objType << 24) + TAG_DH_0);
209c2c66affSColin Finck else
210c2c66affSColin Finck pObject = EngAllocMem(0, objSize, ((ULONG)objType << 24) + TAG_DH_0);
211c2c66affSColin Finck
212c2c66affSColin Finck if (!pObject)
213c2c66affSColin Finck {
214c2c66affSColin Finck EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
215c2c66affSColin Finck }
216c2c66affSColin Finck
217c2c66affSColin Finck return pObject;
218c2c66affSColin Finck }
219c2c66affSColin Finck
220c2c66affSColin Finck /*++
221c2c66affSColin Finck * @name DdFreeObject
222c2c66affSColin Finck * @implemented
223c2c66affSColin Finck *
224c2c66affSColin Finck * The function DdFreeObject is used internally in dxg.sys
225c2c66affSColin Finck * It frees memory of DX kernel object
226c2c66affSColin Finck *
227c2c66affSColin Finck * @param PVOID pObject
228c2c66affSColin Finck * Object memory to be freed
229c2c66affSColin Finck *
230c2c66affSColin Finck * @remarks.
231c2c66affSColin Finck * Only used internally in dxg.sys
232c2c66affSColin Finck */
233c2c66affSColin Finck VOID
234c2c66affSColin Finck FASTCALL
DdFreeObject(PVOID pObject)235c2c66affSColin Finck DdFreeObject(PVOID pObject)
236c2c66affSColin Finck {
237c2c66affSColin Finck EngFreeMem(pObject);
238c2c66affSColin Finck }
239c2c66affSColin Finck
240c2c66affSColin Finck
241c2c66affSColin Finck /*++
242c2c66affSColin Finck * @name DdGetFreeHandle
243c2c66affSColin Finck * @implemented
244c2c66affSColin Finck *
245c2c66affSColin Finck * The function DdGetFreeHandle is used internally in dxg.sys
246c2c66affSColin Finck * It allocates new handle for specified object type
247c2c66affSColin Finck *
248c2c66affSColin Finck * @param UCHAR oType
249c2c66affSColin Finck * Object type
250c2c66affSColin Finck *
251c2c66affSColin Finck * @return
252c2c66affSColin Finck * Returns handle or 0 if it fails.
253c2c66affSColin Finck *
254c2c66affSColin Finck * @remarks.
255c2c66affSColin Finck * Only used internally in dxg.sys
256c2c66affSColin Finck *--*/
257c2c66affSColin Finck HANDLE
258c2c66affSColin Finck FASTCALL
DdGetFreeHandle(UCHAR objType)259c2c66affSColin Finck DdGetFreeHandle(UCHAR objType)
260c2c66affSColin Finck {
261c2c66affSColin Finck PVOID mAllocMem = NULL;
262c2c66affSColin Finck ULONG mAllocEntries = 0;
263c2c66affSColin Finck PDD_ENTRY pEntry = NULL;
264*2a5e2a2aSTimo Kreuzer ULONG_PTR retVal;
265c2c66affSColin Finck ULONG index;
266c2c66affSColin Finck
267c2c66affSColin Finck // check if memory is allocated
268c2c66affSColin Finck if (!gpentDdHmgr)
269c2c66affSColin Finck return 0;
270c2c66affSColin Finck
271c2c66affSColin Finck // check if we reached maximum handle index
272c2c66affSColin Finck if (gcMaxDdHmgr == DDHMG_HANDLE_LIMIT)
273c2c66affSColin Finck return 0;
274c2c66affSColin Finck
275c2c66affSColin Finck // check if we have free handle to reuse
276c2c66affSColin Finck if (ghFreeDdHmgr)
277c2c66affSColin Finck {
278c2c66affSColin Finck index = ghFreeDdHmgr;
279c2c66affSColin Finck pEntry = (PDD_ENTRY)((PBYTE)gpentDdHmgr + (sizeof(DD_ENTRY) * index));
280c2c66affSColin Finck
281c2c66affSColin Finck // put next free index to our global variable
282c2c66affSColin Finck ghFreeDdHmgr = pEntry->NextFree;
283c2c66affSColin Finck
284c2c66affSColin Finck // build handle
285c2c66affSColin Finck pEntry->FullUnique = objType | 8;
286c2c66affSColin Finck retVal = (pEntry->FullUnique << 21) | index;
287c2c66affSColin Finck return (HANDLE)retVal;
288c2c66affSColin Finck }
289c2c66affSColin Finck
290c2c66affSColin Finck // if all pre-allocated memory is already used then allocate more
291c2c66affSColin Finck if (gcSizeDdHmgr == gcMaxDdHmgr)
292c2c66affSColin Finck {
293c2c66affSColin Finck // allocate buffer for next 1024 handles
294c2c66affSColin Finck mAllocEntries = gcSizeDdHmgr + 1024;
295c2c66affSColin Finck mAllocMem = EngAllocMem(FL_ZERO_MEMORY, sizeof(DD_ENTRY) * (mAllocEntries), TAG_THDD);
296c2c66affSColin Finck if (!mAllocMem)
297c2c66affSColin Finck return 0;
298c2c66affSColin Finck
299c2c66affSColin Finck memmove(&mAllocMem, gpentDdHmgr, sizeof(DD_ENTRY) * gcSizeDdHmgr);
300c2c66affSColin Finck gcSizeDdHmgr = mAllocEntries;
301c2c66affSColin Finck gpentDdHmgrLast = gpentDdHmgr;
302c2c66affSColin Finck EngFreeMem(gpentDdHmgr);
303c2c66affSColin Finck gpentDdHmgr = mAllocMem;
304c2c66affSColin Finck }
305c2c66affSColin Finck
306c2c66affSColin Finck pEntry = (PDD_ENTRY)((PBYTE)gpentDdHmgr + (sizeof(DD_ENTRY) * gcMaxDdHmgr));
307c2c66affSColin Finck
308c2c66affSColin Finck // build handle
309c2c66affSColin Finck pEntry->FullUnique = objType | 8;
310c2c66affSColin Finck retVal = (pEntry->FullUnique << 21) | gcMaxDdHmgr;
311c2c66affSColin Finck gcMaxDdHmgr = gcMaxDdHmgr + 1;
312c2c66affSColin Finck
313c2c66affSColin Finck return (HANDLE)retVal;
314c2c66affSColin Finck }
315c2c66affSColin Finck
316c2c66affSColin Finck /*++
317c2c66affSColin Finck * @name DdHmgAlloc
318c2c66affSColin Finck * @implemented
319c2c66affSColin Finck *
320c2c66affSColin Finck * The function DdHmgAlloc is used internally in dxg.sys
321c2c66affSColin Finck * It allocates object
322c2c66affSColin Finck *
323c2c66affSColin Finck * @param ULONG objSize
324c2c66affSColin Finck * Size of memory to be allocated
325c2c66affSColin Finck * @param CHAR objType
326c2c66affSColin Finck * Object type
327c2c66affSColin Finck * @param UINT objLock
328c2c66affSColin Finck * Object lock flag
329c2c66affSColin Finck *
330c2c66affSColin Finck * @return
331c2c66affSColin Finck * Handle if object is not locked by objLock
332c2c66affSColin Finck * Object if lock is set in objLock
333c2c66affSColin Finck * 0 if it fails.
334c2c66affSColin Finck *
335c2c66affSColin Finck * @remarks.
336c2c66affSColin Finck * Only used internally in dxg.sys
337c2c66affSColin Finck *--*/
338c2c66affSColin Finck HANDLE
339c2c66affSColin Finck FASTCALL
DdHmgAlloc(ULONG objSize,CHAR objType,BOOLEAN objLock)340c2c66affSColin Finck DdHmgAlloc(ULONG objSize, CHAR objType, BOOLEAN objLock)
341c2c66affSColin Finck {
342c2c66affSColin Finck PVOID pObject = NULL;
343c2c66affSColin Finck HANDLE DdHandle = NULL;
344c2c66affSColin Finck PDD_ENTRY pEntry = NULL;
345c2c66affSColin Finck DWORD Index;
346c2c66affSColin Finck
347c2c66affSColin Finck pObject = DdAllocateObject(objSize, objType, TRUE);
348c2c66affSColin Finck if (!pObject)
349c2c66affSColin Finck return 0;
350c2c66affSColin Finck
351c2c66affSColin Finck EngAcquireSemaphore(ghsemHmgr);
352c2c66affSColin Finck
353c2c66affSColin Finck /* Get next free handle */
354c2c66affSColin Finck DdHandle = DdGetFreeHandle(objType);
355c2c66affSColin Finck
356c2c66affSColin Finck if (DdHandle)
357c2c66affSColin Finck {
358c2c66affSColin Finck Index = DDHMG_HTOI(DdHandle);
359c2c66affSColin Finck
360c2c66affSColin Finck pEntry = (PDD_ENTRY)((PBYTE)gpentDdHmgr + (sizeof(DD_ENTRY) * Index));
361c2c66affSColin Finck
362c2c66affSColin Finck pEntry->pobj = pObject;
363c2c66affSColin Finck pEntry->Objt = objType;
364c2c66affSColin Finck
365*2a5e2a2aSTimo Kreuzer pEntry->Pid = (HANDLE)(((ULONG_PTR)PsGetCurrentProcessId() & 0xFFFFFFFC) | ((ULONG_PTR)(pEntry->Pid) & 1));
366c2c66affSColin Finck
367c2c66affSColin Finck if (objLock)
368c2c66affSColin Finck {
369c2c66affSColin Finck InterlockedIncrement((VOID*)&pEntry->pobj->cExclusiveLock);
370c2c66affSColin Finck pEntry->pobj->Tid = KeGetCurrentThread();
371c2c66affSColin Finck }
372c2c66affSColin Finck pEntry->pobj->hHmgr = DdHandle;
373c2c66affSColin Finck
374c2c66affSColin Finck EngReleaseSemaphore(ghsemHmgr);
375c2c66affSColin Finck
376c2c66affSColin Finck /* Return handle if object not locked */
377c2c66affSColin Finck if (!objLock)
378c2c66affSColin Finck return DdHandle;
379c2c66affSColin Finck
380c2c66affSColin Finck return (HANDLE)pEntry;
381c2c66affSColin Finck }
382c2c66affSColin Finck
383c2c66affSColin Finck EngReleaseSemaphore(ghsemHmgr);
384c2c66affSColin Finck DdFreeObject(pObject);
385c2c66affSColin Finck return 0;
386c2c66affSColin Finck }
387c2c66affSColin Finck
388c2c66affSColin Finck /*++
389c2c66affSColin Finck * @name DdHmgFree
390c2c66affSColin Finck * @implemented
391c2c66affSColin Finck *
392c2c66affSColin Finck * The function DdHmgFree is used internally in dxg.sys
393c2c66affSColin Finck * It frees DX object and memory allocated to it
394c2c66affSColin Finck *
395c2c66affSColin Finck * @param HANDLE DdHandle
396c2c66affSColin Finck * DX object handle
397c2c66affSColin Finck *
398c2c66affSColin Finck * @remarks.
399c2c66affSColin Finck * Only used internally in dxg.sys
400c2c66affSColin Finck *--*/
401c2c66affSColin Finck VOID
402c2c66affSColin Finck FASTCALL
DdHmgFree(HANDLE DdHandle)403c2c66affSColin Finck DdHmgFree(HANDLE DdHandle)
404c2c66affSColin Finck {
405c2c66affSColin Finck PDD_ENTRY pEntry = NULL;
406c2c66affSColin Finck
407c2c66affSColin Finck DWORD Index = DDHMG_HTOI(DdHandle);
408c2c66affSColin Finck
409c2c66affSColin Finck EngAcquireSemaphore(ghsemHmgr);
410c2c66affSColin Finck
411c2c66affSColin Finck pEntry = (PDD_ENTRY)((PBYTE)gpentDdHmgr + (sizeof(DD_ENTRY) * Index));
412c2c66affSColin Finck
413c2c66affSColin Finck // check if we have object that should be freed
414c2c66affSColin Finck if (pEntry->pobj)
415c2c66affSColin Finck DdFreeObject(pEntry->pobj);
416c2c66affSColin Finck
417c2c66affSColin Finck pEntry->NextFree = ghFreeDdHmgr;
418c2c66affSColin Finck
419c2c66affSColin Finck // reset process ID
420*2a5e2a2aSTimo Kreuzer pEntry->Pid = (HANDLE)((DWORD_PTR)pEntry->Pid & 1);
421c2c66affSColin Finck ghFreeDdHmgr = Index;
422c2c66affSColin Finck
423c2c66affSColin Finck EngReleaseSemaphore(ghsemHmgr);
424c2c66affSColin Finck }
425