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

Alexandre Julliard julliard at winehq.org
Thu Sep 8 14:52:10 CDT 2011


Module: wine
Branch: master
Commit: d12d98511cc6257b0d8aa6e3af3e804b0a098a2f
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d12d98511cc6257b0d8aa6e3af3e804b0a098a2f

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Sep  7 23:47:31 2011 +0200

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 95a45ff..9c77016 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 28d326f..ca95f20 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 5ba4e59..65cc3f7 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 f6ab1e2..8ab7a06 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 23a59ee..c1f7e8b 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 e9c992a..7fe633c 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;




More information about the wine-cvs mailing list