From: Paul Gofman Subject: [PATCH v2 2/6] ddraw: Create a separate texture for drawing with bindable sysmem surfaces. Message-Id: <20210225232014.988118-2-pgofman@codeweavers.com> Date: Fri, 26 Feb 2021 02:20:10 +0300 In-Reply-To: <20210225232014.988118-1-pgofman@codeweavers.com> References: <20210225232014.988118-1-pgofman@codeweavers.com> Signed-off-by: Paul Gofman --- dlls/ddraw/ddraw_private.h | 55 ++++++++++++ dlls/ddraw/device.c | 18 ++-- dlls/ddraw/surface.c | 167 +++++++++++++++++++++++++++++++------ dlls/ddraw/tests/ddraw1.c | 1 - dlls/ddraw/tests/ddraw2.c | 1 - dlls/ddraw/tests/ddraw4.c | 1 - dlls/ddraw/tests/ddraw7.c | 7 +- 7 files changed, 207 insertions(+), 43 deletions(-) diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index e25ab23c2bc..c6fb8d5f3a3 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -155,6 +155,9 @@ void DDRAW_Convert_DDSCAPS_1_To_2(const DDSCAPS *pIn, DDSCAPS2 *pOut) DECLSPEC_H void DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(const DDDEVICEIDENTIFIER2 *pIn, DDDEVICEIDENTIFIER *pOut) DECLSPEC_HIDDEN; struct wined3d_vertex_declaration *ddraw_find_decl(struct ddraw *ddraw, DWORD fvf) DECLSPEC_HIDDEN; +#define DDRAW_SURFACE_LOCATION_DEFAULT 0x00000001 +#define DDRAW_SURFACE_LOCATION_DRAW 0x00000002 + struct ddraw_surface { /* IUnknown fields */ @@ -175,7 +178,9 @@ struct ddraw_surface /* Connections to other Objects */ struct ddraw *ddraw; + unsigned int texture_location; 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 +658,56 @@ static inline BOOL ddraw_surface_can_be_lost(const struct ddraw_surface *surface return surface->sysmem_fallback; } +#define DDRAW_SURFACE_READ 0x00000001 +#define DDRAW_SURFACE_WRITE 0x00000002 +#define DDRAW_SURFACE_RW (DDRAW_SURFACE_READ | DDRAW_SURFACE_WRITE) + +static inline struct wined3d_texture *ddraw_surface_get_default_texture(struct ddraw_surface *surface, unsigned int flags) +{ + if (surface->draw_texture) + { + if (flags & DDRAW_SURFACE_READ && !(surface->texture_location & DDRAW_SURFACE_LOCATION_DEFAULT)) + { + 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); + surface->texture_location |= DDRAW_SURFACE_LOCATION_DEFAULT; + } + + if (flags & DDRAW_SURFACE_WRITE) + surface->texture_location = DDRAW_SURFACE_LOCATION_DEFAULT; + } + return surface->wined3d_texture; +} + +static inline struct wined3d_texture *ddraw_surface_get_draw_texture(struct ddraw_surface *surface, unsigned int flags) +{ + if (!surface->draw_texture) + return surface->wined3d_texture; + + if (flags & DDRAW_SURFACE_READ && !(surface->texture_location & DDRAW_SURFACE_LOCATION_DRAW)) + { + 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); + surface->texture_location |= DDRAW_SURFACE_LOCATION_DRAW; + } + + if (flags & DDRAW_SURFACE_WRITE) + surface->texture_location = DDRAW_SURFACE_LOCATION_DRAW; + + return surface->draw_texture; +} + +static inline struct wined3d_texture *ddraw_surface_get_any_texture(struct ddraw_surface *surface, unsigned int flags) +{ + if (surface->texture_location & DDRAW_SURFACE_LOCATION_DEFAULT) + return ddraw_surface_get_default_texture(surface, flags); + + assert(surface->texture_location & DDRAW_SURFACE_LOCATION_DRAW); + return ddraw_surface_get_draw_texture(surface, flags); +} + /* Used for generic dumping */ struct flag_info { diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 5e66007213d..ea81972064e 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -1898,7 +1898,7 @@ static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface, return DDERR_INVALIDCAPS; } - if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) + if (device->hardware_device && !(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) { WARN("Surface %p is not in video memory.\n", target_impl); wined3d_mutex_unlock(); @@ -1974,7 +1974,7 @@ static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface, return DDERR_INVALIDPIXELFORMAT; } - if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) + if (device->hardware_device && !(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) { WARN("Surface %p is not in video memory.\n", target_impl); IDirectDrawSurface4_AddRef(target); @@ -2023,7 +2023,7 @@ static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface, return DDERR_INVALIDPIXELFORMAT; } - if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) + if (device->hardware_device && !(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) { WARN("Surface %p is not in video memory.\n", target_impl); IDirectDrawSurface_AddRef(target); @@ -6951,6 +6951,12 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw, c device->hardware_device = IsEqualGUID(&IID_IDirect3DTnLHalDevice, guid) || IsEqualGUID(&IID_IDirect3DHALDevice, guid); + if (device->hardware_device && !(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) + { + WARN("Surface %p is not in video memory.\n", target); + return D3DERR_SURFACENOTINVIDMEM; + } + if (outer_unknown) device->outer_unknown = outer_unknown; else @@ -7038,12 +7044,6 @@ HRESULT d3d_device_create(struct ddraw *ddraw, const GUID *guid, struct ddraw_su return DDERR_OUTOFMEMORY; } - if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) - { - WARN("Surface %p is not in video memory.\n", target); - return D3DERR_SURFACENOTINVIDMEM; - } - if (ddraw->d3ddevice) { FIXME("Only one Direct3D device per DirectDraw object supported.\n"); diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index b910fb6817e..1e1a1a721c5 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -56,8 +56,8 @@ static BOOL ddraw_gdi_is_front(struct ddraw *ddraw) HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RECT *rect, BOOL read, unsigned int swap_interval) { + struct wined3d_texture *dst_texture, *src_texture; struct ddraw *ddraw = surface->ddraw; - struct wined3d_texture *dst_texture; HDC surface_dc, screen_dc; int x, y, w, h; HRESULT hr; @@ -112,8 +112,9 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, else dst_texture = ddraw->wined3d_frontbuffer; - if (SUCCEEDED(hr = wined3d_texture_blt(dst_texture, 0, rect, surface->wined3d_texture, - surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT)) && swap_interval) + if (SUCCEEDED(hr = wined3d_texture_blt(dst_texture, 0, rect, + ddraw_surface_get_any_texture(surface, DDRAW_SURFACE_READ), surface->sub_resource_idx, rect, 0, + NULL, WINED3D_TEXF_POINT)) && swap_interval) { hr = wined3d_swapchain_present(ddraw->wined3d_swapchain, rect, rect, NULL, swap_interval, 0); ddraw->flags |= DDRAW_SWAPPED; @@ -121,7 +122,9 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, return hr; } - if (FAILED(hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, &surface_dc))) + src_texture = ddraw_surface_get_default_texture(surface, DDRAW_SURFACE_READ); + + if (FAILED(hr = wined3d_texture_get_dc(src_texture, surface->sub_resource_idx, &surface_dc))) { ERR("Failed to get surface DC, hr %#x.\n", hr); return hr; @@ -131,7 +134,7 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, if (!(screen_dc = GetDC(NULL))) { - wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, surface_dc); + wined3d_texture_release_dc(src_texture, surface->sub_resource_idx, surface_dc); ERR("Failed to get screen DC.\n"); return E_FAIL; } @@ -144,7 +147,7 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, surface_dc, x, y, SRCCOPY); ReleaseDC(NULL, screen_dc); - wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, surface_dc); + wined3d_texture_release_dc(src_texture, surface->sub_resource_idx, surface_dc); if (!ret) { @@ -1057,9 +1060,9 @@ static HRESULT surface_lock(struct ddraw_surface *surface, if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) hr = ddraw_surface_update_frontbuffer(surface, rect, TRUE, 0); if (SUCCEEDED(hr)) - hr = wined3d_resource_map(wined3d_texture_get_resource(surface->wined3d_texture), - surface->sub_resource_idx, &map_desc, rect ? &box : NULL, - wined3dmapflags_from_ddrawmapflags(flags)); + hr = wined3d_resource_map(wined3d_texture_get_resource + (ddraw_surface_get_default_texture(surface, DDRAW_SURFACE_RW)), surface->sub_resource_idx, + &map_desc, rect ? &box : NULL, wined3dmapflags_from_ddrawmapflags(flags)); if (FAILED(hr)) { wined3d_mutex_unlock(); @@ -1235,7 +1238,8 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Unlock(IDirectDrawSurface TRACE("iface %p, data %p.\n", iface, data); wined3d_mutex_lock(); - hr = wined3d_resource_unmap(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx); + hr = wined3d_resource_unmap(wined3d_texture_get_resource + (ddraw_surface_get_default_texture(surface, 0)), surface->sub_resource_idx); if (SUCCEEDED(hr) && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE, 0); wined3d_mutex_unlock(); @@ -1307,7 +1311,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 +1341,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 +1368,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 +1405,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 +1428,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)) { @@ -1503,6 +1523,7 @@ 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); + ddraw_surface_get_draw_texture(dst_surface, dst_rect ? DDRAW_SURFACE_RW : DDRAW_SURFACE_WRITE); return wined3d_device_clear_rendertarget_view(wined3d_device, ddraw_surface_get_rendertarget_view(dst_surface), dst_rect, wined3d_flags, &colour, 0.0f, 0); @@ -1519,6 +1540,7 @@ 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); + ddraw_surface_get_draw_texture(dst_surface, dst_rect ? DDRAW_SURFACE_RW : DDRAW_SURFACE_WRITE); return wined3d_device_clear_rendertarget_view(wined3d_device, ddraw_surface_get_rendertarget_view(dst_surface), dst_rect, wined3d_flags, NULL, colour.r, 0); @@ -1534,8 +1556,9 @@ static HRESULT ddraw_surface_blt(struct ddraw_surface *dst_surface, const RECT * if (!(flags & DDBLT_ASYNC)) wined3d_flags |= WINED3D_BLT_SYNCHRONOUS; - return wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx, dst_rect, - src_surface->wined3d_texture, src_surface->sub_resource_idx, src_rect, wined3d_flags, fx, filter); + return wined3d_texture_blt(ddraw_surface_get_any_texture(dst_surface, DDRAW_SURFACE_RW), + dst_surface->sub_resource_idx, dst_rect, ddraw_surface_get_any_texture(src_surface, DDRAW_SURFACE_READ), + src_surface->sub_resource_idx, src_rect, wined3d_flags, fx, filter); } static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, const RECT *dst_rect_in, @@ -2305,7 +2328,7 @@ static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *dc) else if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE, 0); if (SUCCEEDED(hr)) - hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, dc); + hr = wined3d_texture_get_dc(ddraw_surface_get_default_texture(surface, DDRAW_SURFACE_RW), surface->sub_resource_idx, dc); if (SUCCEEDED(hr)) { @@ -2401,7 +2424,8 @@ static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC h { hr = DDERR_NODC; } - else if (SUCCEEDED(hr = wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, hdc))) + else if (SUCCEEDED(hr = wined3d_texture_release_dc(ddraw_surface_get_default_texture(surface, 0), + surface->sub_resource_idx, hdc))) { surface->dc = NULL; if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) @@ -2551,6 +2575,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 +4294,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; @@ -4376,8 +4405,9 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltFast(IDirectDrawSurfac if (src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE, 0); if (SUCCEEDED(hr)) - hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect, - src_impl->wined3d_texture, src_impl->sub_resource_idx, src_rect, flags, NULL, WINED3D_TEXF_POINT); + hr = wined3d_texture_blt(ddraw_surface_get_any_texture(dst_impl, DDRAW_SURFACE_RW), + dst_impl->sub_resource_idx, &dst_rect, ddraw_surface_get_any_texture(src_impl,DDRAW_SURFACE_READ), + src_impl->sub_resource_idx, src_rect, flags, NULL, WINED3D_TEXF_POINT); if (SUCCEEDED(hr) && (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE, 0); wined3d_mutex_unlock(); @@ -4736,6 +4766,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 +4880,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 +4966,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(); @@ -5293,8 +5343,8 @@ static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTextu wined3d_mutex_lock(); - dst_resource = wined3d_texture_get_resource(dst_surface->wined3d_texture); - src_resource = wined3d_texture_get_resource(src_surface->wined3d_texture); + dst_resource = wined3d_texture_get_resource(ddraw_surface_get_default_texture(dst_surface, DDRAW_SURFACE_WRITE)); + src_resource = wined3d_texture_get_resource(ddraw_surface_get_default_texture(src_surface, DDRAW_SURFACE_READ)); if (((src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) != (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)) @@ -5832,6 +5882,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->draw_texture); + heap_free(surface); } @@ -5902,6 +5955,65 @@ static HRESULT ddraw_surface_reserve_memory(struct wined3d_texture *wined3d_text return hr; } +static void ddraw_surface_create_draw_texture(struct ddraw_surface *surface) +{ + DDSURFACEDESC2 *desc = &surface->surface_desc; + struct wined3d_resource *draw_texture_resource; + struct wined3d_resource_desc wined3d_desc; + unsigned int i, layer_count, level_count; + struct wined3d_texture *draw_texture; + struct ddraw_surface *parent; + unsigned int bind_flags; + HRESULT hr; + + if (!(desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)) + return; + + 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) + return; + + layer_count = surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP ? 6 : 1; + level_count = wined3d_texture_get_level_count(surface->wined3d_texture); + + draw_texture_resource = wined3d_texture_get_resource(surface->wined3d_texture); + wined3d_resource_get_desc(draw_texture_resource, &wined3d_desc); + + wined3d_desc.bind_flags = bind_flags; + wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU; + + if (FAILED(hr = wined3d_texture_create(surface->ddraw->wined3d_device, &wined3d_desc, layer_count, + level_count, 0, NULL, NULL, + &ddraw_null_wined3d_parent_ops, &draw_texture))) + { + WARN("Failed to create wined3d texture, hr %#x.\n", hr); + return; + } + + wined3d_resource_set_parent(draw_texture_resource, wined3d_texture_get_parent(surface->wined3d_texture)); + + i = 0; + while ((parent = wined3d_texture_get_sub_resource_parent(surface->wined3d_texture, i))) + { + wined3d_texture_set_sub_resource_parent(draw_texture, i, parent); + wined3d_texture_incref(parent->draw_texture = draw_texture); + ++i; + } + assert(surface->draw_texture); + + wined3d_texture_decref(draw_texture); + TRACE("Surface %p, created draw_texture %p.\n", surface, draw_texture); +} + HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc, struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version) { @@ -6416,22 +6528,24 @@ 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); + ddraw_surface_create_draw_texture(root); + 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) @@ -6573,7 +6687,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ hr = hr_ddraw_from_wined3d(hr); goto fail; } - + ddraw_surface_create_draw_texture(last); *attach = last; attach = &last->complex_array[0]; } @@ -6663,6 +6777,7 @@ void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, wined3d_texture_incref(surface->wined3d_texture = wined3d_texture); surface->sub_resource_idx = sub_resource_idx; *parent_ops = &ddraw_surface_wined3d_parent_ops; + surface->texture_location = DDRAW_SURFACE_LOCATION_DEFAULT; wined3d_private_store_init(&surface->private_store); } @@ -6695,7 +6810,7 @@ struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddr if (surface->wined3d_rtv) return surface->wined3d_rtv; - if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(surface->wined3d_texture, + if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(ddraw_surface_get_draw_texture(surface, 0), surface->sub_resource_idx, surface, &ddraw_view_wined3d_parent_ops, &surface->wined3d_rtv))) { ERR("Failed to create rendertarget view, hr %#x.\n", hr); diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c index 57bc622e48b..e75a9fac0a8 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c @@ -4580,7 +4580,6 @@ static void test_rt_caps(const GUID *device_guid) } hr = IDirectDrawSurface_QueryInterface(surface, device_guid, (void **)&device); - todo_wine_if(software_device && test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM) ok((!software_device && hr == test_data[i].create_device_hr) || (software_device && (hr == (test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM ? DD_OK : test_data[i].create_device_hr))), diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index d2889aa05d7..b882589f2ad 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -5053,7 +5053,6 @@ static void test_rt_caps(const GUID *device_guid) hr = IDirect3D2_CreateDevice(d3d, device_guid, surface, &device); - todo_wine_if(software_device && test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM) ok((!software_device && hr == test_data[i].create_device_hr) || (software_device && (hr == (test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM ? DD_OK : test_data[i].create_device_hr))), diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index 6e003fbfb7e..42936fd7c74 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -6706,7 +6706,6 @@ static void test_rt_caps(const GUID *device_guid) hr = IDirect3D3_CreateDevice(d3d, device_guid, surface, &device, NULL); - todo_wine_if(software_device && test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM) ok((!software_device && hr == test_data[i].create_device_hr) || (software_device && (hr == (test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM ? DD_OK : test_data[i].create_device_hr))), diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 559d13d035c..7e83d26d6db 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -6419,10 +6419,8 @@ static void test_rt_caps(const GUID *device_guid) expected_caps = test_data[i].caps_out[software_device] ? test_data[i].caps_out[software_device] : test_data[i].caps_out[0]; - todo_wine_if(test_data[i].caps_out[software_device] - && surface_desc.ddsCaps.dwCaps == test_data[i].caps_out[0]) ok(surface_desc.ddsCaps.dwCaps == expected_caps - || broken(surface_desc.ddsCaps.dwCaps == test_data[i].caps_out[0]), + || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out[0], "Got unexpected caps %#x, test %u, software_device %u.\n", surface_desc.ddsCaps.dwCaps, i, software_device); } @@ -6437,7 +6435,6 @@ static void test_rt_caps(const GUID *device_guid) surface_desc.ddsCaps.dwCaps2, test_data[i].caps2_out, i, software_device); hr = IDirect3D7_CreateDevice(d3d, device_guid, surface, &device); - todo_wine_if(software_device && test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM) ok((!software_device && hr == test_data[i].create_device_hr) || (software_device && (hr == (test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM ? DD_OK : test_data[i].create_device_hr))), @@ -6492,7 +6489,7 @@ static void test_rt_caps(const GUID *device_guid) hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0); ok(hr == test_data[i].set_rt_hr || (software_device && hr == DDERR_NOPALETTEATTACHED) - || broken(hr == test_data[i].alternative_set_rt_hr), + || hr == test_data[i].alternative_set_rt_hr, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device); if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT) -- 2.29.2