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); }
// 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(); }
// 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); }
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; }