Alexandre Julliard : gdi32: Add a mechanism for stacking gdi drivers.

Alexandre Julliard julliard at winehq.org
Thu Mar 10 11:30:23 CST 2011


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Mar  9 20:10:25 2011 +0100

gdi32: Add a mechanism for stacking gdi drivers.

---

 dlls/gdi32/dc.c            |   52 ++++++++++++++++++++++++++++++++++---------
 dlls/gdi32/enhmfdrv/init.c |    3 +-
 dlls/gdi32/gdi_private.h   |   12 +++++++++-
 dlls/gdi32/mfdrv/init.c    |    3 +-
 dlls/wineps.drv/psdrv.h    |    2 +-
 dlls/winex11.drv/x11drv.h  |    2 +-
 6 files changed, 56 insertions(+), 18 deletions(-)

diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c
index 088f6c7..f25eb8d 100644
--- a/dlls/gdi32/dc.c
+++ b/dlls/gdi32/dc.c
@@ -79,7 +79,8 @@ DC *alloc_dc_ptr( const DC_FUNCTIONS *funcs, WORD magic )
 
     dc->funcs               = funcs;
     dc->nulldrv.funcs       = &null_driver;
-    dc->physDev             = NULL;
+    dc->nulldrv.next        = NULL;
+    dc->physDev             = &dc->nulldrv;
     dc->thread              = GetCurrentThreadId();
     dc->refcount            = 1;
     dc->dirty               = 0;
@@ -229,6 +230,34 @@ void update_dc( DC *dc )
 
 
 /***********************************************************************
+ *           push_dc_driver
+ *
+ * Push a driver on top of the DC driver stack.
+ */
+void push_dc_driver( DC * dc, PHYSDEV physdev )
+{
+    physdev->next = dc->physDev;
+    physdev->hdc = dc->hSelf;
+    dc->physDev = physdev;
+    dc->funcs = physdev->funcs;
+}
+
+
+/***********************************************************************
+ *           pop_dc_driver
+ *
+ * Pop the top driver from the DC driver stack.
+ */
+void pop_dc_driver( DC * dc, PHYSDEV physdev )
+{
+    assert( physdev == dc->physDev );
+    assert( physdev != &dc->nulldrv );
+    dc->physDev = physdev->next;
+    dc->funcs = dc->physDev->funcs;
+}
+
+
+/***********************************************************************
  *           DC_DeleteObject
  */
 static BOOL DC_DeleteObject( HGDIOBJ handle )
@@ -633,6 +662,7 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
 {
     HDC hdc;
     DC * dc;
+    PHYSDEV physdev;
     const DC_FUNCTIONS *funcs;
     WCHAR buf[300];
 
@@ -663,14 +693,15 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
           debugstr_w(driver), debugstr_w(device), debugstr_w(output), dc->hSelf );
 
     if (dc->funcs->pCreateDC &&
-        !dc->funcs->pCreateDC( hdc, &dc->physDev, buf, device, output, initData ))
+        !dc->funcs->pCreateDC( hdc, &physdev, buf, device, output, initData ))
     {
         WARN("creation aborted by device\n" );
         goto error;
     }
 
-    dc->physDev->funcs = funcs;
-    dc->physDev->hdc = hdc;
+    physdev->funcs = funcs;
+    push_dc_driver( dc, physdev );
+
     dc->vis_rect.left   = 0;
     dc->vis_rect.top    = 0;
     dc->vis_rect.right  = GetDeviceCaps( hdc, DESKTOPHORZRES );
@@ -782,21 +813,20 @@ HDC WINAPI CreateCompatibleDC( HDC hdc )
     dc->vis_rect.bottom = 1;
     if (!(dc->hVisRgn = CreateRectRgn( 0, 0, 1, 1 ))) goto error;   /* default bitmap is 1x1 */
 
-    /* Copy the driver-specific physical device info into
-     * the new DC. The driver may use this read-only info
-     * while creating the compatible DC below. */
-    dc->physDev = physDev;
     ret = dc->hSelf;
 
+    /* Pass the driver-specific physical device info into
+     * the new DC. The driver may use this read-only info
+     * while creating the compatible DC. */
     if (dc->funcs->pCreateDC &&
-        !dc->funcs->pCreateDC( dc->hSelf, &dc->physDev, NULL, NULL, NULL, NULL ))
+        !dc->funcs->pCreateDC( dc->hSelf, &physDev, NULL, NULL, NULL, NULL ))
     {
         WARN("creation aborted by device\n");
         goto error;
     }
 
-    dc->physDev->funcs = funcs;
-    dc->physDev->hdc = hdc;
+    physDev->funcs = funcs;
+    push_dc_driver( dc, physDev );
     DC_InitDC( dc );
     release_dc_ptr( dc );
     return ret;
diff --git a/dlls/gdi32/enhmfdrv/init.c b/dlls/gdi32/enhmfdrv/init.c
index efa91ee..241bd7e 100644
--- a/dlls/gdi32/enhmfdrv/init.c
+++ b/dlls/gdi32/enhmfdrv/init.c
@@ -319,9 +319,8 @@ HDC WINAPI CreateEnhMetaFileW(
         free_dc_ptr( dc );
         return 0;
     }
-    dc->physDev = (PHYSDEV)physDev;
     physDev->dev.funcs = &EMFDRV_Funcs;
-    physDev->dev.hdc = dc->hSelf;
+    push_dc_driver( dc, &physDev->dev );
     physDev->hdc = dc->hSelf;
 
     if(description) { /* App name\0Title\0\0 */
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index efa61a0..7b72c45 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -75,6 +75,7 @@ typedef struct tagGDIOBJHDR
 typedef struct gdi_physdev
 {
     const struct tagDC_FUNCS *funcs;
+    struct gdi_physdev       *next;
     HDC                       hdc;
 } *PHYSDEV;
 
@@ -377,6 +378,8 @@ extern BOOL free_dc_ptr( DC *dc ) DECLSPEC_HIDDEN;
 extern DC *get_dc_ptr( HDC hdc ) DECLSPEC_HIDDEN;
 extern void release_dc_ptr( DC *dc ) DECLSPEC_HIDDEN;
 extern void update_dc( DC *dc ) DECLSPEC_HIDDEN;
+extern void push_dc_driver( DC * dc, PHYSDEV physdev ) DECLSPEC_HIDDEN;
+extern void pop_dc_driver( DC * dc, PHYSDEV physdev ) DECLSPEC_HIDDEN;
 extern void DC_InitDC( DC * dc ) DECLSPEC_HIDDEN;
 extern void DC_UpdateXforms( DC * dc ) DECLSPEC_HIDDEN;
 extern INT save_dc_state( HDC hdc ) DECLSPEC_HIDDEN;
@@ -395,7 +398,14 @@ extern const DC_FUNCTIONS *DRIVER_get_display_driver(void) DECLSPEC_HIDDEN;
 extern const DC_FUNCTIONS *DRIVER_load_driver( LPCWSTR name ) DECLSPEC_HIDDEN;
 extern BOOL DRIVER_GetDriverName( LPCWSTR device, LPWSTR driver, DWORD size ) DECLSPEC_HIDDEN;
 
-#define GET_DC_PHYSDEV(dc,func) ((dc)->physDev->funcs->func ? (dc)->physDev : &(dc)->nulldrv)
+static inline PHYSDEV get_physdev_entry_point( PHYSDEV dev, size_t offset )
+{
+    while (!((void **)dev->funcs)[offset / sizeof(void *)]) dev = dev->next;
+    return dev;
+}
+
+#define GET_DC_PHYSDEV(dc,func) get_physdev_entry_point( (dc)->physDev, FIELD_OFFSET(DC_FUNCTIONS,func))
+#define GET_NEXT_PHYSDEV(dev,func) get_physdev_entry_point( (dev)->next, FIELD_OFFSET(DC_FUNCTIONS,func))
 
 /* enhmetafile.c */
 extern HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, BOOL on_disk ) DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/mfdrv/init.c b/dlls/gdi32/mfdrv/init.c
index 4659e73..3bb815b 100644
--- a/dlls/gdi32/mfdrv/init.c
+++ b/dlls/gdi32/mfdrv/init.c
@@ -171,9 +171,8 @@ static DC *MFDRV_AllocMetaFile(void)
         free_dc_ptr( dc );
         return NULL;
     }
-    dc->physDev = (PHYSDEV)physDev;
     physDev->dev.funcs = &MFDRV_Funcs;
-    physDev->dev.hdc = dc->hSelf;
+    push_dc_driver( dc, &physDev->dev );
     physDev->hdc = dc->hSelf;
 
     if (!(physDev->mh = HeapAlloc( GetProcessHeap(), 0, sizeof(*physDev->mh) )))
diff --git a/dlls/wineps.drv/psdrv.h b/dlls/wineps.drv/psdrv.h
index 62f9ccc..c6c7571 100644
--- a/dlls/wineps.drv/psdrv.h
+++ b/dlls/wineps.drv/psdrv.h
@@ -353,7 +353,7 @@ typedef struct {
 
 typedef struct
 {
-    void               *reserved[2];    /* reserved for gdi */
+    void               *reserved[3];    /* reserved for gdi */
     HDC                 hdc;
     PSFONT		font;		/* Current PS font */
     DOWNLOAD            *downloaded_fonts;
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index da59d7e..6048096 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -144,7 +144,7 @@ struct xrender_info;
   /* X physical device */
 typedef struct
 {
-    void         *reserved[2];  /* reserved for gdi */
+    void         *reserved[3];  /* reserved for gdi */
     HDC           hdc;
     GC            gc;          /* X Window GC */
     Drawable      drawable;




More information about the wine-cvs mailing list