Skip to content
Snippets Groups Projects
Commit c5eda9ef authored by George Nachman's avatar George Nachman
Browse files

Lots of bugs and not faster than single-threaded drawing.

parent 3c2aeca5
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -1595,6 +1595,8 @@
A6A2699C190319A000437DA9 /* ProfilesAdvancedPreferencesViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = A6A2699A190319A000437DA9 /* ProfilesAdvancedPreferencesViewController.h */; };
A6A51A401B45CEA9007891F3 /* VT100DCSParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A6A51A3F1B45CEA9007891F3 /* VT100DCSParserTest.m */; };
A6A5991D1887C63700CB4209 /* ToolCommandHistoryView.h in Headers */ = {isa = PBXBuildFile; fileRef = A6A5991B1887C63700CB4209 /* ToolCommandHistoryView.h */; };
A6AC81961D4B1F56006F2ADC /* iTermDrawingShard.h in Headers */ = {isa = PBXBuildFile; fileRef = A6AC81941D4B1F56006F2ADC /* iTermDrawingShard.h */; };
A6AC81971D4B1F56006F2ADC /* iTermDrawingShard.m in Sources */ = {isa = PBXBuildFile; fileRef = A6AC81951D4B1F56006F2ADC /* iTermDrawingShard.m */; };
A6ACD1F81B62F2210095CB57 /* iTermRuleTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A6ACD1F71B62F2210095CB57 /* iTermRuleTest.m */; };
A6AE1ECF191FFA1C00780C19 /* iTermMouseCursor.h in Headers */ = {isa = PBXBuildFile; fileRef = A6AE1ECE191FFA1C00780C19 /* iTermMouseCursor.h */; };
A6AE1ED81926F89B00780C19 /* iTermAnnouncementViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = A6AE1ED61926F89B00780C19 /* iTermAnnouncementViewController.h */; };
Loading
Loading
@@ -3343,6 +3345,8 @@
A6A51A3F1B45CEA9007891F3 /* VT100DCSParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VT100DCSParserTest.m; sourceTree = "<group>"; };
A6A5991B1887C63700CB4209 /* ToolCommandHistoryView.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ToolCommandHistoryView.h; sourceTree = "<group>"; tabWidth = 4; };
A6A5991C1887C63700CB4209 /* ToolCommandHistoryView.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = ToolCommandHistoryView.m; sourceTree = "<group>"; tabWidth = 4; };
A6AC81941D4B1F56006F2ADC /* iTermDrawingShard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iTermDrawingShard.h; sourceTree = "<group>"; };
A6AC81951D4B1F56006F2ADC /* iTermDrawingShard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iTermDrawingShard.m; sourceTree = "<group>"; };
A6ACD1F71B62F2210095CB57 /* iTermRuleTest.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = iTermRuleTest.m; sourceTree = "<group>"; };
A6AE1ECC191FF9DB00780C19 /* iTermMouseCursor.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = iTermMouseCursor.m; sourceTree = "<group>"; tabWidth = 4; };
A6AE1ECE191FFA1C00780C19 /* iTermMouseCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = iTermMouseCursor.h; sourceTree = "<group>"; tabWidth = 4; };
Loading
Loading
@@ -5154,6 +5158,8 @@
A6936B481D2D756200521B04 /* iTermWindowOcclusionChangeMonitor.m */,
A686F38B1D3951A800F08ED7 /* iTermBoxDrawingBezierCurveFactory.h */,
A686F38C1D3951A800F08ED7 /* iTermBoxDrawingBezierCurveFactory.m */,
A6AC81941D4B1F56006F2ADC /* iTermDrawingShard.h */,
A6AC81951D4B1F56006F2ADC /* iTermDrawingShard.m */,
);
name = Helpers;
sourceTree = "<group>";
Loading
Loading
@@ -6150,6 +6156,7 @@
A66DB8421CA24E8800233E88 /* iTermAutoMasterParser.h in Headers */,
A6FEA2781CF2CBCC00376F28 /* iTermAppHotKeyProvider.h in Headers */,
A60251681CCD3E5E009BABF1 /* NSURL+iTerm.h in Headers */,
A6AC81961D4B1F56006F2ADC /* iTermDrawingShard.h in Headers */,
1D300BAA1BD9A8BB002043F7 /* NSDate+iTerm.h in Headers */,
A6FEA26C1CF2C86800376F28 /* iTermBaseHotKey.h in Headers */,
A6EFF23F1D21949D00806EEF /* iTermShortcut.h in Headers */,
Loading
Loading
@@ -7757,6 +7764,7 @@
A6C7634F1B45C52B00E3C992 /* SessionTitleView.m in Sources */,
A6C762B21B45C52B00E3C992 /* NSDateFormatterExtras.m in Sources */,
A6C763A01B45C52B00E3C992 /* TmuxWindowsTable.m in Sources */,
A6AC81971D4B1F56006F2ADC /* iTermDrawingShard.m in Sources */,
A6EFF2481D21DD0700806EEF /* iTermSessionHotkeyController.m in Sources */,
A6C762B41B45C52B00E3C992 /* NSDictionary+Profile.m in Sources */,
A6C763E51B45C70100E3C992 /* SCEvent.m in Sources */,
Loading
Loading
Loading
Loading
@@ -67,7 +67,7 @@
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Development"
buildConfiguration = "Deployment"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
Loading
Loading
Loading
Loading
@@ -59,10 +59,12 @@
- (NSString *)componentsJoinedWithOxfordComma;
 
- (NSArray *)intersectArray:(NSArray *)other;
- (NSArray *)arrayByShufflingArray;
 
@end
 
@interface NSMutableArray<ObjectType> (iTerm)
- (void)reverse;
- (void)removeObjectsPassingTest:(BOOL (^)(ObjectType anObject))block;
- (void)shuffle;
@end
Loading
Loading
@@ -235,6 +235,12 @@
return intersection;
}
 
- (NSArray *)arrayByShufflingArray {
NSMutableArray *result = [[self mutableCopy] autorelease];
[result shuffle];
return result;
}
@end
 
@implementation NSMutableArray (iTerm)
Loading
Loading
@@ -262,4 +268,16 @@
[self removeObjectsAtIndexes:indexes];
}
 
- (void)shuffle {
NSUInteger count = self.count;
if (!count) {
return;
}
for (NSUInteger i = 0; i + 1 < count; i++) {
NSInteger numberLeft = count - i;
NSInteger j = i + arc4random_uniform((u_int32_t )numberLeft);
[self exchangeObjectAtIndex:i withObjectAtIndex:j];
}
}
@end
Loading
Loading
@@ -150,5 +150,7 @@
+ (NSString *)downloadsDirectory;
+ (double)pointSizeOfTimeStamp;
+ (BOOL)showYellowMarkForJobStoppedBySignal;
+ (BOOL)parallelizeTextDrawing;
+ (int)numberOfDrawingShards;
 
@end
Loading
Loading
@@ -210,4 +210,7 @@ DEFINE_BOOL(experimentalKeyHandling, NO, @"Experimental Features: Improved suppo
DEFINE_BOOL(hideStuckTooltips, NO, @"Experimental Features: Hide stuck tooltips.\nWhen you hide iTerm2 using a hotkey while a tooltip is fading out it gets stuck because of an OS bug. Work around it with a nasty hack by enabling this feature.")
DEFINE_BOOL(showYellowMarkForJobStoppedBySignal, NO, @"Experimental Features: Use a yellow for a Shell Integration prompt mark when the job is stopped by a signal.");
 
DEFINE_BOOL(parallelizeTextDrawing, YES, @"Experimental Features: Parallelize drawing");
DEFINE_INT(numberOfDrawingShards, 4, @"Experimental Features: Number of drawing shards when parallelizing drawing");
@end
Loading
Loading
@@ -41,7 +41,7 @@ NS_INLINE BOOL iTermBackgroundColorRunsEqual(iTermBackgroundColorRun *a,
 
// Line number to draw at (row - scrollbackOverflow)
@property(nonatomic, assign) int line;
@property(nonatomic, assign) int equivalentRows;
@property(nonatomic, retain) NSArray<iTermBoxedBackgroundColorRun *> *array;
 
// Creates a new autoreleased iTermBackgroundColorRunsInLine object that's ready to use.
Loading
Loading
//
// iTermDrawingShard.h
// iTerm2
//
// Created by George Nachman on 7/28/16.
//
//
#import <Cocoa/Cocoa.h>
extern dispatch_queue_t gCompositingQueue;
@interface iTermDrawingShard : NSObject
@property(nonatomic, assign) CGContextRef bitmapContext;
@property(nonatomic, assign) NSRange range;
@property(nonatomic, assign) NSRect rect;
@property(nonatomic, copy) void (^compositingBlock)();
@property(nonatomic, readonly) dispatch_group_t group;
@property(nonatomic, readonly) NSArray *events;
@property(nonatomic, readonly) int shardNumber;
@property(nonatomic, readonly) NSSize capacity;
@property(nonatomic, readonly) CGLayerRef layer;
- (instancetype)initWithRect:(NSRect)rect
scale:(CGFloat)scale
range:(NSRange)range
bitmapContext:(CGContextRef)bitmapContext
queue:(dispatch_queue_t)queue;
- (instancetype)initWithRect:(NSRect)rect
scale:(CGFloat)scale
range:(NSRange)range
shardNumber:(int)shardNumber;
- (void)addEvent:(NSString *)event;
- (void)addDebugEvent:(NSString *)event;
- (void)removeAllEvents;
- (void)drawWithBlock:(void (^)())block;
- (void)compositeWhenReady;
- (void)setLayerContextFromContext:(CGContextRef)context;
@end
@interface iTermSynchronousDrawingShard : iTermDrawingShard
@end
NSTimeInterval MillisSinceDrawingEpoch();
void ResetDrawingEpoch();
\ No newline at end of file
//
// iTermDrawingShard.m
// iTerm2
//
// Created by George Nachman on 7/28/16.
//
//
#import "iTermDrawingShard.h"
static uint64_t gDrawingEpoch;
dispatch_queue_t gCompositingQueue;
void ResetDrawingEpoch() {
gDrawingEpoch = mach_absolute_time();
}
NSTimeInterval MillisSinceDrawingEpoch() {
static mach_timebase_info_data_t sTimebaseInfo;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
mach_timebase_info(&sTimebaseInfo);
});
double nanoseconds = (mach_absolute_time() - gDrawingEpoch) * sTimebaseInfo.numer / sTimebaseInfo.denom;
double ms = nanoseconds / 1000000.0;
return ms;
}
@implementation iTermDrawingShard {
NSMutableData *_data;
dispatch_queue_t _queue;
NSMutableArray *_events;
CGFloat _scale;
}
+ (dispatch_queue_t)queueForShardNumber:(int)shardNumber {
static NSMutableArray<dispatch_queue_t> *queues;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
queues = [[NSMutableArray alloc] init];
});
while (queues.count <= shardNumber) {
[queues addObject:dispatch_queue_create("com.googlecode.iterm2.DrawingQueue", DISPATCH_QUEUE_SERIAL)];
}
return queues[shardNumber];
}
+ (CGLayerRef)layerOfSize:(NSSize)size scale:(CGFloat)scale data:(NSMutableData *)data context:(CGContextRef)context {
CGSize scaledSize = CGSizeMake(size.width * scale, size.height * scale);
return CGLayerCreateWithContext(context, scaledSize, NULL);
}
+ (CGContextRef)bitmapContextOfSize:(NSSize)size scale:(CGFloat)scale data:(NSMutableData *)data {
NSInteger bytesPerRow = size.width * scale * 4;
NSUInteger storageNeeded = bytesPerRow * scale * size.height;
NSLog(@"%0.6fms: Calling setLength: %d", MillisSinceDrawingEpoch(), (int)storageNeeded);
[data setLength:storageNeeded];
NSLog(@"%0.6fms: Calling CGColorSpaceCreateDeviceRGB", MillisSinceDrawingEpoch());
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSLog(@"%0.6fms: Calling CGBitmapContextCreate", MillisSinceDrawingEpoch());
CGContextRef bitmapContext = CGBitmapContextCreate((void *)data.mutableBytes,
size.width * scale,
size.height * scale,
8,
bytesPerRow,
colorSpace,
(CGBitmapInfo)kCGImageAlphaPremultipliedLast);
NSLog(@"%0.6fms: Returned from CGBitmapContextCreate", MillisSinceDrawingEpoch());
assert(bitmapContext);
CGColorSpaceRelease(colorSpace);
CGContextScaleCTM(bitmapContext, scale, scale);
return bitmapContext;
}
- (instancetype)initWithRect:(NSRect)rect
scale:(CGFloat)scale
range:(NSRange)range
bitmapContext:(CGContextRef)bitmapContext
queue:(dispatch_queue_t)queue {
self = [super init];
if (self) {
_data = [[NSMutableData alloc] init];
_events = [[NSMutableArray alloc] init];
[self addEvent:@"Begin Initialize shard"];
_range = range;
_rect = rect;
_scale = scale;
_group = dispatch_group_create();
self.bitmapContext = bitmapContext;
_queue = queue;
_capacity = rect.size;
if (queue) {
dispatch_retain(queue);
}
if (bitmapContext) {
CFRetain(bitmapContext);
}
[self addEvent:@"End Initialize shard"];
}
return self;
}
- (void)setBitmapContext:(CGContextRef)bitmapContext {
if (_bitmapContext) {
CFRelease(_bitmapContext);
}
_bitmapContext = bitmapContext;
if (bitmapContext) {
CFRetain(bitmapContext);
}
}
// [[iTermDrawingShard alloc] initWithSize:NSMakeSize(width * scale, _cellSize.height * scale) scale:self.isRetina ? 2.0 : 1.0];
- (instancetype)initWithRect:(NSRect)rect scale:(CGFloat)scale range:(NSRange)range shardNumber:(int)shardNumber {
if (range.length == 0 || rect.size.height <= 0) {
return nil;
}
NSLog(@"%0.6fms: Creating bitmap context for shard %d", MillisSinceDrawingEpoch(), shardNumber);
// CGContextRef bitmapContext = [iTermDrawingShard bitmapContextOfSize:rect.size scale:scale data:_data];
NSLog(@"%0.6fms: Done creating bitmap context for shard %d", MillisSinceDrawingEpoch(), shardNumber);
dispatch_queue_t queue = [iTermDrawingShard queueForShardNumber:shardNumber];
self = [self initWithRect:rect scale:scale range:range bitmapContext:nil queue:queue];
// CFRelease(bitmapContext);
CFRelease(queue);
if (self) {
if (shardNumber >= 0) {
_shardNumber = shardNumber;
dispatch_retain(_queue);
}
}
return self;
}
- (void)dealloc {
if (_bitmapContext) {
CFRelease(_bitmapContext);
}
if (_queue) {
dispatch_release(_queue);
}
dispatch_release(_group);
[_events release];
[_data release];
[super dealloc];
}
- (void)setLayerContextFromContext:(CGContextRef)context {
if (_layer) {
CFRelease(_layer);
_layer = nil;
}
if (context) {
_layer = [iTermDrawingShard layerOfSize:_rect.size scale:_scale data:_data context:context];
self.bitmapContext = CGLayerGetContext(_layer);
} else {
self.bitmapContext = nil;
}
}
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p number=%d destination=%@ range=%@>",
NSStringFromClass([self class]), self, _shardNumber, NSStringFromRect(_rect),
NSStringFromRange(_range)];
}
- (void)addDebugEvent:(NSString *)event {
[self addEvent:event];
}
- (void)addEvent:(NSString *)event {
@synchronized(self) {
[_events addObject:[NSString stringWithFormat:@"%0.6fms: %@", MillisSinceDrawingEpoch(), event]];
}
}
- (void)removeAllEvents {
@synchronized(self) {
[_events removeAllObjects];
}
}
- (void)drawWithBlock:(void (^)())block {
[self addDebugEvent:@"Queue drawing block"];
dispatch_group_enter(_group);
dispatch_async(_queue, ^{
[self addDebugEvent:@"Begin drawing"];
block();
[self addDebugEvent:@"End drawing"];
[self addEvent:[NSString stringWithFormat:@"Shard %d drew", _shardNumber]];
dispatch_group_leave(_group);
});
}
- (void)compositeWhenReady {
if (_compositingBlock) {
dispatch_group_notify(_group, gCompositingQueue, ^() {
[self addEvent:@"Begin compositing"];
_compositingBlock();
[self addEvent:@"End compositing"];
});
}
}
@end
@implementation iTermSynchronousDrawingShard
- (void)drawWithBlock:(void (^)())block {
// NSLog(@"Perform draw on synchronous shard");
block();
}
@end
Loading
Loading
@@ -264,8 +264,4 @@
// Draw timestamps. Returns the width of the widest timestamp.
- (CGFloat)drawTimestamps;
 
#pragma mark - Testing Only
- (void)clipAndDrawRect:(NSRect)rect;
@end
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment