From bc75bec270bfdc09c881799b331aabf4d119a271 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Fri, 5 Jan 2018 18:53:12 +0100 Subject: [PATCH] wined3d: Add a download function for WINED3DFMT_X8D24_UNORM. Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/surface.c | 58 ++++++++++++++++++++++++++++++++++++------ dlls/wined3d/texture.c | 10 ++++---- dlls/wined3d/utils.c | 47 +++++++++++++++++++++++++++------- dlls/wined3d/wined3d_private.h | 8 ++++-- 4 files changed, 99 insertions(+), 24 deletions(-) diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index da22c7ad9aa..2a90c12353a 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -546,7 +546,7 @@ static void surface_download_data(struct wined3d_surface *surface, const struct void *mem; /* Only support read back of converted P8 surfaces. */ - if (texture->flags & WINED3D_TEXTURE_CONVERTED && format->id != WINED3DFMT_P8_UINT) + if (texture->flags & WINED3D_TEXTURE_CONVERTED && format->id != WINED3DFMT_P8_UINT && !format->download) { ERR("Trying to read back converted surface %p with format %s.\n", surface, debug_d3dformat(format->id)); return; @@ -556,6 +556,12 @@ static void surface_download_data(struct wined3d_surface *surface, const struct if (surface->texture_target == GL_TEXTURE_2D_ARRAY) { + if (format->download) + { + FIXME("Reading back converted array texture %p is not supported.\n", texture); + return; + } + /* NP2 emulation is not allowed on array textures. */ if (texture->flags & WINED3D_TEXTURE_COND_NP2_EMULATED) ERR("Array texture %p uses NP2 emulation.\n", texture); @@ -573,6 +579,12 @@ static void surface_download_data(struct wined3d_surface *surface, const struct if (texture->flags & WINED3D_TEXTURE_COND_NP2_EMULATED) { + if (format->download) + { + FIXME("Reading back converted texture %p with NP2 emulation is not supported.\n", texture); + return; + } + wined3d_texture_get_pitch(texture, surface->texture_level, &dst_row_pitch, &dst_slice_pitch); wined3d_format_calculate_pitch(format, texture->resource.device->surface_alignment, wined3d_texture_get_level_pow2_width(texture, surface->texture_level), @@ -590,6 +602,30 @@ static void surface_download_data(struct wined3d_surface *surface, const struct ERR("Unexpected compressed format for NP2 emulated texture.\n"); } + if (format->download) + { + struct wined3d_format f; + + if (data.buffer_object) + ERR("Converted texture %p uses PBO unexpectedly.\n", texture); + + WARN_(d3d_perf)("Downloading converted surface %p with format %s.\n", surface, debug_d3dformat(format->id)); + + f = *format; + f.byte_count = format->conv_byte_count; + wined3d_texture_get_pitch(texture, surface->texture_level, &dst_row_pitch, &dst_slice_pitch); + wined3d_format_calculate_pitch(&f, texture->resource.device->surface_alignment, + wined3d_texture_get_level_width(texture, surface->texture_level), + wined3d_texture_get_level_height(texture, surface->texture_level), + &src_row_pitch, &src_slice_pitch); + + if (!(temporary_mem = HeapAlloc(GetProcessHeap(), 0, src_slice_pitch))) + { + ERR("Failed to allocate memory.\n"); + return; + } + } + if (temporary_mem) { mem = temporary_mem; @@ -623,7 +659,13 @@ static void surface_download_data(struct wined3d_surface *surface, const struct checkGLcall("glGetTexImage"); } - if (texture->flags & WINED3D_TEXTURE_COND_NP2_EMULATED) + if (format->download) + { + format->download(mem, data.addr, src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch, + wined3d_texture_get_level_width(texture, surface->texture_level), + wined3d_texture_get_level_height(texture, surface->texture_level), 1); + } + else if (texture->flags & WINED3D_TEXTURE_COND_NP2_EMULATED) { const BYTE *src_data; unsigned int h, y; @@ -1261,8 +1303,8 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr DWORD map_binding; if (!(conv = find_converter(src_format->id, dst_format->id)) && (!device->d3d_initialized - || !is_identity_fixup(src_format->color_fixup) || src_format->convert - || !is_identity_fixup(dst_format->color_fixup) || dst_format->convert + || !is_identity_fixup(src_format->color_fixup) || src_format->conv_byte_count + || !is_identity_fixup(dst_format->color_fixup) || dst_format->conv_byte_count || (src_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED))) { FIXME("Cannot find a conversion function from format %s to %s.\n", @@ -2258,7 +2300,7 @@ static BOOL surface_load_texture(struct wined3d_surface *surface, /* Don't use PBOs for converted surfaces. During PBO conversion we look at * WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is * getting called. */ - if ((format.convert || conversion) && texture->sub_resources[sub_resource_idx].buffer_object) + if ((format.conv_byte_count || conversion) && texture->sub_resources[sub_resource_idx].buffer_object) { TRACE("Removing the pbo attached to surface %p.\n", surface); @@ -2267,7 +2309,7 @@ static BOOL surface_load_texture(struct wined3d_surface *surface, } wined3d_texture_get_memory(texture, sub_resource_idx, &data, sub_resource->locations); - if (format.convert) + if (format.conv_byte_count) { /* This code is entered for texture formats which need a fixup. */ format.byte_count = format.conv_byte_count; @@ -2281,7 +2323,7 @@ static BOOL surface_load_texture(struct wined3d_surface *surface, context_release(context); return FALSE; } - format.convert(src_mem, dst_mem, src_row_pitch, src_slice_pitch, + format.upload(src_mem, dst_mem, src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch, width, height, 1); src_row_pitch = dst_row_pitch; context_unmap_bo_address(context, &data, GL_PIXEL_UNPACK_BUFFER); @@ -3871,7 +3913,7 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst TRACE("Not doing upload because of scaling.\n"); else if (convert) TRACE("Not doing upload because of format conversion.\n"); - else if (dst_texture->resource.format->convert) + else if (dst_texture->resource.format->conv_byte_count) TRACE("Not doing upload because the destination format needs conversion.\n"); else { diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index ddbe340dc82..4dc739cc4c0 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -35,7 +35,7 @@ static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const return texture->resource.pool == WINED3D_POOL_DEFAULT && texture->resource.access_flags & WINED3D_RESOURCE_ACCESS_CPU && gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] - && !texture->resource.format->convert + && !texture->resource.format->conv_byte_count && !(texture->flags & (WINED3D_TEXTURE_PIN_SYSMEM | WINED3D_TEXTURE_COND_NP2_EMULATED)); } @@ -1668,7 +1668,7 @@ static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wi TRACE("texture %p, context %p, format %s.\n", texture, context, debug_d3dformat(format->id)); - if (format->convert) + if (format->conv_byte_count) { texture->flags |= WINED3D_TEXTURE_CONVERTED; } @@ -2306,7 +2306,7 @@ static void texture3d_upload_data(struct wined3d_texture *texture, unsigned int update_d = box->back - box->front; } - if (format->convert) + if (format->conv_byte_count) { if (data->buffer_object) ERR("Loading a converted texture from a PBO.\n"); @@ -2317,7 +2317,7 @@ static void texture3d_upload_data(struct wined3d_texture *texture, unsigned int dst_slice_pitch = dst_row_pitch * update_h; converted_mem = wined3d_calloc(update_d, dst_slice_pitch); - format->convert(data->addr, converted_mem, row_pitch, slice_pitch, + format->upload(data->addr, converted_mem, row_pitch, slice_pitch, dst_row_pitch, dst_slice_pitch, update_w, update_h, update_d); mem = converted_mem; } @@ -2354,7 +2354,7 @@ static void texture3d_download_data(struct wined3d_texture *texture, unsigned in const struct wined3d_format *format = texture->resource.format; const struct wined3d_gl_info *gl_info = context->gl_info; - if (format->convert) + if (format->conv_byte_count) { FIXME("Attempting to download a converted volume, format %s.\n", debug_d3dformat(format->id)); diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index b3003f13028..8a96a20c117 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -434,8 +434,12 @@ struct wined3d_format_texture_info unsigned int conv_byte_count; unsigned int flags; enum wined3d_gl_extension extension; - void (*convert)(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch, - UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth); + void (*upload)(const BYTE *src, BYTE *dst, unsigned int src_row_pitch, unsigned int src_slice_pitch, + unsigned int dst_row_pitch, unsigned int dst_slice_pitch, + unsigned int width, unsigned int height, unsigned int depth); + void (*download)(const BYTE *src, BYTE *dst, unsigned int src_row_pitch, unsigned int src_slice_pitch, + unsigned int dst_row_pitch, unsigned int dst_slice_pitch, + unsigned int width, unsigned int height, unsigned int depth); }; static void convert_l4a4_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch, @@ -839,8 +843,32 @@ static void convert_s8_uint_d24_float(const BYTE *src, BYTE *dst, UINT src_row_p } } -static void convert_x8_d24_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch, - UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth) +static void x8_d24_unorm_upload(const BYTE *src, BYTE *dst, + unsigned int src_row_pitch, unsigned int src_slice_pitch, + unsigned int dst_row_pitch, unsigned int dst_slice_pitch, + unsigned int width, unsigned int height, unsigned int depth) +{ + unsigned int x, y, z; + + for (z = 0; z < depth; ++z) + { + for (y = 0; y < height; ++y) + { + const DWORD *source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch); + DWORD *dest = (DWORD *)(dst + z * dst_slice_pitch + y * dst_row_pitch); + + for (x = 0; x < width; ++x) + { + dest[x] = source[x] << 8 | ((source[x] >> 16) & 0xff); + } + } + } +} + +static void x8_d24_unorm_download(const BYTE *src, BYTE *dst, + unsigned int src_row_pitch, unsigned int src_slice_pitch, + unsigned int dst_row_pitch, unsigned int dst_slice_pitch, + unsigned int width, unsigned int height, unsigned int depth) { unsigned int x, y, z; @@ -853,7 +881,7 @@ static void convert_x8_d24_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, for (x = 0; x < width; ++x) { - dest[x] = source[x] << 8 | source[x] >> 16; + dest[x] = source[x] >> 8; } } } @@ -1088,7 +1116,7 @@ static const struct wined3d_format_texture_info format_texture_info[] = /* format id gl_internal gl_srgb_internal gl_rt_internal gl_format gl_type conv_byte_count flags - extension convert */ + extension upload download */ /* FourCC formats */ /* GL_APPLE_ycbcr_422 claims that its '2YUV' format, which is supported via the UNSIGNED_SHORT_8_8_REV_APPLE type * is equivalent to 'UYVY' format on Windows, and the 'YUVS' via UNSIGNED_SHORT_8_8_APPLE equates to 'YUY2'. The @@ -1609,12 +1637,12 @@ static const struct wined3d_format_texture_info format_texture_info[] = {WINED3DFMT_X8D24_UNORM, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 4, WINED3DFMT_FLAG_DEPTH, - WINED3D_GL_EXT_NONE, convert_x8_d24_unorm}, + WINED3D_GL_EXT_NONE, x8_d24_unorm_upload, x8_d24_unorm_download}, {WINED3DFMT_X8D24_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 4, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW, - ARB_DEPTH_TEXTURE, convert_x8_d24_unorm}, + ARB_DEPTH_TEXTURE, x8_d24_unorm_upload, x8_d24_unorm_download}, {WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW, @@ -2944,8 +2972,9 @@ static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct win query_internal_format(adapter, format, &format_texture_info[i], gl_info, srgb_write, FALSE); /* Texture conversion stuff */ - format->convert = format_texture_info[i].convert; format->conv_byte_count = format_texture_info[i].conv_byte_count; + format->upload = format_texture_info[i].upload; + format->download = format_texture_info[i].download; srgb_format = NULL; for (j = 0; j < ARRAY_SIZE(format_srgb_info); ++j) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 20f53aa9e96..9f68b0ad30f 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4240,8 +4240,12 @@ struct wined3d_format float depth_bias_scale; struct wined3d_rational height_scale; struct color_fixup_desc color_fixup; - void (*convert)(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch, - UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth); + void (*upload)(const BYTE *src, BYTE *dst, unsigned int src_row_pitch, unsigned int src_slice_pitch, + unsigned int dst_row_pitch, unsigned dst_slice_pitch, + unsigned int width, unsigned int height, unsigned int depth); + void (*download)(const BYTE *src, BYTE *dst, unsigned int src_row_pitch, unsigned int src_slice_pitch, + unsigned int dst_row_pitch, unsigned dst_slice_pitch, + unsigned int width, unsigned int height, unsigned int depth); enum wined3d_format_id typeless_id; GLenum gl_view_class; -- 2.11.4.GIT