Author: jimtabor Date: Wed Dec 30 23:56:09 2009 New Revision: 44817
URL: http://svn.reactos.org/svn/reactos?rev=44817&view=rev Log: [Win32k] - Plugged in region attribute support and added the PEB cache for it as well.
[Gdi32] - Using CreateRectRgn only with attribute and PEB cache support.
[Testing] - Wine tests: gdi32; clipping and dc. gdiplus; region. user32; dce. Same results. - Applications, AbiWord 2.6.8, FF 3.5, miranda 0.7.19 unicode, putty, SeaMonkey 2.0, WinMerge 2.12.4 and winamp 2.95 rc std. Same results.
Modified: trunk/reactos/dll/win32/gdi32/misc/misc.c trunk/reactos/dll/win32/gdi32/objects/region.c trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c trunk/reactos/subsystems/win32/win32k/objects/region.c
Modified: trunk/reactos/dll/win32/gdi32/misc/misc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdi32/misc/misc.c... ============================================================================== --- trunk/reactos/dll/win32/gdi32/misc/misc.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdi32/misc/misc.c [iso-8859-1] Wed Dec 30 23:56:09 2009 @@ -16,10 +16,9 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* $Id$ - * +/* * PROJECT: ReactOS gdi32.dll - * FILE: lib/gdi32/misc/misc.c + * FILE: dll/win32/gdi32/misc/misc.c * PURPOSE: Miscellaneous functions * PROGRAMMER: Thomas Weidenmueller w3seek@reactos.com * UPDATE HISTORY: @@ -284,10 +283,46 @@ return NtGdiSetBoundsRect(hdc, prc, 0x8000 | DCB_ACCUMULATE ) ? TRUE : FALSE; }
+extern PGDIHANDLECACHE GdiHandleCache; + HGDIOBJ FASTCALL hGetPEBHandle(HANDLECACHETYPE Type, COLORREF cr) { - return NULL; -} - + int Number; + HANDLE Lock; + HGDIOBJ Handle = NULL; + + Lock = InterlockedCompareExchangePointer( (PVOID*)&GdiHandleCache->ulLock, + NtCurrentTeb(), + NULL ); + + if (Lock) return Handle; + + Number = GdiHandleCache->ulNumHandles[Type]; + + if ( Number && Number <= CACHE_REGION_ENTRIES ) + { + if ( Type == hctRegionHandle) + { + PRGN_ATTR pRgn_Attr; + HGDIOBJ *hPtr; + hPtr = GdiHandleCache->Handle + CACHE_BRUSH_ENTRIES+CACHE_PEN_ENTRIES; + Handle = hPtr[Number - 1]; + + if (GdiGetHandleUserData( Handle, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr)) + { + if (pRgn_Attr->AttrFlags & ATTR_CACHED) + { + DPRINT("Get Handle! Count %d\n", GdiHandleCache->ulNumHandles[Type]); + pRgn_Attr->AttrFlags &= ~ATTR_CACHED; + hPtr[Number - 1] = NULL; + GdiHandleCache->ulNumHandles[Type]--; + } + } + } + } + (void)InterlockedExchangePointer((PVOID*)&GdiHandleCache->ulLock, Lock); + return Handle; +} +
Modified: trunk/reactos/dll/win32/gdi32/objects/region.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdi32/objects/reg... ============================================================================== --- trunk/reactos/dll/win32/gdi32/objects/region.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdi32/objects/region.c [iso-8859-1] Wed Dec 30 23:56:09 2009 @@ -438,39 +438,35 @@ { PRGN_ATTR pRgn_Attr; HRGN hrgn; - int x, y; - -//// Remove when Brush/Pen/Rgn Attr is ready! - return NtGdiCreateRectRgn(x1,y1,x2,y2); -//// + int tmp;
/* Normalize points */ - x = x1; + tmp = x1; if ( x1 > x2 ) { x1 = x2; - x2 = x; - } - - y = y1; + x2 = tmp; + } + + tmp = y1; if ( y1 > y2 ) { y1 = y2; - y2 = y; - } - - if ( (UINT)x1 < 0x80000000 || - (UINT)y1 < 0x80000000 || - (UINT)x2 > 0x7FFFFFFF || - (UINT)y2 > 0x7FFFFFFF ) + y2 = tmp; + } + /* Check outside 24 bit limit for universal set. Chp 9 Areas, pg 560.*/ + if ( x1 < -(1<<27) || + y1 < -(1<<27) || + x2 > (1<<27)-1 || + y2 > (1<<27)-1 ) { SetLastError(ERROR_INVALID_PARAMETER); return NULL; }
-// hrgn = hGetPEBHandle(hctRegionHandle, 0); - -// if (!hrgn) + hrgn = hGetPEBHandle(hctRegionHandle, 0); + + if (!hrgn) hrgn = NtGdiCreateRectRgn(0, 0, 1, 1);
if (!hrgn) @@ -478,6 +474,7 @@
if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr)) { + DPRINT1("No Attr for Region handle!!!\n"); DeleteRegion(hrgn); return NULL; } @@ -778,15 +775,11 @@ nRightRect = nXOffset + nRightRect; nBottomRect = nYOffset + nBottomRect;
- /* Mask and bit test. */ - if ( ( nLeftRect & 0xF8000000 && - (nLeftRect & 0xF8000000) != 0x80000000 ) || - ( nTopRect & 0xF8000000 && - (nTopRect & 0xF8000000) != 0x80000000 ) || - ( nRightRect & 0xF8000000 && - (nRightRect & 0xF8000000) != 0x80000000 ) || - ( nBottomRect & 0xF8000000 && - (nBottomRect & 0xF8000000) != 0x80000000 ) ) + /* Check 28 bit limit. Chp 9 Areas, pg 560. */ + if ( nLeftRect < -(1<<27) || + nTopRect < -(1<<27) || + nRightRect > (1<<27)-1 || + nBottomRect > (1<<27)-1 ) { return ERROR; }
Modified: trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/obj... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c [iso-8859-1] Wed Dec 30 23:56:09 2009 @@ -654,6 +654,69 @@ }
+BOOL +FASTCALL +bPEBCacheHandle(HGDIOBJ Handle, int oType, PVOID pAttr) +{ + PGDIHANDLECACHE GdiHandleCache; + HGDIOBJ *hPtr; + BOOL Ret = FALSE; + int Offset = 0, Number; + HANDLE Lock; + + GdiHandleCache = (PGDIHANDLECACHE)NtCurrentTeb()->ProcessEnvironmentBlock->GdiHandleBuffer; + + switch (oType) + { + case hctBrushHandle: + Offset = 0; + break; + + case hctPenHandle: + Offset = CACHE_BRUSH_ENTRIES; + break; + + case hctRegionHandle: + Offset = CACHE_BRUSH_ENTRIES+CACHE_PEN_ENTRIES; + break; + + default: + return FALSE; + } + + Lock = InterlockedCompareExchangePointer( (PVOID*)&GdiHandleCache->ulLock, + NtCurrentTeb(), + NULL ); + if (Lock) return FALSE; + + _SEH2_TRY + { + Number = GdiHandleCache->ulNumHandles[oType]; + + hPtr = GdiHandleCache->Handle + Offset; + + if ( oType == hctRegionHandle) + { + if ( Number < CACHE_REGION_ENTRIES ) + { + ((PRGN_ATTR)pAttr)->AttrFlags |= ATTR_CACHED; + hPtr[Number] = Handle; + GdiHandleCache->ulNumHandles[oType]++; + DPRINT("Put Handle Count %d\n", GdiHandleCache->ulNumHandles[oType]); + Ret = TRUE; + } + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Ret = FALSE; + } + _SEH2_END; + + (void)InterlockedExchangePointer((PVOID*)&GdiHandleCache->ulLock, Lock); + return Ret; +} + /*! * Delete GDI object * \param hObject object handle @@ -676,11 +739,17 @@ Index = GDI_HANDLE_GET_INDEX(hObject); Entry = &GdiHandleTable->Entries[Index]; pAttr = Entry->UserData; - + switch (dwObjectType) { -// case GDI_OBJECT_TYPE_BRUSH: + case GDI_OBJECT_TYPE_BRUSH: + break; + case GDI_OBJECT_TYPE_REGION: + if (bPEBCacheHandle(hObject, hctRegionHandle, pAttr)) + { + return TRUE; + } if (pAttr) FreeObjectAttr(pAttr); break;
@@ -1485,58 +1554,6 @@
/** PUBLIC FUNCTIONS **********************************************************/
-/* - Since Brush/Pen and Region objects are sharable,,, we can just use - UserHeapAlloc to allocate the small attribute objects. - - Example Allocating: - - // Save Kernel Space Pointer - (PBRUSH)->pBrushAttr = IntGdiAllocObjAttr(GDIObjType_BRUSH_TYPE); - - // Kernel Space to User Space Pointer - (PGDI_TABLE_ENTRY)->UserData = pBrushAttr; - // Gdi will adjust for heap delta. - - Example Freeing: - - (PGDI_TABLE_ENTRY)->UserData = NULL; // Zero the user ptr. - UserHeapFree((PBRUSH)->pBrushAttr); // Free from kernel ptr. - (PBRUSH)->pBrushAttr = NULL; - - Notes: - Testing with DC_ATTR works but has drawing difficulties. - Base on observation, (Over looking the obvious) we need to supply heap delta - to user space gdi. Now, with testing, looks all normal. - - */ -PVOID -FASTCALL -IntGdiAllocObjAttr(GDIOBJTYPE Type) -{ - PVOID pMemAttr = NULL; - - switch( Type ) - { - case GDIObjType_DC_TYPE: - pMemAttr = UserHeapAlloc(sizeof(DC_ATTR)); - if (pMemAttr) RtlZeroMemory(pMemAttr, sizeof(DC_ATTR)); - break; - case GDIObjType_RGN_TYPE: - pMemAttr = UserHeapAlloc(sizeof(RGN_ATTR)); - if (pMemAttr) RtlZeroMemory(pMemAttr, sizeof(RGN_ATTR)); - break; - case GDIObjType_BRUSH_TYPE: - pMemAttr = UserHeapAlloc(sizeof(BRUSH_ATTR)); - if (pMemAttr) RtlZeroMemory(pMemAttr, sizeof(BRUSH_ATTR)); - break; - default: - break; - } - return pMemAttr; -} - - BOOL FASTCALL IntGdiSetBrushOwner(PBRUSH pbr, DWORD OwnerMask)
Modified: trunk/reactos/subsystems/win32/win32k/objects/region.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/obj... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/objects/region.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/objects/region.c [iso-8859-1] Wed Dec 30 23:56:09 2009 @@ -2034,6 +2034,8 @@ { HRGN hReg; PROSRGNDATA pReg; + INT Index; + PGDI_TABLE_ENTRY Entry;
pReg = (PROSRGNDATA)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_REGION); if(!pReg) @@ -2059,6 +2061,10 @@ return NULL; } } + + Index = GDI_HANDLE_GET_INDEX(hReg); + Entry = &GdiHandleTable->Entries[Index]; + Entry->UserData = AllocateObjectAttr();
EMPTY_REGION(pReg); pReg->rdh.dwSize = sizeof(RGNDATAHEADER); @@ -2085,27 +2091,35 @@ Entry = &GdiHandleTable->Entries[Index];
pRgn_Attr = Entry->UserData; + if (pRgn_Attr) { - if ( pRgn_Attr->AttrFlags & (ATTR_RGN_VALID|ATTR_RGN_DIRTY) ) - { - switch (pRgn_Attr->Flags) + _SEH2_TRY + { + if ( pRgn_Attr->AttrFlags & (ATTR_RGN_VALID|ATTR_RGN_DIRTY) ) { - case NULLREGION: - EMPTY_REGION( pRgn ); - pRgn_Attr->AttrFlags &= ~ATTR_RGN_DIRTY; // Clear flag in these cases, - break; - - case SIMPLEREGION: - REGION_SetRectRgn( pRgn, - pRgn_Attr->Rect.left, - pRgn_Attr->Rect.top, - pRgn_Attr->Rect.right, - pRgn_Attr->Rect.bottom ); - pRgn_Attr->AttrFlags &= ~ATTR_RGN_DIRTY; // just incase, force a redraw. - break; + switch (pRgn_Attr->Flags) + { + case NULLREGION: + EMPTY_REGION( pRgn ); + break; + + case SIMPLEREGION: + REGION_SetRectRgn( pRgn, + pRgn_Attr->Rect.left, + pRgn_Attr->Rect.top, + pRgn_Attr->Rect.right, + pRgn_Attr->Rect.bottom ); + break; + } + pRgn_Attr->AttrFlags &= ~ATTR_RGN_DIRTY; } } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + } + _SEH2_END; + if (ppRgn_Attr) *ppRgn_Attr = pRgn_Attr; } @@ -2132,17 +2146,25 @@ Entry = &GdiHandleTable->Entries[Index];
pRgn_Attr = Entry->UserData; - if ( pRgn_Attr ) + + _SEH2_TRY { - if ( pRgn_Attr->AttrFlags & ATTR_RGN_VALID ) - { - pRgn_Attr->Flags = REGION_Complexity( pRgn ); - pRgn_Attr->Rect.left = pRgn->rdh.rcBound.left; - pRgn_Attr->Rect.top = pRgn->rdh.rcBound.top; - pRgn_Attr->Rect.right = pRgn->rdh.rcBound.right; - pRgn_Attr->Rect.bottom = pRgn->rdh.rcBound.bottom; + if ( pRgn_Attr ) + { + if ( pRgn_Attr->AttrFlags & ATTR_RGN_VALID ) + { + pRgn_Attr->Flags = REGION_Complexity( pRgn ); + pRgn_Attr->Rect.left = pRgn->rdh.rcBound.left; + pRgn_Attr->Rect.top = pRgn->rdh.rcBound.top; + pRgn_Attr->Rect.right = pRgn->rdh.rcBound.right; + pRgn_Attr->Rect.bottom = pRgn->rdh.rcBound.bottom; + } } } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + } + _SEH2_END; } REGION_UnlockRgn(pRgn); }