diff options
-rw-r--r-- | intern/ghost/CMakeLists.txt | 2 | ||||
-rw-r--r-- | intern/ghost/GHOST_C-api.h | 19 | ||||
-rw-r--r-- | intern/ghost/GHOST_ISystem.h | 6 | ||||
-rw-r--r-- | intern/ghost/GHOST_Types.h | 5 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_C-api.cpp | 19 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_ContextD3D.cpp | 358 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_ContextD3D.h | 133 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_System.cpp | 10 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_System.h | 13 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWin32.cpp | 42 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWin32.h | 14 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWin32.cpp | 14 |
12 files changed, 634 insertions, 1 deletions
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index cc671e31f92..c4f1efe1580 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -280,11 +280,13 @@ elseif(WIN32) ) list(APPEND SRC + intern/GHOST_ContextD3D.cpp intern/GHOST_DisplayManagerWin32.cpp intern/GHOST_DropTargetWin32.cpp intern/GHOST_SystemWin32.cpp intern/GHOST_WindowWin32.cpp + intern/GHOST_ContextD3D.h intern/GHOST_DisplayManagerWin32.h intern/GHOST_DropTargetWin32.h intern/GHOST_SystemWin32.h diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index ba46a868df6..a3cc9aa1df5 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -229,6 +229,25 @@ extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemha extern GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle, GHOST_ContextHandle contexthandle); +#ifdef WIN32 +/** + * Create a new offscreen context. + * Never explicitly delete the context, use disposeContext() instead. + * \param systemhandle The handle to the system + * \return A handle to the new context ( == NULL if creation failed). + */ +GHOST_ContextHandle GHOST_CreateDirectXContext(GHOST_SystemHandle systemhandle); + +/** + * Dispose of a context. + * \param systemhandle The handle to the system + * \param contexthandle Handle to the context to be disposed. + * \return Indication of success. + */ +GHOST_TSuccess GHOST_DisposeDirectXContext(GHOST_SystemHandle systemhandle, + GHOST_ContextHandle contexthandle); +#endif + /** * Returns the window user data. * \param windowhandle The handle to the window diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 4634eb1bc66..5d529141ca7 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -267,6 +267,12 @@ class GHOST_ISystem { virtual GHOST_IContext *createOffscreenContext() = 0; /** + * Overload to allow requesting a different context type. By default only OpenGL is supported. + * However by explicitly overloading this a system may add support for others. + */ + virtual GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type) = 0; + + /** * Dispose of a context. * \param context Pointer to the context to be disposed. * \return Indication of success. diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 98dd1de867f..38a6a0b04d2 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -140,7 +140,10 @@ typedef enum { GHOST_kWindowOrderTop = 0, GHOST_kWindowOrderBottom } GHOST_TWind typedef enum { GHOST_kDrawingContextTypeNone = 0, - GHOST_kDrawingContextTypeOpenGL + GHOST_kDrawingContextTypeOpenGL, +#ifdef WIN32 + GHOST_kDrawingContextTypeD3D, +#endif } GHOST_TDrawingContextType; typedef enum { diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 3c3860bd2c0..9a7e3da828b 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -146,6 +146,25 @@ GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle, return system->disposeContext(context); } +#ifdef WIN32 +GHOST_ContextHandle GHOST_CreateDirectXContext(GHOST_SystemHandle systemhandle) +{ + GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; + + return (GHOST_ContextHandle)system->createOffscreenContext(GHOST_kDrawingContextTypeD3D); +} + +GHOST_TSuccess GHOST_DisposeDirectXContext(GHOST_SystemHandle systemhandle, + GHOST_ContextHandle contexthandle) +{ + GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; + GHOST_IContext *context = (GHOST_IContext *)contexthandle; + + return system->disposeContext(context); +} + +#endif + GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, const char *title, GHOST_TInt32 left, diff --git a/intern/ghost/intern/GHOST_ContextD3D.cpp b/intern/ghost/intern/GHOST_ContextD3D.cpp new file mode 100644 index 00000000000..ed65d499073 --- /dev/null +++ b/intern/ghost/intern/GHOST_ContextD3D.cpp @@ -0,0 +1,358 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup GHOST + * + * For testing purposes, it can be useful to do some DirectX only drawing. A patch for this can be + * found here: https://developer.blender.org/P1284 + */ + +#include <iostream> +#include <string> + +#include <GL/glew.h> +#include <GL/wglew.h> + +#include "GHOST_ContextWGL.h" /* For shared drawing */ +#include "GHOST_ContextD3D.h" + +HMODULE GHOST_ContextD3D::s_d3d_lib = NULL; +PFN_D3D11_CREATE_DEVICE GHOST_ContextD3D::s_D3D11CreateDeviceFn = NULL; + +GHOST_ContextD3D::GHOST_ContextD3D(bool stereoVisual, HWND hWnd) + : GHOST_Context(stereoVisual), m_hWnd(hWnd) +{ +} + +GHOST_ContextD3D::~GHOST_ContextD3D() +{ + m_device->Release(); + m_device_ctx->ClearState(); + m_device_ctx->Release(); +} + +GHOST_TSuccess GHOST_ContextD3D::swapBuffers() +{ + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_ContextD3D::activateDrawingContext() +{ + return GHOST_kFailure; +} + +GHOST_TSuccess GHOST_ContextD3D::releaseDrawingContext() +{ + return GHOST_kFailure; +} + +GHOST_TSuccess GHOST_ContextD3D::setupD3DLib() +{ + if (s_d3d_lib == NULL) { + s_d3d_lib = LoadLibraryA("d3d11.dll"); + + WIN32_CHK(s_d3d_lib != NULL); + + if (s_d3d_lib == NULL) { + fprintf(stderr, "LoadLibrary(\"d3d11.dll\") failed!\n"); + return GHOST_kFailure; + } + } + + if (s_D3D11CreateDeviceFn == NULL) { + s_D3D11CreateDeviceFn = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(s_d3d_lib, + "D3D11CreateDevice"); + + WIN32_CHK(s_D3D11CreateDeviceFn != NULL); + + if (s_D3D11CreateDeviceFn == NULL) { + fprintf(stderr, "GetProcAddress(s_d3d_lib, \"D3D11CreateDevice\") failed!\n"); + return GHOST_kFailure; + } + } + + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_ContextD3D::initializeDrawingContext() +{ + if (setupD3DLib() == GHOST_kFailure) { + return GHOST_kFailure; + } + + HRESULT hres = s_D3D11CreateDeviceFn( + NULL, + D3D_DRIVER_TYPE_HARDWARE, + NULL, + /* For debugging you may want to pass D3D11_CREATE_DEVICE_DEBUG here, but that requires + * additional setup, see + * https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-layers#debug-layer. + */ + 0, + NULL, + 0, + D3D11_SDK_VERSION, + &m_device, + NULL, + &m_device_ctx); + + WIN32_CHK(hres == S_OK); + + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_ContextD3D::releaseNativeHandles() +{ + return GHOST_kFailure; +} + +class GHOST_SharedOpenGLResource { + struct SharedData { + HANDLE device; + GLuint fbo; + HANDLE render_buf{nullptr}; + } m_shared; + + public: + GHOST_SharedOpenGLResource(ID3D11Device *device, + ID3D11DeviceContext *device_ctx, + unsigned int width, + unsigned int height, + ID3D11RenderTargetView *render_target = nullptr) + : m_device(device), m_device_ctx(device_ctx), m_cur_width(width), m_cur_height(height) + { + ID3D11Resource *backbuffer_res; + + if (!render_target) { + D3D11_TEXTURE2D_DESC texDesc{}; + D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc{}; + ID3D11Texture2D *tex; + + texDesc.Width = width; + texDesc.Height = height; + texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + texDesc.SampleDesc.Count = 1; + texDesc.ArraySize = 1; + texDesc.MipLevels = 1; + texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + + device->CreateTexture2D(&texDesc, NULL, &tex); + if (!tex) { + /* If texture creation fails, we just return and leave the render target unset. So it needs + * to be NULL-checked before use. */ + fprintf(stderr, "Error creating texture for shared DirectX-OpenGL resource\n"); + return; + } + + renderTargetViewDesc.Format = texDesc.Format; + renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + renderTargetViewDesc.Texture2D.MipSlice = 0; + + device->CreateRenderTargetView(tex, &renderTargetViewDesc, &render_target); + + tex->Release(); + } + + m_render_target = render_target; + if (m_render_target) { + m_render_target->GetResource(&backbuffer_res); + } + if (backbuffer_res) { + backbuffer_res->QueryInterface<ID3D11Texture2D>(&m_render_target_tex); + backbuffer_res->Release(); + } + + if (!m_render_target || !m_render_target_tex) { + fprintf(stderr, "Error creating render target for shared DirectX-OpenGL resource\n"); + return; + } + } + + ~GHOST_SharedOpenGLResource() + { + if (m_render_target_tex) { + m_render_target_tex->Release(); + } + if (m_render_target) { + m_render_target->Release(); + } + + if (m_is_initialized) { + if (m_shared.render_buf) { + wglDXUnregisterObjectNV(m_shared.device, m_shared.render_buf); + } + if (m_shared.device) { + wglDXCloseDeviceNV(m_shared.device); + } + glDeleteFramebuffers(1, &m_shared.fbo); + glDeleteRenderbuffers(1, &m_gl_render_buf); + } + } + + void reregisterSharedObject() + { + if (m_shared.render_buf) { + wglDXUnregisterObjectNV(m_shared.device, m_shared.render_buf); + } + + if (!m_render_target_tex) { + return; + } + + m_shared.render_buf = wglDXRegisterObjectNV(m_shared.device, + m_render_target_tex, + m_gl_render_buf, + GL_RENDERBUFFER, + WGL_ACCESS_READ_WRITE_NV); + + if (!m_shared.render_buf) { + fprintf(stderr, "Error registering shared object using wglDXRegisterObjectNV()\n"); + return; + } + } + + GHOST_TSuccess initialize() + { + m_shared.device = wglDXOpenDeviceNV(m_device); + if (m_shared.device == NULL) { + fprintf(stderr, "Error opening shared device using wglDXOpenDeviceNV()\n"); + return GHOST_kFailure; + } + + /* Build the renderbuffer. */ + glGenRenderbuffers(1, &m_gl_render_buf); + glBindRenderbuffer(GL_RENDERBUFFER, m_gl_render_buf); + + reregisterSharedObject(); + + /* Build the framebuffer */ + glGenFramebuffers(1, &m_shared.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, m_shared.fbo); + glFramebufferRenderbuffer( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_gl_render_buf); + m_is_initialized = true; + + return GHOST_kSuccess; + } + + void ensureUpdated(unsigned int width, unsigned int height) + { + if (m_is_initialized == false) { + initialize(); + } + + if ((m_cur_width != width) || (m_cur_height != height)) { + m_cur_width = width; + m_cur_height = height; + reregisterSharedObject(); + } + } + + GHOST_TSuccess blit(unsigned int width, unsigned int height) + { + GLint fbo; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &fbo); + + if (!m_render_target || !m_render_target_tex) { + return GHOST_kFailure; + } + + ensureUpdated(width, height); + +#ifdef NDEBUG + const float clear_col[] = {0.8f, 0.5f, 1.0f, 1.0f}; + m_device_ctx->ClearRenderTargetView(m_render_target, clear_col); +#endif + m_device_ctx->OMSetRenderTargets(1, &m_render_target, nullptr); + + beginGLOnly(); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_shared.fbo); + GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (err != GL_FRAMEBUFFER_COMPLETE) { + fprintf( + stderr, "Error: Framebuffer for shared DirectX-OpenGL resource incomplete %u\n", err); + return GHOST_kFailure; + } + + /* No glBlitNamedFramebuffer, gotta be 3.3 compatible. */ + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + endGLOnly(); + + return GHOST_kSuccess; + } + + ID3D11RenderTargetView *m_render_target{nullptr}; + ID3D11Texture2D *m_render_target_tex{nullptr}; + + private: + void beginGLOnly() + { + wglDXLockObjectsNV(m_shared.device, 1, &m_shared.render_buf); + } + void endGLOnly() + { + wglDXUnlockObjectsNV(m_shared.device, 1, &m_shared.render_buf); + } + + ID3D11Device *m_device; + ID3D11DeviceContext *m_device_ctx; + GLuint m_gl_render_buf; + unsigned int m_cur_width, m_cur_height; + bool m_is_initialized{false}; +}; + +GHOST_SharedOpenGLResource *GHOST_ContextD3D::createSharedOpenGLResource( + unsigned int width, unsigned int height, ID3D11RenderTargetView *render_target) +{ + if (!(WGL_NV_DX_interop && WGL_NV_DX_interop2)) { + fprintf(stderr, + "Error: Can't render OpenGL framebuffer using Direct3D. NV_DX_interop extension not " + "available."); + return nullptr; + } + GHOST_SharedOpenGLResource *shared_res = new GHOST_SharedOpenGLResource( + m_device, m_device_ctx, width, height, render_target); + + return shared_res; +} +GHOST_SharedOpenGLResource *GHOST_ContextD3D::createSharedOpenGLResource(unsigned int width, + unsigned int height) +{ + return createSharedOpenGLResource(width, height, nullptr); +} + +void GHOST_ContextD3D::disposeSharedOpenGLResource(GHOST_SharedOpenGLResource *shared_res) +{ + delete shared_res; +} + +GHOST_TSuccess GHOST_ContextD3D::blitFromOpenGLContext(GHOST_SharedOpenGLResource *shared_res, + unsigned int width, + unsigned int height) +{ + return shared_res->blit(width, height); +} + +ID3D11Texture2D *GHOST_ContextD3D::getSharedTexture2D(GHOST_SharedOpenGLResource *shared_res) +{ + return shared_res->m_render_target_tex; +} diff --git a/intern/ghost/intern/GHOST_ContextD3D.h b/intern/ghost/intern/GHOST_ContextD3D.h new file mode 100644 index 00000000000..601282fc80f --- /dev/null +++ b/intern/ghost/intern/GHOST_ContextD3D.h @@ -0,0 +1,133 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup GHOST + */ + +#ifndef __GHOST_CONTEXTD3D_H__ +#define __GHOST_CONTEXTD3D_H__ + +#ifndef WIN32 +# error WIN32 only! +#endif // WIN32 + +#include <D3D11.h> + +#include "GHOST_Context.h" + +class GHOST_ContextD3D : public GHOST_Context { + public: + GHOST_ContextD3D(bool stereoVisual, HWND hWnd); + ~GHOST_ContextD3D(); + + /** + * Swaps front and back buffers of a window. + * \return A boolean success indicator. + */ + GHOST_TSuccess swapBuffers(); + + /** + * Activates the drawing context of this window. + * \return A boolean success indicator. + */ + GHOST_TSuccess activateDrawingContext(); + + /** + * Release the drawing context of the calling thread. + * \return A boolean success indicator. + */ + GHOST_TSuccess releaseDrawingContext(); + + /** + * Call immediately after new to initialize. If this fails then immediately delete the object. + * \return Indication as to whether initialization has succeeded. + */ + GHOST_TSuccess initializeDrawingContext(); + + /** + * Updates the drawing context of this window. Needed + * whenever the window is changed. + * \return Indication of success. + */ + GHOST_TSuccess updateDrawingContext() + { + return GHOST_kFailure; + } + + /** + * Checks if it is OK for a remove the native display + * \return Indication as to whether removal has succeeded. + */ + GHOST_TSuccess releaseNativeHandles(); + + /** + * Sets the swap interval for swapBuffers. + * \param interval The swap interval to use. + * \return A boolean success indicator. + */ + GHOST_TSuccess setSwapInterval(int /*interval*/) + { + return GHOST_kFailure; + } + + /** + * Gets the current swap interval for swapBuffers. + * \param intervalOut Variable to store the swap interval if it can be read. + * \return Whether the swap interval can be read. + */ + GHOST_TSuccess getSwapInterval(int &) + { + return GHOST_kFailure; + } + + /** + * Gets the OpenGL framebuffer associated with the OpenGL context + * \return The ID of an OpenGL framebuffer object. + */ + unsigned int getDefaultFramebuffer() + { + return 0; + } + + class GHOST_SharedOpenGLResource *createSharedOpenGLResource( + unsigned int width, unsigned int height, ID3D11RenderTargetView *render_target); + class GHOST_SharedOpenGLResource *createSharedOpenGLResource(unsigned int width, + unsigned int height); + void disposeSharedOpenGLResource(class GHOST_SharedOpenGLResource *shared_res); + GHOST_TSuccess blitFromOpenGLContext(class GHOST_SharedOpenGLResource *shared_res, + unsigned int width, + unsigned int height); + ID3D11Texture2D *getSharedTexture2D(class GHOST_SharedOpenGLResource *shared_res); + + bool isUpsideDown() const + { + return true; + } + + private: + GHOST_TSuccess setupD3DLib(); + + static HMODULE s_d3d_lib; + static PFN_D3D11_CREATE_DEVICE s_D3D11CreateDeviceFn; + + HWND m_hWnd; + + ID3D11Device *m_device; + ID3D11DeviceContext *m_device_ctx; +}; + +#endif /* __GHOST_CONTEXTD3D_H__ */ diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index fc9ce1f66e1..12096d65240 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -122,6 +122,16 @@ GHOST_TSuccess GHOST_System::disposeWindow(GHOST_IWindow *window) return success; } +GHOST_IContext *GHOST_System::createOffscreenContext(GHOST_TDrawingContextType type) +{ + switch (type) { + case GHOST_kDrawingContextTypeOpenGL: + return createOffscreenContext(); + default: + return NULL; + } +} + bool GHOST_System::validWindow(GHOST_IWindow *window) { return m_windowManager->getWindowFound(window); diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index 26b566e6b7e..dff27b0903d 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -112,6 +112,19 @@ class GHOST_System : public GHOST_ISystem { GHOST_TSuccess disposeWindow(GHOST_IWindow *window); /** + * Create a new offscreen context. + * Never explicitly delete the context, use disposeContext() instead. + * \return The new context (or 0 if creation failed). + */ + virtual GHOST_IContext *createOffscreenContext() = 0; + + /** + * Overload to allow requesting a different context type. By default only OpenGL is supported. + * However by explicitly overloading this a system may add support for others. + */ + GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type); + + /** * Returns whether a window is valid. * \param window Pointer to the window to be checked. * \return Indication of validity. diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 4a4016cbca1..7d2a8f5810c 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -21,6 +21,7 @@ * \ingroup GHOST */ +#include "GHOST_ContextD3D.h" #include "GHOST_SystemWin32.h" #include "GHOST_EventDragnDrop.h" @@ -405,6 +406,47 @@ GHOST_TSuccess GHOST_SystemWin32::disposeContext(GHOST_IContext *context) return GHOST_kSuccess; } +/** + * Create a new offscreen DirectX 11 context. + * Never explicitly delete the window, use #disposeContext() instead. + * \return The new context (or 0 if creation failed). + */ +GHOST_IContext *GHOST_SystemWin32::createOffscreenContextD3D() +{ + GHOST_Context *context; + + HWND wnd = CreateWindowA("STATIC", + "Blender XR", + WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, + 0, + 0, + 64, + 64, + NULL, + NULL, + GetModuleHandle(NULL), + NULL); + + context = new GHOST_ContextD3D(false, wnd); + if (context->initializeDrawingContext() == GHOST_kFailure) { + delete context; + } + + return context; +} + +GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_TDrawingContextType type) +{ + switch (type) { + case GHOST_kDrawingContextTypeOpenGL: + return createOffscreenContext(); + case GHOST_kDrawingContextTypeD3D: + return createOffscreenContextD3D(); + default: + return NULL; + } +} + bool GHOST_SystemWin32::processEvents(bool waitForEvent) { MSG msg; diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index b069e6cf3b6..c5af3e120be 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -131,6 +131,13 @@ class GHOST_SystemWin32 : public GHOST_System { GHOST_IContext *createOffscreenContext(); /** + * Create a new offscreen context. + * Never explicitly delete the window, use disposeContext() instead. + * \return The new context (or 0 if creation failed). + */ + GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type); + + /** * Dispose of a context. * \param context Pointer to the context to be disposed. * \return Indication of success. @@ -249,6 +256,13 @@ class GHOST_SystemWin32 : public GHOST_System { GHOST_TSuccess exit(); /** + * Create a new offscreen DirectX context. + * Never explicitly delete the window, use disposeContext() instead. + * \return The new context (or 0 if creation failed). + */ + GHOST_IContext *createOffscreenContextD3D(); + + /** * Converts raw WIN32 key codes from the wndproc to GHOST keys. * \param vKey The virtual key from hardKey * \param ScanCode The ScanCode of pressed key (similar to PS/2 Set 1) diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 2ab0e837efb..1d2630bc66d 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -23,6 +23,7 @@ #define _USE_MATH_DEFINES +#include "GHOST_ContextD3D.h" #include "GHOST_WindowManager.h" #include "GHOST_WindowWin32.h" #include "GHOST_SystemWin32.h" @@ -750,6 +751,19 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty # error // must specify either core or compat at build time #endif } + else if (type == GHOST_kDrawingContextTypeD3D) { + GHOST_Context *context; + + context = new GHOST_ContextD3D(false, m_hWnd); + if (context->initializeDrawingContext()) { + return context; + } + else { + delete context; + } + + return context; + } return NULL; } |