1
0
mirror of https://github.com/wine-mirror/wine synced 2024-07-08 03:45:57 +00:00

ddraw: Create the second texture for system memory bindable surfaces.

Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2021-03-11 16:33:55 +03:00 committed by Alexandre Julliard
parent b5a531d9b0
commit d2d9f713df
4 changed files with 229 additions and 28 deletions

View File

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

View File

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

View File

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

View File

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