gdi32: Allocate the DIB driver on first use, and free it only upon DC destruction.

This commit is contained in:
Alexandre Julliard 2011-09-07 23:47:31 +02:00
parent da0327917c
commit d12d98511c
6 changed files with 45 additions and 26 deletions

View File

@ -702,13 +702,18 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
} }
old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap ); 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 ); old_physdev = pop_dc_driver( &dc->physDev );
if(bitmap->dib) if(bitmap->dib)
{ {
physdev = &dc->dibdrv.dev; physdev = dc->dibdrv;
push_dc_driver( &dc->physDev, physdev, physdev->funcs ); 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 else
physdev = GET_DC_PHYSDEV( dc, pSelectBitmap ); physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
@ -742,8 +747,10 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
done: done:
if(!ret) if(!ret)
{ {
if(physdev == &dc->dibdrv.dev) pop_dc_driver( &dc->physDev ); if (physdev && physdev == dc->dibdrv)
if(old_physdev == &dc->dibdrv.dev) push_dc_driver( &dc->physDev, old_physdev, old_physdev->funcs ); 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 ); release_dc_ptr( dc );
return ret; return ret;

View File

@ -392,7 +392,7 @@ static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, HDC hdc )
PHYSDEV pattern_dev = physdev; PHYSDEV pattern_dev = physdev;
/* FIXME: This will go away once the dib driver implements /* FIXME: This will go away once the dib driver implements
pattern brushes */ pattern brushes */
if(pattern_dev == &dc->dibdrv.dev) if(pattern_dev == dc->dibdrv)
pattern_dev = GET_NEXT_PHYSDEV( physdev, pSelectBrush ); pattern_dev = GET_NEXT_PHYSDEV( physdev, pSelectBrush );
BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, pattern_dev ); BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, pattern_dev );

View File

@ -79,8 +79,7 @@ DC *alloc_dc_ptr( WORD magic )
dc->nulldrv.funcs = &null_driver; dc->nulldrv.funcs = &null_driver;
dc->nulldrv.next = NULL; dc->nulldrv.next = NULL;
dc->dibdrv.dev.funcs = &dib_driver; dc->dibdrv = NULL;
dc->dibdrv.dev.next = NULL;
dc->physDev = &dc->nulldrv; dc->physDev = &dc->nulldrv;
dc->thread = GetCurrentThreadId(); dc->thread = GetCurrentThreadId();
dc->refcount = 1; dc->refcount = 1;
@ -185,7 +184,9 @@ void free_dc_ptr( DC *dc )
{ {
PHYSDEV physdev = pop_dc_driver( &dc->physDev ); PHYSDEV physdev = pop_dc_driver( &dc->physDev );
physdev->funcs->pDeleteDC( 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_gdi_handle( dc->hSelf );
free_dc_state( dc ); free_dc_state( dc );
} }

View File

@ -349,6 +349,26 @@ void restore_clipping_region( dibdrv_physdev *pdev, HRGN rgn )
pdev->clip = 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 * dibdrv_DeleteDC
*/ */
@ -359,7 +379,8 @@ static BOOL dibdrv_DeleteDC( PHYSDEV dev )
DeleteObject(pdev->clip); DeleteObject(pdev->clip);
free_pattern_brush(pdev); free_pattern_brush(pdev);
free_dib_info(&pdev->dib); 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; if (!bmp) return 0;
assert(bmp->dib); assert(bmp->dib);
pdev->clip = CreateRectRgn(0, 0, 0, 0); free_dib_info(&pdev->dib);
pdev->defer = 0; 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)) if(!init_dib_info_from_bitmapobj(&pdev->dib, bmp, private_color_table))
pdev->defer |= DEFER_FORMAT; pdev->defer |= DEFER_FORMAT;
@ -494,7 +510,7 @@ const DC_FUNCTIONS dib_driver =
NULL, /* pCloseFigure */ NULL, /* pCloseFigure */
NULL, /* pCreateBitmap */ NULL, /* pCreateBitmap */
NULL, /* pCreateCompatibleDC */ NULL, /* pCreateCompatibleDC */
NULL, /* pCreateDC */ dibdrv_CreateDC, /* pCreateDC */
NULL, /* pCreateDIBSection */ NULL, /* pCreateDIBSection */
NULL, /* pDeleteBitmap */ NULL, /* pDeleteBitmap */
dibdrv_DeleteDC, /* pDeleteDC */ dibdrv_DeleteDC, /* pDeleteDC */

View File

@ -40,11 +40,6 @@ static inline dibdrv_physdev *get_dibdrv_pdev( PHYSDEV dev )
return (dibdrv_physdev *)dev; return (dibdrv_physdev *)dev;
} }
static inline DC *get_dibdrv_dc( PHYSDEV dev )
{
return CONTAINING_RECORD( dev, DC, dibdrv );
}
typedef struct primitive_funcs typedef struct primitive_funcs
{ {
void (* solid_rects)(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor); void (* solid_rects)(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor);

View File

@ -186,8 +186,8 @@ typedef struct tagDC
GDIOBJHDR header; GDIOBJHDR header;
HDC hSelf; /* Handle to this DC */ HDC hSelf; /* Handle to this DC */
struct gdi_physdev nulldrv; /* physdev for the null driver */ struct gdi_physdev nulldrv; /* physdev for the null driver */
struct dibdrv_physdev dibdrv; /* physdev for the dib driver */ PHYSDEV dibdrv; /* physdev for the dib driver */
PHYSDEV physDev; /* Physical device (driver-specific) */ PHYSDEV physDev; /* current top of the physdev stack */
DWORD thread; /* thread owning the DC */ DWORD thread; /* thread owning the DC */
LONG refcount; /* thread refcount */ LONG refcount; /* thread refcount */
LONG dirty; /* dirty flag */ LONG dirty; /* dirty flag */