123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- /*
- * Copyright (c) 2016 Bilibili
- * copyright (c) 2016 Zhang Rui <bbcallen@gmail.com>
- *
- * This file is part of ijkPlayer.
- *
- * ijkPlayer is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * ijkPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with ijkPlayer; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #ifndef __APPLE__
- #include "ijksdl_egl.h"
- #include <stdlib.h>
- #include <stdbool.h>
- #include "ijksdl/ijksdl_gles2.h"
- #include "ijksdl/ijksdl_log.h"
- #include "ijksdl/ijksdl_vout.h"
- #include "ijksdl/gles2/internal.h"
- #define IJK_EGL_RENDER_BUFFER 0
- typedef struct IJK_EGL_Opaque {
- IJK_GLES2_Renderer *renderer;
- } IJK_EGL_Opaque;
- static EGLBoolean IJK_EGL_isValid(IJK_EGL* egl)
- {
- if (egl &&
- egl->window &&
- egl->display &&
- egl->surface &&
- egl->context) {
- return EGL_TRUE;
- }
- return EGL_FALSE;
- }
- void IJK_EGL_terminate(IJK_EGL* egl)
- {
- if (!IJK_EGL_isValid(egl))
- return;
- if (egl->opaque)
- IJK_GLES2_Renderer_freeP(&egl->opaque->renderer);
- if (egl->display) {
- eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- if (egl->context)
- eglDestroyContext(egl->display, egl->context);
- if (egl->surface)
- eglDestroySurface(egl->display, egl->surface);
- eglTerminate(egl->display);
- eglReleaseThread(); // FIXME: call at thread exit
- }
- egl->context = EGL_NO_CONTEXT;
- egl->surface = EGL_NO_SURFACE;
- egl->display = EGL_NO_DISPLAY;
- }
- static int IJK_EGL_getSurfaceWidth(IJK_EGL* egl)
- {
- EGLint width = 0;
- if (!eglQuerySurface(egl->display, egl->surface, EGL_WIDTH, &width)) {
- ALOGE("[EGL] eglQuerySurface(EGL_WIDTH) returned error %d", eglGetError());
- return 0;
- }
- return width;
- }
- static int IJK_EGL_getSurfaceHeight(IJK_EGL* egl)
- {
- EGLint height = 0;
- if (!eglQuerySurface(egl->display, egl->surface, EGL_HEIGHT, &height)) {
- ALOGE("[EGL] eglQuerySurface(EGL_HEIGHT) returned error %d", eglGetError());
- return 0;
- }
- return height;
- }
- static EGLBoolean IJK_EGL_setSurfaceSize(IJK_EGL* egl, int width, int height)
- {
- if (!IJK_EGL_isValid(egl))
- return EGL_FALSE;
- #ifdef __ANDROID__
- egl->width = IJK_EGL_getSurfaceWidth(egl);
- egl->height = IJK_EGL_getSurfaceHeight(egl);
- if (width != egl->width || height != egl->height) {
- int format = ANativeWindow_getFormat(egl->window);
- ALOGI("ANativeWindow_setBuffersGeometry(w=%d,h=%d) -> (w=%d,h=%d);",
- egl->width, egl->height,
- width, height);
- int ret = ANativeWindow_setBuffersGeometry(egl->window, width, height, format);
- if (ret) {
- ALOGE("[EGL] ANativeWindow_setBuffersGeometry() returned error %d", ret);
- return EGL_FALSE;
- }
- egl->width = IJK_EGL_getSurfaceWidth(egl);
- egl->height = IJK_EGL_getSurfaceHeight(egl);
- return (egl->width && egl->height) ? EGL_TRUE : EGL_FALSE;
- }
- return EGL_TRUE;
- #else
- // FIXME: other platform?
- #endif
- return EGL_FALSE;
- }
- static EGLBoolean IJK_EGL_makeCurrent(IJK_EGL* egl, EGLNativeWindowType window)
- {
- if (window && window == egl->window &&
- egl->display &&
- egl->surface &&
- egl->context) {
- if (!eglMakeCurrent(egl->display, egl->surface, egl->surface, egl->context)) {
- ALOGE("[EGL] elgMakeCurrent() failed (cached)\n");
- return EGL_FALSE;
- }
- return EGL_TRUE;
- }
- IJK_EGL_terminate(egl);
- egl->window = window;
- if (!window)
- return EGL_FALSE;
- EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (display == EGL_NO_DISPLAY) {
- ALOGE("[EGL] eglGetDisplay failed\n");
- return EGL_FALSE;
- }
- EGLint major, minor;
- if (!eglInitialize(display, &major, &minor)) {
- ALOGE("[EGL] eglInitialize failed\n");
- return EGL_FALSE;
- }
- ALOGI("[EGL] eglInitialize %d.%d\n", (int)major, (int)minor);
- static const EGLint configAttribs[] = {
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_BLUE_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_RED_SIZE, 8,
- EGL_NONE
- };
- static const EGLint contextAttribs[] = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE
- };
- EGLConfig config;
- EGLint numConfig;
- if (!eglChooseConfig(display, configAttribs, &config, 1, &numConfig)) {
- ALOGE("[EGL] eglChooseConfig failed\n");
- eglTerminate(display);
- return EGL_FALSE;
- }
- #ifdef __ANDROID__
- {
- EGLint native_visual_id = 0;
- if (!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &native_visual_id)) {
- ALOGE("[EGL] eglGetConfigAttrib() returned error %d", eglGetError());
- eglTerminate(display);
- return EGL_FALSE;
- }
- int32_t width = ANativeWindow_getWidth(window);
- int32_t height = ANativeWindow_getWidth(window);
- ALOGI("[EGL] ANativeWindow_setBuffersGeometry(f=%d);", native_visual_id);
- int ret = ANativeWindow_setBuffersGeometry(window, width, height, native_visual_id);
- if (ret) {
- ALOGE("[EGL] ANativeWindow_setBuffersGeometry(format) returned error %d", ret);
- eglTerminate(display);
- return EGL_FALSE;
- }
- }
- #endif
- EGLSurface surface = eglCreateWindowSurface(display, config, window, NULL);
- if (surface == EGL_NO_SURFACE) {
- ALOGE("[EGL] eglCreateWindowSurface failed\n");
- eglTerminate(display);
- return EGL_FALSE;
- }
- EGLSurface context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
- if (context == EGL_NO_CONTEXT) {
- ALOGE("[EGL] eglCreateContext failed\n");
- eglDestroySurface(display, surface);
- eglTerminate(display);
- return EGL_FALSE;
- }
- if (!eglMakeCurrent(display, surface, surface, context)) {
- ALOGE("[EGL] elgMakeCurrent() failed (new)\n");
- eglDestroyContext(display, context);
- eglDestroySurface(display, surface);
- eglTerminate(display);
- return EGL_FALSE;
- }
- #if 0
- #if defined(__ANDROID__)
- {
- const char *extensions = (const char *) glGetString(GL_EXTENSIONS);
- if (extensions) {
- char *dup_extensions = strdup(extensions);
- if (dup_extensions) {
- char *brk = NULL;
- char *ext = strtok_r(dup_extensions, " ", &brk);
- while (ext) {
- if (0 == strcmp(ext, "GL_EXT_texture_rg"))
- egl->gles2_extensions[IJK_GLES2__GL_EXT_texture_rg] = 1;
- ext = strtok_r(NULL, " ", &brk);
- }
- free(dup_extensions);
- }
- }
- }
- #elif defined(__APPLE__)
- egl->gles2_extensions[IJK_GLES2__GL_EXT_texture_rg] = 1;
- #endif
- ALOGI("[EGL] GLES2 extensions begin:\n");
- ALOGI("[EGL] GL_EXT_texture_rg: %d\n", egl->gles2_extensions[IJK_GLES2__GL_EXT_texture_rg]);
- ALOGI("[EGL] GLES2 extensions end.\n");
- #endif
- IJK_GLES2_Renderer_setupGLES();
- egl->context = context;
- egl->surface = surface;
- egl->display = display;
- return EGL_TRUE;
- }
- static EGLBoolean IJK_EGL_prepareRenderer(IJK_EGL* egl, SDL_VoutOverlay *overlay)
- {
- assert(egl);
- assert(egl->opaque);
- IJK_EGL_Opaque *opaque = egl->opaque;
- if (!IJK_GLES2_Renderer_isValid(opaque->renderer) ||
- !IJK_GLES2_Renderer_isFormat(opaque->renderer, overlay->format)) {
- IJK_GLES2_Renderer_reset(opaque->renderer);
- IJK_GLES2_Renderer_freeP(&opaque->renderer);
- opaque->renderer = IJK_GLES2_Renderer_create(overlay);
- if (!opaque->renderer) {
- ALOGE("[EGL] Could not create render.");
- return EGL_FALSE;
- }
- if (!IJK_GLES2_Renderer_use(opaque->renderer)) {
- ALOGE("[EGL] Could not use render.");
- IJK_GLES2_Renderer_freeP(&opaque->renderer);
- return EGL_FALSE;
- }
- }
- if (!IJK_EGL_setSurfaceSize(egl, overlay->w, overlay->h)) {
- ALOGE("[EGL] IJK_EGL_setSurfaceSize(%d, %d) failed\n", overlay->w, overlay->h);
- return EGL_FALSE;
- }
- glViewport(0, 0, egl->width, egl->height); IJK_GLES2_checkError_TRACE("glViewport");
- return EGL_TRUE;
- }
- static EGLBoolean IJK_EGL_display_internal(IJK_EGL* egl, EGLNativeWindowType window, SDL_VoutOverlay *overlay)
- {
- IJK_EGL_Opaque *opaque = egl->opaque;
- if (!IJK_EGL_prepareRenderer(egl, overlay)) {
- ALOGE("[EGL] IJK_EGL_prepareRenderer failed\n");
- return EGL_FALSE;
- }
- if (!IJK_GLES2_Renderer_renderOverlay(opaque->renderer, overlay)) {
- ALOGE("[EGL] IJK_GLES2_render failed\n");
- return EGL_FALSE;
- }
- eglSwapBuffers(egl->display, egl->surface);
- return EGL_TRUE;
- }
- EGLBoolean IJK_EGL_display(IJK_EGL* egl, EGLNativeWindowType window, SDL_VoutOverlay *overlay)
- {
- EGLBoolean ret = EGL_FALSE;
- if (!egl)
- return EGL_FALSE;
- IJK_EGL_Opaque *opaque = egl->opaque;
- if (!opaque)
- return EGL_FALSE;
- if (!IJK_EGL_makeCurrent(egl, window))
- return EGL_FALSE;
- ret = IJK_EGL_display_internal(egl, window, overlay);
- eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglReleaseThread(); // FIXME: call at thread exit
- return ret;
- }
- void IJK_EGL_releaseWindow(IJK_EGL* egl)
- {
- if (!egl || !egl->opaque || !egl->opaque->renderer)
- return;
- IJK_EGL_terminate(egl);
- }
- void IJK_EGL_free(IJK_EGL *egl)
- {
- if (!egl)
- return;
- IJK_EGL_terminate(egl);
- memset(egl, 0, sizeof(IJK_EGL));
- free(egl);
- }
- void IJK_EGL_freep(IJK_EGL **egl)
- {
- if (!egl || !*egl)
- return;
- IJK_EGL_free(*egl);
- *egl = NULL;
- }
- static SDL_Class g_class = {
- .name = "EGL",
- };
- IJK_EGL *IJK_EGL_create()
- {
- IJK_EGL *egl = (IJK_EGL*) mallocz(sizeof(IJK_EGL));
- if (!egl)
- return NULL;
- egl->opaque_class = &g_class;
- egl->opaque = mallocz(sizeof(IJK_EGL_Opaque));
- if (!egl->opaque) {
- free(egl);
- return NULL;
- }
- return egl;
- }
- #endif
|