mirror of https://github.com/mpv-player/mpv
rpi: factor out context creation
To be used by vo_rpi.c. No functional changes.
This commit is contained in:
parent
da8a9ff589
commit
c36c596b7b
|
@ -23,25 +23,11 @@
|
|||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <bcm_host.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
#include "common/common.h"
|
||||
#include "x11_common.h"
|
||||
#include "gl_common.h"
|
||||
|
||||
struct priv {
|
||||
EGLDisplay egl_display;
|
||||
EGLContext egl_context;
|
||||
EGLSurface egl_surface;
|
||||
DISPMANX_DISPLAY_HANDLE_T display;
|
||||
DISPMANX_ELEMENT_HANDLE_T window;
|
||||
DISPMANX_UPDATE_HANDLE_T update;
|
||||
// yep, the API keeps a pointer to it
|
||||
EGL_DISPMANX_WINDOW_T egl_window;
|
||||
int w, h;
|
||||
};
|
||||
#include "gl_rpi.h"
|
||||
|
||||
static void *get_proc_address(const GLubyte *name)
|
||||
{
|
||||
|
@ -60,10 +46,8 @@ static void *get_proc_address(const GLubyte *name)
|
|||
return p;
|
||||
}
|
||||
|
||||
static EGLConfig select_fb_config_egl(struct MPGLContext *ctx)
|
||||
static EGLConfig select_fb_config_egl(struct mp_egl_rpi *p)
|
||||
{
|
||||
struct priv *p = ctx->priv;
|
||||
|
||||
EGLint attributes[] = {
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_RED_SIZE, 8,
|
||||
|
@ -80,19 +64,102 @@ static EGLConfig select_fb_config_egl(struct MPGLContext *ctx)
|
|||
eglChooseConfig(p->egl_display, attributes, &config, 1, &config_count);
|
||||
|
||||
if (!config_count) {
|
||||
MP_FATAL(ctx->vo, "Could find EGL configuration!\n");
|
||||
MP_FATAL(p, "Could find EGL configuration!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
int mp_egl_rpi_init(struct mp_egl_rpi *p, DISPMANX_ELEMENT_HANDLE_T window,
|
||||
int w, int h)
|
||||
{
|
||||
p->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (!eglInitialize(p->egl_display, NULL, NULL)) {
|
||||
MP_FATAL(p, "EGL failed to initialize.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
EGLConfig config = select_fb_config_egl(p);
|
||||
if (!config)
|
||||
goto fail;
|
||||
|
||||
p->egl_window = (EGL_DISPMANX_WINDOW_T){
|
||||
.element = window,
|
||||
.width = w,
|
||||
.height = h,
|
||||
};
|
||||
p->egl_surface = eglCreateWindowSurface(p->egl_display, config,
|
||||
&p->egl_window, NULL);
|
||||
|
||||
if (p->egl_surface == EGL_NO_SURFACE) {
|
||||
MP_FATAL(p, "Could not create EGL surface!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
EGLint context_attributes[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
p->egl_context = eglCreateContext(p->egl_display, config,
|
||||
EGL_NO_CONTEXT, context_attributes);
|
||||
|
||||
if (p->egl_context == EGL_NO_CONTEXT) {
|
||||
MP_FATAL(p, "Could not create EGL context!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface,
|
||||
p->egl_context);
|
||||
|
||||
p->gl = talloc_zero(NULL, struct GL);
|
||||
|
||||
const char *exts = eglQueryString(p->egl_display, EGL_EXTENSIONS);
|
||||
mpgl_load_functions(p->gl, get_proc_address, exts, p->log);
|
||||
|
||||
if (!p->gl->version && !p->gl->es)
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
mp_egl_rpi_destroy(p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void mp_egl_rpi_destroy(struct mp_egl_rpi *p)
|
||||
{
|
||||
if (p->egl_context) {
|
||||
eglMakeCurrent(p->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
eglDestroyContext(p->egl_display, p->egl_context);
|
||||
}
|
||||
p->egl_context = EGL_NO_CONTEXT;
|
||||
if (p->egl_display)
|
||||
eglTerminate(p->egl_display);
|
||||
p->egl_display = EGL_NO_DISPLAY;
|
||||
talloc_free(p->gl);
|
||||
p->gl = NULL;
|
||||
}
|
||||
|
||||
struct priv {
|
||||
DISPMANX_DISPLAY_HANDLE_T display;
|
||||
DISPMANX_ELEMENT_HANDLE_T window;
|
||||
DISPMANX_UPDATE_HANDLE_T update;
|
||||
struct mp_egl_rpi egl;
|
||||
int w, h;
|
||||
};
|
||||
|
||||
static bool sc_config_window(struct MPGLContext *ctx, int flags)
|
||||
{
|
||||
struct priv *p = ctx->priv;
|
||||
struct vo *vo = ctx->vo;
|
||||
|
||||
if (p->egl_context) {
|
||||
p->egl.log = vo->log;
|
||||
|
||||
if (p->egl.gl) {
|
||||
vo->dwidth = p->w;
|
||||
vo->dheight = p->h;
|
||||
return true;
|
||||
|
@ -130,43 +197,10 @@ static bool sc_config_window(struct MPGLContext *ctx, int flags)
|
|||
|
||||
vc_dispmanx_update_submit_sync(p->update);
|
||||
|
||||
p->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (!eglInitialize(p->egl_display, NULL, NULL)) {
|
||||
MP_FATAL(ctx->vo, "EGL failed to initialize.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
EGLConfig config = select_fb_config_egl(ctx);
|
||||
if (!config)
|
||||
if (mp_egl_rpi_init(&p->egl, p->window, w, h) < 0)
|
||||
return false;
|
||||
|
||||
p->egl_window = (EGL_DISPMANX_WINDOW_T){.element = p->window, .width = w, .height = h};
|
||||
p->egl_surface = eglCreateWindowSurface(p->egl_display, config, &p->egl_window, NULL);
|
||||
|
||||
if (p->egl_surface == EGL_NO_SURFACE) {
|
||||
MP_FATAL(ctx->vo, "Could not create EGL surface!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
EGLint context_attributes[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
p->egl_context = eglCreateContext(p->egl_display, config,
|
||||
EGL_NO_CONTEXT, context_attributes);
|
||||
|
||||
if (p->egl_context == EGL_NO_CONTEXT) {
|
||||
MP_FATAL(ctx->vo, "Could not create EGL context!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface,
|
||||
p->egl_context);
|
||||
|
||||
const char *exts = eglQueryString(p->egl_display, EGL_EXTENSIONS);
|
||||
mpgl_load_functions(ctx->gl, get_proc_address, exts, vo->log);
|
||||
ctx->gl = p->egl.gl;
|
||||
|
||||
vo->dwidth = p->w = w;
|
||||
vo->dheight = p->h = h;
|
||||
|
@ -177,20 +211,14 @@ static bool sc_config_window(struct MPGLContext *ctx, int flags)
|
|||
static void sc_releaseGlContext(MPGLContext *ctx)
|
||||
{
|
||||
struct priv *p = ctx->priv;
|
||||
if (p->egl_context) {
|
||||
eglMakeCurrent(p->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
eglDestroyContext(p->egl_display, p->egl_context);
|
||||
}
|
||||
p->egl_context = EGL_NO_CONTEXT;
|
||||
eglTerminate(p->egl_display);
|
||||
mp_egl_rpi_destroy(&p->egl);
|
||||
vc_dispmanx_display_close(p->display);
|
||||
}
|
||||
|
||||
static void sc_swapGlBuffers(MPGLContext *ctx)
|
||||
{
|
||||
struct priv *p = ctx->priv;
|
||||
eglSwapBuffers(p->egl_display, p->egl_surface);
|
||||
eglSwapBuffers(p->egl.egl_display, p->egl.egl_surface);
|
||||
}
|
||||
|
||||
static int sc_vo_init(struct vo *vo)
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#include <bcm_host.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
struct mp_egl_rpi {
|
||||
struct mp_log *log;
|
||||
struct GL *gl;
|
||||
EGLDisplay egl_display;
|
||||
EGLContext egl_context;
|
||||
EGLSurface egl_surface;
|
||||
// yep, the API keeps a pointer to it
|
||||
EGL_DISPMANX_WINDOW_T egl_window;
|
||||
};
|
||||
|
||||
int mp_egl_rpi_init(struct mp_egl_rpi *p, DISPMANX_ELEMENT_HANDLE_T window,
|
||||
int w, int h);
|
||||
void mp_egl_rpi_destroy(struct mp_egl_rpi *p);
|
Loading…
Reference in New Issue