ijksdl_egl.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*
  2. * Copyright (c) 2016 Bilibili
  3. * copyright (c) 2016 Zhang Rui <bbcallen@gmail.com>
  4. *
  5. * This file is part of ijkPlayer.
  6. *
  7. * ijkPlayer is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * ijkPlayer is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with ijkPlayer; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #ifndef __APPLE__
  22. #include "ijksdl_egl.h"
  23. #include <stdlib.h>
  24. #include <stdbool.h>
  25. #include "ijksdl/ijksdl_gles2.h"
  26. #include "ijksdl/ijksdl_log.h"
  27. #include "ijksdl/ijksdl_vout.h"
  28. #include "ijksdl/gles2/internal.h"
  29. #define IJK_EGL_RENDER_BUFFER 0
  30. typedef struct IJK_EGL_Opaque {
  31. IJK_GLES2_Renderer *renderer;
  32. } IJK_EGL_Opaque;
  33. static EGLBoolean IJK_EGL_isValid(IJK_EGL* egl)
  34. {
  35. if (egl &&
  36. egl->window &&
  37. egl->display &&
  38. egl->surface &&
  39. egl->context) {
  40. return EGL_TRUE;
  41. }
  42. return EGL_FALSE;
  43. }
  44. void IJK_EGL_terminate(IJK_EGL* egl)
  45. {
  46. if (!IJK_EGL_isValid(egl))
  47. return;
  48. if (egl->opaque)
  49. IJK_GLES2_Renderer_freeP(&egl->opaque->renderer);
  50. if (egl->display) {
  51. eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  52. if (egl->context)
  53. eglDestroyContext(egl->display, egl->context);
  54. if (egl->surface)
  55. eglDestroySurface(egl->display, egl->surface);
  56. eglTerminate(egl->display);
  57. eglReleaseThread(); // FIXME: call at thread exit
  58. }
  59. egl->context = EGL_NO_CONTEXT;
  60. egl->surface = EGL_NO_SURFACE;
  61. egl->display = EGL_NO_DISPLAY;
  62. }
  63. static int IJK_EGL_getSurfaceWidth(IJK_EGL* egl)
  64. {
  65. EGLint width = 0;
  66. if (!eglQuerySurface(egl->display, egl->surface, EGL_WIDTH, &width)) {
  67. ALOGE("[EGL] eglQuerySurface(EGL_WIDTH) returned error %d", eglGetError());
  68. return 0;
  69. }
  70. return width;
  71. }
  72. static int IJK_EGL_getSurfaceHeight(IJK_EGL* egl)
  73. {
  74. EGLint height = 0;
  75. if (!eglQuerySurface(egl->display, egl->surface, EGL_HEIGHT, &height)) {
  76. ALOGE("[EGL] eglQuerySurface(EGL_HEIGHT) returned error %d", eglGetError());
  77. return 0;
  78. }
  79. return height;
  80. }
  81. static EGLBoolean IJK_EGL_setSurfaceSize(IJK_EGL* egl, int width, int height)
  82. {
  83. if (!IJK_EGL_isValid(egl))
  84. return EGL_FALSE;
  85. #ifdef __ANDROID__
  86. egl->width = IJK_EGL_getSurfaceWidth(egl);
  87. egl->height = IJK_EGL_getSurfaceHeight(egl);
  88. if (width != egl->width || height != egl->height) {
  89. int format = ANativeWindow_getFormat(egl->window);
  90. ALOGI("ANativeWindow_setBuffersGeometry(w=%d,h=%d) -> (w=%d,h=%d);",
  91. egl->width, egl->height,
  92. width, height);
  93. int ret = ANativeWindow_setBuffersGeometry(egl->window, width, height, format);
  94. if (ret) {
  95. ALOGE("[EGL] ANativeWindow_setBuffersGeometry() returned error %d", ret);
  96. return EGL_FALSE;
  97. }
  98. egl->width = IJK_EGL_getSurfaceWidth(egl);
  99. egl->height = IJK_EGL_getSurfaceHeight(egl);
  100. return (egl->width && egl->height) ? EGL_TRUE : EGL_FALSE;
  101. }
  102. return EGL_TRUE;
  103. #else
  104. // FIXME: other platform?
  105. #endif
  106. return EGL_FALSE;
  107. }
  108. static EGLBoolean IJK_EGL_makeCurrent(IJK_EGL* egl, EGLNativeWindowType window)
  109. {
  110. if (window && window == egl->window &&
  111. egl->display &&
  112. egl->surface &&
  113. egl->context) {
  114. if (!eglMakeCurrent(egl->display, egl->surface, egl->surface, egl->context)) {
  115. ALOGE("[EGL] elgMakeCurrent() failed (cached)\n");
  116. return EGL_FALSE;
  117. }
  118. return EGL_TRUE;
  119. }
  120. IJK_EGL_terminate(egl);
  121. egl->window = window;
  122. if (!window)
  123. return EGL_FALSE;
  124. EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  125. if (display == EGL_NO_DISPLAY) {
  126. ALOGE("[EGL] eglGetDisplay failed\n");
  127. return EGL_FALSE;
  128. }
  129. EGLint major, minor;
  130. if (!eglInitialize(display, &major, &minor)) {
  131. ALOGE("[EGL] eglInitialize failed\n");
  132. return EGL_FALSE;
  133. }
  134. ALOGI("[EGL] eglInitialize %d.%d\n", (int)major, (int)minor);
  135. static const EGLint configAttribs[] = {
  136. EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
  137. EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
  138. EGL_BLUE_SIZE, 8,
  139. EGL_GREEN_SIZE, 8,
  140. EGL_RED_SIZE, 8,
  141. EGL_NONE
  142. };
  143. static const EGLint contextAttribs[] = {
  144. EGL_CONTEXT_CLIENT_VERSION, 2,
  145. EGL_NONE
  146. };
  147. EGLConfig config;
  148. EGLint numConfig;
  149. if (!eglChooseConfig(display, configAttribs, &config, 1, &numConfig)) {
  150. ALOGE("[EGL] eglChooseConfig failed\n");
  151. eglTerminate(display);
  152. return EGL_FALSE;
  153. }
  154. #ifdef __ANDROID__
  155. {
  156. EGLint native_visual_id = 0;
  157. if (!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &native_visual_id)) {
  158. ALOGE("[EGL] eglGetConfigAttrib() returned error %d", eglGetError());
  159. eglTerminate(display);
  160. return EGL_FALSE;
  161. }
  162. int32_t width = ANativeWindow_getWidth(window);
  163. int32_t height = ANativeWindow_getWidth(window);
  164. ALOGI("[EGL] ANativeWindow_setBuffersGeometry(f=%d);", native_visual_id);
  165. int ret = ANativeWindow_setBuffersGeometry(window, width, height, native_visual_id);
  166. if (ret) {
  167. ALOGE("[EGL] ANativeWindow_setBuffersGeometry(format) returned error %d", ret);
  168. eglTerminate(display);
  169. return EGL_FALSE;
  170. }
  171. }
  172. #endif
  173. EGLSurface surface = eglCreateWindowSurface(display, config, window, NULL);
  174. if (surface == EGL_NO_SURFACE) {
  175. ALOGE("[EGL] eglCreateWindowSurface failed\n");
  176. eglTerminate(display);
  177. return EGL_FALSE;
  178. }
  179. EGLSurface context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
  180. if (context == EGL_NO_CONTEXT) {
  181. ALOGE("[EGL] eglCreateContext failed\n");
  182. eglDestroySurface(display, surface);
  183. eglTerminate(display);
  184. return EGL_FALSE;
  185. }
  186. if (!eglMakeCurrent(display, surface, surface, context)) {
  187. ALOGE("[EGL] elgMakeCurrent() failed (new)\n");
  188. eglDestroyContext(display, context);
  189. eglDestroySurface(display, surface);
  190. eglTerminate(display);
  191. return EGL_FALSE;
  192. }
  193. #if 0
  194. #if defined(__ANDROID__)
  195. {
  196. const char *extensions = (const char *) glGetString(GL_EXTENSIONS);
  197. if (extensions) {
  198. char *dup_extensions = strdup(extensions);
  199. if (dup_extensions) {
  200. char *brk = NULL;
  201. char *ext = strtok_r(dup_extensions, " ", &brk);
  202. while (ext) {
  203. if (0 == strcmp(ext, "GL_EXT_texture_rg"))
  204. egl->gles2_extensions[IJK_GLES2__GL_EXT_texture_rg] = 1;
  205. ext = strtok_r(NULL, " ", &brk);
  206. }
  207. free(dup_extensions);
  208. }
  209. }
  210. }
  211. #elif defined(__APPLE__)
  212. egl->gles2_extensions[IJK_GLES2__GL_EXT_texture_rg] = 1;
  213. #endif
  214. ALOGI("[EGL] GLES2 extensions begin:\n");
  215. ALOGI("[EGL] GL_EXT_texture_rg: %d\n", egl->gles2_extensions[IJK_GLES2__GL_EXT_texture_rg]);
  216. ALOGI("[EGL] GLES2 extensions end.\n");
  217. #endif
  218. IJK_GLES2_Renderer_setupGLES();
  219. egl->context = context;
  220. egl->surface = surface;
  221. egl->display = display;
  222. return EGL_TRUE;
  223. }
  224. static EGLBoolean IJK_EGL_prepareRenderer(IJK_EGL* egl, SDL_VoutOverlay *overlay)
  225. {
  226. assert(egl);
  227. assert(egl->opaque);
  228. IJK_EGL_Opaque *opaque = egl->opaque;
  229. if (!IJK_GLES2_Renderer_isValid(opaque->renderer) ||
  230. !IJK_GLES2_Renderer_isFormat(opaque->renderer, overlay->format)) {
  231. IJK_GLES2_Renderer_reset(opaque->renderer);
  232. IJK_GLES2_Renderer_freeP(&opaque->renderer);
  233. opaque->renderer = IJK_GLES2_Renderer_create(overlay);
  234. if (!opaque->renderer) {
  235. ALOGE("[EGL] Could not create render.");
  236. return EGL_FALSE;
  237. }
  238. if (!IJK_GLES2_Renderer_use(opaque->renderer)) {
  239. ALOGE("[EGL] Could not use render.");
  240. IJK_GLES2_Renderer_freeP(&opaque->renderer);
  241. return EGL_FALSE;
  242. }
  243. }
  244. if (!IJK_EGL_setSurfaceSize(egl, overlay->w, overlay->h)) {
  245. ALOGE("[EGL] IJK_EGL_setSurfaceSize(%d, %d) failed\n", overlay->w, overlay->h);
  246. return EGL_FALSE;
  247. }
  248. glViewport(0, 0, egl->width, egl->height); IJK_GLES2_checkError_TRACE("glViewport");
  249. return EGL_TRUE;
  250. }
  251. static EGLBoolean IJK_EGL_display_internal(IJK_EGL* egl, EGLNativeWindowType window, SDL_VoutOverlay *overlay)
  252. {
  253. IJK_EGL_Opaque *opaque = egl->opaque;
  254. if (!IJK_EGL_prepareRenderer(egl, overlay)) {
  255. ALOGE("[EGL] IJK_EGL_prepareRenderer failed\n");
  256. return EGL_FALSE;
  257. }
  258. if (!IJK_GLES2_Renderer_renderOverlay(opaque->renderer, overlay)) {
  259. ALOGE("[EGL] IJK_GLES2_render failed\n");
  260. return EGL_FALSE;
  261. }
  262. eglSwapBuffers(egl->display, egl->surface);
  263. return EGL_TRUE;
  264. }
  265. EGLBoolean IJK_EGL_display(IJK_EGL* egl, EGLNativeWindowType window, SDL_VoutOverlay *overlay)
  266. {
  267. EGLBoolean ret = EGL_FALSE;
  268. if (!egl)
  269. return EGL_FALSE;
  270. IJK_EGL_Opaque *opaque = egl->opaque;
  271. if (!opaque)
  272. return EGL_FALSE;
  273. if (!IJK_EGL_makeCurrent(egl, window))
  274. return EGL_FALSE;
  275. ret = IJK_EGL_display_internal(egl, window, overlay);
  276. eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  277. eglReleaseThread(); // FIXME: call at thread exit
  278. return ret;
  279. }
  280. void IJK_EGL_releaseWindow(IJK_EGL* egl)
  281. {
  282. if (!egl || !egl->opaque || !egl->opaque->renderer)
  283. return;
  284. IJK_EGL_terminate(egl);
  285. }
  286. void IJK_EGL_free(IJK_EGL *egl)
  287. {
  288. if (!egl)
  289. return;
  290. IJK_EGL_terminate(egl);
  291. memset(egl, 0, sizeof(IJK_EGL));
  292. free(egl);
  293. }
  294. void IJK_EGL_freep(IJK_EGL **egl)
  295. {
  296. if (!egl || !*egl)
  297. return;
  298. IJK_EGL_free(*egl);
  299. *egl = NULL;
  300. }
  301. static SDL_Class g_class = {
  302. .name = "EGL",
  303. };
  304. IJK_EGL *IJK_EGL_create()
  305. {
  306. IJK_EGL *egl = (IJK_EGL*) mallocz(sizeof(IJK_EGL));
  307. if (!egl)
  308. return NULL;
  309. egl->opaque_class = &g_class;
  310. egl->opaque = mallocz(sizeof(IJK_EGL_Opaque));
  311. if (!egl->opaque) {
  312. free(egl);
  313. return NULL;
  314. }
  315. return egl;
  316. }
  317. #endif