[PATCH 2/3] user32: Create window surfaces for nulldrv.

Rémi Bernon rbernon at codeweavers.com
Thu Apr 15 06:46:40 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/user32/driver.c | 130 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 130 insertions(+)

diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c
index 68c10bf4d9a..4deaf73a025 100644
--- a/dlls/user32/driver.c
+++ b/dlls/user32/driver.c
@@ -20,6 +20,8 @@
 
 #include <stdarg.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
 #include <wchar.h>
 
 #include "windef.h"
@@ -188,6 +190,132 @@ void USER_unload_driver(void)
  * These are fallbacks for entry points that are not implemented in the real driver.
  */
 
+struct nulldrv_window_surface
+{
+    struct window_surface base;
+    BITMAPINFOHEADER info;
+    CRITICAL_SECTION cs;
+    RECT bounds;
+    char pixels[1];
+};
+
+static const struct window_surface_funcs nulldrv_window_surface_funcs;
+
+static inline void reset_bounds( RECT *bounds )
+{
+    bounds->left = bounds->top = INT_MAX;
+    bounds->right = bounds->bottom = INT_MIN;
+}
+
+static struct nulldrv_window_surface *impl_from_window_surface( struct window_surface *base )
+{
+    if (base->funcs != &nulldrv_window_surface_funcs) return NULL;
+    return CONTAINING_RECORD( base, struct nulldrv_window_surface, base );
+}
+
+static void CDECL nulldrv_window_surface_lock( struct window_surface *base )
+{
+    struct nulldrv_window_surface *impl = impl_from_window_surface( base );
+    EnterCriticalSection( &impl->cs );
+}
+
+static void CDECL nulldrv_window_surface_unlock( struct window_surface *base )
+{
+    struct nulldrv_window_surface *impl = impl_from_window_surface( base );
+    LeaveCriticalSection( &impl->cs );
+}
+
+static void *CDECL nulldrv_window_surface_get_bitmap_info( struct window_surface *base, BITMAPINFO *info )
+{
+    struct nulldrv_window_surface *impl = impl_from_window_surface( base );
+    info->bmiHeader = impl->info;
+    return impl->pixels;
+}
+
+static RECT *CDECL nulldrv_window_surface_get_bounds( struct window_surface *base )
+{
+    struct nulldrv_window_surface *impl = impl_from_window_surface( base );
+    return &impl->bounds;
+}
+
+static void CDECL nulldrv_window_surface_set_region( struct window_surface *base, HRGN region )
+{
+    TRACE_(nulldrv)( "base %p, region %p\n", base, region );
+}
+
+static void CDECL nulldrv_window_surface_flush( struct window_surface *base )
+{
+    struct nulldrv_window_surface *impl = impl_from_window_surface( base );
+    reset_bounds( &impl->bounds );
+}
+
+static void CDECL nulldrv_window_surface_destroy( struct window_surface *base )
+{
+    struct nulldrv_window_surface *impl = impl_from_window_surface( base );
+    impl->cs.DebugInfo->Spare[0] = 0;
+    DeleteCriticalSection( &impl->cs );
+    free( impl );
+}
+
+static const struct window_surface_funcs nulldrv_window_surface_funcs =
+{
+    nulldrv_window_surface_lock,
+    nulldrv_window_surface_unlock,
+    nulldrv_window_surface_get_bitmap_info,
+    nulldrv_window_surface_get_bounds,
+    nulldrv_window_surface_set_region,
+    nulldrv_window_surface_flush,
+    nulldrv_window_surface_destroy
+};
+
+static void nulldrv_update_window_surface( const RECT *visible_rect, struct window_surface **window_surface )
+{
+    struct nulldrv_window_surface *impl = NULL;
+    struct window_surface *base;
+    SIZE_T size;
+    RECT surface_rect = *visible_rect;
+
+    TRACE_(nulldrv)( "visible_rect %s, window_surface %p.\n", wine_dbgstr_rect( visible_rect ), window_surface );
+
+    OffsetRect( &surface_rect, -surface_rect.left, -surface_rect.top );
+    size = 4 * surface_rect.right * surface_rect.bottom;
+
+    /* check that old surface is a nulldrv_window_surface, or release it */
+    if ((base = *window_surface) && !(impl = impl_from_window_surface( base ))) window_surface_release( base );
+
+    /* if the rect didn't change, keep the same surface */
+    if (impl && EqualRect( &surface_rect, &impl->base.rect )) return;
+
+    /* create a new window surface */
+    *window_surface = NULL;
+    if (impl) window_surface_release( &impl->base );
+    if (!(impl = calloc(1, offsetof( struct nulldrv_window_surface, pixels[size] )))) return;
+
+    impl->base.funcs = &nulldrv_window_surface_funcs;
+    impl->base.ref = 1;
+    impl->base.rect = surface_rect;
+
+    impl->info.biSize          = sizeof( impl->info );
+    impl->info.biWidth         = surface_rect.right;
+    impl->info.biHeight        = surface_rect.bottom;
+    impl->info.biPlanes        = 1;
+    impl->info.biBitCount      = 32;
+    impl->info.biCompression   = BI_RGB;
+    impl->info.biSizeImage     = size;
+    impl->info.biXPelsPerMeter = 0;
+    impl->info.biYPelsPerMeter = 0;
+    impl->info.biClrUsed       = 0;
+    impl->info.biClrImportant  = 0;
+
+    InitializeCriticalSection( &impl->cs );
+    impl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": surface");
+    reset_bounds( &impl->bounds );
+
+    TRACE_(nulldrv)( "created window surface %p\n", &impl->base );
+
+    *window_surface = &impl->base;
+}
+
 static HKL CDECL nulldrv_ActivateKeyboardLayout( HKL layout, UINT flags )
 {
     TRACE_(nulldrv)("layout %p, flags %x.\n", layout, flags);
@@ -511,6 +639,8 @@ static void CDECL nulldrv_WindowPosChanging( HWND hwnd, HWND insert_after, UINT
     TRACE_(nulldrv)("hwnd %p, insert_after %p, swp_flags %x, window_rect %s, client_rect %s, visible_rect %s, surface %p.\n",
                     hwnd, insert_after, swp_flags, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect),
                     wine_dbgstr_rect(visible_rect), surface);
+
+    if (surface && *surface) nulldrv_update_window_surface( visible_rect, surface );
 }
 
 static void CDECL nulldrv_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags,
-- 
2.31.0




More information about the wine-devel mailing list