From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/bitmap.c | 3 +++ dlls/d2d1/tests/d2d1.c | 8 ++++++++ 2 files changed, 11 insertions(+)
diff --git a/dlls/d2d1/bitmap.c b/dlls/d2d1/bitmap.c index 6a02279b91b..1c6383ae4a9 100644 --- a/dlls/d2d1/bitmap.c +++ b/dlls/d2d1/bitmap.c @@ -257,6 +257,9 @@ static HRESULT STDMETHODCALLTYPE d2d_bitmap_Map(ID2D1Bitmap1 *iface, D2D1_MAP_OP
TRACE("iface %p, options %#x, mapped_rect %p.\n", iface, options, mapped_rect);
+ if (!(bitmap->options & D2D1_BITMAP_OPTIONS_CPU_READ)) + return E_INVALIDARG; + if (bitmap->mapped_resource.pData) return D2DERR_WRONG_STATE;
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 807a7be5ae6..9706b02528b 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -11804,6 +11804,14 @@ static void test_bitmap_map(BOOL d3d11) ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); if (SUCCEEDED(hr)) ID2D1Bitmap1_Release(bitmap);
+ /* Create without D2D1_BITMAP_OPTIONS_CPU_READ, surface supports CPU reads. */ + bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_CANNOT_DRAW; + hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, surface, &bitmap_desc, &bitmap); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1Bitmap1_Map(bitmap, D2D1_MAP_OPTIONS_READ, &mapped_rect); + ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); + ID2D1Bitmap1_Release(bitmap); + ID3D11Texture2D_Release(texture); IDXGISurface_Release(surface);
Hi,
While running your changed tests, 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=115866
Your paranoid android.
=== debian11 (32 bit Hebrew:Israel report) ===
d2d1: Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7dab02f9).
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/bitmap.c | 24 ++++++++++++++++++++++++ dlls/d2d1/d2d1_private.h | 1 + dlls/d2d1/device.c | 2 +- dlls/d2d1/tests/d2d1.c | 1 - 4 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/dlls/d2d1/bitmap.c b/dlls/d2d1/bitmap.c index 1c6383ae4a9..097d984e3ae 100644 --- a/dlls/d2d1/bitmap.c +++ b/dlls/d2d1/bitmap.c @@ -495,6 +495,30 @@ HRESULT d2d_bitmap_create(struct d2d_device_context *context, D2D1_SIZE_U size, return *bitmap ? S_OK : E_OUTOFMEMORY; }
+unsigned int d2d_get_bitmap_options_for_surface(IDXGISurface *surface) +{ + D3D11_TEXTURE2D_DESC desc; + unsigned int options = 0; + ID3D11Texture2D *texture; + + if (FAILED(IDXGISurface_QueryInterface(surface, &IID_ID3D11Texture2D, (void **)&texture))) + return 0; + + ID3D11Texture2D_GetDesc(texture, &desc); + ID3D11Texture2D_Release(texture); + + if (desc.BindFlags & D3D11_BIND_RENDER_TARGET) + options |= D2D1_BITMAP_OPTIONS_TARGET; + if (!(desc.BindFlags & D3D11_BIND_SHADER_RESOURCE)) + options |= D2D1_BITMAP_OPTIONS_CANNOT_DRAW; + if (desc.MiscFlags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE) + options |= D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE; + if (desc.Usage == D3D11_USAGE_STAGING && desc.CPUAccessFlags & D3D11_CPU_ACCESS_READ) + options |= D2D1_BITMAP_OPTIONS_CPU_READ; + + return options; +} + HRESULT d2d_bitmap_create_shared(struct d2d_device_context *context, REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES1 *desc, struct d2d_bitmap **bitmap) { diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index 48649f6a916..efc9247a822 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -409,6 +409,7 @@ HRESULT d2d_bitmap_create_shared(struct d2d_device_context *context, REFIID iid, const D2D1_BITMAP_PROPERTIES1 *desc, struct d2d_bitmap **bitmap) DECLSPEC_HIDDEN; HRESULT d2d_bitmap_create_from_wic_bitmap(struct d2d_device_context *context, IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES1 *desc, struct d2d_bitmap **bitmap) DECLSPEC_HIDDEN; +unsigned int d2d_get_bitmap_options_for_surface(IDXGISurface *surface) DECLSPEC_HIDDEN; struct d2d_bitmap *unsafe_impl_from_ID2D1Bitmap(ID2D1Bitmap *iface) DECLSPEC_HIDDEN;
struct d2d_state_block diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index eb0c1935ebb..64b573da974 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -1876,7 +1876,7 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface( memset(&bitmap_desc, 0, sizeof(bitmap_desc)); bitmap_desc.pixelFormat.format = surface_desc.Format; bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; - bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW; + bitmap_desc.bitmapOptions = d2d_get_bitmap_options_for_surface(surface); desc = &bitmap_desc; }
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 9706b02528b..515c14e5adb 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -11782,7 +11782,6 @@ static void test_bitmap_map(BOOL d3d11) hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, surface, NULL, &bitmap); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); options = ID2D1Bitmap1_GetOptions(bitmap); - todo_wine ok(options == (D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ), "Unexpected options %#x.\n", options); ID2D1Bitmap1_Release(bitmap);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/bitmap.c | 1 + dlls/d2d1/device.c | 5 ++++- dlls/d2d1/tests/d2d1.c | 1 - 3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/d2d1/bitmap.c b/dlls/d2d1/bitmap.c index 097d984e3ae..cebabbe4a61 100644 --- a/dlls/d2d1/bitmap.c +++ b/dlls/d2d1/bitmap.c @@ -616,6 +616,7 @@ HRESULT d2d_bitmap_create_shared(struct d2d_device_context *context, REFIID iid, { memset(&d, 0, sizeof(d)); d.pixelFormat.format = surface_desc.Format; + d.bitmapOptions = d2d_get_bitmap_options_for_surface(surface); } else { diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index 64b573da974..b7faf33e266 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -405,7 +405,10 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSharedBitmap(ID2D1Devi if (desc) { memcpy(&bitmap_desc, desc, sizeof(*desc)); - bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW; + if (IsEqualIID(iid, &IID_IDXGISurface) || IsEqualIID(iid, &IID_IDXGISurface1)) + bitmap_desc.bitmapOptions = d2d_get_bitmap_options_for_surface(data); + else + bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW; bitmap_desc.colorContext = NULL; }
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 515c14e5adb..5185c07c29b 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -11772,7 +11772,6 @@ static void test_bitmap_map(BOOL d3d11) hr = ID2D1Bitmap_QueryInterface(bitmap2, &IID_ID2D1Bitmap1, (void **)&bitmap); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); options = ID2D1Bitmap1_GetOptions(bitmap); - todo_wine ok(options == (D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ), "Unexpected options %#x.\n", options);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/device.c | 56 ++++++++++++++++++++++++++++++++++-- dlls/d2d1/tests/d2d1.c | 65 +++++++++++++++++++++++++++++++++++------- 2 files changed, 109 insertions(+), 12 deletions(-)
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index b7faf33e266..12aa2acc331 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -1856,17 +1856,69 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromWicCol return E_NOTIMPL; }
+static BOOL d2d_bitmap_check_options_with_surface(unsigned int options, unsigned int surface_options) +{ + switch (options) + { + case D2D1_BITMAP_OPTIONS_NONE: + case D2D1_BITMAP_OPTIONS_TARGET: + case D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW: + case D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE: + case D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE: + case D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ: + case D2D1_BITMAP_OPTIONS_CANNOT_DRAW: + break; + default: + WARN("Invalid bitmap options %#x.\n", options); + return FALSE; + } + + if (options && (options & D2D1_BITMAP_OPTIONS_TARGET) != (surface_options & D2D1_BITMAP_OPTIONS_TARGET)) + return FALSE; + if (options & D2D1_BITMAP_OPTIONS_TARGET) + { + if (!(options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW) && (surface_options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW)) + return FALSE; + if (options & D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE && !(surface_options & D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE)) + return FALSE; + return TRUE; + } + + if (options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW) + { + if (!(surface_options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW)) + return FALSE; + + if (options & D2D1_BITMAP_OPTIONS_CPU_READ && !(surface_options & D2D1_BITMAP_OPTIONS_CPU_READ)) + return FALSE; + } + + return TRUE; +} + static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface(ID2D1DeviceContext *iface, IDXGISurface *surface, const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap) { struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface); D2D1_BITMAP_PROPERTIES1 bitmap_desc; + unsigned int surface_options; struct d2d_bitmap *object; HRESULT hr;
TRACE("iface %p, surface %p, desc %p, bitmap %p.\n", iface, surface, desc, bitmap);
- if (!desc) + surface_options = d2d_get_bitmap_options_for_surface(surface); + + if (desc) + { + if (!d2d_bitmap_check_options_with_surface(desc->bitmapOptions, surface_options)) + { + WARN("Incompatible bitmap options %#x, surface options %#x.\n", + desc->bitmapOptions, surface_options); + return E_INVALIDARG; + } + } + else { DXGI_SURFACE_DESC surface_desc;
@@ -1879,7 +1931,7 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface( memset(&bitmap_desc, 0, sizeof(bitmap_desc)); bitmap_desc.pixelFormat.format = surface_desc.Format; bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; - bitmap_desc.bitmapOptions = d2d_get_bitmap_options_for_surface(surface); + bitmap_desc.bitmapOptions = surface_options; desc = &bitmap_desc; }
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 5185c07c29b..c73039504d3 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -1213,6 +1213,24 @@ static BOOL init_test_context_(unsigned int line, struct d2d1_test_context *ctx, return TRUE; }
+#define check_bitmap_options(b, o) check_bitmap_options_(__LINE__, b, o) +static void check_bitmap_options_(unsigned int line, ID2D1Bitmap *bitmap, DWORD expected_options) +{ + D2D1_BITMAP_OPTIONS options; + ID2D1Bitmap1 *bitmap1; + HRESULT hr; + + hr = ID2D1Bitmap_QueryInterface(bitmap, &IID_ID2D1Bitmap1, (void **)&bitmap1); + if (FAILED(hr)) + return; + + options = ID2D1Bitmap1_GetOptions(bitmap1); + ok_(__FILE__, line)(options == expected_options, "Got unexpected bitmap options %#x, expected %#lx.\n", + options, expected_options); + + ID2D1Bitmap1_Release(bitmap1); +} + #define check_bitmap_surface(b, s, o) check_bitmap_surface_(__LINE__, b, s, o) static void check_bitmap_surface_(unsigned int line, ID2D1Bitmap *bitmap, BOOL has_surface, DWORD expected_options) { @@ -11605,6 +11623,7 @@ static void test_bitmap_map(BOOL d3d11) }; D2D1_BITMAP_PROPERTIES1 bitmap_desc; D3D11_TEXTURE2D_DESC texture_desc; + ID2D1Bitmap *bitmap2, *bitmap3; struct d2d1_test_context ctx; D2D1_MAPPED_RECT mapped_rect; ID3D11Device *d3d_device; @@ -11612,7 +11631,6 @@ static void test_bitmap_map(BOOL d3d11) unsigned int i, options; IDXGISurface *surface; ID2D1Bitmap1 *bitmap; - ID2D1Bitmap *bitmap2; D2D1_SIZE_U size; HRESULT hr;
@@ -11768,14 +11786,13 @@ static void test_bitmap_map(BOOL d3d11) hr = ID2D1DeviceContext_CreateSharedBitmap(ctx.context, &IID_IDXGISurface, surface, (const D2D1_BITMAP_PROPERTIES *)&bitmap_desc, &bitmap2); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + check_bitmap_options(bitmap2, D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ);
- hr = ID2D1Bitmap_QueryInterface(bitmap2, &IID_ID2D1Bitmap1, (void **)&bitmap); + hr = ID2D1DeviceContext_CreateSharedBitmap(ctx.context, &IID_ID2D1Bitmap, bitmap2, NULL, &bitmap3); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - options = ID2D1Bitmap1_GetOptions(bitmap); - ok(options == (D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ), - "Unexpected options %#x.\n", options); + check_bitmap_options(bitmap3, D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ); + ID2D1Bitmap_Release(bitmap3);
- ID2D1Bitmap1_Release(bitmap); ID2D1Bitmap_Release(bitmap2);
hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, surface, NULL, &bitmap); @@ -11788,9 +11805,7 @@ static void test_bitmap_map(BOOL d3d11) /* Options incompatible with the surface. */ bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET; hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, surface, &bitmap_desc, &bitmap); - todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) ID2D1Bitmap1_Release(bitmap); bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_NONE; hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, surface, &bitmap_desc, &bitmap); todo_wine @@ -11798,9 +11813,7 @@ static void test_bitmap_map(BOOL d3d11) if (SUCCEEDED(hr)) ID2D1Bitmap1_Release(bitmap); bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW; hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, surface, &bitmap_desc, &bitmap); - todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) ID2D1Bitmap1_Release(bitmap);
/* Create without D2D1_BITMAP_OPTIONS_CPU_READ, surface supports CPU reads. */ bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_CANNOT_DRAW; @@ -11813,6 +11826,38 @@ static void test_bitmap_map(BOOL d3d11) ID3D11Texture2D_Release(texture); IDXGISurface_Release(surface);
+ /* Surface D2D1_BITMAP_OPTIONS_TARGET */ + texture_desc.Width = 4; + texture_desc.Height = 4; + texture_desc.MipLevels = 1; + texture_desc.ArraySize = 1; + texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + texture_desc.SampleDesc.Count = 1; + texture_desc.SampleDesc.Quality = 0; + texture_desc.Usage = D3D11_USAGE_DEFAULT; + texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + texture_desc.CPUAccessFlags = 0; + texture_desc.MiscFlags = 0; + + hr = ID3D11Device_CreateTexture2D(d3d_device, &texture_desc, NULL, &texture); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID3D11Texture2D_QueryInterface(texture, &IID_IDXGISurface, (void **)&surface); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_TARGET; + hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, surface, &bitmap_desc, &bitmap); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ID2D1Bitmap1_Release(bitmap); + + bitmap_desc.bitmapOptions = 0; + hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, surface, &bitmap_desc, &bitmap); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + check_bitmap_options((ID2D1Bitmap *)bitmap, 0); + ID2D1Bitmap1_Release(bitmap); + + ID3D11Texture2D_Release(texture); + IDXGISurface_Release(surface); + ID3D11Device_Release(d3d_device);
release_test_context(&ctx);