summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-03-01 15:55:08 +0100
committerwm4 <wm4@nowhere>2013-03-28 21:46:17 +0100
commit16e951c2cdfa6710f0d5cc77b513e0f2a5f1377d (patch)
tree8c5d12be204f0f03437041b31cf7fb7272101b7f /video
parent3374a43998f183b585640de0a588db2431ed87ae (diff)
downloadmpv-16e951c2cdfa6710f0d5cc77b513e0f2a5f1377d.tar.bz2
mpv-16e951c2cdfa6710f0d5cc77b513e0f2a5f1377d.tar.xz
gl_common: split into platform specific files
Do this instead of stuffing all x11/cocoa/win32/wayland specific code into gl_common.c. The cocoa specific parts could probably go directly into cocoa_common.m, possibly same with wayland. Also redo how the list of backends is managed. Get rid of the GLTYPE_ constants. Instead of having a big switch() on GLTYPE_, each backend entry has a function pointer to setup the MPGLContext callback (e.g. mpgl_set_backend_x11()).
Diffstat (limited to 'video')
-rw-r--r--video/out/gl_cocoa.c67
-rw-r--r--video/out/gl_common.c829
-rw-r--r--video/out/gl_common.h25
-rw-r--r--video/out/gl_w32.c218
-rw-r--r--video/out/gl_wayland.c259
-rw-r--r--video/out/gl_x11.c282
-rw-r--r--video/out/vo_corevideo.m2
-rw-r--r--video/out/vo_opengl.c6
-rw-r--r--video/out/vo_opengl_old.c6
-rw-r--r--video/out/w32_common.h2
10 files changed, 891 insertions, 805 deletions
diff --git a/video/out/gl_cocoa.c b/video/out/gl_cocoa.c
new file mode 100644
index 0000000000..81be21da58
--- /dev/null
+++ b/video/out/gl_cocoa.c
@@ -0,0 +1,67 @@
+/*
+ * MPlayer is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MPlayer 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * You can alternatively redistribute this file 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.
+ */
+
+#include "cocoa_common.h"
+#include "gl_common.h"
+
+static bool config_window_cocoa(struct MPGLContext *ctx, uint32_t d_width,
+ uint32_t d_height, uint32_t flags)
+{
+ int rv = vo_cocoa_config_window(ctx->vo, d_width, d_height, flags,
+ ctx->requested_gl_version >= MPGL_VER(3, 0));
+ if (rv != 0)
+ return false;
+
+ mpgl_load_functions(ctx->gl, (void *)vo_cocoa_glgetaddr, NULL);
+
+ ctx->depth_r = vo_cocoa_cgl_color_size(ctx->vo);
+ ctx->depth_g = vo_cocoa_cgl_color_size(ctx->vo);
+ ctx->depth_b = vo_cocoa_cgl_color_size(ctx->vo);
+
+ if (!ctx->gl->SwapInterval)
+ ctx->gl->SwapInterval = vo_cocoa_swap_interval;
+
+ return true;
+}
+
+static void releaseGlContext_cocoa(MPGLContext *ctx)
+{
+}
+
+static void swapGlBuffers_cocoa(MPGLContext *ctx)
+{
+ vo_cocoa_swap_buffers(ctx->vo);
+}
+
+void mpgl_set_backend_cocoa(MPGLContext *ctx)
+{
+ ctx->config_window = config_window_cocoa;
+ ctx->releaseGlContext = releaseGlContext_cocoa;
+ ctx->swapGlBuffers = swapGlBuffers_cocoa;
+ ctx->check_events = vo_cocoa_check_events;
+ ctx->update_xinerama_info = vo_cocoa_update_xinerama_info;
+ ctx->fullscreen = vo_cocoa_fullscreen;
+ ctx->ontop = vo_cocoa_ontop;
+ ctx->vo_init = vo_cocoa_init;
+ ctx->pause = vo_cocoa_pause;
+ ctx->resume = vo_cocoa_resume;
+ ctx->vo_uninit = vo_cocoa_uninit;
+}
diff --git a/video/out/gl_common.c b/video/out/gl_common.c
index 72c23079a5..5437c28f02 100644
--- a/video/out/gl_common.c
+++ b/video/out/gl_common.c
@@ -144,12 +144,8 @@ static bool is_software_gl(GL *gl)
#ifdef HAVE_LIBDL
#include <dlfcn.h>
#endif
-/**
- * \brief find address of a linked function
- * \param s name of function to find
- * \return address of function or NULL if not found
- */
-static void *getdladdr(const char *s)
+
+void *mp_getdladdr(const char *s)
{
void *ret = NULL;
#ifdef HAVE_LIBDL
@@ -456,12 +452,12 @@ struct gl_functions gl_functions[] = {
// Fill the GL struct with function pointers and extensions from the current
-// GL context.
+// GL context. Called by the backend.
// getProcAddress: function to resolve function names, may be NULL
// ext2: an extra extension string
// Note: if you create a CONTEXT_FORWARD_COMPATIBLE_BIT_ARB with OpenGL 3.0,
// you must append "GL_ARB_compatibility" to ext2.
-static void getFunctions(GL *gl, void *(*getProcAddress)(const GLubyte *),
+void mpgl_load_functions(GL *gl, void *(*getProcAddress)(const GLubyte *),
const char *ext2)
{
talloc_free_children(gl);
@@ -470,7 +466,7 @@ static void getFunctions(GL *gl, void *(*getProcAddress)(const GLubyte *),
};
if (!getProcAddress)
- getProcAddress = (void *)getdladdr;
+ getProcAddress = (void *)mp_getdladdr;
gl->GetString = getProcAddress("glGetString");
if (!gl->GetString)
@@ -839,808 +835,69 @@ mp_image_t *glGetWindowScreenshot(GL *gl)
return image;
}
-#ifdef CONFIG_GL_COCOA
-#include "cocoa_common.h"
-
-static bool config_window_cocoa(struct MPGLContext *ctx, uint32_t d_width,
- uint32_t d_height, uint32_t flags)
-{
- int rv = vo_cocoa_config_window(ctx->vo, d_width, d_height, flags,
- ctx->requested_gl_version >= MPGL_VER(3, 0));
- if (rv != 0)
- return false;
-
- getFunctions(ctx->gl, (void *)vo_cocoa_glgetaddr, NULL);
-
- ctx->depth_r = vo_cocoa_cgl_color_size(ctx->vo);
- ctx->depth_g = vo_cocoa_cgl_color_size(ctx->vo);
- ctx->depth_b = vo_cocoa_cgl_color_size(ctx->vo);
+typedef void (*MPGLSetBackendFn)(MPGLContext *ctx);
- if (!ctx->gl->SwapInterval)
- ctx->gl->SwapInterval = vo_cocoa_swap_interval;
-
- return true;
-}
-
-static void releaseGlContext_cocoa(MPGLContext *ctx)
-{
-}
+struct backend {
+ const char *name;
+ MPGLSetBackendFn init;
+};
-static void swapGlBuffers_cocoa(MPGLContext *ctx)
-{
- vo_cocoa_swap_buffers(ctx->vo);
-}
+static struct backend backends[] = {
+#ifdef CONFIG_GL_COCOA
+ {"cocoa", mpgl_set_backend_cocoa},
#endif
-
#ifdef CONFIG_GL_WIN32
-#include <windows.h>
-#include "w32_common.h"
-
-struct w32_context {
- HGLRC context;
-};
-
-static void *w32gpa(const GLubyte *procName)
-{
- HMODULE oglmod;
- void *res = wglGetProcAddress(procName);
- if (res)
- return res;
- oglmod = GetModuleHandle("opengl32.dll");
- return GetProcAddress(oglmod, procName);
-}
-
-static bool create_context_w32_old(struct MPGLContext *ctx)
-{
- GL *gl = ctx->gl;
-
- struct w32_context *w32_ctx = ctx->priv;
- HGLRC *context = &w32_ctx->context;
-
- if (*context) {
- gl->Finish(); // supposedly to prevent flickering
- return true;
- }
-
- HWND win = ctx->vo->w32->window;
- HDC windc = GetDC(win);
- bool res = false;
-
- HGLRC new_context = wglCreateContext(windc);
- if (!new_context) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not create GL context!\n");
- goto out;
- }
-
- if (!wglMakeCurrent(windc, new_context)) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not set GL context!\n");
- wglDeleteContext(new_context);
- goto out;
- }
-
- *context = new_context;
-
- getFunctions(ctx->gl, w32gpa, NULL);
- res = true;
-
-out:
- ReleaseDC(win, windc);
- return res;
-}
-
-static bool create_context_w32_gl3(struct MPGLContext *ctx)
-{
- struct w32_context *w32_ctx = ctx->priv;
- HGLRC *context = &w32_ctx->context;
-
- if (*context) // reuse existing context
- return true; // not reusing it breaks gl3!
-
- HWND win = ctx->vo->w32->window;
- HDC windc = GetDC(win);
- HGLRC new_context = 0;
-
- new_context = wglCreateContext(windc);
- if (!new_context) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not create GL context!\n");
- return false;
- }
-
- // set context
- if (!wglMakeCurrent(windc, new_context)) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not set GL context!\n");
- goto out;
- }
-
- const char *(GLAPIENTRY *wglGetExtensionsStringARB)(HDC hdc)
- = w32gpa((const GLubyte*)"wglGetExtensionsStringARB");
-
- if (!wglGetExtensionsStringARB)
- goto unsupported;
-
- const char *wgl_exts = wglGetExtensionsStringARB(windc);
- if (!strstr(wgl_exts, "WGL_ARB_create_context"))
- goto unsupported;
-
- HGLRC (GLAPIENTRY *wglCreateContextAttribsARB)(HDC hDC, HGLRC hShareContext,
- const int *attribList)
- = w32gpa((const GLubyte*)"wglCreateContextAttribsARB");
-
- if (!wglCreateContextAttribsARB)
- goto unsupported;
-
- int gl_version = ctx->requested_gl_version;
- int attribs[] = {
- WGL_CONTEXT_MAJOR_VERSION_ARB, MPGL_VER_GET_MAJOR(gl_version),
- WGL_CONTEXT_MINOR_VERSION_ARB, MPGL_VER_GET_MINOR(gl_version),
- WGL_CONTEXT_FLAGS_ARB, 0,
- WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
- 0
- };
-
- *context = wglCreateContextAttribsARB(windc, 0, attribs);
- if (! *context) {
- // NVidia, instead of ignoring WGL_CONTEXT_FLAGS_ARB, will error out if
- // it's present on pre-3.2 contexts.
- // Remove it from attribs and retry the context creation.
- attribs[6] = attribs[7] = 0;
- *context = wglCreateContextAttribsARB(windc, 0, attribs);
- }
- if (! *context) {
- int err = GetLastError();
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not create an OpenGL 3.x"
- " context: error 0x%x\n", err);
- goto out;
- }
-
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(new_context);
-
- if (!wglMakeCurrent(windc, *context)) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not set GL3 context!\n");
- wglDeleteContext(*context);
- return false;
- }
-
- /* update function pointers */
- getFunctions(ctx->gl, w32gpa, NULL);
-
- int pfmt = GetPixelFormat(windc);
- PIXELFORMATDESCRIPTOR pfd;
- if (DescribePixelFormat(windc, pfmt, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) {
- ctx->depth_r = pfd.cRedBits;
- ctx->depth_g = pfd.cGreenBits;
- ctx->depth_b = pfd.cBlueBits;
- }
-
- return true;
-
-unsupported:
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] The current OpenGL implementation does"
- " not support OpenGL 3.x \n");
-out:
- wglDeleteContext(new_context);
- return false;
-}
-
-static bool config_window_w32(struct MPGLContext *ctx, uint32_t d_width,
- uint32_t d_height, uint32_t flags)
-{
- if (!vo_w32_config(ctx->vo, d_width, d_height, flags))
- return false;
-
- bool success = false;
- if (ctx->requested_gl_version >= MPGL_VER(3, 0))
- success = create_context_w32_gl3(ctx);
- if (!success)
- success = create_context_w32_old(ctx);
- return success;
-}
-
-static void releaseGlContext_w32(MPGLContext *ctx)
-{
- struct w32_context *w32_ctx = ctx->priv;
- HGLRC *context = &w32_ctx->context;
- if (*context) {
- wglMakeCurrent(0, 0);
- wglDeleteContext(*context);
- }
- *context = 0;
-}
-
-static void swapGlBuffers_w32(MPGLContext *ctx)
-{
- HDC vo_hdc = GetDC(ctx->vo->w32->window);
- SwapBuffers(vo_hdc);
- ReleaseDC(ctx->vo->w32->window, vo_hdc);
-}
+ {"win", mpgl_set_backend_w32},
#endif
-
#ifdef CONFIG_GL_X11
-#include <X11/Xlib.h>
-#include <GL/glx.h>
-
-#include "x11_common.h"
-
-#define MP_GET_GLX_WORKAROUNDS
-#include "gl_header_fixes.h"
-
-struct glx_context {
- XVisualInfo *vinfo;
- GLXContext context;
- GLXFBConfig fbc;
-};
-
-static bool create_context_x11_old(struct MPGLContext *ctx)
-{
- struct glx_context *glx_ctx = ctx->priv;
- Display *display = ctx->vo->x11->display;
- struct vo *vo = ctx->vo;
- GL *gl = ctx->gl;
-
- if (glx_ctx->context)
- return true;
-
- GLXContext new_context = glXCreateContext(display, glx_ctx->vinfo, NULL,
- True);
- if (!new_context) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not create GLX context!\n");
- return false;
- }
-
- if (!glXMakeCurrent(display, ctx->vo->x11->window, new_context)) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not set GLX context!\n");
- glXDestroyContext(display, new_context);
- return false;
- }
-
- void *(*getProcAddress)(const GLubyte *);
- getProcAddress = getdladdr("glXGetProcAddress");
- if (!getProcAddress)
- getProcAddress = getdladdr("glXGetProcAddressARB");
-
- const char *glxstr = "";
- const char *(*glXExtStr)(Display *, int)
- = getdladdr("glXQueryExtensionsString");
- if (glXExtStr)
- glxstr = glXExtStr(display, ctx->vo->x11->screen);
-
- getFunctions(gl, getProcAddress, glxstr);
- if (!gl->GenPrograms && gl->GetString &&
- gl->version < MPGL_VER(3, 0) &&
- getProcAddress &&
- strstr(gl->GetString(GL_EXTENSIONS), "GL_ARB_vertex_program"))
- {
- mp_msg(MSGT_VO, MSGL_WARN,
- "Broken glXGetProcAddress detected, trying workaround\n");
- getFunctions(gl, NULL, glxstr);
- }
-
- glx_ctx->context = new_context;
-
- if (!glXIsDirect(vo->x11->display, new_context))
- ctx->gl->mpgl_caps &= ~MPGL_CAP_NO_SW;
-
- return true;
-}
-
-typedef GLXContext (*glXCreateContextAttribsARBProc)
- (Display*, GLXFBConfig, GLXContext, Bool, const int*);
-
-static bool create_context_x11_gl3(struct MPGLContext *ctx, bool debug)
-{
- struct glx_context *glx_ctx = ctx->priv;
- struct vo *vo = ctx->vo;
-
- if (glx_ctx->context)
- return true;
-
- glXCreateContextAttribsARBProc glXCreateContextAttribsARB =
- (glXCreateContextAttribsARBProc)
- glXGetProcAddressARB((const GLubyte *)"glXCreateContextAttribsARB");
-
- const char *glxstr = "";
- const char *(*glXExtStr)(Display *, int)
- = getdladdr("glXQueryExtensionsString");
- if (glXExtStr)
- glxstr = glXExtStr(vo->x11->display, vo->x11->screen);
- bool have_ctx_ext = glxstr && !!strstr(glxstr, "GLX_ARB_create_context");
-
- if (!(have_ctx_ext && glXCreateContextAttribsARB)) {
- return false;
- }
-
- int gl_version = ctx->requested_gl_version;
- int context_attribs[] = {
- GLX_CONTEXT_MAJOR_VERSION_ARB, MPGL_VER_GET_MAJOR(gl_version),
- GLX_CONTEXT_MINOR_VERSION_ARB, MPGL_VER_GET_MINOR(gl_version),
- GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
- GLX_CONTEXT_FLAGS_ARB, debug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
- None
- };
- GLXContext context = glXCreateContextAttribsARB(vo->x11->display,
- glx_ctx->fbc, 0, True,
- context_attribs);
- if (!context) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not create GLX context!\n");
- return false;
- }
-
- // set context
- if (!glXMakeCurrent(vo->x11->display, vo->x11->window, context)) {
- mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not set GLX context!\n");
- glXDestroyContext(vo->x11->display, context);
- return false;
- }
-
- glx_ctx->context = context;
-
- getFunctions(ctx->gl, (void *)glXGetProcAddress, glxstr);
-
- if (!glXIsDirect(vo->x11->display, context))
- ctx->gl->mpgl_caps &= ~MPGL_CAP_NO_SW;
-
- return true;
-}
-
-// The GL3/FBC initialization code roughly follows/copies from:
-// http://www.opengl.org/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX)
-// but also uses some of the old code.
-
-static GLXFBConfig select_fb_config(struct vo *vo, const int *attribs)
-{
- int fbcount;
- GLXFBConfig *fbc = glXChooseFBConfig(vo->x11->display, vo->x11->screen,
- attribs, &fbcount);
- if (!fbc)
- return NULL;
-
- // The list in fbc is sorted (so that the first element is the best).
- GLXFBConfig fbconfig = fbc[0];
-
- XFree(fbc);
-
- return fbconfig;
-}
-
-static bool config_window_x11(struct MPGLContext *ctx, uint32_t d_width,
- uint32_t d_height, uint32_t flags)
-{
- struct vo *vo = ctx->vo;
- struct glx_context *glx_ctx = ctx->priv;
-
- if (glx_ctx->context) {
- // GL context and window already exist.
- // Only update window geometry etc.
- vo_x11_config_vo_window(vo, glx_ctx->vinfo, vo->dx, vo->dy, d_width,
- d_height, flags, "gl");
- return true;
- }
-
- int glx_major, glx_minor;
-
- // FBConfigs were added in GLX version 1.3.
- if (!glXQueryVersion(vo->x11->display, &glx_major, &glx_minor) ||
- (MPGL_VER(glx_major, glx_minor) < MPGL_VER(1, 3)))
- {
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] GLX version older than 1.3.\n");
- return false;
- }
-
- const int glx_attribs_stereo_value_idx = 1; // index of GLX_STEREO + 1
- int glx_attribs[] = {
- GLX_STEREO, False,
- GLX_X_RENDERABLE, True,
- GLX_RED_SIZE, 1,
- GLX_GREEN_SIZE, 1,
- GLX_BLUE_SIZE, 1,
- GLX_DOUBLEBUFFER, True,
- None
- };
- GLXFBConfig fbc = NULL;
- if (flags & VOFLAG_STEREO) {
- glx_attribs[glx_attribs_stereo_value_idx] = True;
- fbc = select_fb_config(vo, glx_attribs);
- if (!fbc) {
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] Could not find a stereo visual,"
- " 3D will probably not work!\n");
- glx_attribs[glx_attribs_stereo_value_idx] = False;
- }
- }
- if (!fbc)
- fbc = select_fb_config(vo, glx_attribs);
- if (!fbc) {
- mp_msg(MSGT_VO, MSGL_ERR, "[gl] no GLX support present\n");
- return false;
- }
-
- glx_ctx->fbc = fbc;
- glx_ctx->vinfo = glXGetVisualFromFBConfig(vo->x11->display, fbc);
-
- mp_msg(MSGT_VO, MSGL_V, "[gl] GLX chose visual with ID 0x%x\n",
- (int)glx_ctx->vinfo->visualid);
-
- glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_RED_SIZE, &ctx->depth_r);
- glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_GREEN_SIZE, &ctx->depth_g);
- glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_BLUE_SIZE, &ctx->depth_b);
-
- vo_x11_config_vo_window(vo, glx_ctx->vinfo, vo->dx, vo->dy, d_width,
- d_height, flags, "gl");
-
- bool success = false;
- if (ctx->requested_gl_version >= MPGL_VER(3, 0))
- success = create_context_x11_gl3(ctx, flags & VOFLAG_GL_DEBUG);
- if (!success)
- success = create_context_x11_old(ctx);
- return success;
-}
-
-
-/**
- * \brief free the VisualInfo and GLXContext of an OpenGL context.
- * \ingroup glcontext
- */
-static void releaseGlContext_x11(MPGLContext *ctx)
-{
- struct glx_context *glx_ctx = ctx->priv;
- XVisualInfo **vinfo = &glx_ctx->vinfo;
- GLXContext *context = &glx_ctx->context;
- Display *display = ctx->vo->x11->display;
- GL *gl = ctx->gl;
- if (*vinfo)
- XFree(*vinfo);
- *vinfo = NULL;
- if (*context) {
- if (gl->Finish)
- gl->Finish();
- glXMakeCurrent(display, None, NULL);
- glXDestroyContext(display, *context);
- }
- *context = 0;
-}
-
-static void swapGlBuffers_x11(MPGLContext *ctx)
-{
- glXSwapBuffers(ctx->vo->x11->display, ctx->vo->x11->window);
-}
+ {"x11", mpgl_set_backend_x11},
#endif
-
#ifdef CONFIG_GL_WAYLAND
-
-#include "wayland_common.h"
-#include <wayland-egl.h>
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-struct egl_context {
- EGLSurface egl_surface;
-
- struct wl_egl_window *egl_window;
-
- struct {
- EGLDisplay dpy;
- EGLContext ctx;
- EGLConfig conf;
- } egl;
-};
-
-static void egl_resize_func(struct vo_wayland_state *wl,
- struct egl_context *ctx)
-{
- int32_t x, y, scaled_height;
- double ratio;
- int minimum_size = 50;
-
- if (wl->window->pending_width < minimum_size)
- wl->window->pending_width = minimum_size;
- if (wl->window->pending_height < minimum_size)
- wl->window->pending_height = minimum_size;
-
- ratio = (double) wl->vo->aspdat.orgw / wl->vo->aspdat.orgh;
- scaled_height = wl->window->pending_height * ratio;
- if (wl->window->pending_width > scaled_height) {
- wl->window->pending_height = wl->window->pending_width / ratio;
- } else {
- wl->window->pending_width = scaled_height;
- }
-
- if (wl->window->edges & WL_SHELL_SURFACE_RESIZE_LEFT)
- x = wl->window->width - wl->window->pending_width;
- else
- x = 0;
-
- if (wl->window->edges & WL_SHELL_SURFACE_RESIZE_TOP)
- y = wl->window->height - wl->window->pending_height;
- else
- y = 0;
-
- wl_egl_window_resize(ctx->egl_window,
- wl->window->pending_width,
- wl->window->pending_height,
- x, y);
-
- wl->window->width = wl->window->pending_width;
- wl->window->height = wl->window->pending_height;
-
- /* set size for mplayer */
- wl->vo->dwidth = wl->window->pending_width;
- wl->vo->dheight = wl->window->pending_height;
- wl->window->events |= VO_EVENT_RESIZE;
- wl->window->edges = 0;
- wl->window->resize_needed = 0;
-}
-
-static bool egl_create_context(struct vo_wayland_state *wl,
- struct egl_context *egl_ctx,
- MPGLContext *ctx)
-{
- EGLint major, minor, n;
-
- GL *gl = ctx->gl;
- const char *eglstr = "";
-
- if (!(egl_ctx->egl.dpy = eglGetDisplay(wl->display->display)))
- return false;
-
- EGLint config_attribs[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RED_SIZE, 1,
- EGL_GREEN_SIZE, 1,
- EGL_BLUE_SIZE, 1,
- EGL_ALPHA_SIZE, 0,
- EGL_DEPTH_SIZE, 1,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
- EGL_NONE
- };
-
- /* major and minor here returns the supported EGL version (e.g.: 1.4) */
- if (eglInitialize(egl_ctx->egl.dpy, &major, &minor) != EGL_TRUE)
- return false;
-
- EGLint context_attribs[] = {
- EGL_CONTEXT_MAJOR_VERSION_KHR,
- MPGL_VER_GET_MAJOR(ctx->requested_gl_version),
- /* EGL_CONTEXT_MINOR_VERSION_KHR, */
- /* MPGL_VER_GET_MINOR(ctx->requested_gl_version), */
- /* EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR, 0, */
- /* Segfaults on anything else than the major version */
- EGL_NONE
- };
-
- if (eglBindAPI(EGL_OPENGL_API) != EGL_TRUE)
- return false;
-
- eglChooseConfig(egl_ctx->egl.dpy, config_attribs,
- &egl_ctx->egl.conf, 1, &n);
-
- egl_ctx->egl.ctx = eglCreateContext(egl_ctx->egl.dpy,
- egl_ctx->egl.conf,
- EGL_NO_CONTEXT,
- context_attribs);
- if (!egl_ctx->egl.ctx)
- return false;
-
- eglMakeCurrent(egl_ctx->egl.dpy, NULL, NULL, egl_ctx->egl.ctx);
-
- eglstr = eglQueryString(egl_ctx->egl.dpy, EGL_EXTENSIONS);
-
- getFunctions(gl, (void*(*)(const GLubyte*))eglGetProcAddress, eglstr);
- if (!gl->BindProgram)
- getFunctions(gl, NULL, eglstr);
-
- return true;
-}
-
-static void egl_create_window(struct vo_wayland_state *wl,
- struct egl_context *egl_ctx,
- uint32_t width,
- uint32_t height)
-{
- egl_ctx->egl_window = wl_egl_window_create(wl->window->surface,
- wl->window->width,
- wl->window->height);
-
- egl_ctx->egl_surface = eglCreateWindowSurface(egl_ctx->egl.dpy,
- egl_ctx->egl.conf,
- egl_ctx->egl_window,
- NULL);
-
- eglMakeCurrent(egl_ctx->egl.dpy,
- egl_ctx->egl_surface,
- egl_ctx->egl_surface,
- egl_ctx->egl.ctx);
-
- wl_display_dispatch_pending(wl->display->display);
-}
-
-static bool config_window_wayland(struct MPGLContext *ctx,
- uint32_t d_width,
- uint32_t d_height,
- uint32_t flags)
-{
- struct egl_context * egl_ctx = ctx->priv;
- struct vo_wayland_state * wl = ctx->vo->wayland;
- bool ret = false;
-
- wl->window->pending_width = d_width;
- wl->window->pending_height = d_height;
- wl->window->width = d_width;
- wl->window->height = d_height;
-
- vo_wayland_update_window_title(ctx->vo);
-
- if ((VOFLAG_FULLSCREEN & flags) && wl->window->type != TYPE_FULLSCREEN)
- vo_wayland_fullscreen(ctx->vo);
-
- if (!egl_ctx->egl.ctx) {
- /* Create OpenGL context */
- ret = egl_create_context(wl, egl_ctx, ctx);
-
- /* If successfully created the context and we don't want to hide the
- * window than also create the window immediately */
- if (ret && !(VOFLAG_HIDDEN & flags))
- egl_create_window(wl, egl_ctx, d_width, d_height);
-
- return ret;
- }
- else {
- /* If the window exists just resize it */
- if (egl_ctx->egl_window)
- egl_resize_func(wl, egl_ctx);
-
- else {
- /* If the context exists and the hidden flag is unset then
- * create the window */
- if (!(VOFLAG_HIDDEN & flags))
- egl_create_window(wl, egl_ctx, d_width, d_height);
- }
- return true;
- }
-}
-
-static void releaseGlContext_wayland(MPGLContext *ctx)
-{
- GL *gl = ctx->gl;
- struct egl_context * egl_ctx = ctx->priv;
-
- gl->Finish();
- eglMakeCurrent(egl_ctx->egl.dpy, NULL, NULL, EGL_NO_CONTEXT);
- eglDestroyContext(egl_ctx->egl.dpy, egl_ctx->egl.ctx);
- eglTerminate(egl_ctx->egl.dpy);
- eglReleaseThread();
- wl_egl_window_destroy(egl_ctx->egl_window);
- egl_ctx->egl.ctx = NULL;
-}
-
-static void swapGlBuffers_wayland(MPGLContext *ctx)
-{
- struct egl_context * egl_ctx = ctx->priv;
- struct vo_wayland_state *wl = ctx->vo->wayland;
-
- eglSwapBuffers(egl_ctx->egl.dpy, egl_ctx->egl_surface);
-
- /* resize window after the buffers have swapped
- * makes resizing more fluid */
- if (wl->window->resize_needed) {
- wl_egl_window_get_attached_size(egl_ctx->egl_window,
- &wl->window->width,
- &wl->window->height);
- egl_resize_func(wl, egl_ctx);
- }
-}
-
+ {"wayland", mpgl_set_backend_wayland},
#endif
-
-struct backend {
- const char *name;
- enum MPGLType type;
-};
-
-static struct backend backends[] = {
- {"auto", GLTYPE_AUTO},
- {"cocoa", GLTYPE_COCOA},
- {"win", GLTYPE_W32},
- {"x11", GLTYPE_X11},
- {"wayland", GLTYPE_WAYLAND},
{0}
};
int mpgl_find_backend(const char *name)
{
+ if (name == NULL || strcmp(name, "auto") == 0)
+ return -1;
for (const struct backend *entry = backends; entry->name; entry++) {
if (strcmp(entry->name, name) == 0)
- return entry->type;
+ return entry - backends;
}
- return -1;
+ return -2;
}
-MPGLContext *mpgl_init(enum MPGLType type, struct vo *vo)
+static MPGLContext *init_backend(struct vo *vo, MPGLSetBackendFn set_backend)
{
- MPGLContext *ctx;
- if (type == GLTYPE_AUTO) {
- ctx = mpgl_init(GLTYPE_COCOA, vo);
- if (ctx)
- return ctx;
- ctx = mpgl_init(GLTYPE_W32, vo);
- if (ctx)
- return ctx;
- ctx = mpgl_init(GLTYPE_X11, vo);
- if (ctx)
- return ctx;
- return mpgl_init(GLTYPE_WAYLAND, vo);
- }
- ctx = talloc_zero(NULL, MPGLContext);
+ MPGLContext *ctx = talloc_ptrtype(NULL, ctx);
*ctx = (MPGLContext) {
.gl = talloc_zero(ctx, GL),
- .type = type,
.vo = vo,
};
- switch (ctx->type) {
-#ifdef CONFIG_GL_COCOA
- case GLTYPE_COCOA:
- ctx->config_window = config_window_cocoa;
- ctx->releaseGlContext = releaseGlContext_cocoa;
- ctx->swapGlBuffers = swapGlBuffers_cocoa;
- ctx->check_events = vo_cocoa_check_events;
- ctx->update_xinerama_info = vo_cocoa_update_xinerama_info;
- ctx->fullscreen = vo_cocoa_fullscreen;
- ctx->ontop = vo_cocoa_ontop;
- ctx->vo_init = vo_cocoa_init;
- ctx->pause = vo_cocoa_pause;
- ctx->resume = vo_cocoa_resume;
- ctx->vo_uninit = vo_cocoa_uninit;
- break;
-#endif
-#ifdef CONFIG_GL_WIN32
- case GLTYPE_W32:
- ctx->priv = talloc_zero(ctx, struct w32_context);
- ctx->config_window = config_window_w32;
- ctx->releaseGlContext = releaseGlContext_w32;
- ctx->swapGlBuffers = swapGlBuffers_w32;
- ctx->update_xinerama_info = w32_update_xinerama_info;
- ctx->border = vo_w32_border;
- ctx->check_events = vo_w32_check_events;
- ctx->fullscreen = vo_w32_fullscreen;
- ctx->ontop = vo_w32_ontop;
- ctx->vo_init = vo_w32_init;
- ctx->vo_uninit = vo_w32_uninit;
- break;
-#endif
-#ifdef CONFIG_GL_X11
- case GLTYPE_X11:
- ctx->priv = talloc_zero(ctx, struct glx_context);
- ctx->config_window = config_window_x11;
- ctx->releaseGlContext = releaseGlContext_x11;
- ctx->swapGlBuffers = swapGlBuffers_x11;
- ctx->update_xinerama_info = vo_x11_update_screeninfo;
- ctx->border = vo_x11_border;
- ctx->check_events = vo_x11_check_events;
- ctx->fullscreen = vo_x11_fullscreen;
- ctx->ontop = vo_x11_ontop;
- ctx->vo_init = vo_x11_init;
- ctx->vo_uninit = vo_x11_uninit;
- break;
-#endif
-#ifdef CONFIG_GL_WAYLAND
- case GLTYPE_WAYLAND:
- ctx->priv = talloc_zero(ctx, struct egl_context);
- ctx->config_window = config_window_wayland;
- ctx->releaseGlContext = releaseGlContext_wayland;
- ctx->swapGlBuffers = swapGlBuffers_wayland;
- ctx->update_xinerama_info = vo_wayland_update_screeninfo;
- ctx->border = vo_wayland_border;
- ctx->check_events = vo_wayland_check_events;
- ctx->fullscreen = vo_wayland_fullscreen;
- ctx->ontop = vo_wayland_ontop;
- ctx->vo_init = vo_wayland_init;
- ctx->vo_uninit = vo_wayland_uninit;
- break;
-#endif
+ set_backend(ctx);
+ if (!ctx->vo_init(vo)) {
+ talloc_free(ctx);
+ ctx = NULL;
}
- if (ctx->vo_init && ctx->vo_init(vo))
- return ctx;
- talloc_free(ctx);
- return NULL;
+ return ctx;
+}
+
+MPGLContext *mpgl_init(struct vo *vo, const char *backend_name)
+{
+ MPGLContext *ctx = NULL;
+ int index = mpgl_find_backend(backend_name);
+ if (index == -1) {
+ for (const struct backend *entry = backends; entry->name; entry++) {
+ ctx = init_backend(vo, entry->init);
+ if (ctx)
+ return ctx;
+ }
+ } else if (index >= 0) {
+ ctx = init_backend(vo, backends[index].init);
+ }
+ return ctx;
}
bool mpgl_config_window(struct MPGLContext *ctx, int gl_caps, uint32_t d_width,
diff --git a/video/out/gl_common.h b/video/out/gl_common.h
index 0150e9319c..1f28d87855 100644
--- a/video/out/gl_common.h
+++ b/