Example #1
0
//	Link a shared DirectX texture to an OpenGL texture
//	and create a GLDX interop object handle
//
//	IN	pSharedTexture  Pointer to shared the DirectX texture
//	IN	dxShareHandle   Handle of the DirectX texture to be shared
//	IN	glTextureID     ID of the OpenGL texture that is to be linked to the shared DirectX texture
//	Returns             Handle to the GL/DirectX interop object (the shared texture)
//
HANDLE spoutGLDXinterop::LinkGLDXtextures (	void* pDXdevice,
											void* pSharedTexture,
											HANDLE dxShareHandle,
											GLuint glTexture) 
{

	HANDLE hInteropObject;

	// Prepare the DirectX device for interoperability with OpenGL
	// The return value is a handle to a GL/DirectX interop device.
	if(!m_hInteropDevice) m_hInteropDevice = wglDXOpenDeviceNV(pDXdevice);
	if (m_hInteropDevice == NULL) return false;

	// prepare shared resource
	// wglDXSetResourceShareHandle does not need to be called for DirectX
	// version 10 and 11 resources. Calling this function for DirectX 10
	// and 11 resources is not an error but has no effect.
	if (!wglDXSetResourceShareHandleNV(pSharedTexture, dxShareHandle))
		return NULL;

	// Prepare the DirectX texture for use by OpenGL
	// register for interop and associate the opengl texture with the dx texture
	hInteropObject = wglDXRegisterObjectNV( m_hInteropDevice,
											pSharedTexture,	// DX texture
											glTexture,		// OpenGL texture
											GL_TEXTURE_2D,	// Must be TEXTURE_2D
											WGL_ACCESS_READ_WRITE_NV); // We will write and the receiver will read

	return hInteropObject;

}
EXTERN_C_ENTER

JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_WGLNVDXInterop_nwglDXSetResourceShareHandleNV(JNIEnv *__env, jclass clazz, jlong dxObjectAddress, jlong shareHandleAddress, jlong __functionAddress) {
	void *dxObject = (void *)(intptr_t)dxObjectAddress;
	HANDLE shareHandle = (HANDLE)(intptr_t)shareHandleAddress;
	wglDXSetResourceShareHandleNVPROC wglDXSetResourceShareHandleNV = (wglDXSetResourceShareHandleNVPROC)(intptr_t)__functionAddress;
	UNUSED_PARAMS(__env, clazz)
	return (jint)wglDXSetResourceShareHandleNV(dxObject, shareHandle);
}
bool D3DPresentEngine::createSharedTexture(int w, int h, int textureID)
{

	_w = w;
	_h = h;
	if (gl_handleD3D == NULL ) 	gl_handleD3D = wglDXOpenDeviceNV(m_pDevice);

	if (!gl_handleD3D)
	{
		printf("ofxWMFVideoplayer : openning the shared device failed\nCreate SharedTexture Failed");
		return false;

	}

	gl_name=textureID;

	HANDLE sharedHandle = NULL; //We need to create a shared handle for the ressource, otherwise the extension fails on ATI/Intel cards
	
	
	HRESULT hr = m_pDevice->CreateTexture(w,h,1,D3DUSAGE_RENDERTARGET,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&d3d_shared_texture,&sharedHandle);

	if (FAILED(hr))
	{
		printf("ofxWMFVideoplayer : Error creating D3DTexture\n");
		return false;
	}

	if (!sharedHandle)
	{
		printf("ofxWMFVideoplayer : Error creating D3D sahred handle\n");
		return false;
	}
	
	wglDXSetResourceShareHandleNV(d3d_shared_texture,sharedHandle);

	d3d_shared_texture->GetSurfaceLevel(0,&d3d_shared_surface);
		
	gl_handle = wglDXRegisterObjectNV(gl_handleD3D, d3d_shared_texture,
		gl_name,
		GL_TEXTURE_RECTANGLE,
		WGL_ACCESS_READ_ONLY_NV);

	

	

	if (!gl_handle) 
	{
		printf("ofxWMFVideoplayer : openning the shared texture failed\nCreate SharedTexture Failed");
		return false;
	}
	return true;
}
    bool RenderManagerD3D11OpenGL::RegisterRenderBuffersInternal(
        const std::vector<RenderBuffer>& buffers,
        bool appWillNotOverwriteBeforeNewPresent) {
        // Make sure we're doing okay.
        if (!doingOkay()) {
            std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers(): "
                         "Display not opened."
                      << std::endl;
            return false;
        }

        // Make sure we don't have more eyes than buffers.  We can have fewer
        // because the client may have consolidated a number of eyes onto
        // one buffer.
        size_t numEyes = GetNumEyes();
        if (buffers.size() > numEyes) {
            std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers: "
                         "Wrong number of buffers: "
                      << buffers.size() << ", need " << numEyes << std::endl;
            return false;
        }

        // Delete any previously-registered buffers.
        for (size_t i = 0; i < m_oglToD3D.size(); i++) {
            wglDXUnregisterObjectNV(m_glD3DHandle, m_oglToD3D[i].glColorHandle);
            m_oglToD3D[i].D3DrenderTargetView->Release();
            m_oglToD3D[i].D3DTexture->Release();
        }
        m_oglToD3D.clear();

        // Allocate D3D buffers to be used and tie them to the OpenGL buffers.
        for (size_t i = 0; i < buffers.size(); i++) {
            // If we have already mapped this buffer, we go ahead and skip it,
            // so that we don't tie the same OpenGL buffer to multiple D3D
            // buffers.  It is not an error to map the same buffer twice.
            bool found = false;
            for (size_t j = 0; j < i; j++) {
                if (buffers[i].OpenGL->colorBufferName ==
                    buffers[j].OpenGL->colorBufferName) {
                    found = true;
                }
            }
            if (found) {
                continue;
            }

            // Figure out how large the buffer should be by binding this texture
            // and querying the size of the 0th mipmap level.
            GLint width = 0, height = 0;
            glBindTexture(GL_TEXTURE_2D, buffers[i].OpenGL->colorBufferName);
            const GLint mipLevel = 0;
            glGetTexLevelParameteriv(GL_TEXTURE_2D, mipLevel, GL_TEXTURE_WIDTH,
                                     &width);
            glGetTexLevelParameteriv(GL_TEXTURE_2D, mipLevel, GL_TEXTURE_HEIGHT,
                                     &height);
            if ((width == 0) || (height == 0)) {
                std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers: "
                             "Zero-sized buffer for buffer: "
                          << i << std::endl;
                return false;
            }

            // Initialize a new render target texture description.
            // Make it a shared texture so that we can use it with OpenGL
            // Interop.
            D3D11_TEXTURE2D_DESC textureDesc = {};
            textureDesc.Width = width;
            textureDesc.Height = height;
            textureDesc.MipLevels = 1;
            textureDesc.ArraySize = 1;
            // textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
            textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
            textureDesc.SampleDesc.Count = 1;
            textureDesc.SampleDesc.Quality = 0;
            textureDesc.Usage = D3D11_USAGE_DEFAULT;
            // We need it to be both a render target and a shader resource
            textureDesc.BindFlags =
                D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
            textureDesc.CPUAccessFlags = 0;
            textureDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;

            // Create a new render target texture to use.
            ID3D11Texture2D* D3DTexture = nullptr;
            HRESULT hr = m_D3D11Renderer->m_D3D11device->CreateTexture2D(
                &textureDesc, NULL, &D3DTexture);
            if (FAILED(hr)) {
                std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers: "
                             "Can't create texture"
                          << std::endl;
                return false;
            }

            // Fill in the resource view for your render texture buffer here
            D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc = {};
            // This must match what was created in the texture to be rendered
            // @todo Figure this out by introspection on the texture?
            // renderTargetViewDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
            renderTargetViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
            renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
            renderTargetViewDesc.Texture2D.MipSlice = 0;

            // Create the render target view.
            ID3D11RenderTargetView*
                renderTargetView; //< Pointer to our render target view
            hr = m_D3D11Renderer->m_D3D11device->CreateRenderTargetView(
                D3DTexture, &renderTargetViewDesc, &renderTargetView);
            if (FAILED(hr)) {
                std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers: "
                             "Could not create render target"
                          << std::endl;
                return false;
            }

            // Create a share handle for the texture, to enable it to be shared
            // between multiple devices.  Then register the share handle with
            // interop.
            // https://msdn.microsoft.com/en-us/library/windows/desktop/ff476531(v=vs.85).aspx
            // https://www.opengl.org/registry/specs/NV/DX_interop.txt
            IDXGIResource* pOtherResource = nullptr;
            hr = D3DTexture->QueryInterface(__uuidof(IDXGIResource),
                                            (void**)&pOtherResource);
            HANDLE sharedHandle;
            hr = pOtherResource->GetSharedHandle(&sharedHandle);
            if (FAILED(hr)) {
                std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers: "
                             "Could not get shared handle"
                          << std::endl;
                return false;
            }
            if (wglDXSetResourceShareHandleNV(D3DTexture, sharedHandle) !=
                TRUE) {
                std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers()"
                             ": Could not share resource"
                          << std::endl;
                return false;
            }

            // Prepare the things we need for wrapping Direct3D
            // objects. Information on how to do this comes from
            // the DX_interop2.txt file from opengl.org and from the
            // secondstory/ofDxSharedTextureExample project on Github.
            // Bind the OpenGL texture to the D3D texture for rendering
            HANDLE glColorHandle = wglDXRegisterObjectNV(
                m_glD3DHandle, D3DTexture, buffers[i].OpenGL->colorBufferName,
                GL_TEXTURE_2D, WGL_ACCESS_WRITE_DISCARD_NV);
            if (glColorHandle == nullptr) {
                std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers: "
                             "Can't get Color buffer handle"
                          << " (error " << GetLastError() << ")";
                switch (GetLastError()) {
                case ERROR_INVALID_HANDLE:
                    std::cerr << "  (Invalid handle)" << std::endl;
                    break;
                case ERROR_INVALID_DATA:
                    std::cerr << "  (Invalid data)" << std::endl;
                    break;
                case ERROR_OPEN_FAILED:
                    std::cerr << "  (Could not open Direct3D resource)"
                              << std::endl;
                    break;
                default:
                    std::cerr << "  (Unexpected error code)" << std::endl;
                }
                return false;
            }

            // New object to fill in
            OglToD3DTexture map;
            map.OpenGLTexture = buffers[i].OpenGL->colorBufferName;
            map.glColorHandle = glColorHandle;
            map.D3DTexture = D3DTexture;
            map.D3DrenderTargetView = renderTargetView;
            m_oglToD3D.push_back(map);

            // Lock the render target for OpenGL access
            if (!wglDXLockObjectsNV(m_glD3DHandle, 1, &map.glColorHandle)) {
                std::cerr << "RenderManagerD3D11OpenGL::RegisterRenderBuffers: "
                             "Can't lock Color buffer"
                          << std::endl;
                return false;
            }
        }

        // We're done -- call the base-class function to notify that we've
        // registered our buffers
        return RenderManager::RegisterRenderBuffersInternal(buffers,
          appWillNotOverwriteBeforeNewPresent);
    }