From: Zhiyi Zhang zzhang@codeweavers.com
Create a bitmap of the virtual screen size for all display device contexts. Previously, the concern was that allocating a full size bitmap may use too much memory. But now that there is a real world application that needs this, it is now necessary. Fortunately, tests show that all display device contexts use the same bitmap.
Fix a regression from 19229020.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56825 --- dlls/user32/tests/monitor.c | 5 ----- dlls/win32u/dc.c | 11 ++--------- dlls/win32u/gdiobj.c | 5 ++++- dlls/win32u/sysparams.c | 21 +++++++++++++++++++++ dlls/win32u/win32u_private.h | 1 + 5 files changed, 28 insertions(+), 15 deletions(-)
diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c index f2eb70e3eb3..2575d278392 100644 --- a/dlls/user32/tests/monitor.c +++ b/dlls/user32/tests/monitor.c @@ -2509,10 +2509,8 @@ static void _check_display_dc(INT line, HDC hdc, const DEVMODEA *dm, BOOL allow_ if (ret) { ok_(__FILE__, line)(bitmap.bmType == 0, "Expected bmType %d, got %d.\n", 0, bitmap.bmType); - todo_wine ok_(__FILE__, line)(bitmap.bmWidth == GetSystemMetrics(SM_CXVIRTUALSCREEN), "Expected bmWidth %d, got %d.\n", GetSystemMetrics(SM_CXVIRTUALSCREEN), bitmap.bmWidth); - todo_wine ok_(__FILE__, line)(bitmap.bmHeight == GetSystemMetrics(SM_CYVIRTUALSCREEN), "Expected bmHeight %d, got %d.\n", GetSystemMetrics(SM_CYVIRTUALSCREEN), bitmap.bmHeight); ok_(__FILE__, line)(bitmap.bmBitsPixel == 32, "Expected bmBitsPixel %d, got %d.\n", 32, @@ -2690,7 +2688,6 @@ static void test_display_dc(void) hdc2 = CreateDCA("DISPLAY", NULL, NULL, NULL); ok(!!hdc2, "CreateDCA failed.\n"); hbitmap2 = GetCurrentObject(hdc2, OBJ_BITMAP); - todo_wine ok(hbitmap2 == old_hbitmap, "Expected the same bitmap handle.\n");
/* Tests after mode changes to a mode with different resolution */ @@ -2713,7 +2710,6 @@ static void test_display_dc(void)
/* Test that a different bitmap handle is used for the display DC after resolution changes */ hbitmap2 = GetCurrentObject(hdc, OBJ_BITMAP); - todo_wine ok(hbitmap2 != old_hbitmap, "Expected a different bitmap handle.\n");
/* Test that the old display bitmap is invalid after waiting for a bit. This suggests @@ -2721,7 +2717,6 @@ static void test_display_dc(void) * has the same bitmap handle so the display bitmap is not being reference counted */ Sleep(500); count = GetObjectW(old_hbitmap, sizeof(bitmap), &bitmap); - todo_wine ok(!count, "GetObject failed, count %d.\n", count); } } diff --git a/dlls/win32u/dc.c b/dlls/win32u/dc.c index 24a3bca5544..3f6a501041a 100644 --- a/dlls/win32u/dc.c +++ b/dlls/win32u/dc.c @@ -275,13 +275,7 @@ void free_dc_ptr( DC *dc ) GDI_dec_ref_count( dc->hPen ); GDI_dec_ref_count( dc->hBrush ); GDI_dec_ref_count( dc->hFont ); - if (dc->hBitmap) - { - if (dc->is_display) - NtGdiDeleteObjectApp( dc->hBitmap ); - else - GDI_dec_ref_count( dc->hBitmap ); - } + if (dc->hBitmap && !dc->is_display) GDI_dec_ref_count( dc->hBitmap ); free_gdi_handle( dc->hSelf ); free_dc_state( dc ); } @@ -729,9 +723,8 @@ HDC WINAPI NtGdiOpenDCW( UNICODE_STRING *device, const DEVMODEW *devmode, UNICOD
if (!(dc = alloc_dc_ptr( NTGDI_OBJ_DC ))) return 0; hdc = dc->hSelf; - if (is_display) - dc->hBitmap = NtGdiCreateCompatibleBitmap( hdc, 1, 1 ); + dc->hBitmap = get_display_bitmap(); else dc->hBitmap = GDI_inc_ref_count( GetStockObject( DEFAULT_BITMAP ));
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index 5cf99e39ff0..fec99243aa2 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -969,7 +969,10 @@ HANDLE WINAPI NtGdiGetDCObject( HDC hdc, UINT type ) case NTGDI_OBJ_BRUSH: ret = dc->hBrush; break; case NTGDI_OBJ_PAL: ret = dc->hPalette; break; case NTGDI_OBJ_FONT: ret = dc->hFont; break; - case NTGDI_OBJ_SURF: ret = dc->hBitmap; break; + case NTGDI_OBJ_SURF: + /* Update bitmap for display device contexts */ + if (dc->is_display) dc->hBitmap = get_display_bitmap(); + ret = dc->hBitmap; break; default: FIXME( "(%p, %d): unknown type.\n", hdc, type ); break; diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index afa75928c94..094a963d305 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2100,6 +2100,27 @@ static HDC get_display_dc(void) return display_dc; }
+HBITMAP get_display_bitmap(void) +{ + static RECT old_virtual_rect; + static HBITMAP hbitmap; + RECT virtual_rect; + HBITMAP ret; + + virtual_rect = get_virtual_screen_rect( 0 ); + pthread_mutex_lock( &display_dc_lock ); + if (!EqualRect( &old_virtual_rect, &virtual_rect )) + { + if (hbitmap) NtGdiDeleteObjectApp( hbitmap ); + hbitmap = NtGdiCreateBitmap( virtual_rect.right - virtual_rect.left, + virtual_rect.bottom - virtual_rect.top, 1, 32, NULL ); + old_virtual_rect = virtual_rect; + } + ret = hbitmap; + pthread_mutex_unlock( &display_dc_lock ); + return ret; +} + static void release_display_dc( HDC hdc ) { pthread_mutex_unlock( &display_dc_lock ); diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 73933acc14a..c4521899299 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -161,6 +161,7 @@ extern BOOL enable_thunk_lock; extern HBRUSH get_55aa_brush(void); extern DWORD get_dialog_base_units(void); extern LONG get_char_dimensions( HDC hdc, TEXTMETRICW *metric, int *height ); +extern HBITMAP get_display_bitmap(void); extern INT get_display_depth( UNICODE_STRING *name ); extern RECT get_display_rect( const WCHAR *display ); extern UINT get_monitor_dpi( HMONITOR monitor );