winex11.drv: Remove x11drv_win_data dependency in dce code, in order to move dce.c in user32.

Pierre d'Herbemont pdherbemont at free.fr
Wed Dec 13 18:16:08 CST 2006


This patch prepares the factorization of graphics drivers' dce code in 
user32. The only problematic part may be the addition of a new escape 
X11DRV_SET_HWND, and which would need to be generalized to all drivers.

Alternatively we could achieve the same by adding a new driver function 
that would call trigger X11DRV_SET_DRAWABLE.

The connection between hwnd and its own dce is maintained in a new list 
called hwnd_to_dce_list. Its goal is to replace the 
X11DRV_get_win_data(hwnd)->dce call. I don't really know if GetDC is 
time critical but this could impact performances if XFindContext is 
doing is job in less than O(n).

This new list is probably not needed, and could have probably been 
replaced by correctly parsing dce_list elements' flags, but I am not 
sure of this and I think it would be less simple and less effective than 
doing this.

Pierre.
---
  dlls/winex11.drv/dce.c    |   98 
+++++++++++++++++++++++++++++---------------
  dlls/winex11.drv/init.c   |   20 +++++++++
  dlls/winex11.drv/window.c |    5 +-
  dlls/winex11.drv/x11drv.h |   15 +++++-
  4 files changed, 98 insertions(+), 40 deletions(-)
-------------- next part --------------
diff --git a/dlls/winex11.drv/dce.c b/dlls/winex11.drv/dce.c
index a0454cb..78ec3c0 100644
--- a/dlls/winex11.drv/dce.c
+++ b/dlls/winex11.drv/dce.c
@@ -49,7 +49,15 @@ struct dce
                                   always >= 1 for class DCEs */
 };
 
+struct hwnd_to_dce
+{
+    struct list entry;         /* entry in global DCE list */
+    struct dce  *dce;
+    HWND        hwnd;
+};
+
 static struct list dce_list = LIST_INIT(dce_list);
+static struct list hwnd_to_dce_list = LIST_INIT(hwnd_to_dce_list);
 
 static BOOL16 CALLBACK dc_hook( HDC16 hDC, WORD code, DWORD data, LPARAM lParam );
 
@@ -85,11 +93,29 @@ static void dump_cache(void)
     LeaveCriticalSection( &dce_section );
 }
 
+/***********************************************************************
+ *           get_hwnd_to_dce
+ */
+static struct hwnd_to_dce * get_hwnd_to_dce(HWND hwnd)
+{
+    struct hwnd_to_dce *hwnd_to_dce;
+    EnterCriticalSection( &dce_section );
+    LIST_FOR_EACH_ENTRY( hwnd_to_dce, &hwnd_to_dce_list, struct hwnd_to_dce, entry )
+    {
+        if (hwnd_to_dce->hwnd == hwnd)
+        {
+            LeaveCriticalSection( &dce_section );
+            return hwnd_to_dce;
+        }
+    }
+    LeaveCriticalSection( &dce_section );
+    return NULL;
+}
 
 /***********************************************************************
  *		update_visible_region
  *
- * Set the visible region and X11 drawable for the DC associated to
+ * Set the visible region and hwnd for the DC associated to
  * a given window.
  */
 static void update_visible_region( struct dce *dce )
@@ -97,8 +123,7 @@ static void update_visible_region( struc
     NTSTATUS status;
     HRGN vis_rgn = 0;
     HWND top = 0;
-    struct x11drv_escape_set_drawable escape;
-    struct x11drv_win_data *data;
+    struct x11drv_escape_set_hwnd escape;
     DWORD flags = dce->flags;
     size_t size = 256;
 
@@ -130,10 +155,10 @@ static void update_visible_region( struc
                 escape.dc_rect.top = reply->win_rect.top - reply->top_rect.top;
                 escape.dc_rect.right = reply->win_rect.right - reply->top_rect.left;
                 escape.dc_rect.bottom = reply->win_rect.bottom - reply->top_rect.top;
-                escape.drawable_rect.left = reply->top_rect.left;
-                escape.drawable_rect.top = reply->top_rect.top;
-                escape.drawable_rect.right = reply->top_rect.right;
-                escape.drawable_rect.bottom = reply->top_rect.bottom;
+                escape.hwnd_rect.left = reply->top_rect.left;
+                escape.hwnd_rect.top = reply->top_rect.top;
+                escape.hwnd_rect.right = reply->top_rect.right;
+                escape.hwnd_rect.bottom = reply->top_rect.bottom;
             }
             else size = reply->total_size;
         }
@@ -146,20 +171,15 @@ static void update_visible_region( struc
     if (dce->clip_rgn) CombineRgn( vis_rgn, vis_rgn, dce->clip_rgn,
                                    (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
 
-    if (top == dce->hwnd && ((data = X11DRV_get_win_data( dce->hwnd )) != NULL) &&
-         IsIconic( dce->hwnd ) && data->icon_window)
-        escape.drawable = data->icon_window;
-    else
-        escape.drawable = X11DRV_get_whole_window( top );
-
-    escape.code = X11DRV_SET_DRAWABLE;
-    escape.mode = IncludeInferiors;
+    escape.hwnd = top;
+    escape.allow_iconic = (top == dce->hwnd) && IsIconic( top );
+    escape.code = X11DRV_SET_HWND;
     ExtEscape( dce->hdc, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL );
 
     /* map region to DC coordinates */
     OffsetRgn( vis_rgn,
-               -(escape.drawable_rect.left + escape.dc_rect.left),
-               -(escape.drawable_rect.top + escape.dc_rect.top) );
+               -(escape.hwnd_rect.left + escape.dc_rect.left),
+               -(escape.hwnd_rect.top + escape.dc_rect.top) );
     SelectVisRgn16( HDC_16(dce->hdc), HRGN_16(vis_rgn) );
     DeleteObject( vis_rgn );
 }
@@ -249,19 +269,24 @@ static struct dce *alloc_cache_dce(void)
  *
  * Allocate a DCE for a newly created window if necessary.
  */
-void alloc_window_dce( struct x11drv_win_data *data )
+void alloc_window_dce( HWND hwnd )
 {
     struct x11drv_escape_set_dce escape;
+    struct hwnd_to_dce *hwnd_to_dce;
     struct dce *dce;
     void *class_ptr = NULL;
-    LONG style = GetClassLongW( data->hwnd, GCL_STYLE );
+    LONG style = GetClassLongW( hwnd, GCL_STYLE );
 
     if (!(style & (CS_CLASSDC|CS_OWNDC))) return;  /* nothing to do */
 
+    if (!(hwnd_to_dce = HeapAlloc( GetProcessHeap(), 0, sizeof(*hwnd_to_dce) ))) return;
+
+    hwnd_to_dce->hwnd = hwnd;
+
     if (!(style & CS_OWNDC))  /* class dc */
     {
         /* hack: get the class pointer from the window structure */
-        WND *win = WIN_GetPtr( data->hwnd );
+        WND *win = WIN_GetPtr( hwnd );
         class_ptr = win->class;
         WIN_ReleasePtr( win );
 
@@ -271,7 +296,8 @@ void alloc_window_dce( struct x11drv_win
             if (dce->class_ptr == class_ptr)
             {
                 dce->count++;
-                data->dce = dce;
+                hwnd_to_dce->dce = dce;
+                list_add_head( &hwnd_to_dce_list, &hwnd_to_dce->entry );
                 LeaveCriticalSection( &dce_section );
                 return;
             }
@@ -292,7 +318,7 @@ void alloc_window_dce( struct x11drv_win
 
     SetDCHook( dce->hdc, dc_hook, (DWORD)dce );
 
-    dce->hwnd      = data->hwnd;
+    dce->hwnd      = hwnd;
     dce->clip_rgn  = 0;
     dce->flags     = 0;
     dce->class_ptr = class_ptr;
@@ -300,16 +326,18 @@ void alloc_window_dce( struct x11drv_win
 
     if (style & CS_OWNDC)
     {
-        LONG win_style = GetWindowLongW( data->hwnd, GWL_STYLE );
+        LONG win_style = GetWindowLongW( hwnd, GWL_STYLE );
         if (win_style & WS_CLIPCHILDREN) dce->flags |= DCX_CLIPCHILDREN;
         if (win_style & WS_CLIPSIBLINGS) dce->flags |= DCX_CLIPSIBLINGS;
     }
     SetHookFlags16( HDC_16(dce->hdc), DCHF_INVALIDATEVISRGN );
 
+    hwnd_to_dce->dce = dce;
+
     EnterCriticalSection( &dce_section );
     list_add_tail( &dce_list, &dce->entry );
+    list_add_head( &hwnd_to_dce_list, &hwnd_to_dce->entry );
     LeaveCriticalSection( &dce_section );
-    data->dce = dce;
 
     escape.code = X11DRV_SET_DCE;
     escape.dce  = dce;
@@ -322,12 +350,14 @@ void alloc_window_dce( struct x11drv_win
  *
  * Free a class or window DCE.
  */
-void free_window_dce( struct x11drv_win_data *data )
+void free_window_dce( HWND hwnd )
 {
-    struct dce *dce = data->dce;
+    struct hwnd_to_dce *hwnd_to_dce = get_hwnd_to_dce(hwnd);
+    struct dce *dce;
 
-    if (dce)
+    if (hwnd_to_dce)
     {
+        dce = hwnd_to_dce->dce;
         EnterCriticalSection( &dce_section );
         if (!--dce->count)
         {
@@ -337,12 +367,12 @@ void free_window_dce( struct x11drv_win_
             if (dce->clip_rgn) DeleteObject( dce->clip_rgn );
             HeapFree( GetProcessHeap(), 0, dce );
         }
-        else if (dce->hwnd == data->hwnd)
+        else if (dce->hwnd == hwnd)
         {
             release_dce( dce );
         }
         LeaveCriticalSection( &dce_section );
-        data->dce = NULL;
+        list_remove( &hwnd_to_dce->entry );
     }
 
     /* now check for cache DCEs */
@@ -350,10 +380,10 @@ void free_window_dce( struct x11drv_win_
     EnterCriticalSection( &dce_section );
     LIST_FOR_EACH_ENTRY( dce, &dce_list, struct dce, entry )
     {
-        if (dce->hwnd != data->hwnd) continue;
+        if (dce->hwnd != hwnd) continue;
         if (!(dce->flags & DCX_CACHE)) continue;
 
-        if (dce->count) WARN( "GetDC() without ReleaseDC() for window %p\n", data->hwnd );
+        if (dce->count) WARN( "GetDC() without ReleaseDC() for window %p\n", hwnd );
         release_dce( dce );
         dce->count = 0;
     }
@@ -431,7 +461,7 @@ HDC X11DRV_GetDCEx( HWND hwnd, HRGN hrgn
 {
     static const DWORD clip_flags = DCX_PARENTCLIP | DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW;
 
-    struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
+    struct hwnd_to_dce *hwnd_to_dce = get_hwnd_to_dce( hwnd );
     struct dce *dce;
     BOOL bUpdateVisRgn = TRUE;
     HWND parent;
@@ -455,7 +485,7 @@ HDC X11DRV_GetDCEx( HWND hwnd, HRGN hrgn
 
             if (window_style & WS_CLIPCHILDREN && !(window_style & WS_MINIMIZE))
                 flags |= DCX_CLIPCHILDREN;
-            if (!data || !data->dce) flags |= DCX_CACHE;
+            if (!hwnd_to_dce) flags |= DCX_CACHE;
         }
     }
 
@@ -520,7 +550,7 @@ HDC X11DRV_GetDCEx( HWND hwnd, HRGN hrgn
     else
     {
         flags |= DCX_NORESETATTRS;
-        dce = data->dce;
+        dce = hwnd_to_dce->dce;
         if (dce->hwnd == hwnd)
         {
             TRACE("\tskipping hVisRgn update\n");
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c
index cf23866..913882a 100644
--- a/dlls/winex11.drv/init.c
+++ b/dlls/winex11.drv/init.c
@@ -329,6 +329,26 @@ INT X11DRV_ExtEscape( X11DRV_PDEVICE *ph
                     return TRUE;
                 }
                 break;
+            case X11DRV_SET_HWND:
+                if (in_count >= sizeof(struct x11drv_escape_set_hwnd))
+                {
+                    const struct x11drv_escape_set_hwnd *data = (const struct x11drv_escape_set_hwnd *)in_data;
+                    struct x11drv_win_data *win_data;
+                    struct x11drv_escape_set_drawable escape;
+
+                    escape.dc_rect = data->dc_rect;
+                    escape.drawable_rect = data->hwnd_rect;
+                    escape.mode = IncludeInferiors;
+                    escape.code = X11DRV_SET_DRAWABLE;
+
+                    if (data->allow_iconic && ((win_data = X11DRV_get_win_data( data->hwnd )) != NULL) &&
+                        win_data->icon_window)
+                        escape.drawable = win_data->icon_window;
+                    else
+                        escape.drawable = X11DRV_get_whole_window( data->hwnd );
+                    return X11DRV_ExtEscape( physDev, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL );
+                }
+                break;
             case X11DRV_SET_DRAWABLE:
                 if (in_count >= sizeof(struct x11drv_escape_set_drawable))
                 {
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index b8ebe2f..11248ce 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -902,7 +902,7 @@ void X11DRV_DestroyWindow( HWND hwnd )
 
     if (!(data = X11DRV_get_win_data( hwnd ))) return;
 
-    free_window_dce( data );
+    free_window_dce( hwnd );
     destroy_whole_window( display, data );
     destroy_icon_window( display, data );
 
@@ -927,7 +927,6 @@ static struct x11drv_win_data *alloc_win
         data->icon_window   = 0;
         data->xic           = 0;
         data->managed       = FALSE;
-        data->dce           = NULL;
         data->lock_changes  = 0;
         data->hWMIconBitmap = 0;
         data->hWMIconMask   = 0;
@@ -1026,7 +1025,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CRE
     }
 
     /* get class or window DC if needed */
-    alloc_window_dce( data );
+    alloc_window_dce( hwnd );
 
     /* Make sure we've updated the window title if SetWindowText was called
        before alloc_win_data */
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 63137bd..d540993 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -467,6 +467,7 @@ enum x11drv_escape_codes
     X11DRV_GET_DRAWABLE,     /* get current drawable for a DC */
     X11DRV_GET_FONT,         /* get current X font for a DC */
     X11DRV_SET_DRAWABLE,     /* set current drawable for a DC */
+    X11DRV_SET_HWND,         /* set current hwnd for a DC */
     X11DRV_START_EXPOSURES,  /* start graphics exposures */
     X11DRV_END_EXPOSURES,    /* end graphics exposures */
     X11DRV_GET_DCE,          /* get the DCE pointer */
@@ -475,6 +476,15 @@ enum x11drv_escape_codes
     X11DRV_SYNC_PIXMAP       /* sync the dibsection to its pixmap */
 };
 
+struct x11drv_escape_set_hwnd
+{
+    enum x11drv_escape_codes code;         /* escape code (X11DRV_SET_HWND) */
+    HWND                     hwnd;         /* hwnd */
+    BOOL                     allow_iconic; /* allow to draw in iconic window */
+    RECT                     dc_rect;      /* DC rectangle relative to drawable */
+    RECT                     hwnd_rect;    /* HWND rectangle relative to screen */
+};
+
 struct x11drv_escape_set_drawable
 {
     enum x11drv_escape_codes code;         /* escape code (X11DRV_SET_DRAWABLE) */
@@ -643,7 +653,6 @@ struct x11drv_win_data
     RECT        client_rect;    /* client area relative to whole window */
     XIC         xic;            /* X input context */
     BOOL        managed;        /* is window managed? */
-    struct dce *dce;            /* DCE for CS_OWNDC or CS_CLASSDC windows */
     unsigned int lock_changes;  /* lock count for X11 change requests */
     HBITMAP     hWMIconBitmap;
     HBITMAP     hWMIconMask;
@@ -654,8 +663,8 @@ extern Window X11DRV_get_whole_window( H
 extern BOOL X11DRV_is_window_rect_mapped( const RECT *rect );
 extern XIC X11DRV_get_ic( HWND hwnd );
 
-extern void alloc_window_dce( struct x11drv_win_data *data );
-extern void free_window_dce( struct x11drv_win_data *data );
+extern void alloc_window_dce( HWND hwnd );
+extern void free_window_dce( HWND hwnd );
 extern void invalidate_dce( HWND hwnd, const RECT *rect );
 
 /* X context to associate a hwnd to an X window */


More information about the wine-patches mailing list