Added reference counting and delayed destruction of GDI objects.

This commit is contained in:
Uwe Bonnes 2001-08-20 19:17:28 +00:00 committed by Alexandre Julliard
parent d44e495aa4
commit 8e5e003f09
2 changed files with 59 additions and 3 deletions

View File

@ -757,6 +757,7 @@ BOOL WINAPI DeleteDC( HDC hdc )
SelectObject( hdc, GetStockObject(BLACK_PEN) ); SelectObject( hdc, GetStockObject(BLACK_PEN) );
SelectObject( hdc, GetStockObject(WHITE_BRUSH) ); SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
SelectObject( hdc, GetStockObject(SYSTEM_FONT) ); SelectObject( hdc, GetStockObject(SYSTEM_FONT) );
SelectObject( hdc, GetStockObject(DEFAULT_BITMAP) );
funcs = dc->funcs; funcs = dc->funcs;
if (dc->funcs->pDeleteDC) dc->funcs->pDeleteDC(dc); if (dc->funcs->pDeleteDC) dc->funcs->pDeleteDC(dc);
} }

View File

@ -144,6 +144,48 @@ static HFONT create_stock_font( char const *fontName, const LOGFONTW *font, HKEY
TRACE("(%04x): " text " %ld\n", (handle), GDI_level.crst.RecursionCount) TRACE("(%04x): " text " %ld\n", (handle), GDI_level.crst.RecursionCount)
/***********************************************************************
* inc_ref_count
*
* Increment the reference count of a GDI object.
*/
inline static void inc_ref_count( HGDIOBJ handle )
{
GDIOBJHDR *header;
if ((header = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
{
header->dwCount++;
GDI_ReleaseObj( handle );
}
}
/***********************************************************************
* dec_ref_count
*
* Decrement the reference count of a GDI object.
*/
inline static void dec_ref_count( HGDIOBJ handle )
{
GDIOBJHDR *header;
if ((header = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
{
if (header->dwCount) header->dwCount--;
if (header->dwCount != 0x80000000) GDI_ReleaseObj( handle );
else
{
/* handle delayed DeleteObject*/
header->dwCount = 0;
GDI_ReleaseObj( handle );
TRACE( "executing delayed DeleteObject for %04x\n", handle );
DeleteObject( handle );
}
}
}
/*********************************************************************** /***********************************************************************
* GDI_Init * GDI_Init
* *
@ -243,7 +285,6 @@ inline static GDIOBJHDR *alloc_large_heap( WORD size, HGDIOBJ *handle )
*/ */
void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle ) void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle )
{ {
static DWORD count = 0;
GDIOBJHDR *obj; GDIOBJHDR *obj;
_EnterSysLevel( &GDI_level ); _EnterSysLevel( &GDI_level );
@ -269,7 +310,7 @@ void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle )
obj->hNext = 0; obj->hNext = 0;
obj->wMagic = magic|OBJECT_NOSYSTEM; obj->wMagic = magic|OBJECT_NOSYSTEM;
obj->dwCount = ++count; obj->dwCount = 0;
TRACE_SEC( *handle, "enter" ); TRACE_SEC( *handle, "enter" );
return obj; return obj;
@ -427,7 +468,15 @@ BOOL WINAPI DeleteObject( HGDIOBJ obj )
GDI_ReleaseObj( obj ); GDI_ReleaseObj( obj );
return TRUE; return TRUE;
} }
if (header->dwCount)
{
TRACE("delayed for %04x because object in use, count %ld\n", obj, header->dwCount );
header->dwCount |= 0x80000000; /* mark for delete */
GDI_ReleaseObj( obj );
return TRUE;
}
TRACE("%04x\n", obj ); TRACE("%04x\n", obj );
/* Delete object */ /* Delete object */
@ -701,6 +750,12 @@ HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
if (dc->funcs->pSelectObject) if (dc->funcs->pSelectObject)
ret = dc->funcs->pSelectObject( dc, handle ); ret = dc->funcs->pSelectObject( dc, handle );
GDI_ReleaseObj( hdc ); GDI_ReleaseObj( hdc );
if (ret && ret != handle)
{
inc_ref_count( handle );
dec_ref_count( ret );
}
return ret; return ret;
} }