Author: fireball Date: Sun Aug 2 22:53:12 2009 New Revision: 42348
URL: http://svn.reactos.org/svn/reactos?rev=42348&view=rev Log: - Create stock bitmap in win32k and use it whenever a stock bitmap is selected into the DC. - Bring in GDIOBJ_ConvertToStockObj from trunk. - Fixes arwinss issue nr. 7.
Modified: branches/arwinss/reactos/dll/win32/winent.drv/gdidrv.c branches/arwinss/reactos/include/psdk/ntrosgdi.h branches/arwinss/reactos/subsystems/win32/win32k/gdi/bitmap.c branches/arwinss/reactos/subsystems/win32/win32k/gdi/dc.c branches/arwinss/reactos/subsystems/win32/win32k/gre/gdiobj.c branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h branches/arwinss/reactos/subsystems/win32/win32k/main/init.c branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db
Modified: branches/arwinss/reactos/dll/win32/winent.drv/gdidrv.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/dll/win32/winent... ============================================================================== --- branches/arwinss/reactos/dll/win32/winent.drv/gdidrv.c [iso-8859-1] (original) +++ branches/arwinss/reactos/dll/win32/winent.drv/gdidrv.c [iso-8859-1] Sun Aug 2 22:53:12 2009 @@ -19,6 +19,9 @@ #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(rosgdidrv); + +/* GLOBALS ****************************************************************/ +HANDLE hStockBitmap;
/* FUNCTIONS **************************************************************/
@@ -123,6 +126,10 @@ hKernelDC = (*pdev)->hKernelDC; else hKernelDC = 0; + + /* Save stock bitmap's handle */ + if (dcInfo.dwType == OBJ_MEMDC && !hStockBitmap) + hStockBitmap = GetCurrentObject( hdc, OBJ_BITMAP );
/* Call the win32 kernel */ bRet = RosGdiCreateDC(&dcInfo, &hKernelDC, driver, device, output, initData); @@ -453,8 +460,18 @@
HBITMAP CDECL RosDrv_SelectBitmap( NTDRV_PDEVICE *physDev, HBITMAP hbitmap ) { - RosGdiSelectBitmap(physDev->hKernelDC, hbitmap); - + BOOL bRes, bStock = FALSE; + + /* Check if it's a stock bitmap */ + if (hbitmap == hStockBitmap) bStock = TRUE; + + /* Select the bitmap into the DC */ + bRes = RosGdiSelectBitmap(physDev->hKernelDC, hbitmap, bStock); + + /* If there was an error, return 0 */ + if (!bRes) return 0; + + /* Return handle of selected bitmap as a success*/ return hbitmap; }
Modified: branches/arwinss/reactos/include/psdk/ntrosgdi.h URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/include/psdk/ntr... ============================================================================== --- branches/arwinss/reactos/include/psdk/ntrosgdi.h [iso-8859-1] (original) +++ branches/arwinss/reactos/include/psdk/ntrosgdi.h [iso-8859-1] Sun Aug 2 22:53:12 2009 @@ -101,7 +101,7 @@ BOOL APIENTRY RosGdiDeleteDC( HDC physDev ); BOOL APIENTRY RosGdiGetDCOrgEx( HDC physDev, LPPOINT lpp ); BOOL APIENTRY RosGdiPaintRgn( HDC physDev, HRGN hrgn ); -VOID APIENTRY RosGdiSelectBitmap( HDC physDev, HBITMAP hbitmap ); +BOOL APIENTRY RosGdiSelectBitmap( HDC physDev, HBITMAP hbitmap, BOOL stock ); VOID APIENTRY RosGdiSelectBrush( HDC physDev, LOGBRUSH *pLogBrush ); HFONT APIENTRY RosGdiSelectFont( HDC physDev, HFONT hfont, HANDLE gdiFont ); VOID APIENTRY RosGdiSelectPen( HDC physDev, LOGPEN *pLogPen, EXTLOGPEN *pExtLogPen );
Modified: branches/arwinss/reactos/subsystems/win32/win32k/gdi/bitmap.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/gdi/bitmap.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/gdi/bitmap.c [iso-8859-1] Sun Aug 2 22:53:12 2009 @@ -11,6 +11,9 @@ #include <win32k.h> #define NDEBUG #include <debug.h> + +/* GLOBALS *******************************************************************/ +HGDIOBJ hStockBmp;
/* PUBLIC FUNCTIONS **********************************************************/
@@ -293,5 +296,17 @@ return bRet; }
+VOID +CreateStockBitmap() +{ + SIZE slSize; + + /* Create 1x1 bitmap */ + slSize.cx = 1; slSize.cy = 1; + hStockBmp = GreCreateBitmap(slSize, 1, 1, 0, NULL); + + /* Convert it to a stock object */ + GDIOBJ_ConvertToStockObj(&hStockBmp); +}
/* EOF */
Modified: branches/arwinss/reactos/subsystems/win32/win32k/gdi/dc.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/gdi/dc.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/gdi/dc.c [iso-8859-1] Sun Aug 2 22:53:12 2009 @@ -185,21 +185,26 @@ return FALSE; }
-VOID APIENTRY RosGdiSelectBitmap( HDC physDev, HBITMAP hbitmap ) +BOOL APIENTRY RosGdiSelectBitmap( HDC physDev, HBITMAP hbitmap, BOOL bStock ) { PDC pDC; PSURFACE pSurface; HGDIOBJ hBmpKern; - SIZEL slSize; - - hBmpKern = GDI_MapUserHandle(hbitmap); - if (!hBmpKern) - { - DPRINT1("Trying to select an unknown bitmap %x to the DC %x!\n", hbitmap, physDev); - - /* It probably is a stock bitmap, so select it */ - slSize.cx = 1; slSize.cy = 1; - hBmpKern = GreCreateBitmap(slSize, 1, 1, 0, NULL); + + if (bStock) + { + /* Selecting stock bitmap */ + hBmpKern = hStockBmp; + } + else + { + /* Selecting usual bitmap */ + hBmpKern = GDI_MapUserHandle(hbitmap); + if (!hBmpKern) + { + DPRINT1("Trying to select an unknown bitmap %x to the DC %x!\n", hbitmap, physDev); + return FALSE; + } }
DPRINT("Selecting %x bitmap to hdc %x\n", hBmpKern, physDev); @@ -220,6 +225,8 @@
/* Release the DC object */ DC_Unlock(pDC); + + return TRUE; }
VOID APIENTRY RosGdiSelectBrush( HDC physDev, LOGBRUSH *pLogBrush )
Modified: branches/arwinss/reactos/subsystems/win32/win32k/gre/gdiobj.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/gre/gdiobj.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/gre/gdiobj.c [iso-8859-1] Sun Aug 2 22:53:12 2009 @@ -1050,6 +1050,139 @@ }
BOOL APIENTRY +GDIOBJ_ConvertToStockObj(HGDIOBJ *phObj) +{ + /* + * FIXME !!!!! THIS FUNCTION NEEDS TO BE FIXED - IT IS NOT SAFE WHEN OTHER THREADS + * MIGHT ATTEMPT TO LOCK THE OBJECT DURING THIS CALL!!! + */ + PGDI_TABLE_ENTRY Entry; + HANDLE ProcessId, LockedProcessId, PrevProcId; + PTHREADINFO Thread; + HGDIOBJ hObj; + + GDIDBG_INITLOOPTRACE(); + + ASSERT(phObj); + hObj = *phObj; + + DPRINT("GDIOBJ_ConvertToStockObj: hObj: 0x%08x\n", hObj); + + Thread = PsGetCurrentThreadWin32Thread(); + + if (!GDI_HANDLE_IS_STOCKOBJ(hObj)) + { + ProcessId = PsGetCurrentProcessId(); + LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1); + + Entry = GDI_HANDLE_GET_ENTRY(GdiHandleTable, hObj); + +LockHandle: + /* lock the object, we must not convert stock objects, so don't check!!! */ + PrevProcId = InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, LockedProcessId, ProcessId); + if (PrevProcId == ProcessId) + { + LONG NewType, PrevType, OldType; + + /* we're locking an object that belongs to our process. First calculate + the new object type including the stock object flag and then try to + exchange it.*/ + /* On Windows the higher 16 bit of the type field don't contain the + full type from the handle, but the base type. + (type = BRSUH, PEN, EXTPEN, basetype = BRUSH) */ + OldType = ((ULONG)hObj & GDI_HANDLE_BASETYPE_MASK) | ((ULONG)hObj >> GDI_ENTRY_UPPER_SHIFT); + /* We are currently not using bits 24..31 (flags) of the type field, but for compatibility + we copy them as we can't get them from the handle */ + OldType |= Entry->Type & GDI_ENTRY_FLAGS_MASK; + + /* As the object should be a stock object, set it's flag, but only in the lower 16 bits */ + NewType = OldType | GDI_ENTRY_STOCK_MASK; + + /* Try to exchange the type field - but only if the old (previous type) matches! */ + PrevType = InterlockedCompareExchange(&Entry->Type, NewType, OldType); + if (PrevType == OldType && Entry->KernelData != NULL) + { + PTHREADINFO PrevThread; + PBASEOBJECT Object; + + /* We successfully set the stock object flag. + KernelData should never be NULL here!!! */ + ASSERT(Entry->KernelData); + + Object = Entry->KernelData; + + PrevThread = Object->Tid; + if (Object->cExclusiveLock == 0 || PrevThread == Thread) + { + /* dereference the process' object counter */ + if (PrevProcId != GDI_GLOBAL_PROCESS) + { + PEPROCESS OldProcess; + PPROCESSINFO W32Process; + NTSTATUS Status; + + /* FIXME */ + Status = PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)PrevProcId & ~0x1), &OldProcess); + if (NT_SUCCESS(Status)) + { + W32Process = (PPROCESSINFO)OldProcess->Win32Process; + if (W32Process != NULL) + { + InterlockedDecrement(&W32Process->GDIHandleCount); + } + ObDereferenceObject(OldProcess); + } + } + + hObj = (HGDIOBJ)((ULONG)(hObj) | GDI_HANDLE_STOCK_MASK); + *phObj = hObj; + Object->hHmgr = hObj; + + /* remove the process id lock and make it global */ + (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, GDI_GLOBAL_PROCESS); + + /* we're done, successfully converted the object */ + return TRUE; + } + else + { + GDIDBG_TRACELOOP(hObj, PrevThread, Thread); + + /* WTF?! The object is already locked by a different thread! + Release the lock, wait a bit and try again! + FIXME - we should give up after some time unless we want to wait forever! */ + (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId); + + DelayExecution(); + goto LockHandle; + } + } + else + { + DPRINT1("Attempted to convert object 0x%x that is deleted! Should never get here!!!\n", hObj); + DPRINT1("OldType = 0x%x, Entry->Type = 0x%x, NewType = 0x%x, Entry->KernelData = 0x%x\n", OldType, Entry->Type, NewType, Entry->KernelData); + } + } + else if (PrevProcId == LockedProcessId) + { + GDIDBG_TRACELOOP(hObj, PrevProcId, ProcessId); + + /* the object is currently locked, wait some time and try again. + FIXME - we shouldn't loop forever! Give up after some time! */ + DelayExecution(); + /* try again */ + goto LockHandle; + } + else + { + DPRINT1("Attempted to convert invalid handle: 0x%x\n", hObj); + } + } + + return FALSE; +} + +BOOL APIENTRY GDIOBJ_SetOwnership(HGDIOBJ ObjectHandle, PEPROCESS NewOwner) { PGDI_TABLE_ENTRY Entry;
Modified: branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h [iso-8859-1] Sun Aug 2 22:53:12 2009 @@ -62,6 +62,10 @@ INT FASTCALL BitsPerFormat(ULONG Format);
+/* bitmap.c */ +extern HGDIOBJ hStockBmp; +VOID CreateStockBitmap(); + /* font.c */ VOID NTAPI GreTextOut(PDC pDC, INT x, INT y, UINT flags,
Modified: branches/arwinss/reactos/subsystems/win32/win32k/main/init.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/main/init.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/main/init.c [iso-8859-1] Sun Aug 2 22:53:12 2009 @@ -345,6 +345,9 @@ /* Initialize handle-mapping */ GDI_InitHandleMapping();
+ /* Create stock objects */ + CreateStockBitmap(); + /* Init video driver implementation */ InitDcImpl();
Modified: branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db [iso-8859-1] Sun Aug 2 22:53:12 2009 @@ -17,7 +17,7 @@ RosGdiDeleteDC 1 RosGdiGetDCOrgEx 2 RosGdiPaintRgn 2 -RosGdiSelectBitmap 2 +RosGdiSelectBitmap 3 RosGdiSelectBrush 2 RosGdiSelectFont 3 RosGdiSelectPen 3