diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index e25ab23c2bc..432e28065e0 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -176,6 +176,7 @@ struct ddraw_surface /* Connections to other Objects */ struct ddraw *ddraw; struct wined3d_texture *wined3d_texture; + struct wined3d_texture *draw_texture; unsigned int sub_resource_idx; struct wined3d_rendertarget_view *wined3d_rtv; struct wined3d_private_store private_store; @@ -653,6 +654,23 @@ static inline BOOL ddraw_surface_can_be_lost(const struct ddraw_surface *surface return surface->sysmem_fallback; } +static inline void d3d_surface_sync_textures(struct ddraw_surface *surface, BOOL upload) +{ + if (!surface->draw_texture) + return; + + if (upload) + wined3d_device_copy_sub_resource_region(surface->ddraw->wined3d_device, + wined3d_texture_get_resource(surface->draw_texture), surface->sub_resource_idx, 0, 0, 0, + wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx, NULL, 0); + else + wined3d_device_copy_sub_resource_region(surface->ddraw->wined3d_device, + wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx, 0, 0, 0, + wined3d_texture_get_resource(surface->draw_texture), surface->sub_resource_idx, NULL, 0); +} + +void d3d_device_sync_surfaces(struct d3d_device *device, BOOL upload) DECLSPEC_HIDDEN; + /* Used for generic dumping */ struct flag_info { diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 5e66007213d..e4822e5d29e 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -3427,6 +3427,47 @@ static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT return D3D_OK; } +static void d3d_device_sync_rendertarget(struct d3d_device *device, BOOL upload) +{ + struct wined3d_rendertarget_view *rtv; + + if (device->hardware_device) + return; + + if ((rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0))) + d3d_surface_sync_textures(wined3d_rendertarget_view_get_parent(rtv), upload); + + if ((rtv = wined3d_device_get_depth_stencil_view(device->wined3d_device))) + d3d_surface_sync_textures(wined3d_rendertarget_view_get_parent(rtv), upload); +} + +void d3d_device_sync_surfaces(struct d3d_device *device, BOOL upload) +{ + const struct wined3d_stateblock_state *state = device->stateblock_state; + struct ddraw_surface *surface; + unsigned int i, j; + + if (device->hardware_device) + return; + + d3d_device_sync_rendertarget(device, upload); + + for (i = 0; i < ARRAY_SIZE(state->textures); ++i) + { + if (!state->textures[i]) + continue; + + j = 0; + while ((surface = wined3d_texture_get_sub_resource_parent(state->textures[i], j))) + { + if (!surface->draw_texture) + break; + d3d_surface_sync_textures(surface, upload); + ++j; + } + } +} + static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count, DWORD flags) @@ -3481,7 +3522,9 @@ static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface, wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf)); wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0); wined3d_device_apply_stateblock(device->wined3d_device, device->state); + d3d_device_sync_surfaces(device, TRUE); hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count); + d3d_device_sync_surfaces(device, FALSE); done: wined3d_mutex_unlock(); @@ -3693,7 +3736,9 @@ static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface, wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0); wined3d_stateblock_set_base_vertex_index(device->state, vb_pos / stride); wined3d_device_apply_stateblock(device->wined3d_device, device->state); + d3d_device_sync_surfaces(device, TRUE); hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count); + d3d_device_sync_surfaces(device, FALSE); done: wined3d_mutex_unlock(); @@ -4019,7 +4064,9 @@ static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIM wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0); wined3d_device_apply_stateblock(device->wined3d_device, device->state); + d3d_device_sync_surfaces(device, TRUE); hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, vertex_count); + d3d_device_sync_surfaces(device, FALSE); done: wined3d_mutex_unlock(); @@ -4155,7 +4202,9 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface, wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf)); wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0); wined3d_device_apply_stateblock(device->wined3d_device, device->state); + d3d_device_sync_surfaces(device, TRUE); hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count); + d3d_device_sync_surfaces(device, FALSE); done: wined3d_mutex_unlock(); @@ -4277,7 +4326,9 @@ static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVE /* Now draw the primitives */ wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0); wined3d_device_apply_stateblock(device->wined3d_device, device->state); + d3d_device_sync_surfaces(device, TRUE); hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count); + d3d_device_sync_surfaces(device, FALSE); wined3d_mutex_unlock(); @@ -4431,7 +4482,9 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface, wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0); wined3d_device_apply_stateblock(device->wined3d_device, device->state); + d3d_device_sync_surfaces(device, TRUE); hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count); + d3d_device_sync_surfaces(device, FALSE); wined3d_mutex_unlock(); @@ -4778,7 +4831,7 @@ static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface, TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture); if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE)) - wined3d_texture = surf->wined3d_texture; + wined3d_texture = surf->draw_texture ? surf->draw_texture : surf->wined3d_texture; wined3d_mutex_lock(); wined3d_stateblock_set_texture(device->update_state, stage, wined3d_texture); @@ -5270,7 +5323,9 @@ static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count, wined3d_mutex_lock(); wined3d_device_apply_stateblock(device->wined3d_device, device->state); + d3d_device_sync_rendertarget(device, TRUE); hr = wined3d_device_clear(device->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil); + d3d_device_sync_rendertarget(device, FALSE); wined3d_mutex_unlock(); return hr; @@ -5732,7 +5787,8 @@ static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 return DDERR_INVALIDPARAMS; wined3d_mutex_lock(); - wined3d_resource_preload(wined3d_texture_get_resource(surface->wined3d_texture)); + wined3d_resource_preload(wined3d_texture_get_resource(surface->draw_texture ? surface->draw_texture + : surface->wined3d_texture)); wined3d_mutex_unlock(); return D3D_OK; diff --git a/dlls/ddraw/executebuffer.c b/dlls/ddraw/executebuffer.c index e0a9445bf71..6900059b05f 100644 --- a/dlls/ddraw/executebuffer.c +++ b/dlls/ddraw/executebuffer.c @@ -81,8 +81,10 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer, struct d3d ddraw_find_decl(device->ddraw, D3DFVF_TLVERTEX)); wined3d_device_apply_stateblock(device->wined3d_device, device->state); + d3d_device_sync_surfaces(device, TRUE); for (i = 0; i < count; ++i) wined3d_device_draw_primitive(device->wined3d_device, p[i].wFirst, p[i].wCount); + d3d_device_sync_surfaces(device, FALSE); instr += sizeof(*p) * count; break; @@ -189,7 +191,9 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer, struct d3d ddraw_find_decl(device->ddraw, D3DFVF_TLVERTEX)); wined3d_stateblock_set_index_buffer(device->state, buffer->index_buffer, WINED3DFMT_R16_UINT); wined3d_device_apply_stateblock(device->wined3d_device, device->state); + d3d_device_sync_surfaces(device, TRUE); wined3d_device_draw_indexed_primitive(device->wined3d_device, index_pos, index_count); + d3d_device_sync_surfaces(device, FALSE); buffer->index_pos = index_pos + index_count; break; @@ -310,8 +314,10 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer, struct d3d ddraw_find_decl(device->ddraw, op == D3DPROCESSVERTICES_TRANSFORMLIGHT ? D3DFVF_VERTEX : D3DFVF_LVERTEX)); wined3d_device_apply_stateblock(device->wined3d_device, device->state); + d3d_device_sync_surfaces(device, TRUE); wined3d_device_process_vertices(device->wined3d_device, ci->wStart, ci->wDest, ci->dwCount, buffer->dst_vertex_buffer, NULL, 0, D3DFVF_TLVERTEX); + d3d_device_sync_surfaces(device, FALSE); break; case D3DPROCESSVERTICES_COPY: diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index b910fb6817e..2d5bdf5cad2 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -371,7 +371,7 @@ static void ddraw_surface_add_iface(struct ddraw_surface *surface) wined3d_mutex_lock(); if (surface->wined3d_rtv) wined3d_rendertarget_view_incref(surface->wined3d_rtv); - wined3d_texture_incref(surface->wined3d_texture); + wined3d_texture_incref(surface->draw_texture ? surface->draw_texture : surface->wined3d_texture); wined3d_mutex_unlock(); } } @@ -583,7 +583,7 @@ static void ddraw_surface_cleanup(struct ddraw_surface *surface) if (surface->wined3d_rtv) wined3d_rendertarget_view_decref(surface->wined3d_rtv); - wined3d_texture_decref(surface->wined3d_texture); + wined3d_texture_decref(surface->draw_texture ? surface->draw_texture : surface->wined3d_texture); } static ULONG ddraw_surface_release_iface(struct ddraw_surface *This) @@ -1307,7 +1307,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface * struct ddraw_texture *dst_ddraw_texture, *src_ddraw_texture; struct wined3d_rendertarget_view *tmp_rtv, *src_rtv, *rtv; DDSCAPS caps = {DDSCAPS_FLIP}; - struct wined3d_texture *texture; + struct wined3d_texture *texture, *draw_texture; IDirectDrawSurface *current; void *texture_memory; HRESULT hr; @@ -1337,6 +1337,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface * rtv = wined3d_device_get_rendertarget_view(dst_impl->ddraw->wined3d_device, 0); dst_ddraw_texture = wined3d_texture_get_parent(dst_impl->wined3d_texture); texture_memory = dst_ddraw_texture->texture_memory; + draw_texture = dst_impl->draw_texture; if (src_impl) { @@ -1363,13 +1364,18 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface * wined3d_rendertarget_view_set_parent(src_rtv, dst_impl); dst_impl->wined3d_rtv = src_rtv; wined3d_texture_set_sub_resource_parent(src_impl->wined3d_texture, 0, dst_impl); + if (src_impl->draw_texture) + wined3d_texture_set_sub_resource_parent(src_impl->draw_texture, 0, dst_impl); src_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture); dst_ddraw_texture->texture_memory = src_ddraw_texture->texture_memory; wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), dst_ddraw_texture); + if (src_impl->draw_texture) + wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->draw_texture), dst_ddraw_texture); dst_ddraw_texture = src_ddraw_texture; if (src_impl->sub_resource_idx) ERR("Invalid sub-resource index %u on surface %p.\n", src_impl->sub_resource_idx, src_impl); dst_impl->wined3d_texture = src_impl->wined3d_texture; + dst_impl->draw_texture = src_impl->draw_texture; } else { @@ -1395,13 +1401,18 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface * wined3d_rendertarget_view_set_parent(src_rtv, dst_impl); dst_impl->wined3d_rtv = src_rtv; wined3d_texture_set_sub_resource_parent(src_impl->wined3d_texture, 0, dst_impl); + if (src_impl->draw_texture) + wined3d_texture_set_sub_resource_parent(src_impl->draw_texture, 0, dst_impl); src_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture); dst_ddraw_texture->texture_memory = src_ddraw_texture->texture_memory; wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), dst_ddraw_texture); + if (src_impl->draw_texture) + wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->draw_texture), dst_ddraw_texture); dst_ddraw_texture = src_ddraw_texture; if (src_impl->sub_resource_idx) ERR("Invalid sub-resource index %u on surface %p.\n", src_impl->sub_resource_idx, src_impl); dst_impl->wined3d_texture = src_impl->wined3d_texture; + dst_impl->draw_texture = src_impl->draw_texture; dst_impl = src_impl; } } @@ -1413,9 +1424,14 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface * wined3d_rendertarget_view_set_parent(tmp_rtv, src_impl); src_impl->wined3d_rtv = tmp_rtv; wined3d_texture_set_sub_resource_parent(texture, 0, src_impl); + if (draw_texture) + wined3d_texture_set_sub_resource_parent(draw_texture, 0, src_impl); dst_ddraw_texture->texture_memory = texture_memory; wined3d_resource_set_parent(wined3d_texture_get_resource(texture), dst_ddraw_texture); + if (draw_texture) + wined3d_resource_set_parent(wined3d_texture_get_resource(draw_texture), dst_ddraw_texture); src_impl->wined3d_texture = texture; + src_impl->draw_texture = draw_texture; if (flags & ~(DDFLIP_NOVSYNC | DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4)) { @@ -1491,6 +1507,7 @@ static HRESULT ddraw_surface_blt(struct ddraw_surface *dst_surface, const RECT * struct wined3d_device *wined3d_device = dst_surface->ddraw->wined3d_device; struct wined3d_color colour; DWORD wined3d_flags; + HRESULT hr; if (flags & DDBLT_COLORFILL) { @@ -1503,9 +1520,12 @@ static HRESULT ddraw_surface_blt(struct ddraw_surface *dst_surface, const RECT * return DDERR_INVALIDPARAMS; wined3d_device_apply_stateblock(wined3d_device, dst_surface->ddraw->state); - return wined3d_device_clear_rendertarget_view(wined3d_device, + d3d_surface_sync_textures(dst_surface, TRUE); + hr = wined3d_device_clear_rendertarget_view(wined3d_device, ddraw_surface_get_rendertarget_view(dst_surface), dst_rect, wined3d_flags, &colour, 0.0f, 0); + d3d_surface_sync_textures(dst_surface, FALSE); + return hr; } if (flags & DDBLT_DEPTHFILL) @@ -1519,9 +1539,12 @@ static HRESULT ddraw_surface_blt(struct ddraw_surface *dst_surface, const RECT * return DDERR_INVALIDPARAMS; wined3d_device_apply_stateblock(wined3d_device, dst_surface->ddraw->state); - return wined3d_device_clear_rendertarget_view(wined3d_device, + d3d_surface_sync_textures(dst_surface, TRUE); + hr = wined3d_device_clear_rendertarget_view(wined3d_device, ddraw_surface_get_rendertarget_view(dst_surface), dst_rect, wined3d_flags, NULL, colour.r, 0); + d3d_surface_sync_textures(dst_surface, FALSE); + return hr; } wined3d_flags = flags & ~DDBLT_ASYNC; @@ -2551,6 +2574,9 @@ static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWO { resource = wined3d_texture_get_resource(surface->wined3d_texture); wined3d_resource_set_priority(resource, priority); + if (surface->draw_texture) + wined3d_resource_set_priority(wined3d_texture_get_resource(surface->draw_texture), priority); + hr = DD_OK; } wined3d_mutex_unlock(); @@ -4267,6 +4293,8 @@ static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD Ma } hr = wined3d_texture_set_lod(surface->wined3d_texture, MaxLOD); + if (SUCCEEDED(hr) && surface->draw_texture) + hr = wined3d_texture_set_lod(surface->draw_texture, MaxLOD); wined3d_mutex_unlock(); return hr; @@ -4736,6 +4764,14 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, return hr_ddraw_from_wined3d(hr); } + if (surface->draw_texture && FAILED(hr = wined3d_texture_update_desc(surface->draw_texture, + surface->sub_resource_idx, width, height, format_id, WINED3D_MULTISAMPLE_NONE, 0, NULL, 0))) + { + ERR("Failed to update surface desc for draw_texture, hr %#x.\n", hr); + wined3d_mutex_unlock(); + return hr_ddraw_from_wined3d(hr); + } + if (DDSD->dwFlags & DDSD_WIDTH) surface->surface_desc.dwWidth = width; if (DDSD->dwFlags & DDSD_PITCH) @@ -4842,6 +4878,18 @@ static HRESULT WINAPI ddraw_surface1_GetPalette(IDirectDrawSurface *iface, IDire return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette); } +static HRESULT ddraw_surface_set_wined3d_textures_colour_key(struct ddraw_surface *surface, DWORD flags, + struct wined3d_color_key *color_key) +{ + HRESULT hr; + + hr = wined3d_texture_set_color_key(surface->wined3d_texture, flags, color_key); + if (surface->draw_texture && SUCCEEDED(hr)) + hr = wined3d_texture_set_color_key(surface->draw_texture, flags, color_key); + + return hr; +} + static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD flags, DDCOLORKEY *color_key) { DDCOLORKEY fixed_color_key; @@ -4916,7 +4964,7 @@ static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD } if (surface->is_complex_root) - hr = wined3d_texture_set_color_key(surface->wined3d_texture, flags, + hr = ddraw_surface_set_wined3d_textures_colour_key(surface, flags, color_key ? (struct wined3d_color_key *)&fixed_color_key : NULL); wined3d_mutex_unlock(); @@ -5832,6 +5880,9 @@ static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *paren wined3d_private_store_cleanup(&surface->private_store); + if (surface->draw_texture) + wined3d_texture_decref(surface->wined3d_texture); + heap_free(surface); } @@ -5902,6 +5953,84 @@ static HRESULT ddraw_surface_reserve_memory(struct wined3d_texture *wined3d_text return hr; } +static HRESULT ddraw_surface_create_wined3d_texture(DDSURFACEDESC2 *desc, struct wined3d_device *wined3d_device, + const struct wined3d_resource_desc *wined3d_desc, unsigned int layers, unsigned int levels, + struct ddraw_texture *texture, struct wined3d_texture **wined3d_texture) +{ + struct wined3d_resource_desc draw_texture_desc; + struct wined3d_texture *draw_texture; + struct ddraw_surface *parent; + unsigned int bind_flags; + unsigned int i; + HRESULT hr; + + bind_flags = 0; + if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP) + || (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)) + bind_flags |= WINED3D_BIND_SHADER_RESOURCE; + + if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) + bind_flags |= WINED3D_BIND_DEPTH_STENCIL; + else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) + bind_flags |= WINED3D_BIND_RENDER_TARGET; + + if (!bind_flags || (wined3d_desc->access & WINED3D_RESOURCE_ACCESS_GPU && !(bind_flags & ~wined3d_desc->bind_flags))) + goto no_draw_texture; + + draw_texture_desc = *wined3d_desc; + draw_texture_desc.bind_flags = bind_flags; + draw_texture_desc.access = WINED3D_RESOURCE_ACCESS_GPU; + + if (FAILED(hr = wined3d_texture_create(wined3d_device, &draw_texture_desc, layers, + levels, 0, NULL, texture, &ddraw_texture_wined3d_parent_ops, &draw_texture))) + { + WARN("Failed to create draw texture, hr %#x.\n", hr); + goto no_draw_texture; + } + wined3d_texture_decref(draw_texture); + + /* Some applications assume surfaces will always be mapped at the same + * address. Some of those also assume that this address is valid even when + * the surface isn't mapped, and that updates done this way will be + * visible on the screen. The game Nox is such an application, + * Commandos: Behind Enemy Lines is another. Setting + * WINED3D_TEXTURE_CREATE_GET_DC_LENIENT will ensure this. */ + if (FAILED(hr = wined3d_texture_create(wined3d_device, wined3d_desc, layers, levels, + WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, NULL, &ddraw_null_wined3d_parent_ops, + wined3d_texture))) + { + parent = wined3d_texture_get_sub_resource_parent(draw_texture, 0); + if (texture->version == 7) + IDirectDrawSurface7_Release(&parent->IDirectDrawSurface7_iface); + else if (texture->version == 4) + IDirectDrawSurface4_Release(&parent->IDirectDrawSurface4_iface); + else + IDirectDrawSurface_Release(&parent->IDirectDrawSurface_iface); + return hr; + } + wined3d_resource_set_parent(wined3d_texture_get_resource(*wined3d_texture), texture); + for (i = 0; i < layers * levels; ++i) + { + parent = wined3d_texture_get_sub_resource_parent(draw_texture, i); + assert(parent->wined3d_texture == draw_texture); + parent->draw_texture = draw_texture; + parent->wined3d_texture = *wined3d_texture; + wined3d_texture_set_sub_resource_parent(*wined3d_texture, i, parent); + wined3d_texture_incref(*wined3d_texture); + } + wined3d_texture_decref(*wined3d_texture); + TRACE("Surface %p, created draw_texture %p, wined3d_texture %p.\n", + wined3d_texture_get_sub_resource_parent(draw_texture, 0), draw_texture, wined3d_texture); + return D3D_OK; + +no_draw_texture: + if (SUCCEEDED(hr = wined3d_texture_create(wined3d_device, wined3d_desc, layers, levels, + WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, texture, &ddraw_texture_wined3d_parent_ops, + wined3d_texture))) + wined3d_texture_decref(*wined3d_texture); + return hr; +} + HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc, struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version) { @@ -6399,15 +6528,8 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ layers = 6; } - /* Some applications assume surfaces will always be mapped at the same - * address. Some of those also assume that this address is valid even when - * the surface isn't mapped, and that updates done this way will be - * visible on the screen. The game Nox is such an application, - * Commandos: Behind Enemy Lines is another. Setting - * WINED3D_TEXTURE_CREATE_GET_DC_LENIENT will ensure this. */ - if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, layers, levels, - WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, texture, - &ddraw_texture_wined3d_parent_ops, &wined3d_texture))) + if (FAILED(hr = ddraw_surface_create_wined3d_texture(desc, ddraw->wined3d_device, &wined3d_desc, layers, levels, + texture, &wined3d_texture))) { WARN("Failed to create wined3d texture, hr %#x.\n", hr); heap_free(texture); @@ -6415,23 +6537,23 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ } root = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0); - wined3d_texture_decref(wined3d_texture); + root->is_complex_root = TRUE; root->sysmem_fallback = sysmem_fallback; texture->root = root; wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device); if (desc->dwFlags & DDSD_CKDESTOVERLAY) - wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY, + ddraw_surface_set_wined3d_textures_colour_key(root, DDCKEY_DESTOVERLAY, (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay); if (desc->dwFlags & DDSD_CKDESTBLT) - wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT, + ddraw_surface_set_wined3d_textures_colour_key(root, DDCKEY_DESTBLT, (struct wined3d_color_key *)&desc->ddckCKDestBlt); if (desc->dwFlags & DDSD_CKSRCOVERLAY) - wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY, + ddraw_surface_set_wined3d_textures_colour_key(root, DDCKEY_SRCOVERLAY, (struct wined3d_color_key *)&desc->ddckCKSrcOverlay); if (desc->dwFlags & DDSD_CKSRCBLT) - wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT, + ddraw_surface_set_wined3d_textures_colour_key(root, DDCKEY_SRCBLT, (struct wined3d_color_key *)&desc->ddckCKSrcBlt); for (i = 0; i < layers; ++i) @@ -6540,9 +6662,8 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ desc->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER; desc->u5.dwBackBufferCount = 0; - if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, 1, 1, - WINED3D_TEXTURE_CREATE_GET_DC_LENIENT, NULL, texture, - &ddraw_texture_wined3d_parent_ops, &wined3d_texture))) + if (FAILED(hr = ddraw_surface_create_wined3d_texture(desc, ddraw->wined3d_device, &wined3d_desc, 1, 1, + texture, &wined3d_texture))) { heap_free(texture); hr = hr_ddraw_from_wined3d(hr); @@ -6551,7 +6672,6 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ last = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0); last->sysmem_fallback = sysmem_fallback; - wined3d_texture_decref(wined3d_texture); texture->root = last; wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device); @@ -6573,7 +6693,6 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ hr = hr_ddraw_from_wined3d(hr); goto fail; } - *attach = last; attach = &last->complex_array[0]; } @@ -6690,12 +6809,14 @@ static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops = struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddraw_surface *surface) { + struct wined3d_texture *wined3d_texture; HRESULT hr; if (surface->wined3d_rtv) return surface->wined3d_rtv; - if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(surface->wined3d_texture, + wined3d_texture = surface->draw_texture ? surface->draw_texture : surface->wined3d_texture; + if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(wined3d_texture, surface->sub_resource_idx, surface, &ddraw_view_wined3d_parent_ops, &surface->wined3d_rtv))) { ERR("Failed to create rendertarget view, hr %#x.\n", hr);