Fix concurrency and CATransaction flushing issues with CALayer based preview view.

Fix resizing of inputs causing a dispatch/kvo storm due to mismatched coordinate types
This commit is contained in:
Zakk 2019-02-01 08:07:55 -05:00
parent f2eb4ad0b4
commit 028ef54be5
11 changed files with 86 additions and 68 deletions

View file

@ -513,6 +513,7 @@
if (_seekRequest)
{
[self seek:_seekRequestTime];
return nil;
}

View file

@ -17,6 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
{
CVDisplayLinkRef _displayLink;
dispatch_queue_t _displayQueue;
NSRect _lastBounds;
NSSize _lastSurfaceSize;
float _scaleRatio;

View file

@ -21,7 +21,7 @@ CVReturn DisplayCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, c
_lastSurfaceSize = NSZeroSize;
_lastFpsTime = CACurrentMediaTime();
self.doDisplay = YES;
_displayQueue = dispatch_queue_create("PreviewCALayer queue", DISPATCH_QUEUE_SERIAL);
CVDisplayLinkCreateWithCGDisplay(CGMainDisplayID(), &_displayLink);
CVDisplayLinkSetOutputCallback(_displayLink, &DisplayCallback, (__bridge void * _Nullable)(self));
@ -90,16 +90,16 @@ CVReturn DisplayCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, c
{
return;
}
//dispatch_async(_displayQueue
// , ^{
//@autoreleasepool {
_frameCnt++;
dispatch_async(_displayQueue
, ^{
@autoreleasepool {
[CATransaction begin];
[self displayContent];
[CATransaction commit];
//}
// });
[CATransaction commit];
[CATransaction flush];
}
});
}
@ -120,6 +120,7 @@ CVReturn DisplayCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, c
if (self.doRender)
{
toDraw = [self.renderer currentImg];
if (toDraw)
{
CVPixelBufferRetain(toDraw);
@ -185,19 +186,7 @@ CVReturn DisplayCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, c
[self displayIfNeeded];
}
_frameCnt++;
if (_frameCnt == 60)
{
CFTimeInterval deltaTime = sTime - _lastFpsTime;
float statFPS = _frameCnt/deltaTime;
_lastFpsTime = sTime;
_avgRenderTime = _sumRenderTime/_frameCnt;
_sumRenderTime = 0.0f;
_frameCnt = 0;
//NSLog(@"FPS: %f %f/%f/%f", statFPS, _minRenderTime, _maxRenderTime, _avgRenderTime);
}
CVPixelBufferRelease(toDraw);
}
CVReturn DisplayCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, const CVTimeStamp *outputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext)

View file

@ -299,6 +299,7 @@
{
if ([keyPath isEqualToString:@"globalLayoutPosition"])
{
dispatch_async(dispatch_get_main_queue(), ^{
[self updatePosition];

View file

@ -152,10 +152,10 @@ typedef enum resize_style_t {
@property (strong) NSColor *backgroundColor;
@property (readonly) CGRect globalLayoutPosition;
@property (assign) float x_pos;
@property (assign) float y_pos;
@property (assign) float width;
@property (assign) float height;
@property (assign) CGFloat x_pos;
@property (assign) CGFloat y_pos;
@property (assign) CGFloat width;
@property (assign) CGFloat height;
@property (strong) NSMutableDictionary *constraintMap;
@ -379,10 +379,11 @@ typedef enum resize_style_t {
@property (strong) NSColor *backgroundColor;
@property (readonly) CGRect globalLayoutPosition;
@property (assign) float x_pos;
@property (assign) float y_pos;
@property (assign) float width;
@property (assign) float height;
@property (assign) CGFloat x_pos;
@property (assign) CGFloat y_pos;
@property (assign) CGFloat width;
@property (assign) CGFloat height;
@property (strong) NSMutableDictionary *constraintMap;

View file

@ -14,6 +14,14 @@
#import <objc/runtime.h>
#import "CaptureController.h"
#ifndef CGFLOAT_EPSILON
#if CGFLOAT_IS_DOUBLE
#define CGFLOAT_EPSILON DBL_EPSILON
#else
#define CGFLOAT_EPSILON FLT_EPSILON
#endif
#endif
static NSArray *_sourceTypes = nil;
@ -2056,13 +2064,14 @@ static NSArray *_sourceTypes = nil;
}
-(void)frameTick
{
self.layoutPosition = self.layer.frame;
bool x_chg, y_chg, w_chg, h_chg = NO;
if (_x_pos != self.layer.frame.origin.x)
if (fabs(_x_pos - self.layer.frame.origin.x) >= CGFLOAT_EPSILON)
{
x_chg = YES;
@ -2073,30 +2082,34 @@ static NSArray *_sourceTypes = nil;
}
if (_y_pos != self.layer.frame.origin.y)
if (fabs(_y_pos - self.layer.frame.origin.y) >= CGFLOAT_EPSILON)
{
// [self willChangeValueForKey:@"y_pos"];
_y_pos = self.layer.frame.origin.y;
y_chg = YES;
// [self didChangeValueForKey:@"y_pos"];
}
if (_width != self.layer.frame.size.width)
if (fabs(_width - self.layer.frame.size.width) >= CGFLOAT_EPSILON)
{
// [self willChangeValueForKey:@"width"];
_width = self.layer.frame.size.width;
// [self didChangeValueForKey:@"width"];
w_chg = YES;
}
if (_height != self.layer.frame.size.height)
if (fabs(_height - self.layer.frame.size.height) >= CGFLOAT_EPSILON)
{
// [self willChangeValueForKey:@"height"];
_height = self.layer.frame.size.height;
h_chg = YES;
// [self didChangeValueForKey:@"height"];
}
if (y_chg || x_chg || w_chg || h_chg)
{
dispatch_async(dispatch_get_main_queue(), ^{
@ -2111,7 +2124,6 @@ static NSArray *_sourceTypes = nil;
[self willChangeValueForKey:@"x_pos"];
[self didChangeValueForKey:@"x_pos"];
}
if (w_chg)
{
[self willChangeValueForKey:@"width"];
@ -2123,7 +2135,8 @@ static NSArray *_sourceTypes = nil;
[self willChangeValueForKey:@"height"];
[self didChangeValueForKey:@"height"];
}
//[self willChangeValueForKey:@"globalLayoutPosition"];
//[self didChangeValueForKey:@"globalLayoutPosition"];
});
}
[self multiChange];
@ -2425,7 +2438,9 @@ static NSArray *_sourceTypes = nil;
}
}
self.layer.frame = newLayout;
}
}
[CATransaction commit];

View file

@ -9,6 +9,7 @@
<customObject id="-2" userLabel="File's Owner" customClass="InputPopupControllerViewController">
<connections>
<outlet property="backgroundFilterViewController" destination="arq-y0-MNl" id="S27-aF-eKH"/>
<outlet property="height_field" destination="oeD-Hg-xTl" id="U7Y-R5-WCM"/>
<outlet property="inputFilterViewController" destination="b31-q9-7JS" id="cvO-Pu-J16"/>
<outlet property="inputobjctrl" destination="Gdf-y2-DdF" id="FT4-F8-KVU"/>
<outlet property="multiSourceController" destination="4mF-fx-iLB" id="U30-Tg-7IY"/>
@ -17,6 +18,9 @@
<outlet property="sourceConfigView" destination="qdF-gh-veZ" id="EeZ-cn-GeU"/>
<outlet property="sourceFilterViewController" destination="Ipm-Cn-5NK" id="Ge5-yf-IDd"/>
<outlet property="view" destination="E8C-YL-16h" id="aVS-B5-cxz"/>
<outlet property="width_field" destination="A7H-lh-SHi" id="ODg-5z-UHd"/>
<outlet property="x_pos_field" destination="4YP-40-KAW" id="9ON-jY-qpM"/>
<outlet property="y_pos_field" destination="eFs-Ve-sRh" id="njM-SP-BKj"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
@ -27,11 +31,11 @@
<tabViewItems>
<tabViewItem label="Settings" identifier="2" id="iXD-as-NHa">
<view key="view" id="byO-4p-D9j">
<rect key="frame" x="10" y="25" width="642" height="428"/>
<rect key="frame" x="10" y="29" width="642" height="424"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="EBg-Vi-cL7">
<rect key="frame" x="15" y="355" width="53" height="14"/>
<rect key="frame" x="15" y="351" width="53" height="14"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Source" id="YYN-k4-jke">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -47,7 +51,7 @@
</connections>
</textField>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Icu-pd-WRg">
<rect key="frame" x="64" y="376" width="243" height="22"/>
<rect key="frame" x="64" y="372" width="243" height="22"/>
<popUpButtonCell key="cell" type="push" bezelStyle="rounded" alignment="left" controlSize="small" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" id="eyR-QZ-n8r">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="smallSystem"/>
@ -65,7 +69,7 @@
</connections>
</popUpButton>
<textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gJP-2X-7HB">
<rect key="frame" x="15" y="377" width="35" height="18"/>
<rect key="frame" x="15" y="373" width="35" height="18"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Type" id="kpE-OE-l7z">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -73,7 +77,7 @@
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="GaR-E0-cDn">
<rect key="frame" x="307" y="397" width="80" height="27"/>
<rect key="frame" x="307" y="393" width="80" height="27"/>
<buttonCell key="cell" type="push" title="Auto Fit" bezelStyle="rounded" alignment="center" controlSize="small" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Dv6-1D-ZwG">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="smallSystem"/>
@ -87,7 +91,7 @@
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bWQ-Fl-ROJ">
<rect key="frame" x="15" y="406" width="35" height="13"/>
<rect key="frame" x="15" y="402" width="35" height="13"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Name" id="hR6-Ol-IPm">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -95,7 +99,7 @@
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="X91-Lt-pl4">
<rect key="frame" x="67" y="402" width="237" height="19"/>
<rect key="frame" x="67" y="398" width="237" height="19"/>
<constraints>
<constraint firstAttribute="width" constant="237" id="2vb-nA-dVb"/>
</constraints>
@ -113,10 +117,10 @@
</connections>
</textField>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="qdF-gh-veZ">
<rect key="frame" x="17" y="1" width="608" height="330"/>
<rect key="frame" x="17" y="1" width="608" height="326"/>
</customView>
<button translatesAutoresizingMaskIntoConstraints="NO" id="Eoh-8E-U5F">
<rect key="frame" x="312" y="379" width="72" height="18"/>
<rect key="frame" x="312" y="375" width="72" height="18"/>
<constraints>
<constraint firstAttribute="width" constant="67" id="nAZ-T1-2BD"/>
</constraints>
@ -133,10 +137,10 @@
</connections>
</button>
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="gFW-Ox-2QM">
<rect key="frame" x="17" y="337" width="608" height="5"/>
<rect key="frame" x="17" y="333" width="608" height="5"/>
</box>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ESc-uJ-Gih">
<rect key="frame" x="64" y="349" width="243" height="23"/>
<rect key="frame" x="64" y="345" width="243" height="23"/>
<popUpButtonCell key="cell" type="push" bezelStyle="rounded" alignment="left" controlSize="small" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" id="Uwd-iE-r9j">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="smallSystem"/>
@ -164,7 +168,7 @@
</connections>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="uB7-QF-9Sy">
<rect key="frame" x="388" y="405" width="67" height="14"/>
<rect key="frame" x="388" y="401" width="67" height="14"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Video Delay" id="aua-f6-BhG">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@ -172,7 +176,7 @@
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="7CX-iq-haH">
<rect key="frame" x="461" y="402" width="37" height="19"/>
<rect key="frame" x="461" y="398" width="37" height="19"/>
<constraints>
<constraint firstAttribute="width" constant="37" id="TC5-3u-8Ll"/>
</constraints>
@ -186,7 +190,7 @@
</connections>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="afT-Ro-9fT">
<rect key="frame" x="312" y="352" width="62" height="20"/>
<rect key="frame" x="312" y="348" width="62" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="57" id="WQ3-Rr-jPg"/>
</constraints>
@ -199,7 +203,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="2ga-xZ-eXu">
<rect key="frame" x="389" y="352" width="92" height="20"/>
<rect key="frame" x="389" y="348" width="92" height="20"/>
<buttonCell key="cell" type="check" title="Keep Cached" bezelStyle="regularSquare" imagePosition="left" controlSize="small" state="on" inset="2" id="l5S-cD-7cc">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="smallSystem"/>
@ -2181,7 +2185,7 @@
<rect key="frame" x="17" y="161" width="456" height="175"/>
<clipView key="contentView" id="VU8-cU-Tot">
<rect key="frame" x="1" y="0.0" width="454" height="174"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="firstColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowHeight="28" headerView="Cja-SV-r3z" id="Wec-Fy-TOT">
<rect key="frame" x="0.0" y="0.0" width="454" height="151"/>
@ -2395,8 +2399,8 @@
</menu>
</popUpButtonCell>
<connections>
<binding destination="-2" name="content" keyPath="self.resizeFilters" id="RYo-vi-5eN"/>
<binding destination="Gdf-y2-DdF" name="selectedObject" keyPath="selection.downscaleFilter" previousBinding="RYo-vi-5eN" id="nSt-tn-cfp"/>
<binding destination="-2" name="content" keyPath="self.resizeFilters" id="RYo-vi-5eN"/>
</connections>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DCB-vF-Cqd">
@ -2423,8 +2427,8 @@
</menu>
</popUpButtonCell>
<connections>
<binding destination="-2" name="content" keyPath="self.resizeFilters" id="Nng-5f-iSY"/>
<binding destination="Gdf-y2-DdF" name="selectedObject" keyPath="selection.upscaleFilter" previousBinding="Nng-5f-iSY" id="9YI-wE-y3u"/>
<binding destination="-2" name="content" keyPath="self.resizeFilters" id="Nng-5f-iSY"/>
</connections>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sYx-5e-y9E">
@ -2496,7 +2500,7 @@
<rect key="frame" x="-3" y="54" width="124" height="368"/>
<clipView key="contentView" id="ptW-r4-ihY">
<rect key="frame" x="1" y="1" width="122" height="366"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowSizeStyle="automatic" viewBased="YES" id="7TO-Cw-mOa">
<rect key="frame" x="0.0" y="0.0" width="122" height="366"/>
@ -2566,7 +2570,7 @@
<rect key="frame" x="120" y="54" width="525" height="368"/>
<clipView key="contentView" drawsBackground="NO" id="hAW-Jx-skG">
<rect key="frame" x="1" y="1" width="508" height="366"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textView importsGraphics="NO" richText="NO" verticallyResizable="YES" usesFontPanel="YES" findStyle="panel" continuousSpellChecking="YES" allowsUndo="YES" usesRuler="YES" allowsNonContiguousLayout="YES" quoteSubstitution="YES" dashSubstitution="YES" spellingCorrection="YES" smartInsertDelete="YES" id="XJb-k2-QUc">
<rect key="frame" x="0.0" y="0.0" width="508" height="366"/>

View file

@ -30,8 +30,8 @@
} else {
_useMetalRenderer = NO;
}*/
}
*/
//
_useMetalRenderer = NO;
@ -205,13 +205,11 @@
{
return;
}
[CATransaction begin];
[self.renderer setDestination:CVMetalTextureGetTexture(mtlTexture)];
[self.renderer beginFrameAtTime:CACurrentMediaTime() timeStamp:NULL];
[self.renderer addUpdateRect:self.renderer.bounds];
[self.renderer render];
[self.renderer endFrame];
[CATransaction commit];
CFRelease(mtlTexture);
return;
}
@ -261,7 +259,6 @@
[self.renderer addUpdateRect:self.renderer.bounds];
[self.renderer render];
[self.renderer endFrame];
//[CATransaction flush];
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
@ -273,7 +270,7 @@
-(CVPixelBufferRef)currentImg
{
[CATransaction begin];
//[CATransaction begin];
if (!self.layout)
{
@ -300,6 +297,8 @@
if (CGSizeEqualToSize(frameSize, CGSizeZero))
{
CGLSetCurrentContext(NULL);
return nil;
}
@ -318,9 +317,9 @@
if (doSetup && self.renderer)
{
[CATransaction lock];
//[CATransaction lock];
[self setupCArenderer];
[CATransaction unlock];
//[CATransaction unlock];
@synchronized (self) {
_layoutChanged = NO;
}
@ -329,10 +328,11 @@
CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, _cvpool, &destFrame);
//[CATransaction lock];
[CATransaction begin];
[self renderToPixelBuffer:destFrame];
//[CATransaction unlock];
[CATransaction commit];
CGLSetCurrentContext(NULL);
@synchronized(self)
{

View file

@ -177,6 +177,8 @@ typedef enum source_add_order_t {
bool _doingLayoutExport;
JSVirtualMachine *_animationVirtualMachine;
//dispatch_queue_t _animationQueue;
dispatch_group_t _frameTickGroup;
NSDictionary *_undoActionMap;

View file

@ -67,7 +67,7 @@ JS_EXPORT void JSSynchronousGarbageCollectForDebugging(JSContextRef ctx);
_rFbo = 0;
_uuidMap = [NSMutableDictionary dictionary];
_uuidMapPresentation = [NSMutableDictionary dictionary];
_frameTickGroup = dispatch_group_create();
_pendingScripts = [NSMutableDictionary dictionary];
@ -1985,7 +1985,6 @@ JS_EXPORT void JSSynchronousGarbageCollectForDebugging(JSContextRef ctx);
}
[CATransaction commit];
[CATransaction flush];
[self adjustInputs:changedInputs];
[self adjustInputs:newInputs];
@ -2823,10 +2822,16 @@ JS_EXPORT void JSSynchronousGarbageCollectForDebugging(JSContextRef ctx);
if (isource.active)
{
[isource frameTick];
//dispatch_group_async(_frameTickGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// [CATransaction begin];
[isource frameTick];
// [CATransaction commit];
// });
}
}
//dispatch_group_wait(_frameTickGroup, DISPATCH_TIME_FOREVER);
}
}

View file

@ -362,7 +362,6 @@
}
self.userFilterWindow = [[NSWindow alloc] init];
self.userFilterWindow.delegate = self;