20HMODULE GHOST_ContextD3D::s_d3d_lib =
nullptr;
21PFN_D3D11_CREATE_DEVICE GHOST_ContextD3D::s_D3D11CreateDeviceFn =
nullptr;
31 m_device_ctx->ClearState();
32 m_device_ctx->Release();
54 if (s_d3d_lib ==
nullptr) {
55 s_d3d_lib = LoadLibraryA(
"d3d11.dll");
57 WIN32_CHK(s_d3d_lib !=
nullptr);
59 if (s_d3d_lib ==
nullptr) {
60 fprintf(stderr,
"LoadLibrary(\"d3d11.dll\") failed!\n");
65 if (s_D3D11CreateDeviceFn ==
nullptr) {
66 s_D3D11CreateDeviceFn = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(s_d3d_lib,
69 WIN32_CHK(s_D3D11CreateDeviceFn !=
nullptr);
71 if (s_D3D11CreateDeviceFn ==
nullptr) {
72 fprintf(stderr,
"GetProcAddress(s_d3d_lib, \"D3D11CreateDevice\") failed!\n");
86 HRESULT hres = s_D3D11CreateDeviceFn(
88 D3D_DRIVER_TYPE_HARDWARE,
102 WIN32_CHK(hres == S_OK);
117 HANDLE render_target{
nullptr};
120 enum RenderTarget { TARGET_RENDERBUF, TARGET_TEX2D };
124 ID3D11DeviceContext *device_ctx,
128 ID3D11RenderTargetView *render_target =
nullptr)
129 : m_device(device), m_device_ctx(device_ctx), m_cur_width(width), m_cur_height(height)
131 if (!render_target) {
132 D3D11_TEXTURE2D_DESC texDesc{};
133 D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc{};
134 ID3D11Texture2D *tex;
136 texDesc.Width = width;
137 texDesc.Height = height;
139 texDesc.SampleDesc.Count = 1;
140 texDesc.ArraySize = 1;
141 texDesc.MipLevels = 1;
142 texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
144 device->CreateTexture2D(&texDesc,
nullptr, &tex);
148 fprintf(stderr,
"Error creating texture for shared DirectX-OpenGL resource\n");
152 renderTargetViewDesc.Format = texDesc.Format;
153 renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
154 renderTargetViewDesc.Texture2D.MipSlice = 0;
156 device->CreateRenderTargetView(tex, &renderTargetViewDesc, &render_target);
163 ID3D11Resource *backbuffer_res =
nullptr;
165 if (backbuffer_res) {
167 backbuffer_res->Release();
172 fprintf(stderr,
"Error creating render target for shared DirectX-OpenGL resource\n");
186 if (m_is_initialized) {
188 if (m_shared.render_target
193 && !m_use_gl_texture2d
196 wglDXUnregisterObjectNV(m_shared.device, m_shared.render_target);
198 if (m_shared.device) {
199 wglDXCloseDeviceNV(m_shared.device);
201 glDeleteFramebuffers(1, &m_shared.fbo);
202 if (m_use_gl_texture2d) {
203 glDeleteTextures(1, &m_gl_render_target);
206 glDeleteRenderbuffers(1, &m_gl_render_target);
209 glDeleteFramebuffers(1, &m_shared.fbo);
210 if (m_use_gl_texture2d) {
211 glDeleteTextures(1, &m_gl_render_target);
220 if (m_shared.render_target) {
221 wglDXUnregisterObjectNV(m_shared.device, m_shared.render_target);
228 if (target == TARGET_TEX2D) {
229 glTexImage2D(GL_TEXTURE_2D,
240 m_shared.render_target = wglDXRegisterObjectNV(m_shared.device,
243 (target == TARGET_TEX2D) ? GL_TEXTURE_2D :
245 WGL_ACCESS_READ_WRITE_NV);
246 if (!m_shared.render_target) {
247 fprintf(stderr,
"Error registering shared object using wglDXRegisterObjectNV()\n");
256 m_shared.device = wglDXOpenDeviceNV(m_device);
257 if (m_shared.device ==
nullptr) {
258 fprintf(stderr,
"Error opening shared device using wglDXOpenDeviceNV()\n");
263 glGenRenderbuffers(1, &m_gl_render_target);
264 glBindRenderbuffer(GL_RENDERBUFFER, m_gl_render_target);
267 glBindRenderbuffer(GL_RENDERBUFFER, 0);
268 if (m_gl_render_target) {
269 glDeleteRenderbuffers(1, &m_gl_render_target);
272 m_use_gl_texture2d =
true;
273 glGenTextures(1, &m_gl_render_target);
274 glBindTexture(GL_TEXTURE_2D, m_gl_render_target);
280 glGenFramebuffers(1, &m_shared.fbo);
281 glBindFramebuffer(GL_FRAMEBUFFER, m_shared.fbo);
282 if (m_use_gl_texture2d) {
283 glFramebufferTexture2D(
284 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_gl_render_target, 0);
287 glFramebufferRenderbuffer(
288 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_gl_render_target);
290 m_is_initialized =
true;
297 if (m_is_initialized ==
false) {
301 if ((m_cur_width != width) || (m_cur_height != height)) {
303 m_cur_height = height;
311 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &fbo);
320 const float clear_col[] = {0.8f, 0.5f, 1.0f, 1.0f};
327 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_shared.fbo);
328 GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
329 if (err != GL_FRAMEBUFFER_COMPLETE) {
331 stderr,
"Error: Framebuffer for shared DirectX-OpenGL resource incomplete %u\n", err);
336 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
337 glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
339 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
352 wglDXLockObjectsNV(m_shared.device, 1, &m_shared.render_target);
356 wglDXUnlockObjectsNV(m_shared.device, 1, &m_shared.render_target);
359 ID3D11Device *m_device;
360 ID3D11DeviceContext *m_device_ctx;
361 GLuint m_gl_render_target;
362 unsigned int m_cur_width, m_cur_height;
363 bool m_is_initialized{
false};
364 bool m_use_gl_texture2d{
false};
371 ID3D11RenderTargetView *render_target)
373 if (!(WGL_NV_DX_interop && WGL_NV_DX_interop2)) {
375 "Error: Can't render OpenGL framebuffer using Direct3D. NV_DX_interop extension not "
380 m_device, m_device_ctx, width, height,
format, render_target);
400 return shared_res->
blit(width, height);
GHOST_TSuccess activateDrawingContext() override
GHOST_TSuccess initializeDrawingContext() override
GHOST_TSuccess swapBuffers() override
~GHOST_ContextD3D() override
GHOST_ContextD3D(bool stereoVisual, HWND hWnd)
GHOST_TSuccess releaseDrawingContext() override
GHOST_TSuccess blitFromOpenGLContext(class GHOST_SharedOpenGLResource *shared_res, unsigned int width, unsigned int height)
ID3D11Texture2D * getSharedTexture2D(class GHOST_SharedOpenGLResource *shared_res)
class GHOST_SharedOpenGLResource * createSharedOpenGLResource(unsigned int width, unsigned int height, DXGI_FORMAT format, ID3D11RenderTargetView *render_target)
void disposeSharedOpenGLResource(class GHOST_SharedOpenGLResource *shared_res)
GHOST_TSuccess releaseNativeHandles() override
static GHOST_Context * active_context_
GHOST_Context(bool stereoVisual)
void ensureUpdated(unsigned int width, unsigned int height)
GHOST_TSuccess blit(unsigned int width, unsigned int height)
GHOST_TSuccess initialize()
~GHOST_SharedOpenGLResource()
GHOST_SharedOpenGLResource(ID3D11Device *device, ID3D11DeviceContext *device_ctx, unsigned int width, unsigned int height, DXGI_FORMAT format, ID3D11RenderTargetView *render_target=nullptr)
bool reregisterSharedObject(RenderTarget target)
ID3D11RenderTargetView * m_render_target
ID3D11Texture2D * m_render_target_tex