Henri Verbeet : wined3d: Introduce a backup path for swapchain presents using GDI.

Alexandre Julliard julliard at winehq.org
Mon Jun 7 15:02:06 CDT 2021


Module: wine
Branch: stable
Commit: e6fab0bcba6f233d722500e25c32876dd0c22cc5
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=e6fab0bcba6f233d722500e25c32876dd0c22cc5

Author: Henri Verbeet <hverbeet at codeweavers.com>
Date:   Fri Feb 19 21:31:11 2021 +0100

wined3d: Introduce a backup path for swapchain presents using GDI.

Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
(cherry picked from commit 70418f69dd49da5625bb1893d9fc2bef3fe97b5e)
Signed-off-by: Michael Stefaniuc <mstefani at winehq.org>

---

 dlls/wined3d/swapchain.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 1671abb698d..180f724b5cb 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -400,6 +400,73 @@ HRESULT CDECL wined3d_swapchain_get_gamma_ramp(const struct wined3d_swapchain *s
     return WINED3D_OK;
 }
 
+/* The is a fallback for cases where we e.g. can't create a GL context or
+ * Vulkan swapchain for the swapchain window. */
+static void swapchain_blit_gdi(struct wined3d_swapchain *swapchain,
+        struct wined3d_context *context, const RECT *src_rect, const RECT *dst_rect)
+{
+    struct wined3d_texture *back_buffer = swapchain->back_buffers[0];
+    D3DKMT_DESTROYDCFROMMEMORY destroy_desc;
+    D3DKMT_CREATEDCFROMMEMORY create_desc;
+    const struct wined3d_format *format;
+    unsigned int row_pitch, slice_pitch;
+    HDC src_dc, dst_dc;
+    NTSTATUS status;
+    HBITMAP bitmap;
+
+    static unsigned int once;
+
+    TRACE("swapchain %p, context %p, src_rect %s, dst_rect %s.\n",
+            swapchain, context, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect));
+
+    if (!once++)
+        FIXME("Using GDI present.\n");
+
+    format = back_buffer->resource.format;
+    if (!format->ddi_format)
+    {
+        WARN("Cannot create a DC for format %s.\n", debug_d3dformat(format->id));
+        return;
+    }
+
+    wined3d_texture_load_location(back_buffer, 0, context, WINED3D_LOCATION_SYSMEM);
+    wined3d_texture_get_pitch(back_buffer, 0, &row_pitch, &slice_pitch);
+
+    create_desc.pMemory = back_buffer->resource.heap_memory;
+    create_desc.Format = format->ddi_format;
+    create_desc.Width = wined3d_texture_get_level_width(back_buffer, 0);
+    create_desc.Height = wined3d_texture_get_level_height(back_buffer, 0);
+    create_desc.Pitch = row_pitch;
+    create_desc.hDeviceDc = CreateCompatibleDC(NULL);
+    create_desc.pColorTable = NULL;
+
+    status = D3DKMTCreateDCFromMemory(&create_desc);
+    DeleteDC(create_desc.hDeviceDc);
+    if (status)
+    {
+        WARN("Failed to create DC, status %#x.\n", status);
+        return;
+    }
+
+    src_dc = create_desc.hDc;
+    bitmap = create_desc.hBitmap;
+
+    TRACE("Created source DC %p, bitmap %p for backbuffer %p.\n", src_dc, bitmap, back_buffer);
+
+    if (!(dst_dc = GetDCEx(swapchain->win_handle, 0, DCX_USESTYLE | DCX_CACHE)))
+        ERR("Failed to get destination DC.\n");
+
+    if (!BitBlt(dst_dc, dst_rect->left, dst_rect->top, dst_rect->right - dst_rect->left,
+            dst_rect->bottom - dst_rect->top, src_dc, src_rect->left, src_rect->top, SRCCOPY))
+        ERR("Failed to blit.\n");
+
+    ReleaseDC(swapchain->win_handle, dst_dc);
+    destroy_desc.hDc = src_dc;
+    destroy_desc.hBitmap = bitmap;
+    if ((status = D3DKMTDestroyDCFromMemory(&destroy_desc)))
+        ERR("Failed to destroy src dc, status %#x.\n", status);
+}
+
 /* A GL context is provided by the caller */
 static void swapchain_blit(const struct wined3d_swapchain *swapchain,
         struct wined3d_context *context, const RECT *src_rect, const RECT *dst_rect)
@@ -523,6 +590,9 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain,
 
     TRACE("Presenting DC %p.\n", context_gl->dc);
 
+    if (context_gl->dc == swapchain_gl->backup_dc)
+        swapchain_blit_gdi(swapchain, context, src_rect, dst_rect);
+
     if (!(render_to_fbo = swapchain->render_to_fbo)
             && (src_rect->left || src_rect->top
             || src_rect->right != desc->backbuffer_width
@@ -1152,6 +1222,8 @@ static void swapchain_vk_present(struct wined3d_swapchain *swapchain, const RECT
 
     if (swapchain_vk->vk_swapchain)
         wined3d_swapchain_vk_blit(swapchain_vk, context_vk, src_rect, dst_rect, swap_interval);
+    else
+        swapchain_blit_gdi(swapchain, &context_vk->c, src_rect, dst_rect);
 
     wined3d_swapchain_vk_rotate(swapchain, context_vk);
 




More information about the wine-cvs mailing list