JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_WGLNVDXInterop_nwglDXUnregisterObjectNV(JNIEnv *__env, jclass clazz, jlong deviceAddress, jlong objectAddress, jlong __functionAddress) {
	HANDLE device = (HANDLE)(intptr_t)deviceAddress;
	HANDLE object = (HANDLE)(intptr_t)objectAddress;
	wglDXUnregisterObjectNVPROC wglDXUnregisterObjectNV = (wglDXUnregisterObjectNVPROC)(intptr_t)__functionAddress;
	UNUSED_PARAMS(__env, clazz)
	return (jint)wglDXUnregisterObjectNV(device, object);
}
void D3DPresentEngine::releaseSharedTexture()
{
	if (!gl_handleD3D) return;
	wglDXUnlockObjectsNV(gl_handleD3D, 1, &gl_handle);
	wglDXUnregisterObjectNV(gl_handleD3D,gl_handle);
	//glDeleteTextures(1, &gl_name);
	SAFE_RELEASE(d3d_shared_surface);
	SAFE_RELEASE(d3d_shared_texture);

}
Beispiel #3
0
// LJ DEBUG - TODO - not working
// Re-link a gl texture to the shared directX texture
bool spoutGLDXinterop::LinkGLtexture(GLuint glTexture) 
{
	// printf("LinkGLtexture(%d)\n", glTexture);
	if(g_pd3dDevice == NULL || g_pSharedTexture == NULL || m_dxShareHandle == NULL) {
		// printf("    null handles\n");
		return false;
	}

	if(m_hInteropDevice != NULL &&  m_hInteropObject != NULL) {
		// printf("    unregister\n");
		wglDXUnregisterObjectNV(m_hInteropDevice, m_hInteropObject);
		m_hInteropObject = NULL;
	}
	// printf("    unregister OK\n");

	if (m_hInteropDevice != NULL) {
		wglDXCloseDeviceNV(m_hInteropDevice);
	}

	// printf("    close device OK\n");
	m_hInteropDevice = NULL;
	m_hInteropObject = NULL;


	m_hInteropDevice = wglDXOpenDeviceNV(g_pd3dDevice);
	if (m_hInteropDevice == NULL) {
		// printf("    open device fail\n");
		return false;
	}
	// printf("    open device OK\n");

	// Prepare the DirectX texture for use by OpenGL
	// register for interop and associate the opengl texture with the dx texture
	m_hInteropObject = wglDXRegisterObjectNV(g_pd3dDevice, 
											 g_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

	if(!m_hInteropObject) {
		// printf("    null InteropObject\n");
		return false;
	}

	// printf("    InteropObject OK\n");

	return true;

}
 void RenderManagerD3D11OpenGL::cleanupGL() {
     if (m_glD3DHandle) {
         for (size_t i = 0; i < m_oglToD3D.size(); i++) {
             wglDXUnregisterObjectNV(m_glD3DHandle,
                                     m_oglToD3D[i].glColorHandle);
         }
         wglDXCloseDeviceNV(m_glD3DHandle);
         m_glD3DHandle = nullptr;
     }
     delete m_buffers.OpenGL;
     m_buffers.OpenGL = nullptr;
     delete m_library.OpenGL;
     m_library.OpenGL = nullptr;
     removeOpenGLContexts();
 }
Beispiel #5
0
// this is the function that cleans up Direct3D and the gldx interop
// The exit flag is a fix - trouble is with wglDXUnregisterObjectNV
// which crashes on exit to the program but not if called
// while the program is running. Likely due to no GL context on exit
void spoutGLDXinterop::CleanupInterop(bool bExit)
{
	// Some of these things need an opengl context so check
	if(wglGetCurrentContext() != NULL) {
		// Problem here on exit, but not on change of resolution while the program is running !?
		// On exit there may be no openGL context but while the program is running there is
		if(!bExit && m_hInteropDevice != NULL && m_hInteropObject != NULL) {
			wglDXUnregisterObjectNV(m_hInteropDevice, m_hInteropObject);
			m_hInteropObject = NULL;
		}
		if (m_hInteropDevice != NULL) {
			wglDXCloseDeviceNV(m_hInteropDevice);
			m_hInteropDevice = NULL;
		}

		if(m_glTexture)	{
			glDeleteTextures(1, &m_glTexture);
			m_glTexture = 0;
		}

		if(m_fbo) {
			glDeleteFramebuffersEXT(1, &m_fbo);
			m_fbo = 0;
		}

	} // endif there is an opengl context

	CleanupDirectX();

	// Close general texture access mutex
	spoutdx.CloseAccessMutex(m_hAccessMutex);
	m_hAccessMutex = NULL; // Double check that the global handle is NULL

	m_bInitialized = false;

}
    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);
    }
Beispiel #7
0
bool spoutGLDXinterop::CreateInterop(HWND hWnd, char* sendername, unsigned int width, unsigned int height, DWORD dwFormat, bool bReceive)
{
	bool bRet = true;
	DWORD format;
	D3DFORMAT DX9format = D3DFMT_A8R8G8B8; // fixed format for DX9 (21)

	// Needs an openGL context to work
	if(!wglGetCurrentContext()) {
		// MessageBoxA(NULL, "CreateInterop - no GL context", "Warning", MB_OK);
		return false;
	}

	if(bUseDX9) {
		// printf("CreateInterop - DX9 mode - format D3DFMT_A8R8G8B8 (%d) \n", DX9format);
		// DirectX 9
		format = (DWORD)DX9format;
	}
	else {
		// DirectX 11
		// Is this a DX11 texture or a DX9 sender texture?
		if(dwFormat > 0) {
			// printf("CreateInterop - DX11 mode - format %d \n", dwFormat);
			format = (DXGI_FORMAT)dwFormat;
		}
		else {
			// printf("CreateInterop - DX11 mode - default compatible format %d \n", DX11format);
			format = (DWORD)DX11format; // DXGI_FORMAT_B8G8R8A8_UNORM default compatible with DX9
		}
	}

	// Formats
	// DXGI_FORMAT_R8G8B8A8_UNORM; // default DX11 format - not compatible with DX9 (28)
	// DXGI_FORMAT_B8G8R8A8_UNORM; // compatoble DX11 format - works with DX9 (87)

	// Quit now if the receiver can't access the shared memory info of the sender
	// Otherwise m_dxShareHandle is set by getSharedTextureInfo and is the
	// shared texture handle of the Sender texture
	if (bReceive && !getSharedTextureInfo(sendername)) {
		// printf("CreateInterop error 1\n");
		return false;
	}

	// Check the sender format for a DX9 receiver
	// It can only be from a DX9 sender (format 0)
	// or from a compatible DX11 sender (format 87)
	if(bReceive && bUseDX9) {
		if(!(m_TextureInfo.format == 0 || m_TextureInfo.format == 87)) {
			// printf("CreateInterop - Incompatible format %d \n", m_TextureInfo.format);
			return false;
		}
	}

	// Make sure DirectX has been initialized
	// Creates a global pointer to the DirectX device (DX11 g_pd3dDevice or DX9 m_pDevice)
	if(!OpenDirectX(hWnd, bUseDX9)) {
		return false;
	}

	// Allow for sender updates
	// When a sender size changes, the new texture has to be re-registered
	if(m_hInteropDevice != NULL &&  m_hInteropObject != NULL) {
		// printf("CreateInterop - wglDXUnregisterObjectNV\n");
		wglDXUnregisterObjectNV(m_hInteropDevice, m_hInteropObject);
		m_hInteropObject = NULL;
	}

	// Create an fbo for copying textures
	if(m_fbo) {
		// Delete the fbo before the texture so that any texture attachment is released
		// printf("CreateInterop - deleting fbo\n");
		glDeleteFramebuffersEXT(1, &m_fbo);
		m_fbo = 0;
	}
	glGenFramebuffersEXT(1, &m_fbo); 

	// Create a local opengl texture that will be linked to a shared DirectX texture
	if(m_glTexture) {
		// printf("CreateInterop - deleting texture\n");
		glDeleteTextures(1, &m_glTexture);
		m_glTexture = 0;
	}
	glGenTextures(1, &m_glTexture);


	// Create textures and GLDX interop objects
	if(bUseDX9)	bRet = CreateDX9interop(width, height, format, bReceive);
	else bRet = CreateDX11interop(width, height, format, bReceive);

	if(!bRet) {
		// printf("CreateInterop error 2\n");
		return false;
	}

	// Now the global shared texture handle - m_dxShareHandle - has been set so a sender can be created
	// this creates the sender shared memory map and registers the sender
	if (!bReceive) {

		// We are done with the format
		// So for DirectX 9, set to zero to identify the sender as DirectX 9
		if(bUseDX9) format = 0; 
		if(!senders.CreateSender(sendername, width, height, m_dxShareHandle, format))
			return false;

	}

	// Set up local values for this instance
	// Needed for texture read and write size checks
	m_TextureInfo.width			= (unsigned __int32)width;
	m_TextureInfo.height		= (unsigned __int32)height;
	m_TextureInfo.shareHandle	= (unsigned __int32)m_dxShareHandle;
	m_TextureInfo.format		= format;

	// Initialize general texture transfer sync mutex - either sender or receiver can do this
	spoutdx.CreateAccessMutex(sendername, m_hAccessMutex);

	// Now it has initialized OK
	m_bInitialized = true;

	//
	// Now we have globals for this instance
	//
	// m_TextureInfo.width			- width of the texture
	// m_TextureInfo.height			- height of the texture
	// m_TextureInfo.shareHandle	- handle of the shared texture
	// m_TextureInfo.format			- format of the texture
	// m_glTexture					- a linked opengl texture
	// m_dxTexture					- a linked, shared DirectX texture created here
	// m_hInteropDevice				- handle to interop device created by wglDXOpenDeviceNV by init
	// m_hInteropObject				- handle to the connected texture created by wglDXRegisterObjectNV
	// m_hAccessMutex				- mutex for texture access lock
	// m_bInitialized				- whether it initialized OK

	// true means the init was OK, not the connection
	return true; 

}