mirror of
https://github.com/mpv-player/mpv.git
synced 2026-10-23 19:38:51 +08:00
cocoa: remove OpenGL cocoa backend
the OpenGL cocoa backend was deprecated in 0.29, it has lot of bugs, is completely unmaintained and can't properly playback anything anymore on the newest macOS. it is time to remove it.
This commit is contained in:
@@ -117,6 +117,7 @@ Interface changes
|
||||
- add `--target-gamut`
|
||||
- change the way display names are retrieved on macOS, usage of options and properties
|
||||
`--fs-screen-name`, `--screen-name` and `display-names` needs to be adjusted
|
||||
- remove OpenGL cocoa backend that was deprecated in 0.29
|
||||
--- mpv 0.36.0 ---
|
||||
- add `--target-contrast`
|
||||
- Target luminance value is now also applied when ICC profile is used.
|
||||
|
||||
+3
-8
@@ -388,11 +388,7 @@ if features['cocoa']
|
||||
'osdep/macosx_events.m',
|
||||
'osdep/macosx_menubar.m',
|
||||
'osdep/main-fn-cocoa.c',
|
||||
'osdep/path-macosx.m',
|
||||
'video/out/cocoa_common.m',
|
||||
'video/out/cocoa/events_view.m',
|
||||
'video/out/cocoa/video_view.m',
|
||||
'video/out/cocoa/window.m')
|
||||
'osdep/path-macosx.m')
|
||||
endif
|
||||
|
||||
if posix
|
||||
@@ -1079,7 +1075,6 @@ features += {'gl-cocoa': gl_cocoa.allowed()}
|
||||
if features['gl-cocoa']
|
||||
dependencies += GL
|
||||
features += {'gl': true}
|
||||
sources += files('video/out/opengl/context_cocoa.c')
|
||||
endif
|
||||
|
||||
gl_win32 = get_option('gl-win32').require(
|
||||
@@ -1517,8 +1512,8 @@ if features['cocoa'] and features['swift']
|
||||
endif
|
||||
|
||||
macos_cocoa_cb = get_option('macos-cocoa-cb').require(
|
||||
features['cocoa'] and features['swift'],
|
||||
error_message: 'Either cocoa or swift could not be found!',
|
||||
features['cocoa'] and features['gl-cocoa'] and features['swift'],
|
||||
error_message: 'Either cocoa, gl-cocoa or swift could not be found!',
|
||||
)
|
||||
features += {'macos-cocoa-cb': macos_cocoa_cb.allowed()}
|
||||
if features['macos-cocoa-cb']
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it 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.
|
||||
*
|
||||
* 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "video/out/cocoa/mpvadapter.h"
|
||||
|
||||
@interface MpvEventsView : NSView <NSDraggingDestination>
|
||||
@property(nonatomic, retain) MpvCocoaAdapter *adapter;
|
||||
- (BOOL)canHideCursor;
|
||||
@end
|
||||
@@ -1,342 +0,0 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it 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.
|
||||
*
|
||||
* 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "input/input.h"
|
||||
#include "input/keycodes.h"
|
||||
|
||||
#include "video/out/cocoa_common.h"
|
||||
#include "events_view.h"
|
||||
|
||||
@interface MpvEventsView()
|
||||
@property(nonatomic, assign) BOOL hasMouseDown;
|
||||
@property(nonatomic, retain) NSTrackingArea *tracker;
|
||||
- (int)mpvButtonNumber:(NSEvent*)event;
|
||||
- (void)mouseDownEvent:(NSEvent *)event;
|
||||
- (void)mouseUpEvent:(NSEvent *)event;
|
||||
@end
|
||||
|
||||
@implementation MpvEventsView
|
||||
@synthesize adapter = _adapter;
|
||||
@synthesize tracker = _tracker;
|
||||
@synthesize hasMouseDown = _mouse_down;
|
||||
|
||||
- (id)initWithFrame:(NSRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self registerForDraggedTypes:@[NSFilenamesPboardType,
|
||||
NSURLPboardType]];
|
||||
[self setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)rect
|
||||
{
|
||||
[[NSColor blackColor] setFill];
|
||||
NSRectFill(rect);
|
||||
}
|
||||
|
||||
// mpv uses flipped coordinates, because X11 uses those. So let's just use them
|
||||
// as well without having to do any coordinate conversion of mouse positions.
|
||||
- (BOOL)isFlipped { return YES; }
|
||||
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
if (self.tracker)
|
||||
[self removeTrackingArea:self.tracker];
|
||||
|
||||
if (![self.adapter mouseEnabled])
|
||||
return;
|
||||
|
||||
NSTrackingAreaOptions trackingOptions =
|
||||
NSTrackingEnabledDuringMouseDrag |
|
||||
NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved |
|
||||
NSTrackingActiveAlways;
|
||||
|
||||
self.tracker =
|
||||
[[[NSTrackingArea alloc] initWithRect:[self bounds]
|
||||
options:trackingOptions
|
||||
owner:self
|
||||
userInfo:nil] autorelease];
|
||||
|
||||
[self addTrackingArea:self.tracker];
|
||||
|
||||
if (![self containsMouseLocation])
|
||||
[self.adapter putKey:MP_KEY_MOUSE_LEAVE withModifiers:0];
|
||||
}
|
||||
|
||||
- (NSPoint)mouseLocation
|
||||
{
|
||||
return [self.window mouseLocationOutsideOfEventStream];
|
||||
}
|
||||
|
||||
- (BOOL)containsMouseLocation
|
||||
{
|
||||
CGFloat topMargin = 0.0;
|
||||
CGFloat menuBarHeight = [[NSApp mainMenu] menuBarHeight];
|
||||
|
||||
// menuBarHeight is 0 when menu bar is hidden in fullscreen
|
||||
// 1pt to compensate of the black line beneath the menu bar
|
||||
if ([self.adapter isInFullScreenMode] && menuBarHeight > 0) {
|
||||
NSRect tr = [NSWindow frameRectForContentRect:CGRectZero
|
||||
styleMask:NSWindowStyleMaskTitled];
|
||||
topMargin = tr.size.height + 1 + menuBarHeight;
|
||||
}
|
||||
|
||||
NSRect vF = [[self.window screen] frame];
|
||||
vF.size.height -= topMargin;
|
||||
NSRect vFW = [self.window convertRectFromScreen:vF];
|
||||
NSRect vFV = [self convertRect:vFW fromView:nil];
|
||||
NSPoint pt = [self convertPoint:[self mouseLocation] fromView:nil];
|
||||
|
||||
// clip bounds to current visibleFrame
|
||||
NSRect clippedBounds = CGRectIntersection([self bounds], vFV);
|
||||
return CGRectContainsPoint(clippedBounds, pt);
|
||||
}
|
||||
|
||||
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
|
||||
{
|
||||
return [self.adapter mouseEnabled];
|
||||
}
|
||||
|
||||
- (BOOL)acceptsFirstResponder
|
||||
{
|
||||
return [self.adapter keyboardEnabled] || [self.adapter mouseEnabled];
|
||||
}
|
||||
|
||||
- (BOOL)becomeFirstResponder
|
||||
{
|
||||
return [self.adapter keyboardEnabled] || [self.adapter mouseEnabled];
|
||||
}
|
||||
|
||||
- (BOOL)resignFirstResponder { return YES; }
|
||||
|
||||
- (BOOL)canHideCursor
|
||||
{
|
||||
return !self.hasMouseDown && [self containsMouseLocation]
|
||||
&& [[self window] isKeyWindow];
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(NSEvent *)event
|
||||
{
|
||||
[super mouseEntered:event];
|
||||
if ([self.adapter mouseEnabled]) {
|
||||
[self.adapter putKey:MP_KEY_MOUSE_ENTER withModifiers:0];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mouseExited:(NSEvent *)event
|
||||
{
|
||||
if ([self.adapter mouseEnabled]) {
|
||||
[self.adapter putKey:MP_KEY_MOUSE_LEAVE withModifiers:0];
|
||||
} else {
|
||||
[super mouseExited:event];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSPoint)convertPointToPixels:(NSPoint)point
|
||||
{
|
||||
point = [self convertPoint:point fromView:nil];
|
||||
point = [self convertPointToBacking:point];
|
||||
// flip y since isFlipped returning YES doesn't affect the backing
|
||||
// coordinate system
|
||||
point.y = -point.y;
|
||||
return point;
|
||||
}
|
||||
|
||||
- (void)signalMouseMovement:(NSEvent *)event
|
||||
{
|
||||
NSPoint p = [self convertPointToPixels:[event locationInWindow]];
|
||||
[self.adapter signalMouseMovement:p];
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(NSEvent *)event
|
||||
{
|
||||
if ([self.adapter mouseEnabled]) {
|
||||
[self signalMouseMovement:event];
|
||||
} else {
|
||||
[super mouseMoved:event];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mouseDragged:(NSEvent *)event
|
||||
{
|
||||
if ([self.adapter mouseEnabled]) {
|
||||
[self signalMouseMovement:event];
|
||||
} else {
|
||||
[super mouseDragged:event];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent *)event
|
||||
{
|
||||
if ([self.adapter mouseEnabled]) {
|
||||
[self mouseDownEvent:event];
|
||||
} else {
|
||||
[super mouseDown:event];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mouseUp:(NSEvent *)event
|
||||
{
|
||||
if ([self.adapter mouseEnabled]) {
|
||||
[self mouseUpEvent:event];
|
||||
} else {
|
||||
[super mouseUp:event];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)rightMouseDown:(NSEvent *)event
|
||||
{
|
||||
if ([self.adapter mouseEnabled]) {
|
||||
[self mouseDownEvent:event];
|
||||
} else {
|
||||
[super rightMouseUp:event];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)rightMouseUp:(NSEvent *)event
|
||||
{
|
||||
if ([self.adapter mouseEnabled]) {
|
||||
[self mouseUpEvent:event];
|
||||
} else {
|
||||
[super rightMouseUp:event];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)otherMouseDown:(NSEvent *)event
|
||||
{
|
||||
if ([self.adapter mouseEnabled]) {
|
||||
[self mouseDownEvent:event];
|
||||
} else {
|
||||
[super otherMouseDown:event];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)otherMouseUp:(NSEvent *)event
|
||||
{
|
||||
if ([self.adapter mouseEnabled]) {
|
||||
[self mouseUpEvent:event];
|
||||
} else {
|
||||
[super otherMouseUp:event];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)preciseScroll:(NSEvent *)event
|
||||
{
|
||||
CGFloat delta;
|
||||
int cmd;
|
||||
|
||||
if (fabs([event deltaY]) >= fabs([event deltaX])) {
|
||||
delta = [event deltaY] * 0.1;
|
||||
cmd = delta > 0 ? MP_WHEEL_UP : MP_WHEEL_DOWN;
|
||||
} else {
|
||||
delta = [event deltaX] * 0.1;
|
||||
cmd = delta > 0 ? MP_WHEEL_RIGHT : MP_WHEEL_LEFT;
|
||||
}
|
||||
|
||||
[self.adapter putWheel:cmd delta:fabs(delta)];
|
||||
}
|
||||
|
||||
- (void)scrollWheel:(NSEvent *)event
|
||||
{
|
||||
if (![self.adapter mouseEnabled]) {
|
||||
[super scrollWheel:event];
|
||||
return;
|
||||
}
|
||||
|
||||
if ([event hasPreciseScrollingDeltas]) {
|
||||
[self preciseScroll:event];
|
||||
} else {
|
||||
const int modifiers = [event modifierFlags];
|
||||
const float deltaX = (modifiers & NSEventModifierFlagShift) ?
|
||||
[event scrollingDeltaY] : [event scrollingDeltaX];
|
||||
const float deltaY = (modifiers & NSEventModifierFlagShift) ?
|
||||
[event scrollingDeltaX] : [event scrollingDeltaY];
|
||||
int mpkey;
|
||||
|
||||
if (fabs(deltaY) >= fabs(deltaX)) {
|
||||
mpkey = deltaY > 0 ? MP_WHEEL_UP : MP_WHEEL_DOWN;
|
||||
} else {
|
||||
mpkey = deltaX > 0 ? MP_WHEEL_LEFT : MP_WHEEL_RIGHT;
|
||||
}
|
||||
|
||||
[self.adapter putKey:mpkey withModifiers:modifiers];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mouseDownEvent:(NSEvent *)event
|
||||
{
|
||||
[self putMouseEvent:event withState:MP_KEY_STATE_DOWN];
|
||||
|
||||
if ([event clickCount] > 1)
|
||||
[self putMouseEvent:event withState:MP_KEY_STATE_UP];
|
||||
}
|
||||
|
||||
- (void)mouseUpEvent:(NSEvent *)event
|
||||
{
|
||||
[self putMouseEvent:event withState:MP_KEY_STATE_UP];
|
||||
}
|
||||
|
||||
- (void)putMouseEvent:(NSEvent *)event withState:(int)state
|
||||
{
|
||||
self.hasMouseDown = (state == MP_KEY_STATE_DOWN);
|
||||
int mpkey = [self mpvButtonNumber:event];
|
||||
[self.adapter putKey:(mpkey | state) withModifiers:[event modifierFlags]];
|
||||
}
|
||||
|
||||
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
NSPasteboard *pboard = [sender draggingPasteboard];
|
||||
NSArray *types = [pboard types];
|
||||
if ([types containsObject:NSFilenamesPboardType] ||
|
||||
[types containsObject:NSURLPboardType]) {
|
||||
return NSDragOperationCopy;
|
||||
} else {
|
||||
return NSDragOperationNone;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
NSPasteboard *pboard = [sender draggingPasteboard];
|
||||
if ([[pboard types] containsObject:NSFilenamesPboardType]) {
|
||||
NSArray *pbitems = [pboard propertyListForType:NSFilenamesPboardType];
|
||||
[self.adapter handleFilesArray:pbitems];
|
||||
return YES;
|
||||
} else if ([[pboard types] containsObject:NSURLPboardType]) {
|
||||
NSURL *url = [NSURL URLFromPasteboard:pboard];
|
||||
[self.adapter handleFilesArray:@[[url absoluteString]]];
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (int)mpvButtonNumber:(NSEvent*)event
|
||||
{
|
||||
int buttonNumber = [event buttonNumber];
|
||||
switch (buttonNumber) {
|
||||
case 0: return MP_MBTN_LEFT;
|
||||
case 1: return MP_MBTN_RIGHT;
|
||||
case 2: return MP_MBTN_MID;
|
||||
case 3: return MP_MBTN_BACK;
|
||||
case 4: return MP_MBTN_FORWARD;
|
||||
default: return MP_MBTN9 - 5 + buttonNumber;
|
||||
}
|
||||
}
|
||||
@end
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it 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.
|
||||
*
|
||||
* 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include "video/out/vo.h"
|
||||
|
||||
@interface MpvCocoaAdapter : NSObject<NSWindowDelegate>
|
||||
- (void)setNeedsResize;
|
||||
- (void)signalMouseMovement:(NSPoint)point;
|
||||
- (void)putKey:(int)mpkey withModifiers:(int)modifiers;
|
||||
- (void)putWheel:(int)mpkey delta:(float)delta;
|
||||
- (void)putCommand:(char*)cmd;
|
||||
- (void)handleFilesArray:(NSArray *)files;
|
||||
- (void)didChangeWindowedScreenProfile:(NSNotification *)notification;
|
||||
- (void)performAsyncResize:(NSSize)size;
|
||||
- (void)windowDidChangePhysicalScreen;
|
||||
- (void)windowDidEnterFullScreen;
|
||||
- (void)windowDidExitFullScreen;
|
||||
|
||||
- (BOOL)isInFullScreenMode;
|
||||
- (BOOL)wantsNativeFullscreen;
|
||||
- (BOOL)keyboardEnabled;
|
||||
- (BOOL)mouseEnabled;
|
||||
|
||||
- (NSScreen *)getTargetScreen;
|
||||
@property(nonatomic, assign) struct vo *vout;
|
||||
@end
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it 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.
|
||||
*
|
||||
* 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "video/out/cocoa/mpvadapter.h"
|
||||
|
||||
@interface MpvVideoView : NSView
|
||||
@property(nonatomic, retain) MpvCocoaAdapter *adapter;
|
||||
- (NSRect)frameInPixels;
|
||||
@end
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it 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.
|
||||
*
|
||||
* 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "video/out/cocoa_common.h"
|
||||
#include "video_view.h"
|
||||
|
||||
@implementation MpvVideoView
|
||||
@synthesize adapter = _adapter;
|
||||
|
||||
- (id)initWithFrame:(NSRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setFrameSize:(NSSize)size
|
||||
{
|
||||
[super setFrameSize:size];
|
||||
[self.adapter setNeedsResize];
|
||||
}
|
||||
|
||||
- (NSRect)frameInPixels
|
||||
{
|
||||
return [self convertRectToBacking:[self frame]];
|
||||
}
|
||||
|
||||
|
||||
- (void)drawRect:(NSRect)rect
|
||||
{
|
||||
[[NSColor blackColor] setFill];
|
||||
NSRectFill(rect);
|
||||
[self.adapter performAsyncResize:[self frameInPixels].size];
|
||||
}
|
||||
@end
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it 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.
|
||||
*
|
||||
* 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "video/out/cocoa/mpvadapter.h"
|
||||
|
||||
@protocol MpvWindowUpdate
|
||||
- (void)queueNewVideoSize:(NSSize)newSize;
|
||||
- (void)updateBorder:(int)border;
|
||||
@end
|
||||
|
||||
@interface MpvVideoWindow : NSWindow <NSWindowDelegate, MpvWindowUpdate>
|
||||
@property(nonatomic, retain) MpvCocoaAdapter *adapter;
|
||||
- (BOOL)canBecomeKeyWindow;
|
||||
- (BOOL)canBecomeMainWindow;
|
||||
- (void)mulSize:(float)multiplier;
|
||||
@end
|
||||
@@ -1,454 +0,0 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it 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.
|
||||
*
|
||||
* 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libavutil/common.h>
|
||||
|
||||
#include "input/keycodes.h"
|
||||
|
||||
#include "osdep/macosx_events.h"
|
||||
#include "video/out/cocoa_common.h"
|
||||
|
||||
#include "window.h"
|
||||
|
||||
@interface MpvVideoWindow()
|
||||
@property(nonatomic, retain) NSScreen *targetScreen;
|
||||
@property(nonatomic, retain) NSScreen *previousScreen;
|
||||
@property(nonatomic, retain) NSScreen *currentScreen;
|
||||
@property(nonatomic, retain) NSScreen *unfScreen;
|
||||
|
||||
- (NSRect)frameRect:(NSRect)frameRect forCenteredContentSize:(NSSize)newSize;
|
||||
- (void)setCenteredContentSize:(NSSize)newSize;
|
||||
@end
|
||||
|
||||
@implementation MpvVideoWindow {
|
||||
NSSize _queued_video_size;
|
||||
NSRect _unfs_content_frame;
|
||||
int _is_animating;
|
||||
}
|
||||
|
||||
@synthesize adapter = _adapter;
|
||||
@synthesize targetScreen = _target_screen;
|
||||
@synthesize previousScreen = _previous_screen;
|
||||
@synthesize currentScreen = _current_screen;
|
||||
@synthesize unfScreen = _unf_screen;
|
||||
|
||||
- (id)initWithContentRect:(NSRect)content_rect
|
||||
styleMask:(NSWindowStyleMask)style_mask
|
||||
backing:(NSBackingStoreType)buffering_type
|
||||
defer:(BOOL)flag
|
||||
screen:(NSScreen *)screen
|
||||
{
|
||||
if (self = [super initWithContentRect:content_rect
|
||||
styleMask:style_mask
|
||||
backing:buffering_type
|
||||
defer:flag
|
||||
screen:screen]) {
|
||||
[self setBackgroundColor:[NSColor whiteColor]];
|
||||
[self setMinSize:NSMakeSize(50,50)];
|
||||
[self setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary];
|
||||
|
||||
self.targetScreen = screen;
|
||||
self.currentScreen = screen;
|
||||
self.unfScreen = screen;
|
||||
_is_animating = 0;
|
||||
_unfs_content_frame = [self convertRectToScreen:[[self contentView] frame]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setStyleMask:(NSWindowStyleMask)style
|
||||
{
|
||||
NSResponder *nR = [self firstResponder];
|
||||
[super setStyleMask:style];
|
||||
[self makeFirstResponder:nR];
|
||||
}
|
||||
|
||||
- (void)toggleFullScreen:(id)sender
|
||||
{
|
||||
if (_is_animating)
|
||||
return;
|
||||
|
||||
_is_animating = 1;
|
||||
|
||||
self.targetScreen = [self.adapter getTargetScreen];
|
||||
if(![self targetScreen] && ![self previousScreen]) {
|
||||
self.targetScreen = [self screen];
|
||||
} else if (![self targetScreen]) {
|
||||
self.targetScreen = self.previousScreen;
|
||||
self.previousScreen = nil;
|
||||
} else {
|
||||
self.previousScreen = [self screen];
|
||||
}
|
||||
|
||||
if (![self.adapter isInFullScreenMode]) {
|
||||
_unfs_content_frame = [self convertRectToScreen:[[self contentView] frame]];
|
||||
self.unfScreen = [self screen];
|
||||
}
|
||||
|
||||
//move window to target screen when going to fullscreen
|
||||
if (![self.adapter isInFullScreenMode] && ![[self targetScreen] isEqual:[self screen]]) {
|
||||
NSRect frame = [self calculateWindowPositionForScreen:[self targetScreen]
|
||||
withoutBounds:NO];
|
||||
[self setFrame:frame display:YES];
|
||||
}
|
||||
|
||||
if ([self.adapter wantsNativeFullscreen])
|
||||
[super toggleFullScreen:sender];
|
||||
|
||||
if (![self.adapter isInFullScreenMode]) {
|
||||
[self setToFullScreen];
|
||||
} else {
|
||||
[self setToWindow];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setToFullScreen
|
||||
{
|
||||
[self setStyleMask:([self styleMask] | NSWindowStyleMaskFullScreen)];
|
||||
NSRect frame = [[self targetScreen] frame];
|
||||
|
||||
if ([self.adapter wantsNativeFullscreen]) {
|
||||
[self setFrame:frame display:YES];
|
||||
} else {
|
||||
[NSApp setPresentationOptions:NSApplicationPresentationAutoHideMenuBar|
|
||||
NSApplicationPresentationAutoHideDock];
|
||||
[self setFrame:frame display:YES];
|
||||
_is_animating = 0;
|
||||
[self.adapter windowDidEnterFullScreen];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setToWindow
|
||||
{
|
||||
[self setStyleMask:([self styleMask] & ~NSWindowStyleMaskFullScreen)];
|
||||
NSRect frame = [self calculateWindowPositionForScreen:[self targetScreen]
|
||||
withoutBounds:[[self targetScreen] isEqual:[self screen]]];
|
||||
|
||||
if ([self.adapter wantsNativeFullscreen]) {
|
||||
[self setFrame:frame display:YES];
|
||||
[self setContentAspectRatio:_unfs_content_frame.size];
|
||||
[self setCenteredContentSize:_unfs_content_frame.size];
|
||||
} else {
|
||||
[NSApp setPresentationOptions:NSApplicationPresentationDefault];
|
||||
[self setFrame:frame display:YES];
|
||||
[self setContentAspectRatio:_unfs_content_frame.size];
|
||||
[self setCenteredContentSize:_unfs_content_frame.size];
|
||||
_is_animating = 0;
|
||||
[self.adapter windowDidExitFullScreen];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *)customWindowsToEnterFullScreenForWindow:(NSWindow *)window
|
||||
{
|
||||
return [NSArray arrayWithObject:window];
|
||||
}
|
||||
|
||||
- (NSArray*)customWindowsToExitFullScreenForWindow:(NSWindow*)window
|
||||
{
|
||||
return [NSArray arrayWithObject:window];
|
||||
}
|
||||
|
||||
// we still need to keep those around or it will use the standard animation
|
||||
- (void)window:(NSWindow *)window startCustomAnimationToEnterFullScreenWithDuration:(NSTimeInterval)duration {}
|
||||
|
||||
- (void)window:(NSWindow *)window startCustomAnimationToExitFullScreenWithDuration:(NSTimeInterval)duration {}
|
||||
|
||||
- (void)windowDidEnterFullScreen:(NSNotification *)notification
|
||||
{
|
||||
_is_animating = 0;
|
||||
[self.adapter windowDidEnterFullScreen];
|
||||
}
|
||||
|
||||
- (void)windowDidExitFullScreen:(NSNotification *)notification
|
||||
{
|
||||
_is_animating = 0;
|
||||
[self.adapter windowDidExitFullScreen];
|
||||
}
|
||||
|
||||
- (void)windowWillEnterFullScreen:(NSNotification *)notification
|
||||
{
|
||||
[self.adapter windowWillEnterFullScreen:notification];
|
||||
}
|
||||
|
||||
- (void)windowWillExitFullScreen:(NSNotification *)notification
|
||||
{
|
||||
[self.adapter windowWillExitFullScreen:notification];
|
||||
}
|
||||
|
||||
- (void)windowDidFailToEnterFullScreen:(NSWindow *)window
|
||||
{
|
||||
_is_animating = 0;
|
||||
[self setToWindow];
|
||||
[self.adapter windowDidFailToEnterFullScreen:window];
|
||||
}
|
||||
|
||||
- (void)windowDidFailToExitFullScreen:(NSWindow *)window
|
||||
{
|
||||
_is_animating = 0;
|
||||
[self setToFullScreen];
|
||||
[self.adapter windowDidFailToExitFullScreen:window];
|
||||
}
|
||||
|
||||
- (void)windowDidChangeBackingProperties:(NSNotification *)notification
|
||||
{
|
||||
// XXX: we maybe only need expose for this
|
||||
[self.adapter setNeedsResize];
|
||||
}
|
||||
|
||||
- (void)windowDidChangeScreen:(NSNotification *)notification
|
||||
{
|
||||
[self.adapter windowDidChangeScreen:notification];
|
||||
|
||||
if (!_is_animating && ![[self currentScreen] isEqual:[self screen]]) {
|
||||
self.previousScreen = [self screen];
|
||||
}
|
||||
if (![[self currentScreen] isEqual:[self screen]]) {
|
||||
[self.adapter windowDidChangePhysicalScreen];
|
||||
}
|
||||
|
||||
self.currentScreen = [self screen];
|
||||
}
|
||||
|
||||
- (void)windowDidChangeScreenProfile:(NSNotification *)notification
|
||||
{
|
||||
[self.adapter didChangeWindowedScreenProfile:notification];
|
||||
}
|
||||
|
||||
- (void)windowDidResignKey:(NSNotification *)notification
|
||||
{
|
||||
[self.adapter windowDidResignKey:notification];
|
||||
}
|
||||
|
||||
- (void)windowDidBecomeKey:(NSNotification *)notification
|
||||
{
|
||||
[self.adapter windowDidBecomeKey:notification];
|
||||
}
|
||||
|
||||
- (void)windowWillMove:(NSNotification *)notification
|
||||
{
|
||||
[self.adapter windowWillMove:notification];
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeMainWindow { return YES; }
|
||||
- (BOOL)canBecomeKeyWindow { return YES; }
|
||||
|
||||
- (BOOL)windowShouldClose:(id)sender
|
||||
{
|
||||
cocoa_put_key(MP_KEY_CLOSE_WIN);
|
||||
// We have to wait for MPlayer to handle this,
|
||||
// otherwise we are in trouble if the
|
||||
// MP_KEY_CLOSE_WIN handler is disabled
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)normalSize { [self mulSize:1.0f]; }
|
||||
|
||||
- (void)halfSize { [self mulSize:0.5f];}
|
||||
|
||||
- (void)doubleSize { [self mulSize:2.0f];}
|
||||
|
||||
- (void)mulSize:(float)multiplier
|
||||
{
|
||||
char cmd[50];
|
||||
snprintf(cmd, sizeof(cmd), "set window-scale %f", multiplier);
|
||||
[self.adapter putCommand:cmd];
|
||||
}
|
||||
|
||||
- (void)updateBorder:(int)border
|
||||
{
|
||||
int borderStyle = NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|
|
||||
NSWindowStyleMaskMiniaturizable;
|
||||
if (border) {
|
||||
int window_mask = [self styleMask] & ~NSWindowStyleMaskBorderless;
|
||||
window_mask |= borderStyle;
|
||||
[self setStyleMask:window_mask];
|
||||
} else {
|
||||
int window_mask = [self styleMask] & ~borderStyle;
|
||||
window_mask |= NSWindowStyleMaskBorderless;
|
||||
[self setStyleMask:window_mask];
|
||||
}
|
||||
|
||||
if (![self.adapter isInFullScreenMode]) {
|
||||
// XXX: workaround to force redrawing of window decoration
|
||||
if (border) {
|
||||
NSRect frame = [self frame];
|
||||
frame.size.width += 1;
|
||||
[self setFrame:frame display:YES];
|
||||
frame.size.width -= 1;
|
||||
[self setFrame:frame display:YES];
|
||||
}
|
||||
|
||||
[self setContentAspectRatio:_unfs_content_frame.size];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSRect)frameRect:(NSRect)f forCenteredContentSize:(NSSize)ns
|
||||
{
|
||||
NSRect cr = [self contentRectForFrameRect:f];
|
||||
CGFloat dx = (cr.size.width - ns.width) / 2;
|
||||
CGFloat dy = (cr.size.height - ns.height) / 2;
|
||||
return NSInsetRect(f, dx, dy);
|
||||
}
|
||||
|
||||
- (void)setCenteredContentSize:(NSSize)ns
|
||||
{
|
||||
[self setFrame:[self frameRect:[self frame] forCenteredContentSize:ns]
|
||||
display:NO
|
||||
animate:NO];
|
||||
}
|
||||
|
||||
- (NSRect)calculateWindowPositionForScreen:(NSScreen *)screen withoutBounds:(BOOL)withoutBounds
|
||||
{
|
||||
NSRect frame = [self frameRectForContentRect:_unfs_content_frame];
|
||||
NSRect targetFrame = [screen frame];
|
||||
NSRect targetVisibleFrame = [screen visibleFrame];
|
||||
NSRect unfsScreenFrame = [self.unfScreen frame];
|
||||
NSRect visibleWindow = NSIntersectionRect(unfsScreenFrame, frame);
|
||||
|
||||
// calculate visible area of every side
|
||||
CGFloat left = frame.origin.x - unfsScreenFrame.origin.x;
|
||||
CGFloat right = unfsScreenFrame.size.width -
|
||||
(frame.origin.x - unfsScreenFrame.origin.x + frame.size.width);
|
||||
CGFloat bottom = frame.origin.y - unfsScreenFrame.origin.y;
|
||||
CGFloat top = unfsScreenFrame.size.height -
|
||||
(frame.origin.y - unfsScreenFrame.origin.y + frame.size.height);
|
||||
|
||||
// normalize visible areas, decide which one to take horizontal/vertical
|
||||
CGFloat x_per = (unfsScreenFrame.size.width - visibleWindow.size.width);
|
||||
CGFloat y_per = (unfsScreenFrame.size.height - visibleWindow.size.height);
|
||||
if (x_per != 0) x_per = (left >= 0 || right < 0 ? left : right)/x_per;
|
||||
if (y_per != 0) y_per = (bottom >= 0 || top < 0 ? bottom : top)/y_per;
|
||||
|
||||
// calculate visible area for every side for target screen
|
||||
CGFloat x_new_left = targetFrame.origin.x +
|
||||
(targetFrame.size.width - visibleWindow.size.width)*x_per;
|
||||
CGFloat x_new_right = targetFrame.origin.x + targetFrame.size.width -
|
||||
(targetFrame.size.width - visibleWindow.size.width)*x_per - frame.size.width;
|
||||
CGFloat y_new_bottom = targetFrame.origin.y +
|
||||
(targetFrame.size.height - visibleWindow.size.height)*y_per;
|
||||
CGFloat y_new_top = targetFrame.origin.y + targetFrame.size.height -
|
||||
(targetFrame.size.height - visibleWindow.size.height)*y_per - frame.size.height;
|
||||
|
||||
// calculate new coordinates, decide which one to take horizontal/vertical
|
||||
frame.origin.x = left >= 0 || right < 0 ? x_new_left : x_new_right;
|
||||
frame.origin.y = bottom >= 0 || top < 0 ? y_new_bottom : y_new_top;
|
||||
|
||||
// don't place new window on top of a visible menubar
|
||||
CGFloat top_mar = targetFrame.size.height -
|
||||
(frame.origin.y - targetFrame.origin.y + frame.size.height);
|
||||
CGFloat menuBarHeight = targetFrame.size.height -
|
||||
(targetVisibleFrame.size.height + targetVisibleFrame.origin.y);
|
||||
|
||||
if (top_mar < menuBarHeight)
|
||||
frame.origin.y -= top-menuBarHeight;
|
||||
|
||||
if (withoutBounds)
|
||||
return frame;
|
||||
|
||||
//screen bounds right and left
|
||||
if (frame.origin.x + frame.size.width > targetFrame.origin.x + targetFrame.size.width)
|
||||
frame.origin.x = targetFrame.origin.x + targetFrame.size.width - frame.size.width;
|
||||
if (frame.origin.x < targetFrame.origin.x)
|
||||
frame.origin.x = targetFrame.origin.x;
|
||||
|
||||
//screen bounds top and bottom
|
||||
if (frame.origin.y + frame.size.height > targetFrame.origin.y + targetFrame.size.height)
|
||||
frame.origin.y = targetFrame.origin.y + targetFrame.size.height - frame.size.height;
|
||||
if (frame.origin.y < targetFrame.origin.y)
|
||||
frame.origin.y = targetFrame.origin.y;
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
- (NSRect)constrainFrameRect:(NSRect)nf toScreen:(NSScreen *)screen
|
||||
{
|
||||
if ((_is_animating && ![self.adapter isInFullScreenMode]) ||
|
||||
(!_is_animating && [self.adapter isInFullScreenMode]))
|
||||
{
|
||||
return nf;
|
||||
}
|
||||
|
||||
screen = screen ?: self.screen ?: [NSScreen mainScreen];
|
||||
NSRect of = [self frame];
|
||||
NSRect vf = [_is_animating ? [self targetScreen] : screen visibleFrame];
|
||||
NSRect ncf = [self contentRectForFrameRect:nf];
|
||||
|
||||
// Prevent the window's titlebar from exiting the screen on the top edge.
|
||||
// This introduces a 'snap to top' behaviour.
|
||||
if (NSMaxY(nf) > NSMaxY(vf))
|
||||
nf.origin.y = NSMaxY(vf) - NSHeight(nf);
|
||||
|
||||
// Prevent the window's titlebar from exiting the screen on the bottom edge.
|
||||
if (NSMaxY(ncf) < NSMinY(vf))
|
||||
nf.origin.y = NSMinY(vf) + NSMinY(ncf) - NSMaxY(ncf);
|
||||
|
||||
// Prevent window from exiting the screen on the right edge
|
||||
if (NSMinX(nf) > NSMaxX(vf))
|
||||
nf.origin.x = NSMaxX(vf) - NSWidth(nf);
|
||||
|
||||
// Prevent window from exiting the screen on the left
|
||||
if (NSMaxX(nf) < NSMinX(vf))
|
||||
nf.origin.x = NSMinX(vf);
|
||||
|
||||
if (NSHeight(nf) < NSHeight(vf) && NSHeight(of) > NSHeight(vf) &&
|
||||
![self.adapter isInFullScreenMode])
|
||||
// If the window height is smaller than the visible frame, but it was
|
||||
// bigger previously recenter the smaller window vertically. This is
|
||||
// needed to counter the 'snap to top' behaviour.
|
||||
nf.origin.y = (NSHeight(vf) - NSHeight(nf)) / 2;
|
||||
|
||||
return nf;
|
||||
}
|
||||
|
||||
- (void)windowWillStartLiveResize:(NSNotification *)notification
|
||||
{
|
||||
[self.adapter windowWillStartLiveResize:notification];
|
||||
}
|
||||
|
||||
- (void)windowDidEndLiveResize:(NSNotification *)notification
|
||||
{
|
||||
[self.adapter windowDidEndLiveResize:notification];
|
||||
[self setFrame:[self constrainFrameRect:self.frame toScreen:self.screen]
|
||||
display:NO];
|
||||
}
|
||||
|
||||
- (void)tryDequeueSize
|
||||
{
|
||||
if (_queued_video_size.width <= 0.0 || _queued_video_size.height <= 0.0)
|
||||
return;
|
||||
|
||||
[self setContentAspectRatio:_queued_video_size];
|
||||
[self setCenteredContentSize:_queued_video_size];
|
||||
_queued_video_size = NSZeroSize;
|
||||
}
|
||||
|
||||
- (void)queueNewVideoSize:(NSSize)newSize
|
||||
{
|
||||
_unfs_content_frame = [self frameRect:_unfs_content_frame forCenteredContentSize:newSize];
|
||||
if (![self.adapter isInFullScreenMode]) {
|
||||
if (NSEqualSizes(_queued_video_size, newSize))
|
||||
return;
|
||||
_queued_video_size = newSize;
|
||||
[self tryDequeueSize];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)windowDidBecomeMain:(NSNotification *)notification
|
||||
{
|
||||
[self tryDequeueSize];
|
||||
}
|
||||
@end
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Cocoa OpenGL Backend
|
||||
*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it 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.
|
||||
*
|
||||
* 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_COCOA_COMMON_H
|
||||
#define MPLAYER_COCOA_COMMON_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <OpenGL/OpenGL.h>
|
||||
|
||||
struct vo;
|
||||
struct vo_cocoa_state;
|
||||
|
||||
void vo_cocoa_init(struct vo *vo);
|
||||
void vo_cocoa_uninit(struct vo *vo);
|
||||
|
||||
int vo_cocoa_config_window(struct vo *vo);
|
||||
|
||||
int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg);
|
||||
|
||||
void vo_cocoa_swap_buffers(struct vo *vo);
|
||||
void vo_cocoa_set_opengl_ctx(struct vo *vo, CGLContextObj ctx);
|
||||
|
||||
#endif /* MPLAYER_COCOA_COMMON_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,7 +37,6 @@
|
||||
extern const struct ra_ctx_fns ra_ctx_glx;
|
||||
extern const struct ra_ctx_fns ra_ctx_x11_egl;
|
||||
extern const struct ra_ctx_fns ra_ctx_drm_egl;
|
||||
extern const struct ra_ctx_fns ra_ctx_cocoa;
|
||||
extern const struct ra_ctx_fns ra_ctx_wayland_egl;
|
||||
extern const struct ra_ctx_fns ra_ctx_wgl;
|
||||
extern const struct ra_ctx_fns ra_ctx_angle;
|
||||
@@ -71,9 +70,6 @@ static const struct ra_ctx_fns *contexts[] = {
|
||||
#if HAVE_RPI
|
||||
&ra_ctx_rpi,
|
||||
#endif
|
||||
#if HAVE_GL_COCOA
|
||||
&ra_ctx_cocoa,
|
||||
#endif
|
||||
#if HAVE_EGL_ANGLE_WIN32
|
||||
&ra_ctx_angle,
|
||||
#endif
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it 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.
|
||||
*
|
||||
* 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <dlfcn.h>
|
||||
#include "options/m_config.h"
|
||||
#include "video/out/cocoa_common.h"
|
||||
#include "context.h"
|
||||
#include "osdep/macosx_application.h"
|
||||
|
||||
struct priv {
|
||||
GL gl;
|
||||
void (GLAPIENTRY *Flush)(void);
|
||||
CGLPixelFormatObj pix;
|
||||
CGLContextObj ctx;
|
||||
|
||||
struct macos_opts *macos_opts;
|
||||
};
|
||||
|
||||
static int set_swap_interval(int enabled)
|
||||
{
|
||||
CGLContextObj ctx = CGLGetCurrentContext();
|
||||
CGLError err = CGLSetParameter(ctx, kCGLCPSwapInterval, &enabled);
|
||||
return (err == kCGLNoError) ? 0 : -1;
|
||||
}
|
||||
|
||||
static void glFlushDummy(void) { }
|
||||
|
||||
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 ra_ctx *ctx, CGLOpenGLProfile ver)
|
||||
{
|
||||
struct priv *p = ctx->priv;
|
||||
|
||||
CGLPixelFormatAttribute attrs[] = {
|
||||
// let this array ordered by the inverse order of the most probably
|
||||
// rejected attribute to preserve the fallback code
|
||||
kCGLPFAOpenGLProfile,
|
||||
(CGLPixelFormatAttribute) ver,
|
||||
kCGLPFAAccelerated,
|
||||
kCGLPFAAllowOfflineRenderers,
|
||||
// keep this one last to apply the cocoa-force-dedicated-gpu option
|
||||
kCGLPFASupportsAutomaticGraphicsSwitching,
|
||||
0
|
||||
};
|
||||
|
||||
GLint npix;
|
||||
CGLError err;
|
||||
int supported_attribute = MP_ARRAY_SIZE(attrs)-1;
|
||||
|
||||
if (p->macos_opts->macos_force_dedicated_gpu)
|
||||
attrs[--supported_attribute] = 0;
|
||||
|
||||
err = CGLChoosePixelFormat(attrs, &p->pix, &npix);
|
||||
while (err == kCGLBadAttribute && supported_attribute > 3) {
|
||||
// kCGLPFASupportsAutomaticGraphicsSwitching is probably not
|
||||
// supported by the current hardware. Falling back to not using
|
||||
// it and disallowing Offline Renderers if further restrictions
|
||||
// apply
|
||||
attrs[--supported_attribute] = 0;
|
||||
err = CGLChoosePixelFormat(attrs, &p->pix, &npix);
|
||||
}
|
||||
|
||||
if (err != kCGLNoError) {
|
||||
MP_ERR(ctx->vo, "error creating CGL pixel format: %s (%d)\n",
|
||||
CGLErrorString(err), err);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
err = CGLCreateContext(p->pix, 0, &p->ctx);
|
||||
|
||||
error_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool create_gl_context(struct ra_ctx *ctx)
|
||||
{
|
||||
struct priv *p = ctx->priv;
|
||||
GL *gl = &p->gl;
|
||||
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, 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 (ctx->opts.want_alpha)
|
||||
CGLSetParameter(p->ctx, kCGLCPSurfaceOpacity, &(GLint){0});
|
||||
|
||||
mpgl_load_functions(gl, (void *)cocoa_glgetaddr, NULL, ctx->vo->log);
|
||||
gl->SwapInterval = set_swap_interval;
|
||||
p->Flush = gl->Flush;
|
||||
gl->Flush = glFlushDummy;
|
||||
|
||||
CGLReleasePixelFormat(p->pix);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void cocoa_uninit(struct ra_ctx *ctx)
|
||||
{
|
||||
struct priv *p = ctx->priv;
|
||||
ra_gl_ctx_uninit(ctx);
|
||||
CGLReleaseContext(p->ctx);
|
||||
vo_cocoa_uninit(ctx->vo);
|
||||
}
|
||||
|
||||
static void cocoa_swap_buffers(struct ra_ctx *ctx)
|
||||
{
|
||||
struct priv *p = ctx->priv;
|
||||
vo_cocoa_swap_buffers(ctx->vo);
|
||||
p->Flush();
|
||||
}
|
||||
|
||||
static bool cocoa_init(struct ra_ctx *ctx)
|
||||
{
|
||||
struct priv *p = ctx->priv = talloc_zero(ctx, struct priv);
|
||||
GL *gl = &p->gl;
|
||||
p->macos_opts = mp_get_config_group(ctx, ctx->global, &macos_conf);
|
||||
vo_cocoa_init(ctx->vo);
|
||||
|
||||
MP_WARN(ctx->vo, "opengl cocoa backend is deprecated, use vo=libmpv instead\n");
|
||||
|
||||
if (!create_gl_context(ctx))
|
||||
goto fail;
|
||||
|
||||
struct ra_gl_ctx_params params = {
|
||||
.swap_buffers = cocoa_swap_buffers,
|
||||
};
|
||||
|
||||
if (!ra_gl_ctx_init(ctx, gl, params))
|
||||
goto fail;
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
cocoa_uninit(ctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void resize(struct ra_ctx *ctx)
|
||||
{
|
||||
ra_gl_ctx_resize(ctx->swapchain, ctx->vo->dwidth, ctx->vo->dheight, 0);
|
||||
}
|
||||
|
||||
static bool cocoa_reconfig(struct ra_ctx *ctx)
|
||||
{
|
||||
vo_cocoa_config_window(ctx->vo);
|
||||
resize(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int cocoa_control(struct ra_ctx *ctx, int *events, int request,
|
||||
void *arg)
|
||||
{
|
||||
int ret = vo_cocoa_control(ctx->vo, events, request, arg);
|
||||
if (*events & VO_EVENT_RESIZE)
|
||||
resize(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct ra_ctx_fns ra_ctx_cocoa = {
|
||||
.type = "opengl",
|
||||
.name = "cocoa",
|
||||
.init = cocoa_init,
|
||||
.reconfig = cocoa_reconfig,
|
||||
.control = cocoa_control,
|
||||
.uninit = cocoa_uninit,
|
||||
};
|
||||
@@ -446,7 +446,6 @@ struct vo {
|
||||
struct mpv_global *global;
|
||||
struct vo_x11_state *x11;
|
||||
struct vo_w32_state *w32;
|
||||
struct vo_cocoa_state *cocoa;
|
||||
struct vo_wayland_state *wl;
|
||||
struct vo_android_state *android;
|
||||
struct vo_drm_state *drm;
|
||||
|
||||
Reference in New Issue
Block a user