wined3d: Create a proper texture for the software cursor.
This commit is contained in:
parent
69b8c97c1d
commit
505951e32d
|
@ -1027,6 +1027,8 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
|
||||||
|
|
||||||
if (device->logo_texture)
|
if (device->logo_texture)
|
||||||
wined3d_texture_decref(device->logo_texture);
|
wined3d_texture_decref(device->logo_texture);
|
||||||
|
if (device->cursor_texture)
|
||||||
|
wined3d_texture_decref(device->cursor_texture);
|
||||||
|
|
||||||
state_unbind_resources(&device->state);
|
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);
|
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
|
/* Destroy the depth blt resources, they will be invalid after the reset. Also free shader
|
||||||
* private data, it might contain opengl pointers
|
* 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);
|
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,
|
HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device,
|
||||||
UINT x_hotspot, UINT y_hotspot, struct wined3d_surface *cursor_image)
|
UINT x_hotspot, UINT y_hotspot, struct wined3d_surface *cursor_image)
|
||||||
{
|
{
|
||||||
TRACE("device %p, x_hotspot %u, y_hotspot %u, cursor_image %p.\n",
|
TRACE("device %p, x_hotspot %u, y_hotspot %u, cursor_image %p.\n",
|
||||||
device, x_hotspot, y_hotspot, cursor_image);
|
device, x_hotspot, y_hotspot, cursor_image);
|
||||||
|
|
||||||
/* some basic validation checks */
|
if (device->cursor_texture)
|
||||||
if (device->cursorTexture)
|
|
||||||
{
|
{
|
||||||
struct wined3d_context *context = context_acquire(device, NULL);
|
wined3d_texture_decref(device->cursor_texture);
|
||||||
context->gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->cursorTexture);
|
device->cursor_texture = NULL;
|
||||||
context_release(context);
|
|
||||||
device->cursorTexture = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cursor_image)
|
if (cursor_image)
|
||||||
|
@ -3838,50 +3889,15 @@ HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device
|
||||||
/* Do not store the surface's pointer because the application may
|
/* Do not store the surface's pointer because the application may
|
||||||
* release it after setting the cursor image. Windows doesn't
|
* release it after setting the cursor image. Windows doesn't
|
||||||
* addref the set surface, so we can't do this either without
|
* addref the set surface, so we can't do this either without
|
||||||
* creating circular refcount dependencies. Copy out the gl texture
|
* creating circular refcount dependencies. */
|
||||||
* instead. */
|
if (!(device->cursor_texture = wined3d_device_create_cursor_texture(device, cursor_image)))
|
||||||
|
{
|
||||||
|
ERR("Failed to create cursor texture.\n");
|
||||||
|
return WINED3DERR_INVALIDCALL;
|
||||||
|
}
|
||||||
|
|
||||||
device->cursorWidth = cursor_image->resource.width;
|
device->cursorWidth = cursor_image->resource.width;
|
||||||
device->cursorHeight = cursor_image->resource.height;
|
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
|
|
||||||
{
|
|
||||||
FIXME("A cursor texture was not returned.\n");
|
|
||||||
device->cursorTexture = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cursor_image->resource.width == 32 && cursor_image->resource.height == 32)
|
if (cursor_image->resource.width == 32 && cursor_image->resource.height == 32)
|
||||||
{
|
{
|
||||||
|
@ -3978,10 +3994,9 @@ BOOL CDECL wined3d_device_show_cursor(struct wined3d_device *device, BOOL show)
|
||||||
else
|
else
|
||||||
SetCursor(NULL);
|
SetCursor(NULL);
|
||||||
}
|
}
|
||||||
else
|
else if (device->cursor_texture)
|
||||||
{
|
{
|
||||||
if (device->cursorTexture)
|
device->bCursorVisible = show;
|
||||||
device->bCursorVisible = show;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return oldVisible;
|
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);
|
gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->depth_blt_texture);
|
||||||
device->depth_blt_texture = 0;
|
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->blitter->free_private(device);
|
||||||
device->shader_backend->shader_free_private(device);
|
device->shader_backend->shader_free_private(device);
|
||||||
|
|
|
@ -425,49 +425,6 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT
|
||||||
|
|
||||||
gl_info = context->gl_info;
|
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)
|
|
||||||
{
|
|
||||||
struct wined3d_surface cursor;
|
|
||||||
RECT destRect =
|
|
||||||
{
|
|
||||||
swapchain->device->xScreenSpace - swapchain->device->xHotSpot,
|
|
||||||
swapchain->device->yScreenSpace - swapchain->device->yHotSpot,
|
|
||||||
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)
|
if (swapchain->device->logo_texture)
|
||||||
{
|
{
|
||||||
struct wined3d_surface *src_surface = surface_from_resource(
|
struct wined3d_surface *src_surface = surface_from_resource(
|
||||||
|
@ -479,6 +436,27 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT
|
||||||
NULL, WINED3D_TEXF_POINT);
|
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,
|
||||||
|
swapchain->device->yScreenSpace - swapchain->device->yHotSpot,
|
||||||
|
swapchain->device->xScreenSpace + swapchain->device->cursorWidth - swapchain->device->xHotSpot,
|
||||||
|
swapchain->device->yScreenSpace + swapchain->device->cursorHeight - swapchain->device->yHotSpot,
|
||||||
|
};
|
||||||
|
|
||||||
|
TRACE("Rendering the software cursor.\n");
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("Presenting HDC %p.\n", context->hdc);
|
TRACE("Presenting HDC %p.\n", context->hdc);
|
||||||
|
|
||||||
render_to_fbo = swapchain->render_to_fbo;
|
render_to_fbo = swapchain->render_to_fbo;
|
||||||
|
|
|
@ -1921,7 +1921,7 @@ struct wined3d_device
|
||||||
UINT xScreenSpace;
|
UINT xScreenSpace;
|
||||||
UINT yScreenSpace;
|
UINT yScreenSpace;
|
||||||
UINT cursorWidth, cursorHeight;
|
UINT cursorWidth, cursorHeight;
|
||||||
GLuint cursorTexture;
|
struct wined3d_texture *cursor_texture;
|
||||||
HCURSOR hardwareCursor;
|
HCURSOR hardwareCursor;
|
||||||
|
|
||||||
/* The Wine logo texture */
|
/* The Wine logo texture */
|
||||||
|
|
Loading…
Reference in New Issue