mirror of
https://github.com/mpv-player/mpv
synced 2025-01-31 20:21:49 +00:00
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:
parent
469ec23f85
commit
b5bbb49a1a
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user