From: Zebediah Figura zfigura@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52954 --- dlls/d3d9/d3d9_private.h | 8 +++- dlls/d3d9/device.c | 36 ++++++++++++++++-- dlls/d3d9/tests/visual.c | 2 +- dlls/d3d9/texture.c | 80 ++++++++++++++++++++++++++++------------ 4 files changed, 97 insertions(+), 29 deletions(-)
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h index 4169ab74973..fe13f679db4 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -125,6 +125,7 @@ struct d3d9_device HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wined3d *wined3d, UINT adapter, D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters, D3DDISPLAYMODEEX *mode) DECLSPEC_HIDDEN; +void d3d9_device_upload_managed_textures(struct d3d9_device *device);
struct d3d9_resource { @@ -219,7 +220,7 @@ struct d3d9_texture { IDirect3DBaseTexture9 IDirect3DBaseTexture9_iface; struct d3d9_resource resource; - struct wined3d_texture *wined3d_texture; + struct wined3d_texture *wined3d_texture, *draw_texture; struct d3d9_device *parent_device; struct list rtv_list; DWORD usage; @@ -235,6 +236,11 @@ HRESULT d3d9_texture_3d_init(struct d3d9_texture *texture, struct d3d9_device *d HRESULT d3d9_texture_cube_init(struct d3d9_texture *texture, struct d3d9_device *device, unsigned int edge_length, unsigned int level_count, DWORD usage, D3DFORMAT format, D3DPOOL pool);
+static inline struct wined3d_texture *d3d9_texture_get_draw_texture(struct d3d9_texture *texture) +{ + return texture->draw_texture ? texture->draw_texture : texture->wined3d_texture; +} + 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; diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 5f7b3f03ae3..878eed0412d 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -988,7 +988,7 @@ static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource) IUnknown *parent;
wined3d_resource_get_desc(resource, &desc); - if (desc.access & WINED3D_RESOURCE_ACCESS_CPU) + if ((desc.access & WINED3D_RESOURCE_ACCESS_CPU) || (desc.usage & WINED3DUSAGE_MANAGED)) return D3D_OK;
if (desc.resource_type != WINED3D_RTYPE_TEXTURE_2D) @@ -1724,6 +1724,12 @@ static HRESULT WINAPI d3d9_device_UpdateTexture(IDirect3DDevice9Ex *iface, src_impl = unsafe_impl_from_IDirect3DBaseTexture9(src_texture); dst_impl = unsafe_impl_from_IDirect3DBaseTexture9(dst_texture);
+ if (src_impl->draw_texture || dst_impl->draw_texture) + { + WARN("Source or destination is managed; returning D3DERR_INVALIDCALL.\n"); + return D3DERR_INVALIDCALL; + } + wined3d_mutex_lock(); hr = wined3d_device_update_texture(device->wined3d_device, src_impl->wined3d_texture, dst_impl->wined3d_texture); @@ -2638,7 +2644,7 @@ static HRESULT WINAPI d3d9_device_SetTexture(IDirect3DDevice9Ex *iface, DWORD st
wined3d_mutex_lock(); wined3d_stateblock_set_texture(device->update_state, stage, - texture_impl ? texture_impl->wined3d_texture : NULL); + texture_impl ? d3d9_texture_get_draw_texture(texture_impl) : NULL); if (!device->recording) { if (stage < D3D9_MAX_TEXTURE_UNITS) @@ -3004,6 +3010,25 @@ static HRESULT d3d9_device_upload_sysmem_index_buffer(struct d3d9_device *device return S_OK; }
+void d3d9_device_upload_managed_textures(struct d3d9_device *device) +{ + const struct wined3d_stateblock_state *state = device->stateblock_state; + unsigned int i; + + for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i) + { + struct wined3d_texture *wined3d_texture = state->textures[i]; + struct d3d9_texture *d3d9_texture; + + if (!wined3d_texture) + continue; + d3d9_texture = wined3d_texture_get_parent(wined3d_texture); + if (d3d9_texture->draw_texture) + wined3d_device_update_texture(device->wined3d_device, + d3d9_texture->wined3d_texture, d3d9_texture->draw_texture); + } +} + static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count) { @@ -3022,6 +3047,7 @@ static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, } wined3d_device_apply_stateblock(device->wined3d_device, device->state); vertex_count = vertex_count_from_primitive_count(primitive_type, primitive_count); + d3d9_device_upload_managed_textures(device); d3d9_device_upload_sysmem_vertex_buffers(device, 0, start_vertex, vertex_count); d3d9_generate_auto_mipmaps(device); wined3d_device_context_set_primitive_type(device->immediate_context, @@ -3059,6 +3085,7 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface return D3DERR_INVALIDCALL; } index_count = vertex_count_from_primitive_count(primitive_type, primitive_count); + d3d9_device_upload_managed_textures(device); d3d9_device_upload_sysmem_vertex_buffers(device, base_vertex_idx, min_vertex_idx, vertex_count); d3d9_generate_auto_mipmaps(device); wined3d_device_context_set_primitive_type(device->immediate_context, @@ -3113,6 +3140,7 @@ static HRESULT WINAPI d3d9_device_DrawPrimitiveUP(IDirect3DDevice9Ex *iface, goto done;
d3d9_generate_auto_mipmaps(device); + d3d9_device_upload_managed_textures(device); wined3d_device_context_set_primitive_type(device->immediate_context, wined3d_primitive_type_from_d3d(primitive_type), 0); wined3d_device_apply_stateblock(device->wined3d_device, device->state); @@ -3174,11 +3202,11 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitiveUP(IDirect3DDevice9Ex *ifa hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer.buffer, 0, vertex_stride); if (FAILED(hr)) goto done; - - d3d9_generate_auto_mipmaps(device); wined3d_stateblock_set_index_buffer(device->state, device->index_buffer.buffer, wined3dformat_from_d3dformat(index_format));
+ d3d9_generate_auto_mipmaps(device); + d3d9_device_upload_managed_textures(device); wined3d_device_apply_stateblock(device->wined3d_device, device->state); wined3d_device_context_set_primitive_type(device->immediate_context, wined3d_primitive_type_from_d3d(primitive_type), 0); diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 5c31d25f2eb..d8fa298d6c7 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -19678,7 +19678,7 @@ static void add_dirty_rect_test(void) color = getPixelColor(device, 320, 240); ok(color_match(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color); color = getPixelColor(device, 1, 1); - todo_wine ok(color_match(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color); + ok(color_match(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color); hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ok(SUCCEEDED(hr), "Failed to present, hr %#lx.\n", hr);
diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c index b69a7eb9848..e19de0213ae 100644 --- a/dlls/d3d9/texture.c +++ b/dlls/d3d9/texture.c @@ -38,7 +38,7 @@ static ULONG d3d9_texture_incref(struct d3d9_texture *texture) { wined3d_rendertarget_view_incref(surface->wined3d_rtv); } - wined3d_texture_incref(texture->wined3d_texture); + wined3d_texture_incref(d3d9_texture_get_draw_texture(texture)); wined3d_mutex_unlock(); }
@@ -61,7 +61,7 @@ static ULONG d3d9_texture_decref(struct d3d9_texture *texture) 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); - wined3d_texture_decref(texture->wined3d_texture); + wined3d_texture_decref(d3d9_texture_get_draw_texture(texture)); wined3d_mutex_unlock();
/* Release the device last, as it may cause the device to be destroyed. */ @@ -73,7 +73,7 @@ static ULONG d3d9_texture_decref(struct d3d9_texture *texture) static void d3d9_texture_preload(struct d3d9_texture *texture) { wined3d_mutex_lock(); - wined3d_resource_preload(wined3d_texture_get_resource(texture->wined3d_texture)); + wined3d_resource_preload(wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture))); wined3d_mutex_unlock(); }
@@ -122,7 +122,7 @@ static struct wined3d_shader_resource_view *d3d9_texture_acquire_shader_resource 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, + wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)), texture, &d3d9_srv_wined3d_parent_ops, &texture->wined3d_srv))) { ERR("Failed to create shader resource view, hr %#x.\n", hr); @@ -138,6 +138,7 @@ 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); + d3d9_device_upload_managed_textures(texture->parent_device); wined3d_device_context_generate_mipmaps(texture->parent_device->immediate_context, texture->wined3d_srv); texture->flags &= ~D3D9_TEXTURE_MIPMAP_DIRTY; } @@ -233,7 +234,7 @@ static DWORD WINAPI d3d9_texture_2d_SetPriority(IDirect3DTexture9 *iface, DWORD TRACE("iface %p, priority %u.\n", iface, priority);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)); ret = wined3d_resource_set_priority(resource, priority); wined3d_mutex_unlock();
@@ -249,7 +250,7 @@ static DWORD WINAPI d3d9_texture_2d_GetPriority(IDirect3DTexture9 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)); ret = wined3d_resource_get_priority(resource); wined3d_mutex_unlock();
@@ -280,7 +281,7 @@ static DWORD WINAPI d3d9_texture_2d_SetLOD(IDirect3DTexture9 *iface, DWORD lod) TRACE("iface %p, lod %u.\n", iface, lod);
wined3d_mutex_lock(); - ret = wined3d_texture_set_lod(texture->wined3d_texture, lod); + ret = wined3d_texture_set_lod(d3d9_texture_get_draw_texture(texture), lod); wined3d_mutex_unlock();
return ret; @@ -294,7 +295,7 @@ static DWORD WINAPI d3d9_texture_2d_GetLOD(IDirect3DTexture9 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - ret = wined3d_texture_get_lod(texture->wined3d_texture); + ret = wined3d_texture_get_lod(d3d9_texture_get_draw_texture(texture)); wined3d_mutex_unlock();
return ret; @@ -607,7 +608,7 @@ static DWORD WINAPI d3d9_texture_cube_SetPriority(IDirect3DCubeTexture9 *iface, TRACE("iface %p, priority %u.\n", iface, priority);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)); ret = wined3d_resource_set_priority(resource, priority); wined3d_mutex_unlock();
@@ -623,7 +624,7 @@ static DWORD WINAPI d3d9_texture_cube_GetPriority(IDirect3DCubeTexture9 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)); ret = wined3d_resource_get_priority(resource); wined3d_mutex_unlock();
@@ -654,7 +655,7 @@ static DWORD WINAPI d3d9_texture_cube_SetLOD(IDirect3DCubeTexture9 *iface, DWORD TRACE("iface %p, lod %u.\n", iface, lod);
wined3d_mutex_lock(); - ret = wined3d_texture_set_lod(texture->wined3d_texture, lod); + ret = wined3d_texture_set_lod(d3d9_texture_get_draw_texture(texture), lod); wined3d_mutex_unlock();
return ret; @@ -668,7 +669,7 @@ static DWORD WINAPI d3d9_texture_cube_GetLOD(IDirect3DCubeTexture9 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - ret = wined3d_texture_get_lod(texture->wined3d_texture); + ret = wined3d_texture_get_lod(d3d9_texture_get_draw_texture(texture)); wined3d_mutex_unlock();
return ret; @@ -1007,7 +1008,7 @@ static DWORD WINAPI d3d9_texture_3d_SetPriority(IDirect3DVolumeTexture9 *iface, TRACE("iface %p, priority %u.\n", iface, priority);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)); ret = wined3d_resource_set_priority(resource, priority); wined3d_mutex_unlock();
@@ -1023,7 +1024,7 @@ static DWORD WINAPI d3d9_texture_3d_GetPriority(IDirect3DVolumeTexture9 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)); ret = wined3d_resource_get_priority(resource); wined3d_mutex_unlock();
@@ -1054,7 +1055,7 @@ static DWORD WINAPI d3d9_texture_3d_SetLOD(IDirect3DVolumeTexture9 *iface, DWORD TRACE("iface %p, lod %u.\n", iface, lod);
wined3d_mutex_lock(); - ret = wined3d_texture_set_lod(texture->wined3d_texture, lod); + ret = wined3d_texture_set_lod(d3d9_texture_get_draw_texture(texture), lod); wined3d_mutex_unlock();
return ret; @@ -1068,7 +1069,7 @@ static DWORD WINAPI d3d9_texture_3d_GetLOD(IDirect3DVolumeTexture9 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - ret = wined3d_texture_get_lod(texture->wined3d_texture); + ret = wined3d_texture_get_lod(d3d9_texture_get_draw_texture(texture)); wined3d_mutex_unlock();
return ret; @@ -1256,6 +1257,10 @@ struct d3d9_texture *unsafe_impl_from_IDirect3DBaseTexture9(IDirect3DBaseTexture static void STDMETHODCALLTYPE d3d9_texture_wined3d_object_destroyed(void *parent) { struct d3d9_texture *texture = parent; + + /* If the texture was managed, release the sysmem copy now. */ + if (texture->draw_texture) + wined3d_texture_decref(texture->wined3d_texture); d3d9_resource_cleanup(&texture->resource); heap_free(texture); } @@ -1286,7 +1291,7 @@ static HRESULT d3d9_texture_init(struct d3d9_texture *texture, struct d3d9_devic
if (desc->resource_type == WINED3D_RTYPE_TEXTURE_2D && is_gdi_compat_wined3dformat(desc->format)) flags |= WINED3D_TEXTURE_CREATE_GET_DC; - if (pool == D3DPOOL_SYSTEMMEM) + if (pool == D3DPOOL_SYSTEMMEM || pool == D3DPOOL_MANAGED) flags |= WINED3D_TEXTURE_CREATE_RECORD_DIRTY_REGIONS;
if (usage & D3DUSAGE_WRITEONLY) @@ -1341,14 +1346,43 @@ static HRESULT d3d9_texture_init(struct d3d9_texture *texture, struct d3d9_devic level_count = wined3d_log2i(max(max(desc->width, desc->height), desc->depth)) + 1;
wined3d_mutex_lock(); - hr = wined3d_texture_create(device->wined3d_device, desc, layer_count, level_count, flags, - NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture); - wined3d_mutex_unlock(); - if (FAILED(hr)) + if (pool == D3DPOOL_MANAGED) + { + struct wined3d_resource_desc managed_desc = *desc; + + managed_desc.access = WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; + managed_desc.bind_flags = 0; + if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &managed_desc, layer_count, level_count, flags, + NULL, texture, &d3d9_null_wined3d_parent_ops, &texture->wined3d_texture))) + { + wined3d_mutex_unlock(); + WARN("Failed to create sysmem texture, hr %#x.\n", hr); + return hr; + } + + managed_desc.access = WINED3D_RESOURCE_ACCESS_GPU; + managed_desc.bind_flags = desc->bind_flags; + flags &= WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS; + if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &managed_desc, layer_count, level_count, flags, + NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->draw_texture))) + { + wined3d_texture_decref(texture->wined3d_texture); + wined3d_mutex_unlock(); + WARN("Failed to create draw texture, hr %#x.\n", hr); + return hr; + } + } + else { - WARN("Failed to create wined3d texture, hr %#x.\n", hr); - return hr; + if (FAILED(hr = wined3d_texture_create(device->wined3d_device, desc, layer_count, level_count, flags, + NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture))) + { + wined3d_mutex_unlock(); + WARN("Failed to create wined3d texture, hr %#x.\n", hr); + return hr; + } } + wined3d_mutex_unlock();
texture->parent_device = device; IDirect3DDevice9Ex_AddRef(&texture->parent_device->IDirect3DDevice9Ex_iface);