From: Jan Sikorski Subject: [PATCH 2/2] wined3d: Handle typeless multisample resolve. Message-Id: <20210224104035.41465-2-jsikorski@codeweavers.com> Date: Wed, 24 Feb 2021 11:40:35 +0100 In-Reply-To: <20210224104035.41465-1-jsikorski@codeweavers.com> References: <20210224104035.41465-1-jsikorski@codeweavers.com> Signed-off-by: Jan Sikorski --- dlls/d3d11/tests/d3d11.c | 18 +- dlls/d3d8/device.c | 6 +- dlls/d3d9/device.c | 4 +- dlls/ddraw/device.c | 2 +- dlls/ddraw/surface.c | 6 +- dlls/wined3d/arb_program_shader.c | 8 +- dlls/wined3d/cs.c | 10 +- dlls/wined3d/device.c | 12 +- dlls/wined3d/glsl_shader.c | 8 +- dlls/wined3d/surface.c | 12 +- dlls/wined3d/swapchain.c | 4 +- dlls/wined3d/texture.c | 440 +++++++++++++++++++++++++++--- dlls/wined3d/wined3d_private.h | 6 +- include/wine/wined3d.h | 2 +- 14 files changed, 448 insertions(+), 90 deletions(-) diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index aa500634fe1..ebe7486972b 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -30296,13 +30296,13 @@ static void test_multisample_resolve2(void) 4, { 0, 0, 0, 0x3f } }, { FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, - 4, { 0, 0, 0, 0x3f }, TRUE }, + 4, { 0, 0, 0, 0x3f } }, { FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, - 4, { 0, 0, 0, 0x3f }, TRUE }, + 4, { 0, 0, 0, 0x3f } }, { FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, - 4, { 0, 0, 0, 0x3f }, TRUE }, + 4, { 0, 0, 0, 0x3f } }, { FALSE, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, 2, { 0, 0x80 } }, @@ -30314,7 +30314,7 @@ static void test_multisample_resolve2(void) 2, { 0xff, 0x37 } }, { FALSE, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, - 2, { 0x66, 0x36 }, TRUE }, + 2, { 0x66, 0x36 } }, { FALSE, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_FLOAT, 2, { 0xbd, 0xc8 } }, @@ -30323,16 +30323,16 @@ static void test_multisample_resolve2(void) 4, { 0x80, 0x19, 0x19, 0xff } }, { FALSE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - 4, { 0x99, 0x23, 0x23, 0xff }, TRUE }, + 4, { 0x99, 0x23, 0x23, 0xff } }, { FALSE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - 4, { 0x99, 0x23, 0x23, 0xff }, TRUE }, + 4, { 0x99, 0x23, 0x23, 0xff } }, { FALSE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_SNORM, - 4, { 0, 0x19, 0x19, 0xff }, TRUE }, + 4, { 0, 0x19, 0x19, 0xff } }, { FALSE, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, - 4, { 0x3f, 0xc, 0xc, 0x7f }, TRUE }, + 4, { 0x3f, 0xc, 0xc, 0x7f } }, { TRUE, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, 4, { 0x3f, 0, 0, 0x40 }, TRUE }, @@ -30487,7 +30487,7 @@ static void test_multisample_resolve(void) DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - &color, 0xffe1bc89, TRUE}, + &color, 0xffe1bc89}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index f4bdb748275..93fc55db73c 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -1395,7 +1395,7 @@ static HRESULT WINAPI d3d8_device_CopyRects(IDirect3DDevice8 *iface, { RECT rect = {0, 0, src_w, src_h}; wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, &rect, - src->wined3d_texture, src->sub_resource_idx, &rect, 0, NULL, WINED3D_TEXF_POINT); + src->wined3d_texture, src->sub_resource_idx, &rect, 0, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN); } else { @@ -1411,7 +1411,7 @@ static HRESULT WINAPI d3d8_device_CopyRects(IDirect3DDevice8 *iface, dst_points[i].x + w, dst_points[i].y + h}; wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, &dst_rect, - src->wined3d_texture, src->sub_resource_idx, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT); + src->wined3d_texture, src->sub_resource_idx, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN); } } else @@ -1423,7 +1423,7 @@ static HRESULT WINAPI d3d8_device_CopyRects(IDirect3DDevice8 *iface, RECT dst_rect = {0, 0, w, h}; wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, &dst_rect, - src->wined3d_texture, src->sub_resource_idx, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT); + src->wined3d_texture, src->sub_resource_idx, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN); } } } diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index fec631e0e67..ec6839751af 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -1773,7 +1773,7 @@ static HRESULT WINAPI d3d9_device_GetRenderTargetData(IDirect3DDevice9Ex *iface, hr = D3DERR_INVALIDCALL; else hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect, - rt_impl->wined3d_texture, rt_impl->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT); + rt_impl->wined3d_texture, rt_impl->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN); wined3d_mutex_unlock(); return hr; @@ -1874,7 +1874,7 @@ static HRESULT WINAPI d3d9_device_StretchRect(IDirect3DDevice9Ex *iface, IDirect } hr = wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, dst_rect, src->wined3d_texture, - src->sub_resource_idx, src_rect, 0, NULL, wined3d_texture_filter_type_from_d3d(filter)); + src->sub_resource_idx, src_rect, 0, NULL, wined3d_texture_filter_type_from_d3d(filter), WINED3DFMT_UNKNOWN); if (hr == WINEDDERR_INVALIDRECT) hr = D3DERR_INVALIDCALL; if (SUCCEEDED(hr) && dst->texture) diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 4d24c22650e..c187be02980 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -6123,7 +6123,7 @@ static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *d RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h}; if (FAILED(hr = wined3d_texture_blt(dst_level->wined3d_texture, dst_level->sub_resource_idx, &dst_rect, - src_level->wined3d_texture, src_level->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT))) + src_level->wined3d_texture, src_level->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN))) ERR("Blit failed, hr %#x.\n", hr); ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 0ca19d4f8a5..686fc267c43 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -113,7 +113,7 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, 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) + surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN)) && swap_interval) { hr = wined3d_swapchain_present(ddraw->wined3d_swapchain, rect, rect, NULL, swap_interval, 0); ddraw->flags |= DDRAW_SWAPPED; @@ -1535,7 +1535,7 @@ static HRESULT ddraw_surface_blt(struct ddraw_surface *dst_surface, const RECT * 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); + src_surface->wined3d_texture, src_surface->sub_resource_idx, src_rect, wined3d_flags, fx, filter, WINED3DFMT_UNKNOWN); } static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, const RECT *dst_rect_in, @@ -4377,7 +4377,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltFast(IDirectDrawSurfac 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); + src_impl->wined3d_texture, src_impl->sub_resource_idx, src_rect, flags, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN); 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(); diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index af8f2a508fa..bd23f0830b4 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -7792,7 +7792,7 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter) + const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_texture_gl *src_texture_gl = wined3d_texture_gl(src_texture); struct wined3d_context_gl *context_gl = wined3d_context_gl(context); @@ -7805,10 +7805,10 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl RECT s, d; TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, " - "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s.\n", + "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s, format_id %s.\n", blitter, op, context, src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect), dst_texture, dst_sub_resource_idx, wined3d_debug_location(dst_location), - wine_dbgstr_rect(dst_rect), color_key, debug_d3dtexturefiltertype(filter)); + wine_dbgstr_rect(dst_rect), color_key, debug_d3dtexturefiltertype(filter), debug_d3dformat(format_id)); if (!arbfp_blit_supported(op, context, &src_texture->resource, src_location, &dst_texture->resource, dst_location)) @@ -7821,7 +7821,7 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl TRACE("Forwarding to blitter %p.\n", next); return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, color_key, filter); + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, color_key, filter, format_id); } arbfp_blitter = CONTAINING_RECORD(blitter, struct wined3d_arbfp_blitter, blitter); diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 0385b8f4693..635a030e46b 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -411,6 +411,7 @@ struct wined3d_cs_blt_sub_resource DWORD flags; struct wined3d_blt_fx fx; enum wined3d_texture_filter_type filter; + enum wined3d_format_id format_id; }; struct wined3d_cs_update_sub_resource @@ -549,7 +550,7 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) /* Blit the logo into the upper left corner of the back-buffer. */ wined3d_texture_blt(back_buffer, 0, &rect, logo_texture, 0, - &rect, WINED3D_BLT_SRC_CKEY, NULL, WINED3D_TEXF_POINT); + &rect, WINED3D_BLT_SRC_CKEY, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN); } if ((cursor_texture = swapchain->device->cursor_texture) @@ -574,7 +575,7 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) MapWindowPoints(NULL, swapchain->win_handle, (POINT *)&dst_rect, 2); if (wined3d_clip_blit(&clip_rect, &dst_rect, &src_rect)) wined3d_texture_blt(back_buffer, 0, &dst_rect, cursor_texture, 0, - &src_rect, WINED3D_BLT_ALPHA_TEST, NULL, WINED3D_TEXF_POINT); + &src_rect, WINED3D_BLT_ALPHA_TEST, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN); } swapchain->swapchain_ops->swapchain_present(swapchain, &op->src_rect, &op->dst_rect, op->swap_interval, op->flags); @@ -2368,7 +2369,7 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void * { if (FAILED(texture2d_blt(texture_from_resource(op->dst_resource), op->dst_sub_resource_idx, &op->dst_box, texture_from_resource(op->src_resource), op->src_sub_resource_idx, - &op->src_box, op->flags, &op->fx, op->filter))) + &op->src_box, op->flags, &op->fx, op->filter, op->format_id))) FIXME("Blit failed.\n"); } @@ -2381,7 +2382,7 @@ error: void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, const struct wined3d_box *dst_box, struct wined3d_resource *src_resource, unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, DWORD flags, - const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) + const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_cs_blt_sub_resource *op; @@ -2399,6 +2400,7 @@ void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_reso else memset(&op->fx, 0, sizeof(op->fx)); op->filter = filter; + op->format_id = format_id; wined3d_resource_acquire(dst_resource); if (src_resource) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 1fd5f4b012e..53922efc078 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4316,7 +4316,7 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, wined3d_cs_emit_blt_sub_resource(device->cs, &dst_texture->resource, j * dst_level_count + i, &box, &src_texture->resource, j * src_level_count + i + src_skip_levels, &box, - 0, NULL, WINED3D_TEXF_POINT); + 0, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN); } } } @@ -4362,7 +4362,7 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, wined3d_cs_emit_blt_sub_resource(device->cs, &dst_texture->resource, i * dst_level_count + j, &box, &src_texture->resource, i * src_level_count + src_level, &box, - 0, NULL, WINED3D_TEXF_POINT); + 0, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN); } } } @@ -4594,7 +4594,7 @@ void CDECL wined3d_device_copy_resource(struct wined3d_device *device, { wined3d_box_set(&src_box, 0, 0, src_resource->size, 1, 0, 1); wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, 0, &src_box, - src_resource, 0, &src_box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT); + src_resource, 0, &src_box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN); return; } @@ -4619,7 +4619,7 @@ void CDECL wined3d_device_copy_resource(struct wined3d_device *device, unsigned int idx = j * dst_texture->level_count + i; wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, idx, &dst_box, - src_resource, idx, &src_box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT); + src_resource, idx, &src_box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN); } } } @@ -4780,7 +4780,7 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev } wined3d_cs_emit_blt_sub_resource(device->cs, dst_resource, dst_sub_resource_idx, &dst_box, - src_resource, src_sub_resource_idx, src_box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT); + src_resource, src_sub_resource_idx, src_box, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN); return WINED3D_OK; } @@ -4895,7 +4895,7 @@ void CDECL wined3d_device_resolve_sub_resource(struct wined3d_device *device, SetRect(&src_rect, 0, 0, wined3d_texture_get_level_width(src_texture, src_level), wined3d_texture_get_level_height(src_texture, src_level)); wined3d_texture_blt(dst_texture, dst_sub_resource_idx, &dst_rect, - src_texture, src_sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT); + src_texture, src_sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT, format_id); } HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *device, diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 45eebcc2c20..4567370f3fc 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -13061,7 +13061,7 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) + const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_texture_gl *src_texture_gl = wined3d_texture_gl(src_texture); struct wined3d_texture_gl *dst_texture_gl = wined3d_texture_gl(dst_texture); @@ -13078,10 +13078,10 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli RECT s, d; TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, " - "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s.\n", + "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s, format_id %s.\n", blitter, op, context, src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect), dst_texture, dst_sub_resource_idx, wined3d_debug_location(dst_location), - wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter)); + wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter), debug_d3dformat(format_id)); if (!glsl_blitter_supported(op, context, src_texture_gl, src_location, dst_texture_gl, dst_location)) { @@ -13093,7 +13093,7 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli TRACE("Forwarding to blitter %p.\n", next); return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter); + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter, format_id); } glsl_blitter = CONTAINING_RECORD(blitter, struct wined3d_glsl_blitter, blitter); diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index d5d07d8c401..4b39c47cfe2 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1400,7 +1400,7 @@ static DWORD cpu_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter) + const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_box dst_box = {dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, 0, 1}; struct wined3d_box src_box = {src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1}; @@ -1476,7 +1476,7 @@ static bool wined3d_is_colour_blit(enum wined3d_blit_op blit_op) HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, const struct wined3d_box *dst_box, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, DWORD flags, const struct wined3d_blt_fx *fx, - enum wined3d_texture_filter_type filter) + enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_texture_sub_resource *src_sub_resource, *dst_sub_resource; struct wined3d_device *device = dst_texture->resource.device; @@ -1495,9 +1495,9 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ | WINED3D_BLT_RAW; TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_box %s, src_texture %p, " - "src_sub_resource_idx %u, src_box %s, flags %#x, fx %p, filter %s.\n", + "src_sub_resource_idx %u, src_box %s, flags %#x, fx %p, filter %s, format_id %s.\n", dst_texture, dst_sub_resource_idx, debug_box(dst_box), src_texture, src_sub_resource_idx, - debug_box(src_box), flags, fx, debug_d3dtexturefiltertype(filter)); + debug_box(src_box), flags, fx, debug_d3dtexturefiltertype(filter), debug_d3dformat(format_id)); TRACE("Usage is %s.\n", debug_d3dusage(dst_texture->resource.usage)); if (fx) @@ -1581,7 +1581,7 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ context = context_acquire(device, dst_texture, dst_sub_resource_idx); valid_locations = device->blitter->ops->blitter_blit(device->blitter, blit_op, context, src_texture, src_sub_resource_idx, src_texture->resource.draw_binding, &src_rect, - dst_texture, dst_sub_resource_idx, dst_location, &dst_rect, NULL, filter); + dst_texture, dst_sub_resource_idx, dst_location, &dst_rect, NULL, filter, format_id); context_release(context); wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, valid_locations); @@ -1715,7 +1715,7 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ valid_locations = device->blitter->ops->blitter_blit(device->blitter, blit_op, context, src_texture, src_sub_resource_idx, src_location, &src_rect, - dst_texture, dst_sub_resource_idx, dst_location, &dst_rect, colour_key, filter); + dst_texture, dst_sub_resource_idx, dst_location, &dst_rect, colour_key, filter, format_id); context_release(context); diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 72e17a6f833..39fac6c37fa 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -267,7 +267,7 @@ HRESULT CDECL wined3d_swapchain_get_front_buffer_data(const struct wined3d_swapc } return wined3d_texture_blt(dst_texture, sub_resource_idx, &dst_rect, - swapchain->front_buffer, 0, &src_rect, 0, NULL, WINED3D_TEXF_POINT); + swapchain->front_buffer, 0, &src_rect, 0, NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN); } struct wined3d_texture * CDECL wined3d_swapchain_get_back_buffer(const struct wined3d_swapchain *swapchain, @@ -492,7 +492,7 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain, wined3d_texture_validate_location(texture, 0, WINED3D_LOCATION_DRAWABLE); device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_COLOR_BLIT, context, texture, 0, - location, src_rect, texture, 0, WINED3D_LOCATION_DRAWABLE, dst_rect, NULL, filter); + location, src_rect, texture, 0, WINED3D_LOCATION_DRAWABLE, dst_rect, NULL, filter, WINED3DFMT_UNKNOWN); wined3d_texture_invalidate_location(texture, 0, WINED3D_LOCATION_DRAWABLE); } diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index f4f929db2ca..1d763bbb369 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -320,9 +320,13 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont enum wined3d_texture_filter_type filter, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, - const RECT *dst_rect) + const RECT *dst_rect, enum wined3d_format_id format_id) { + unsigned int dst_save_sub_resource_idx = dst_sub_resource_idx; struct wined3d_texture *required_texture, *restore_texture; + struct wined3d_texture *dst_save_texture = dst_texture; + struct wined3d_texture *src_staging_texture = NULL; + struct wined3d_texture *dst_staging_texture = NULL; const struct wined3d_gl_info *gl_info; struct wined3d_context_gl *context_gl; unsigned int restore_idx; @@ -332,10 +336,10 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont RECT s, d; TRACE("device %p, context %p, filter %s, src_texture %p, src_sub_resource_idx %u, src_location %s, " - "src_rect %s, dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s.\n", + "src_rect %s, dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, format_id %s.\n", device, context, debug_d3dtexturefiltertype(filter), src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect), dst_texture, - dst_sub_resource_idx, wined3d_debug_location(dst_location), wine_dbgstr_rect(dst_rect)); + dst_sub_resource_idx, wined3d_debug_location(dst_location), wine_dbgstr_rect(dst_rect), debug_d3dformat(format_id)); scaled_resolve = wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(src_texture), src_location) && (abs(src_rect->bottom - src_rect->top) != abs(dst_rect->bottom - dst_rect->top) @@ -346,6 +350,101 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont else gl_filter = scaled_resolve ? GL_SCALED_RESOLVE_FASTEST_EXT : GL_NEAREST; + context_gl = wined3d_context_gl(context); + if (!context_gl->valid) + { + context_release(context); + WARN("Invalid context, skipping blit.\n"); + return; + } + + gl_info = context_gl->gl_info; + + switch (format_id) + { + case WINED3DFMT_R8G8B8A8_UNORM_SRGB: + case WINED3DFMT_B8G8R8A8_UNORM_SRGB: + case WINED3DFMT_B8G8R8X8_UNORM_SRGB: + gl_info->gl_ops.gl.p_glEnable(GL_FRAMEBUFFER_SRGB); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE)); + break; + default: + break; + } + + if (format_id != WINED3DFMT_UNKNOWN && src_texture->resource.format->id != format_id) + { + struct wined3d_texture_gl *src_staging_texture_gl = NULL; + struct wined3d_texture_gl *src_texture_gl = NULL; + struct wined3d_resource_desc desc; + unsigned src_level; + HRESULT hr; + + src_level = src_sub_resource_idx % src_texture->level_count; + desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; + desc.format = format_id; + desc.multisample_type = src_texture->resource.multisample_type; + desc.multisample_quality = src_texture->resource.multisample_quality; + desc.usage = WINED3DUSAGE_PRIVATE; + desc.bind_flags = 0; + desc.access = WINED3D_RESOURCE_ACCESS_GPU; + desc.width = wined3d_texture_get_level_width(src_texture, src_level); + desc.height = wined3d_texture_get_level_height(src_texture, src_level); + desc.depth = 1; + desc.size = 0; + + hr = wined3d_texture_create(device, &desc, 1, 1, 0, NULL, NULL, &wined3d_null_parent_ops, &src_staging_texture); + if (FAILED(hr)) + { + ERR("Failed to create staging texture, hr %#x.\n", hr); + return; + } + + src_texture_gl = wined3d_texture_gl(src_texture); + src_staging_texture_gl = wined3d_texture_gl(src_staging_texture); + + wined3d_texture_prepare_location(src_staging_texture, 0, context, WINED3D_LOCATION_TEXTURE_RGB); + + GL_EXTCALL(glCopyImageSubData(wined3d_texture_gl_get_texture_name(src_texture_gl, context, false), + src_texture_gl->target, src_level, 0, 0, 0, + wined3d_texture_gl_get_texture_name(src_staging_texture_gl, context, false), + src_staging_texture_gl->target, 0, 0, 0, 0, desc.width, desc.height, 1)); + + checkGLcall("glCopyImageSubData()"); + src_texture = src_staging_texture; + src_sub_resource_idx = 0; + } + + if (format_id != WINED3DFMT_UNKNOWN && dst_texture->resource.format->id != format_id) + { + struct wined3d_resource_desc desc; + unsigned dst_level; + HRESULT hr; + + dst_level = dst_sub_resource_idx % dst_texture->level_count; + desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; + desc.format = format_id; + desc.multisample_type = dst_texture->resource.multisample_type; + desc.multisample_quality = dst_texture->resource.multisample_quality; + desc.usage = WINED3DUSAGE_PRIVATE; + desc.bind_flags = 0; + desc.access = WINED3D_RESOURCE_ACCESS_GPU; + desc.width = wined3d_texture_get_level_width(dst_texture, dst_level); + desc.height = wined3d_texture_get_level_height(dst_texture, dst_level); + desc.depth = 1; + desc.size = 0; + + hr = wined3d_texture_create(device, &desc, 1, 1, 0, NULL, NULL, &wined3d_null_parent_ops, &dst_staging_texture); + if (FAILED(hr)) + { + ERR("Failed to create staging texture, hr %#x.\n", hr); + return; + } + + dst_texture = dst_staging_texture; + dst_sub_resource_idx = 0; + } + /* Make sure the locations are up-to-date. Loading the destination * surface isn't required if the entire surface is overwritten. (And is * in fact harmful if we're being called by surface_load_location() with @@ -374,16 +473,6 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont else restore_texture = NULL; - context_gl = wined3d_context_gl(context); - if (!context_gl->valid) - { - context_release(context); - WARN("Invalid context, skipping blit.\n"); - return; - } - - gl_info = context_gl->gl_info; - if (src_location == WINED3D_LOCATION_DRAWABLE) { TRACE("Source texture %p is onscreen.\n", src_texture); @@ -437,6 +526,27 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont if (dst_location == WINED3D_LOCATION_DRAWABLE && dst_texture->swapchain->front_buffer == dst_texture) gl_info->gl_ops.gl.p_glFlush(); + if (dst_staging_texture) + { + struct wined3d_texture_gl *dst_texture_gl, *dst_save_texture_gl; + dst_texture_gl = wined3d_texture_gl(dst_texture); + dst_save_texture_gl = wined3d_texture_gl(dst_save_texture); + + wined3d_texture_prepare_location(dst_save_texture, 0, context, WINED3D_LOCATION_TEXTURE_RGB); + + GL_EXTCALL(glCopyImageSubData(wined3d_texture_gl_get_texture_name(dst_texture_gl, context, false), + dst_texture_gl->target, 0, 0, 0, 0, + wined3d_texture_gl_get_texture_name(dst_save_texture_gl, context, false), + dst_save_texture_gl->target, dst_save_sub_resource_idx % dst_texture->level_count, 0, 0, 0, + dst_texture->resource.width, dst_texture->resource.height, 1)); + + checkGLcall("glCopyImageSubData()"); + wined3d_texture_decref(dst_texture); + } + + if (src_staging_texture) + wined3d_texture_decref(src_staging_texture); + if (restore_texture) context_restore(context, restore_texture, restore_idx); } @@ -682,8 +792,8 @@ BOOL wined3d_texture_load_location(struct wined3d_texture *texture, { DWORD required_access = wined3d_resource_access_from_location(location); if ((texture->resource.access & required_access) != required_access) - WARN("Operation requires %#x access, but texture only has %#x.\n", - required_access, texture->resource.access); + WARN("Operation requires %#x access, but texture only has %#x, location %s, current %s.\n", + required_access, texture->resource.access, wined3d_debug_location(location), wined3d_debug_location(current)); } if (current & WINED3D_LOCATION_DISCARDED) @@ -2933,7 +3043,7 @@ static BOOL wined3d_texture_load_drawable(struct wined3d_texture *texture, device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_COLOR_BLIT, context, texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &r, texture, sub_resource_idx, WINED3D_LOCATION_DRAWABLE, &r, - NULL, WINED3D_TEXF_POINT); + NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN); return TRUE; } @@ -2971,7 +3081,7 @@ static BOOL wined3d_texture_load_renderbuffer(struct wined3d_texture *texture, src_location = WINED3D_LOCATION_TEXTURE_RGB; texture2d_blt_fbo(texture->resource.device, context, WINED3D_TEXF_POINT, texture, - sub_resource_idx, src_location, &rect, texture, sub_resource_idx, dst_location, &rect); + sub_resource_idx, src_location, &rect, texture, sub_resource_idx, dst_location, &rect, WINED3DFMT_UNKNOWN); return TRUE; } @@ -3018,11 +3128,11 @@ static BOOL wined3d_texture_gl_load_texture(struct wined3d_texture_gl *texture_g if (srgb) texture2d_blt_fbo(device, &context_gl->c, WINED3D_TEXF_POINT, &texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &src_rect, - &texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect); + &texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect, WINED3DFMT_UNKNOWN); else texture2d_blt_fbo(device, &context_gl->c, WINED3D_TEXF_POINT, &texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect, - &texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &src_rect); + &texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &src_rect, WINED3DFMT_UNKNOWN); return TRUE; } @@ -3039,7 +3149,7 @@ static BOOL wined3d_texture_gl_load_texture(struct wined3d_texture_gl *texture_g if (fbo_blitter_supported(WINED3D_BLIT_OP_COLOR_BLIT, gl_info, &texture_gl->t.resource, src_location, &texture_gl->t.resource, dst_location)) texture2d_blt_fbo(device, &context_gl->c, WINED3D_TEXF_POINT, &texture_gl->t, sub_resource_idx, - src_location, &src_rect, &texture_gl->t, sub_resource_idx, dst_location, &src_rect); + src_location, &src_rect, &texture_gl->t, sub_resource_idx, dst_location, &src_rect, WINED3DFMT_UNKNOWN); return TRUE; } @@ -3849,16 +3959,18 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc HRESULT CDECL wined3d_texture_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, const RECT *dst_rect, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, - const RECT *src_rect, DWORD flags, const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) + const RECT *src_rect, DWORD flags, const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter, + enum wined3d_format_id format_id) { struct wined3d_box src_box = {src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1}; struct wined3d_box dst_box = {dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, 0, 1}; HRESULT hr; TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_rect %s, src_texture %p, " - "src_sub_resource_idx %u, src_rect %s, flags %#x, fx %p, filter %s.\n", + "src_sub_resource_idx %u, src_rect %s, flags %#x, fx %p, filter %s, format_id %s.\n", dst_texture, dst_sub_resource_idx, wine_dbgstr_rect(dst_rect), src_texture, - src_sub_resource_idx, wine_dbgstr_rect(src_rect), flags, fx, debug_d3dtexturefiltertype(filter)); + src_sub_resource_idx, wine_dbgstr_rect(src_rect), flags, fx, debug_d3dtexturefiltertype(filter), + debug_d3dformat(format_id)); if (dst_sub_resource_idx >= dst_texture->level_count * dst_texture->layer_count || dst_texture->resource.type != WINED3D_RTYPE_TEXTURE_2D) @@ -3901,7 +4013,7 @@ HRESULT CDECL wined3d_texture_blt(struct wined3d_texture *dst_texture, unsigned } wined3d_cs_emit_blt_sub_resource(dst_texture->resource.device->cs, &dst_texture->resource, dst_sub_resource_idx, - &dst_box, &src_texture->resource, src_sub_resource_idx, &src_box, flags, fx, filter); + &dst_box, &src_texture->resource, src_sub_resource_idx, &src_box, flags, fx, filter, format_id); return WINED3D_OK; } @@ -5655,7 +5767,7 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) + const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_texture_gl *src_texture_gl = wined3d_texture_gl(src_texture); struct wined3d_context_gl *context_gl = wined3d_context_gl(context); @@ -5676,7 +5788,7 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit { if ((next = blitter->next)) return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter); + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter, format_id); } TRACE("Blt from texture %p, %u to rendertarget %p, %u.\n", @@ -5864,7 +5976,7 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) + const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_context_gl *context_gl = wined3d_context_gl(context); struct wined3d_resource *src_resource, *dst_resource; @@ -5873,10 +5985,10 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit struct wined3d_blitter *next; TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, " - "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s.\n", + "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s, format_id %s.\n", blitter, op, context, src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect), dst_texture, dst_sub_resource_idx, wined3d_debug_location(dst_location), - wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter)); + wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter), debug_d3dformat(format_id)); src_resource = &src_texture->resource; dst_resource = &dst_texture->resource; @@ -5902,14 +6014,14 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit TRACE("Forwarding to blitter %p.\n", next); return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter); + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter, format_id); } if (blit_op == WINED3D_BLIT_OP_COLOR_BLIT) { TRACE("Colour blit.\n"); texture2d_blt_fbo(device, context, filter, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect); + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, format_id); return dst_location; } @@ -5980,7 +6092,7 @@ static DWORD raw_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) + const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_texture_gl *src_texture_gl = wined3d_texture_gl(src_texture); struct wined3d_texture_gl *dst_texture_gl = wined3d_texture_gl(dst_texture); @@ -6007,7 +6119,7 @@ static DWORD raw_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit TRACE("Forwarding to blitter %p.\n", next); return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter); + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter, format_id); } TRACE("Blit using ARB_copy_image.\n"); @@ -6381,7 +6493,7 @@ static void vk_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_dev static bool vk_blitter_blit_supported(enum wined3d_blit_op op, const struct wined3d_context *context, const struct wined3d_resource *src_resource, const RECT *src_rect, - const struct wined3d_resource *dst_resource, const RECT *dst_rect) + const struct wined3d_resource *dst_resource, const RECT *dst_rect, enum wined3d_format_id format_id) { const struct wined3d_format *src_format = src_resource->format; const struct wined3d_format *dst_format = dst_resource->format; @@ -6413,7 +6525,9 @@ static bool vk_blitter_blit_supported(enum wined3d_blit_op op, const struct wine } if (op != WINED3D_BLIT_OP_RAW_BLIT - && wined3d_format_vk(src_format)->vk_format != wined3d_format_vk(dst_format)->vk_format) + && wined3d_format_vk(src_format)->vk_format != wined3d_format_vk(dst_format)->vk_format + && ((!wined3d_format_is_typeless(src_format) && !wined3d_format_is_typeless(dst_format)) + || (format_id == WINED3DFMT_UNKNOWN))) { TRACE("Format conversion not supported.\n"); return false; @@ -6445,11 +6559,78 @@ static bool vk_blitter_blit_supported(enum wined3d_blit_op op, const struct wine return true; } +static VkResult create_staging_image_for_resolve(struct wined3d_context_vk *context_vk, + VkImageType vk_image_type, VkFormat vk_format, unsigned width, unsigned height, unsigned depth, + unsigned sample_count, VkImage *image) +{ + struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter); + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + VkMemoryAllocateInfo allocate_info = {0}; + VkMemoryRequirements memory_requirements; + VkImageCreateInfo create_info; + VkDeviceMemory device_memory; + VkResult vr; + + create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + create_info.pNext = NULL; + create_info.flags = 0; + create_info.imageType = vk_image_type; + create_info.format = vk_format; + create_info.extent.width = width; + create_info.extent.height = height; + create_info.extent.depth = depth; + create_info.mipLevels = 1; + create_info.arrayLayers = 1; + create_info.samples = sample_count; + create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + create_info.queueFamilyIndexCount = 0; + create_info.pQueueFamilyIndices = NULL; + create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + vr = VK_CALL(vkCreateImage(device_vk->vk_device, &create_info, NULL, image)); + if (vr != VK_SUCCESS) + { + ERR("Failed to create image, vr %#x.\n", vr); + return vr; + } + + wined3d_context_vk_destroy_image(context_vk, *image, context_vk->current_command_buffer.id); + + VK_CALL(vkGetImageMemoryRequirements(device_vk->vk_device, *image, &memory_requirements)); + + allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocate_info.allocationSize = memory_requirements.size; + allocate_info.memoryTypeIndex = wined3d_adapter_vk_get_memory_type_index(adapter_vk, ~0, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + vr = VK_CALL(vkAllocateMemory(device_vk->vk_device, &allocate_info, NULL, &device_memory)); + if (vr != VK_SUCCESS) + { + ERR("Failed to allocate memory, vr %#x.\n", vr); + return vr; + } + + wined3d_context_vk_destroy_memory(context_vk, device_memory, context_vk->current_command_buffer.id); + + vr = VK_CALL(vkBindImageMemory(device_vk->vk_device, *image, device_memory, 0)); + if (vr != VK_SUCCESS) + { + ERR("Failed to bind image memory, vr %#x.\n", vr); + return vr; + } + + return VK_SUCCESS; +} + static DWORD vk_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op, struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) + const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_texture_vk *src_texture_vk = wined3d_texture_vk(src_texture); struct wined3d_texture_vk *dst_texture_vk = wined3d_texture_vk(dst_texture); @@ -6459,21 +6640,23 @@ static DWORD vk_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_ VkImageAspectFlags src_aspect, dst_aspect; VkCommandBuffer vk_command_buffer; struct wined3d_blitter *next; + unsigned src_sample_count; bool resolve = false; TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, " - "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s.\n", + "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s, format_id %s.\n", blitter, op, context, src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect), dst_texture, dst_sub_resource_idx, wined3d_debug_location(dst_location), - wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter)); + wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter), debug_d3dformat(format_id)); - if (!vk_blitter_blit_supported(op, context, &src_texture->resource, src_rect, &dst_texture->resource, dst_rect)) + if (!vk_blitter_blit_supported(op, context, &src_texture->resource, src_rect, &dst_texture->resource, dst_rect, format_id)) goto next; src_aspect = vk_aspect_mask_from_format(src_texture_vk->t.resource.format); dst_aspect = vk_aspect_mask_from_format(dst_texture_vk->t.resource.format); - if (wined3d_resource_get_sample_count(&src_texture_vk->t.resource) > 1) + src_sample_count = wined3d_resource_get_sample_count(&src_texture_vk->t.resource); + if (src_sample_count > 1) resolve = true; src_level = src_sub_resource_idx % src_texture->level_count; @@ -6523,7 +6706,180 @@ static DWORD vk_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_ dst_texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_texture_vk->vk_image, dst_aspect); - if (resolve) + + if (resolve && format_id != WINED3DFMT_UNKNOWN + && (src_texture->resource.format->id != format_id || dst_texture->resource.format->id != format_id)) + { + const struct wined3d_format_vk *src_format_vk = wined3d_format_vk(src_texture->resource.format); + const struct wined3d_format_vk *dst_format_vk = wined3d_format_vk(dst_texture->resource.format); + VkImage src_vk_image, dst_vk_image; + VkImageResolve resolve_region; + VkImageType vk_image_type; + VkImageCopy copy_region; + VkFormat vk_format; + VkResult vr; + + TRACE("Doing typeless resolve %s to %s (via %s)\n", debug_d3dformat(src_texture->resource.format->id), + debug_d3dformat(dst_texture->resource.format->id), debug_d3dformat(format_id)); + + if (!wined3d_format_is_typeless(&src_format_vk->f)) + { + vk_format = src_format_vk->vk_format; + } + else if (!wined3d_format_is_typeless(&dst_format_vk->f)) + { + vk_format = dst_format_vk->vk_format; + } + else + { + vk_format = wined3d_format_vk(wined3d_get_format(context->device->adapter, format_id, 0))->vk_format; + } + + switch (src_texture->resource.type) + { + case WINED3D_RTYPE_TEXTURE_1D: + vk_image_type = VK_IMAGE_TYPE_1D; + break; + case WINED3D_RTYPE_TEXTURE_2D: + vk_image_type = VK_IMAGE_TYPE_2D; + break; + case WINED3D_RTYPE_TEXTURE_3D: + vk_image_type = VK_IMAGE_TYPE_3D; + break; + default: + ERR("Unexpected resource type: %s\n", debug_d3dresourcetype(src_texture->resource.type)); + goto next; + } + + resolve_region.dstSubresource.aspectMask = dst_aspect; + resolve_region.extent.width = src_rect->right - src_rect->left; + resolve_region.extent.height = src_rect->bottom - src_rect->top; + resolve_region.extent.depth = 1; + + if (src_texture->resource.format->id != format_id) + { + vr = create_staging_image_for_resolve(context_vk, vk_image_type, vk_format, + resolve_region.extent.width, resolve_region.extent.height, 1, src_sample_count, &src_vk_image); + if (vr != VK_SUCCESS) + goto next; + + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, src_vk_image, src_aspect); + + copy_region.srcSubresource.aspectMask = src_aspect; + copy_region.srcSubresource.mipLevel = src_level; + copy_region.srcSubresource.baseArrayLayer = src_layer; + copy_region.srcSubresource.layerCount = 1; + copy_region.srcOffset.x = src_rect->left; + copy_region.srcOffset.y = src_rect->top; + copy_region.srcOffset.z = 0; + copy_region.dstSubresource.aspectMask = src_aspect; + copy_region.dstSubresource.mipLevel = 0; + copy_region.dstSubresource.baseArrayLayer = 0; + copy_region.dstSubresource.layerCount = 1; + copy_region.dstOffset.x = 0; + copy_region.dstOffset.y = 0; + copy_region.dstOffset.z = 0; + copy_region.extent.width = resolve_region.extent.width; + copy_region.extent.height = resolve_region.extent.height; + copy_region.extent.depth = 1; + + VK_CALL(vkCmdCopyImage(vk_command_buffer, src_texture_vk->vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + src_vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region)); + + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + src_vk_image, src_aspect); + + resolve_region.srcSubresource.aspectMask = src_aspect; + resolve_region.srcSubresource.mipLevel = 0; + resolve_region.srcSubresource.baseArrayLayer = 0; + resolve_region.srcSubresource.layerCount = 1; + resolve_region.srcOffset.x = 0; + resolve_region.srcOffset.y = 0; + resolve_region.srcOffset.z = 0; + } + else + { + src_vk_image = src_texture_vk->vk_image; + + resolve_region.srcSubresource.aspectMask = src_aspect; + resolve_region.srcSubresource.mipLevel = src_level; + resolve_region.srcSubresource.baseArrayLayer = src_layer; + resolve_region.srcSubresource.layerCount = 1; + resolve_region.srcOffset.x = src_rect->left; + resolve_region.srcOffset.y = src_rect->top; + resolve_region.srcOffset.z = 0; + } + + if (dst_texture->resource.format->id != format_id) + { + vr = create_staging_image_for_resolve(context_vk, vk_image_type, vk_format, + resolve_region.extent.width, resolve_region.extent.height, 1, VK_SAMPLE_COUNT_1_BIT, &dst_vk_image); + if (vr != VK_SUCCESS) + goto next; + + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_vk_image, dst_aspect); + + resolve_region.dstSubresource.mipLevel = 0; + resolve_region.dstSubresource.baseArrayLayer = 0; + resolve_region.dstSubresource.layerCount = 1; + resolve_region.dstOffset.x = 0; + resolve_region.dstOffset.y = 0; + resolve_region.dstOffset.z = 0; + } + else + { + dst_vk_image = dst_texture_vk->vk_image; + + resolve_region.dstSubresource.mipLevel = dst_level; + resolve_region.dstSubresource.baseArrayLayer = dst_layer; + resolve_region.dstSubresource.layerCount = 1; + resolve_region.dstOffset.x = dst_rect->left; + resolve_region.dstOffset.y = dst_rect->top; + resolve_region.dstOffset.z = 0; + } + + VK_CALL(vkCmdResolveImage(vk_command_buffer, src_vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dst_vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &resolve_region)); + + if (dst_vk_image != dst_texture_vk->vk_image) + { + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dst_vk_image, dst_aspect); + + copy_region.srcSubresource.aspectMask = dst_aspect; + copy_region.srcSubresource.mipLevel = 0; + copy_region.srcSubresource.baseArrayLayer = 0; + copy_region.srcSubresource.layerCount = 1; + copy_region.srcOffset.x = 0; + copy_region.srcOffset.y = 0; + copy_region.srcOffset.z = 0; + copy_region.dstSubresource.aspectMask = dst_aspect; + copy_region.dstSubresource.mipLevel = dst_level; + copy_region.dstSubresource.baseArrayLayer = dst_layer; + copy_region.dstSubresource.layerCount = 1; + copy_region.dstOffset.x = dst_rect->left; + copy_region.dstOffset.y = dst_rect->top; + copy_region.dstOffset.z = 0; + copy_region.extent.width = resolve_region.extent.width; + copy_region.extent.height = resolve_region.extent.height; + copy_region.extent.depth = 1; + + VK_CALL(vkCmdCopyImage(vk_command_buffer, dst_vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dst_texture_vk->vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region)); + } + } + else if (resolve) { VkImageResolve region; @@ -6606,7 +6962,7 @@ next: TRACE("Forwarding to blitter %p.\n", next); return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter); + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter, format_id); } static const struct wined3d_blitter_ops vk_blitter_ops = diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 2a75ab5d43d..b141918cefa 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2756,7 +2756,7 @@ struct wined3d_blitter_ops struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, const struct wined3d_color_key *colour_key, - enum wined3d_texture_filter_type filter); + enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id); }; void wined3d_arbfp_blitter_create(struct wined3d_blitter **next, @@ -4320,7 +4320,7 @@ static inline bool wined3d_texture_is_full_rect(const struct wined3d_texture *te HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, const struct wined3d_box *dst_box, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, DWORD flags, - const struct wined3d_blt_fx *blt_fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; + const struct wined3d_blt_fx *blt_fx, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) DECLSPEC_HIDDEN; void texture2d_get_blt_info(const struct wined3d_texture_gl *texture_gl, unsigned int sub_resource_idx, const RECT *rect, struct wined3d_blt_info *info) DECLSPEC_HIDDEN; void texture2d_load_fb_texture(struct wined3d_texture_gl *texture_gl, unsigned int sub_resource_idx, @@ -4710,7 +4710,7 @@ void wined3d_cs_emit_add_dirty_texture_region(struct wined3d_cs *cs, void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, const struct wined3d_box *dst_box, struct wined3d_resource *src_resource, unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, DWORD flags, - const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; + const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) DECLSPEC_HIDDEN; void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; void wined3d_cs_emit_clear_rendertarget_view(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view, diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 96cb6fc1d86..e47f823ea13 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2830,7 +2830,7 @@ HRESULT __cdecl wined3d_texture_add_dirty_region(struct wined3d_texture *texture UINT layer, const struct wined3d_box *dirty_region); HRESULT __cdecl wined3d_texture_blt(struct wined3d_texture *dst_texture, unsigned int dst_idx, const RECT *dst_rect_in, struct wined3d_texture *src_texture, unsigned int src_idx, const RECT *src_rect_in, DWORD flags, - const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter); + const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter, enum wined3d_format_id); HRESULT __cdecl wined3d_texture_create(struct wined3d_device *device, const struct wined3d_resource_desc *desc, UINT layer_count, UINT level_count, DWORD flags, const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture); -- 2.30.0