[PATCH 1/2] wined3d: Add a download function for WINED3DFMT_X8D24_UNORM.

Henri Verbeet hverbeet at codeweavers.com
Fri Jan 5 11:53:12 CST 2018


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
For bug 43654.
---
 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.0




More information about the wine-devel mailing list