static int func_display_overlay_l(SDL_Vout *vout, SDL_VoutOverlay *overlay) { SDL_Vout_Opaque *opaque = vout->opaque; ANativeWindow *native_window = opaque->native_window; if (!native_window) { if (!opaque->null_native_window_warned) { opaque->null_native_window_warned = 1; ALOGW("voud_display_overlay_l: NULL native_window"); } return -1; } else { opaque->null_native_window_warned = 1; } if (!overlay) { ALOGE("voud_display_overlay_l: NULL overlay"); return -1; } if (overlay->w <= 0 || overlay->h <= 0) { ALOGE("voud_display_overlay_l: invalid overlay dimensions(%d, %d)", overlay->w, overlay->h); return -1; } switch(overlay->format) { case SDL_FCC__AMC: { // only ANativeWindow support IJK_EGL_terminate(opaque->egl); return SDL_VoutOverlayAMediaCodec_releaseFrame_l(overlay, NULL, true); } case SDL_FCC_RV24: case SDL_FCC_I420: case SDL_FCC_I444P10LE: { // only GLES support if (opaque->egl) return IJK_EGL_display(opaque->egl, native_window, overlay); break; } case SDL_FCC_YV12: case SDL_FCC_RV16: case SDL_FCC_RV32: { // both GLES & ANativeWindow support if (vout->overlay_format == SDL_FCC__GLES2 && opaque->egl) return IJK_EGL_display(opaque->egl, native_window, overlay); break; } } // fallback to ANativeWindow IJK_EGL_terminate(opaque->egl); return SDL_Android_NativeWindow_display_l(native_window, overlay); }
static void SDL_VoutAndroid_SetNativeWindow_l(SDL_Vout *vout, ANativeWindow *native_window) { AMCTRACE("%s(%p, %p)\n", __func__, vout, native_window); SDL_Vout_Opaque *opaque = vout->opaque; if (opaque->native_window == native_window) { if (native_window == NULL) { // always invalidate buffers, if native_window is changed SDL_VoutAndroid_invalidateAllBuffers_l(vout); } return; } else IJK_EGL_terminate(opaque->egl); SDL_VoutAndroid_invalidateAllBuffers_l(vout); if (opaque->native_window) ANativeWindow_release(opaque->native_window); if (native_window) ANativeWindow_acquire(native_window); opaque->native_window = native_window; opaque->null_native_window_warned = 0; }
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); }
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; }