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.
This commit is contained in:
Stefano Pigozzi 2014-07-08 08:17:15 +02:00
parent 469ec23f85
commit b5bbb49a1a
3 changed files with 119 additions and 125 deletions

View File

@ -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 */

View File

@ -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;

View File

@ -19,9 +19,15 @@
* version 2.1 of the License, or (at your option) any later version.
*/
#include <OpenGL/OpenGL.h>
#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)
{
int rv = vo_cocoa_config_window(ctx->vo, flags,
ctx->requested_gl_version >= MPGL_VER(3, 0));
if (rv != 0)
return false;
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);
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;