66#include < GL/wglew.h>
77#include < atlcomcli.h>
88
9+ #include " ../ogl/util/device.h"
10+
911namespace caspar { namespace accelerator { namespace d3d {
12+
1013d3d_texture2d::d3d_texture2d (ID3D11Texture2D* tex)
11- : texture_(std::shared_ptr<ID3D11Texture2D>(tex, [](ID3D11Texture2D* p) {
12- if (p)
13- p->Release ();
14- }))
14+ : texture_(tex)
1515{
1616 share_handle_ = nullptr ;
1717
@@ -26,46 +26,81 @@ d3d_texture2d::d3d_texture2d(ID3D11Texture2D* tex)
2626 }
2727
2828 {
29- CComQIPtr<IDXGIResource1> res = texture_. get () ;
29+ CComQIPtr<IDXGIResource1> res = texture_;
3030 if (res) {
3131 res->CreateSharedHandle (nullptr , DXGI_SHARED_RESOURCE_READ, nullptr , &share_handle_);
3232 }
3333 }
3434
35- if (share_handle_ == nullptr || !wglDXSetResourceShareHandleNV (texture_. get () , share_handle_)) {
35+ if (share_handle_ == nullptr || !wglDXSetResourceShareHandleNV (texture_, share_handle_)) {
3636 CASPAR_THROW_EXCEPTION (gl::ogl_exception () << msg_info (" Failed to setup shared d3d texture." ));
3737 }
3838}
3939
4040d3d_texture2d::~d3d_texture2d ()
4141{
42- if (gl_texture_id_ != 0 )
43- glDeleteTextures (1 , &gl_texture_id_);
42+ const std::shared_ptr<ogl::device> ogl = ogl_.lock ();
43+ if (ogl != nullptr ) {
44+ // The cleanup must happen be done on the opengl thread
45+ ogl->dispatch_sync ([&] {
46+ const std::shared_ptr<void > interop = ogl->d3d_interop ();
47+ if (texture_handle_ != nullptr && interop != nullptr ) {
48+ wglDXUnlockObjectsNV (interop.get (), 1 , &texture_handle_);
49+ wglDXUnregisterObjectNV (interop.get (), texture_handle_);
50+ texture_handle_ = nullptr ;
51+ }
52+
53+ if (gl_texture_id_ != 0 ) {
54+ GL (glDeleteTextures (1 , &gl_texture_id_));
55+ gl_texture_id_ = 0 ;
56+ }
57+
58+ // TODO: This appears to be leaking something opengl, but it is not clear what that is.
59+
60+ if (share_handle_ != nullptr ) {
61+ CloseHandle (share_handle_);
62+ share_handle_ = nullptr ;
63+ }
64+ });
65+ }
66+
67+ if (texture_ != nullptr ) {
68+ texture_->Release ();
69+ texture_ = nullptr ;
70+ }
4471}
4572
46- void d3d_texture2d::gen_gl_texture (const std::shared_ptr<void >& interop )
73+ void d3d_texture2d::gen_gl_texture (std::shared_ptr<ogl::device> ogl )
4774{
48- if (gl_texture_id_ == 0 ) {
75+ if (gl_texture_id_ != 0 || texture_ == nullptr )
76+ return ;
77+
78+ ogl_ = ogl;
79+
80+ const std::shared_ptr<void > interop = ogl->d3d_interop ();
81+ if (!interop) {
82+ CASPAR_THROW_EXCEPTION (gl::ogl_exception () << msg_info (" d3d interop not setup to bind shared d3d texture." ));
83+ }
84+
85+ ogl->dispatch_sync ([&] {
4986 GL (glGenTextures (1 , &gl_texture_id_));
50- void * tex_handle = wglDXRegisterObjectNV (
51- interop.get (), texture_.get (), gl_texture_id_, GL_TEXTURE_2D, WGL_ACCESS_READ_ONLY_NV);
52- if (!tex_handle) {
87+
88+ texture_handle_ =
89+ wglDXRegisterObjectNV (interop.get (), texture_, gl_texture_id_, GL_TEXTURE_2D, WGL_ACCESS_READ_ONLY_NV);
90+ if (!texture_handle_) {
5391 GL (glDeleteTextures (1 , &gl_texture_id_));
5492 gl_texture_id_ = 0 ;
5593 CASPAR_THROW_EXCEPTION (gl::ogl_exception () << msg_info (" Failed to bind shared d3d texture." ));
5694 }
5795
58- texture_handle_ = std::shared_ptr<void >(tex_handle, [=](void * p) {
59- wglDXUnlockObjectsNV (interop.get (), 1 , &p);
60- wglDXUnregisterObjectNV (interop.get (), p);
61- });
62-
63- if (!wglDXLockObjectsNV (interop.get (), 1 , &tex_handle)) {
96+ if (!wglDXLockObjectsNV (interop.get (), 1 , &texture_handle_)) {
97+ wglDXUnregisterObjectNV (interop.get (), texture_handle_);
98+ texture_handle_ = nullptr ;
6499 GL (glDeleteTextures (1 , &gl_texture_id_));
65100 gl_texture_id_ = 0 ;
66101 CASPAR_THROW_EXCEPTION (gl::ogl_exception () << msg_info (" Failed to lock shared d3d texture." ));
67102 }
68- }
103+ });
69104}
70105
71106}}} // namespace caspar::accelerator::d3d
0 commit comments