d3d9: Handle D3DUSAGE_AUTOGENMIPMAP textures entirely in d3d9.

Signed-off-by: Matteo Bruni <mbruni@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Matteo Bruni 2018-02-13 01:00:42 +01:00 committed by Alexandre Julliard
parent 478c8b0eb1
commit 3d6eb8cf1d
5 changed files with 313 additions and 66 deletions

View file

@ -40,8 +40,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;
@ -93,6 +101,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;
@ -199,6 +210,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,
@ -208,6 +223,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
{
@ -248,9 +265,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;
@ -318,4 +332,9 @@ static inline unsigned int wined3daccess_from_d3dpool(D3DPOOL pool, unsigned int
}
}
static inline DWORD wined3dusage_from_d3dusage(unsigned int usage)
{
return usage & WINED3DUSAGE_MASK & ~WINED3DUSAGE_AUTOGENMIPMAP;
}
#endif /* __WINE_D3D9_PRIVATE_H */

View file

@ -815,6 +815,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)
@ -876,6 +878,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)
{
@ -1425,6 +1436,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))
@ -1448,6 +1462,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;
@ -1566,6 +1582,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();
@ -1622,6 +1640,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();
@ -1704,6 +1724,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;
@ -1824,6 +1846,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)
{
@ -1848,6 +1883,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;
@ -2243,6 +2280,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;
@ -2483,6 +2527,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)
{
@ -2499,9 +2553,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;
@ -2526,10 +2583,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;
@ -2628,9 +2688,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();
@ -2758,6 +2821,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);
@ -2769,6 +2833,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;

View file

@ -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;

View file

@ -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);

View file

@ -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 (usage & D3DUSAGE_AUTOGENMIPMAP)
levels = 1;
else
levels = wined3d_log2i(max(width, height)) + 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(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,