From: Zebediah Figura zfigura@codeweavers.com
--- dlls/d3d8/d3d8_private.h | 7 +++- dlls/d3d8/device.c | 33 +++++++++++++++- dlls/d3d8/tests/visual.c | 2 +- dlls/d3d8/texture.c | 82 +++++++++++++++++++++++++++++----------- 4 files changed, 98 insertions(+), 26 deletions(-)
diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h index 976f545d556..340f4f2d07d 100644 --- a/dlls/d3d8/d3d8_private.h +++ b/dlls/d3d8/d3d8_private.h @@ -242,7 +242,7 @@ struct d3d8_texture { IDirect3DBaseTexture8 IDirect3DBaseTexture8_iface; struct d3d8_resource resource; - struct wined3d_texture *wined3d_texture; + struct wined3d_texture *wined3d_texture, *draw_texture; IDirect3DDevice8 *parent_device; struct list rtv_list; }; @@ -254,6 +254,11 @@ HRESULT d3d8_texture_3d_init(struct d3d8_texture *texture, struct d3d8_device *d HRESULT d3d8_texture_cube_init(struct d3d8_texture *texture, struct d3d8_device *device, unsigned int edge_length, unsigned int level_count, DWORD usage, D3DFORMAT format, D3DPOOL pool);
+static inline struct wined3d_texture *d3d8_texture_get_draw_texture(struct d3d8_texture *texture) +{ + return texture->draw_texture ? texture->draw_texture : texture->wined3d_texture; +} + struct d3d8_texture *unsafe_impl_from_IDirect3DBaseTexture8(IDirect3DBaseTexture8 *iface) DECLSPEC_HIDDEN;
struct d3d8_vertex_declaration diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 11b3b6cc941..b0be9007ea2 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -899,7 +899,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) @@ -1432,6 +1432,12 @@ static HRESULT WINAPI d3d8_device_UpdateTexture(IDirect3DDevice8 *iface, src_impl = unsafe_impl_from_IDirect3DBaseTexture8(src_texture); dst_impl = unsafe_impl_from_IDirect3DBaseTexture8(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); @@ -2249,7 +2255,7 @@ static HRESULT WINAPI d3d8_device_SetTexture(IDirect3DDevice8 *iface, DWORD stag
wined3d_mutex_lock(); wined3d_stateblock_set_texture(device->update_state, stage, - texture_impl ? texture_impl->wined3d_texture : NULL); + texture_impl ? d3d8_texture_get_draw_texture(texture_impl) : NULL); wined3d_mutex_unlock();
return D3D_OK; @@ -2487,6 +2493,25 @@ static HRESULT d3d8_device_upload_sysmem_index_buffer(struct d3d8_device *device return S_OK; }
+static void d3d8_device_upload_managed_textures(struct d3d8_device *device) +{ + const struct wined3d_stateblock_state *state = device->stateblock_state; + unsigned int i; + + for (i = 0; i < WINED3D_MAX_FRAGMENT_SAMPLERS; ++i) + { + struct wined3d_texture *wined3d_texture = state->textures[i]; + struct d3d8_texture *d3d8_texture; + + if (!wined3d_texture) + continue; + d3d8_texture = wined3d_texture_get_parent(wined3d_texture); + if (d3d8_texture->draw_texture) + wined3d_device_update_texture(device->wined3d_device, + d3d8_texture->wined3d_texture, d3d8_texture->draw_texture); + } +} + static HRESULT WINAPI d3d8_device_DrawPrimitive(IDirect3DDevice8 *iface, D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count) { @@ -2498,6 +2523,7 @@ static HRESULT WINAPI d3d8_device_DrawPrimitive(IDirect3DDevice8 *iface,
vertex_count = vertex_count_from_primitive_count(primitive_type, primitive_count); wined3d_mutex_lock(); + d3d8_device_upload_managed_textures(device); d3d8_device_upload_sysmem_vertex_buffers(device, start_vertex, vertex_count); wined3d_device_context_set_primitive_type(device->immediate_context, wined3d_primitive_type_from_d3d(primitive_type), 0); @@ -2529,6 +2555,7 @@ static HRESULT WINAPI d3d8_device_DrawIndexedPrimitive(IDirect3DDevice8 *iface, return D3D_OK; } base_vertex_index = device->stateblock_state->base_vertex_index; + d3d8_device_upload_managed_textures(device); d3d8_device_upload_sysmem_vertex_buffers(device, base_vertex_index + min_vertex_idx, vertex_count); wined3d_device_context_set_primitive_type(device->immediate_context, wined3d_primitive_type_from_d3d(primitive_type), 0); @@ -2574,6 +2601,7 @@ static HRESULT WINAPI d3d8_device_DrawPrimitiveUP(IDirect3DDevice8 *iface, if (FAILED(hr)) goto done;
+ d3d8_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); @@ -2628,6 +2656,7 @@ static HRESULT WINAPI d3d8_device_DrawIndexedPrimitiveUP(IDirect3DDevice8 *iface base_vertex_idx = vb_pos / vertex_stride - min_vertex_idx; wined3d_stateblock_set_base_vertex_index(device->state, base_vertex_idx);
+ d3d8_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); diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c index 1f6e91609db..2f9462f2d44 100644 --- a/dlls/d3d8/tests/visual.c +++ b/dlls/d3d8/tests/visual.c @@ -5773,7 +5773,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 = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL); ok(SUCCEEDED(hr), "Failed to present, hr %#lx.\n", hr);
diff --git a/dlls/d3d8/texture.c b/dlls/d3d8/texture.c index fea5d9a4ce1..ca366206999 100644 --- a/dlls/d3d8/texture.c +++ b/dlls/d3d8/texture.c @@ -36,7 +36,7 @@ static ULONG d3d8_texture_incref(struct d3d8_texture *texture) { wined3d_rendertarget_view_incref(surface->wined3d_rtv); } - wined3d_texture_incref(texture->wined3d_texture); + wined3d_texture_incref(d3d8_texture_get_draw_texture(texture)); wined3d_mutex_unlock(); }
@@ -59,7 +59,7 @@ static ULONG d3d8_texture_decref(struct d3d8_texture *texture) { wined3d_rendertarget_view_decref(surface->wined3d_rtv); } - wined3d_texture_decref(texture->wined3d_texture); + wined3d_texture_decref(d3d8_texture_get_draw_texture(texture)); wined3d_mutex_unlock();
/* Release the device last, as it may cause the device to be destroyed. */ @@ -70,8 +70,13 @@ static ULONG d3d8_texture_decref(struct d3d8_texture *texture)
static void d3d8_texture_preload(struct d3d8_texture *texture) { + struct d3d8_device *device = impl_from_IDirect3DDevice8(texture->parent_device); + wined3d_mutex_lock(); - wined3d_resource_preload(wined3d_texture_get_resource(texture->wined3d_texture)); + if (texture->draw_texture) + wined3d_device_update_texture(device->wined3d_device, texture->wined3d_texture, texture->draw_texture); + else + wined3d_resource_preload(wined3d_texture_get_resource(texture->wined3d_texture)); wined3d_mutex_unlock(); }
@@ -175,7 +180,7 @@ static DWORD WINAPI d3d8_texture_2d_SetPriority(IDirect3DTexture8 *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(d3d8_texture_get_draw_texture(texture)); ret = wined3d_resource_set_priority(resource, priority); wined3d_mutex_unlock();
@@ -191,7 +196,7 @@ static DWORD WINAPI d3d8_texture_2d_GetPriority(IDirect3DTexture8 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d8_texture_get_draw_texture(texture)); ret = wined3d_resource_get_priority(resource); wined3d_mutex_unlock();
@@ -222,7 +227,7 @@ static DWORD WINAPI d3d8_texture_2d_SetLOD(IDirect3DTexture8 *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(d3d8_texture_get_draw_texture(texture), lod); wined3d_mutex_unlock();
return ret; @@ -236,7 +241,7 @@ static DWORD WINAPI d3d8_texture_2d_GetLOD(IDirect3DTexture8 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - ret = wined3d_texture_get_lod(texture->wined3d_texture); + ret = wined3d_texture_get_lod(d3d8_texture_get_draw_texture(texture)); wined3d_mutex_unlock();
return ret; @@ -476,7 +481,7 @@ static DWORD WINAPI d3d8_texture_cube_SetPriority(IDirect3DCubeTexture8 *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(d3d8_texture_get_draw_texture(texture)); ret = wined3d_resource_set_priority(resource, priority); wined3d_mutex_unlock();
@@ -492,7 +497,7 @@ static DWORD WINAPI d3d8_texture_cube_GetPriority(IDirect3DCubeTexture8 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d8_texture_get_draw_texture(texture)); ret = wined3d_resource_get_priority(resource); wined3d_mutex_unlock();
@@ -523,7 +528,7 @@ static DWORD WINAPI d3d8_texture_cube_SetLOD(IDirect3DCubeTexture8 *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(d3d8_texture_get_draw_texture(texture), lod); wined3d_mutex_unlock();
return ret; @@ -537,7 +542,7 @@ static DWORD WINAPI d3d8_texture_cube_GetLOD(IDirect3DCubeTexture8 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - ret = wined3d_texture_get_lod(texture->wined3d_texture); + ret = wined3d_texture_get_lod(d3d8_texture_get_draw_texture(texture)); wined3d_mutex_unlock();
return ret; @@ -800,7 +805,7 @@ static DWORD WINAPI d3d8_texture_3d_SetPriority(IDirect3DVolumeTexture8 *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(d3d8_texture_get_draw_texture(texture)); ret = wined3d_resource_set_priority(resource, priority); wined3d_mutex_unlock();
@@ -816,7 +821,7 @@ static DWORD WINAPI d3d8_texture_3d_GetPriority(IDirect3DVolumeTexture8 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - resource = wined3d_texture_get_resource(texture->wined3d_texture); + resource = wined3d_texture_get_resource(d3d8_texture_get_draw_texture(texture)); ret = wined3d_resource_get_priority(resource); wined3d_mutex_unlock();
@@ -847,7 +852,7 @@ static DWORD WINAPI d3d8_texture_3d_SetLOD(IDirect3DVolumeTexture8 *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(d3d8_texture_get_draw_texture(texture), lod); wined3d_mutex_unlock();
return ret; @@ -861,7 +866,7 @@ static DWORD WINAPI d3d8_texture_3d_GetLOD(IDirect3DVolumeTexture8 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - ret = wined3d_texture_get_lod(texture->wined3d_texture); + ret = wined3d_texture_get_lod(d3d8_texture_get_draw_texture(texture)); wined3d_mutex_unlock();
return ret; @@ -1031,6 +1036,10 @@ struct d3d8_texture *unsafe_impl_from_IDirect3DBaseTexture8(IDirect3DBaseTexture static void STDMETHODCALLTYPE d3d8_texture_wined3d_object_destroyed(void *parent) { struct d3d8_texture *texture = parent; + + /* If the texture was managed, release the sysmem copy now. */ + if (texture->draw_texture) + wined3d_texture_decref(texture->wined3d_texture); d3d8_resource_cleanup(&texture->resource); heap_free(texture); } @@ -1052,18 +1061,47 @@ static HRESULT d3d8_texture_init(struct d3d8_texture *texture, struct d3d8_devic if (!level_count) level_count = wined3d_log2i(max(max(desc->width, desc->height), desc->depth)) + 1;
- if (pool == D3DPOOL_SYSTEMMEM) + if (pool == D3DPOOL_SYSTEMMEM || pool == D3DPOOL_MANAGED) flags |= WINED3D_TEXTURE_CREATE_RECORD_DIRTY_REGIONS;
wined3d_mutex_lock(); - hr = wined3d_texture_create(device->wined3d_device, desc, layer_count, level_count, flags, - NULL, texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture); - wined3d_mutex_unlock(); - if (FAILED(hr)) + + if (pool == D3DPOOL_MANAGED) { - WARN("Failed to create wined3d texture, hr %#x.\n", hr); - return hr; + 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, &d3d8_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; + if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &managed_desc, layer_count, level_count, 0, + NULL, texture, &d3d8_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 + { + if (FAILED(hr = wined3d_texture_create(device->wined3d_device, desc, layer_count, level_count, flags, + NULL, texture, &d3d8_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->IDirect3DDevice8_iface; IDirect3DDevice8_AddRef(texture->parent_device);