Jelajahi Sumber

Merge pull request #719 from pacemakermusic/master

iOS SwapChain support
Branimir Karadžić 9 tahun lalu
induk
melakukan
61295e1d62
3 mengubah file dengan 179 tambahan dan 14 penghapusan
  1. 6 2
      src/glcontext_eagl.h
  2. 173 11
      src/glcontext_eagl.mm
  3. 0 1
      src/renderer_gl.cpp

+ 6 - 2
src/glcontext_eagl.h

@@ -15,7 +15,11 @@ namespace bgfx { namespace gl
 	struct GlContext
 	struct GlContext
 	{
 	{
 		GlContext()
 		GlContext()
-			: m_context(0)
+			: m_current(0)
+			, m_context(0)
+			, m_fbo(0)
+			, m_colorRbo(0)
+			, m_depthStencilRbo(0)
 		{
 		{
 		}
 		}
 
 
@@ -41,7 +45,7 @@ namespace bgfx { namespace gl
 			return 0 != m_context;
 			return 0 != m_context;
 		}
 		}
 
 
-		void* m_view;
+		SwapChainGL* m_current;
 		void* m_context;
 		void* m_context;
 
 
 		GLuint m_fbo;
 		GLuint m_fbo;

+ 173 - 11
src/glcontext_eagl.mm

@@ -17,6 +17,140 @@ namespace bgfx { namespace gl
 
 
 	static void* s_opengles = NULL;
 	static void* s_opengles = NULL;
 
 
+	struct SwapChainGL
+	{
+		SwapChainGL(EAGLContext *_context, CAEAGLLayer *_layer)
+		: m_context(_context)
+		, m_fbo(0)
+		, m_colorRbo(0)
+		, m_depthStencilRbo(0)
+		{
+			_layer.contentsScale = [UIScreen mainScreen].scale;
+
+			_layer.opaque = true;
+
+			_layer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys
+											: [NSNumber numberWithBool:false]
+											, kEAGLDrawablePropertyRetainedBacking
+											, kEAGLColorFormatRGBA8
+											, kEAGLDrawablePropertyColorFormat
+											, nil];
+
+			[EAGLContext setCurrentContext:_context];
+
+			GL_CHECK(glGenFramebuffers(1, &m_fbo) );
+			GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo) );
+
+			GL_CHECK(glGenRenderbuffers(1, &m_colorRbo) );
+			GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_colorRbo) );
+
+			[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_layer];
+			GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorRbo) );
+
+			GLint width;
+			GLint height;
+			GL_CHECK(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width) );
+			GL_CHECK(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height) );
+			BX_TRACE("Screen size: %d x %d", width, height);
+
+			m_width = width;
+			m_height = height;
+			m_layer = _layer;
+
+			createFrameBuffers(m_width, m_height);
+		}
+
+		~SwapChainGL()
+		{
+			destroyFrameBuffers();
+		}
+
+		void destroyFrameBuffers()
+		{
+			GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) );
+			GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, 0) );
+			GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, 0) );
+			if (0 != m_fbo)
+			{
+			    GL_CHECK(glDeleteFramebuffers(1, &m_fbo) );
+			    m_fbo = 0;
+			}
+
+			if (0 != m_colorRbo)
+			{
+			    GL_CHECK(glDeleteRenderbuffers(1, &m_colorRbo) );
+			    m_colorRbo = 0;
+			}
+
+			if (0 != m_depthStencilRbo)
+			{
+			    GL_CHECK(glDeleteRenderbuffers(1, &m_depthStencilRbo) );
+			    m_depthStencilRbo = 0;
+			}
+		}
+
+		void createFrameBuffers(GLint _width, GLint _height)
+		{
+			GL_CHECK(glGenRenderbuffers(1, &m_depthStencilRbo) );
+			GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilRbo) );
+			GL_CHECK(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, _width, _height) ); // from OES_packed_depth_stencil
+			GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilRbo) );
+			GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilRbo) );
+
+			BX_CHECK(GL_FRAMEBUFFER_COMPLETE ==  glCheckFramebufferStatus(GL_FRAMEBUFFER)
+						, "glCheckFramebufferStatus failed 0x%08x"
+						, glCheckFramebufferStatus(GL_FRAMEBUFFER)
+						);
+
+			makeCurrent();
+			GL_CHECK(glClearColor(0.0f, 0.0f, 0.0f, 0.0f) );
+			GL_CHECK(glClear(GL_COLOR_BUFFER_BIT) );
+			swapBuffers();
+			GL_CHECK(glClear(GL_COLOR_BUFFER_BIT) );
+			swapBuffers();
+		}
+
+		void makeCurrent()
+		{
+			[EAGLContext setCurrentContext:m_context];
+			GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo) );
+
+			GLint newWidth = m_layer.bounds.size.width*[UIScreen mainScreen].scale;
+			GLint newHeight = m_layer.bounds.size.height*[UIScreen mainScreen].scale;
+			resize(newWidth, newHeight);
+		}
+
+		void resize(GLint _width, GLint _height)
+		{
+			if(m_width == _width && m_height == _height)
+			{
+				return;
+			}
+
+			destroyFrameBuffers();
+
+			m_width = _width;
+			m_height = _height;
+
+			createFrameBuffers(m_width, m_height);
+		}
+
+		void swapBuffers()
+		{
+			GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_colorRbo) );
+			[m_context presentRenderbuffer:GL_RENDERBUFFER];
+		}
+
+		EAGLContext* m_context;
+
+		CAEAGLLayer *m_layer;
+		GLuint m_fbo;
+		GLuint m_colorRbo;
+		GLuint m_depthStencilRbo;
+		GLint m_width;
+		GLint m_height;
+	};
+
 	void GlContext::create(uint32_t _width, uint32_t _height)
 	void GlContext::create(uint32_t _width, uint32_t _height)
 	{
 	{
 		s_opengles = bx::dlopen("/System/Library/Frameworks/OpenGLES.framework/OpenGLES");
 		s_opengles = bx::dlopen("/System/Library/Frameworks/OpenGLES.framework/OpenGLES");
@@ -65,6 +199,13 @@ namespace bgfx { namespace gl
 			, glCheckFramebufferStatus(GL_FRAMEBUFFER)
 			, glCheckFramebufferStatus(GL_FRAMEBUFFER)
 			);
 			);
 
 
+		makeCurrent();
+		GL_CHECK(glClearColor(0.0f, 0.0f, 0.0f, 0.0f) );
+		GL_CHECK(glClear(GL_COLOR_BUFFER_BIT) );
+		swap(NULL);
+		GL_CHECK(glClear(GL_COLOR_BUFFER_BIT) );
+		swap(NULL);
+
 		import();
 		import();
 
 
 		g_internalData.context = m_context;
 		g_internalData.context = m_context;
@@ -148,30 +289,51 @@ namespace bgfx { namespace gl
 
 
 	uint64_t GlContext::getCaps() const
 	uint64_t GlContext::getCaps() const
 	{
 	{
-		return 0;
+		return BGFX_CAPS_SWAP_CHAIN;
 	}
 	}
 
 
-	SwapChainGL* GlContext::createSwapChain(void* /*_nwh*/)
+	SwapChainGL* GlContext::createSwapChain(void* _nwh)
 	{
 	{
-		BX_CHECK(false, "Shouldn't be called!");
-		return NULL;
+		return BX_NEW(g_allocator, SwapChainGL)(/*m_display, m_config,*/ (EAGLContext*)m_context, (CAEAGLLayer*)_nwh);
 	}
 	}
 
 
-	void GlContext::destroySwapChain(SwapChainGL*  /*_swapChain*/)
+	void GlContext::destroySwapChain(SwapChainGL* _swapChain)
 	{
 	{
-		BX_CHECK(false, "Shouldn't be called!");
+		BX_DELETE(g_allocator, _swapChain);
 	}
 	}
 
 
 	void GlContext::swap(SwapChainGL* _swapChain)
 	void GlContext::swap(SwapChainGL* _swapChain)
 	{
 	{
-		BX_CHECK(NULL == _swapChain, "Shouldn't be called!"); BX_UNUSED(_swapChain);
-		GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_colorRbo) );
-		EAGLContext* context = (EAGLContext*)m_context;
-		[context presentRenderbuffer:GL_RENDERBUFFER];
+		makeCurrent(_swapChain);
+
+		if (NULL == _swapChain)
+		{
+			GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_colorRbo) );
+			EAGLContext* context = (EAGLContext*)m_context;
+			[context presentRenderbuffer:GL_RENDERBUFFER];
+		}
+		else
+		{
+		    _swapChain->swapBuffers();
+		}
 	}
 	}
 
 
-	void GlContext::makeCurrent(SwapChainGL* /*_swapChain*/)
+	void GlContext::makeCurrent(SwapChainGL* _swapChain)
 	{
 	{
+		if (m_current != _swapChain)
+		{
+			m_current = _swapChain;
+
+			if (NULL == _swapChain)
+			{
+				[EAGLContext setCurrentContext:(EAGLContext*)m_context];
+				GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo) );
+			}
+			else
+			{
+				_swapChain->makeCurrent();
+			}
+		}
 	}
 	}
 
 
 	void GlContext::import()
 	void GlContext::import()

+ 0 - 1
src/renderer_gl.cpp

@@ -2565,7 +2565,6 @@ namespace bgfx { namespace gl
 				if (UINT16_MAX != frameBuffer.m_denseIdx)
 				if (UINT16_MAX != frameBuffer.m_denseIdx)
 				{
 				{
 					m_glctx.makeCurrent(frameBuffer.m_swapChain);
 					m_glctx.makeCurrent(frameBuffer.m_swapChain);
-					GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) );
 				}
 				}
 				else
 				else
 				{
 				{