From b5bbb49a1af7b0b167987f3b638d99baeb6a36bf Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 8 Jul 2014 08:17:15 +0200 Subject: cocoa: move CGL context creation to gl_cocoa This approach is similar to what other vo_opengl backends do. It can also be used in the future to create another cocoa backend that renders offscreen with IOSurfaces or FBOs. --- video/out/cocoa_common.h | 9 ++-- video/out/cocoa_common.m | 127 ++++++----------------------------------------- video/out/gl_cocoa.c | 106 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 118 insertions(+), 124 deletions(-) diff --git a/video/out/cocoa_common.h b/video/out/cocoa_common.h index e0696eb24a..8e59ab6764 100644 --- a/video/out/cocoa_common.h +++ b/video/out/cocoa_common.h @@ -29,7 +29,7 @@ void *vo_cocoa_glgetaddr(const char *s); int vo_cocoa_init(struct vo *vo); void vo_cocoa_uninit(struct vo *vo); -int vo_cocoa_config_window(struct vo *vo, uint32_t flags, int gl3profile); +int vo_cocoa_config_window(struct vo *vo, uint32_t flags, void *gl_ctx); void vo_cocoa_set_current_context(struct vo *vo, bool current); void vo_cocoa_swap_buffers(struct vo *vo); @@ -42,11 +42,10 @@ void vo_cocoa_register_resize_callback(struct vo *vo, void vo_cocoa_register_gl_clear_callback(struct vo *vo, void *ctx, void (*cb)(void *ctx)); -// returns an int to conform to the gl extensions from other platforms -int vo_cocoa_swap_interval(int enabled); - void *vo_cocoa_cgl_context(struct vo *vo); void *vo_cocoa_cgl_pixel_format(struct vo *vo); -int vo_cocoa_cgl_color_size(struct vo *vo); + +void vo_cocoa_create_nsgl_ctx(struct vo *vo, void *ctx); +void vo_cocoa_release_nsgl_ctx(struct vo *vo); #endif /* MPLAYER_COCOA_COMMON_H */ diff --git a/video/out/cocoa_common.m b/video/out/cocoa_common.m index 1e0b7abda5..2a699b8d51 100644 --- a/video/out/cocoa_common.m +++ b/video/out/cocoa_common.m @@ -177,9 +177,6 @@ void vo_cocoa_uninit(struct vo *vo) [s->window release]; s->window = nil; - [s->gl_ctx release]; - s->gl_ctx = nil; - [s->lock release]; s->lock = nil; }); @@ -330,66 +327,6 @@ static void create_window(struct vo *vo, struct mp_rect *win, int geo_flags) } } -static CGLOpenGLProfile cgl_profile(int gl3profile) { - if (gl3profile) { - return kCGLOGLPVersion_3_2_Core; - } else { - return kCGLOGLPVersion_Legacy; - } -} - -static int create_gl_context(struct vo *vo, int gl3profile) -{ - struct vo_cocoa_state *s = vo->cocoa; - CGLError err; - - CGLPixelFormatAttribute attrs[] = { - kCGLPFAOpenGLProfile, - (CGLPixelFormatAttribute) cgl_profile(gl3profile), - 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 - }; - - CGLPixelFormatObj pix; - GLint npix; - - err = CGLChoosePixelFormat(attrs, &pix, &npix); - if (err == kCGLBadAttribute) { - // kCGLPFASupportsAutomaticGraphicsSwitching is probably not supported - // by the current hardware. Falling back to not using it. - MP_ERR(vo, "error creating CGL pixel format with automatic GPU " - "switching. falling back\n"); - attrs[MP_ARRAY_SIZE(attrs) - 2] = 0; - err = CGLChoosePixelFormat(attrs, &pix, &npix); - } - - if (err != kCGLNoError) { - MP_FATAL(s, "error creating CGL pixel format: %s (%d)\n", - CGLErrorString(err), err); - } - - CGLContextObj ctx; - if ((err = CGLCreateContext(pix, 0, &ctx)) != kCGLNoError) { - MP_FATAL(s, "error creating CGL context: %s (%d)\n", - CGLErrorString(err), err); - return -1; - } - - s->gl_ctx = [[NSOpenGLContext alloc] initWithCGLContextObj:ctx]; - [s->gl_ctx makeCurrentContext]; - - CGLReleasePixelFormat(pix); - CGLReleaseContext(ctx); - - return 0; -} - static void cocoa_set_window_title(struct vo *vo, const char *title) { struct vo_cocoa_state *s = vo->cocoa; @@ -452,7 +389,20 @@ static void cocoa_add_fs_screen_profile_observer(struct vo *vo) usingBlock:nblock]; } -int vo_cocoa_config_window(struct vo *vo, uint32_t flags, int gl3profile) +void vo_cocoa_create_nsgl_ctx(struct vo *vo, void *ctx) +{ + struct vo_cocoa_state *s = vo->cocoa; + s->gl_ctx = [[NSOpenGLContext alloc] initWithCGLContextObj:ctx]; + [s->gl_ctx makeCurrentContext]; +} + +void vo_cocoa_release_nsgl_ctx(struct vo *vo) +{ + struct vo_cocoa_state *s = vo->cocoa; + [s->gl_ctx release]; +} + +int vo_cocoa_config_window(struct vo *vo, uint32_t flags, void *gl_ctx) { struct vo_cocoa_state *s = vo->cocoa; __block int ctxok = 0; @@ -474,30 +424,8 @@ int vo_cocoa_config_window(struct vo *vo, uint32_t flags, int gl3profile) s->old_dwidth = width; s->old_dheight = height; - if (flags & VOFLAG_HIDDEN) { - // This is certainly the first execution of vo_config_window and - // is called in order for an OpenGL based VO to perform detection - // of OpenGL extensions. On OSX to accomplish this task we are - // allowed only create a OpenGL context without attaching it to - // a drawable. - ctxok = create_gl_context(vo, gl3profile); - if (ctxok < 0) return; - } else if (!s->gl_ctx || !s->window) { - // Either gl_ctx+window or window alone is not created. - // Handle each of them independently. This is to handle correctly - // both VOs like vo_corevideo who skip the the OpenGL detection - // phase completly and generic OpenGL VOs who use VOFLAG_HIDDEN. - if (!s->gl_ctx) { - ctxok = create_gl_context(vo, gl3profile); - if (ctxok < 0) return; - } - - if (!s->window) - create_window(vo, &geo.win, geo.flags); - } - - if (s->window) { - // Everything is properly initialized + if (!(flags & VOFLAG_HIDDEN) && !s->window) { + create_window(vo, &geo.win, geo.flags); if (reset_size) [s->window queueNewVideoSize:NSMakeSize(width, height)]; cocoa_set_window_title(vo, vo_get_window_title(vo)); @@ -751,13 +679,6 @@ int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg) return VO_NOTIMPL; } -int vo_cocoa_swap_interval(int enabled) -{ - [[NSOpenGLContext currentContext] setValues:&enabled - forParameter:NSOpenGLCPSwapInterval]; - return 0; -} - void *vo_cocoa_cgl_context(struct vo *vo) { struct vo_cocoa_state *s = vo->cocoa; @@ -769,22 +690,6 @@ void *vo_cocoa_cgl_pixel_format(struct vo *vo) return CGLGetPixelFormat(vo_cocoa_cgl_context(vo)); } -int vo_cocoa_cgl_color_size(struct vo *vo) -{ - GLint value; - CGLDescribePixelFormat(vo_cocoa_cgl_pixel_format(vo), 0, - kCGLPFAColorSize, &value); - switch (value) { - case 32: - case 24: - return 8; - case 16: - return 5; - } - - return 8; -} - @implementation MpvCocoaAdapter @synthesize vout = _video_output; diff --git a/video/out/gl_cocoa.c b/video/out/gl_cocoa.c index 77f416135f..a32ba8f23d 100644 --- a/video/out/gl_cocoa.c +++ b/video/out/gl_cocoa.c @@ -19,9 +19,15 @@ * version 2.1 of the License, or (at your option) any later version. */ +#include #include "cocoa_common.h" #include "gl_common.h" +struct cgl_context { + CGLPixelFormatObj pix; + CGLContextObj ctx; +}; + static void gl_clear(void *ctx) { struct GL *gl = ctx; @@ -29,22 +35,102 @@ static void gl_clear(void *ctx) gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } -static bool config_window_cocoa(struct MPGLContext *ctx, int flags) +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) { - int rv = vo_cocoa_config_window(ctx->vo, flags, - ctx->requested_gl_version >= MPGL_VER(3, 0)); - if (rv != 0) + struct cgl_context *p = ctx->priv; + GLint value; + CGLDescribePixelFormat(p->pix, 0, kCGLPFAColorSize, &value); + switch (value) { + case 32: + case 24: + return 8; + case 16: + return 5; + default: + return 8; + } +} + +static bool create_gl_context(struct MPGLContext *ctx) +{ + struct cgl_context *p = ctx->priv; + CGLError err; + + CGLOpenGLProfile gl_vers_map[] = { + [2] = kCGLOGLPVersion_Legacy, + [3] = kCGLOGLPVersion_GL3_Core, + [4] = kCGLOGLPVersion_GL4_Core, + }; + + int gl_major = MPGL_VER_GET_MAJOR(ctx->requested_gl_version); + if (gl_major < 2 || gl_major >= MP_ARRAY_SIZE(gl_vers_map)) { + MP_FATAL(ctx->vo, "OpenGL major version %d not supported", gl_major); + return false; + } + + CGLPixelFormatAttribute attrs[] = { + kCGLPFAOpenGLProfile, + (CGLPixelFormatAttribute) gl_vers_map[gl_major], + 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; + err = CGLChoosePixelFormat(attrs, &p->pix, &npix); + if (err == kCGLBadAttribute) { + // kCGLPFASupportsAutomaticGraphicsSwitching is probably not supported + // by the current hardware. Falling back to not using it. + MP_ERR(ctx->vo, "error creating CGL pixel format with automatic GPU " + "switching. falling back\n"); + attrs[MP_ARRAY_SIZE(attrs) - 2] = 0; + err = CGLChoosePixelFormat(attrs, &p->pix, &npix); + } + + if (err != kCGLNoError) { + MP_FATAL(ctx->vo, "error creating CGL pixel format: %s (%d)\n", + CGLErrorString(err), err); + } + + if ((err = CGLCreateContext(p->pix, 0, &p->ctx)) != kCGLNoError) { + MP_FATAL(ctx->vo, "error creating CGL context: %s (%d)\n", + CGLErrorString(err), err); return false; + } + vo_cocoa_create_nsgl_ctx(ctx->vo, p->ctx); + ctx->depth_r = ctx->depth_g = ctx->depth_b = cgl_color_size(ctx); mpgl_load_functions(ctx->gl, (void *)vo_cocoa_glgetaddr, NULL, ctx->vo->log); - 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); + CGLReleasePixelFormat(p->pix); + + return true; +} + +static bool config_window_cocoa(struct MPGLContext *ctx, int flags) +{ + struct cgl_context *p = ctx->priv; + + if (p->ctx == NULL) + if (!create_gl_context(ctx)) + return false; if (!ctx->gl->SwapInterval) - ctx->gl->SwapInterval = vo_cocoa_swap_interval; + ctx->gl->SwapInterval = set_swap_interval; + vo_cocoa_config_window(ctx->vo, flags, p->ctx); vo_cocoa_register_gl_clear_callback(ctx->vo, ctx->gl, gl_clear); return true; @@ -52,6 +138,9 @@ static bool config_window_cocoa(struct MPGLContext *ctx, int flags) static void releaseGlContext_cocoa(MPGLContext *ctx) { + struct cgl_context *p = ctx->priv; + vo_cocoa_release_nsgl_ctx(ctx->vo); + CGLReleaseContext(p->ctx); } static void swapGlBuffers_cocoa(MPGLContext *ctx) @@ -66,6 +155,7 @@ static void set_current_cocoa(MPGLContext *ctx, bool current) void mpgl_set_backend_cocoa(MPGLContext *ctx) { + ctx->priv = talloc_zero(ctx, struct cgl_context); ctx->config_window = config_window_cocoa; ctx->releaseGlContext = releaseGlContext_cocoa; ctx->swapGlBuffers = swapGlBuffers_cocoa; -- cgit v1.2.3