forked from Mirrors/wine-wine
gdi32: Store the object selection count directly in the GDI handle table.
parent
5f14ff42a8
commit
b95dd7e831
|
@ -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 );
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue