Hardcoded buffer sizes are error-prone.
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/wined3d/utils.c | 75 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 20 deletions(-)
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 4e1da1ce009b..a9db5e072919 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -4148,12 +4148,44 @@ const char *debug_d3ddevicetype(enum wined3d_device_type device_type) } }
+struct debug_buffer +{ + char str[200]; /* wine_dbg_sprintf() limits string size to 200 */ + char *ptr; + int size; +}; + +static void init_debug_buffer(struct debug_buffer *buffer, const char *default_string) +{ + strcpy(buffer->str, default_string); + buffer->ptr = buffer->str; + buffer->size = ARRAY_SIZE(buffer->str); +} + +static BOOL debug_append(struct debug_buffer *buffer, const char *str, const char *separator) +{ + int size; + + if (!separator || buffer->ptr == buffer->str) + separator = ""; + size = snprintf(buffer->ptr, buffer->size, "%s%s", separator, str); + if (size == -1 || size >= buffer->size) + { + buffer->size = 0; + return FALSE; + } + + buffer->ptr += size; + buffer->size -= size; + return TRUE; +} + const char *wined3d_debug_resource_access(DWORD access) { - char buf[125]; + struct debug_buffer buffer;
- buf[0] = '\0'; -#define ACCESS_TO_STR(x) if (access & x) { strcat(buf, " | "#x); access &= ~x; } + init_debug_buffer(&buffer, "0"); +#define ACCESS_TO_STR(x) if (access & x) { debug_append(&buffer, #x, " | "); access &= ~x; } ACCESS_TO_STR(WINED3D_RESOURCE_ACCESS_GPU); ACCESS_TO_STR(WINED3D_RESOURCE_ACCESS_CPU); ACCESS_TO_STR(WINED3D_RESOURCE_ACCESS_MAP_R); @@ -4162,15 +4194,15 @@ const char *wined3d_debug_resource_access(DWORD access) if (access) FIXME("Unrecognised access flag(s) %#x.\n", access);
- return buf[0] ? wine_dbg_sprintf("%s", &buf[3]) : "0"; + return wine_dbg_sprintf("%s", buffer.str); }
const char *debug_d3dusage(DWORD usage) { - char buf[552]; + struct debug_buffer buffer;
- buf[0] = '\0'; -#define WINED3DUSAGE_TO_STR(u) if (usage & u) { strcat(buf, " | "#u); usage &= ~u; } + init_debug_buffer(&buffer, "0"); +#define WINED3DUSAGE_TO_STR(x) if (usage & x) { debug_append(&buffer, #x, " | "); usage &= ~x; } WINED3DUSAGE_TO_STR(WINED3DUSAGE_RENDERTARGET); WINED3DUSAGE_TO_STR(WINED3DUSAGE_DEPTHSTENCIL); WINED3DUSAGE_TO_STR(WINED3DUSAGE_WRITEONLY); @@ -4191,17 +4223,18 @@ const char *debug_d3dusage(DWORD usage) WINED3DUSAGE_TO_STR(WINED3DUSAGE_STATICDECL); WINED3DUSAGE_TO_STR(WINED3DUSAGE_OVERLAY); #undef WINED3DUSAGE_TO_STR - if (usage) FIXME("Unrecognized usage flag(s) %#x\n", usage); + if (usage) + FIXME("Unrecognized usage flag(s) %#x.\n", usage);
- return buf[0] ? wine_dbg_sprintf("%s", &buf[3]) : "0"; + return wine_dbg_sprintf("%s", buffer.str); }
-const char *debug_d3dusagequery(DWORD usagequery) +const char *debug_d3dusagequery(DWORD usage) { - char buf[238]; + struct debug_buffer buffer;
- buf[0] = '\0'; -#define WINED3DUSAGEQUERY_TO_STR(u) if (usagequery & u) { strcat(buf, " | "#u); usagequery &= ~u; } + init_debug_buffer(&buffer, "0"); +#define WINED3DUSAGEQUERY_TO_STR(x) if (usage & x) { debug_append(&buffer, #x, " | "); usage &= ~x; } WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_FILTER); WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_GENMIPMAP); WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_LEGACYBUMPMAP); @@ -4211,9 +4244,10 @@ const char *debug_d3dusagequery(DWORD usagequery) WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_VERTEXTEXTURE); WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_WRAPANDMIP); #undef WINED3DUSAGEQUERY_TO_STR - if (usagequery) FIXME("Unrecognized usage query flag(s) %#x\n", usagequery); + if (usage) + FIXME("Unrecognized usage query flag(s) %#x.\n", usage);
- return buf[0] ? wine_dbg_sprintf("%s", &buf[3]) : "0"; + return wine_dbg_sprintf("%s", buffer.str); }
const char *debug_d3ddeclmethod(enum wined3d_decl_method method) @@ -6014,9 +6048,9 @@ int wined3d_ffp_vertex_program_key_compare(const void *key, const struct wine_rb
const char *wined3d_debug_location(DWORD location) { + struct debug_buffer buffer; const char *prefix = ""; const char *suffix = ""; - char buf[294];
if (wined3d_popcount(location) > 16) { @@ -6025,8 +6059,8 @@ const char *wined3d_debug_location(DWORD location) suffix = ")"; }
- buf[0] = '\0'; -#define LOCATION_TO_STR(u) if (location & u) { strcat(buf, " | "#u); location &= ~u; } + init_debug_buffer(&buffer, "0"); +#define LOCATION_TO_STR(x) if (location & x) { debug_append(&buffer, #x, " | "); location &= ~x; } LOCATION_TO_STR(WINED3D_LOCATION_DISCARDED); LOCATION_TO_STR(WINED3D_LOCATION_SYSMEM); LOCATION_TO_STR(WINED3D_LOCATION_USER_MEMORY); @@ -6037,9 +6071,10 @@ const char *wined3d_debug_location(DWORD location) LOCATION_TO_STR(WINED3D_LOCATION_RB_MULTISAMPLE); LOCATION_TO_STR(WINED3D_LOCATION_RB_RESOLVED); #undef LOCATION_TO_STR - if (location) FIXME("Unrecognized location flag(s) %#x.\n", location); + if (location) + FIXME("Unrecognized location flag(s) %#x.\n", location);
- return wine_dbg_sprintf("%s%s%s", prefix, buf[0] ? &buf[3] : "0", suffix); + return wine_dbg_sprintf("%s%s%s", prefix, buffer.str, suffix); }
/* Print a floating point value with the %.8e format specifier, always using
Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
There is some overlap between the new tests and the visual StretchRect() tests.
--- dlls/d3d9/tests/device.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+)
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index 0ffc1aeb9727..0bd5016b11f7 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -12246,6 +12246,184 @@ static void test_swapchain_multisample_reset(void) DestroyWindow(window); }
+static void test_stretch_rect(void) +{ + IDirect3DTexture9 *src_texture, *dst_texture; + IDirect3DSurface9 *src_surface, *dst_surface; + IDirect3DSurface9 *src_rt, *dst_rt; + D3DFORMAT src_format, dst_format; + IDirect3DSurface9 *src, *dst; + D3DPOOL src_pool, dst_pool; + BOOL can_stretch_textures; + IDirect3DDevice9 *device; + HRESULT expected_hr; + unsigned int i, j; + IDirect3D9 *d3d; + ULONG refcount; + D3DCAPS9 caps; + HWND window; + HRESULT hr; + + static const D3DFORMAT formats[] = + { + D3DFMT_A8R8G8B8, + D3DFMT_X8R8G8B8, + D3DFMT_R5G6B5, + }; + + window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, NULL, NULL, NULL, NULL); + ok(!!window, "Failed to create a window.\n"); + d3d = Direct3DCreate9(D3D_SDK_VERSION); + ok(!!d3d, "Failed to create a D3D object.\n"); + + if (!(device = create_device(d3d, window, NULL))) + { + skip("Failed to create a 3D device.\n"); + IDirect3D9_Release(d3d); + DestroyWindow(window); + return; + } + + memset(&caps, 0, sizeof(caps)); + hr = IDirect3DDevice9_GetDeviceCaps(device, &caps); + ok(hr == D3D_OK, "Failed to get caps, hr %#x.\n", hr); + can_stretch_textures = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES; + + for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i) + { + src_format = formats[i]; + if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, src_format)) + || FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, src_format))) + { + skip("Format %#x not supported.\n", src_format); + continue; + } + + for (j = 0; j < sizeof(formats) / sizeof(*formats); ++j) + { + dst_format = formats[j]; + if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, dst_format)) + || FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, dst_format))) + { + skip("Format %#x not supported.\n", dst_format); + continue; + } + + hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, src_format, + D3DMULTISAMPLE_NONE, 0, FALSE, &src_rt, NULL); + ok(hr == D3D_OK, "Failed to create render target, hr %#x.\n", hr); + hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, dst_format, + D3DMULTISAMPLE_NONE, 0, FALSE, &dst_rt, NULL); + ok(hr == D3D_OK, "Failed to create render target, hr %#x.\n", hr); + + hr = IDirect3DDevice9_StretchRect(device, src_rt, NULL, dst_rt, NULL, D3DTEXF_NONE); + ok(hr == D3D_OK, "Got hr %#x (formats %#x/%#x).\n", hr, src_format, dst_format); + + for (src_pool = D3DPOOL_DEFAULT; src_pool <= D3DPOOL_SCRATCH; ++src_pool) + { + for (dst_pool = D3DPOOL_DEFAULT; dst_pool <= D3DPOOL_SCRATCH; ++dst_pool) + { + hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0, + src_format, src_pool, &src_texture, NULL); + ok(hr == D3D_OK, "Failed to create texture, hr %#x.\n", hr); + hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0, + dst_format, dst_pool, &dst_texture, NULL); + ok(hr == D3D_OK, "Failed to create texture, hr %#x.\n", hr); + hr = IDirect3DTexture9_GetSurfaceLevel(src_texture, 0, &src); + ok(hr == D3D_OK, "Failed to get surface, hr %#x.\n", hr); + hr = IDirect3DTexture9_GetSurfaceLevel(dst_texture, 0, &dst); + ok(hr == D3D_OK, "Failed to get surface, hr %#x.\n", hr); + IDirect3DTexture9_Release(src_texture); + IDirect3DTexture9_Release(dst_texture); + + hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst, NULL, D3DTEXF_NONE); + todo_wine + ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n", + hr, src_format, dst_format, src_pool, dst_pool); + + /* render target <-> texture */ + if (src_pool == D3DPOOL_DEFAULT && can_stretch_textures) + expected_hr = D3D_OK; + else + expected_hr = D3DERR_INVALIDCALL; + hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst_rt, NULL, D3DTEXF_NONE); + todo_wine_if(expected_hr != D3D_OK) + ok(hr == expected_hr, "Got hr %#x, expected hr %#x (formats %#x/%#x, pool %#x).\n", + hr, expected_hr, src_format, dst_format, src_pool); + hr = IDirect3DDevice9_StretchRect(device, src_rt, NULL, dst, NULL, D3DTEXF_NONE); + todo_wine + ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pool %#x).\n", + hr, src_format, dst_format, dst_pool); + + if (src_pool == D3DPOOL_MANAGED || dst_pool == D3DPOOL_MANAGED) + { + IDirect3DSurface9_Release(src); + IDirect3DSurface9_Release(dst); + continue; + } + + if (src_pool == D3DPOOL_DEFAULT && dst_pool == D3DPOOL_DEFAULT) + expected_hr = D3D_OK; + else + expected_hr = D3DERR_INVALIDCALL; + + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32, + src_format, src_pool, &src_surface, NULL); + ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr); + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32, + dst_format, dst_pool, &dst_surface, NULL); + ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr); + + hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, dst_surface, NULL, D3DTEXF_NONE); + todo_wine_if(expected_hr != D3D_OK) + ok(hr == expected_hr, "Got hr %#x, expected %#x (formats %#x/%#x, pools %#x/%#x).\n", + hr, expected_hr, src_format, dst_format, src_pool, dst_pool); + + /* offscreen plain <-> texture */ + hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst_surface, NULL, D3DTEXF_NONE); + todo_wine + ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n", + hr, src_format, dst_format, src_pool, dst_pool); + hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, dst, NULL, D3DTEXF_NONE); + todo_wine + ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n", + hr, src_format, dst_format, src_pool, dst_pool); + + /* offscreen plain <-> render target */ + expected_hr = src_pool == D3DPOOL_DEFAULT ? D3D_OK : D3DERR_INVALIDCALL; + hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, dst_rt, NULL, D3DTEXF_NONE); + todo_wine_if(expected_hr != D3D_OK) + ok(hr == expected_hr, "Got hr %#x, expected hr %#x (formats %#x/%#x, pool %#x).\n", + hr, expected_hr, src_format, dst_format, src_pool); + hr = IDirect3DDevice9_StretchRect(device, src_rt, NULL, dst_surface, NULL, D3DTEXF_NONE); + todo_wine + ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pool %#x).\n", + hr, src_format, dst_format, dst_pool); + + IDirect3DSurface9_Release(src_surface); + IDirect3DSurface9_Release(dst_surface); + + IDirect3DSurface9_Release(src); + IDirect3DSurface9_Release(dst); + } + } + + IDirect3DSurface9_Release(src_rt); + IDirect3DSurface9_Release(dst_rt); + } + } + + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + IDirect3D9_Release(d3d); + DestroyWindow(window); +} + START_TEST(device) { WNDCLASSA wc = {0}; @@ -12368,6 +12546,7 @@ START_TEST(device) test_lockable_backbuffer(); test_clip_planes_limits(); test_swapchain_multisample_reset(); + test_stretch_rect();
UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL)); }
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
On 22 February 2018 at 19:13, Józef Kucia jkucia@codeweavers.com wrote:
- for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i)
ARRAY_SIZE
On Fri, Feb 23, 2018 at 1:16 PM, Henri Verbeet hverbeet@gmail.com wrote:
On 22 February 2018 at 19:13, Józef Kucia jkucia@codeweavers.com wrote:
- for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i)
ARRAY_SIZE
Right, it was initially a visual test, and visual.c does not have an ARRAY_SIZE() macro yet.
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/d3d9/device.c | 11 +++++++++++ dlls/d3d9/tests/device.c | 13 +++++-------- 2 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 5e0f55838f68..3d3d27332cbc 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -1612,6 +1612,17 @@ static HRESULT WINAPI d3d9_device_StretchRect(IDirect3DDevice9Ex *iface, IDirect src_rect = &s; }
+ if (dst_desc.access & WINED3D_RESOURCE_ACCESS_CPU) + { + WARN("Destination resource is not in DEFAULT pool.\n"); + goto done; + } + if (src_desc.access & WINED3D_RESOURCE_ACCESS_CPU) + { + WARN("Source resource is not in DEFAULT pool.\n"); + goto done; + } + if (src_desc.usage & WINED3DUSAGE_DEPTHSTENCIL) { if (device->in_scene) diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index 0bd5016b11f7..0f3abf38ec06 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -12342,7 +12342,7 @@ static void test_stretch_rect(void) IDirect3DTexture9_Release(dst_texture);
hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst, NULL, D3DTEXF_NONE); - todo_wine + todo_wine_if(src_pool == D3DPOOL_DEFAULT && dst_pool == D3DPOOL_DEFAULT) ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n", hr, src_format, dst_format, src_pool, dst_pool);
@@ -12352,11 +12352,10 @@ static void test_stretch_rect(void) else expected_hr = D3DERR_INVALIDCALL; hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst_rt, NULL, D3DTEXF_NONE); - todo_wine_if(expected_hr != D3D_OK) ok(hr == expected_hr, "Got hr %#x, expected hr %#x (formats %#x/%#x, pool %#x).\n", hr, expected_hr, src_format, dst_format, src_pool); hr = IDirect3DDevice9_StretchRect(device, src_rt, NULL, dst, NULL, D3DTEXF_NONE); - todo_wine + todo_wine_if(dst_pool == D3DPOOL_DEFAULT) ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pool %#x).\n", hr, src_format, dst_format, dst_pool);
@@ -12380,28 +12379,26 @@ static void test_stretch_rect(void) ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, dst_surface, NULL, D3DTEXF_NONE); - todo_wine_if(expected_hr != D3D_OK) ok(hr == expected_hr, "Got hr %#x, expected %#x (formats %#x/%#x, pools %#x/%#x).\n", hr, expected_hr, src_format, dst_format, src_pool, dst_pool);
/* offscreen plain <-> texture */ hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst_surface, NULL, D3DTEXF_NONE); - todo_wine + todo_wine_if(src_pool == D3DPOOL_DEFAULT && dst_pool == D3DPOOL_DEFAULT) ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n", hr, src_format, dst_format, src_pool, dst_pool); hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, dst, NULL, D3DTEXF_NONE); - todo_wine + todo_wine_if(src_pool == D3DPOOL_DEFAULT && dst_pool == D3DPOOL_DEFAULT) ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n", hr, src_format, dst_format, src_pool, dst_pool);
/* offscreen plain <-> render target */ expected_hr = src_pool == D3DPOOL_DEFAULT ? D3D_OK : D3DERR_INVALIDCALL; hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, dst_rt, NULL, D3DTEXF_NONE); - todo_wine_if(expected_hr != D3D_OK) ok(hr == expected_hr, "Got hr %#x, expected hr %#x (formats %#x/%#x, pool %#x).\n", hr, expected_hr, src_format, dst_format, src_pool); hr = IDirect3DDevice9_StretchRect(device, src_rt, NULL, dst_surface, NULL, D3DTEXF_NONE); - todo_wine + todo_wine_if(dst_pool == D3DPOOL_DEFAULT) ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pool %#x).\n", hr, src_format, dst_format, dst_pool);
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/d3d9/device.c | 6 ++++++ dlls/d3d9/tests/device.c | 3 --- dlls/d3d9/tests/visual.c | 16 ++++++++-------- 3 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 3d3d27332cbc..1c9a625223c6 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -1623,6 +1623,12 @@ static HRESULT WINAPI d3d9_device_StretchRect(IDirect3DDevice9Ex *iface, IDirect goto done; }
+ if (dst->texture && !(dst_desc.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) + { + WARN("Destination is a texture.\n"); + goto done; + } + if (src_desc.usage & WINED3DUSAGE_DEPTHSTENCIL) { if (device->in_scene) diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index 0f3abf38ec06..6084fd209a79 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -12342,7 +12342,6 @@ static void test_stretch_rect(void) IDirect3DTexture9_Release(dst_texture);
hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst, NULL, D3DTEXF_NONE); - todo_wine_if(src_pool == D3DPOOL_DEFAULT && dst_pool == D3DPOOL_DEFAULT) ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n", hr, src_format, dst_format, src_pool, dst_pool);
@@ -12355,7 +12354,6 @@ static void test_stretch_rect(void) ok(hr == expected_hr, "Got hr %#x, expected hr %#x (formats %#x/%#x, pool %#x).\n", hr, expected_hr, src_format, dst_format, src_pool); hr = IDirect3DDevice9_StretchRect(device, src_rt, NULL, dst, NULL, D3DTEXF_NONE); - todo_wine_if(dst_pool == D3DPOOL_DEFAULT) ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pool %#x).\n", hr, src_format, dst_format, dst_pool);
@@ -12388,7 +12386,6 @@ static void test_stretch_rect(void) ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n", hr, src_format, dst_format, src_pool, dst_pool); hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, dst, NULL, D3DTEXF_NONE); - todo_wine_if(src_pool == D3DPOOL_DEFAULT && dst_pool == D3DPOOL_DEFAULT) ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n", hr, src_format, dst_format, src_pool, dst_pool);
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 23fd1fbfaa4c..08d1849b36da 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -3743,7 +3743,7 @@ static void stretchrect_test(void)
/* offscreenplain ==> texture, same size (should fail). */ hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_tex_dest64, NULL, D3DTEXF_NONE); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
/* Fill the smaller offscreen surface with red. */ fill_surface(surf_offscreen32, 0xffff0000, 0); @@ -3769,7 +3769,7 @@ static void stretchrect_test(void)
/* offscreenplain ==> texture, scaling (should fail). */ hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_tex_dest64, NULL, D3DTEXF_NONE); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
/************************************************************* * Tests for when the source parameter is a regular texture. * @@ -3826,7 +3826,7 @@ static void stretchrect_test(void)
/* texture ==> texture, same size (should fail). */ hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_tex_dest64, NULL, D3DTEXF_NONE); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
/* Fill the surface of the smaller regular texture with red. */ /* Can't fill the surf_tex directly because it's created in D3DPOOL_DEFAULT. */ @@ -3855,7 +3855,7 @@ static void stretchrect_test(void)
/* texture ==> texture, scaling (should fail). */ hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_tex_dest64, NULL, D3DTEXF_NONE); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
/****************************************************************** * Tests for when the source parameter is a rendertarget texture. * @@ -3912,7 +3912,7 @@ static void stretchrect_test(void)
/* rendertarget texture ==> texture, same size (should fail). */ hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_tex_dest64, NULL, D3DTEXF_NONE); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
/* Fill the surface of the smaller rendertarget texture with red. */ /* Can't fill the surf_tex_rt directly because it's created in D3DPOOL_DEFAULT. */ @@ -3941,7 +3941,7 @@ static void stretchrect_test(void)
/* rendertarget texture ==> texture, scaling (should fail). */ hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_tex_dest64, NULL, D3DTEXF_NONE); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
/****************************************************************** * Tests for when the source parameter is a rendertarget surface. * @@ -3995,7 +3995,7 @@ static void stretchrect_test(void)
/* rendertarget surface ==> texture, same size (should fail). */ hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_tex_dest64, NULL, D3DTEXF_NONE); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
/* Fill the surface of the smaller rendertarget texture with red. */ fill_surface(surf_rt32, 0xffff0000, 0); @@ -4021,7 +4021,7 @@ static void stretchrect_test(void)
/* rendertarget surface ==> texture, scaling (should fail). */ hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_tex_dest64, NULL, D3DTEXF_NONE); - todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
/* backbuffer ==> surface tests (no scaling). */ /* Blit with NULL rectangles. */
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=36149
Your paranoid android.
=== w1064 (32 bit visual) === visual.c:8499: Test failed: Got unexpected color 0x00007580 for quad 2 (different colors).
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
On 22 February 2018 at 19:13, Józef Kucia jkucia@codeweavers.com wrote:
- if (dst->texture && !(dst_desc.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL)))
- {
WARN("Destination is a texture.\n");
goto done;
- }
The WARN is a little inaccurate since e.g. rendertarget textures are fine.
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/wined3d/surface.c | 71 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 26 deletions(-)
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 6e80f85773cc..72bf9d32ff8f 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1402,21 +1402,21 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr }
static void read_from_framebuffer(struct wined3d_surface *surface, - struct wined3d_context *old_ctx, DWORD dst_location) + struct wined3d_context *old_ctx, DWORD src_location, DWORD dst_location) { unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface); struct wined3d_texture *texture = surface->container; struct wined3d_device *device = texture->resource.device; - const struct wined3d_gl_info *gl_info; struct wined3d_context *context = old_ctx; struct wined3d_surface *restore_rt = NULL; + const struct wined3d_gl_info *gl_info; unsigned int row_pitch, slice_pitch; + struct wined3d_bo_address data; unsigned int width, height; - BYTE *mem; BYTE *row, *top, *bottom; - int i; - BOOL srcIsUpsideDown; - struct wined3d_bo_address data; + BOOL src_is_upside_down; + unsigned int i; + BYTE *mem;
wined3d_texture_get_memory(texture, sub_resource_idx, &data, dst_location);
@@ -1425,21 +1425,30 @@ static void read_from_framebuffer(struct wined3d_surface *surface, context = context_acquire(device, texture, sub_resource_idx); else restore_rt = NULL; - - context_apply_blit_state(context, device); gl_info = context->gl_info;
+ if (src_location != texture->resource.draw_binding) + { + context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, surface, NULL, src_location); + context_check_fbo_status(context, GL_READ_FRAMEBUFFER); + context_invalidate_state(context, STATE_FRAMEBUFFER); + } + else + { + context_apply_blit_state(context, device); + } + /* Select the correct read buffer, and give some debug output. - * There is no need to keep track of the current read buffer or reset it, every part of the code - * that reads sets the read buffer as desired. + * There is no need to keep track of the current read buffer or reset it, + * every part of the code that reads sets the read buffer as desired. */ - if (wined3d_resource_is_offscreen(&texture->resource)) + if (src_location != WINED3D_LOCATION_DRAWABLE || wined3d_resource_is_offscreen(&texture->resource)) { /* Mapping the primary render target which is not on a swapchain. * Read from the back buffer. */ TRACE("Mapping offscreen render target.\n"); gl_info->gl_ops.gl.p_glReadBuffer(context_get_offscreen_gl_buffer(context)); - srcIsUpsideDown = TRUE; + src_is_upside_down = TRUE; } else { @@ -1447,9 +1456,9 @@ static void read_from_framebuffer(struct wined3d_surface *surface, GLenum buffer = wined3d_texture_get_gl_buffer(texture); TRACE("Mapping %#x buffer.\n", buffer); gl_info->gl_ops.gl.p_glReadBuffer(buffer); - checkGLcall("glReadBuffer"); - srcIsUpsideDown = FALSE; + src_is_upside_down = FALSE; } + checkGLcall("glReadBuffer");
if (data.buffer_object) { @@ -1474,7 +1483,7 @@ static void read_from_framebuffer(struct wined3d_surface *surface, gl_info->gl_ops.gl.p_glPixelStorei(GL_PACK_ROW_LENGTH, 0); checkGLcall("glPixelStorei");
- if (!srcIsUpsideDown) + if (!src_is_upside_down) { /* glReadPixels returns the image upside down, and there is no way to * prevent this. Flip the lines in software. */ @@ -2134,24 +2143,34 @@ static BOOL surface_load_sysmem(struct wined3d_surface *surface, sub_resource = &texture->sub_resources[sub_resource_idx]; wined3d_texture_prepare_location(texture, sub_resource_idx, context, dst_location);
- if (sub_resource->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)) - wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); - - /* Download the surface to system memory. */ - if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + /* We cannot download data from multisample textures directly. */ + if (is_multisample_location(texture, WINED3D_LOCATION_TEXTURE_RGB)) { - wined3d_texture_bind_and_dirtify(texture, context, - !(sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)); - surface_download_data(surface, gl_info, dst_location); - ++texture->download_count; - + wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_RB_RESOLVED); + read_from_framebuffer(surface, context, WINED3D_LOCATION_RB_RESOLVED, dst_location); return TRUE; } + else + { + if (sub_resource->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)) + wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); + + /* Download the surface to system memory. */ + if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + { + wined3d_texture_bind_and_dirtify(texture, context, + !(sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB)); + surface_download_data(surface, gl_info, dst_location); + ++texture->download_count; + + return TRUE; + } + }
if (!(texture->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) && (sub_resource->locations & WINED3D_LOCATION_DRAWABLE)) { - read_from_framebuffer(surface, context, dst_location); + read_from_framebuffer(surface, context, texture->resource.draw_binding, dst_location); return TRUE; }
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/wined3d/wined3d_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c index cc0dc252c115..b57bcdcc8738 100644 --- a/dlls/wined3d/wined3d_main.c +++ b/dlls/wined3d/wined3d_main.c @@ -81,7 +81,7 @@ struct wined3d_settings wined3d_settings = PCI_DEVICE_NONE,/* PCI Device ID */ 0, /* The default of memory is set in init_driver_info */ NULL, /* No wine logo by default */ - FALSE, /* Prefer multisample renderbuffers to multisample textures by default. */ + TRUE, /* Prefer multisample textures to multisample renderbuffers. */ ~0u, /* Don't force a specific sample count by default. */ FALSE, /* No strict draw ordering. */ FALSE, /* Don't range check relative addressing indices in float constants. */
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
On 22 February 2018 at 19:13, Józef Kucia jkucia@codeweavers.com wrote:
+static BOOL debug_append(struct debug_buffer *buffer, const char *str, const char *separator) +{
- int size;
- if (!separator || buffer->ptr == buffer->str)
separator = "";
- size = snprintf(buffer->ptr, buffer->size, "%s%s", separator, str);
- if (size == -1 || size >= buffer->size)
- {
buffer->size = 0;
return FALSE;
- }
I'm not especially concerned about it, but note that this would give no indication that any text was omitted. It may be helpful to e.g. replace the end of the debug string with "..." when this happens.