Module: wine Branch: master Commit: b95dd7e831215ca80b341332598df600bd148a36 URL: http://source.winehq.org/git/wine.git/?a=commit;h=b95dd7e831215ca80b34133259...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Oct 17 13:17:56 2012 +0200
gdi32: Store the object selection count directly in the GDI handle table.
---
dlls/gdi32/bitmap.c | 2 +- dlls/gdi32/dib.c | 2 +- dlls/gdi32/gdi_private.h | 2 +- dlls/gdi32/gdiobj.c | 56 ++++++++++++++++++++++++++++++--------------- 4 files changed, 40 insertions(+), 22 deletions(-)
diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c index 38bc172..0055fe4 100644 --- a/dlls/gdi32/bitmap.c +++ b/dlls/gdi32/bitmap.c @@ -436,7 +436,7 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc ) 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" ); GDI_ReleaseObj( handle ); diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c index eed57e8..89ac980 100644 --- a/dlls/gdi32/dib.c +++ b/dlls/gdi32/dib.c @@ -1589,7 +1589,7 @@ static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc ) goto done; }
- if (bitmap->header.selcount) + if (GDI_get_ref_count( handle )) { WARN( "Bitmap already selected in another DC\n" ); GDI_ReleaseObj( handle ); diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 5dadbc2..cb2f9cd 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -61,7 +61,6 @@ typedef struct tagGDIOBJHDR { WORD system : 1; /* system object flag */ WORD deleted : 1; /* whether DeleteObject has been called on this object */ - DWORD selcount; /* number of times the object is selected in a DC */ } GDIOBJHDR;
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_ReleaseObj( HGDIOBJ ) 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 BOOL GDI_dec_ref_count( HGDIOBJ handle ) DECLSPEC_HIDDEN; extern void GDI_hdc_using_object(HGDIOBJ obj, HDC hdc) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/gdiobj.c b/dlls/gdi32/gdiobj.c index afc0c59..4fe72a9 100644 --- a/dlls/gdi32/gdiobj.c +++ b/dlls/gdi32/gdiobj.c @@ -53,6 +53,7 @@ struct gdi_handle_entry const struct gdi_obj_funcs *funcs; /* type-specific functions */ struct hdc_list *hdcs; /* list of HDCs interested in this object */ 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]; @@ -524,21 +525,36 @@ 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 * * Increment the reference count of a GDI object. */ HGDIOBJ GDI_inc_ref_count( HGDIOBJ handle ) { - GDIOBJHDR *header; + struct gdi_handle_entry *entry;
- if ((header = GDI_GetObjPtr( handle, 0 ))) - { - header->selcount++; - GDI_ReleaseObj( handle ); - } + EnterCriticalSection( &gdi_section ); + if ((entry = handle_entry( handle ))) entry->selcount++; else handle = 0; - + LeaveCriticalSection( &gdi_section ); return handle; }
@@ -550,22 +566,24 @@ HGDIOBJ GDI_inc_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 ); - if (!--header->selcount && header->deleted) + assert( entry->selcount ); + if (!--entry->selcount && entry->obj->deleted) { /* handle delayed DeleteObject*/ - header->deleted = 0; - GDI_ReleaseObj( handle ); + entry->obj->deleted = 0; + LeaveCriticalSection( &gdi_section ); TRACE( "executing delayed DeleteObject for %p\n", 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", 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 ); } @@ -689,7 +707,6 @@ HGDIOBJ alloc_gdi_handle( GDIOBJHDR *obj, WORD type, const struct gdi_obj_funcs /* initialize the object header */ obj->system = 0; obj->deleted = 0; - obj->selcount = 0;
EnterCriticalSection( &gdi_section ); 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->hdcs = NULL; entry->type = type; + entry->selcount = 0; next_gdi_handle = i; ret = entry_to_handle( entry ); LeaveCriticalSection( &gdi_section ); @@ -829,9 +847,9 @@ BOOL WINAPI DeleteObject( HGDIOBJ obj ) hdcs_head = entry->hdcs; 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 */ } else funcs = entry->funcs;