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

Basic proof of concept is working.

parent d88b43ff
No related branches found
No related tags found
No related merge requests found
//
// iTermMetalFrameData.m
// iTerm2SharedARC
//
// Created by George Nachman on 10/27/17.
//
#import "iTermMetalFrameData.h"
#import <MetalKit/MetalKit.h>
void iTermMetalFrameDataStatsBundleInitialize(iTermMetalFrameDataStatsBundle *bundle) {
iTermPreciseTimerStatsInit(&bundle->mainThreadStats, "main thread");
iTermPreciseTimerStatsInit(&bundle->getCurrentDrawableStats, "mt.currentDrawable");
iTermPreciseTimerStatsInit(&bundle->getCurrentRenderPassDescriptorStats, "mt.renderPassDescr");
iTermPreciseTimerStatsInit(&bundle->dispatchStats, "dispatch");
iTermPreciseTimerStatsInit(&bundle->prepareStats, "prepare");
iTermPreciseTimerStatsInit(&bundle->waitForGroup, "wait for group");
iTermPreciseTimerStatsInit(&bundle->finalizeStats, "finalize");
iTermPreciseTimerStatsInit(&bundle->metalSetupStats, "metal setup");
iTermPreciseTimerStatsInit(&bundle->renderingStats, "rendering");
iTermPreciseTimerStatsInit(&bundle->endToEnd, "end to end");
}
static NSInteger gNextFrameDataNumber;
@implementation iTermMetalFrameData {
NSTimeInterval _creation;
NSInteger _frameNumber;
iTermMetalFrameDataStatsBundle _stats;
}
- (instancetype)init {
self = [super init];
if (self) {
_creation = [NSDate timeIntervalSinceReferenceDate];
_frameNumber = gNextFrameDataNumber++;
iTermMetalFrameDataStatsBundleInitialize(&_stats);
iTermPreciseTimerStatsStartTimer(&_stats.endToEnd);
iTermPreciseTimerStatsStartTimer(&_stats.mainThreadStats);
self.status = @"just created";
}
return self;
}
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p age=%f frameNumber=%@/%@ status=%@>",
self.class,
self,
[NSDate timeIntervalSinceReferenceDate] - _creation,
@(_frameNumber),
@(gNextFrameDataNumber),
self.status];
}
- (void)loadFromView:(MTKView *)view {
iTermPreciseTimerStatsStartTimer(&_stats.getCurrentDrawableStats);
self.drawable = view.currentDrawable;
iTermPreciseTimerStatsMeasureAndRecordTimer(&_stats.getCurrentDrawableStats);
iTermPreciseTimerStatsStartTimer(&_stats.getCurrentRenderPassDescriptorStats);
self.renderPassDescriptor = view.currentRenderPassDescriptor;
iTermPreciseTimerStatsMeasureAndRecordTimer(&_stats.getCurrentRenderPassDescriptorStats);
iTermPreciseTimerStatsMeasureAndRecordTimer(&_stats.mainThreadStats);
}
- (void)prepareWithBlock:(void (^)(void))block {
iTermPreciseTimerStatsStartTimer(&_stats.prepareStats);
self.status = @"before prepare";
block();
self.status = @"after prepare";
iTermPreciseTimerStatsMeasureAndRecordTimer(&_stats.prepareStats);
}
- (void)waitForUpdatesToFinishOnGroup:(dispatch_group_t)group
onQueue:(dispatch_queue_t)queue
finalize:(void (^)(void))finalize
render:(void (^)(void))render {
iTermPreciseTimerStatsStartTimer(&_stats.waitForGroup);
dispatch_group_notify(group, queue, ^{
self.status = @"before finalize";
iTermPreciseTimerStatsMeasureAndRecordTimer(&_stats.waitForGroup);
iTermPreciseTimerStatsStartTimer(&_stats.finalizeStats);
self.status = @"finalizing";
finalize();
iTermPreciseTimerStatsMeasureAndRecordTimer(&_stats.finalizeStats);
iTermPreciseTimerStatsStartTimer(&_stats.metalSetupStats);
self.status = @"doing metal setup";
render();
self.status = @"waiting for render to complete";
iTermPreciseTimerStatsMeasureAndRecordTimer(&_stats.metalSetupStats);
iTermPreciseTimerStatsStartTimer(&_stats.renderingStats);
});
}
- (void)didComplete {
self.status = @"complete";
iTermPreciseTimerStatsMeasureAndRecordTimer(&_stats.renderingStats);
iTermPreciseTimerStatsMeasureAndRecordTimer(&_stats.endToEnd);
}
- (void)addStatsTo:(iTermMetalFrameDataStatsBundle *)dest {
iTermPreciseTimerStatsRecord(&dest->mainThreadStats, _stats.mainThreadStats.mean * _stats.mainThreadStats.n, _stats.mainThreadStats.n);
iTermPreciseTimerStatsRecord(&dest->getCurrentDrawableStats, _stats.getCurrentDrawableStats.mean * _stats.getCurrentDrawableStats.n, _stats.getCurrentDrawableStats.n);
iTermPreciseTimerStatsRecord(&dest->getCurrentRenderPassDescriptorStats, _stats.getCurrentRenderPassDescriptorStats.mean * _stats.getCurrentRenderPassDescriptorStats.n, _stats.getCurrentRenderPassDescriptorStats.n);
iTermPreciseTimerStatsRecord(&dest->dispatchStats, _stats.dispatchStats.mean * _stats.dispatchStats.n, _stats.dispatchStats.n);
iTermPreciseTimerStatsRecord(&dest->prepareStats, _stats.prepareStats.mean * _stats.prepareStats.n, _stats.prepareStats.n);
iTermPreciseTimerStatsRecord(&dest->waitForGroup, _stats.waitForGroup.mean * _stats.waitForGroup.n, _stats.waitForGroup.n);
iTermPreciseTimerStatsRecord(&dest->finalizeStats, _stats.finalizeStats.mean * _stats.finalizeStats.n, _stats.finalizeStats.n);
iTermPreciseTimerStatsRecord(&dest->metalSetupStats, _stats.metalSetupStats.mean * _stats.metalSetupStats.n, _stats.metalSetupStats.n);
iTermPreciseTimerStatsRecord(&dest->renderingStats, _stats.renderingStats.mean * _stats.renderingStats.n, _stats.renderingStats.n);
iTermPreciseTimerStatsRecord(&dest->endToEnd, _stats.endToEnd.mean * _stats.endToEnd.n, _stats.endToEnd.n);
}
@end
//
// iTermMetalGlue.h
// iTerm2SharedARC
//
// Created by George Nachman on 10/8/17.
//
#import <Foundation/Foundation.h>
#import "iTermMetalDriver.h"
NS_ASSUME_NONNULL_BEGIN
@class iTermTextDrawingHelper;
@class VT100Screen;
@class PTYTextView;
@interface iTermMetalGlue : NSObject<iTermMetalDriverDataSource>
@property (nullable, nonatomic, strong) PTYTextView *textView;
@property (nonatomic, strong) VT100Screen *screen;
@end
NS_ASSUME_NONNULL_END
This diff is collapsed.
//
// iTermMetalGlyphKey.h
// iTerm2
//
// Created by George Nachman on 10/9/17.
//
#include <simd/simd.h>
typedef struct {
unichar code;
BOOL isComplex;
BOOL image;
BOOL boxDrawing;
BOOL thinStrokes;
} iTermMetalGlyphKey;
typedef struct {
vector_float4 foregroundColor;
vector_float4 backgroundColor;
} iTermMetalGlyphAttributes;
Loading
Loading
@@ -141,10 +141,10 @@ void iTermPreciseTimerPeriodicLog(iTermPreciseTimerStats stats[],
iTermPreciseTimerStatsInit(&stats[i], NULL);
}
if (logToConsole) {
ELog(@"%@", log);
} else {
DLog(@"%@", log);
NSLog(@"%@", log);
}
DLog(@"%@", log);
iTermPreciseTimerStart(&gLastLog);
}
}
Loading
Loading
Loading
Loading
@@ -54,6 +54,8 @@ static const CGFloat kMaximumToolbeltSizeAsFractionOfWindow = 0.5;
// Create the tab view.
self.tabView = [[[PTYTabView alloc] initWithFrame:self.bounds] autorelease];
#warning This should be only for the metal code path
self.tabView.drawsBackground = NO;
_tabView.autoresizingMask = (NSViewWidthSizable | NSViewHeightSizable);
_tabView.autoresizesSubviews = YES;
_tabView.allowsTruncatedLabels = NO;
Loading
Loading
Loading
Loading
@@ -19,6 +19,8 @@
@class PTYFontInfo;
@class VT100ScreenMark;
 
BOOL CheckFindMatchAtIndex(NSData *findMatches, int index);
@protocol iTermTextDrawingHelperDelegate <NSObject>
 
- (void)drawingHelperDrawBackgroundImageInRect:(NSRect)rect
Loading
Loading
@@ -48,7 +50,7 @@
isBackground:(BOOL)isBackground;
 
- (PTYFontInfo *)drawingHelperFontForChar:(UniChar)ch
isComplex:(BOOL)complex
isComplex:(BOOL)isComplex
renderBold:(BOOL *)renderBold
renderItalic:(BOOL *)renderItalic;
 
Loading
Loading
@@ -275,7 +277,11 @@
rectsPtr:(const NSRect *)rectArray
rectCount:(NSInteger)rectCount;
 
- (NSImage *)imageForCoord:(VT100GridCoord)coord size:(CGSize)size;
// Draw timestamps. Returns the width of the widest timestamp.
- (CGFloat)drawTimestamps;
 
- (VT100GridCoordRange)coordRangeForRect:(NSRect)rect;
@end
Loading
Loading
@@ -46,6 +46,13 @@ static const int kBadgeMargin = 4;
extern void CGContextSetFontSmoothingStyle(CGContextRef, int);
extern int CGContextGetFontSmoothingStyle(CGContextRef);
 
BOOL CheckFindMatchAtIndex(NSData *findMatches, int index) {
int theIndex = index / 8;
int mask = 1 << (index & 7);
const char *matchBytes = findMatches.bytes;
return !!(theIndex < [findMatches length] && (matchBytes[theIndex] & mask));
}
@interface iTermTextDrawingHelper() <iTermCursorDelegate>
@end
 
Loading
Loading
@@ -288,6 +295,37 @@ typedef struct iTermTextColorContext {
DLog(@"end drawRect:%@ in view %@", [NSValue valueWithRect:rect], _delegate);
}
 
- (NSImage *)imageForCoord:(VT100GridCoord)coord size:(CGSize)size {
NSData *rawMatches = [_delegate drawingHelperMatchesOnLine:coord.y];
screen_char_t *line = [_delegate drawingHelperLineAtIndex:coord.y];
iTermBackgroundColorRun backgroundRun = {
.range = { coord.x, 1 },
.bgColor = line[coord.x].backgroundColor,
.bgGreen = line[coord.x].bgGreen,
.bgBlue = line[coord.x].bgBlue,
.bgColorMode = line[coord.x].backgroundColorMode,
.selected = [[_selection selectedIndexesOnLine:coord.y] containsIndex:coord.x],
.isMatch = CheckFindMatchAtIndex(rawMatches, coord.x),
};
iTermBoxedBackgroundColorRun *boxedRun = [iTermBoxedBackgroundColorRun boxedBackgroundColorRunWithValue:backgroundRun];
NSColor *color = [self unprocessedColorForBackgroundRun:&backgroundRun];
// The unprocessed color is needed for minimum contrast computation for text color.
boxedRun.unprocessedBackgroundColor = color;
boxedRun.backgroundColor = [_colorMap processedBackgroundColorForBackgroundColor:color];
NSImage *image = [[NSImage alloc] initWithSize:size];
[image lockFocus];
[[NSColor redColor] set];
NSRectFill(NSMakeRect(0, 0, size.width, size.height));
[self drawForegroundForLineNumber:coord.y
y:0
backgroundRuns:@[ boxedRun ]
context:[[NSGraphicsContext currentContext] graphicsPort]];
[image unlockFocus];
return image;
}
- (NSInteger)numberOfEquivalentBackgroundColorLinesInRunArrays:(NSArray<iTermBackgroundColorRunsInLine *> *)backgroundRunArrays
fromIndex:(NSInteger)startIndex {
NSInteger count = 1;
Loading
Loading
@@ -1229,7 +1267,6 @@ typedef struct iTermTextColorContext {
CGContextSetBlendMode(ctx, kCGBlendModeSourceAtop);
}
CGContextSetFillColor(ctx, components);
double y = point.y + _cellSize.height + _baselineOffset;
int x = point.x + positions[0];
// Flip vertically and translate to (x, y).
Loading
Loading
@@ -1240,6 +1277,7 @@ typedef struct iTermTextColorContext {
CGContextSetTextMatrix(ctx, CGAffineTransformMake(1.0, 0.0,
m21, -1.0,
x, y));
CGPoint points[length];
for (int i = 0; i < length; i++) {
points[i].x = positions[i] - positions[0];
Loading
Loading
@@ -1257,7 +1295,6 @@ typedef struct iTermTextColorContext {
 
CGContextShowGlyphsAtPositions(ctx, glyphs, points, length);
}
#if 0
// Indicates which regions were drawn with the fastpath
[[NSColor yellowColor] set];
Loading
Loading
@@ -1562,10 +1599,10 @@ typedef struct iTermTextColorContext {
return maskContext;
}
 
static NSColor *iTermTextDrawingHelperGetTextColor(screen_char_t *c,
BOOL inUnderlinedRange,
int index,
iTermTextColorContext *context) {
NSColor *iTermTextDrawingHelperGetTextColor(screen_char_t *c,
BOOL inUnderlinedRange,
int index,
iTermTextColorContext *context) {
NSColor *rawColor = nil;
BOOL isMatch = NO;
const BOOL needsProcessing = context->backgroundColor && (context->minimumContrast > 0.001 ||
Loading
Loading
@@ -1765,16 +1802,16 @@ static BOOL iTermTextDrawingHelperIsCharacterDrawable(screen_char_t *c,
textColorContext);
}
 
const BOOL complex = c->complexChar;
const BOOL isComplex = c->complexChar;
const unichar code = c->code;
 
attributes->boxDrawing = !complex && [[iTermBoxDrawingBezierCurveFactory boxDrawingCharactersWithBezierPaths] characterIsMember:code];
attributes->boxDrawing = !isComplex && [[iTermBoxDrawingBezierCurveFactory boxDrawingCharactersWithBezierPaths] characterIsMember:code];
attributes->bold = c->bold;
 
attributes->fakeBold = c->bold; // default value
attributes->fakeItalic = c->italic; // default value
PTYFontInfo *fontInfo = [_delegate drawingHelperFontForChar:code
isComplex:complex
isComplex:isComplex
renderBold:&attributes->fakeBold
renderItalic:&attributes->fakeItalic];
 
Loading
Loading
@@ -1912,10 +1949,10 @@ static BOOL iTermTextDrawingHelperIsCharacterDrawable(screen_char_t *c,
iTermPreciseTimerStatsStartTimer(&_stats[TIMER_ATTRS_FOR_CHAR]);
screen_char_t c = line[i];
unichar code = c.code;
BOOL complex = c.complexChar;
BOOL isComplex = c.complexChar;
 
NSString *charAsString;
if (complex) {
if (isComplex) {
charAsString = ComplexCharToStr(c.code);
} else {
charAsString = nil;
Loading
Loading
Loading
Loading
@@ -15,7 +15,7 @@
 
// Timer period between updates when active (not idle, tab is visible or title bar is changing,
// etc.)
static const NSTimeInterval kActiveUpdateCadence = 1 / 20.0;
static const NSTimeInterval kActiveUpdateCadence = 1 / 60.0;
 
// Timer period between updates when adaptive frame rate is enabled and throughput is low but not 0.
static const NSTimeInterval kFastUpdateCadence = 1.0 / 60.0;
Loading
Loading
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