[PATCH 1/5] wined3d: Add support for converted volumes (try 2).

Stefan Dösinger stefan at codeweavers.com
Mon Sep 23 06:29:12 CDT 2013


Try 2: Fix sysmem eviction condition.

The purpose of this patch is to reduce the difference between volumes
and surfaces. I don't know any application that uses this functionality.
Windows drivers support this, contrary to what the removed comment says.

Note that uploading directly to the destination texture in
update_texture means that if the destination is locked (possible with a
default pool dynamic volume), we can't read back the data. I'm fine with
a FIXME until we find an application that actually needs this. If there
is such an application, my preference would be to reverse the conversion
rather than try to maintain a sysmem copy for converted default pool
resources - the latter option is much more invasive.
---
 dlls/wined3d/directx.c | 12 -----------
 dlls/wined3d/volume.c  | 56 ++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 52 insertions(+), 16 deletions(-)

diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 653d123..4a65993 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -3874,18 +3874,6 @@ HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT ad
                 return WINED3DERR_NOTAVAILABLE;
             }
 
-            /* Filter formats that need conversion; For one part, this
-             * conversion is unimplemented, and volume textures are huge, so
-             * it would be a big performance hit. Unless we hit an application
-             * needing one of those formats, don't advertize them to avoid
-             * leading applications into temptation. The windows drivers don't
-             * support most of those formats on volumes anyway. */
-            if (format->convert)
-            {
-                TRACE("[FAILED] - No converted formats on volumes.\n");
-                return WINED3DERR_NOTAVAILABLE;
-            }
-
             /* The GL_EXT_texture_compression_s3tc spec requires that loading
              * an s3tc compressed texture results in an error. While the D3D
              * refrast does support s3tc volumes, at least the nvidia Windows
diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c
index ea481a1..b0dd756 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -102,11 +102,37 @@ void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wine
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_format *format = volume->resource.format;
+    UINT width = volume->resource.width;
+    UINT height = volume->resource.height;
+    UINT depth = volume->resource.depth, z;
+    BYTE *mem = data->addr;
 
     TRACE("volume %p, context %p, level %u, format %s (%#x).\n",
             volume, context, volume->texture_level, debug_d3dformat(format->id),
             format->id);
 
+    if (format->convert)
+    {
+        UINT dst_row_pitch, dst_slice_pitch;
+        UINT src_row_pitch, src_slice_pitch;
+        UINT alignment = volume->resource.device->surface_alignment;
+
+        if (data->buffer_object)
+            ERR("Loading a converted volume from a PBO.\n");
+        if (format->flags & WINED3DFMT_FLAG_BLOCKS)
+            ERR("Converting a block-based format.\n");
+
+        dst_row_pitch = width * format->conv_byte_count;
+        dst_row_pitch = (dst_row_pitch + alignment - 1) & ~(alignment - 1);
+        dst_slice_pitch = dst_row_pitch * height;
+
+        wined3d_volume_get_pitch(volume, &src_row_pitch, &src_slice_pitch);
+
+        mem = HeapAlloc(GetProcessHeap(), 0, dst_slice_pitch * depth);
+        for (z = 0; z < depth; z++)
+            format->convert(data->addr + z * src_slice_pitch, mem + z * dst_slice_pitch,
+                    src_row_pitch, dst_row_pitch, width, height);
+    }
 
     if (data->buffer_object)
     {
@@ -115,8 +141,8 @@ void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wine
     }
 
     GL_EXTCALL(glTexSubImage3DEXT(GL_TEXTURE_3D, volume->texture_level, 0, 0, 0,
-            volume->resource.width, volume->resource.height, volume->resource.depth,
-            format->glFormat, format->glType, data->addr));
+            width, height, depth,
+            format->glFormat, format->glType, mem));
     checkGLcall("glTexSubImage3D");
 
     if (data->buffer_object)
@@ -124,6 +150,9 @@ void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wine
         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
         checkGLcall("glBindBufferARB");
     }
+
+    if (mem != data->addr)
+        HeapFree(GetProcessHeap(), 0, mem);
 }
 
 static void wined3d_volume_validate_location(struct wined3d_volume *volume, DWORD location)
@@ -147,6 +176,13 @@ static void wined3d_volume_download_data(struct wined3d_volume *volume,
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_format *format = volume->resource.format;
 
+    if (format->convert)
+    {
+        FIXME("Attempting to download a converted volume, format %s.\n",
+                debug_d3dformat(format->id));
+        return;
+    }
+
     if (data->buffer_object)
     {
         GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, data->buffer_object));
@@ -218,6 +254,17 @@ static void wined3d_volume_srgb_transfer(struct wined3d_volume *volume,
     HeapFree(GetProcessHeap(), 0, data.addr);
 }
 
+static BOOL wined3d_volume_can_evict(const struct wined3d_volume *volume)
+{
+    if (volume->resource.pool != WINED3D_POOL_MANAGED)
+        return FALSE;
+    if (volume->download_count >= 10)
+        return FALSE;
+    if (volume->resource.format->convert)
+        return FALSE;
+
+    return TRUE;
+}
 /* Context activation is done by the caller. */
 static void wined3d_volume_load_location(struct wined3d_volume *volume,
         struct wined3d_context *context, DWORD location)
@@ -280,7 +327,7 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume,
             }
             wined3d_volume_validate_location(volume, location);
 
-            if (volume->resource.pool == WINED3D_POOL_MANAGED && volume->download_count < 10)
+            if (wined3d_volume_can_evict(volume))
                 wined3d_volume_evict_sysmem(volume);
 
             break;
@@ -808,7 +855,8 @@ static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_device
     volume->locations = WINED3D_LOCATION_DISCARDED;
 
     if (pool == WINED3D_POOL_DEFAULT && usage & WINED3DUSAGE_DYNAMIC
-            && gl_info->supported[ARB_PIXEL_BUFFER_OBJECT])
+            && gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]
+            && !format->convert)
     {
         wined3d_resource_free_sysmem(&volume->resource);
         volume->flags |= WINED3D_VFLAG_PBO;
-- 
1.8.1.5




More information about the wine-patches mailing list