[PATCH 1/5] wined3d: Create a proper texture for the software cursor.

Henri Verbeet hverbeet at codeweavers.com
Mon Nov 18 03:46:16 CST 2013


---
 dlls/wined3d/device.c          |  136 +++++++++++++++++++++-------------------
 dlls/wined3d/swapchain.c       |   60 ++++++------------
 dlls/wined3d/wined3d_private.h |    2 +-
 3 files changed, 93 insertions(+), 105 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 2d65684..8652f45 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1027,6 +1027,8 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
 
     if (device->logo_texture)
         wined3d_texture_decref(device->logo_texture);
+    if (device->cursor_texture)
+        wined3d_texture_decref(device->cursor_texture);
 
     state_unbind_resources(&device->state);
 
@@ -1038,13 +1040,6 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
         resource->resource_ops->resource_unload(resource);
     }
 
-    /* Delete the mouse cursor texture */
-    if (device->cursorTexture)
-    {
-        gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->cursorTexture);
-        device->cursorTexture = 0;
-    }
-
     /* Destroy the depth blt resources, they will be invalid after the reset. Also free shader
      * private data, it might contain opengl pointers
      */
@@ -3790,19 +3785,75 @@ void CDECL wined3d_device_set_depth_stencil(struct wined3d_device *device, struc
         wined3d_surface_decref(prev);
 }
 
+struct wined3d_texture *wined3d_device_create_cursor_texture(struct wined3d_device *device,
+        struct wined3d_surface *cursor_image)
+{
+    struct wined3d_resource_desc desc;
+    struct wined3d_map_desc map_desc;
+    struct wined3d_texture *texture;
+    struct wined3d_surface *surface;
+    BYTE *src_data, *dst_data;
+    unsigned int src_pitch;
+    unsigned int i;
+
+    if (FAILED(wined3d_surface_map(cursor_image, &map_desc, NULL, WINED3D_MAP_READONLY)))
+    {
+        ERR("Failed to map source surface.\n");
+        return NULL;
+    }
+
+    src_pitch = map_desc.row_pitch;
+    src_data = map_desc.data;
+
+    desc.resource_type = WINED3D_RTYPE_TEXTURE;
+    desc.format = WINED3DFMT_B8G8R8A8_UNORM;
+    desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
+    desc.multisample_quality = 0;
+    desc.usage = 0;
+    desc.pool = WINED3D_POOL_SYSTEM_MEM;
+    desc.width = cursor_image->resource.width;
+    desc.height = cursor_image->resource.height;
+    desc.depth = 1;
+    desc.size = 0;
+
+    if (FAILED(wined3d_texture_create_2d(device, &desc, 1, WINED3D_SURFACE_MAPPABLE,
+            NULL, &wined3d_null_parent_ops, &texture)))
+    {
+        ERR("Failed to create cursor texture.\n");
+        wined3d_surface_unmap(cursor_image);
+        return NULL;
+    }
+
+    surface = surface_from_resource(wined3d_texture_get_sub_resource(texture, 0));
+    if (FAILED(wined3d_surface_map(surface, &map_desc, NULL, 0)))
+    {
+        ERR("Failed to map destination surface.\n");
+        wined3d_texture_decref(texture);
+        wined3d_surface_unmap(cursor_image);
+        return NULL;
+    }
+
+    dst_data = map_desc.data;
+
+    for (i = 0; i < desc.height; ++i)
+        memcpy(&dst_data[map_desc.row_pitch * i], &src_data[src_pitch * i], desc.width * 4);
+
+    wined3d_surface_unmap(surface);
+    wined3d_surface_unmap(cursor_image);
+
+    return texture;
+}
+
 HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device,
         UINT x_hotspot, UINT y_hotspot, struct wined3d_surface *cursor_image)
 {
     TRACE("device %p, x_hotspot %u, y_hotspot %u, cursor_image %p.\n",
             device, x_hotspot, y_hotspot, cursor_image);
 
-    /* some basic validation checks */
-    if (device->cursorTexture)
+    if (device->cursor_texture)
     {
-        struct wined3d_context *context = context_acquire(device, NULL);
-        context->gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->cursorTexture);
-        context_release(context);
-        device->cursorTexture = 0;
+        wined3d_texture_decref(device->cursor_texture);
+        device->cursor_texture = NULL;
     }
 
     if (cursor_image)
@@ -3838,51 +3889,16 @@ HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device
         /* Do not store the surface's pointer because the application may
          * release it after setting the cursor image. Windows doesn't
          * addref the set surface, so we can't do this either without
-         * creating circular refcount dependencies. Copy out the gl texture
-         * instead. */
-        device->cursorWidth = cursor_image->resource.width;
-        device->cursorHeight = cursor_image->resource.height;
-        if (SUCCEEDED(wined3d_surface_map(cursor_image, &map_desc, NULL, WINED3D_MAP_READONLY)))
-        {
-            const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-            const struct wined3d_format *format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM);
-            struct wined3d_context *context;
-            char *mem, *bits = map_desc.data;
-            GLint intfmt = format->glInternal;
-            GLint gl_format = format->glFormat;
-            GLint type = format->glType;
-            INT height = device->cursorHeight;
-            INT width = device->cursorWidth;
-            INT bpp = format->byte_count;
-            INT i;
-
-            /* Reformat the texture memory (pitch and width can be
-             * different) */
-            mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
-            for (i = 0; i < height; ++i)
-                memcpy(&mem[width * bpp * i], &bits[map_desc.row_pitch * i], width * bpp);
-            wined3d_surface_unmap(cursor_image);
-
-            context = context_acquire(device, NULL);
-
-            context_invalidate_active_texture(context);
-            /* Create a new cursor texture */
-            gl_info->gl_ops.gl.p_glGenTextures(1, &device->cursorTexture);
-            checkGLcall("glGenTextures");
-            context_bind_texture(context, GL_TEXTURE_2D, device->cursorTexture);
-            /* Copy the bitmap memory into the cursor texture */
-            gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, gl_format, type, mem);
-            checkGLcall("glTexImage2D");
-            HeapFree(GetProcessHeap(), 0, mem);
-
-            context_release(context);
-        }
-        else
+         * creating circular refcount dependencies. */
+        if (!(device->cursor_texture = wined3d_device_create_cursor_texture(device, cursor_image)))
         {
-            FIXME("A cursor texture was not returned.\n");
-            device->cursorTexture = 0;
+            ERR("Failed to create cursor texture.\n");
+            return WINED3DERR_INVALIDCALL;
         }
 
+        device->cursorWidth = cursor_image->resource.width;
+        device->cursorHeight = cursor_image->resource.height;
+
         if (cursor_image->resource.width == 32 && cursor_image->resource.height == 32)
         {
             UINT mask_size = cursor_image->resource.width * cursor_image->resource.height / 8;
@@ -3978,10 +3994,9 @@ BOOL CDECL wined3d_device_show_cursor(struct wined3d_device *device, BOOL show)
         else
             SetCursor(NULL);
     }
-    else
+    else if (device->cursor_texture)
     {
-        if (device->cursorTexture)
-            device->bCursorVisible = show;
+        device->bCursorVisible = show;
     }
 
     return oldVisible;
@@ -4035,11 +4050,6 @@ static void delete_opengl_contexts(struct wined3d_device *device, struct wined3d
         gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->depth_blt_texture);
         device->depth_blt_texture = 0;
     }
-    if (device->cursorTexture)
-    {
-        gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->cursorTexture);
-        device->cursorTexture = 0;
-    }
 
     device->blitter->free_private(device);
     device->shader_backend->shader_free_private(device);
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 1b45cd0..23c1c4d 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -425,12 +425,22 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT
 
     gl_info = context->gl_info;
 
-    /* Render the cursor onto the back buffer, using our nifty directdraw blitting code :-) */
-    if (swapchain->device->bCursorVisible &&
-        swapchain->device->cursorTexture &&
-        !swapchain->device->hardwareCursor)
+    if (swapchain->device->logo_texture)
     {
-        struct wined3d_surface cursor;
+        struct wined3d_surface *src_surface = surface_from_resource(
+                wined3d_texture_get_sub_resource(swapchain->device->logo_texture, 0));
+        RECT rect = {0, 0, src_surface->resource.width, src_surface->resource.height};
+
+        /* Blit the logo into the upper left corner of the drawable. */
+        wined3d_surface_blt(back_buffer, &rect, src_surface, &rect, WINEDDBLT_KEYSRC,
+                NULL, WINED3D_TEXF_POINT);
+    }
+
+    if (swapchain->device->bCursorVisible && swapchain->device->cursor_texture
+            && !swapchain->device->hardwareCursor)
+    {
+        struct wined3d_surface *cursor = surface_from_resource(
+                wined3d_texture_get_sub_resource(swapchain->device->cursor_texture, 0));
         RECT destRect =
         {
             swapchain->device->xScreenSpace - swapchain->device->xHotSpot,
@@ -438,44 +448,12 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT
             swapchain->device->xScreenSpace + swapchain->device->cursorWidth - swapchain->device->xHotSpot,
             swapchain->device->yScreenSpace + swapchain->device->cursorHeight - swapchain->device->yHotSpot,
         };
-        TRACE("Rendering the cursor. Creating fake surface at %p\n", &cursor);
-        /* Build a fake surface to call the Blitting code. It is not possible to use the interface passed by
-         * the application because we are only supposed to copy the information out. Using a fake surface
-         * allows us to use the Blitting engine and avoid copying the whole texture -> render target blitting code.
-         */
-        memset(&cursor, 0, sizeof(cursor));
-        cursor.resource.ref = 1;
-        cursor.resource.device = swapchain->device;
-        cursor.resource.pool = WINED3D_POOL_SCRATCH;
-        cursor.resource.format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM);
-        cursor.resource.type = WINED3D_RTYPE_SURFACE;
-        cursor.texture_name = swapchain->device->cursorTexture;
-        cursor.texture_target = GL_TEXTURE_2D;
-        cursor.texture_level = 0;
-        cursor.resource.width = swapchain->device->cursorWidth;
-        cursor.resource.height = swapchain->device->cursorHeight;
-        /* The cursor must have pow2 sizes */
-        cursor.pow2Width = cursor.resource.width;
-        cursor.pow2Height = cursor.resource.height;
-        /* The surface is in the texture */
-        cursor.flags |= SFLAG_INTEXTURE;
-        /* DDBLT_KEYSRC will cause BltOverride to enable the alpha test with GL_NOTEQUAL, 0.0,
-         * which is exactly what we want :-)
-         */
-        if (swapchain->desc.windowed)
-            MapWindowPoints(NULL, swapchain->win_handle, (POINT *)&destRect, 2);
-        wined3d_surface_blt(back_buffer, &destRect, &cursor, NULL, WINEDDBLT_KEYSRC,
-                NULL, WINED3D_TEXF_POINT);
-    }
 
-    if (swapchain->device->logo_texture)
-    {
-        struct wined3d_surface *src_surface = surface_from_resource(
-                wined3d_texture_get_sub_resource(swapchain->device->logo_texture, 0));
-        RECT rect = {0, 0, src_surface->resource.width, src_surface->resource.height};
+        TRACE("Rendering the software cursor.\n");
 
-        /* Blit the logo into the upper left corner of the drawable. */
-        wined3d_surface_blt(back_buffer, &rect, src_surface, &rect, WINEDDBLT_KEYSRC,
+        if (swapchain->desc.windowed)
+            MapWindowPoints(NULL, swapchain->win_handle, (POINT *)&destRect, 2);
+        wined3d_surface_blt(back_buffer, &destRect, cursor, NULL, WINEDDBLT_KEYSRC,
                 NULL, WINED3D_TEXF_POINT);
     }
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 3c39ee1..8e922fc 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1921,7 +1921,7 @@ struct wined3d_device
     UINT                    xScreenSpace;
     UINT                    yScreenSpace;
     UINT                    cursorWidth, cursorHeight;
-    GLuint                  cursorTexture;
+    struct wined3d_texture *cursor_texture;
     HCURSOR                 hardwareCursor;
 
     /* The Wine logo texture */
-- 
1.7.10.4




More information about the wine-patches mailing list