Search code examples
direct3ddirect2d

Copy From RenderTarget to Host Memory


Using Direct2D I would like to be able to either render to system memory or copy the content of a render target to system memory.

Is that possible with Direct2D? Or will I have to do some d3d interop?


Solution

  • You can use ID2D1Factory::CreateWICBitmapRenderTarget to render on a WIC bitmap, and you can then read in the pixels from the WIC bitmap. Something along these lines:

    ID2D1Factory* d2dfac = 0;
    D2D1CreateFactory( D2D1_FACTORY_TYPE_SINGLE_THREADED, &d2dfac );
    
    IWICImagingFactory* wicfac = 0;
    CoCreateInstance( CLSID_WICImagingFactory, 0, CLSCTX_INPROC_SERVER,
              IID_IWICImagingFactory, (void**)&wicfac );
    
    IWICBitmap* bmp = 0;
    wicfac->CreateBitmap( width, height,
                          GUID_WICPixelFormat32bppPBGRA,
                          WICBitmapCacheOnLoad, &bmp );
    
    ID2D1RenderTarget* render = 0;
    d2dfac->CreateWicBitmapRenderTarget(
        bmp,
        D2D1::RenderTargetProperties( D2D1_RENDER_TARGET_TYPE_DEFAULT,
                                      D2D1::PixelFormat( DXGI_FORMAT_B8G8R8A8_UNORM,
                                                         D2D1_ALPHA_MODE_PREMULTIPLIED ),
                                      0.f, 0.f,
                                      D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE ),
        &render );
    
    render->BeginDraw();
    // ... Draw on the render target ...
    render->EndDraw( 0, 0 );
    
    WICRect rect = { 0, 0, width, height };
    IWICBitmapLock* lock = 0;
    bmp->Lock( &rect, WICBitmapLockRead, &lock );
    
    BYTE* data = 0;
    UINT sz = 0;
    lock->GetDataPointer( &sz, &data );