Jump to content
  • Advertisement
MarcinWSB

DX11 Sharing surface with ID2D1DCRenderTarget created by CreateDCRenderTarget

Recommended Posts

I have found an example here:
 
 
about sharing surfaces/textures created by DX11 into the ID2D1DCRenderTarget, however the above example is based on SwapChain bound to a window (hwnd)
 
What I need is to draw a shared texture into GDI as this is the only plugin interface in an old software I have. Any ideas ?
 
Here is what I do.
 
SharedSurface::SharedSurface():
{

	//Initialize the ID2D1Factory object
	D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory);
	//D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, &pD2DFactory);
	//initialize the ID2D1DCRenderTarget
	D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
		D2D1_RENDER_TARGET_TYPE_HARDWARE, // D2D1_RENDER_TARGET_TYPE_DEFAULT,
		D2D1::PixelFormat(
			DXGI_FORMAT_B8G8R8A8_UNORM,
			D2D1_ALPHA_MODE_PREMULTIPLIED),
		0,
		0,
		D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE,
		D2D1_FEATURE_LEVEL_DEFAULT
	);
	HRESULT hr = pD2DFactory->CreateDCRenderTarget(&props, &pRT);

	DWORD createDeviceFlags = 0;
	createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;

	ID3D11DeviceContext* context;
	D3D_FEATURE_LEVEL fl;

    DXGI_SWAP_CHAIN_DESC sd;
	ZeroMemory( &sd, sizeof( sd ) );
	sd.BufferCount = 1;
	sd.BufferDesc.Width = width;
	sd.BufferDesc.Height = height;
	sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	sd.BufferDesc.RefreshRate.Numerator = 60;
	sd.BufferDesc.RefreshRate.Denominator = 1;
	sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHARED;
	sd.OutputWindow = 0; // g_hWnd;
	sd.SampleDesc.Count = 1;
	sd.SampleDesc.Quality = 0;
	sd.Windowed = FALSE, // TRUE;		

	hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE,
		nullptr, createDeviceFlags, nullptr,
		0, D3D11_SDK_VERSION, &sd, &pSwapChain, &mDevice, &fl, &context);

	hr = m_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));		

}

bool SharedSurface::CreateTexture(ID3D11Device* device, UINT width, UINT height)
{
	HRESULT hr;
	D3D11_TEXTURE2D_DESC desc;
	ZeroMemory(&desc, sizeof(desc));
	desc.Width = width;
	desc.Height = height;
	desc.MipLevels = 1;
	desc.ArraySize = 1;
	desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
	desc.SampleDesc.Count = 1;

	desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; // D3D11_RESOURCE_MISC_SHARED; // 
	desc.Usage = D3D11_USAGE_DEFAULT;
	desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
	desc.CPUAccessFlags = 0; // D3D11_CPU_ACCESS_READ; // 0;

	if (device != nullptr)
		mDevice = device;

	hr = mDevice->CreateTexture2D(&desc, NULL, &pTexture);

	IDXGIResource * pDXGIResource = NULL;
	hr = pTexture->QueryInterface(__uuidof(IDXGIResource), (void **)&pDXGIResource);

	if SUCCEEDED(hr)
	{

		hr = pDXGIResource->GetSharedHandle(&sharedHandle);
		pDXGIResource->Release();

		if SUCCEEDED(hr)
		{
			hr = pTexture->QueryInterface(__uuidof(IDXGIKeyedMutex),
				(LPVOID*)&pMutex);

		}
	}


	hr = pTexture->QueryInterface(__uuidof(IDXGISurface), (void **)&pSurface);

	FLOAT dpiX;
    FLOAT dpiY;
    pD2DFactory->GetDesktopDpi(&dpiX, &dpiY);

	D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_HARDWARE/*D2D1_RENDER_TARGET_TYPE_DEFAULT*/, D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),dpiX,dpiY);

	hr = pD2DFactory->CreateDxgiSurfaceRenderTarget(pBackBuffer,&props,	&pBackBufferRT);

	DXGI_SURFACE_DESC sdesc;
	D2D1_BITMAP_PROPERTIES bp;
	ZeroMemory(&bp, sizeof(bp));
	pSurface->GetDesc(&sdesc);
	bp.pixelFormat = D2D1::PixelFormat(sdesc.Format, D2D1_ALPHA_MODE_PREMULTIPLIED);

	hr = pBackBufferRT->CreateSharedBitmap(__uuidof(ID3D11Texture2D), pSurface,&bp, &pBitmap);

	return SUCCEEDED(hr);

}

void SharedSurface::Draw()
{
	pBackBufferRT->BeginDraw();
	pBackBufferRT->DrawBitmap(pBitmap);
	pBackBufferRT->EndDraw();
	pBackBufferRT->Present();

}
void SharedSurface::BindDC(HDC hdc, int width, int height)
{
	RECT rct;
	rct.top = 0;
	rct.left = 0;
	rct.right = width;
	rct.bottom = height;
	pRT->BindDC(hdc, &rct);
}

// HOW TO EXCHANGE between pBackBufferRT and pRT ? 

 

Share this post


Link to post
Share on other sites
Advertisement

It looks like CreateDxgiSurfaceRenderTarget cannot be used with D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE and CreateSharedBitmap cannot be used with ID2D1DCRenderTarget as it must be used with render target created by CreateDxgiSurfaceRenderTarget , so looks there is no straight way to do it. Any tricks ?

Share this post


Link to post
Share on other sites

I am a bit unclear what you are trying to do. You can do 2 totally seperate things with directx2d in your directx3d program.

1. You can use directx2d to write to the swapchain backbuffer.

2. You can use direct2d to write to a texturebuffer that you use as a SRV in your 3d pipeline. This has nothing to do with the swapchain. For example you might want your pixel shader to use this texture to display some text on the side of an object.

See here for different things you can do  - https://msdn.microsoft.com/en-gb/library/windows/desktop/dd370966(v=vs.85).aspx

Share this post


Link to post
Share on other sites

The scenario is the following.

I have quite old app using dx9 which allows plugin integration. Unfortunately the plugin integration is through GDI, so I receive Paint callback with HDC. What I do is drawing into Texture2D using DX11 in another process and share the texture with GDI plugin. It works fine when I share the texture bits through CPU. Now, I want to use GPU only and use the texture sharing between DX11 and GDI so I tried to create ID2D1DCRenderTarget   but that I cannot link with any shared surface ...

Share this post


Link to post
Share on other sites

You'd need to create a swapchain on the corresponding HWND and Present() to copy the bits, or create a GDI_COMPATIBLE surface and use the IDXGISurface1::GetDC/ReleaseDC methods to get a second DC, and use GDI to do the copy.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!