From d12d98511cc6257b0d8aa6e3af3e804b0a098a2f Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 7 Sep 2011 23:47:31 +0200 Subject: [PATCH] gdi32: Allocate the DIB driver on first use, and free it only upon DC destruction. --- dlls/gdi32/bitmap.c | 17 ++++++++++++----- dlls/gdi32/brush.c | 2 +- dlls/gdi32/dc.c | 5 +++-- dlls/gdi32/dibdrv/dc.c | 32 ++++++++++++++++++++++++-------- dlls/gdi32/dibdrv/dibdrv.h | 5 ----- dlls/gdi32/gdi_private.h | 10 +++++----- 6 files changed, 45 insertions(+), 26 deletions(-) diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c index 95a45ffbffa..9c7701674a0 100644 --- a/dlls/gdi32/bitmap.c +++ b/dlls/gdi32/bitmap.c @@ -702,13 +702,18 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc ) } old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap ); - if(old_physdev == &dc->dibdrv.dev) + if(old_physdev == dc->dibdrv) old_physdev = pop_dc_driver( &dc->physDev ); if(bitmap->dib) { - physdev = &dc->dibdrv.dev; - push_dc_driver( &dc->physDev, physdev, physdev->funcs ); + physdev = dc->dibdrv; + if (physdev) push_dc_driver( &dc->physDev, physdev, physdev->funcs ); + else + { + if (!dib_driver.pCreateDC( &dc->physDev, NULL, NULL, NULL, NULL )) goto done; + dc->dibdrv = physdev = dc->physDev; + } } else physdev = GET_DC_PHYSDEV( dc, pSelectBitmap ); @@ -742,8 +747,10 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc ) done: if(!ret) { - if(physdev == &dc->dibdrv.dev) pop_dc_driver( &dc->physDev ); - if(old_physdev == &dc->dibdrv.dev) push_dc_driver( &dc->physDev, old_physdev, old_physdev->funcs ); + if (physdev && physdev == dc->dibdrv) + pop_dc_driver( &dc->physDev ); + if (old_physdev && old_physdev == dc->dibdrv) + push_dc_driver( &dc->physDev, old_physdev, old_physdev->funcs ); } release_dc_ptr( dc ); return ret; diff --git a/dlls/gdi32/brush.c b/dlls/gdi32/brush.c index 28d326f1295..ca95f2089ac 100644 --- a/dlls/gdi32/brush.c +++ b/dlls/gdi32/brush.c @@ -392,7 +392,7 @@ static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, HDC hdc ) PHYSDEV pattern_dev = physdev; /* FIXME: This will go away once the dib driver implements pattern brushes */ - if(pattern_dev == &dc->dibdrv.dev) + if(pattern_dev == dc->dibdrv) pattern_dev = GET_NEXT_PHYSDEV( physdev, pSelectBrush ); BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, pattern_dev ); diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 5ba4e59f63e..65cc3f78a3a 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -79,8 +79,7 @@ DC *alloc_dc_ptr( WORD magic ) dc->nulldrv.funcs = &null_driver; dc->nulldrv.next = NULL; - dc->dibdrv.dev.funcs = &dib_driver; - dc->dibdrv.dev.next = NULL; + dc->dibdrv = NULL; dc->physDev = &dc->nulldrv; dc->thread = GetCurrentThreadId(); dc->refcount = 1; @@ -185,7 +184,9 @@ void free_dc_ptr( DC *dc ) { PHYSDEV physdev = pop_dc_driver( &dc->physDev ); physdev->funcs->pDeleteDC( physdev ); + if (physdev == dc->dibdrv) dc->dibdrv = NULL; } + if (dc->dibdrv) dc->dibdrv->funcs->pDeleteDC( dc->dibdrv ); free_gdi_handle( dc->hSelf ); free_dc_state( dc ); } diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c index f6ab1e2af03..8ab7a060fb6 100644 --- a/dlls/gdi32/dibdrv/dc.c +++ b/dlls/gdi32/dibdrv/dc.c @@ -349,6 +349,26 @@ void restore_clipping_region( dibdrv_physdev *pdev, HRGN rgn ) pdev->clip = rgn; } +/********************************************************************** + * dibdrv_CreateDC + */ +static BOOL dibdrv_CreateDC( PHYSDEV *dev, LPCWSTR driver, LPCWSTR device, + LPCWSTR output, const DEVMODEW *data ) +{ + dibdrv_physdev *pdev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pdev) ); + + if (!pdev) return FALSE; + if (!(pdev->clip = CreateRectRgn(0, 0, 0, 0))) + { + HeapFree( GetProcessHeap(), 0, pdev ); + return FALSE; + } + clear_dib_info(&pdev->dib); + clear_dib_info(&pdev->brush_dib); + push_dc_driver( dev, &pdev->dev, &dib_driver ); + return TRUE; +} + /*********************************************************************** * dibdrv_DeleteDC */ @@ -359,7 +379,8 @@ static BOOL dibdrv_DeleteDC( PHYSDEV dev ) DeleteObject(pdev->clip); free_pattern_brush(pdev); free_dib_info(&pdev->dib); - return 0; + HeapFree( GetProcessHeap(), 0, pdev ); + return TRUE; } /*********************************************************************** @@ -375,13 +396,8 @@ static HBITMAP dibdrv_SelectBitmap( PHYSDEV dev, HBITMAP bitmap ) if (!bmp) return 0; assert(bmp->dib); - pdev->clip = CreateRectRgn(0, 0, 0, 0); + free_dib_info(&pdev->dib); pdev->defer = 0; - - clear_dib_info(&pdev->dib); - clear_dib_info(&pdev->brush_dib); - pdev->brush_and_bits = pdev->brush_xor_bits = NULL; - if(!init_dib_info_from_bitmapobj(&pdev->dib, bmp, private_color_table)) pdev->defer |= DEFER_FORMAT; @@ -494,7 +510,7 @@ const DC_FUNCTIONS dib_driver = NULL, /* pCloseFigure */ NULL, /* pCreateBitmap */ NULL, /* pCreateCompatibleDC */ - NULL, /* pCreateDC */ + dibdrv_CreateDC, /* pCreateDC */ NULL, /* pCreateDIBSection */ NULL, /* pDeleteBitmap */ dibdrv_DeleteDC, /* pDeleteDC */ diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h index 23a59ee0458..c1f7e8b3407 100644 --- a/dlls/gdi32/dibdrv/dibdrv.h +++ b/dlls/gdi32/dibdrv/dibdrv.h @@ -40,11 +40,6 @@ static inline dibdrv_physdev *get_dibdrv_pdev( PHYSDEV dev ) return (dibdrv_physdev *)dev; } -static inline DC *get_dibdrv_dc( PHYSDEV dev ) -{ - return CONTAINING_RECORD( dev, DC, dibdrv ); -} - typedef struct primitive_funcs { void (* solid_rects)(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor); diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index e9c992a1548..7fe633c0d2b 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -186,11 +186,11 @@ typedef struct tagDC GDIOBJHDR header; HDC hSelf; /* Handle to this DC */ struct gdi_physdev nulldrv; /* physdev for the null driver */ - struct dibdrv_physdev dibdrv; /* physdev for the dib driver */ - PHYSDEV physDev; /* Physical device (driver-specific) */ - DWORD thread; /* thread owning the DC */ - LONG refcount; /* thread refcount */ - LONG dirty; /* dirty flag */ + PHYSDEV dibdrv; /* physdev for the dib driver */ + PHYSDEV physDev; /* current top of the physdev stack */ + DWORD thread; /* thread owning the DC */ + LONG refcount; /* thread refcount */ + LONG dirty; /* dirty flag */ INT saveLevel; struct tagDC *saved_dc; DWORD_PTR dwHookData; -- 2.11.4.GIT