JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_WGLNVDXInterop_nwglDXLockObjectsNV(JNIEnv *__env, jclass clazz, jlong deviceAddress, jint count, jlong objectsAddress, jlong __functionAddress) {
	HANDLE device = (HANDLE)(intptr_t)deviceAddress;
	HANDLE *objects = (HANDLE *)(intptr_t)objectsAddress;
	wglDXLockObjectsNVPROC wglDXLockObjectsNV = (wglDXLockObjectsNVPROC)(intptr_t)__functionAddress;
	UNUSED_PARAMS(__env, clazz)
	return (jint)wglDXLockObjectsNV(device, count, objects);
}
예제 #2
0
/*

	GL/DX Interop lock

	A return value of TRUE indicates that all objects were
    successfully locked.  A return value of FALSE indicates an
    error. If the function returns FALSE, none of the objects will be locked.

	Attempting to access an interop object via GL when the object is
    not locked, or attempting to access the DirectX resource through
    the DirectX API when it is locked by GL, will result in undefined
    behavior and may result in data corruption or program
    termination. Likewise, passing invalid interop device or object
    handles to this function has undefined results, including program
    termination.

	Note that only one GL context may hold the lock on the
    resource at any given time --- concurrent access from multiple GL
    contexts is not currently supported.

	http://halogenica.net/sharing-resources-between-directx-and-opengl/

	This lock triggers the GPU to perform the necessary flushing and stalling
	to guarantee that the surface has finished being written to before reading from it. 

	DISCUSSION: The Lock/Unlock calls serve as synchronization points
    between OpenGL and DirectX. They ensure that any rendering
    operations that affect the resource on one driver are complete
    before the other driver takes ownership of it.

	This function assumes only one object to 

	Must return S_OK (0) - otherwise the error can be checked.

*/
HRESULT spoutGLDXinterop::LockInteropObject(HANDLE hDevice, HANDLE *hObject)
{
	DWORD dwError;
	HRESULT hr;

	if(hDevice == NULL || hObject == NULL || *hObject == NULL) {
		return E_HANDLE;
	}

	// lock dx object
	if(wglDXLockObjectsNV(hDevice, 1, hObject) == TRUE) {
		return S_OK;
	}
	else {
		dwError = GetLastError();
		switch (dwError) {
			case ERROR_BUSY :			// One or more of the objects in <hObjects> was already locked.
				hr = E_ACCESSDENIED;	// General access denied error
				// printf("	spoutGLDXinterop::LockInteropObject ERROR_BUSY\n");
				break;
			case ERROR_INVALID_DATA :	// One or more of the objects in <hObjects>
										// does not belong to the interop device
										// specified by <hDevice>.
				hr = E_ABORT;			// Operation aborted
				// printf("	spoutGLDXinterop::LockInteropObject ERROR_INVALID_DATA\n");
				break;
			case ERROR_LOCK_FAILED :	// One or more of the objects in <hObjects> failed to 
				hr = E_ABORT;			// Operation aborted
				// printf("	spoutGLDXinterop::LockInteropObject ERROR_LOCK_FAILED\n");
				break;
			default:
				hr = E_FAIL;			// unspecified error
				// printf("	spoutGLDXinterop::LockInteropObject UNKNOWN_ERROR\n");
				break;
		} // end switch
	} // end false

	return hr;

} // LockInteropObject
    bool RenderManagerD3D11OpenGL::PresentEye(PresentEyeParameters params) {
        if (params.m_buffer.OpenGL == nullptr) {
            std::cerr
                << "RenderManagerD3D11OpenGL::PresentEye(): NULL buffer pointer"
                << std::endl;
            return false;
        }

        // Verify that we have registered this buffer.
        OglToD3DTexture* oglMap = nullptr;
        for (size_t i = 0; i < m_oglToD3D.size(); i++) {
            if (m_oglToD3D[i].OpenGLTexture ==
                params.m_buffer.OpenGL->colorBufferName) {
                oglMap = &m_oglToD3D[i];
            }
        }
        if (oglMap == nullptr) {
            std::cerr
                << "RenderManagerD3D11OpenGL::PresentEye(): Unregistered buffer"
                << " (call RegisterRenderBuffers before presenting)"
                << std::endl;
            return false;
        }
        if (params.m_buffer.OpenGL->colorBufferName != oglMap->OpenGLTexture) {
            std::cerr
                << "RenderManagerD3D11OpenGL::PresentEye(): Mis-matched buffer"
                << " (call RegisterRenderBuffers whenever a new render-texture "
                   "is created)"
                << std::endl;
            return false;
        }

        // Create a new param buffer and fill in the new D3D buffer pointer
        // along with our current info.  Invert the flip-buffer flag, because
        // we need to render upside-down.  Rotate around the negative Z axis
        // rather than the positive.  Then call the D3D PresentEye method
        // and clean up after ourselves.
        PresentEyeParameters sendParams = params;
        sendParams.m_flipInY = !sendParams.m_flipInY;
        sendParams.m_buffer.OpenGL = nullptr;
        sendParams.m_buffer.D3D11 = new RenderBufferD3D11;
        sendParams.m_buffer.D3D11->colorBuffer = oglMap->D3DTexture;
        sendParams.m_buffer.D3D11->colorBufferView =
            oglMap->D3DrenderTargetView;

        // Transpose the texture matrix because we're feeding it to Direct3D,
        // which stores matrix elements in a different order.  We're sending
        // it our OpenGL transforms because we used OpenGL to render the two
        // images, so that's what the texture matrix needs to assume.
        matrix16 textureMat;
        if (params.m_ATW != nullptr) {
            // Transpose the matrix, because it is in OpenGL format.
            for (size_t r = 0; r < 4; r++) {
                for (size_t c = 0; c < 4; c++) {
                    textureMat.data[r * 4 + c] = params.m_ATW->data[c * 4 + r];
                }
            }
            sendParams.m_ATW = &textureMat;
        }

        // Unlock the render target to enable Direct3D access
        if (!wglDXUnlockObjectsNV(m_glD3DHandle, 1, &oglMap->glColorHandle)) {
            std::cerr << "RenderManagerD3D11OpenGL::PresentEye: Can't unlock "
                         "Color buffer"
                      << std::endl;
            return false;
        }

        // Render the the eye with the relevant texture.
        bool ret = m_D3D11Renderer->PresentEye(sendParams);

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

        delete sendParams.m_buffer.D3D11;
        return ret;
    }
    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);
    }
예제 #5
0
bool D3DPresentEngine::lockSharedTexture()
{
	if (!gl_handleD3D) return false;
	if (!gl_handle) return false;
	return wglDXLockObjectsNV(gl_handleD3D, 1, &gl_handle);
}