Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - added patch.
dlls/wined3d/surface.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index a67a08042c..d2552bbd69 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -175,13 +175,6 @@ void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_context *co break; }
- /* Resolve the source surface first if needed. */ - if (wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(src_texture), src_location) - && (src_texture->resource.format->id != dst_texture->resource.format->id - || abs(src_rect->bottom - src_rect->top) != abs(dst_rect->bottom - dst_rect->top) - || abs(src_rect->right - src_rect->left) != abs(dst_rect->right - dst_rect->left))) - src_location = WINED3D_LOCATION_RB_RESOLVED; - /* 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 @@ -944,6 +937,14 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit if (blit_op == WINED3D_BLIT_OP_COLOR_BLIT) { TRACE("Colour blit.\n"); + + /* Resolve the source surface first if needed. */ + if (wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(src_texture), src_location) + && (src_texture->resource.format->id != dst_texture->resource.format->id + || abs(src_rect->bottom - src_rect->top) != abs(dst_rect->bottom - dst_rect->top) + || abs(src_rect->right - src_rect->left) != abs(dst_rect->right - dst_rect->left))) + src_location = WINED3D_LOCATION_RB_RESOLVED; + 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); return dst_location;
If either source or destination is multisampled scaled FBO blit results in GL_INVALID_OPERATION.
Fixes black screen in 'BlazBlue Calamity Trigger'.
Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - handle resolve in fbo_blitter_blit().
dlls/d3d9/tests/visual.c | 88 +++++++++++++++++++++++++++++----------- dlls/wined3d/surface.c | 15 ++++--- 2 files changed, 75 insertions(+), 28 deletions(-)
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 62c053b212..0e71e23018 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -4332,7 +4332,7 @@ static void test_multisample_stretch_rect(void) D3DTEXF_POINT, D3DTEXF_LINEAR, }; - IDirect3DSurface9 *rt, *ms_rt, *rt_r5g6b5; + IDirect3DSurface9 *rt, *ms_rt, *ms_rt2, *rt_r5g6b5; struct surface_readback rb; IDirect3DDevice9 *device; DWORD quality_levels; @@ -4367,27 +4367,30 @@ static void test_multisample_stretch_rect(void)
hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL); - ok(hr == S_OK, "Failed to create render target, hr %#x.\n", hr); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, quality_levels - 1, FALSE, &ms_rt, NULL); - ok(hr == S_OK, "Failed to create render target, hr %#x.\n", hr); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, + D3DFMT_A8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, quality_levels - 1, FALSE, &ms_rt2, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DDevice9_SetRenderTarget(device, 0, ms_rt); - ok(hr == D3D_OK, "Failed to set render target, hr %#x.\n", hr); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ff00ff, 0.0f, 0); - ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt); - ok(hr == D3D_OK, "Failed to set render target, hr %#x.\n", hr); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
for (i = 0; i < ARRAY_SIZE(filters); ++i) { hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0); - ok(hr == D3D_OK, "Test %u: Failed to clear, hr %#x.\n", i, hr); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); hr = IDirect3DDevice9_StretchRect(device, ms_rt, NULL, rt, NULL, filters[i]); - ok(hr == S_OK, "Test %u: Failed to stretch rect, hr %#x.\n", i, hr); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); color = getPixelColor(device, 64, 64); - ok(color == 0x00ff00ff, "Test %u: Got color 0x%08x.\n", i, color); + ok(color == 0x00ff00ff, "Test %u, got unexpected color 0x%08x.\n", i, color); }
/* Scaling */ @@ -4395,29 +4398,67 @@ static void test_multisample_stretch_rect(void) for (i = 0; i < ARRAY_SIZE(filters); ++i) { hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0); - ok(hr == D3D_OK, "Test %u: Failed to clear, hr %#x.\n", i, hr); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); + hr = IDirect3DDevice9_StretchRect(device, rt, NULL, ms_rt2, NULL, D3DTEXF_NONE); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); + hr = IDirect3DDevice9_StretchRect(device, ms_rt, NULL, rt, &rect, filters[i]); - ok(hr == S_OK, "Test %u: Failed to stretch rect, hr %#x.\n", i, hr); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); + get_rt_readback(rt, &rb); + color = get_readback_color(&rb, 32, 32); + ok(color == 0x00ff00ff, "Test %u, got unexpected color 0x%08x.\n", i, color); + color = get_readback_color(&rb, 64, 64); + ok(color == 0xffffffff, "Test %u, got unexpected color 0x%08x.\n", i, color); + color = get_readback_color(&rb, 96, 96); + ok(color == 0xffffffff, "Test %u, got unexpected color 0x%08x.\n", i, color); + release_surface_readback(&rb); + + hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); + hr = IDirect3DDevice9_StretchRect(device, ms_rt, &rect, rt, NULL, filters[i]); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); get_rt_readback(rt, &rb); color = get_readback_color(&rb, 32, 32); - ok(color == 0x00ff00ff, "Test %u: Got color 0x%08x.\n", i, color); + ok(color == 0x00ff00ff, "Test %u, got unexpected color 0x%08x.\n", i, color); color = get_readback_color(&rb, 64, 64); - ok(color == 0xffffffff, "Test %u: Got color 0x%08x.\n", i, color); + ok(color == 0x00ff00ff, "Test %u, got unexpected color 0x%08x.\n", i, color); color = get_readback_color(&rb, 96, 96); - ok(color == 0xffffffff, "Test %u: Got color 0x%08x.\n", i, color); + ok(color == 0x00ff00ff, "Test %u, got unexpected color 0x%08x.\n", i, color); release_surface_readback(&rb);
+ hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0f, 0); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); + hr = IDirect3DDevice9_StretchRect(device, rt, NULL, ms_rt, &rect, filters[i]); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0); - ok(hr == D3D_OK, "Test %u: Failed to clear, hr %#x.\n", i, hr); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); hr = IDirect3DDevice9_StretchRect(device, ms_rt, &rect, rt, NULL, filters[i]); - ok(hr == S_OK, "Test %u: Failed to stretch rect, hr %#x.\n", i, hr); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); + get_rt_readback(rt, &rb); + color = get_readback_color(&rb, 32, 32); + ok(color == 0xffffff00, "Test %u, got unexpected color 0x%08x.\n", i, color); + color = get_readback_color(&rb, 64, 64); + ok(color == 0xffffff00, "Test %u, got unexpected color 0x%08x.\n", i, color); + color = get_readback_color(&rb, 96, 96); + ok(color == 0xffffff00, "Test %u, got unexpected color 0x%08x.\n", i, color); + release_surface_readback(&rb); + + hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ff00ff, 0.0f, 0); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); + hr = IDirect3DDevice9_StretchRect(device, rt, NULL, ms_rt, NULL, D3DTEXF_NONE); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); + + hr = IDirect3DDevice9_StretchRect(device, ms_rt, &rect, ms_rt2, NULL, filters[i]); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); + hr = IDirect3DDevice9_StretchRect(device, ms_rt2, &rect, rt, NULL, filters[i]); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); get_rt_readback(rt, &rb); color = get_readback_color(&rb, 32, 32); - ok(color == 0x00ff00ff, "Test %u: Got color 0x%08x.\n", i, color); + ok(color == 0x00ff00ff, "Test %u, got unexpected color 0x%08x.\n", i, color); color = get_readback_color(&rb, 64, 64); - ok(color == 0x00ff00ff, "Test %u: Got color 0x%08x.\n", i, color); + ok(color == 0x00ff00ff, "Test %u, got unexpected color 0x%08x.\n", i, color); color = get_readback_color(&rb, 96, 96); - ok(color == 0x00ff00ff, "Test %u: Got color 0x%08x.\n", i, color); + ok(color == 0x00ff00ff, "Test %u, got unexpected color 0x%08x.\n", i, color); release_surface_readback(&rb); }
@@ -4433,18 +4474,19 @@ static void test_multisample_stretch_rect(void) for (i = 0; i < ARRAY_SIZE(filters); ++i) { hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0); - ok(hr == D3D_OK, "Test %u: Failed to clear, hr %#x.\n", i, hr); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); hr = IDirect3DDevice9_StretchRect(device, ms_rt, NULL, rt_r5g6b5, NULL, filters[i]); - ok(hr == S_OK, "Test %u: Failed to stretch rect, hr %#x.\n", i, hr); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); hr = IDirect3DDevice9_StretchRect(device, rt_r5g6b5, NULL, rt, NULL, filters[i]); - ok(hr == S_OK, "Test %u: Failed to stretch rect, hr %#x.\n", i, hr); + ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr); color = getPixelColor(device, 64, 64); - ok(color == 0x00ff00ff, "Test %u: Got color 0x%08x.\n", i, color); + ok(color == 0x00ff00ff, "Test %u, got unexpected color 0x%08x.\n", i, color); }
IDirect3DSurface9_Release(rt_r5g6b5);
done: + IDirect3DSurface9_Release(ms_rt2); IDirect3DSurface9_Release(ms_rt); IDirect3DSurface9_Release(rt); refcount = IDirect3DDevice9_Release(device); diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index d2552bbd69..1e47f47841 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -938,12 +938,17 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit { TRACE("Colour blit.\n");
- /* Resolve the source surface first if needed. */ - if (wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(src_texture), src_location) - && (src_texture->resource.format->id != dst_texture->resource.format->id + /* Resolve the source and destination surfaces if needed. */ + if (src_texture->resource.format->id != dst_texture->resource.format->id || abs(src_rect->bottom - src_rect->top) != abs(dst_rect->bottom - dst_rect->top) - || abs(src_rect->right - src_rect->left) != abs(dst_rect->right - dst_rect->left))) - src_location = WINED3D_LOCATION_RB_RESOLVED; + || abs(src_rect->right - src_rect->left) != abs(dst_rect->right - dst_rect->left)) + { + if (wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(dst_texture), dst_location)) + dst_location = WINED3D_LOCATION_RB_RESOLVED; + + if (wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(src_texture), src_location)) + src_location = WINED3D_LOCATION_RB_RESOLVED; + }
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);
On Mon, 9 Mar 2020 at 18:45, Paul Gofman gofmanp@gmail.com wrote:
@@ -938,12 +938,17 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit { TRACE("Colour blit.\n");
/* Resolve the source surface first if needed. */
if (wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(src_texture), src_location)
&& (src_texture->resource.format->id != dst_texture->resource.format->id
/* Resolve the source and destination surfaces if needed. */
if (src_texture->resource.format->id != dst_texture->resource.format->id || abs(src_rect->bottom - src_rect->top) != abs(dst_rect->bottom - dst_rect->top)
|| abs(src_rect->right - src_rect->left) != abs(dst_rect->right - dst_rect->left)))
src_location = WINED3D_LOCATION_RB_RESOLVED;
|| abs(src_rect->right - src_rect->left) != abs(dst_rect->right - dst_rect->left))
{
if (wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(dst_texture), dst_location))
dst_location = WINED3D_LOCATION_RB_RESOLVED;
What initially bothered me about this is that it breaks the blitter interface a little; i.e., a caller asking for a blit to WINED3D_LOCATION_RB_MULTISAMPLE can potentially end up not getting a an up-to-date WINED3D_LOCATION_RB_MULTISAMPLE. I think that still works out in practice for all current callers, but it seems undesirable in the long term. It would be easy enough to avoid that by adding a wined3d_texture_load_location() call with the requested destination location, but then that would introduce a potentially redundant extra blit.
After giving it some more thought though, I'm wondering whether perhaps the best option would be for texture2d_blt() to not request scaled multi-sample blits in the first place, unless it knows that at least one blitter can handle those. (I.e., introducing something like "d3d_info->scaled_resolve".)
On 3/10/20 11:11, Henri Verbeet wrote:
On Mon, 9 Mar 2020 at 18:45, Paul Gofman gofmanp@gmail.com wrote:
@@ -938,12 +938,17 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit { TRACE("Colour blit.\n");
/* Resolve the source surface first if needed. */
if (wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(src_texture), src_location)
&& (src_texture->resource.format->id != dst_texture->resource.format->id
/* Resolve the source and destination surfaces if needed. */
if (src_texture->resource.format->id != dst_texture->resource.format->id || abs(src_rect->bottom - src_rect->top) != abs(dst_rect->bottom - dst_rect->top)
|| abs(src_rect->right - src_rect->left) != abs(dst_rect->right - dst_rect->left)))
src_location = WINED3D_LOCATION_RB_RESOLVED;
|| abs(src_rect->right - src_rect->left) != abs(dst_rect->right - dst_rect->left))
{
if (wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(dst_texture), dst_location))
dst_location = WINED3D_LOCATION_RB_RESOLVED;
What initially bothered me about this is that it breaks the blitter interface a little; i.e., a caller asking for a blit to WINED3D_LOCATION_RB_MULTISAMPLE can potentially end up not getting a an up-to-date WINED3D_LOCATION_RB_MULTISAMPLE. I think that still works out in practice for all current callers, but it seems undesirable in the long term. It would be easy enough to avoid that by adding a wined3d_texture_load_location() call with the requested destination location, but then that would introduce a potentially redundant extra blit.
An extra wined3d_texture_load_location() for requested destintation location was introduced in the first version when resolve was in texture2d_blt_fbo(), but I thought one of the reasons it is actually better to do in fbo_blitter_blit() is that we can avoid that. Doesn't dst_location returned from blitter have the purpose to give us some flexibility to leave the different dst_location?
After giving it some more thought though, I'm wondering whether perhaps the best option would be for texture2d_blt() to not request scaled multi-sample blits in the first place, unless it knows that at least one blitter can handle those. (I.e., introducing something like "d3d_info->scaled_resolve".)
I am not sure I fully understand. Currently fbo blitter thinks it can always handle that, just does it wrong when the destination texture is also multisampled. GLSL blitter does not support support source multisampled textures, but should be fine with multisampled destination. Do you mean to just do not support scaled resolves in FBO blitter, or do not support if EXT_framebuffer_multisample_blit_scaled is not available (if it is available, we still need to resolve destination texture)?
As a separate question, if no blitter is decided to be able to handle scaled resolve, should texture2d_blt() do the resolve first and then scaled blit?
On Tue, 10 Mar 2020 at 12:15, Paul Gofman gofmanp@gmail.com wrote:
On 3/10/20 11:11, Henri Verbeet wrote:
What initially bothered me about this is that it breaks the blitter interface a little; i.e., a caller asking for a blit to WINED3D_LOCATION_RB_MULTISAMPLE can potentially end up not getting a an up-to-date WINED3D_LOCATION_RB_MULTISAMPLE. I think that still works out in practice for all current callers, but it seems undesirable in the long term. It would be easy enough to avoid that by adding a wined3d_texture_load_location() call with the requested destination location, but then that would introduce a potentially redundant extra blit.
An extra wined3d_texture_load_location() for requested destintation location was introduced in the first version when resolve was in texture2d_blt_fbo(), but I thought one of the reasons it is actually better to do in fbo_blitter_blit() is that we can avoid that. Doesn't dst_location returned from blitter have the purpose to give us some flexibility to leave the different dst_location?
Somewhat, the original idea was that it allows the blitter to return additional locations that ended up being validated as a result of the blit, so that the caller can avoid invalidating those.
After giving it some more thought though, I'm wondering whether perhaps the best option would be for texture2d_blt() to not request scaled multi-sample blits in the first place, unless it knows that at least one blitter can handle those. (I.e., introducing something like "d3d_info->scaled_resolve".)
I am not sure I fully understand. Currently fbo blitter thinks it can always handle that, just does it wrong when the destination texture is also multisampled. GLSL blitter does not support support source multisampled textures, but should be fine with multisampled destination. Do you mean to just do not support scaled resolves in FBO blitter, or do not support if EXT_framebuffer_multisample_blit_scaled is not available (if it is available, we still need to resolve destination texture)?
In texture2d_blt(), we use "texture->resource.draw_binding" as source/destination location for textures with WINED3D_RESOURCE_ACCESS_GPU, but we don't necessarily have to do that. If we instead used WINED3D_LOCATION_RB_RESOLVED in the appropriate cases, the blitters wouldn't need to deal with scaled resolves. Using EXT_framebuffer_multisample_blit_scaled when available may still be advantageous, particularly when using ARB_texture_multisample, but blitter support for scaled resolves would be optional in that case.
As a separate question, if no blitter is decided to be able to handle scaled resolve, should texture2d_blt() do the resolve first and then scaled blit?
Where needed, resolves would happen implicitly by using WINED3D_LOCATION_RB_RESOLVED as source/destination locations.
On 3/10/20 12:16, Henri Verbeet wrote:
On Tue, 10 Mar 2020 at 12:15, Paul Gofman gofmanp@gmail.com wrote:
On 3/10/20 11:11, Henri Verbeet wrote:
What initially bothered me about this is that it breaks the blitter interface a little; i.e., a caller asking for a blit to WINED3D_LOCATION_RB_MULTISAMPLE can potentially end up not getting a an up-to-date WINED3D_LOCATION_RB_MULTISAMPLE. I think that still works out in practice for all current callers, but it seems undesirable in the long term. It would be easy enough to avoid that by adding a wined3d_texture_load_location() call with the requested destination location, but then that would introduce a potentially redundant extra blit.
An extra wined3d_texture_load_location() for requested destintation location was introduced in the first version when resolve was in texture2d_blt_fbo(), but I thought one of the reasons it is actually better to do in fbo_blitter_blit() is that we can avoid that. Doesn't dst_location returned from blitter have the purpose to give us some flexibility to leave the different dst_location?
Somewhat, the original idea was that it allows the blitter to return additional locations that ended up being validated as a result of the blit, so that the caller can avoid invalidating those.
After giving it some more thought though, I'm wondering whether perhaps the best option would be for texture2d_blt() to not request scaled multi-sample blits in the first place, unless it knows that at least one blitter can handle those. (I.e., introducing something like "d3d_info->scaled_resolve".)
I am not sure I fully understand. Currently fbo blitter thinks it can always handle that, just does it wrong when the destination texture is also multisampled. GLSL blitter does not support support source multisampled textures, but should be fine with multisampled destination. Do you mean to just do not support scaled resolves in FBO blitter, or do not support if EXT_framebuffer_multisample_blit_scaled is not available (if it is available, we still need to resolve destination texture)?
In texture2d_blt(), we use "texture->resource.draw_binding" as source/destination location for textures with WINED3D_RESOURCE_ACCESS_GPU, but we don't necessarily have to do that. If we instead used WINED3D_LOCATION_RB_RESOLVED in the appropriate cases, the blitters wouldn't need to deal with scaled resolves. Using EXT_framebuffer_multisample_blit_scaled when available may still be advantageous, particularly when using ARB_texture_multisample, but blitter support for scaled resolves would be optional in that case.
As a separate question, if no blitter is decided to be able to handle scaled resolve, should texture2d_blt() do the resolve first and then scaled blit?
Where needed, resolves would happen implicitly by using WINED3D_LOCATION_RB_RESOLVED as source/destination locations.
So I suggest I do the following:
1. Use _LOCATION_RB_RESOLVED instead of draw_binding in texture2d_blt() if otherwise it would result in scaled resolve, and maybe also when we have blit operation other than WINED3D_BLIT_OP_COLOR_BLIT;
2. Introduce d3d_info->scaled_resolve, base it on EXT_framebuffer_multisample_blit_scaled in GL adapter, and adjust the condition in 1 if scaled_resolve is available.
On Tue, 10 Mar 2020 at 13:04, Paul Gofman gofmanp@gmail.com wrote:
So I suggest I do the following:
- Use _LOCATION_RB_RESOLVED instead of draw_binding in texture2d_blt()
if otherwise it would result in scaled resolve, and maybe also when we have blit operation other than WINED3D_BLIT_OP_COLOR_BLIT;
- Introduce d3d_info->scaled_resolve, base it on
EXT_framebuffer_multisample_blit_scaled in GL adapter, and adjust the condition in 1 if scaled_resolve is available.
Right.
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/wined3d/adapter_gl.c | 2 ++ dlls/wined3d/surface.c | 15 +++++++++++---- dlls/wined3d/wined3d_gl.h | 1 + 3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 6e60c5323e..ee091a9b77 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -206,6 +206,8 @@ static const struct wined3d_extension_map gl_extension_map[] = {"GL_EXT_texture_snorm", EXT_TEXTURE_SNORM }, {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB }, {"GL_EXT_texture_sRGB_decode", EXT_TEXTURE_SRGB_DECODE }, + {"GL_EXT_framebuffer_multisample_blit_scaled", + EXT_FRAMEBUFFER_MULTISAMPLE_BLIT_SCALED}, {"GL_EXT_texture_swizzle", ARB_TEXTURE_SWIZZLE }, {"GL_EXT_vertex_array_bgra", ARB_VERTEX_ARRAY_BGRA },
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 1e47f47841..8b37286cbe 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -149,6 +149,7 @@ void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_context *co struct wined3d_texture *required_texture, *restore_texture; const struct wined3d_gl_info *gl_info; struct wined3d_context_gl *context_gl; + BOOL is_source_multisampled; unsigned int restore_idx; GLenum gl_filter; GLenum buffer; @@ -160,10 +161,13 @@ void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_context *co 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));
+ is_source_multisampled = wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(src_texture), + src_location); + switch (filter) { case WINED3D_TEXF_LINEAR: - gl_filter = GL_LINEAR; + gl_filter = is_source_multisampled ? GL_SCALED_RESOLVE_NICEST_EXT : GL_LINEAR; break;
default: @@ -171,7 +175,7 @@ void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_context *co /* fall through */ case WINED3D_TEXF_NONE: case WINED3D_TEXF_POINT: - gl_filter = GL_NEAREST; + gl_filter = is_source_multisampled ? GL_SCALED_RESOLVE_FASTEST_EXT : GL_NEAREST; break; }
@@ -896,6 +900,7 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) { struct wined3d_context_gl *context_gl = wined3d_context_gl(context); + const struct wined3d_gl_info *gl_info = context_gl->gl_info; struct wined3d_resource *src_resource, *dst_resource; enum wined3d_blit_op blit_op = op; struct wined3d_device *device; @@ -920,7 +925,7 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit blit_op = WINED3D_BLIT_OP_COLOR_BLIT; }
- if (!fbo_blitter_supported(blit_op, context_gl->gl_info, + if (!fbo_blitter_supported(blit_op, gl_info, src_resource, src_location, dst_resource, dst_location)) { if (!(next = blitter->next)) @@ -946,7 +951,9 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit if (wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(dst_texture), dst_location)) dst_location = WINED3D_LOCATION_RB_RESOLVED;
- if (wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(src_texture), src_location)) + if (wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(src_texture), src_location) + && (src_texture->resource.format->id != dst_texture->resource.format->id + || !gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE_BLIT_SCALED])) src_location = WINED3D_LOCATION_RB_RESOLVED; }
diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h index 3372b4b6be..2d838d7f84 100644 --- a/dlls/wined3d/wined3d_gl.h +++ b/dlls/wined3d/wined3d_gl.h @@ -185,6 +185,7 @@ enum wined3d_gl_extension EXT_TEXTURE_SNORM, EXT_TEXTURE_SRGB, EXT_TEXTURE_SRGB_DECODE, + EXT_FRAMEBUFFER_MULTISAMPLE_BLIT_SCALED, /* NVIDIA */ NV_FENCE, NV_FOG_DISTANCE,