Search code examples
xamluwpdirectxdirect2d

DirectX:- How to copy a pointer image data to the existing D2D1Bitmap?


I've 4 image byte array with the same resolution 640*480. I'm trying to copy the byte array data from memory if the D2D1Bitmap is already available. After copying, d2dContext.DrawBitmap(bitmap) method fails, Here is the code,

Any pointers on what I'm missing?

        if (bitmap == nullptr)
        {
            hr = m_d2dContext->CreateBitmap(D2D1::SizeU(width, height),
                buffer->Data,
                width * 4,
                //(width * height) / 2 * 3,
                D2D1::BitmapProperties(D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE)),
                //D2D1::BitmapProperties(D2D1::PixelFormat(DXGI_FORMAT_NV12,D2D1_ALPHA_MODE_IGNORE)),
                &bitmap);
            if (FAILED(hr))
            {
                return;
            }
        }
        else
        {
            D2D1_SIZE_F rtSize = m_d2dTargetBitmap->GetSize();
            D2D1_RECT_U rect = D2D1::RectU(
                0,
                0,
                rtSize.width,
                rtSize.height
            );
            hr = bitmap->CopyFromMemory(&rect , buffer->Data, width * 4);                
        }

        m_d2dContext->BeginDraw();               
        m_d2dContext->DrawBitmap(bitmap);
        //bitmap->Release();
        hr = m_d2dContext->EndDraw();

Solution

  • An ID2D1Bitmap is a context-bound resource, since it's created from a ID2D1RenderTarget interface using ID2D1RenderTarget::CreateBitmap

    It means you cannot create a static ID2D1Bitmap and use it on multiple context like you do. When you do this, on EndDraw, you get messages like this one when debugging (since the DirectX Debug Layer is enabled thanks to the options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION we can see in the sample code), in the Visual Studio output window:

    D2D DEBUG ERROR - The resource [00000194E6EDD838] was allocated by factory [00000194B3973918] and used with factory [0000000000000000].
    

    In your context, one solution is to make the bitmap reference member of the D3DPanel class and use it the same way as you do:

    public ref class D3DPanel sealed : public DirectXPanels::DirectXPanelBase
    {
        ...
        ID2D1Bitmap* m_bitmap;
        ...
    };
    
    ....
    
    if (m_bitmap == nullptr)
    {
        m_d2dContext->CreateBitmap(...,  &m_bitmap);
    }
    else
    {
        m_bitmap->CopyFromMemory(&rect , buffer->Data, width * 4);                
    }
    
    m_d2dContext->BeginDraw();               
    m_d2dContext->DrawBitmap(m_bitmap);
    m_d2dContext->EndDraw();
    

    PS: you shall Release the bitmap when you release the context, for example in class destructor.