From 2c03cf49279965e79386aa0c965d5c973ed670e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Sun, 7 Sep 2014 17:17:38 -0700 Subject: [PATCH] Added multiple windows support. --- include/bgfx.h | 9 ++ src/bgfx.cpp | 68 ++++++++--- src/bgfx_p.h | 81 ++++++++++--- src/glcontext_eagl.h | 13 +++ src/glcontext_egl.cpp | 18 ++- src/glcontext_egl.h | 9 +- src/glcontext_glx.cpp | 18 ++- src/glcontext_glx.h | 9 +- src/glcontext_ppapi.cpp | 17 ++- src/glcontext_ppapi.h | 9 +- src/glcontext_wgl.cpp | 100 +++++++++++++--- src/glcontext_wgl.h | 14 ++- src/renderer_d3d11.cpp | 69 ++++++++++- src/renderer_d3d11.h | 8 +- src/renderer_d3d9.cpp | 253 +++++++++++++++++++++++++++------------- src/renderer_d3d9.h | 12 +- src/renderer_gl.cpp | 73 ++++++++++-- src/renderer_gl.h | 11 +- src/renderer_null.cpp | 4 + 19 files changed, 633 insertions(+), 162 deletions(-) diff --git a/include/bgfx.h b/include/bgfx.h index 921e8579..c3f5cbb3 100644 --- a/include/bgfx.h +++ b/include/bgfx.h @@ -815,6 +815,9 @@ namespace bgfx /// FrameBufferHandle createFrameBuffer(uint8_t _num, TextureHandle* _handles, bool _destroyTextures = false); + /// Create frame buffer. + FrameBufferHandle createFrameBuffer(void* _nwh, uint16_t _width, uint16_t _height, TextureFormat::Enum _depthFormat = TextureFormat::UnknownDepth); + /// Destroy frame buffer. void destroyFrameBuffer(FrameBufferHandle _handle); @@ -971,6 +974,9 @@ namespace bgfx /// frame buffer handle will draw primitives from this view into /// default back buffer. /// + /// NOTE: + /// Not persistent after bgfx::reset call. + /// void setViewFrameBuffer(uint8_t _id, FrameBufferHandle _handle); /// Set view frame buffer for multiple views. @@ -980,6 +986,9 @@ namespace bgfx /// frame buffer handle will draw primitives from this view into /// default back buffer. /// + /// NOTE: + /// Not persistent after bgfx::reset call. + /// void setViewFrameBufferMask(uint32_t _viewMask, FrameBufferHandle _handle); /// Set view view and projection matrices, all draw primitives in this diff --git a/src/bgfx.cpp b/src/bgfx.cpp index e3f0bebd..8c971f80 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -699,12 +699,13 @@ namespace bgfx BX_WARN(invalidHandle != m_key.m_program, "Program with invalid handle"); if (invalidHandle != m_key.m_program) { - m_key.m_depth = _depth; - m_key.m_view = _id; - m_key.m_seq = s_ctx->m_seq[_id] & s_ctx->m_seqMask[_id]; + m_key.m_depth = _depth; + m_key.m_view = _id; + m_key.m_seq = s_ctx->m_seq[_id] & s_ctx->m_seqMask[_id]; s_ctx->m_seq[_id]++; + uint64_t key = m_key.encodeDraw(); - m_sortKeys[m_num] = key; + m_sortKeys[m_num] = key; m_sortValues[m_num] = m_numRenderItems; ++m_num; @@ -749,11 +750,12 @@ namespace bgfx viewMask >>= ntz; id += ntz; - m_key.m_view = id; - m_key.m_seq = s_ctx->m_seq[id] & s_ctx->m_seqMask[id]; + m_key.m_view = id; + m_key.m_seq = s_ctx->m_seq[id] & s_ctx->m_seqMask[id]; s_ctx->m_seq[id]++; + uint64_t key = m_key.encodeDraw(); - m_sortKeys[m_num] = key; + m_sortKeys[m_num] = key; m_sortValues[m_num] = m_numRenderItems; ++m_num; } @@ -794,12 +796,13 @@ namespace bgfx m_key.m_program = _handle.idx; if (invalidHandle != m_key.m_program) { - m_key.m_depth = 0; - m_key.m_view = _id; - m_key.m_seq = s_ctx->m_seq[_id] & s_ctx->m_seqMask[_id]; + m_key.m_depth = 0; + m_key.m_view = _id; + m_key.m_seq = s_ctx->m_seq[_id] & s_ctx->m_seqMask[_id]; s_ctx->m_seq[_id]++; + uint64_t key = m_key.encodeCompute(); - m_sortKeys[m_num] = key; + m_sortKeys[m_num] = key; m_sortValues[m_num] = m_numRenderItems; ++m_num; @@ -1094,7 +1097,6 @@ namespace bgfx CHECK_HANDLE_LEAK(m_textureHandle); CHECK_HANDLE_LEAK(m_frameBufferHandle); CHECK_HANDLE_LEAK(m_uniformHandle); - #undef CHECK_HANDLE_LEAK } } @@ -1781,16 +1783,38 @@ again: FrameBufferHandle handle; _cmdbuf.read(handle); - uint8_t num; - _cmdbuf.read(num); + bool window; + _cmdbuf.read(window); - TextureHandle textureHandles[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; - for (uint32_t ii = 0; ii < num; ++ii) + if (window) { - _cmdbuf.read(textureHandles[ii]); - } + void* nwh; + _cmdbuf.read(nwh); - m_renderCtx->createFrameBuffer(handle, num, textureHandles); + uint16_t width; + _cmdbuf.read(width); + + uint16_t height; + _cmdbuf.read(height); + + TextureFormat::Enum depthFormat; + _cmdbuf.read(depthFormat); + + m_renderCtx->createFrameBuffer(handle, nwh, width, height, depthFormat); + } + else + { + uint8_t num; + _cmdbuf.read(num); + + TextureHandle textureHandles[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; + for (uint32_t ii = 0; ii < num; ++ii) + { + _cmdbuf.read(textureHandles[ii]); + } + + m_renderCtx->createFrameBuffer(handle, num, textureHandles); + } } break; @@ -2479,6 +2503,12 @@ again: return handle; } + FrameBufferHandle createFrameBuffer(void* _nwh, uint16_t _width, uint16_t _height, TextureFormat::Enum _depthFormat) + { + BGFX_CHECK_MAIN_THREAD(); + return s_ctx->createFrameBuffer(_nwh, _width, _height, _depthFormat); + } + void destroyFrameBuffer(FrameBufferHandle _handle) { BGFX_CHECK_MAIN_THREAD(); diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 9f9f2bc0..a4e42153 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -640,6 +640,10 @@ namespace bgfx }; #define SORT_KEY_RENDER_DRAW UINT64_C(0x0000000800000000) + + BX_STATIC_ASSERT(BGFX_CONFIG_MAX_VIEWS <= 32); + BX_STATIC_ASSERT( (BGFX_CONFIG_MAX_PROGRAMS & (BGFX_CONFIG_MAX_PROGRAMS-1) ) == 0); // must be power of 2 + struct SortKey { uint64_t encodeDraw() @@ -1422,14 +1426,14 @@ namespace bgfx void resetFreeHandles() { - m_numFreeIndexBufferHandles = 0; - m_numFreeVertexDeclHandles = 0; + m_numFreeIndexBufferHandles = 0; + m_numFreeVertexDeclHandles = 0; m_numFreeVertexBufferHandles = 0; - m_numFreeShaderHandles = 0; - m_numFreeProgramHandles = 0; - m_numFreeTextureHandles = 0; - m_numFreeFrameBufferHandles = 0; - m_numFreeUniformHandles = 0; + m_numFreeShaderHandles = 0; + m_numFreeProgramHandles = 0; + m_numFreeTextureHandles = 0; + m_numFreeFrameBufferHandles = 0; + m_numFreeUniformHandles = 0; } SortKey m_key; @@ -1479,6 +1483,7 @@ namespace bgfx uint16_t m_numFreeTextureHandles; uint16_t m_numFreeFrameBufferHandles; uint16_t m_numFreeUniformHandles; + uint16_t m_numFreeWindowHandles; IndexBufferHandle m_freeIndexBufferHandle[BGFX_CONFIG_MAX_INDEX_BUFFERS]; VertexDeclHandle m_freeVertexDeclHandle[BGFX_CONFIG_MAX_VERTEX_DECLS]; @@ -1696,6 +1701,7 @@ namespace bgfx virtual void updateTextureEnd() = 0; virtual void destroyTexture(TextureHandle _handle) = 0; virtual void createFrameBuffer(FrameBufferHandle _handle, uint8_t _num, const TextureHandle* _textureHandles) = 0; + virtual void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _depthFormat) = 0; virtual void destroyFrameBuffer(FrameBufferHandle _handle) = 0; virtual void createUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name) = 0; virtual void destroyUniform(UniformHandle _handle) = 0; @@ -2464,23 +2470,25 @@ namespace bgfx BGFX_API_FUNC(FrameBufferHandle createFrameBuffer(uint8_t _num, TextureHandle* _handles) ) { FrameBufferHandle handle = { m_frameBufferHandle.alloc() }; - BX_WARN(isValid(handle), "Failed to allocate render target handle."); + BX_WARN(isValid(handle), "Failed to allocate frame buffer handle."); if (isValid(handle) ) { CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateFrameBuffer); cmdbuf.write(handle); + cmdbuf.write(false); cmdbuf.write(_num); FrameBufferRef& ref = m_frameBufferRef[handle.idx]; - memset(ref.m_th, 0xff, sizeof(ref.m_th) ); + ref.m_window = false; + memset(ref.un.m_th, 0xff, sizeof(ref.un.m_th) ); for (uint32_t ii = 0; ii < _num; ++ii) { TextureHandle handle = _handles[ii]; cmdbuf.write(handle); - ref.m_th[ii] = handle; + ref.un.m_th[ii] = handle; textureIncRef(handle); } } @@ -2488,6 +2496,29 @@ namespace bgfx return handle; } + BGFX_API_FUNC(FrameBufferHandle createFrameBuffer(void* _nwh, uint16_t _width, uint16_t _height, TextureFormat::Enum _depthFormat) ) + { + FrameBufferHandle handle = { m_frameBufferHandle.alloc() }; + BX_WARN(isValid(handle), "Failed to allocate frame buffer handle."); + + if (isValid(handle) ) + { + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateFrameBuffer); + cmdbuf.write(handle); + cmdbuf.write(true); + cmdbuf.write(_nwh); + cmdbuf.write(_width); + cmdbuf.write(_height); + cmdbuf.write(_depthFormat); + + FrameBufferRef& ref = m_frameBufferRef[handle.idx]; + ref.m_window = true; + ref.un.m_nwh = _nwh; + } + + return handle; + } + BGFX_API_FUNC(void destroyFrameBuffer(FrameBufferHandle _handle) ) { CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::DestroyFrameBuffer); @@ -2495,12 +2526,15 @@ namespace bgfx m_submit->free(_handle); FrameBufferRef& ref = m_frameBufferRef[_handle.idx]; - for (uint32_t ii = 0; ii < BX_COUNTOF(ref.m_th); ++ii) + if (!ref.m_window) { - TextureHandle th = ref.m_th[ii]; - if (isValid(th) ) + for (uint32_t ii = 0; ii < BX_COUNTOF(ref.un.m_th); ++ii) { - textureDecRef(th); + TextureHandle th = ref.un.m_th[ii]; + if (isValid(th) ) + { + textureDecRef(th); + } } } } @@ -2614,7 +2648,7 @@ namespace bgfx Rect& rect = m_rect[_id]; rect.m_x = _x; rect.m_y = _y; - rect.m_width = bx::uint16_max(_width, 1); + rect.m_width = bx::uint16_max(_width, 1); rect.m_height = bx::uint16_max(_height, 1); } @@ -2634,7 +2668,7 @@ namespace bgfx Rect& scissor = m_scissor[_id]; scissor.m_x = _x; scissor.m_y = _y; - scissor.m_width = _width; + scissor.m_width = _width; scissor.m_height = _height; } @@ -2850,7 +2884,9 @@ namespace bgfx TextureHandle textureHandle = BGFX_INVALID_HANDLE; if (isValid(_handle) ) { - textureHandle = m_frameBufferRef[_handle.idx].m_th[_attachment]; + const FrameBufferRef& ref = m_frameBufferRef[_handle.idx]; + BX_CHECK(!ref.m_window, "Can't sample window frame buffer."); + textureHandle = ref.un.m_th[_attachment]; BX_CHECK(isValid(textureHandle), "Frame buffer texture %d is invalid.", _attachment); } @@ -2878,7 +2914,9 @@ namespace bgfx TextureHandle textureHandle = BGFX_INVALID_HANDLE; if (isValid(_handle) ) { - textureHandle = m_frameBufferRef[_handle.idx].m_th[_attachment]; + const FrameBufferRef& ref = m_frameBufferRef[_handle.idx]; + BX_CHECK(!ref.m_window, "Can't sample window frame buffer."); + textureHandle = ref.un.m_th[_attachment]; BX_CHECK(isValid(textureHandle), "Frame buffer texture %d is invalid.", _attachment); } @@ -3014,7 +3052,12 @@ namespace bgfx struct FrameBufferRef { - TextureHandle m_th[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; + union un + { + TextureHandle m_th[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; + void* m_nwh; + } un; + bool m_window; }; typedef stl::unordered_map UniformHashMap; diff --git a/src/glcontext_eagl.h b/src/glcontext_eagl.h index 17b60145..341e8dd0 100644 --- a/src/glcontext_eagl.h +++ b/src/glcontext_eagl.h @@ -10,6 +10,8 @@ namespace bgfx { + struct SwapChainGL; + struct GlContext { GlContext() @@ -21,8 +23,19 @@ namespace bgfx void destroy(); void resize(uint32_t _width, uint32_t _height, bool _vsync); void swap(); + + SwapChainGL* createSwapChain(void* _nwh); + void destorySwapChain(SwapChainGL* _swapChain); + void swap(SwapChainGL* _swapChain = NULL); + void makeCurrent(SwapChainGL* _swapChain = NULL); + void import(); + GLuint getFbo() + { + return m_fbo; + } + bool isValid() const { return 0 != m_context; diff --git a/src/glcontext_egl.cpp b/src/glcontext_egl.cpp index 9cbeec07..eb4025a2 100644 --- a/src/glcontext_egl.cpp +++ b/src/glcontext_egl.cpp @@ -237,12 +237,28 @@ EGL_IMPORT eglSwapInterval(m_display, _vsync ? 1 : 0); } - void GlContext::swap() + SwapChainGL* GlContext::createSwapChain(void* /*_nwh*/) { + BX_CHECK(false, "Shouldn't be called!"); + return NULL; + } + + void GlContext::destorySwapChain(SwapChainGL* /*_swapChain*/) + { + BX_CHECK(false, "Shouldn't be called!"); + } + + void GlContext::swap(SwapChainGL* _swapChain) + { + BX_CHECK(NULL == _swapChain, "Shouldn't be called!"); BX_UNUSED(_swapChain); eglMakeCurrent(m_display, m_surface, m_surface, m_context); eglSwapBuffers(m_display, m_surface); } + void GlContext::makeCurrent(SwapChainGL* /*_swapChain*/) + { + } + void GlContext::import() { BX_TRACE("Import:"); diff --git a/src/glcontext_egl.h b/src/glcontext_egl.h index 5853e773..2d86e266 100644 --- a/src/glcontext_egl.h +++ b/src/glcontext_egl.h @@ -12,6 +12,8 @@ namespace bgfx { + struct SwapChainGL; + struct GlContext { GlContext() @@ -24,7 +26,12 @@ namespace bgfx void create(uint32_t _width, uint32_t _height); void destroy(); void resize(uint32_t _width, uint32_t _height, bool _vsync); - void swap(); + + SwapChainGL* createSwapChain(void* _nwh); + void destorySwapChain(SwapChainGL* _swapChain); + void swap(SwapChainGL* _swapChain = NULL); + void makeCurrent(SwapChainGL* _swapChain = NULL); + void import(); bool isValid() const diff --git a/src/glcontext_glx.cpp b/src/glcontext_glx.cpp index 4e32417b..c132dc76 100644 --- a/src/glcontext_glx.cpp +++ b/src/glcontext_glx.cpp @@ -212,11 +212,27 @@ namespace bgfx } } - void GlContext::swap() + SwapChainGL* GlContext::createSwapChain(void* /*_nwh*/) { + BX_CHECK(false, "Shouldn't be called!"); + return NULL; + } + + void GlContext::destorySwapChain(SwapChainGL* /*_swapChain*/) + { + BX_CHECK(false, "Shouldn't be called!"); + } + + void GlContext::swap(SwapChainGL* _swapChain) + { + BX_CHECK(NULL == _swapChain, "Shouldn't be called!"); BX_UNUSED(_swapChain); glXSwapBuffers(s_display, s_window); } + void GlContext::makeCurrent(SwapChainGL* /*_swapChain*/) + { + } + void GlContext::import() { # define GL_EXTENSION(_optional, _proto, _func, _import) \ diff --git a/src/glcontext_glx.h b/src/glcontext_glx.h index 00d121a2..1999bb24 100644 --- a/src/glcontext_glx.h +++ b/src/glcontext_glx.h @@ -13,6 +13,8 @@ namespace bgfx { + struct SwapChainGL; + struct GlContext { GlContext() @@ -23,7 +25,12 @@ namespace bgfx void create(uint32_t _width, uint32_t _height); void destroy(); void resize(uint32_t _width, uint32_t _height, bool _vsync); - void swap(); + + SwapChainGL* createSwapChain(void* _nwh); + void destorySwapChain(SwapChainGL* _swapChain); + void swap(SwapChainGL* _swapChain = NULL); + void makeCurrent(SwapChainGL* _swapChain = NULL); + void import(); bool isValid() const diff --git a/src/glcontext_ppapi.cpp b/src/glcontext_ppapi.cpp index ca47417d..37e2dfbc 100644 --- a/src/glcontext_ppapi.cpp +++ b/src/glcontext_ppapi.cpp @@ -158,11 +158,26 @@ namespace bgfx s_ppapi.resize(_width, _height, _vsync); } - void GlContext::swap() + SwapChainGL* GlContext::createSwapChain(void* /*_nwh*/) + { + BX_CHECK(false, "Shouldn't be called!"); + return NULL; + } + + void GlContext::destorySwapChain(SwapChainGL* /*_swapChain*/) + { + BX_CHECK(false, "Shouldn't be called!"); + } + + void GlContext::swap(SwapChainGL* /*_swapChain*/) { s_ppapi.swap(); } + void GlContext::makeCurrent(SwapChainGL* /*_swapChain*/) + { + } + void GlContext::import() { } diff --git a/src/glcontext_ppapi.h b/src/glcontext_ppapi.h index 9fb021c8..230d088f 100644 --- a/src/glcontext_ppapi.h +++ b/src/glcontext_ppapi.h @@ -15,6 +15,8 @@ namespace bgfx { + struct SwapChainGL; + struct GlContext { GlContext() @@ -24,7 +26,12 @@ namespace bgfx void create(uint32_t _width, uint32_t _height); void destroy(); void resize(uint32_t _width, uint32_t _height, bool _vsync); - void swap(); + + SwapChainGL* createSwapChain(void* _nwh); + void destorySwapChain(SwapChainGL* _swapChain); + void swap(SwapChainGL* _swapChain = NULL); + void makeCurrent(SwapChainGL* _swapChain = NULL); + void import(); bool isValid() const; }; diff --git a/src/glcontext_wgl.cpp b/src/glcontext_wgl.cpp index 81502d78..ab28b788 100644 --- a/src/glcontext_wgl.cpp +++ b/src/glcontext_wgl.cpp @@ -24,6 +24,36 @@ namespace bgfx # define GL_IMPORT(_optional, _proto, _func, _import) _proto _func # include "glimports.h" + struct SwapChainGL + { + SwapChainGL(void* _nwh) + : m_hwnd( (HWND)_nwh) + { + m_hdc = GetDC(m_hwnd); + } + + ~SwapChainGL() + { + wglMakeCurrent(NULL, NULL); + wglDeleteContext(m_context); + ReleaseDC(m_hwnd, m_hdc); + } + + void makeCurrent() + { + wglMakeCurrent(m_hdc, m_context); + } + + void swapBuffers() + { + SwapBuffers(m_hdc); + } + + HWND m_hwnd; + HDC m_hdc; + HGLRC m_context; + }; + static HGLRC createContext(HDC _hdc) { PIXELFORMATDESCRIPTOR pfd; @@ -121,10 +151,10 @@ namespace bgfx HGLRC context = createContext(hdc); - wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); - wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); + wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); + wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); - wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); + wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); if (NULL != wglGetExtensionsStringARB) { @@ -151,11 +181,10 @@ namespace bgfx }; int result; - int pixelFormat; uint32_t numFormats = 0; do { - result = wglChoosePixelFormatARB(m_hdc, attrs, NULL, 1, &pixelFormat, &numFormats); + result = wglChoosePixelFormatARB(m_hdc, attrs, NULL, 1, &m_pixelFormat, &numFormats); if (0 == result || 0 == numFormats) { @@ -165,8 +194,7 @@ namespace bgfx } while (0 == numFormats); - PIXELFORMATDESCRIPTOR pfd; - DescribePixelFormat(m_hdc, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + DescribePixelFormat(m_hdc, m_pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &m_pfd); BX_TRACE("Pixel format:\n" "\tiPixelType %d\n" @@ -174,14 +202,14 @@ namespace bgfx "\tcAlphaBits %d\n" "\tcDepthBits %d\n" "\tcStencilBits %d\n" - , pfd.iPixelType - , pfd.cColorBits - , pfd.cAlphaBits - , pfd.cDepthBits - , pfd.cStencilBits + , m_pfd.iPixelType + , m_pfd.cColorBits + , m_pfd.cAlphaBits + , m_pfd.cDepthBits + , m_pfd.cStencilBits ); - result = SetPixelFormat(m_hdc, pixelFormat, &pfd); + result = SetPixelFormat(m_hdc, m_pixelFormat, &m_pfd); // When window is created by SDL and SDL_WINDOW_OPENGL is set SetPixelFormat // will fail. Just warn and continue. In case it failed for some other reason // create context will fail and it will error out there. @@ -213,6 +241,9 @@ namespace bgfx m_context = wglCreateContextAttribsARB(m_hdc, 0, contextAttrs); } BGFX_FATAL(NULL != m_context, Fatal::UnableToInitialize, "Failed to create context 0x%08x.", GetLastError() ); + + BX_STATIC_ASSERT(sizeof(contextAttrs) == sizeof(m_contextAttrs) ); + memcpy(m_contextAttrs, contextAttrs, sizeof(contextAttrs) ); } wglMakeCurrent(NULL, NULL); @@ -261,12 +292,49 @@ namespace bgfx } } - void GlContext::swap() + SwapChainGL* GlContext::createSwapChain(void* _nwh) { - if (NULL != g_bgfxHwnd) + SwapChainGL* swapChain = BX_NEW(g_allocator, SwapChainGL)(_nwh); + + int result = SetPixelFormat(swapChain->m_hdc, m_pixelFormat, &m_pfd); + BX_WARN(result, "SetPixelFormat failed (last err: 0x%08x)!", GetLastError() ); + + swapChain->m_context = wglCreateContextAttribsARB(swapChain->m_hdc, m_context, m_contextAttrs); + BX_CHECK(NULL != swapChain->m_context, "Create swap chain failed: %x", glGetError() ); + return swapChain; + } + + void GlContext::destorySwapChain(SwapChainGL* _swapChain) + { + BX_DELETE(g_allocator, _swapChain); + } + + void GlContext::makeCurrent(SwapChainGL* _swapChain) + { + if (NULL == _swapChain) { wglMakeCurrent(m_hdc, m_context); - SwapBuffers(m_hdc); + } + else + { + _swapChain->makeCurrent(); + } + } + + void GlContext::swap(SwapChainGL* _swapChain) + { + if (NULL == _swapChain) + { + if (NULL != g_bgfxHwnd) + { + wglMakeCurrent(m_hdc, m_context); + SwapBuffers(m_hdc); + } + } + else + { + _swapChain->makeCurrent(); + _swapChain->swapBuffers(); } } diff --git a/src/glcontext_wgl.h b/src/glcontext_wgl.h index 9cb4e5cb..d2d726a9 100644 --- a/src/glcontext_wgl.h +++ b/src/glcontext_wgl.h @@ -15,7 +15,7 @@ namespace bgfx typedef PROC (APIENTRYP PFNWGLGETPROCADDRESSPROC) (LPCSTR lpszProc); typedef BOOL (APIENTRYP PFNWGLMAKECURRENTPROC) (HDC hdc, HGLRC hglrc); typedef HGLRC (APIENTRYP PFNWGLCREATECONTEXTPROC) (HDC hdc); -typedef BOOL (APIENTRYP PFNWGLDELETECONTEXTPROC) (HGLRC hglrc); +typedef BOOL (APIENTRYP PFNWGLDELETECONTEXTPROC) (HGLRC hglrc); // typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void); typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); @@ -56,6 +56,8 @@ typedef void (APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum z extern PFNWGLCREATECONTEXTPROC wglCreateContext; extern PFNWGLDELETECONTEXTPROC wglDeleteContext; + struct SwapChainGL; + struct GlContext { GlContext() @@ -68,7 +70,12 @@ typedef void (APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum z void create(uint32_t _width, uint32_t _height); void destroy(); void resize(uint32_t _width, uint32_t _height, bool _vsync); - void swap(); + + SwapChainGL* createSwapChain(void* _nwh); + void destorySwapChain(SwapChainGL* _swapChain); + void swap(SwapChainGL* _swapChain = NULL); + void makeCurrent(SwapChainGL* _swapChain = NULL); + void import(); bool isValid() const @@ -76,6 +83,9 @@ typedef void (APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum z return NULL != m_context; } + int32_t m_contextAttrs[9]; + int m_pixelFormat; + PIXELFORMATDESCRIPTOR m_pfd; void* m_opengl32dll; HGLRC m_context; HDC m_hdc; diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index b24b92d0..ad8b58b2 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -515,7 +515,7 @@ namespace bgfx }; memset(&m_scd, 0, sizeof(m_scd) ); - m_scd.BufferDesc.Width = BGFX_DEFAULT_WIDTH; + m_scd.BufferDesc.Width = BGFX_DEFAULT_WIDTH; m_scd.BufferDesc.Height = BGFX_DEFAULT_HEIGHT; m_scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; m_scd.BufferDesc.RefreshRate.Numerator = 60; @@ -573,6 +573,8 @@ namespace bgfx ); BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Failed to create swap chain."); + m_numWindows = 1; + if (BX_ENABLED(BGFX_CONFIG_DEBUG) ) { ID3D11InfoQueue* infoQueue; @@ -792,9 +794,26 @@ namespace bgfx m_frameBuffers[_handle.idx].create(_num, _textureHandles); } + void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _depthFormat) BX_OVERRIDE + { + uint16_t denseIdx = m_numWindows++; + m_windows[denseIdx] = _handle; + m_frameBuffers[_handle.idx].create(denseIdx, _nwh, _width, _height, _depthFormat); + } + void destroyFrameBuffer(FrameBufferHandle _handle) BX_OVERRIDE { - m_frameBuffers[_handle.idx].destroy(); + uint16_t denseIdx = m_frameBuffers[_handle.idx].destroy(); + if (UINT16_MAX != denseIdx) + { + --m_numWindows; + if (m_numWindows > 1) + { + FrameBufferHandle handle = m_windows[m_numWindows]; + m_windows[denseIdx] = handle; + m_frameBuffers[handle.idx].m_denseIdx = denseIdx; + } + } } void createUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name) BX_OVERRIDE @@ -1013,6 +1032,10 @@ namespace bgfx if (NULL != m_swapChain) { uint32_t syncInterval = !!(m_flags & BGFX_RESET_VSYNC); + for (uint32_t ii = 1, num = m_numWindows; ii < num; ++ii) + { + DX_CHECK(m_frameBuffers[m_windows[ii].idx].m_swapChain->Present(syncInterval, 0) ); + } DX_CHECK(m_swapChain->Present(syncInterval, 0) ); } } @@ -1820,7 +1843,11 @@ namespace bgfx IDXGIAdapter* m_adapter; DXGI_ADAPTER_DESC m_adapterDesc; IDXGIFactory* m_factory; + IDXGISwapChain* m_swapChain; + uint16_t m_numWindows; + FrameBufferHandle m_windows[BGFX_CONFIG_MAX_FRAME_BUFFERS]; + ID3D11Device* m_device; ID3D11DeviceContext* m_deviceCtx; ID3D11RenderTargetView* m_backBufferColor; @@ -2442,7 +2469,8 @@ namespace bgfx { m_rtv[ii] = NULL; } - m_dsv = NULL; + m_dsv = NULL; + m_swapChain = NULL; m_num = 0; for (uint32_t ii = 0; ii < _num; ++ii) @@ -2475,7 +2503,34 @@ namespace bgfx } } - void FrameBufferD3D11::destroy() + void FrameBufferD3D11::create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _depthFormat) + { + BX_UNUSED(_depthFormat); + + DXGI_SWAP_CHAIN_DESC scd; + memcpy(&scd, &s_renderD3D11->m_scd, sizeof(DXGI_SWAP_CHAIN_DESC) ); + scd.BufferDesc.Width = _width; + scd.BufferDesc.Height = _height; + scd.OutputWindow = (HWND)_nwh; + + HRESULT hr; + hr = s_renderD3D11->m_factory->CreateSwapChain(s_renderD3D11->m_device + , &scd + , &m_swapChain + ); + BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Failed to create swap chain."); + + ID3D11Resource* ptr; + DX_CHECK(m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&ptr) ); + DX_CHECK(s_renderD3D11->m_device->CreateRenderTargetView(ptr, NULL, &m_rtv[0]) ); + DX_RELEASE(ptr, 0); + m_srv[0] = NULL; + m_dsv = NULL; + m_denseIdx = _denseIdx; + m_num = 1; + } + + uint16_t FrameBufferD3D11::destroy() { for (uint32_t ii = 0, num = m_num; ii < num; ++ii) { @@ -2484,8 +2539,14 @@ namespace bgfx } DX_RELEASE(m_dsv, 0); + DX_RELEASE(m_swapChain, 0); m_num = 0; + + uint16_t denseIdx = m_denseIdx; + m_denseIdx = UINT16_MAX; + + return denseIdx; } void FrameBufferD3D11::resolve() diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index d6769f22..9d198b09 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -273,18 +273,22 @@ namespace bgfx struct FrameBufferD3D11 { FrameBufferD3D11() - : m_num(0) + : m_denseIdx(UINT16_MAX) + , m_num(0) { } void create(uint8_t _num, const TextureHandle* _handles); - void destroy(); + void create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _depthFormat); + uint16_t destroy(); void resolve(); void clear(const Clear& _clear, const float _palette[][4]); ID3D11RenderTargetView* m_rtv[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; ID3D11ShaderResourceView* m_srv[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; ID3D11DepthStencilView* m_dsv; + IDXGISwapChain* m_swapChain; + uint16_t m_denseIdx; uint8_t m_num; }; diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 929d0105..00aa45f0 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -259,8 +259,6 @@ namespace bgfx RendererContextD3D9() : m_d3d9(NULL) , m_device(NULL) - , m_backBufferColor(NULL) - , m_backBufferDepthStencil(NULL) , m_captureTexture(NULL) , m_captureSurface(NULL) , m_captureResolve(NULL) @@ -292,7 +290,7 @@ namespace bgfx m_params.FullScreen_RefreshRateInHz = 0; m_params.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; m_params.SwapEffect = D3DSWAPEFFECT_DISCARD; - m_params.hDeviceWindow = g_bgfxHwnd; + m_params.hDeviceWindow = NULL; m_params.Windowed = true; RECT rect; @@ -304,9 +302,9 @@ namespace bgfx BGFX_FATAL(NULL != m_d3d9dll, Fatal::UnableToInitialize, "Failed to load d3d9.dll."); #if BGFX_CONFIG_DEBUG_PIX - m_D3DPERF_SetMarker = (D3DPERF_SetMarkerFunc)bx::dlsym(m_d3d9dll, "D3DPERF_SetMarker"); + m_D3DPERF_SetMarker = (D3DPERF_SetMarkerFunc )bx::dlsym(m_d3d9dll, "D3DPERF_SetMarker"); m_D3DPERF_BeginEvent = (D3DPERF_BeginEventFunc)bx::dlsym(m_d3d9dll, "D3DPERF_BeginEvent"); - m_D3DPERF_EndEvent = (D3DPERF_EndEventFunc)bx::dlsym(m_d3d9dll, "D3DPERF_EndEvent"); + m_D3DPERF_EndEvent = (D3DPERF_EndEventFunc )bx::dlsym(m_d3d9dll, "D3DPERF_EndEvent"); BX_CHECK(NULL != m_D3DPERF_SetMarker && NULL != m_D3DPERF_BeginEvent @@ -373,9 +371,9 @@ namespace bgfx uint32_t behaviorFlags[] = { - D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_PUREDEVICE|D3DCREATE_FPU_PRESERVE, - D3DCREATE_MIXED_VERTEXPROCESSING|D3DCREATE_FPU_PRESERVE, - D3DCREATE_SOFTWARE_VERTEXPROCESSING|D3DCREATE_FPU_PRESERVE, + D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE | D3DCREATE_PUREDEVICE, + D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, + D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, }; for (uint32_t ii = 0; ii < BX_COUNTOF(behaviorFlags) && NULL == m_device; ++ii) @@ -402,6 +400,8 @@ namespace bgfx BGFX_FATAL(m_device, Fatal::UnableToInitialize, "Unable to create Direct3D9 device."); + m_numWindows = 1; + #if BGFX_CONFIG_RENDERER_DIRECT3D9EX if (NULL != m_d3d9ex) { @@ -711,9 +711,26 @@ namespace bgfx m_frameBuffers[_handle.idx].create(_num, _textureHandles); } + void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _depthFormat) BX_OVERRIDE + { + uint16_t denseIdx = m_numWindows++; + m_windows[denseIdx] = _handle; + m_frameBuffers[_handle.idx].create(denseIdx, _nwh, _width, _height, _depthFormat); + } + void destroyFrameBuffer(FrameBufferHandle _handle) BX_OVERRIDE { - m_frameBuffers[_handle.idx].destroy(); + uint16_t denseIdx = m_frameBuffers[_handle.idx].destroy(); + if (UINT16_MAX != denseIdx) + { + --m_numWindows; + if (m_numWindows > 1) + { + FrameBufferHandle handle = m_windows[m_numWindows]; + m_windows[denseIdx] = handle; + m_frameBuffers[handle.idx].m_denseIdx = denseIdx; + } + } } void createUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name) BX_OVERRIDE @@ -902,9 +919,9 @@ namespace bgfx void updateResolution(const Resolution& _resolution) { - if (m_params.BackBufferWidth != _resolution.m_width - || m_params.BackBufferHeight != _resolution.m_height - || m_flags != _resolution.m_flags) + if (m_params.BackBufferWidth != _resolution.m_width + || m_params.BackBufferHeight != _resolution.m_height + || m_flags != _resolution.m_flags) { m_flags = _resolution.m_flags; @@ -921,7 +938,7 @@ namespace bgfx m_params.BackBufferFormat = dm.Format; #endif // BX_PLATFORM_WINDOWS - m_params.BackBufferWidth = _resolution.m_width; + m_params.BackBufferWidth = _resolution.m_width; m_params.BackBufferHeight = _resolution.m_height; m_params.FullScreen_RefreshRateInHz = BGFX_RESET_FULLSCREEN == (m_flags&BGFX_RESET_FULLSCREEN_MASK) ? 60 : 0; m_params.PresentationInterval = !!(m_flags&BGFX_RESET_VSYNC) ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; @@ -929,7 +946,7 @@ namespace bgfx updateMsaa(); Msaa& msaa = s_msaa[(m_flags&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT]; - m_params.MultiSampleType = msaa.m_type; + m_params.MultiSampleType = msaa.m_type; m_params.MultiSampleQuality = msaa.m_quality; m_resolution = _resolution; @@ -1033,30 +1050,42 @@ namespace bgfx } #endif // BGFX_CONFIG_RENDERER_DIRECT3D9EX - HRESULT hr; - hr = m_device->Present(NULL, NULL, NULL, NULL); + for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii) + { + HRESULT hr; + if (0 == ii) + { + hr = m_swapChain->Present(NULL, NULL, g_bgfxHwnd, NULL, 0); + } + else + { + hr = m_frameBuffers[m_windows[ii].idx].present(); + } #if BX_PLATFORM_WINDOWS - if (isLost(hr) ) - { - do + if (isLost(hr) ) { - do + do { + do + { + hr = m_device->TestCooperativeLevel(); + } + while (D3DERR_DEVICENOTRESET != hr); + + reset(); hr = m_device->TestCooperativeLevel(); } - while (D3DERR_DEVICENOTRESET != hr); + while (FAILED(hr) ); - reset(); - hr = m_device->TestCooperativeLevel(); + break; + } + else if (FAILED(hr) ) + { + BX_TRACE("Present failed with err 0x%08x.", hr); } - while (FAILED(hr) ); - } - else if (FAILED(hr) ) - { - BX_TRACE("Present failed with err 0x%08x.", hr); - } #endif // BX_PLATFORM_ + } } } @@ -1082,6 +1111,7 @@ namespace bgfx DX_RELEASE(m_backBufferColor, 0); DX_RELEASE(m_backBufferDepthStencil, 0); + DX_RELEASE(m_swapChain, 0); capturePreReset(); @@ -1108,7 +1138,8 @@ namespace bgfx void postReset() { - DX_CHECK(m_device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_backBufferColor) ); + DX_CHECK(m_device->GetSwapChain(0, &m_swapChain) ); + DX_CHECK(m_swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &m_backBufferColor) ); DX_CHECK(m_device->GetDepthStencilSurface(&m_backBufferDepthStencil) ); capturePostReset(); @@ -1179,9 +1210,9 @@ namespace bgfx { if (m_flags&BGFX_RESET_CAPTURE) { - uint32_t width = m_params.BackBufferWidth; + uint32_t width = m_params.BackBufferWidth; uint32_t height = m_params.BackBufferHeight; - D3DFORMAT fmt = m_params.BackBufferFormat; + D3DFORMAT fmt = m_params.BackBufferFormat; DX_CHECK(m_device->CreateTexture(width , height @@ -1567,6 +1598,10 @@ namespace bgfx IDirect3DDevice9* m_device; D3DPOOL m_pool; + IDirect3DSwapChain9* m_swapChain; + uint16_t m_numWindows; + FrameBufferHandle m_windows[BGFX_CONFIG_MAX_FRAME_BUFFERS]; + IDirect3DSurface9* m_backBufferColor; IDirect3DSurface9* m_backBufferDepthStencil; @@ -2502,38 +2537,71 @@ namespace bgfx } } - void FrameBufferD3D9::destroy() + void FrameBufferD3D9::create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _depthFormat) { - for (uint32_t ii = 0, num = m_num; ii < num; ++ii) - { - m_colorHandle[ii].idx = invalidHandle; + BX_UNUSED(_width, _height, _depthFormat); - IDirect3DSurface9* ptr = m_color[ii]; - if (NULL != ptr) - { - ptr->Release(); - m_color[ii] = NULL; - } + m_hwnd = (HWND)_nwh; + DX_CHECK(s_renderD3D9->m_device->CreateAdditionalSwapChain(&s_renderD3D9->m_params, &m_swapChain) ); + DX_CHECK(m_swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &m_color[0]) ); + m_colorHandle[0].idx = invalidHandle; + m_depthStencil = NULL; + m_denseIdx = _denseIdx; + m_num = 1; + m_needResolve = false; + } + + uint16_t FrameBufferD3D9::destroy() + { + if (NULL != m_hwnd) + { + DX_RELEASE(m_color[0], 0); + DX_RELEASE(m_swapChain, 0); } - - if (NULL != m_depthStencil) + else { - if (0 == m_num) + for (uint32_t ii = 0, num = m_num; ii < num; ++ii) { - IDirect3DSurface9* ptr = m_color[0]; + m_colorHandle[ii].idx = invalidHandle; + + IDirect3DSurface9* ptr = m_color[ii]; if (NULL != ptr) { ptr->Release(); - m_color[0] = NULL; + m_color[ii] = NULL; } } - m_depthStencil->Release(); - m_depthStencil = NULL; + if (NULL != m_depthStencil) + { + if (0 == m_num) + { + IDirect3DSurface9* ptr = m_color[0]; + if (NULL != ptr) + { + ptr->Release(); + m_color[0] = NULL; + } + } + + m_depthStencil->Release(); + m_depthStencil = NULL; + } } + m_hwnd = NULL; m_num = 0; m_depthHandle.idx = invalidHandle; + + uint16_t denseIdx = m_denseIdx; + m_denseIdx = UINT16_MAX; + + return denseIdx; + } + + HRESULT FrameBufferD3D9::present() + { + return m_swapChain->Present(NULL, NULL, m_hwnd, NULL, 0); } void FrameBufferD3D9::resolve() const @@ -2556,57 +2624,78 @@ namespace bgfx void FrameBufferD3D9::preReset() { - for (uint32_t ii = 0, num = m_num; ii < num; ++ii) + if (NULL != m_hwnd) { - m_color[ii]->Release(); - m_color[ii] = NULL; + DX_RELEASE(m_color[0], 0); + DX_RELEASE(m_swapChain, 0); } - - if (isValid(m_depthHandle) ) + else { - if (0 == m_num) + for (uint32_t ii = 0, num = m_num; ii < num; ++ii) { - m_color[0]->Release(); - m_color[0] = NULL; + m_color[ii]->Release(); + m_color[ii] = NULL; } - m_depthStencil->Release(); - m_depthStencil = NULL; + if (isValid(m_depthHandle) ) + { + if (0 == m_num) + { + m_color[0]->Release(); + m_color[0] = NULL; + } + + m_depthStencil->Release(); + m_depthStencil = NULL; + } } } void FrameBufferD3D9::postReset() { - for (uint32_t ii = 0, num = m_num; ii < num; ++ii) + if (NULL != m_hwnd) { - TextureD3D9& texture = s_renderD3D9->m_textures[m_colorHandle[ii].idx]; - if (NULL != texture.m_surface) - { - m_color[ii] = texture.m_surface; - m_color[ii]->AddRef(); - } - else - { - DX_CHECK(texture.m_texture2d->GetSurfaceLevel(0, &m_color[ii]) ); - } + DX_CHECK(s_renderD3D9->m_device->CreateAdditionalSwapChain(&s_renderD3D9->m_params, &m_swapChain) ); + DX_CHECK(m_swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &m_color[0]) ); } - - if (isValid(m_depthHandle) ) + else { - TextureD3D9& texture = s_renderD3D9->m_textures[m_depthHandle.idx]; - if (NULL != texture.m_surface) + for (uint32_t ii = 0, num = m_num; ii < num; ++ii) { - m_depthStencil = texture.m_surface; - m_depthStencil->AddRef(); - } - else - { - DX_CHECK(texture.m_texture2d->GetSurfaceLevel(0, &m_depthStencil) ); + TextureHandle th = m_colorHandle[ii]; + + if (isValid(th) ) + { + TextureD3D9& texture = s_renderD3D9->m_textures[th.idx]; + if (NULL != texture.m_surface) + { + m_color[ii] = texture.m_surface; + m_color[ii]->AddRef(); + } + else + { + DX_CHECK(texture.m_texture2d->GetSurfaceLevel(0, &m_color[ii]) ); + } + } } - if (0 == m_num) + if (isValid(m_depthHandle) ) { - createNullColorRT(); + TextureD3D9& texture = s_renderD3D9->m_textures[m_depthHandle.idx]; + if (NULL != texture.m_surface) + { + m_depthStencil = texture.m_surface; + m_depthStencil->AddRef(); + } + else + { + DX_CHECK(texture.m_texture2d->GetSurfaceLevel(0, &m_depthStencil) ); + } + + if (0 == m_num) + { + createNullColorRT(); + } } } } diff --git a/src/renderer_d3d9.h b/src/renderer_d3d9.h index 6261e8f5..92816d17 100644 --- a/src/renderer_d3d9.h +++ b/src/renderer_d3d9.h @@ -353,14 +353,18 @@ namespace bgfx struct FrameBufferD3D9 { FrameBufferD3D9() - : m_num(0) + : m_hwnd(NULL) + , m_denseIdx(UINT16_MAX) + , m_num(0) , m_needResolve(0) { m_depthHandle.idx = invalidHandle; } void create(uint8_t _num, const TextureHandle* _handles); - void destroy(); + void create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _depthFormat); + uint16_t destroy(); + HRESULT present(); void resolve() const; void preReset(); void postReset(); @@ -368,8 +372,12 @@ namespace bgfx IDirect3DSurface9* m_color[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; IDirect3DSurface9* m_depthStencil; + IDirect3DSwapChain9* m_swapChain; + HWND m_hwnd; + TextureHandle m_colorHandle[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; TextureHandle m_depthHandle; + uint16_t m_denseIdx; uint8_t m_num; bool m_needResolve; }; diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index d7b53d0c..6c570b13 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -826,7 +826,8 @@ namespace bgfx struct RendererContextGL : public RendererContextI { RendererContextGL() - : m_rtMsaa(false) + : m_numWindows(1) + , m_rtMsaa(false) , m_capture(NULL) , m_captureSize(0) , m_maxAnisotropy(0.0f) @@ -1376,6 +1377,10 @@ namespace bgfx { if (m_flip) { + for (uint32_t ii = 1, num = m_numWindows; ii < num; ++ii) + { + m_glctx.swap(m_frameBuffers[m_windows[ii].idx].m_swapChain); + } m_glctx.swap(); } } @@ -1491,9 +1496,26 @@ namespace bgfx m_frameBuffers[_handle.idx].create(_num, _textureHandles); } + void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _depthFormat) BX_OVERRIDE + { + uint16_t denseIdx = m_numWindows++; + m_windows[denseIdx] = _handle; + m_frameBuffers[_handle.idx].create(denseIdx, _nwh, _width, _height, _depthFormat); + } + void destroyFrameBuffer(FrameBufferHandle _handle) BX_OVERRIDE { - m_frameBuffers[_handle.idx].destroy(); + uint16_t denseIdx = m_frameBuffers[_handle.idx].destroy(); + if (UINT16_MAX != denseIdx) + { + --m_numWindows; + if (m_numWindows > 1) + { + FrameBufferHandle handle = m_windows[m_numWindows]; + m_windows[denseIdx] = handle; + m_frameBuffers[handle.idx].m_denseIdx = denseIdx; + } + } } void createUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name) BX_OVERRIDE @@ -1655,6 +1677,8 @@ namespace bgfx frameBuffer.resolve(); } + m_glctx.makeCurrent(NULL); + if (!isValid(_fbh) ) { GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) ); @@ -1662,8 +1686,17 @@ namespace bgfx else { FrameBufferGL& frameBuffer = m_frameBuffers[_fbh.idx]; - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer.m_fbo[0]) ); - _height = frameBuffer.m_height; + if (UINT16_MAX != frameBuffer.m_denseIdx) + { + m_glctx.makeCurrent(frameBuffer.m_swapChain); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); + } + else + { + m_glctx.makeCurrent(NULL); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer.m_fbo[0]) ); + _height = frameBuffer.m_height; + } } m_fbh = _fbh; @@ -1764,8 +1797,7 @@ namespace bgfx #if BX_PLATFORM_IOS // iOS: need to figure out how to deal with FBO created by context. - m_backBufferFbo = m_glctx.m_fbo; - m_msaaBackBufferFbo = m_glctx.m_fbo; + m_backBufferFbo = m_msaaBackBufferFbo = m_glctx.getFbo() #endif // BX_PLATFORM_IOS } else @@ -2203,6 +2235,9 @@ namespace bgfx } } + uint16_t m_numWindows; + FrameBufferHandle m_windows[BGFX_CONFIG_MAX_FRAME_BUFFERS]; + IndexBufferGL m_indexBuffers[BGFX_CONFIG_MAX_INDEX_BUFFERS]; VertexBufferGL m_vertexBuffers[BGFX_CONFIG_MAX_VERTEX_BUFFERS]; ShaderGL m_shaders[BGFX_CONFIG_MAX_SHADERS]; @@ -3700,6 +3735,7 @@ namespace bgfx GL_CHECK(glGenFramebuffers(1, &m_fbo[0]) ); GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo[0]) ); +// m_denseIdx = UINT16_MAX; bool needResolve = false; GLenum buffers[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; @@ -3807,11 +3843,31 @@ namespace bgfx GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, s_renderGL->m_msaaBackBufferFbo) ); } - void FrameBufferGL::destroy() + void FrameBufferGL::create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _depthFormat) + { + BX_UNUSED(_depthFormat); + m_swapChain = s_renderGL->m_glctx.createSwapChain(_nwh); + m_width = _width; + m_height = _height; + m_denseIdx = _denseIdx; + } + + uint16_t FrameBufferGL::destroy() { GL_CHECK(glDeleteFramebuffers(0 == m_fbo[1] ? 1 : 2, m_fbo) ); memset(m_fbo, 0, sizeof(m_fbo) ); m_num = 0; + + if (NULL != m_swapChain) + { + s_renderGL->m_glctx.destorySwapChain(m_swapChain); + m_swapChain = NULL; + } + + uint16_t denseIdx = m_denseIdx; + m_denseIdx = UINT16_MAX; + + return denseIdx; } void FrameBufferGL::resolve() @@ -3840,6 +3896,8 @@ namespace bgfx void RendererContextGL::submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter) { + m_glctx.makeCurrent(NULL); + const GLuint defaultVao = s_renderGL->m_vao; if (0 != defaultVao) { @@ -4733,6 +4791,7 @@ namespace bgfx } } + m_glctx.makeCurrent(NULL); int64_t now = bx::getHPCounter(); elapsed += now; diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 9a712ce7..3ae71ef6 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -815,19 +815,24 @@ namespace bgfx struct FrameBufferGL { FrameBufferGL() - : m_num(0) + : m_swapChain(NULL) + , m_denseIdx(UINT16_MAX) + , m_num(0) { memset(m_fbo, 0, sizeof(m_fbo) ); } void create(uint8_t _num, const TextureHandle* _handles); - void destroy(); + void create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _depthFormat); + uint16_t destroy(); void resolve(); - uint8_t m_num; + SwapChainGL* m_swapChain; GLuint m_fbo[2]; uint32_t m_width; uint32_t m_height; + uint16_t m_denseIdx; + uint8_t m_num; }; struct ProgramGL diff --git a/src/renderer_null.cpp b/src/renderer_null.cpp index e784ae99..227de914 100644 --- a/src/renderer_null.cpp +++ b/src/renderer_null.cpp @@ -121,6 +121,10 @@ namespace bgfx { } + void createFrameBuffer(FrameBufferHandle /*_handle*/, void* /*_nwh*/, uint32_t /*_width*/, uint32_t /*_height*/, TextureFormat::Enum /*_depthFormat*/) BX_OVERRIDE + { + } + void destroyFrameBuffer(FrameBufferHandle /*_handle*/) BX_OVERRIDE { }