Exemplo n.º 1
0
bool spoutDirectX::CreateSharedDX11Texture(ID3D11Device* pd3dDevice, 
											unsigned int width, 
											unsigned int height, 
											DXGI_FORMAT format, 
											ID3D11Texture2D** pSharedTexture,
											HANDLE &dxShareHandle)
{
	ID3D11Texture2D* pTexture;
	
	if(pd3dDevice == NULL)
		MessageBoxA(NULL, "CreateSharedDX11Texture NULL device", "SpoutSender", MB_OK);

	//
	// Create a new shared DX11 texture
	//

	pTexture = *pSharedTexture; // The texture pointer

	// if(pTexture == NULL) MessageBoxA(NULL, "CreateSharedDX11Texture NULL texture", "SpoutSender", MB_OK);

	// Textures being shared from D3D9 to D3D11 have the following restrictions (LJ - D3D11 to D3D9 ?).
	//		Textures must be 2D
	//		Only 1 mip level is allowed
	//		Texture must have default usage
	//		Texture must be write only	- ?? LJ ??
	//		MSAA textures are not allowed
	//		Bind flags must have SHADER_RESOURCE and RENDER_TARGET set
	//		Only R10G10B10A2_UNORM, R16G16B16A16_FLOAT and R8G8B8A8_UNORM formats are allowed - ?? LJ ??
	//		** If a shared texture is updated on one device ID3D11DeviceContext::Flush must be called on that device **

	// http://msdn.microsoft.com/en-us/library/windows/desktop/ff476903%28v=vs.85%29.aspx
	// To share a resource between two Direct3D 11 devices the resource must have been created
	// with the D3D11_RESOURCE_MISC_SHARED flag, if it was created using the ID3D11Device interface.
	//
	D3D11_TEXTURE2D_DESC desc;
	ZeroMemory(&desc, sizeof(desc));
	desc.Width				= width;
	desc.Height				= height;
	desc.BindFlags			= D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
	desc.MiscFlags			= D3D11_RESOURCE_MISC_SHARED; // This texture will be shared
	// A DirectX 11 texture with D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX is not compatible with DirectX 9
	// so a general named mutext is used for all texture types
	desc.Format				= format;
	desc.Usage				= D3D11_USAGE_DEFAULT;
	// Multisampling quality and count
	// The default sampler mode, with no anti-aliasing, has a count of 1 and a quality level of 0.
	desc.SampleDesc.Quality = 0;
	desc.SampleDesc.Count	= 1;
	desc.MipLevels			= 1;
	desc.ArraySize			= 1;

	HRESULT res = pd3dDevice->CreateTexture2D(&desc, NULL, &pTexture); // pSharedTexture);

	if (res != S_OK) {
		// http://msdn.microsoft.com/en-us/library/windows/desktop/ff476174%28v=vs.85%29.aspx
		printf("spoutDirectX::CreateSharedDX11Texture ERROR : [0x%x]\n", res);
		switch (res) {
			case D3DERR_INVALIDCALL:
				printf("    D3DERR_INVALIDCALL \n");
				break;
			case E_INVALIDARG:
				printf("    E_INVALIDARG \n");
				break;
			case E_OUTOFMEMORY:
				printf("    E_OUTOFMEMORY \n");
				break;
			default :
				printf("    Unlisted error\n");
				break;
		}
		return false;
	}

	// The DX11 texture is created OK
	// Get the texture share handle so it can be saved in shared memory for receivers to pick up
	// When sharing a resource between two Direct3D 10/11 devices the unique handle 
	// of the resource can be obtained by querying the resource for the IDXGIResource 
	// interface and then calling GetSharedHandle.
	IDXGIResource* pOtherResource(NULL);
	if(pTexture->QueryInterface( __uuidof(IDXGIResource), (void**)&pOtherResource) != S_OK) {
		printf("    QueryInterface error\n");
		return false;
	}

	// Return the shared texture handle
	pOtherResource->GetSharedHandle(&dxShareHandle); 
	pOtherResource->Release();

	*pSharedTexture = pTexture;

	return true;

}
Exemplo n.º 2
0
    HRESULT STDMETHODCALLTYPE SwapPresentHook(UINT syncInterval, UINT flags)
    {
        IDXGISwapChain *swap = (IDXGISwapChain*)this;

        if(lpCurrentSwap == NULL && !bTargetAcquired)
        {
            lpCurrentSwap = swap;
            SetupD3D11(swap);
            bTargetAcquired = true;
        }

        if(lpCurrentSwap == swap)
        {
            ID3D11Device *device = NULL;
            HRESULT chi;
            if(SUCCEEDED(chi = swap->GetDevice(__uuidof(ID3D11Device), (void**)&device)))
            {
                if(!lpCurrentDevice)
                {
                    lpCurrentDevice = device;

                    oldD3D11Release = GetVTable(device, (8/4));
                    newD3D11Release = ConvertClassProcToFarproc((CLASSPROC)&D3D11Override::DeviceReleaseHook);
                    SetVTable(device, (8/4), newD3D11Release);
                }

                ID3D11DeviceContext *context;
                device->GetImmediateContext(&context);

                if(!bHasTextures && bCapturing)
                {
                    if(dxgiFormat)
                    {
                        if(!hwndReceiver)
                            hwndReceiver = FindWindow(RECEIVER_WINDOWCLASS, NULL);

                        if(hwndReceiver)
                        {
                            D3D11_TEXTURE2D_DESC texDesc;
                            ZeroMemory(&texDesc, sizeof(texDesc));
                            texDesc.Width  = d3d11CaptureInfo.cx;
                            texDesc.Height = d3d11CaptureInfo.cy;
                            texDesc.MipLevels = 1;
                            texDesc.ArraySize = 1;
                            texDesc.Format = dxgiFormat;
                            texDesc.SampleDesc.Count = 1;
                            texDesc.Usage = D3D11_USAGE_STAGING;
                            texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;

                            bool bSuccess = true;
                            UINT pitch;

                            for(UINT i=0; i<2; i++)
                            {
                                HRESULT ching;
                                if(FAILED(ching = device->CreateTexture2D(&texDesc, NULL, &d3d11Textures[i])))
                                {
                                    bSuccess = false;
                                    break;
                                }

                                if(i == 0)
                                {
                                    ID3D11Resource *resource;
                                    if(FAILED(d3d11Textures[i]->QueryInterface(__uuidof(ID3D11Resource), (void**)&resource)))
                                    {
                                        bSuccess = false;
                                        break;
                                    }

                                    D3D11_MAPPED_SUBRESOURCE map;
                                    if(FAILED(context->Map(resource, 0, D3D11_MAP_READ, 0, &map)))
                                    {
                                        bSuccess = false;
                                        break;
                                    }

                                    pitch = map.RowPitch;
                                    context->Unmap(resource, 0);
                                    resource->Release();
                                }
                            }

                            if(bSuccess)
                            {
                                d3d11CaptureInfo.mapID = InitializeSharedMemory(pitch*d3d11CaptureInfo.cy, &d3d11CaptureInfo.mapSize, &copyData, textureBuffers);
                                if(!d3d11CaptureInfo.mapID)
                                    bSuccess = false;
                            }

                            if(bSuccess)
                            {
                                bHasTextures = true;
                                d3d11CaptureInfo.captureType = CAPTURETYPE_MEMORY;
                                d3d11CaptureInfo.hwndSender = hwndSender;
                                d3d11CaptureInfo.pitch = pitch;
                                d3d11CaptureInfo.bFlip = FALSE;
                                PostMessage(hwndReceiver, RECEIVER_NEWCAPTURE, 0, (LPARAM)&d3d11CaptureInfo);
                            }
                            else
                            {
                                for(UINT i=0; i<2; i++)
                                {
                                    SafeRelease(d3d11Textures[i]);

                                    if(textureBuffers[i])
                                    {
                                        free(textureBuffers[i]);
                                        textureBuffers[i] = NULL;
                                    }
                                }
                            }
                        }
                    }
                }

                if(bHasTextures)
                {
                    if(bCapturing)
                    {
                        DWORD nextCapture = curCapture == 0 ? 1 : 0;

                        ID3D11Texture2D *texture = d3d11Textures[curCapture];
                        ID3D11Resource *backBuffer = NULL;

                        if(SUCCEEDED(swap->GetBuffer(0, IID_ID3D11Resource, (void**)&backBuffer)))
                        {
                            if(bIsMultisampled)
                                context->ResolveSubresource(texture, 0, backBuffer, 0, dxgiFormat);
                            else
                                context->CopyResource(texture, backBuffer);
                            backBuffer->Release();

                            ID3D11Texture2D *lastTexture = d3d11Textures[nextCapture];
                            ID3D11Resource *resource;

                            if(SUCCEEDED(lastTexture->QueryInterface(__uuidof(ID3D11Resource), (void**)&resource)))
                            {
                                D3D11_MAPPED_SUBRESOURCE map;
                                if(SUCCEEDED(context->Map(resource, 0, D3D11_MAP_READ, 0, &map)))
                                {
                                    LPBYTE *pTextureBuffer = NULL;
                                    int lastRendered = -1;

                                    //under no circumstances do we -ever- allow a stall
                                    if(WaitForSingleObject(textureMutexes[curCapture], 0) == WAIT_OBJECT_0)
                                        lastRendered = (int)curCapture;
                                    else if(WaitForSingleObject(textureMutexes[nextCapture], 0) == WAIT_OBJECT_0)
                                        lastRendered = (int)nextCapture;

                                    if(lastRendered != -1)
                                    {
                                        SSECopy(textureBuffers[lastRendered], map.pData, map.RowPitch*d3d11CaptureInfo.cy);
                                        ReleaseMutex(textureMutexes[lastRendered]);
                                    }

                                    context->Unmap(resource, 0);
                                    copyData->lastRendered = (UINT)lastRendered;
                                }

                                resource->Release();
                            }
                        }

                        curCapture = nextCapture;
                    }
                    else
                        ClearD3D11Data();
                }

                device->Release();
                context->Release();
            }
        }

        gi11swapPresent.Unhook();
        HRESULT hRes = swap->Present(syncInterval, flags);
        gi11swapPresent.Rehook();

        return hRes;
    }