OpenGLContext.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #include "pch.h"
  2. #if SUPPORT_OPENGL_ES
  3. #include <EGL/egl.h>
  4. #endif
  5. #include "OpenGLContext.h"
  6. namespace unity
  7. {
  8. namespace webrtc
  9. {
  10. #if SUPPORT_OPENGL_ES
  11. class EGLContextImpl : public OpenGLContext
  12. {
  13. public:
  14. EGLContextImpl(EGLContext sharedCtx = 0)
  15. : created_(false)
  16. {
  17. RTC_DCHECK(display);
  18. // Return if the context is already created.
  19. context_ = eglGetCurrentContext();
  20. if(context_ != nullptr)
  21. return;
  22. int count = 0;
  23. if(!eglGetConfigs(display, 0, 0, &count))
  24. {
  25. RTC_LOG(LS_ERROR) << "eglGetConfigs failed:" << eglGetError();
  26. throw;
  27. }
  28. std::vector<EGLConfig> configs(count);
  29. eglGetConfigs(display, configs.data(), count, &count);
  30. EGLint contextAttr[] =
  31. {
  32. EGL_CONTEXT_CLIENT_VERSION, 2,
  33. EGL_NONE
  34. };
  35. context_ = eglCreateContext(display, configs[0], sharedCtx, contextAttr);
  36. RTC_DCHECK(context_);
  37. if(!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context_))
  38. {
  39. RTC_LOG(LS_ERROR) << "eglMakeCurrent failed:" << eglGetError();
  40. throw;
  41. }
  42. created_ = true;
  43. }
  44. ~EGLContextImpl()
  45. {
  46. if(created_)
  47. {
  48. eglDestroySurface(display, surface_);
  49. eglDestroyContext(display, context_);
  50. }
  51. }
  52. EGLContext context() const { return context_; }
  53. static EGLDisplay display;
  54. private:
  55. EGLContext context_;
  56. EGLSurface surface_;
  57. // In Unity, this flag is false because the context already created which rely on the render thread.
  58. bool created_;
  59. };
  60. EGLDisplay EGLContextImpl::display;
  61. #endif
  62. #if SUPPORT_OPENGL_CORE && UNITY_LINUX
  63. class GLXContextImpl : public OpenGLContext
  64. {
  65. public:
  66. GLXContextImpl(GLXContext sharedCtx = 0)
  67. : created_(false)
  68. {
  69. RTC_DCHECK(display);
  70. // Return if the context is already created.
  71. context_ = glXGetCurrentContext();
  72. if(context_ != nullptr)
  73. return;
  74. static int dblBuf[] =
  75. {
  76. GLX_RGBA,
  77. GLX_DEPTH_SIZE, 16,
  78. GLX_DOUBLEBUFFER,
  79. None
  80. };
  81. XVisualInfo *vi = glXChooseVisual(display, DefaultScreen(display), dblBuf);
  82. context_ = glXCreateContext(display, vi, sharedCtx, GL_TRUE);
  83. RTC_DCHECK(context_);
  84. XFree(vi);
  85. const int visualAttrs[] = { None };
  86. const int attrs[] = {
  87. GLX_PBUFFER_WIDTH, 1,
  88. GLX_PBUFFER_HEIGHT, 1,
  89. None
  90. };
  91. int returnedElements;
  92. GLXFBConfig* configs = glXChooseFBConfig(display, 0, visualAttrs, &returnedElements);
  93. pbuffer_ = glXCreatePbuffer(display, configs[0], attrs);
  94. RTC_DCHECK(pbuffer_);
  95. if(!glXMakeContextCurrent(display, pbuffer_, pbuffer_, context_))
  96. {
  97. RTC_LOG(LS_ERROR) << "glXMakeContextCurrent failed";
  98. throw;
  99. }
  100. XFree(configs);
  101. configs = nullptr;
  102. created_ = true;
  103. }
  104. ~GLXContextImpl()
  105. {
  106. glXDestroyPbuffer(display, pbuffer_);
  107. glXDestroyContext(display, context_);
  108. }
  109. GLXContext context() const { return context_; }
  110. static Display* display;
  111. private:
  112. GLXPbuffer pbuffer_;
  113. GLXContext context_;
  114. // In Unity, this flag is false because the context already created which rely on the render thread.
  115. bool created_;
  116. };
  117. Display* GLXContextImpl::display;
  118. #endif
  119. void OpenGLContext::Init()
  120. {
  121. #if SUPPORT_OPENGL_ES
  122. EGLContextImpl::display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  123. RTC_DCHECK(EGLContextImpl::display);
  124. EGLint major, minor;
  125. if(!eglInitialize(EGLContextImpl::display, &major, &minor))
  126. {
  127. RTC_LOG(LS_ERROR) << "eglInitialize failed:" << eglGetError();
  128. throw;
  129. }
  130. #elif SUPPORT_OPENGL_CORE && UNITY_LINUX
  131. int version = gladLoaderLoadGL();
  132. RTC_DCHECK(version);
  133. Display *display = XOpenDisplay(nullptr);
  134. RTC_DCHECK(display);
  135. int screen = DefaultScreen(display);
  136. int result = gladLoaderLoadGLX(display, screen);
  137. RTC_DCHECK(result);
  138. GLXContextImpl::display = display;
  139. #endif
  140. }
  141. std::unique_ptr<OpenGLContext> OpenGLContext::CurrentContext()
  142. {
  143. #if SUPPORT_OPENGL_ES
  144. if(eglGetCurrentContext())
  145. return CreateGLContext();
  146. return nullptr;
  147. #endif
  148. #if SUPPORT_OPENGL_CORE && UNITY_LINUX
  149. if(glXGetCurrentContext())
  150. return CreateGLContext();
  151. return nullptr;
  152. #endif
  153. }
  154. std::unique_ptr<OpenGLContext> OpenGLContext::CreateGLContext(const OpenGLContext* shared)
  155. {
  156. #if SUPPORT_OPENGL_ES
  157. const EGLContextImpl* context = static_cast<const EGLContextImpl*>(shared);
  158. EGLContext eglContext = context ? context->context() : nullptr;
  159. return std::make_unique<EGLContextImpl>(eglContext);
  160. #endif
  161. #if SUPPORT_OPENGL_CORE && UNITY_LINUX
  162. const GLXContextImpl* context = static_cast<const GLXContextImpl*>(shared);
  163. GLXContext glxContext = context ? context->context() : nullptr;
  164. return std::make_unique<GLXContextImpl>(glxContext);
  165. #endif
  166. }
  167. }
  168. }