0

I am working on an app that displays pages of a document (when it's done, it is going to look like the screenshot below).
The main window has 2 sub windows each with their own ID2D1RenderTarget one for showing the thumbnails and one for the main view. When document is being loaded, an ID2D1Bitmap is created for each page using the render target of the thumbnail view. Then that bitmap is converted into a Shared Bitmap using CreateSharedBitmap function of the same render target. This shared bitmap can be drawn on the same render target that created it.
The problem is when I try to use that same shared bitmap to draw on the render target of the main view, nothing is printed (not even other objects) and the EndDraw returns -2003238891.
If I use the render target of the main view to create the bitmap, it draws correctly on the main view and not on the thumbnail view(EndDraw returns the same error code).

Anyone knows how I can overcome this issue?

Thank you Sam

Screenshot of what the application should look like when it is finished

Sam
  • 2,473
  • 3
  • 18
  • 29
  • -2003238891 to 0x88990015 are related through 2s complement. The easiest way to convert a 32-bit number from "negative" form into "2s complement" form (the actual binary representation) is to add 2^32 (aka 4294967296). In this case, (-2003238891 + 4294967296 == 2291728405, which is 0x88990015 in hex) – Dragontamer5788 Oct 07 '17 at 06:11

2 Answers2

0

The error is D2DERR_WRONG_RESOURCE_DOMAIN 0x88990015 "The resource used was created by a render target in a different resource domain."

The description should be pretty accurate: you queued an operation with an incompatible resource as an argument, however since the execution is asynchronous you only have the failure in EndDraw.

Possible Causes

This message occurs when an application has attempted a drawing operation that mixes resources from different resource domains. Device contexts, brushes, and bitmaps, for example, are device-specific. While performing an operation such as ID2D1DeviceContext::DrawBitmap, the argument bitmap should belong to the same resource domain as the device context. In this example, a way to ensure this is to create the bitmap using that device context’s CreateBitmap member function, rather than that of some other device context.

Possible Fixes

When groups of resources should be used together, ensure they are created from the same ID2D1Device. Non-target resources created directly from an ID2D1Factory, such as state blocks and geometries, and are considered device-independent and do not have this restriction.

See also:

Community
  • 1
  • 1
Roman R.
  • 68,205
  • 6
  • 94
  • 158
  • perhaps I have not correctly understood the concept of ***Shared Bitmap***. According to [CreateSharedBitmap](https://msdn.microsoft.com/en-us/library/windows/desktop/dd371865(v=vs.85).aspx)'s documentation,
    Creates an ID2D1Bitmap whose data is shared with another resource.
    . Also how did you translate `-2003238891` to `0x88990015`?
    – Sam Jun 16 '16 at 20:48
0

HRESULT hr, hr is a long integer.

if (FAILED(hr))...

WCHAR string[20]; swprintf(string, 20, "%x", hr); MessageBox(NULL, string, NULL, MB_OK);

This should help as the first step to decode the hresult errors.

The shared bitmap is not documented that well but here is one advantage that I've found.

When you create a shared bitmap from a WIC bitmap, you can basically display the wic bitmap by using render_tgt->DrawBitmap(...) without the need to copy the pixels to the bitmap first. On a side note, the WIC bitmap and wic_lock interface allows you to address the pixels directly.

So far, I have not seen any method to work backwards and create a render target from a bitmap or shared bitmap or memory. Even the CreateBitmapFromMemory method just copies the data into a d2d bitmap and any updates to the d2d bitmap does not affect the memory it was created from. To create a shared bitmap your render target must be software type. Direct 3D does not support Direct 2D software render targets. Don't give up. There might be some guru out there that can figure out if QueryInterface will unlock some magical hidden useful features from a shared d2d bitmap.

Software Usage: Create a WIC bitmap on the "child" Create a D2D Render target from the WIC bitmap Create a Shared bitmap from the main window every time you need to display the bitmap then release it immediately. Notes: The bitmap properties must be compatible between the render targets and wic bitmap and the shared bitmap
Notes: you cannot use the wic-d2d-render-target while the wic lock or shared bitmap are active.

This way the WIC bitmap is your anchor. This would be a workaround to using shared memory.

Maintain Hardware usage: child -> copy the bitmap bits to memory main -> copy the memory into a bitmap created by the main window. Either way, the bitmap properties such as bppp, order or bytes, etc.. must be compatible between render targets for the child and main window

HRESULT XMAIN::Create_HWnd_Tgt(ID2D1HwndRenderTarget **hwnd_tgt, HWND hwnd, bool makebmp)
{
if (hwnd == NULL) { return E_POINTER; }
if (hwnd_tgt == NULL) { return E_POINTER; }

if (demo.d2d.factory == NULL) { return E_FAIL; }

HRESULT hr = S_OK;

RECT rc = { 0 };

SafeRelease(hwnd_tgt);

GetClientRect(hwnd, &rc);

D2D1_RENDER_TARGET_PROPERTIES rt_props = D2D1::RenderTargetProperties();

D2D1_SIZE_U size = D2D1::SizeU((rc.right - rc.left), (rc.bottom - rc.top));

//This is required when using a wic shared bitmap
rt_props.type = D2D1_RENDER_TARGET_TYPE_SOFTWARE;

rt_props.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
rt_props.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
rt_props.dpiX = 0;
rt_props.dpiY = 0;
rt_props.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
rt_props.minLevel = D2D1_FEATURE_LEVEL_9;//D2D1_FEATURE_LEVEL_DEFAULT;

// Create a Direct2D render target.

hr = demo.d2d.factory->CreateHwndRenderTarget(
    rt_props,
    D2D1::HwndRenderTargetProperties(hwnd, size),
    hwnd_tgt
);

if ((*hwnd_tgt) == NULL) {}

return hr;
}