gdi32: Store the object selection count directly in the GDI handle table.

oldstable
Alexandre Julliard 2012-10-17 13:17:56 +02:00
parent 5f14ff42a8
commit b95dd7e831
4 changed files with 40 additions and 22 deletions

View File

@ -436,7 +436,7 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
goto done; goto done;
} }
if (bitmap->header.selcount && (handle != GetStockObject(DEFAULT_BITMAP))) if (handle != GetStockObject(DEFAULT_BITMAP) && GDI_get_ref_count( handle ))
{ {
WARN( "Bitmap already selected in another DC\n" ); WARN( "Bitmap already selected in another DC\n" );
GDI_ReleaseObj( handle ); GDI_ReleaseObj( handle );

View File

@ -1589,7 +1589,7 @@ static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc )
goto done; goto done;
} }
if (bitmap->header.selcount) if (GDI_get_ref_count( handle ))
{ {
WARN( "Bitmap already selected in another DC\n" ); WARN( "Bitmap already selected in another DC\n" );
GDI_ReleaseObj( handle ); GDI_ReleaseObj( handle );

View File

@ -61,7 +61,6 @@ typedef struct tagGDIOBJHDR
{ {
WORD system : 1; /* system object flag */ WORD system : 1; /* system object flag */
WORD deleted : 1; /* whether DeleteObject has been called on this object */ WORD deleted : 1; /* whether DeleteObject has been called on this object */
DWORD selcount; /* number of times the object is selected in a DC */
} GDIOBJHDR; } GDIOBJHDR;
typedef struct tagGdiFont GdiFont; typedef struct tagGdiFont GdiFont;
@ -316,6 +315,7 @@ extern void *free_gdi_handle( HGDIOBJ handle ) DECLSPEC_HIDDEN;
extern void *GDI_GetObjPtr( HGDIOBJ, WORD ) DECLSPEC_HIDDEN; extern void *GDI_GetObjPtr( HGDIOBJ, WORD ) DECLSPEC_HIDDEN;
extern void GDI_ReleaseObj( HGDIOBJ ) DECLSPEC_HIDDEN; extern void GDI_ReleaseObj( HGDIOBJ ) DECLSPEC_HIDDEN;
extern void GDI_CheckNotLock(void) DECLSPEC_HIDDEN; extern void GDI_CheckNotLock(void) DECLSPEC_HIDDEN;
extern UINT GDI_get_ref_count( HGDIOBJ handle ) DECLSPEC_HIDDEN;
extern HGDIOBJ GDI_inc_ref_count( HGDIOBJ handle ) DECLSPEC_HIDDEN; extern HGDIOBJ GDI_inc_ref_count( HGDIOBJ handle ) DECLSPEC_HIDDEN;
extern BOOL GDI_dec_ref_count( HGDIOBJ handle ) DECLSPEC_HIDDEN; extern BOOL GDI_dec_ref_count( HGDIOBJ handle ) DECLSPEC_HIDDEN;
extern void GDI_hdc_using_object(HGDIOBJ obj, HDC hdc) DECLSPEC_HIDDEN; extern void GDI_hdc_using_object(HGDIOBJ obj, HDC hdc) DECLSPEC_HIDDEN;

View File

@ -53,6 +53,7 @@ struct gdi_handle_entry
const struct gdi_obj_funcs *funcs; /* type-specific functions */ const struct gdi_obj_funcs *funcs; /* type-specific functions */
struct hdc_list *hdcs; /* list of HDCs interested in this object */ struct hdc_list *hdcs; /* list of HDCs interested in this object */
WORD type; /* object type (one of the OBJ_* constants) */ WORD type; /* object type (one of the OBJ_* constants) */
WORD selcount; /* number of times the object is selected in a DC */
}; };
static struct gdi_handle_entry gdi_handles[MAX_GDI_HANDLES]; static struct gdi_handle_entry gdi_handles[MAX_GDI_HANDLES];
@ -523,6 +524,24 @@ static UINT get_default_charset( void )
} }
/***********************************************************************
* GDI_get_ref_count
*
* Retrieve the reference count of a GDI object.
* Note: the object must be locked otherwise the count is meaningless.
*/
UINT GDI_get_ref_count( HGDIOBJ handle )
{
struct gdi_handle_entry *entry;
UINT ret = 0;
EnterCriticalSection( &gdi_section );
if ((entry = handle_entry( handle ))) ret = entry->selcount;
LeaveCriticalSection( &gdi_section );
return ret;
}
/*********************************************************************** /***********************************************************************
* GDI_inc_ref_count * GDI_inc_ref_count
* *
@ -530,15 +549,12 @@ static UINT get_default_charset( void )
*/ */
HGDIOBJ GDI_inc_ref_count( HGDIOBJ handle ) HGDIOBJ GDI_inc_ref_count( HGDIOBJ handle )
{ {
GDIOBJHDR *header; struct gdi_handle_entry *entry;
if ((header = GDI_GetObjPtr( handle, 0 ))) EnterCriticalSection( &gdi_section );
{ if ((entry = handle_entry( handle ))) entry->selcount++;
header->selcount++;
GDI_ReleaseObj( handle );
}
else handle = 0; else handle = 0;
LeaveCriticalSection( &gdi_section );
return handle; return handle;
} }
@ -550,22 +566,24 @@ HGDIOBJ GDI_inc_ref_count( HGDIOBJ handle )
*/ */
BOOL GDI_dec_ref_count( HGDIOBJ handle ) BOOL GDI_dec_ref_count( HGDIOBJ handle )
{ {
GDIOBJHDR *header; struct gdi_handle_entry *entry;
if ((header = GDI_GetObjPtr( handle, 0 ))) EnterCriticalSection( &gdi_section );
if ((entry = handle_entry( handle )))
{ {
assert( header->selcount ); assert( entry->selcount );
if (!--header->selcount && header->deleted) if (!--entry->selcount && entry->obj->deleted)
{ {
/* handle delayed DeleteObject*/ /* handle delayed DeleteObject*/
header->deleted = 0; entry->obj->deleted = 0;
GDI_ReleaseObj( handle ); LeaveCriticalSection( &gdi_section );
TRACE( "executing delayed DeleteObject for %p\n", handle ); TRACE( "executing delayed DeleteObject for %p\n", handle );
DeleteObject( handle ); DeleteObject( handle );
return TRUE;
} }
else GDI_ReleaseObj( handle );
} }
return header != NULL; LeaveCriticalSection( &gdi_section );
return entry != NULL;
} }
@ -668,7 +686,7 @@ static void dump_gdi_objects( void )
} }
TRACE( "handle %p obj %p type %s selcount %u deleted %u\n", TRACE( "handle %p obj %p type %s selcount %u deleted %u\n",
entry_to_handle( entry ), entry->obj, gdi_obj_type( entry->type ), entry_to_handle( entry ), entry->obj, gdi_obj_type( entry->type ),
entry->obj->selcount, entry->obj->deleted ); entry->selcount, entry->obj->deleted );
} }
LeaveCriticalSection( &gdi_section ); LeaveCriticalSection( &gdi_section );
} }
@ -689,7 +707,6 @@ HGDIOBJ alloc_gdi_handle( GDIOBJHDR *obj, WORD type, const struct gdi_obj_funcs
/* initialize the object header */ /* initialize the object header */
obj->system = 0; obj->system = 0;
obj->deleted = 0; obj->deleted = 0;
obj->selcount = 0;
EnterCriticalSection( &gdi_section ); EnterCriticalSection( &gdi_section );
for (i = next_gdi_handle + 1; i < MAX_GDI_HANDLES; i++) for (i = next_gdi_handle + 1; i < MAX_GDI_HANDLES; i++)
@ -708,6 +725,7 @@ HGDIOBJ alloc_gdi_handle( GDIOBJHDR *obj, WORD type, const struct gdi_obj_funcs
entry->funcs = funcs; entry->funcs = funcs;
entry->hdcs = NULL; entry->hdcs = NULL;
entry->type = type; entry->type = type;
entry->selcount = 0;
next_gdi_handle = i; next_gdi_handle = i;
ret = entry_to_handle( entry ); ret = entry_to_handle( entry );
LeaveCriticalSection( &gdi_section ); LeaveCriticalSection( &gdi_section );
@ -829,9 +847,9 @@ BOOL WINAPI DeleteObject( HGDIOBJ obj )
hdcs_head = entry->hdcs; hdcs_head = entry->hdcs;
entry->hdcs = NULL; entry->hdcs = NULL;
if (entry->obj->selcount) if (entry->selcount)
{ {
TRACE("delayed for %p because object in use, count %u\n", obj, entry->obj->selcount ); TRACE("delayed for %p because object in use, count %u\n", obj, entry->selcount );
entry->obj->deleted = 1; /* mark for delete */ entry->obj->deleted = 1; /* mark for delete */
} }
else funcs = entry->funcs; else funcs = entry->funcs;