[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