[PATCH 4/6] d3d9: Keep track of D3DUSAGE_AUTOGENMIPMAP textures in the d3d9 device.

Matteo Bruni mbruni at codeweavers.com
Fri Feb 1 05:59:31 CST 2019


Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
This is sort-of a partial revert of commit
6cfab2f7adf8d8a32b5fad6bf75f9859e6fa0b01. This time use a scheme
similar to the one used by Henri for system memory buffers to avoid
the issues with stateblocks solved by the original patch and, at the
same time, restore some lost performance.

It might also help with moving the stateblock stuff to the client
libraries but I'm happy to drop this patch if it turns out to be
actually harmful in that regard.

 dlls/d3d9/d3d9_private.h |  2 ++
 dlls/d3d9/device.c       | 23 +++++++++++++++++++++--
 dlls/d3d9/stateblock.c   | 16 +++++++++++++++-
 3 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index 1032f8e8e9c..3fe0376e5c1 100644
--- a/dlls/d3d9/d3d9_private.h
+++ b/dlls/d3d9/d3d9_private.h
@@ -111,6 +111,8 @@ struct d3d9_device
     DWORD recording : 1;
     DWORD padding : 11;
 
+    DWORD auto_mipmaps; /* D3D9_MAX_TEXTURE_UNITS */
+
     unsigned int max_user_clip_planes;
 
     UINT implicit_swapchain_count;
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index 98ada03af8b..9fffac86ff0 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -1012,6 +1012,9 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device,
             device->device_state = D3D9_DEVICE_STATE_OK;
         }
 
+        if (!device->d3d_parent->extended)
+            device->auto_mipmaps = 0;
+
         rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0);
         device->render_targets[0] = wined3d_rendertarget_view_get_sub_resource_parent(rtv);
         for (i = 1; i < ARRAY_SIZE(device->render_targets); ++i)
@@ -2456,6 +2459,18 @@ static HRESULT WINAPI d3d9_device_SetTexture(IDirect3DDevice9Ex *iface, DWORD st
     wined3d_mutex_lock();
     hr = wined3d_device_set_texture(device->wined3d_device, stage,
             texture_impl ? texture_impl->wined3d_texture : NULL);
+    if (SUCCEEDED(hr) && !device->recording)
+    {
+        unsigned int i = stage >= D3DVERTEXTEXTURESAMPLER0 ? stage - D3DVERTEXTEXTURESAMPLER0 + 16 : stage;
+
+        if (i < D3D9_MAX_TEXTURE_UNITS)
+        {
+            if (texture_impl && texture_impl->usage & D3DUSAGE_AUTOGENMIPMAP)
+                device->auto_mipmaps |= 1u << i;
+            else
+                device->auto_mipmaps &= ~(1u << i);
+        }
+    }
     wined3d_mutex_unlock();
 
     return hr;
@@ -2700,10 +2715,14 @@ static float WINAPI d3d9_device_GetNPatchMode(IDirect3DDevice9Ex *iface)
 static void d3d9_generate_auto_mipmaps(struct d3d9_device *device)
 {
     struct wined3d_texture *texture;
-    unsigned int i, stage;
+    unsigned int i, stage, map;
 
-    for (i = 0; i < D3D9_MAX_TEXTURE_UNITS; ++i)
+    map = device->auto_mipmaps;
+    while (map)
     {
+        i = ffs(map) - 1;
+        map ^= 1u << i;
+
         stage = i >= 16 ? i - 16 + D3DVERTEXTEXTURESAMPLER0 : i;
         if ((texture = wined3d_device_get_texture(device->wined3d_device, stage)))
             d3d9_texture_gen_auto_mipmap(wined3d_texture_get_parent(texture));
diff --git a/dlls/d3d9/stateblock.c b/dlls/d3d9/stateblock.c
index 8431ef77002..c681e95e277 100644
--- a/dlls/d3d9/stateblock.c
+++ b/dlls/d3d9/stateblock.c
@@ -109,10 +109,12 @@ static HRESULT WINAPI d3d9_stateblock_Capture(IDirect3DStateBlock9 *iface)
 static HRESULT WINAPI d3d9_stateblock_Apply(IDirect3DStateBlock9 *iface)
 {
     struct d3d9_stateblock *stateblock = impl_from_IDirect3DStateBlock9(iface);
+    struct wined3d_texture *wined3d_texture;
+    unsigned int i, offset, stride, stage;
     struct wined3d_buffer *wined3d_buffer;
     struct d3d9_vertexbuffer *buffer;
-    unsigned int i, offset, stride;
     enum wined3d_format_id format;
+    struct d3d9_texture *texture;
     struct d3d9_device *device;
     HRESULT hr;
 
@@ -134,6 +136,18 @@ static HRESULT WINAPI d3d9_stateblock_Apply(IDirect3DStateBlock9 *iface)
     }
     device->sysmem_ib = (wined3d_buffer = wined3d_device_get_index_buffer(device->wined3d_device, &format, &offset))
             && (buffer = wined3d_buffer_get_parent(wined3d_buffer)) && buffer->draw_buffer;
+    device->auto_mipmaps = 0;
+    for (i = 0; i < D3D9_MAX_TEXTURE_UNITS; ++i)
+    {
+        stage = i >= 16 ? i - 16 + D3DVERTEXTEXTURESAMPLER0 : i;
+
+        if ((wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage))
+            && (texture = wined3d_texture_get_parent(wined3d_texture))
+            && texture->usage & D3DUSAGE_AUTOGENMIPMAP)
+            device->auto_mipmaps |= 1u << i;
+        else
+            device->auto_mipmaps &= ~(1u << i);
+    }
     wined3d_mutex_unlock();
 
     return D3D_OK;
-- 
2.19.2




More information about the wine-devel mailing list