mirror of
https://github.com/mpv-player/mpv
synced 2024-12-23 07:12:39 +00:00
cocoa: redo synchronization
Before this change, Cocoa state was accessed from both the VO and the Cocoa main thread. This was probably not a good idea. There was some locking as well as implicit synchronization using the dispatch mechanism, but it wasn't watertight. Change this completely. Now Cocoa things are always accessed from the main thread only. The old mutex falls away, as well as the vo_cocoa_set_current_context() function, which implicitly used the lock to coordinate VO accesses. With the new code, the VO thread generally has to wait for the main thread, while the main thread never waits for the VO and rarely accesses it. Fortunately, this is rather straight forward, and most of this is achieved by making vo_cocoa_control() run on the main thread. The logic of the code does generally not change. Some aspects are trickier. Apparently we can't access the NSOpenGLContext from the VO thread, because this object is not thread- safe. We use some CGLContextObj functions instead, such as for making the context current and swapping the buffers.
This commit is contained in:
parent
7e21f6fd00
commit
d89eb74cb7
@ -20,8 +20,11 @@
|
||||
#ifndef MPLAYER_COCOA_COMMON_H
|
||||
#define MPLAYER_COCOA_COMMON_H
|
||||
|
||||
#include "vo.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <OpenGL/OpenGL.h>
|
||||
|
||||
struct vo;
|
||||
struct vo_cocoa_state;
|
||||
|
||||
int vo_cocoa_init(struct vo *vo);
|
||||
@ -29,12 +32,9 @@ void vo_cocoa_uninit(struct vo *vo);
|
||||
|
||||
int vo_cocoa_config_window(struct vo *vo, uint32_t flags);
|
||||
|
||||
void vo_cocoa_set_current_context(struct vo *vo, bool current);
|
||||
void vo_cocoa_swap_buffers(struct vo *vo);
|
||||
int vo_cocoa_check_events(struct vo *vo);
|
||||
int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg);
|
||||
|
||||
void vo_cocoa_create_nsgl_ctx(struct vo *vo, void *ctx);
|
||||
void vo_cocoa_release_nsgl_ctx(struct vo *vo);
|
||||
void vo_cocoa_swap_buffers(struct vo *vo);
|
||||
void vo_cocoa_set_opengl_ctx(struct vo *vo, CGLContextObj ctx);
|
||||
|
||||
#endif /* MPLAYER_COCOA_COMMON_H */
|
||||
|
@ -30,6 +30,7 @@
|
||||
#import "video/out/cocoa/mpvadapter.h"
|
||||
|
||||
#include "osdep/threads.h"
|
||||
#include "osdep/atomics.h"
|
||||
#include "osdep/macosx_compat.h"
|
||||
#include "osdep/macosx_events_objc.h"
|
||||
|
||||
@ -48,18 +49,20 @@
|
||||
|
||||
#include "common/msg.h"
|
||||
|
||||
#define cocoa_lock(s) pthread_mutex_lock(&s->mutex)
|
||||
#define cocoa_unlock(s) pthread_mutex_unlock(&s->mutex)
|
||||
|
||||
static void vo_cocoa_fullscreen(struct vo *vo);
|
||||
static int vo_cocoa_fullscreen(struct vo *vo);
|
||||
static void cocoa_rm_fs_screen_profile_observer(struct vo_cocoa_state *s);
|
||||
|
||||
struct vo_cocoa_state {
|
||||
// --- The following members can be accessed only by the main thread (i.e.
|
||||
// where Cocoa runs), or if the main thread is fully blocked.
|
||||
|
||||
NSWindow *window;
|
||||
NSView *view;
|
||||
MpvVideoView *video;
|
||||
MpvCocoaAdapter *adapter;
|
||||
NSOpenGLContext *gl_ctx;
|
||||
|
||||
CGLContextObj cgl_ctx;
|
||||
NSOpenGLContext *nsgl_ctx;
|
||||
|
||||
NSScreen *current_screen;
|
||||
NSScreen *fs_screen;
|
||||
@ -67,19 +70,16 @@ struct vo_cocoa_state {
|
||||
|
||||
NSInteger window_level;
|
||||
|
||||
int pending_events;
|
||||
|
||||
bool waiting_frame;
|
||||
bool skip_swap_buffer;
|
||||
bool embedded; // wether we are embedding in another GUI
|
||||
|
||||
atomic_bool waiting_frame;
|
||||
|
||||
IOPMAssertionID power_mgmt_assertion;
|
||||
io_connect_t light_sensor;
|
||||
uint64_t last_lmuvalue;
|
||||
int last_lux;
|
||||
IONotificationPortRef light_sensor_io_port;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
struct mp_log *log;
|
||||
|
||||
uint32_t old_dwidth;
|
||||
@ -89,36 +89,26 @@ struct vo_cocoa_state {
|
||||
NSData *icc_fs_profile;
|
||||
id fs_icc_changed_ns_observer;
|
||||
|
||||
pthread_mutex_t resize_lock;
|
||||
pthread_cond_t resize_wakeup;
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t wakeup;
|
||||
|
||||
// --- The following members are protected by the lock.
|
||||
// If the VO and main threads are both blocked, locking is optional
|
||||
// for members accessed only by VO and main thread.
|
||||
|
||||
int pending_events;
|
||||
|
||||
int vo_dwidth; // current or soon-to-be VO size
|
||||
int vo_dheight;
|
||||
|
||||
// Protected by the resize_lock
|
||||
bool vo_ready; // the VO is in a state in which it can
|
||||
// render frames
|
||||
int frame_w, frame_h; // dimensions of the frame rendered
|
||||
};
|
||||
|
||||
static void with_cocoa_lock(struct vo_cocoa_state *s, void(^block)(void))
|
||||
static void run_on_main_thread(struct vo *vo, void(^block)(void))
|
||||
{
|
||||
cocoa_lock(s);
|
||||
block();
|
||||
cocoa_unlock(s);
|
||||
}
|
||||
|
||||
static void with_cocoa_lock_on_main_thread(struct vo *vo, void(^block)(void))
|
||||
{
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
with_cocoa_lock(s, block);
|
||||
});
|
||||
}
|
||||
|
||||
static void with_cocoa_lock_on_main_thread_sync(struct vo *vo, void(^block)(void))
|
||||
{
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
with_cocoa_lock(s, block);
|
||||
});
|
||||
dispatch_sync(dispatch_get_main_queue(), block);
|
||||
}
|
||||
|
||||
static void queue_new_video_size(struct vo *vo, int w, int h)
|
||||
@ -130,6 +120,16 @@ static void queue_new_video_size(struct vo *vo, int w, int h)
|
||||
}
|
||||
}
|
||||
|
||||
static void flag_events(struct vo *vo, int events)
|
||||
{
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
pthread_mutex_lock(&s->lock);
|
||||
s->pending_events |= events;
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
if (events)
|
||||
vo_wakeup(vo);
|
||||
}
|
||||
|
||||
static void enable_power_management(struct vo_cocoa_state *s)
|
||||
{
|
||||
if (!s->power_mgmt_assertion) return;
|
||||
@ -197,16 +197,14 @@ static void light_sensor_cb(void *ctx, io_service_t srv, natural_t mtype, void *
|
||||
if (s->last_lmuvalue != mean) {
|
||||
s->last_lmuvalue = mean;
|
||||
s->last_lux = lmuvalue_to_lux(s->last_lmuvalue);
|
||||
s->pending_events |= VO_EVENT_AMBIENT_LIGHTING_CHANGED;
|
||||
vo_wakeup(vo);
|
||||
return;
|
||||
flag_events(vo, VO_EVENT_AMBIENT_LIGHTING_CHANGED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cocoa_init_light_sensor(struct vo *vo)
|
||||
{
|
||||
with_cocoa_lock_on_main_thread(vo, ^{
|
||||
run_on_main_thread(vo, ^{
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
io_service_t srv = IOServiceGetMatchingService(
|
||||
kIOMasterPortDefault, IOServiceMatching("AppleLMUController"));
|
||||
@ -249,14 +247,12 @@ int vo_cocoa_init(struct vo *vo)
|
||||
{
|
||||
struct vo_cocoa_state *s = talloc_zero(NULL, struct vo_cocoa_state);
|
||||
*s = (struct vo_cocoa_state){
|
||||
.waiting_frame = false,
|
||||
.power_mgmt_assertion = kIOPMNullAssertionID,
|
||||
.log = mp_log_new(s, vo->log, "cocoa"),
|
||||
.embedded = vo->opts->WinID >= 0,
|
||||
};
|
||||
mpthread_mutex_init_recursive(&s->mutex);
|
||||
pthread_mutex_init(&s->resize_lock, NULL);
|
||||
pthread_cond_init(&s->resize_wakeup, NULL);
|
||||
pthread_mutex_init(&s->lock, NULL);
|
||||
pthread_cond_init(&s->wakeup, NULL);
|
||||
vo->cocoa = s;
|
||||
cocoa_init_light_sensor(vo);
|
||||
return 1;
|
||||
@ -286,17 +282,18 @@ void vo_cocoa_uninit(struct vo *vo)
|
||||
{
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
|
||||
pthread_mutex_lock(&s->resize_lock);
|
||||
pthread_mutex_lock(&s->lock);
|
||||
s->vo_ready = false;
|
||||
pthread_cond_signal(&s->resize_wakeup);
|
||||
pthread_mutex_unlock(&s->resize_lock);
|
||||
pthread_cond_signal(&s->wakeup);
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
with_cocoa_lock_on_main_thread_sync(vo, ^{
|
||||
run_on_main_thread(vo, ^{
|
||||
enable_power_management(s);
|
||||
cocoa_uninit_light_sensor(s);
|
||||
cocoa_rm_fs_screen_profile_observer(s);
|
||||
|
||||
[s->gl_ctx release];
|
||||
[s->nsgl_ctx release];
|
||||
CGLReleaseContext(s->cgl_ctx);
|
||||
|
||||
// needed to stop resize events triggered by the event's view -clear
|
||||
// causing many uses after free
|
||||
@ -310,6 +307,8 @@ void vo_cocoa_uninit(struct vo *vo)
|
||||
if (s->window)
|
||||
[s->window release];
|
||||
|
||||
pthread_cond_destroy(&s->wakeup);
|
||||
pthread_mutex_destroy(&s->lock);
|
||||
talloc_free(s);
|
||||
});
|
||||
}
|
||||
@ -369,7 +368,7 @@ static void vo_cocoa_update_screen_fps(struct vo *vo)
|
||||
CVDisplayLinkRelease(link);
|
||||
}
|
||||
|
||||
s->pending_events |= VO_EVENT_WIN_STATE;
|
||||
flag_events(vo, VO_EVENT_WIN_STATE);
|
||||
}
|
||||
|
||||
static void vo_cocoa_update_screen_info(struct vo *vo, struct mp_rect *out_rc)
|
||||
@ -388,15 +387,6 @@ static void vo_cocoa_update_screen_info(struct vo *vo, struct mp_rect *out_rc)
|
||||
}
|
||||
}
|
||||
|
||||
static void resize_window(struct vo *vo)
|
||||
{
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
NSRect frame = [s->video frameInPixels];
|
||||
vo->dwidth = frame.size.width;
|
||||
vo->dheight = frame.size.height;
|
||||
[s->gl_ctx update];
|
||||
}
|
||||
|
||||
static void vo_set_level(struct vo *vo, int ontop)
|
||||
{
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
@ -484,7 +474,7 @@ static void create_ui(struct vo *vo, struct mp_rect *win, int geo_flags)
|
||||
[s->video setWantsBestResolutionOpenGLSurface:YES];
|
||||
|
||||
[s->view addSubview:s->video];
|
||||
[s->gl_ctx setView:s->video];
|
||||
[s->nsgl_ctx setView:s->video];
|
||||
[s->video release];
|
||||
|
||||
s->video.adapter = adapter;
|
||||
@ -532,7 +522,7 @@ static void cocoa_add_fs_screen_profile_observer(struct vo *vo)
|
||||
return;
|
||||
|
||||
void (^nblock)(NSNotification *n) = ^(NSNotification *n) {
|
||||
s->pending_events |= VO_EVENT_ICC_PROFILE_CHANGED;
|
||||
flag_events(vo, VO_EVENT_ICC_PROFILE_CHANGED);
|
||||
};
|
||||
|
||||
s->fs_icc_changed_ns_observer = [[NSNotificationCenter defaultCenter]
|
||||
@ -542,24 +532,19 @@ static void cocoa_add_fs_screen_profile_observer(struct vo *vo)
|
||||
usingBlock:nblock];
|
||||
}
|
||||
|
||||
void vo_cocoa_create_nsgl_ctx(struct vo *vo, void *ctx)
|
||||
void vo_cocoa_set_opengl_ctx(struct vo *vo, CGLContextObj 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];
|
||||
s->gl_ctx = nil;
|
||||
run_on_main_thread(vo, ^{
|
||||
s->cgl_ctx = CGLRetainContext(ctx);
|
||||
s->nsgl_ctx = [[NSOpenGLContext alloc] initWithCGLContextObj:s->cgl_ctx];
|
||||
});
|
||||
}
|
||||
|
||||
int vo_cocoa_config_window(struct vo *vo, uint32_t flags)
|
||||
{
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
with_cocoa_lock_on_main_thread(vo, ^{
|
||||
run_on_main_thread(vo, ^{
|
||||
struct mp_rect screenrc;
|
||||
vo_cocoa_update_screen_info(vo, &screenrc);
|
||||
|
||||
@ -587,67 +572,73 @@ int vo_cocoa_config_window(struct vo *vo, uint32_t flags)
|
||||
vo_set_level(vo, vo->opts->ontop);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&s->resize_lock);
|
||||
s->vo_ready = true;
|
||||
pthread_mutex_unlock(&s->resize_lock);
|
||||
|
||||
// trigger a resize -> don't set vo->dwidth and vo->dheight directly
|
||||
// since this block is executed asynchronously to the video
|
||||
// reconfiguration code.
|
||||
s->pending_events |= VO_EVENT_RESIZE;
|
||||
// Use the actual size of the new window
|
||||
NSRect frame = [s->video frameInPixels];
|
||||
vo->dwidth = s->vo_dwidth = frame.size.width;
|
||||
vo->dheight = s->vo_dheight = frame.size.height;
|
||||
|
||||
[s->nsgl_ctx update];
|
||||
|
||||
if (!s->embedded) {
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
set_application_icon(NSApp);
|
||||
}
|
||||
});
|
||||
|
||||
if (!s->embedded) {
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
set_application_icon(NSApp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vo_cocoa_set_current_context(struct vo *vo, bool current)
|
||||
// Trigger a VO resize - called from the main thread. This is done async,
|
||||
// because the VO must resize and redraw while vo_cocoa_resize_redraw() is
|
||||
// blocking.
|
||||
static void resize_event(struct vo *vo)
|
||||
{
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
NSRect frame = [s->video frameInPixels];
|
||||
|
||||
if (current) {
|
||||
cocoa_lock(s);
|
||||
if (s->gl_ctx) [s->gl_ctx makeCurrentContext];
|
||||
} else {
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
cocoa_unlock(s);
|
||||
}
|
||||
pthread_mutex_lock(&s->lock);
|
||||
s->vo_dwidth = frame.size.width;
|
||||
s->vo_dheight = frame.size.height;
|
||||
s->pending_events |= VO_EVENT_RESIZE | VO_EVENT_EXPOSE;
|
||||
// Live-resizing: make sure at least one frame will be drawn
|
||||
s->frame_w = s->frame_h = 0;
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
[s->nsgl_ctx update];
|
||||
|
||||
vo_wakeup(vo);
|
||||
}
|
||||
|
||||
static void vo_cocoa_resize_redraw(struct vo *vo, int width, int height)
|
||||
{
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
|
||||
struct timespec e = mp_time_us_to_timespec(mp_add_timeout(mp_time_us(), 0.1));
|
||||
resize_event(vo);
|
||||
|
||||
pthread_mutex_lock(&s->resize_lock);
|
||||
pthread_mutex_lock(&s->lock);
|
||||
|
||||
// Make sure at least one frame will be drawn
|
||||
s->frame_w = s->frame_h = 0;
|
||||
|
||||
s->pending_events |= VO_EVENT_RESIZE | VO_EVENT_EXPOSE;
|
||||
// Make vo.c not do video timing, which would slow down resizing.
|
||||
vo_event(vo, VO_EVENT_LIVE_RESIZING);
|
||||
|
||||
// Wait until a new frame with the new size was rendered. For some reason,
|
||||
// Cocoa requires this to be done before drawRect() returns.
|
||||
struct timespec e = mp_time_us_to_timespec(mp_add_timeout(mp_time_us(), 0.1));
|
||||
while (s->frame_w != width && s->frame_h != height && s->vo_ready) {
|
||||
if (pthread_cond_timedwait(&s->resize_wakeup, &s->resize_lock, &e))
|
||||
if (pthread_cond_timedwait(&s->wakeup, &s->lock, &e))
|
||||
break;
|
||||
}
|
||||
|
||||
vo_query_and_reset_events(vo, VO_EVENT_LIVE_RESIZING);
|
||||
|
||||
pthread_mutex_unlock(&s->resize_lock);
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
}
|
||||
|
||||
static void draw_changes_after_next_frame(struct vo *vo)
|
||||
{
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
if (!s->waiting_frame) {
|
||||
s->waiting_frame = true;
|
||||
if (atomic_compare_exchange_strong(&s->waiting_frame, &(bool){false}, true))
|
||||
NSDisableScreenUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
void vo_cocoa_swap_buffers(struct vo *vo)
|
||||
@ -655,57 +646,47 @@ void vo_cocoa_swap_buffers(struct vo *vo)
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
|
||||
// Don't swap a frame with wrong size
|
||||
if (s->pending_events & VO_EVENT_RESIZE)
|
||||
pthread_mutex_lock(&s->lock);
|
||||
bool skip = s->pending_events & VO_EVENT_RESIZE;
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
if (skip)
|
||||
return;
|
||||
|
||||
[s->gl_ctx flushBuffer];
|
||||
CGLFlushDrawable(s->cgl_ctx);
|
||||
|
||||
pthread_mutex_lock(&s->resize_lock);
|
||||
pthread_mutex_lock(&s->lock);
|
||||
s->frame_w = vo->dwidth;
|
||||
s->frame_h = vo->dheight;
|
||||
pthread_cond_signal(&s->resize_wakeup);
|
||||
pthread_mutex_unlock(&s->resize_lock);
|
||||
pthread_cond_signal(&s->wakeup);
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
if (s->waiting_frame) {
|
||||
s->waiting_frame = false;
|
||||
if (atomic_compare_exchange_strong(&s->waiting_frame, &(bool){true}, false))
|
||||
NSEnableScreenUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
int vo_cocoa_check_events(struct vo *vo)
|
||||
static int vo_cocoa_check_events(struct vo *vo)
|
||||
{
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
int events = s->pending_events;
|
||||
s->pending_events = 0;
|
||||
|
||||
if (events & VO_EVENT_RESIZE) {
|
||||
resize_window(vo);
|
||||
vo->dwidth = s->vo_dwidth;
|
||||
vo->dheight = s->vo_dheight;
|
||||
}
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
static int vo_cocoa_fullscreen_sync(struct vo *vo)
|
||||
{
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
|
||||
if (s->embedded)
|
||||
return VO_NOTIMPL;
|
||||
|
||||
with_cocoa_lock_on_main_thread(vo, ^{
|
||||
vo_cocoa_fullscreen(vo);
|
||||
});
|
||||
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void vo_cocoa_fullscreen(struct vo *vo)
|
||||
static int vo_cocoa_fullscreen(struct vo *vo)
|
||||
{
|
||||
struct vo_cocoa_state *s = vo->cocoa;
|
||||
struct mp_vo_opts *opts = vo->opts;
|
||||
|
||||
if (s->embedded)
|
||||
return;
|
||||
return VO_NOTIMPL;
|
||||
|
||||
vo_cocoa_update_screen_info(vo, NULL);
|
||||
|
||||
@ -719,8 +700,10 @@ static void vo_cocoa_fullscreen(struct vo *vo)
|
||||
[[s->view window] setDelegate:s->adapter];
|
||||
}
|
||||
|
||||
s->pending_events |= VO_EVENT_ICC_PROFILE_CHANGED;
|
||||
s->pending_events |= VO_EVENT_RESIZE;
|
||||
flag_events(vo, VO_EVENT_ICC_PROFILE_CHANGED);
|
||||
resize_event(vo);
|
||||
|
||||
return VO_TRUE;
|
||||
}
|
||||
|
||||
static void vo_cocoa_control_get_icc_profile(struct vo *vo, void *arg)
|
||||
@ -737,26 +720,21 @@ static void vo_cocoa_control_get_icc_profile(struct vo *vo, void *arg)
|
||||
p->len = [profile length];
|
||||
}
|
||||
|
||||
int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
|
||||
static int vo_cocoa_control_on_main_thread(struct vo *vo, int request, void *arg)
|
||||
{
|
||||
struct mp_vo_opts *opts = vo->opts;
|
||||
|
||||
switch (request) {
|
||||
case VOCTRL_CHECK_EVENTS:
|
||||
*events |= vo_cocoa_check_events(vo);
|
||||
return VO_TRUE;
|
||||
case VOCTRL_FULLSCREEN:
|
||||
opts->fullscreen = !opts->fullscreen;
|
||||
return vo_cocoa_fullscreen_sync(vo);
|
||||
return vo_cocoa_fullscreen(vo);
|
||||
case VOCTRL_ONTOP:
|
||||
return vo_cocoa_ontop(vo);
|
||||
case VOCTRL_GET_UNFS_WINDOW_SIZE: {
|
||||
int *s = arg;
|
||||
with_cocoa_lock(vo->cocoa, ^{
|
||||
NSSize size = [vo->cocoa->view frame].size;
|
||||
s[0] = size.width;
|
||||
s[1] = size.height;
|
||||
});
|
||||
NSSize size = [vo->cocoa->view frame].size;
|
||||
s[0] = size.width;
|
||||
s[1] = size.height;
|
||||
return VO_TRUE;
|
||||
}
|
||||
case VOCTRL_SET_UNFS_WINDOW_SIZE: {
|
||||
@ -764,16 +742,12 @@ int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
|
||||
int w, h;
|
||||
w = s[0];
|
||||
h = s[1];
|
||||
with_cocoa_lock_on_main_thread(vo, ^{
|
||||
queue_new_video_size(vo, w, h);
|
||||
});
|
||||
queue_new_video_size(vo, w, h);
|
||||
return VO_TRUE;
|
||||
}
|
||||
case VOCTRL_GET_WIN_STATE: {
|
||||
with_cocoa_lock(vo->cocoa, ^{
|
||||
const bool minimized = [[vo->cocoa->view window] isMiniaturized];
|
||||
*(int *)arg = minimized ? VO_WIN_STATE_MINIMIZED : 0;
|
||||
});
|
||||
const bool minimized = [[vo->cocoa->view window] isMiniaturized];
|
||||
*(int *)arg = minimized ? VO_WIN_STATE_MINIMIZED : 0;
|
||||
return VO_TRUE;
|
||||
}
|
||||
case VOCTRL_SET_CURSOR_VISIBILITY:
|
||||
@ -805,12 +779,35 @@ int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
|
||||
return VO_NOTIMPL;
|
||||
}
|
||||
|
||||
static int vo_cocoa_control_async(struct vo *vo, int *events, int request, void *arg)
|
||||
{
|
||||
switch (request) {
|
||||
case VOCTRL_CHECK_EVENTS:
|
||||
*events |= vo_cocoa_check_events(vo);
|
||||
return VO_TRUE;
|
||||
case VOCTRL_GET_RECENT_FLIP_TIME:
|
||||
return VO_FALSE; // unsupported, but avoid syncing with main thread
|
||||
}
|
||||
return VO_NOTIMPL;
|
||||
}
|
||||
|
||||
int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
|
||||
{
|
||||
__block int r = vo_cocoa_control_async(vo, events, request, arg);
|
||||
if (r == VO_NOTIMPL) {
|
||||
run_on_main_thread(vo, ^{
|
||||
r = vo_cocoa_control_on_main_thread(vo, request, arg);
|
||||
});
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@implementation MpvCocoaAdapter
|
||||
@synthesize vout = _video_output;
|
||||
|
||||
- (void)performAsyncResize:(NSSize)size {
|
||||
struct vo_cocoa_state *s = self.vout->cocoa;
|
||||
if (!s->waiting_frame)
|
||||
if (!atomic_load(&s->waiting_frame))
|
||||
vo_cocoa_resize_redraw(self.vout, size.width, size.height);
|
||||
}
|
||||
|
||||
@ -823,9 +820,7 @@ int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
|
||||
}
|
||||
|
||||
- (void)setNeedsResize {
|
||||
struct vo_cocoa_state *s = self.vout->cocoa;
|
||||
s->pending_events |= VO_EVENT_RESIZE;
|
||||
vo_wakeup(self.vout);
|
||||
resize_event(self.vout);
|
||||
}
|
||||
|
||||
- (void)recalcMovableByWindowBackground:(NSPoint)p
|
||||
@ -887,8 +882,7 @@ int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
|
||||
|
||||
- (void)didChangeWindowedScreenProfile:(NSScreen *)screen
|
||||
{
|
||||
struct vo_cocoa_state *s = self.vout->cocoa;
|
||||
s->pending_events |= VO_EVENT_ICC_PROFILE_CHANGED;
|
||||
flag_events(self.vout, VO_EVENT_ICC_PROFILE_CHANGED);
|
||||
}
|
||||
|
||||
- (void)didChangeMousePosition
|
||||
@ -909,14 +903,12 @@ int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
|
||||
|
||||
- (void)windowDidMiniaturize:(NSNotification *)notification
|
||||
{
|
||||
struct vo_cocoa_state *s = self.vout->cocoa;
|
||||
s->pending_events |= VO_EVENT_WIN_STATE;
|
||||
flag_events(self.vout, VO_EVENT_WIN_STATE);
|
||||
}
|
||||
|
||||
- (void)windowDidDeminiaturize:(NSNotification *)notification
|
||||
{
|
||||
struct vo_cocoa_state *s = self.vout->cocoa;
|
||||
s->pending_events |= VO_EVENT_WIN_STATE;
|
||||
flag_events(self.vout, VO_EVENT_WIN_STATE);
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -121,7 +121,9 @@ static bool create_gl_context(struct MPGLContext *ctx)
|
||||
return false;
|
||||
}
|
||||
|
||||
vo_cocoa_create_nsgl_ctx(ctx->vo, p->ctx);
|
||||
vo_cocoa_set_opengl_ctx(ctx->vo, p->ctx);
|
||||
CGLSetCurrentContext(p->ctx);
|
||||
|
||||
ctx->depth_r = ctx->depth_g = ctx->depth_b = cgl_color_size(ctx);
|
||||
mpgl_load_functions(ctx->gl, (void *)cocoa_glgetaddr, NULL, ctx->vo->log);
|
||||
|
||||
@ -149,7 +151,6 @@ 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);
|
||||
}
|
||||
|
||||
@ -158,11 +159,6 @@ static void swapGlBuffers_cocoa(MPGLContext *ctx)
|
||||
vo_cocoa_swap_buffers(ctx->vo);
|
||||
}
|
||||
|
||||
static void set_current_cocoa(MPGLContext *ctx, bool current)
|
||||
{
|
||||
vo_cocoa_set_current_context(ctx->vo, current);
|
||||
}
|
||||
|
||||
void mpgl_set_backend_cocoa(MPGLContext *ctx)
|
||||
{
|
||||
ctx->priv = talloc_zero(ctx, struct cgl_context);
|
||||
@ -172,5 +168,4 @@ void mpgl_set_backend_cocoa(MPGLContext *ctx)
|
||||
ctx->vo_init = vo_cocoa_init;
|
||||
ctx->vo_uninit = vo_cocoa_uninit;
|
||||
ctx->vo_control = vo_cocoa_control;
|
||||
ctx->set_current = set_current_cocoa;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user