summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/context_cocoa.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/opengl/context_cocoa.c')
-rw-r--r--video/out/opengl/context_cocoa.c181
1 files changed, 181 insertions, 0 deletions
diff --git a/video/out/opengl/context_cocoa.c b/video/out/opengl/context_cocoa.c
new file mode 100644
index 0000000000..1bcfa09755
--- /dev/null
+++ b/video/out/opengl/context_cocoa.c
@@ -0,0 +1,181 @@
+/*
+ * This file is part of mpv.
+ *
+ * mpv 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.
+ *
+ * mpv 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 mpv. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * 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 <OpenGL/OpenGL.h>
+#include <dlfcn.h>
+#include "video/out/cocoa_common.h"
+#include "osdep/macosx_versions.h"
+#include "context.h"
+
+struct cgl_context {
+ CGLPixelFormatObj pix;
+ CGLContextObj ctx;
+};
+
+static int set_swap_interval(int enabled)
+{
+ CGLContextObj ctx = CGLGetCurrentContext();
+ CGLError err = CGLSetParameter(ctx, kCGLCPSwapInterval, &enabled);
+ return (err == kCGLNoError) ? 0 : -1;
+}
+
+static int cgl_color_size(struct MPGLContext *ctx)
+{
+ struct cgl_context *p = ctx->priv;
+ GLint value;
+ CGLDescribePixelFormat(p->pix, 0, kCGLPFAColorSize, &value);
+ return value > 16 ? 8 : 5;
+}
+
+static void *cocoa_glgetaddr(const char *s)
+{
+ void *ret = NULL;
+ void *handle = dlopen(
+ "/System/Library/Frameworks/OpenGL.framework/OpenGL",
+ RTLD_LAZY | RTLD_LOCAL);
+ if (!handle)
+ return NULL;
+ ret = dlsym(handle, s);
+ dlclose(handle);
+ return ret;
+}
+
+static CGLError test_gl_version(struct vo *vo,
+ CGLContextObj *ctx,
+ CGLPixelFormatObj *pix,
+ CGLOpenGLProfile version)
+{
+ CGLPixelFormatAttribute attrs[] = {
+ kCGLPFAOpenGLProfile,
+ (CGLPixelFormatAttribute) version,
+ kCGLPFADoubleBuffer,
+ kCGLPFAAccelerated,
+ #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_8
+ // leave this as the last entry of the array to not break the fallback
+ // code
+ kCGLPFASupportsAutomaticGraphicsSwitching,
+ #endif
+ 0
+ };
+
+ GLint npix;
+ CGLError err;
+ err = CGLChoosePixelFormat(attrs, pix, &npix);
+ if (err == kCGLBadAttribute) {
+ // kCGLPFASupportsAutomaticGraphicsSwitching is probably not supported
+ // by the current hardware. Falling back to not using it.
+ attrs[MP_ARRAY_SIZE(attrs) - 2] = 0;
+ err = CGLChoosePixelFormat(attrs, pix, &npix);
+ }
+
+ if (err != kCGLNoError) {
+ MP_ERR(vo, "error creating CGL pixel format: %s (%d)\n",
+ CGLErrorString(err), err);
+ goto error_out;
+ }
+
+ err = CGLCreateContext(*pix, 0, ctx);
+
+error_out:
+ return err;
+}
+
+static bool create_gl_context(struct MPGLContext *ctx, int vo_flags)
+{
+ struct cgl_context *p = ctx->priv;
+ CGLError err;
+
+ CGLOpenGLProfile gl_versions[] = {
+ kCGLOGLPVersion_3_2_Core,
+ kCGLOGLPVersion_Legacy,
+ };
+
+ for (int n = 0; n < MP_ARRAY_SIZE(gl_versions); n++) {
+ err = test_gl_version(ctx->vo, &p->ctx, &p->pix, gl_versions[n]);
+ if (err == kCGLNoError)
+ break;
+ }
+
+ if (err != kCGLNoError) {
+ MP_FATAL(ctx->vo, "error creating CGL context: %s (%d)\n",
+ CGLErrorString(err), err);
+ return false;
+ }
+
+ vo_cocoa_set_opengl_ctx(ctx->vo, p->ctx);
+ CGLSetCurrentContext(p->ctx);
+
+ if (vo_flags & VOFLAG_ALPHA)
+ CGLSetParameter(p->ctx, kCGLCPSurfaceOpacity, &(GLint){0});
+
+ mpgl_load_functions(ctx->gl, (void *)cocoa_glgetaddr, NULL, ctx->vo->log);
+ ctx->gl->fb_r = ctx->gl->fb_g = ctx->gl->fb_b = cgl_color_size(ctx);
+
+ CGLReleasePixelFormat(p->pix);
+
+ return true;
+}
+
+static void cocoa_uninit(MPGLContext *ctx)
+{
+ struct cgl_context *p = ctx->priv;
+ CGLReleaseContext(p->ctx);
+ vo_cocoa_uninit(ctx->vo);
+}
+
+static int cocoa_init(MPGLContext *ctx, int vo_flags)
+{
+ vo_cocoa_init(ctx->vo);
+
+ if (!create_gl_context(ctx, vo_flags))
+ return -1;
+
+ ctx->gl->SwapInterval = set_swap_interval;
+ return 0;
+}
+
+static int cocoa_reconfig(struct MPGLContext *ctx)
+{
+ vo_cocoa_config_window(ctx->vo);
+ return 0;
+}
+
+static int cocoa_control(struct MPGLContext *ctx, int *events, int request,
+ void *arg)
+{
+ return vo_cocoa_control(ctx->vo, events, request, arg);
+}
+
+static void cocoa_swap_buffers(struct MPGLContext *ctx)
+{
+ vo_cocoa_swap_buffers(ctx->vo);
+}
+
+const struct mpgl_driver mpgl_driver_cocoa = {
+ .name = "cocoa",
+ .priv_size = sizeof(struct cgl_context),
+ .init = cocoa_init,
+ .reconfig = cocoa_reconfig,
+ .swap_buffers = cocoa_swap_buffers,
+ .control = cocoa_control,
+ .uninit = cocoa_uninit,
+}; \ No newline at end of file