glcontext_eagl.mm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /*
  2. * Copyright 2011-2021 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #include "bgfx_p.h"
  6. #if BX_PLATFORM_IOS && (BGFX_CONFIG_RENDERER_OPENGLES|BGFX_CONFIG_RENDERER_OPENGL)
  7. # include <UIKit/UIKit.h>
  8. # include <QuartzCore/CAEAGLLayer.h>
  9. # include "renderer_gl.h"
  10. namespace bgfx { namespace gl
  11. {
  12. # define GL_IMPORT(_optional, _proto, _func, _import) _proto _func = NULL
  13. # include "glimports.h"
  14. static void* s_opengles = NULL;
  15. struct SwapChainGL
  16. {
  17. SwapChainGL(EAGLContext *_context, CAEAGLLayer *_layer)
  18. : m_context(_context)
  19. , m_fbo(0)
  20. , m_colorRbo(0)
  21. , m_depthStencilRbo(0)
  22. {
  23. _layer.contentsScale = [UIScreen mainScreen].scale;
  24. _layer.opaque = [_layer.style valueForKey:@"opaque"] == nil
  25. ? true
  26. : [[_layer.style valueForKey:@"opaque"] boolValue]
  27. ;
  28. _layer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys
  29. : [NSNumber numberWithBool:false]
  30. , kEAGLDrawablePropertyRetainedBacking
  31. , kEAGLColorFormatRGBA8
  32. , kEAGLDrawablePropertyColorFormat
  33. , nil
  34. ];
  35. [EAGLContext setCurrentContext:_context];
  36. GL_CHECK(glGenFramebuffers(1, &m_fbo) );
  37. GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo) );
  38. GL_CHECK(glGenRenderbuffers(1, &m_colorRbo) );
  39. GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_colorRbo) );
  40. [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_layer];
  41. GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorRbo) );
  42. GLint width;
  43. GLint height;
  44. GL_CHECK(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width) );
  45. GL_CHECK(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height) );
  46. BX_TRACE("Screen size: %d x %d", width, height);
  47. m_width = width;
  48. m_height = height;
  49. m_layer = _layer;
  50. createFrameBuffers(m_width, m_height);
  51. }
  52. ~SwapChainGL()
  53. {
  54. destroyFrameBuffers();
  55. }
  56. void destroyFrameBuffers()
  57. {
  58. GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) );
  59. GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, 0) );
  60. GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, 0) );
  61. if (0 != m_fbo)
  62. {
  63. GL_CHECK(glDeleteFramebuffers(1, &m_fbo) );
  64. m_fbo = 0;
  65. }
  66. if (0 != m_colorRbo)
  67. {
  68. GL_CHECK(glDeleteRenderbuffers(1, &m_colorRbo) );
  69. m_colorRbo = 0;
  70. }
  71. if (0 != m_depthStencilRbo)
  72. {
  73. GL_CHECK(glDeleteRenderbuffers(1, &m_depthStencilRbo) );
  74. m_depthStencilRbo = 0;
  75. }
  76. }
  77. void createFrameBuffers(GLint _width, GLint _height)
  78. {
  79. GL_CHECK(glGenRenderbuffers(1, &m_depthStencilRbo) );
  80. GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilRbo) );
  81. GL_CHECK(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, _width, _height) );
  82. GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilRbo) );
  83. GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilRbo) );
  84. GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  85. BX_ASSERT(GL_FRAMEBUFFER_COMPLETE == err, "glCheckFramebufferStatus failed 0x%08x", err);
  86. BX_UNUSED(err);
  87. makeCurrent();
  88. GL_CHECK(glClearColor(0.0f, 0.0f, 0.0f, 0.0f) );
  89. GL_CHECK(glClear(GL_COLOR_BUFFER_BIT) );
  90. swapBuffers();
  91. GL_CHECK(glClear(GL_COLOR_BUFFER_BIT) );
  92. swapBuffers();
  93. }
  94. void makeCurrent()
  95. {
  96. [EAGLContext setCurrentContext:m_context];
  97. GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo) );
  98. GLint newWidth = m_layer.bounds.size.width*[UIScreen mainScreen].scale;
  99. GLint newHeight = m_layer.bounds.size.height*[UIScreen mainScreen].scale;
  100. resize(newWidth, newHeight);
  101. }
  102. void resize(GLint _width, GLint _height)
  103. {
  104. if (m_width == _width
  105. && m_height == _height)
  106. {
  107. return;
  108. }
  109. destroyFrameBuffers();
  110. m_width = _width;
  111. m_height = _height;
  112. createFrameBuffers(m_width, m_height);
  113. }
  114. void swapBuffers()
  115. {
  116. GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_colorRbo) );
  117. [m_context presentRenderbuffer:GL_RENDERBUFFER];
  118. }
  119. EAGLContext* m_context;
  120. CAEAGLLayer *m_layer;
  121. GLuint m_fbo;
  122. GLuint m_colorRbo;
  123. GLuint m_depthStencilRbo;
  124. GLint m_width;
  125. GLint m_height;
  126. };
  127. void GlContext::create(uint32_t _width, uint32_t _height)
  128. {
  129. s_opengles = bx::dlopen("/System/Library/Frameworks/OpenGLES.framework/OpenGLES");
  130. BX_ASSERT(NULL != s_opengles, "OpenGLES dynamic library is not found!");
  131. BX_UNUSED(_width, _height);
  132. CAEAGLLayer* layer = (__bridge CAEAGLLayer*)g_platformData.nwh;
  133. layer.opaque = [layer.style valueForKey:@"opaque"] == nil ? true : [[layer.style valueForKey:@"opaque"] boolValue];
  134. layer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys
  135. : [NSNumber numberWithBool:false]
  136. , kEAGLDrawablePropertyRetainedBacking
  137. , kEAGLColorFormatRGBA8
  138. , kEAGLDrawablePropertyColorFormat
  139. , nil
  140. ];
  141. EAGLContext* context = (__bridge EAGLContext*)g_platformData.context;
  142. if (NULL == context)
  143. {
  144. context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
  145. if (NULL == context)
  146. {
  147. context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
  148. }
  149. }
  150. BX_ASSERT(NULL != context, "No valid OpenGLES context.");
  151. m_context = (__bridge void*)context;
  152. [EAGLContext setCurrentContext:context];
  153. [CATransaction flush];
  154. GL_CHECK(glGenFramebuffers(1, &m_fbo) );
  155. GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo) );
  156. GL_CHECK(glGenRenderbuffers(1, &m_colorRbo) );
  157. GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_colorRbo) );
  158. [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer];
  159. GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorRbo) );
  160. GLint width;
  161. GLint height;
  162. GL_CHECK(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width) );
  163. GL_CHECK(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height) );
  164. BX_TRACE("Screen size: %d x %d", width, height);
  165. GL_CHECK(glGenRenderbuffers(1, &m_depthStencilRbo) );
  166. GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilRbo) );
  167. GL_CHECK(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height) );
  168. GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilRbo) );
  169. GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilRbo) );
  170. BX_ASSERT(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER)
  171. , "glCheckFramebufferStatus failed 0x%08x"
  172. , glCheckFramebufferStatus(GL_FRAMEBUFFER)
  173. );
  174. makeCurrent();
  175. GL_CHECK(glClearColor(0.0f, 0.0f, 0.0f, 0.0f) );
  176. GL_CHECK(glClear(GL_COLOR_BUFFER_BIT) );
  177. swap(NULL);
  178. GL_CHECK(glClear(GL_COLOR_BUFFER_BIT) );
  179. swap(NULL);
  180. import();
  181. g_internalData.context = m_context;
  182. }
  183. void GlContext::destroy()
  184. {
  185. if (0 != m_fbo)
  186. {
  187. GL_CHECK(glDeleteFramebuffers(1, &m_fbo) );
  188. m_fbo = 0;
  189. }
  190. if (0 != m_colorRbo)
  191. {
  192. GL_CHECK(glDeleteRenderbuffers(1, &m_colorRbo) );
  193. m_colorRbo = 0;
  194. }
  195. if (0 != m_depthStencilRbo)
  196. {
  197. GL_CHECK(glDeleteRenderbuffers(1, &m_depthStencilRbo) );
  198. m_depthStencilRbo = 0;
  199. }
  200. EAGLContext* context = (__bridge EAGLContext*)m_context;
  201. bx::dlclose(s_opengles);
  202. }
  203. void GlContext::resize(uint32_t _width, uint32_t _height, uint32_t _flags)
  204. {
  205. BX_UNUSED(_width, _height, _flags);
  206. BX_TRACE("resize context");
  207. if (0 != m_fbo)
  208. {
  209. GL_CHECK(glDeleteFramebuffers(1, &m_fbo) );
  210. m_fbo = 0;
  211. }
  212. if (0 != m_colorRbo)
  213. {
  214. GL_CHECK(glDeleteRenderbuffers(1, &m_colorRbo) );
  215. m_colorRbo = 0;
  216. }
  217. if (0 != m_depthStencilRbo)
  218. {
  219. GL_CHECK(glDeleteRenderbuffers(1, &m_depthStencilRbo) );
  220. m_depthStencilRbo = 0;
  221. }
  222. GL_CHECK(glGenFramebuffers(1, &m_fbo) );
  223. GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo) );
  224. GL_CHECK(glGenRenderbuffers(1, &m_colorRbo) );
  225. GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_colorRbo) );
  226. [((__bridge EAGLContext*)m_context) renderbufferStorage:GL_RENDERBUFFER fromDrawable:(__bridge CAEAGLLayer*)g_platformData.nwh];
  227. GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorRbo) );
  228. GLint width;
  229. GLint height;
  230. GL_CHECK(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width) );
  231. GL_CHECK(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height) );
  232. BX_TRACE("Screen size: %d x %d", width, height);
  233. GL_CHECK(glGenRenderbuffers(1, &m_depthStencilRbo) );
  234. GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilRbo) );
  235. GL_CHECK(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height) );
  236. GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilRbo) );
  237. GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilRbo) );
  238. BX_ASSERT(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER)
  239. , "glCheckFramebufferStatus failed 0x%08x"
  240. , glCheckFramebufferStatus(GL_FRAMEBUFFER)
  241. );
  242. }
  243. uint64_t GlContext::getCaps() const
  244. {
  245. return BGFX_CAPS_SWAP_CHAIN;
  246. }
  247. SwapChainGL* GlContext::createSwapChain(void* _nwh)
  248. {
  249. return BX_NEW(g_allocator, SwapChainGL)(/*m_display, m_config,*/ (__bridge EAGLContext*)m_context, (__bridge CAEAGLLayer*)_nwh);
  250. }
  251. void GlContext::destroySwapChain(SwapChainGL* _swapChain)
  252. {
  253. BX_DELETE(g_allocator, _swapChain);
  254. }
  255. void GlContext::swap(SwapChainGL* _swapChain)
  256. {
  257. makeCurrent(_swapChain);
  258. if (NULL == _swapChain)
  259. {
  260. GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_colorRbo) );
  261. EAGLContext* context = (__bridge EAGLContext*)m_context;
  262. [context presentRenderbuffer:GL_RENDERBUFFER];
  263. }
  264. else
  265. {
  266. _swapChain->swapBuffers();
  267. }
  268. }
  269. void GlContext::makeCurrent(SwapChainGL* _swapChain)
  270. {
  271. if (m_current != _swapChain)
  272. {
  273. m_current = _swapChain;
  274. if (NULL == _swapChain)
  275. {
  276. [EAGLContext setCurrentContext:(__bridge EAGLContext*)m_context];
  277. GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo) );
  278. }
  279. else
  280. {
  281. _swapChain->makeCurrent();
  282. }
  283. }
  284. }
  285. void GlContext::import()
  286. {
  287. BX_TRACE("Import:");
  288. # define GL_EXTENSION(_optional, _proto, _func, _import) \
  289. { \
  290. if (_func == NULL) \
  291. { \
  292. _func = (_proto)bx::dlsym(s_opengles, #_import); \
  293. BX_TRACE("%p " #_func " (" #_import ")", _func); \
  294. } \
  295. BGFX_FATAL(_optional || NULL != _func, Fatal::UnableToInitialize \
  296. , "Failed to create OpenGLES context. EAGLGetProcAddress(\"%s\")" \
  297. , #_import); \
  298. }
  299. # include "glimports.h"
  300. }
  301. } /* namespace gl */ } // namespace bgfx
  302. #endif // BX_PLATFORM_IOS && (BGFX_CONFIG_RENDERER_OPENGLES|BGFX_CONFIG_RENDERER_OPENGL)