[PATCH 3/5] d3d9: Handle D3DUSAGE_AUTOGENMIPMAP textures entirely in d3d9.
Matteo Bruni
mbruni at codeweavers.com
Tue Feb 6 12:36:15 CST 2018
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
dlls/d3d9/d3d9_private.h | 25 ++++-
dlls/d3d9/device.c | 75 +++++++++++++
dlls/d3d9/surface.c | 4 +
dlls/d3d9/tests/device.c | 5 +-
dlls/d3d9/texture.c | 270 ++++++++++++++++++++++++++++++++++++-----------
5 files changed, 313 insertions(+), 66 deletions(-)
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index 5a1aac81ed1..ce76c71e029 100644
--- a/dlls/d3d9/d3d9_private.h
+++ b/dlls/d3d9/d3d9_private.h
@@ -39,8 +39,16 @@
#include "d3d9.h"
#include "wine/wined3d.h"
+#define D3D9_MAX_VERTEX_SHADER_CONSTANTF 256
+#define D3D9_MAX_TEXTURE_UNITS 20
+#define D3D9_MAX_SIMULTANEOUS_RENDERTARGETS 4
+
#define D3DPRESENTFLAGS_MASK 0x00000fffu
+#define D3D9_TEXTURE_MIPMAP_DIRTY 0x1
+
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+
extern const struct wined3d_parent_ops d3d9_null_wined3d_parent_ops DECLSPEC_HIDDEN;
HRESULT vdecl_convert_fvf(DWORD FVF, D3DVERTEXELEMENT9 **ppVertexElements) DECLSPEC_HIDDEN;
@@ -92,6 +100,9 @@ struct d3d9_device
UINT index_buffer_size;
UINT index_buffer_pos;
+ struct d3d9_texture *textures[D3D9_MAX_TEXTURE_UNITS];
+ struct d3d9_surface *render_targets[D3D9_MAX_SIMULTANEOUS_RENDERTARGETS];
+
LONG device_state;
BOOL in_destruction;
BOOL in_scene;
@@ -198,6 +209,10 @@ struct d3d9_texture
struct wined3d_texture *wined3d_texture;
IDirect3DDevice9Ex *parent_device;
struct list rtv_list;
+ DWORD usage;
+ BOOL flags;
+ struct wined3d_shader_resource_view *wined3d_srv;
+ D3DTEXTUREFILTERTYPE autogen_filter_type;
};
HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *device,
@@ -207,6 +222,8 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device,
HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *device,
UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) DECLSPEC_HIDDEN;
struct d3d9_texture *unsafe_impl_from_IDirect3DBaseTexture9(IDirect3DBaseTexture9 *iface) DECLSPEC_HIDDEN;
+void d3d9_texture_flag_auto_gen_mipmap(struct d3d9_texture *texture) DECLSPEC_HIDDEN;
+void d3d9_texture_gen_auto_mipmap(struct d3d9_texture *texture) DECLSPEC_HIDDEN;
struct d3d9_stateblock
{
@@ -247,9 +264,6 @@ HRESULT vertexshader_init(struct d3d9_vertexshader *shader,
struct d3d9_device *device, const DWORD *byte_code) DECLSPEC_HIDDEN;
struct d3d9_vertexshader *unsafe_impl_from_IDirect3DVertexShader9(IDirect3DVertexShader9 *iface) DECLSPEC_HIDDEN;
-#define D3D9_MAX_VERTEX_SHADER_CONSTANTF 256
-#define D3D9_MAX_SIMULTANEOUS_RENDERTARGETS 4
-
struct d3d9_pixelshader
{
IDirect3DPixelShader9 IDirect3DPixelShader9_iface;
@@ -315,4 +329,9 @@ static inline unsigned int wined3daccess_from_d3dpool(D3DPOOL pool)
}
}
+static inline DWORD wined3dusage_from_d3dusage(unsigned int usage)
+{
+ return usage & WINED3DUSAGE_MASK & ~WINED3DUSAGE_AUTOGENMIPMAP;
+}
+
#endif /* __WINE_D3D9_PRIVATE_H */
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index 954f3faa30d..d2766c72a54 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -816,6 +816,8 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device,
BOOL extended = device->d3d_parent->extended;
struct wined3d_swapchain_desc swapchain_desc;
struct wined3d_display_mode wined3d_mode;
+ struct wined3d_rendertarget_view *rtv;
+ unsigned int i;
HRESULT hr;
if (!extended && device->device_state == D3D9_DEVICE_STATE_LOST)
@@ -877,6 +879,15 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device,
device->device_state = D3D9_DEVICE_STATE_OK;
}
+
+ if (!device->d3d_parent->extended)
+ for (i = 0; i < ARRAY_SIZE(device->textures); ++i)
+ device->textures[i] = NULL;
+
+ 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)
+ device->render_targets[i] = NULL;
}
else if (!extended)
{
@@ -1431,6 +1442,9 @@ static HRESULT WINAPI d3d9_device_UpdateSurface(IDirect3DDevice9Ex *iface,
wined3d_texture_get_resource(dst->wined3d_texture), dst->sub_resource_idx, dst_point ? dst_point->x : 0,
dst_point ? dst_point->y : 0, 0, wined3d_texture_get_resource(src->wined3d_texture),
src->sub_resource_idx, &src_box);
+ if (SUCCEEDED(hr) && dst->texture)
+ d3d9_texture_flag_auto_gen_mipmap(dst->texture);
+
wined3d_mutex_unlock();
if (FAILED(hr))
@@ -1454,6 +1468,8 @@ static HRESULT WINAPI d3d9_device_UpdateTexture(IDirect3DDevice9Ex *iface,
wined3d_mutex_lock();
hr = wined3d_device_update_texture(device->wined3d_device,
src_impl->wined3d_texture, dst_impl->wined3d_texture);
+ if (SUCCEEDED(hr))
+ d3d9_texture_flag_auto_gen_mipmap(dst_impl);
wined3d_mutex_unlock();
return hr;
@@ -1572,6 +1588,8 @@ static HRESULT WINAPI d3d9_device_StretchRect(IDirect3DDevice9Ex *iface, IDirect
src->wined3d_texture, src->sub_resource_idx, src_rect, 0, NULL, filter);
if (hr == WINEDDERR_INVALIDRECT)
hr = D3DERR_INVALIDCALL;
+ if (SUCCEEDED(hr) && dst->texture)
+ d3d9_texture_flag_auto_gen_mipmap(dst->texture);
done:
wined3d_mutex_unlock();
@@ -1628,6 +1646,8 @@ static HRESULT WINAPI d3d9_device_ColorFill(IDirect3DDevice9Ex *iface,
hr = wined3d_device_clear_rendertarget_view(device->wined3d_device,
rtv, rect, WINED3DCLEAR_TARGET, &c, 0.0f, 0);
d3d9_surface_release_rendertarget_view(surface_impl, rtv);
+ if (SUCCEEDED(hr) && surface_impl->texture)
+ d3d9_texture_flag_auto_gen_mipmap(surface_impl->texture);
wined3d_mutex_unlock();
@@ -1710,6 +1730,8 @@ static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWO
rtv = surface_impl ? d3d9_surface_acquire_rendertarget_view(surface_impl) : NULL;
hr = wined3d_device_set_rendertarget_view(device->wined3d_device, idx, rtv, TRUE);
d3d9_surface_release_rendertarget_view(surface_impl, rtv);
+ if (SUCCEEDED(hr))
+ device->render_targets[idx] = surface_impl;
wined3d_mutex_unlock();
return hr;
@@ -1830,6 +1852,19 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_EndScene(IDirect3DDevice9Ex
return hr;
}
+static void d3d9_rts_flag_auto_gen_mipmap(struct d3d9_device *device)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(device->render_targets); ++i)
+ {
+ struct d3d9_surface *surface = device->render_targets[i];
+
+ if (surface && surface->texture)
+ d3d9_texture_flag_auto_gen_mipmap(surface->texture);
+ }
+}
+
static HRESULT WINAPI d3d9_device_Clear(IDirect3DDevice9Ex *iface, DWORD rect_count,
const D3DRECT *rects, DWORD flags, D3DCOLOR color, float z, DWORD stencil)
{
@@ -1854,6 +1889,8 @@ static HRESULT WINAPI d3d9_device_Clear(IDirect3DDevice9Ex *iface, DWORD rect_co
wined3d_mutex_lock();
hr = wined3d_device_clear(device->wined3d_device, rect_count, (const RECT *)rects, flags, &c, z, stencil);
+ if (SUCCEEDED(hr))
+ d3d9_rts_flag_auto_gen_mipmap(device);
wined3d_mutex_unlock();
return hr;
@@ -2251,6 +2288,13 @@ 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))
+ {
+ unsigned int i = stage >= D3DVERTEXTEXTURESAMPLER0 ? stage - D3DVERTEXTEXTURESAMPLER0 + 16 : stage;
+
+ if (stage < ARRAY_SIZE(device->textures))
+ device->textures[i] = texture_impl;
+ }
wined3d_mutex_unlock();
return hr;
@@ -2491,6 +2535,16 @@ static float WINAPI d3d9_device_GetNPatchMode(IDirect3DDevice9Ex *iface)
return ret;
}
+/* wined3d critical section must be taken by the caller. */
+static void d3d9_generate_auto_mipmaps(struct d3d9_device *device)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(device->textures); ++i)
+ if (device->textures[i])
+ d3d9_texture_gen_auto_mipmap(device->textures[i]);
+}
+
static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface,
D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count)
{
@@ -2507,9 +2561,12 @@ static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface,
WARN("Called without a valid vertex declaration set.\n");
return D3DERR_INVALIDCALL;
}
+ d3d9_generate_auto_mipmaps(device);
wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex,
vertex_count_from_primitive_count(primitive_type, primitive_count));
+ if (SUCCEEDED(hr))
+ d3d9_rts_flag_auto_gen_mipmap(device);
wined3d_mutex_unlock();
return hr;
@@ -2534,10 +2591,13 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface
WARN("Called without a valid vertex declaration set.\n");
return D3DERR_INVALIDCALL;
}
+ d3d9_generate_auto_mipmaps(device);
wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx);
wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, start_idx,
vertex_count_from_primitive_count(primitive_type, primitive_count));
+ if (SUCCEEDED(hr))
+ d3d9_rts_flag_auto_gen_mipmap(device);
wined3d_mutex_unlock();
return hr;
@@ -2629,9 +2689,12 @@ static HRESULT WINAPI d3d9_device_DrawPrimitiveUP(IDirect3DDevice9Ex *iface,
if (FAILED(hr))
goto done;
+ d3d9_generate_auto_mipmaps(device);
wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vtx_count);
wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
+ if (SUCCEEDED(hr))
+ d3d9_rts_flag_auto_gen_mipmap(device);
done:
wined3d_mutex_unlock();
@@ -2752,6 +2815,7 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitiveUP(IDirect3DDevice9Ex *ifa
if (FAILED(hr))
goto done;
+ d3d9_generate_auto_mipmaps(device);
wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer,
wined3dformat_from_d3dformat(index_format), 0);
wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vertex_stride - min_vertex_idx);
@@ -2763,6 +2827,9 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitiveUP(IDirect3DDevice9Ex *ifa
wined3d_device_set_index_buffer(device->wined3d_device, NULL, WINED3DFMT_UNKNOWN, 0);
wined3d_device_set_base_vertex_index(device->wined3d_device, 0);
+ if (SUCCEEDED(hr))
+ d3d9_rts_flag_auto_gen_mipmap(device);
+
done:
wined3d_mutex_unlock();
return hr;
@@ -4147,6 +4214,14 @@ HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wine
return E_OUTOFMEMORY;
}
+ /* We could also simply ignore the initial rendertarget since it's known
+ * not to be a texture (we currently use these only for automatic mipmap
+ * generation). */
+ wined3d_mutex_lock();
+ device->render_targets[0] = wined3d_rendertarget_view_get_sub_resource_parent(
+ wined3d_device_get_rendertarget_view(device->wined3d_device, 0));
+ wined3d_mutex_unlock();
+
IDirect3D9Ex_AddRef(&parent->IDirect3D9Ex_iface);
device->d3d_parent = parent;
diff --git a/dlls/d3d9/surface.c b/dlls/d3d9/surface.c
index 8c42a8c630d..a38cbb4d816 100644
--- a/dlls/d3d9/surface.c
+++ b/dlls/d3d9/surface.c
@@ -270,6 +270,8 @@ static HRESULT WINAPI d3d9_surface_UnlockRect(IDirect3DSurface9 *iface)
wined3d_mutex_lock();
hr = wined3d_resource_unmap(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx);
+ if (SUCCEEDED(hr) && surface->texture)
+ d3d9_texture_flag_auto_gen_mipmap(surface->texture);
wined3d_mutex_unlock();
if (hr == WINEDDERR_NOTLOCKED)
@@ -307,6 +309,8 @@ static HRESULT WINAPI d3d9_surface_ReleaseDC(IDirect3DSurface9 *iface, HDC dc)
wined3d_mutex_lock();
hr = wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, dc);
+ if (SUCCEEDED(hr) && surface->texture)
+ d3d9_texture_flag_auto_gen_mipmap(surface->texture);
wined3d_mutex_unlock();
return hr;
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index a9fd4e4d30f..71cfdf49219 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -7124,10 +7124,9 @@ static void test_mipmap_gen(void)
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
- ok(filter_type == D3DTEXF_LINEAR /* || broken(filter_type == D3DTEXF_POINT)*/,
- "Got unexpected filter_type %#x.\n", filter_type);
+ ok(filter_type == D3DTEXF_LINEAR, "Got unexpected filter_type %#x.\n", filter_type);
hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
- todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
+ ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c
index a1c52591c1b..e51c6fc6e58 100644
--- a/dlls/d3d9/texture.c
+++ b/dlls/d3d9/texture.c
@@ -38,6 +38,62 @@ static inline struct d3d9_texture *impl_from_IDirect3DVolumeTexture9(IDirect3DVo
return CONTAINING_RECORD(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface);
}
+static void STDMETHODCALLTYPE srv_wined3d_object_destroyed(void *parent)
+{
+ struct d3d9_texture *texture = parent;
+
+ texture->wined3d_srv = NULL;
+}
+
+static const struct wined3d_parent_ops d3d9_srv_wined3d_parent_ops =
+{
+ srv_wined3d_object_destroyed,
+};
+
+/* wined3d critical section must be taken by the caller. */
+static struct wined3d_shader_resource_view *d3d9_texture_acquire_shader_resource_view(struct d3d9_texture *texture)
+{
+ struct wined3d_sub_resource_desc sr_desc;
+ struct wined3d_view_desc desc;
+ HRESULT hr;
+
+ if (texture->wined3d_srv)
+ return texture->wined3d_srv;
+
+ wined3d_texture_get_sub_resource_desc(texture->wined3d_texture, 0, &sr_desc);
+ desc.format_id = sr_desc.format;
+ desc.flags = 0;
+ desc.u.texture.level_idx = 0;
+ desc.u.texture.level_count = wined3d_texture_get_level_count(texture->wined3d_texture);
+ desc.u.texture.layer_idx = 0;
+ desc.u.texture.layer_count = sr_desc.usage & WINED3DUSAGE_LEGACY_CUBEMAP ? 6 : 1;
+ if (FAILED(hr = wined3d_shader_resource_view_create(&desc,
+ wined3d_texture_get_resource(texture->wined3d_texture), texture,
+ &d3d9_srv_wined3d_parent_ops, &texture->wined3d_srv)))
+ {
+ ERR("Failed to create shader resource view, hr %#x.\n", hr);
+ return NULL;
+ }
+
+ return texture->wined3d_srv;
+}
+
+/* wined3d critical section must be taken by the caller. */
+void d3d9_texture_gen_auto_mipmap(struct d3d9_texture *texture)
+{
+ if (!(texture->flags & D3D9_TEXTURE_MIPMAP_DIRTY))
+ return;
+ d3d9_texture_acquire_shader_resource_view(texture);
+ wined3d_shader_resource_view_generate_mipmaps(texture->wined3d_srv);
+ texture->flags &= ~D3D9_TEXTURE_MIPMAP_DIRTY;
+}
+
+void d3d9_texture_flag_auto_gen_mipmap(struct d3d9_texture *texture)
+{
+ if (texture->usage & D3DUSAGE_AUTOGENMIPMAP)
+ texture->flags |= D3D9_TEXTURE_MIPMAP_DIRTY;
+}
+
static HRESULT WINAPI d3d9_texture_2d_QueryInterface(IDirect3DTexture9 *iface, REFIID riid, void **out)
{
TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
@@ -95,6 +151,8 @@ static ULONG WINAPI d3d9_texture_2d_Release(IDirect3DTexture9 *iface)
struct d3d9_surface *surface;
wined3d_mutex_lock();
+ if (texture->wined3d_srv)
+ wined3d_shader_resource_view_decref(texture->wined3d_srv);
LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry)
{
wined3d_rendertarget_view_decref(surface->wined3d_rtv);
@@ -235,6 +293,9 @@ static DWORD WINAPI d3d9_texture_2d_GetLevelCount(IDirect3DTexture9 *iface)
TRACE("iface %p.\n", iface);
+ if (texture->usage & D3DUSAGE_AUTOGENMIPMAP)
+ return 1;
+
wined3d_mutex_lock();
ret = wined3d_texture_get_level_count(texture->wined3d_texture);
wined3d_mutex_unlock();
@@ -245,35 +306,44 @@ static DWORD WINAPI d3d9_texture_2d_GetLevelCount(IDirect3DTexture9 *iface)
static HRESULT WINAPI d3d9_texture_2d_SetAutoGenFilterType(IDirect3DTexture9 *iface, D3DTEXTUREFILTERTYPE filter_type)
{
struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
- HRESULT hr;
TRACE("iface %p, filter_type %#x.\n", iface, filter_type);
- wined3d_mutex_lock();
- hr = wined3d_texture_set_autogen_filter_type(texture->wined3d_texture,
- (enum wined3d_texture_filter_type)filter_type);
- wined3d_mutex_unlock();
+ if (filter_type == D3DTEXF_NONE)
+ {
+ WARN("Invalid filter type D3DTEXF_NONE specified.\n");
+ return D3DERR_INVALIDCALL;
+ }
+ if (!(texture->usage & D3DUSAGE_AUTOGENMIPMAP))
+ WARN("Called on a texture without the D3DUSAGE_AUTOGENMIPMAP flag.\n");
+ else if (filter_type != D3DTEXF_LINEAR)
+ FIXME("Unsupported filter type %u.\n", filter_type);
- return hr;
+ texture->autogen_filter_type = filter_type;
+ return D3D_OK;
}
static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_2d_GetAutoGenFilterType(IDirect3DTexture9 *iface)
{
struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
- D3DTEXTUREFILTERTYPE ret;
TRACE("iface %p.\n", iface);
- wined3d_mutex_lock();
- ret = (D3DTEXTUREFILTERTYPE)wined3d_texture_get_autogen_filter_type(texture->wined3d_texture);
- wined3d_mutex_unlock();
+ if (!(texture->usage & D3DUSAGE_AUTOGENMIPMAP))
+ WARN("Called on a texture without the D3DUSAGE_AUTOGENMIPMAP flag.\n");
- return ret;
+ return texture->autogen_filter_type;
}
static void WINAPI d3d9_texture_2d_GenerateMipSubLevels(IDirect3DTexture9 *iface)
{
+ struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
+
TRACE("iface %p.\n", iface);
+
+ wined3d_mutex_lock();
+ d3d9_texture_gen_auto_mipmap(texture);
+ wined3d_mutex_unlock();
}
static HRESULT WINAPI d3d9_texture_2d_GetLevelDesc(IDirect3DTexture9 *iface, UINT level, D3DSURFACE_DESC *desc)
@@ -284,12 +354,18 @@ static HRESULT WINAPI d3d9_texture_2d_GetLevelDesc(IDirect3DTexture9 *iface, UIN
TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
+ if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n");
+ return D3DERR_INVALIDCALL;
+ }
+
wined3d_mutex_lock();
if (SUCCEEDED(hr = wined3d_texture_get_sub_resource_desc(texture->wined3d_texture, level, &wined3d_desc)))
{
desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
desc->Type = D3DRTYPE_SURFACE;
- desc->Usage = d3dusage_from_wined3dusage(wined3d_desc.usage);
+ desc->Usage = texture->usage;
desc->Pool = d3dpool_from_wined3daccess(wined3d_desc.access, wined3d_desc.usage);
desc->MultiSampleType = wined3d_desc.multisample_type;
desc->MultiSampleQuality = wined3d_desc.multisample_quality;
@@ -309,6 +385,12 @@ static HRESULT WINAPI d3d9_texture_2d_GetSurfaceLevel(IDirect3DTexture9 *iface,
TRACE("iface %p, level %u, surface %p.\n", iface, level, surface);
+ if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n");
+ return D3DERR_INVALIDCALL;
+ }
+
wined3d_mutex_lock();
if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level)))
{
@@ -333,6 +415,12 @@ static HRESULT WINAPI d3d9_texture_2d_LockRect(IDirect3DTexture9 *iface,
TRACE("iface %p, level %u, locked_rect %p, rect %p, flags %#x.\n",
iface, level, locked_rect, rect, flags);
+ if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n");
+ return D3DERR_INVALIDCALL;
+ }
+
wined3d_mutex_lock();
if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level)))
hr = D3DERR_INVALIDCALL;
@@ -351,6 +439,12 @@ static HRESULT WINAPI d3d9_texture_2d_UnlockRect(IDirect3DTexture9 *iface, UINT
TRACE("iface %p, level %u.\n", iface, level);
+ if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n");
+ return D3DERR_INVALIDCALL;
+ }
+
wined3d_mutex_lock();
if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level)))
hr = D3DERR_INVALIDCALL;
@@ -473,6 +567,8 @@ static ULONG WINAPI d3d9_texture_cube_Release(IDirect3DCubeTexture9 *iface)
TRACE("Releasing child %p.\n", texture->wined3d_texture);
wined3d_mutex_lock();
+ if (texture->wined3d_srv)
+ wined3d_shader_resource_view_decref(texture->wined3d_srv);
LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry)
{
wined3d_rendertarget_view_decref(surface->wined3d_rtv);
@@ -613,6 +709,9 @@ static DWORD WINAPI d3d9_texture_cube_GetLevelCount(IDirect3DCubeTexture9 *iface
TRACE("iface %p.\n", iface);
+ if (texture->usage & D3DUSAGE_AUTOGENMIPMAP)
+ return 1;
+
wined3d_mutex_lock();
ret = wined3d_texture_get_level_count(texture->wined3d_texture);
wined3d_mutex_unlock();
@@ -624,35 +723,44 @@ static HRESULT WINAPI d3d9_texture_cube_SetAutoGenFilterType(IDirect3DCubeTextur
D3DTEXTUREFILTERTYPE filter_type)
{
struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
- HRESULT hr;
TRACE("iface %p, filter_type %#x.\n", iface, filter_type);
- wined3d_mutex_lock();
- hr = wined3d_texture_set_autogen_filter_type(texture->wined3d_texture,
- (enum wined3d_texture_filter_type)filter_type);
- wined3d_mutex_unlock();
+ if (filter_type == D3DTEXF_NONE)
+ {
+ WARN("Invalid filter type D3DTEXF_NONE specified.\n");
+ return D3DERR_INVALIDCALL;
+ }
+ if (!(texture->usage & D3DUSAGE_AUTOGENMIPMAP))
+ WARN("Called on a texture without the D3DUSAGE_AUTOGENMIPMAP flag.\n");
+ else if (filter_type != D3DTEXF_LINEAR)
+ FIXME("Unsupported filter type %u.\n", filter_type);
- return hr;
+ texture->autogen_filter_type = filter_type;
+ return D3D_OK;
}
static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_cube_GetAutoGenFilterType(IDirect3DCubeTexture9 *iface)
{
struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
- D3DTEXTUREFILTERTYPE ret;
TRACE("iface %p.\n", iface);
- wined3d_mutex_lock();
- ret = (D3DTEXTUREFILTERTYPE)wined3d_texture_get_autogen_filter_type(texture->wined3d_texture);
- wined3d_mutex_unlock();
+ if (!(texture->usage & D3DUSAGE_AUTOGENMIPMAP))
+ WARN("Called on a texture without the D3DUSAGE_AUTOGENMIPMAP flag.\n");
- return ret;
+ return texture->autogen_filter_type;
}
static void WINAPI d3d9_texture_cube_GenerateMipSubLevels(IDirect3DCubeTexture9 *iface)
{
+ struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
+
TRACE("iface %p.\n", iface);
+
+ wined3d_mutex_lock();
+ d3d9_texture_gen_auto_mipmap(texture);
+ wined3d_mutex_unlock();
}
static HRESULT WINAPI d3d9_texture_cube_GetLevelDesc(IDirect3DCubeTexture9 *iface, UINT level, D3DSURFACE_DESC *desc)
@@ -664,6 +772,12 @@ static HRESULT WINAPI d3d9_texture_cube_GetLevelDesc(IDirect3DCubeTexture9 *ifac
TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
+ if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n");
+ return D3DERR_INVALIDCALL;
+ }
+
wined3d_mutex_lock();
level_count = wined3d_texture_get_level_count(texture->wined3d_texture);
if (level >= level_count)
@@ -676,7 +790,7 @@ static HRESULT WINAPI d3d9_texture_cube_GetLevelDesc(IDirect3DCubeTexture9 *ifac
{
desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
desc->Type = D3DRTYPE_SURFACE;
- desc->Usage = d3dusage_from_wined3dusage(wined3d_desc.usage);
+ desc->Usage = texture->usage;
desc->Pool = d3dpool_from_wined3daccess(wined3d_desc.access, wined3d_desc.usage);
desc->MultiSampleType = wined3d_desc.multisample_type;
desc->MultiSampleQuality = wined3d_desc.multisample_quality;
@@ -698,6 +812,12 @@ static HRESULT WINAPI d3d9_texture_cube_GetCubeMapSurface(IDirect3DCubeTexture9
TRACE("iface %p, face %#x, level %u, surface %p.\n", iface, face, level, surface);
+ if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n");
+ return D3DERR_INVALIDCALL;
+ }
+
wined3d_mutex_lock();
level_count = wined3d_texture_get_level_count(texture->wined3d_texture);
if (level >= level_count)
@@ -732,6 +852,12 @@ static HRESULT WINAPI d3d9_texture_cube_LockRect(IDirect3DCubeTexture9 *iface,
TRACE("iface %p, face %#x, level %u, locked_rect %p, rect %p, flags %#x.\n",
iface, face, level, locked_rect, rect, flags);
+ if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n");
+ return D3DERR_INVALIDCALL;
+ }
+
wined3d_mutex_lock();
sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, sub_resource_idx)))
@@ -753,6 +879,12 @@ static HRESULT WINAPI d3d9_texture_cube_UnlockRect(IDirect3DCubeTexture9 *iface,
TRACE("iface %p, face %#x, level %u.\n", iface, face, level);
+ if (texture->usage & D3DUSAGE_AUTOGENMIPMAP && level)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP textures have only one accessible level.\n");
+ return D3DERR_INVALIDCALL;
+ }
+
wined3d_mutex_lock();
sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, sub_resource_idx)))
@@ -1014,31 +1146,16 @@ static DWORD WINAPI d3d9_texture_3d_GetLevelCount(IDirect3DVolumeTexture9 *iface
static HRESULT WINAPI d3d9_texture_3d_SetAutoGenFilterType(IDirect3DVolumeTexture9 *iface,
D3DTEXTUREFILTERTYPE filter_type)
{
- struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
- HRESULT hr;
-
TRACE("iface %p, filter_type %#x.\n", iface, filter_type);
- wined3d_mutex_lock();
- hr = wined3d_texture_set_autogen_filter_type(texture->wined3d_texture,
- (enum wined3d_texture_filter_type)filter_type);
- wined3d_mutex_unlock();
-
- return hr;
+ return D3DERR_INVALIDCALL;
}
static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_3d_GetAutoGenFilterType(IDirect3DVolumeTexture9 *iface)
{
- struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
- D3DTEXTUREFILTERTYPE filter_type;
-
TRACE("iface %p.\n", iface);
- wined3d_mutex_lock();
- filter_type = (D3DTEXTUREFILTERTYPE)wined3d_texture_get_autogen_filter_type(texture->wined3d_texture);
- wined3d_mutex_unlock();
-
- return filter_type;
+ return D3DTEXF_NONE;
}
static void WINAPI d3d9_texture_3d_GenerateMipSubLevels(IDirect3DVolumeTexture9 *iface)
@@ -1059,7 +1176,7 @@ static HRESULT WINAPI d3d9_texture_3d_GetLevelDesc(IDirect3DVolumeTexture9 *ifac
{
desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
desc->Type = D3DRTYPE_VOLUME;
- desc->Usage = d3dusage_from_wined3dusage(wined3d_desc.usage);
+ desc->Usage = texture->usage;
desc->Pool = d3dpool_from_wined3daccess(wined3d_desc.access, wined3d_desc.usage);
desc->Width = wined3d_desc.width;
desc->Height = wined3d_desc.height;
@@ -1213,12 +1330,13 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device,
texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl;
d3d9_resource_init(&texture->resource);
list_init(&texture->rtv_list);
+ texture->usage = usage;
desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
desc.format = wined3dformat_from_d3dformat(format);
desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
desc.multisample_quality = 0;
- desc.usage = usage & WINED3DUSAGE_MASK;
+ desc.usage = wined3dusage_from_d3dusage(usage);
desc.usage |= WINED3DUSAGE_TEXTURE;
if (pool == D3DPOOL_SCRATCH)
desc.usage |= WINED3DUSAGE_SCRATCH;
@@ -1234,13 +1352,28 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device,
if (is_gdi_compat_wined3dformat(desc.format))
flags |= WINED3D_TEXTURE_CREATE_GET_DC;
- if (!levels)
+ if (usage & D3DUSAGE_AUTOGENMIPMAP)
+ {
+ if (pool == D3DPOOL_SYSTEMMEM)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP texture can't be in D3DPOOL_SYSTEMMEM, returning D3DERR_INVALIDCALL.\n");
+ return D3DERR_INVALIDCALL;
+ }
+ if (levels && levels != 1)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP texture with %u levels, returning D3DERR_INVALIDCALL.\n", levels);
+ return D3DERR_INVALIDCALL;
+ }
+ flags |= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS;
+ texture->autogen_filter_type = D3DTEXF_LINEAR;
+ levels = 0;
+ }
+ else
{
- if (usage & D3DUSAGE_AUTOGENMIPMAP)
- levels = 1;
- else
- levels = wined3d_log2i(max(width, height)) + 1;
+ texture->autogen_filter_type = D3DTEXF_NONE;
}
+ if (!levels)
+ levels = wined3d_log2i(max(width, height)) + 1;
wined3d_mutex_lock();
hr = wined3d_texture_create(device->wined3d_device, &desc, 1, levels, flags,
@@ -1268,12 +1401,13 @@ HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *devic
texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl;
d3d9_resource_init(&texture->resource);
list_init(&texture->rtv_list);
+ texture->usage = usage;
desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
desc.format = wined3dformat_from_d3dformat(format);
desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
desc.multisample_quality = 0;
- desc.usage = usage & WINED3DUSAGE_MASK;
+ desc.usage = wined3dusage_from_d3dusage(usage);
desc.usage |= WINED3DUSAGE_LEGACY_CUBEMAP | WINED3DUSAGE_TEXTURE;
if (pool == D3DPOOL_SCRATCH)
desc.usage |= WINED3DUSAGE_SCRATCH;
@@ -1289,13 +1423,28 @@ HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *devic
if (is_gdi_compat_wined3dformat(desc.format))
flags |= WINED3D_TEXTURE_CREATE_GET_DC;
- if (!levels)
+ if (usage & D3DUSAGE_AUTOGENMIPMAP)
{
- if (usage & D3DUSAGE_AUTOGENMIPMAP)
- levels = 1;
- else
- levels = wined3d_log2i(edge_length) + 1;
+ if (pool == D3DPOOL_SYSTEMMEM)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP texture can't be in D3DPOOL_SYSTEMMEM, returning D3DERR_INVALIDCALL.\n");
+ return D3DERR_INVALIDCALL;
+ }
+ if (levels && levels != 1)
+ {
+ WARN("D3DUSAGE_AUTOGENMIPMAP texture with %u levels, returning D3DERR_INVALIDCALL.\n", levels);
+ return D3DERR_INVALIDCALL;
+ }
+ flags |= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS;
+ texture->autogen_filter_type = D3DTEXF_LINEAR;
+ levels = 0;
}
+ else
+ {
+ texture->autogen_filter_type = D3DTEXF_NONE;
+ }
+ if (!levels)
+ levels = wined3d_log2i(edge_length) + 1;
wined3d_mutex_lock();
hr = wined3d_texture_create(device->wined3d_device, &desc, 6, levels, flags,
@@ -1322,12 +1471,13 @@ HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *dev
texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl;
d3d9_resource_init(&texture->resource);
list_init(&texture->rtv_list);
+ texture->usage = usage;
desc.resource_type = WINED3D_RTYPE_TEXTURE_3D;
desc.format = wined3dformat_from_d3dformat(format);
desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
desc.multisample_quality = 0;
- desc.usage = usage & WINED3DUSAGE_MASK;
+ desc.usage = wined3dusage_from_d3dusage(usage);
desc.usage |= WINED3DUSAGE_TEXTURE;
if (pool == D3DPOOL_SCRATCH)
desc.usage |= WINED3DUSAGE_SCRATCH;
@@ -1337,13 +1487,13 @@ HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *dev
desc.depth = depth;
desc.size = 0;
- if (!levels)
+ if (usage & D3DUSAGE_AUTOGENMIPMAP)
{
- if (usage & D3DUSAGE_AUTOGENMIPMAP)
- levels = 1;
- else
- levels = wined3d_log2i(max(max(width, height), depth)) + 1;
+ WARN("D3DUSAGE_AUTOGENMIPMAP volume texture is not supported, returning D3DERR_INVALIDCALL.\n");
+ return D3DERR_INVALIDCALL;
}
+ if (!levels)
+ levels = wined3d_log2i(max(max(width, height), depth)) + 1;
wined3d_mutex_lock();
hr = wined3d_texture_create(device->wined3d_device, &desc, 1, levels, 0,
--
2.13.6
More information about the wine-devel
mailing list