Alexandre Julliard : gdi32: Only create the DC visible region when necessary.

Alexandre Julliard julliard at winehq.org
Wed Dec 7 13:57:12 CST 2011


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Dec  7 16:50:57 2011 +0100

gdi32: Only create the DC visible region when necessary.

Most DCs can simply use the visible rectangle instead.

---

 dlls/gdi32/bitmap.c   |    1 -
 dlls/gdi32/clipping.c |   58 +++++++++++++++++++++++++++++++++---------------
 dlls/gdi32/dc.c       |   25 ++++++--------------
 3 files changed, 48 insertions(+), 36 deletions(-)

diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c
index 45c3011..4f0b173 100644
--- a/dlls/gdi32/bitmap.c
+++ b/dlls/gdi32/bitmap.c
@@ -639,7 +639,6 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
         dc->vis_rect.top    = 0;
         dc->vis_rect.right  = bitmap->bitmap.bmWidth;
         dc->vis_rect.bottom = bitmap->bitmap.bmHeight;
-        SetRectRgn( dc->hVisRgn, 0, 0, bitmap->bitmap.bmWidth, bitmap->bitmap.bmHeight);
         GDI_ReleaseObj( handle );
         DC_InitDC( dc );
         GDI_dec_ref_count( ret );
diff --git a/dlls/gdi32/clipping.c b/dlls/gdi32/clipping.c
index 7f69950..41590bd 100644
--- a/dlls/gdi32/clipping.c
+++ b/dlls/gdi32/clipping.c
@@ -29,6 +29,16 @@
 WINE_DEFAULT_DEBUG_CHANNEL(clipping);
 
 
+/* return the DC visible rectangle if not empty */
+static inline BOOL get_dc_visrect( DC *dc, RECT *rect )
+{
+    rect->left = 0;
+    rect->top = 0;
+    rect->right = dc->vis_rect.right - dc->vis_rect.left;
+    rect->bottom = dc->vis_rect.bottom - dc->vis_rect.top;
+    return !is_rect_empty( rect );
+}
+
 /***********************************************************************
  *           get_clip_rect
  *
@@ -77,6 +87,7 @@ BOOL clip_visrect( DC *dc, RECT *dst, const RECT *src )
 void CLIPPING_UpdateGCRegion( DC * dc )
 {
     HRGN clip_rgn;
+    RECT visrect;
     PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDeviceClipping );
 
     /* update the intersection of meta and clip regions */
@@ -91,11 +102,17 @@ void CLIPPING_UpdateGCRegion( DC * dc )
         dc->hMetaClipRgn = 0;
     }
     clip_rgn = get_clip_region( dc );
-    if (clip_rgn || dc->hVisRgn)
+    if (dc->hVisRgn)
     {
         if (!dc->region) dc->region = CreateRectRgn( 0, 0, 0, 0 );
         CombineRgn( dc->region, dc->hVisRgn, clip_rgn, clip_rgn ? RGN_AND : RGN_COPY );
     }
+    else if (get_dc_visrect( dc, &visrect ))
+    {
+        if (!dc->region) dc->region = CreateRectRgn( 0, 0, 0, 0 );
+        SetRectRgn( dc->region, visrect.left, visrect.top, visrect.right, visrect.bottom );
+        if (clip_rgn) CombineRgn( dc->region, dc->region, clip_rgn, RGN_AND );
+    }
     else
     {
         if (dc->region) DeleteObject( dc->region );
@@ -272,7 +289,7 @@ void CDECL __wine_set_visible_region( HDC hdc, HRGN hrgn, const RECT *vis_rect )
     /* map region to DC coordinates */
     OffsetRgn( hrgn, -vis_rect->left, -vis_rect->top );
 
-    DeleteObject( dc->hVisRgn );
+    if (dc->hVisRgn) DeleteObject( dc->hVisRgn );
     dc->dirty = 0;
     dc->vis_rect = *vis_rect;
     dc->hVisRgn = hrgn;
@@ -476,7 +493,8 @@ INT WINAPI GetMetaRgn( HDC hdc, HRGN hRgn )
  */
 INT WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, INT iCode)
 {
-    HRGN rgn;
+    INT ret = 1;
+    RECT visrect;
     DC *dc = get_dc_ptr( hDC );
 
     if (!dc) return -1;
@@ -484,33 +502,37 @@ INT WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, INT iCode)
     switch (iCode)
     {
     case 1:
-        rgn = dc->hClipRgn;
+        if (dc->hClipRgn) CombineRgn( hRgn, dc->hClipRgn, 0, RGN_COPY );
+        else ret = 0;
         break;
     case 2:
-        rgn = dc->hMetaRgn;
+        if (dc->hMetaRgn) CombineRgn( hRgn, dc->hMetaRgn, 0, RGN_COPY );
+        else ret = 0;
         break;
     case 3:
-        rgn = dc->hMetaClipRgn;
-        if(!rgn) rgn = dc->hClipRgn;
-        if(!rgn) rgn = dc->hMetaRgn;
+        if (dc->hMetaClipRgn) CombineRgn( hRgn, dc->hMetaClipRgn, 0, RGN_COPY );
+        else if (dc->hClipRgn) CombineRgn( hRgn, dc->hClipRgn, 0, RGN_COPY );
+        else if (dc->hMetaRgn) CombineRgn( hRgn, dc->hMetaRgn, 0, RGN_COPY );
+        else ret = 0;
         break;
     case SYSRGN: /* == 4 */
         update_dc( dc );
-        rgn = dc->hVisRgn;
+        if (dc->hVisRgn)
+            CombineRgn( hRgn, dc->hVisRgn, 0, RGN_COPY );
+        else if (get_dc_visrect( dc, &visrect ))
+            SetRectRgn( hRgn, visrect.left, visrect.top, visrect.right, visrect.bottom );
+        else
+            ret = 0;
+        /* On Windows NT/2000, the SYSRGN returned is in screen coordinates */
+        if (ret && !(GetVersion() & 0x80000000)) OffsetRgn( hRgn, dc->vis_rect.left, dc->vis_rect.top );
         break;
     default:
         WARN("Unknown code %d\n", iCode);
-        release_dc_ptr( dc );
-        return -1;
+        ret = -1;
+        break;
     }
-    if (rgn) CombineRgn( hRgn, rgn, 0, RGN_COPY );
     release_dc_ptr( dc );
-
-    /* On Windows NT/2000, the SYSRGN returned is in screen coordinates */
-    if (iCode == SYSRGN && !(GetVersion() & 0x80000000))
-        OffsetRgn( hRgn, dc->vis_rect.left, dc->vis_rect.top );
-
-    return (rgn != 0);
+    return ret;
 }
 
 
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c
index 2519a28..4e819d6 100644
--- a/dlls/gdi32/dc.c
+++ b/dlls/gdi32/dc.c
@@ -585,11 +585,10 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
         ERR( "no driver found for %s\n", debugstr_w(buf) );
         return 0;
     }
-    if (!(dc = alloc_dc_ptr( OBJ_DC ))) goto error;
+    if (!(dc = alloc_dc_ptr( OBJ_DC ))) return 0;
     hdc = dc->hSelf;
 
     dc->hBitmap = GDI_inc_ref_count( GetStockObject( DEFAULT_BITMAP ));
-    if (!(dc->hVisRgn = CreateRectRgn( 0, 0, 1, 1 ))) goto error;
 
     TRACE("(driver=%s, device=%s, output=%s): returning %p\n",
           debugstr_w(driver), debugstr_w(device), debugstr_w(output), dc->hSelf );
@@ -599,7 +598,8 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
         if (!funcs->pCreateDC( &dc->physDev, buf, device, output, initData ))
         {
             WARN("creation aborted by device\n" );
-            goto error;
+            free_dc_ptr( dc );
+            return 0;
         }
     }
 
@@ -607,15 +607,10 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
     dc->vis_rect.top    = 0;
     dc->vis_rect.right  = GetDeviceCaps( hdc, DESKTOPHORZRES );
     dc->vis_rect.bottom = GetDeviceCaps( hdc, DESKTOPVERTRES );
-    SetRectRgn(dc->hVisRgn, dc->vis_rect.left, dc->vis_rect.top, dc->vis_rect.right, dc->vis_rect.bottom);
 
     DC_InitDC( dc );
     release_dc_ptr( dc );
     return hdc;
-
-error:
-    if (dc) free_dc_ptr( dc );
-    return 0;
 }
 
 
@@ -698,7 +693,7 @@ HDC WINAPI CreateCompatibleDC( HDC hdc )
         release_dc_ptr( origDC );
     }
 
-    if (!(dc = alloc_dc_ptr( OBJ_MEMDC ))) goto error;
+    if (!(dc = alloc_dc_ptr( OBJ_MEMDC ))) return 0;
 
     TRACE("(%p): returning %p\n", hdc, dc->hSelf );
 
@@ -707,22 +702,18 @@ HDC WINAPI CreateCompatibleDC( HDC hdc )
     dc->vis_rect.top    = 0;
     dc->vis_rect.right  = 1;
     dc->vis_rect.bottom = 1;
-    if (!(dc->hVisRgn = CreateRectRgn( 0, 0, 1, 1 ))) goto error;   /* default bitmap is 1x1 */
 
     ret = dc->hSelf;
 
     if (!funcs->pCreateCompatibleDC( physDev, &dc->physDev ))
     {
         WARN("creation aborted by device\n");
-        goto error;
+        free_dc_ptr( dc );
+        return 0;
     }
     DC_InitDC( dc );
     release_dc_ptr( dc );
     return ret;
-
-error:
-    if (dc) free_dc_ptr( dc );
-    return 0;
 }
 
 
@@ -790,8 +781,8 @@ HDC WINAPI ResetDCW( HDC hdc, const DEVMODEW *devmode )
             dc->vis_rect.top    = 0;
             dc->vis_rect.right  = GetDeviceCaps( hdc, DESKTOPHORZRES );
             dc->vis_rect.bottom = GetDeviceCaps( hdc, DESKTOPVERTRES );
-            SetRectRgn( dc->hVisRgn, dc->vis_rect.left, dc->vis_rect.top,
-                        dc->vis_rect.right, dc->vis_rect.bottom );
+            if (dc->hVisRgn) DeleteObject( dc->hVisRgn );
+            dc->hVisRgn = 0;
             CLIPPING_UpdateGCRegion( dc );
         }
         release_dc_ptr( dc );




More information about the wine-cvs mailing list