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

Add a frame cursor renderer. Pass screen scale through to all transient states.

parent 5f892dc5
No related branches found
No related tags found
No related merge requests found
Showing
with 129 additions and 14 deletions
Loading
Loading
@@ -15,6 +15,7 @@ extern const CGFloat BOTTOM_MARGIN;
transientState:(__kindof iTermMetalCellRendererTransientState *)transientState;
 
- (void)createTransientStateForViewportSize:(vector_uint2)viewportSize
scale:(CGFloat)scale
cellSize:(CGSize)cellSize
gridSize:(VT100GridSize)gridSize
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
Loading
Loading
@@ -51,6 +52,7 @@ extern const CGFloat BOTTOM_MARGIN;
transientStateClass:(Class)transientStateClass NS_DESIGNATED_INITIALIZER;
 
- (void)createTransientStateForViewportSize:(vector_uint2)viewportSize
scale:(CGFloat)scale
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
completion:(void (^)(__kindof iTermMetalRendererTransientState *transientState))completion NS_UNAVAILABLE;
 
Loading
Loading
Loading
Loading
@@ -55,10 +55,11 @@ NS_ASSUME_NONNULL_BEGIN
}
 
- (void)createTransientStateForViewportSize:(vector_uint2)viewportSize
scale:(CGFloat)scale
cellSize:(CGSize)cellSize
gridSize:(VT100GridSize)gridSize
commandBuffer:(nonnull id<MTLCommandBuffer>)commandBuffer completion:(nonnull void (^)(__kindof iTermMetalCellRendererTransientState * _Nonnull))completion {
[super createTransientStateForViewportSize:viewportSize commandBuffer:commandBuffer completion:^(__kindof iTermMetalRendererTransientState * _Nonnull transientState) {
[super createTransientStateForViewportSize:viewportSize scale:scale commandBuffer:commandBuffer completion:^(__kindof iTermMetalRendererTransientState * _Nonnull transientState) {
iTermMetalCellRendererTransientState *tState = transientState;
tState.piuElementSize = _piuElementSize;
tState.gridSize = gridSize;
Loading
Loading
Loading
Loading
@@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
transientState:(__kindof iTermMetalRendererTransientState *)transientState;
 
- (void)createTransientStateForViewportSize:(vector_uint2)viewportSize
scale:(CGFloat)scale
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
completion:(void (^)(__kindof iTermMetalRendererTransientState *transientState))completion;
 
Loading
Loading
@@ -23,6 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) vector_uint2 viewportSize;
@property (nonatomic, strong) id<MTLBuffer> vertexBuffer;
@property (nonatomic, readonly, strong) id<MTLRenderPipelineState> pipelineState;
@property (nonatomic, readonly) CGFloat scale;
@end
 
@interface iTermMetalRenderer : NSObject<iTermMetalRenderer>
Loading
Loading
Loading
Loading
@@ -4,6 +4,7 @@
 
@interface iTermMetalRendererTransientState()
@property (nonatomic, readwrite, strong) id<MTLRenderPipelineState> pipelineState;
@property (nonatomic, readwrite) CGFloat scale;
@end
 
@implementation iTermMetalRendererTransientState
Loading
Loading
@@ -55,11 +56,13 @@
#pragma mark - Protocol Methods
 
- (void)createTransientStateForViewportSize:(vector_uint2)viewportSize
scale:(CGFloat)scale
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
completion:(void (^)(__kindof iTermMetalRendererTransientState * _Nonnull))completion {
iTermMetalRendererTransientState *tState = [[self.transientStateClass alloc] init];
tState.pipelineState = [self newPipelineState];
tState.viewportSize = viewportSize;
tState.scale = scale;
completion(tState);
}
 
Loading
Loading
Loading
Loading
@@ -53,11 +53,13 @@
}
 
- (void)createTransientStateForViewportSize:(vector_uint2)viewportSize
scale:(CGFloat)scale
cellSize:(CGSize)cellSize
gridSize:(VT100GridSize)gridSize
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
completion:(void (^)(__kindof iTermMetalCellRendererTransientState * _Nonnull))completion {
[_cellRenderer createTransientStateForViewportSize:viewportSize
scale:scale
cellSize:cellSize
gridSize:gridSize
commandBuffer:commandBuffer
Loading
Loading
Loading
Loading
@@ -46,9 +46,11 @@ NS_ASSUME_NONNULL_BEGIN
}
 
- (void)createTransientStateForViewportSize:(vector_uint2)viewportSize
scale:(CGFloat)scale
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
completion:(void (^)(__kindof iTermMetalRendererTransientState * _Nonnull))completion {
[_metalRenderer createTransientStateForViewportSize:viewportSize
scale:scale
commandBuffer:commandBuffer
completion:^(__kindof iTermMetalRendererTransientState * _Nonnull transientState) {
[self initializeTransientState:transientState];
Loading
Loading
Loading
Loading
@@ -62,9 +62,11 @@ NS_ASSUME_NONNULL_BEGIN
}
 
- (void)createTransientStateForViewportSize:(vector_uint2)viewportSize
scale:(CGFloat)scale
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
completion:(void (^)(__kindof iTermMetalRendererTransientState * _Nonnull))completion {
[_metalRenderer createTransientStateForViewportSize:viewportSize
scale:scale
commandBuffer:commandBuffer
completion:^(__kindof iTermMetalRendererTransientState * _Nonnull transientState) {
[self initializeTransientState:transientState];
Loading
Loading
Loading
Loading
@@ -44,9 +44,11 @@ NS_ASSUME_NONNULL_BEGIN
}
 
- (void)createTransientStateForViewportSize:(vector_uint2)viewportSize
scale:(CGFloat)scale
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
completion:(void (^)(__kindof iTermMetalRendererTransientState * _Nonnull))completion {
[_metalRenderer createTransientStateForViewportSize:viewportSize
scale:scale
commandBuffer:commandBuffer
completion:^(__kindof iTermMetalRendererTransientState * _Nonnull transientState) {
[self initializeTransientState:transientState];
Loading
Loading
Loading
Loading
@@ -50,11 +50,13 @@
}
 
- (void)createTransientStateForViewportSize:(vector_uint2)viewportSize
scale:(CGFloat)scale
cellSize:(CGSize)cellSize
gridSize:(VT100GridSize)gridSize
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
completion:(void (^)(__kindof iTermMetalCellRendererTransientState * _Nonnull))completion {
[_cellRenderer createTransientStateForViewportSize:viewportSize
scale:scale
cellSize:cellSize
gridSize:gridSize
commandBuffer:commandBuffer
Loading
Loading
Loading
Loading
@@ -11,6 +11,8 @@ NS_ASSUME_NONNULL_BEGIN
+ (instancetype)newUnderlineCursorRendererWithDevice:(id<MTLDevice>)device;
+ (instancetype)newBarCursorRendererWithDevice:(id<MTLDevice>)device;
+ (instancetype)newBlockCursorRendererWithDevice:(id<MTLDevice>)device;
+ (instancetype)newFrameCursorRendererWithDevice:(id<MTLDevice>)device;
+ (iTermCopyModeCursorRenderer *)newCopyModeCursorRendererWithDevice:(id<MTLDevice>)device;
 
- (instancetype)init NS_UNAVAILABLE;
Loading
Loading
@@ -27,4 +29,7 @@ NS_ASSUME_NONNULL_BEGIN
 
@end
 
@interface iTermFrameCursorRenderer : iTermCursorRenderer
@end
NS_ASSUME_NONNULL_END
Loading
Loading
@@ -15,6 +15,10 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) BOOL selecting;
@end
 
@interface iTermFrameCursorRendererTransientState : iTermCursorRendererTransientState
@property (nonatomic, strong) id<MTLTexture> texture;
@end
@implementation iTermCopyModeCursorRendererTransientState
 
- (NSImage *)newImage {
Loading
Loading
@@ -22,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
 
[image lockFocus];
const CGFloat heightFraction = 1 / 3.0;
const CGFloat scale = 2;
const CGFloat scale = self.scale;
NSRect rect = NSMakeRect(scale / 2,
scale / 2,
self.cellSize.width,
Loading
Loading
@@ -54,6 +58,29 @@ NS_ASSUME_NONNULL_BEGIN
 
@end
 
@implementation iTermFrameCursorRendererTransientState
- (NSImage *)newImage {
NSImage *image = [[NSImage alloc] initWithSize:self.cellSize];
[image lockFocus];
NSRect rect = NSMakeRect(0,
0,
self.cellSize.width,
self.cellSize.height);
rect = NSInsetRect(rect, self.scale / 2, self.scale / 2);
NSBezierPath *path = [NSBezierPath bezierPathWithRect:rect];
[path setLineWidth:self.scale];
[self.color setStroke];
[path stroke];
[image unlockFocus];
return image;
}
@end
@interface iTermUnderlineCursorRenderer : iTermCursorRenderer
@end
 
Loading
Loading
@@ -88,6 +115,12 @@ NS_ASSUME_NONNULL_BEGIN
fragmentFunctionName:@"iTermTextureCursorFragmentShader"];
}
 
+ (instancetype)newFrameCursorRendererWithDevice:(id<MTLDevice>)device {
return [[iTermFrameCursorRenderer alloc] initWithDevice:device
vertexFunctionName:@"iTermTextureCursorVertexShader"
fragmentFunctionName:@"iTermTextureCursorFragmentShader"];
}
- (instancetype)initWithDevice:(id<MTLDevice>)device
vertexFunctionName:(NSString *)vertexFunctionName
fragmentFunctionName:(NSString *)fragmentFunctionName {
Loading
Loading
@@ -115,11 +148,13 @@ NS_ASSUME_NONNULL_BEGIN
}
 
- (void)createTransientStateForViewportSize:(vector_uint2)viewportSize
scale:(CGFloat)scale
cellSize:(CGSize)cellSize
gridSize:(VT100GridSize)gridSize
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
completion:(void (^)(__kindof iTermMetalCellRendererTransientState * _Nonnull))completion {
[_cellRenderer createTransientStateForViewportSize:viewportSize
scale:scale
cellSize:cellSize
gridSize:gridSize
commandBuffer:commandBuffer
Loading
Loading
@@ -200,6 +235,52 @@ NS_ASSUME_NONNULL_BEGIN
 
@end
 
@implementation iTermFrameCursorRenderer {
id<MTLTexture> _texture;
CGSize _textureSize;
}
- (Class)transientStateClass {
return [iTermFrameCursorRendererTransientState class];
}
- (void)initializeTransientState:(iTermFrameCursorRendererTransientState *)tState {
[super initializeTransientState:tState];
tState.vertexBuffer = [_cellRenderer newQuadOfSize:CGSizeMake(tState.cellSize.width,
tState.cellSize.height)];
tState.color = _color;
if (_texture == nil || !CGSizeEqualToSize(_textureSize, tState.cellSize)) {
_texture = [_cellRenderer textureFromImage:[tState newImage]];
_textureSize = tState.cellSize;
}
tState.texture = _texture;
}
- (void)drawWithRenderEncoder:(id<MTLRenderCommandEncoder>)renderEncoder
transientState:(__kindof iTermMetalCellRendererTransientState *)transientState {
iTermFrameCursorRendererTransientState *tState = transientState;
iTermCursorDescription description = {
.origin = {
tState.cellSize.width * tState.coord.x,
tState.cellSize.height * (tState.gridSize.height - tState.coord.y - 1),
},
};
id<MTLBuffer> descriptionBuffer = [_cellRenderer.device newBufferWithBytes:&description
length:sizeof(description)
options:MTLResourceStorageModeShared];
[_cellRenderer drawWithTransientState:tState
renderEncoder:renderEncoder
numberOfVertices:6
numberOfPIUs:tState.gridSize.width
vertexBuffers:@{ @(iTermVertexInputIndexVertices): tState.vertexBuffer,
@(iTermVertexInputIndexCursorDescription): descriptionBuffer,
@(iTermVertexInputIndexOffset): tState.offsetBuffer }
fragmentBuffers:@{}
textures:@{ @(iTermTextureIndexPrimary): tState.texture } ];
}
@end
@implementation iTermCopyModeCursorRenderer {
id<MTLTexture> _texture;
CGSize _textureSize;
Loading
Loading
Loading
Loading
@@ -52,11 +52,13 @@
}
 
- (void)createTransientStateForViewportSize:(vector_uint2)viewportSize
scale:(CGFloat)scale
cellSize:(CGSize)cellSize
gridSize:(VT100GridSize)gridSize
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
completion:(void (^)(__kindof iTermMetalCellRendererTransientState * _Nonnull))completion {
[_cellRenderer createTransientStateForViewportSize:viewportSize
scale:scale
cellSize:cellSize
gridSize:gridSize
commandBuffer:commandBuffer
Loading
Loading
Loading
Loading
@@ -193,11 +193,13 @@ extern "C" {
}
 
- (void)createTransientStateForViewportSize:(vector_uint2)viewportSize
scale:(CGFloat)scale
cellSize:(CGSize)cellSize
gridSize:(VT100GridSize)gridSize
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
completion:(void (^)(__kindof iTermMetalCellRendererTransientState * _Nonnull))completion {
[_cellRenderer createTransientStateForViewportSize:viewportSize
scale:scale
cellSize:cellSize
gridSize:gridSize
commandBuffer:commandBuffer
Loading
Loading
Loading
Loading
@@ -41,6 +41,7 @@ static const NSInteger iTermMetalDriverMaximumNumberOfFramesInFlight = 3;
iTermCursorRenderer *_underlineCursorRenderer;
iTermCursorRenderer *_barCursorRenderer;
iTermCursorRenderer *_blockCursorRenderer;
iTermCursorRenderer *_frameCursorRenderer;
iTermCopyModeCursorRenderer *_copyModeCursorRenderer;
 
// The command Queue from which we'll obtain command buffers
Loading
Loading
@@ -81,6 +82,7 @@ static const NSInteger iTermMetalDriverMaximumNumberOfFramesInFlight = 3;
_underlineCursorRenderer = [iTermCursorRenderer newUnderlineCursorRendererWithDevice:mtkView.device];
_barCursorRenderer = [iTermCursorRenderer newBarCursorRendererWithDevice:mtkView.device];
_blockCursorRenderer = [iTermCursorRenderer newBlockCursorRendererWithDevice:mtkView.device];
_frameCursorRenderer = [iTermCursorRenderer newFrameCursorRendererWithDevice:mtkView.device];
_copyModeCursorRenderer = [iTermCursorRenderer newCopyModeCursorRendererWithDevice:mtkView.device];
_commandQueue = [mtkView.device newCommandQueue];
_queue = dispatch_queue_create("com.iterm2.metalDriver", NULL);
Loading
Loading
@@ -187,6 +189,7 @@ static const NSInteger iTermMetalDriverMaximumNumberOfFramesInFlight = 3;
[self.nonCellRenderers enumerateObjectsUsingBlock:^(id<iTermMetalRenderer> _Nonnull renderer, NSUInteger idx, BOOL * _Nonnull stop) {
dispatch_group_enter(group);
[renderer createTransientStateForViewportSize:_viewportSize
scale:frameData.scale
commandBuffer:commandBuffer
completion:^(__kindof iTermMetalRendererTransientState * _Nonnull tState) {
if (tState) {
Loading
Loading
@@ -202,6 +205,7 @@ static const NSInteger iTermMetalDriverMaximumNumberOfFramesInFlight = 3;
[self.cellRenderers enumerateObjectsUsingBlock:^(id<iTermMetalCellRenderer> _Nonnull renderer, NSUInteger idx, BOOL * _Nonnull stop) {
dispatch_group_enter(group);
[renderer createTransientStateForViewportSize:_viewportSize
scale:frameData.scale
cellSize:_cellSize
gridSize:gridSize
commandBuffer:commandBuffer
Loading
Loading
@@ -255,8 +259,7 @@ static const NSInteger iTermMetalDriverMaximumNumberOfFramesInFlight = 3;
CGFloat scale = frameData.scale;
 
iTermMetalCursorInfo *cursorInfo = [frameData.perFrameState metalDriverCursorInfo];
if (cursorInfo.cursorVisible && cursorInfo.shouldDrawText) {
NSLog(@"Cursor on line %d of display", cursorInfo.coord.y);
if (!cursorInfo.frameOnly && cursorInfo.cursorVisible && cursorInfo.shouldDrawText) {
iTermMetalRowData *rowWithCursor = frameData.rows[cursorInfo.coord.y];
iTermMetalGlyphAttributes *glyphAttributes = (iTermMetalGlyphAttributes *)rowWithCursor.attributesData.mutableBytes;
glyphAttributes[cursorInfo.coord.x].foregroundColor = cursorInfo.textColor;
Loading
Loading
@@ -333,9 +336,15 @@ static const NSInteger iTermMetalDriverMaximumNumberOfFramesInFlight = 3;
renderEncoder:renderEncoder];
break;
case CURSOR_BOX:
[self drawCellRenderer:_blockCursorRenderer
frameData:frameData
renderEncoder:renderEncoder];
if (cursorInfo.frameOnly) {
[self drawCellRenderer:_frameCursorRenderer
frameData:frameData
renderEncoder:renderEncoder];
} else {
[self drawCellRenderer:_blockCursorRenderer
frameData:frameData
renderEncoder:renderEncoder];
}
break;
case CURSOR_VERTICAL:
[self drawCellRenderer:_barCursorRenderer
Loading
Loading
@@ -443,7 +452,8 @@ static const NSInteger iTermMetalDriverMaximumNumberOfFramesInFlight = 3;
[self updateCursorGuideRendererWithPerFrameState:perFrameState];
} else if (renderer == _underlineCursorRenderer ||
renderer == _barCursorRenderer ||
renderer == _blockCursorRenderer) {
renderer == _blockCursorRenderer ||
renderer == _frameCursorRenderer) {
[self updateCursorRendererWithPerFrameState:perFrameState];
} else if (renderer == _copyModeCursorRenderer) {
[self updateCopyModeCursorRendererWithPerFrameState:perFrameState];
Loading
Loading
@@ -475,6 +485,8 @@ static const NSInteger iTermMetalDriverMaximumNumberOfFramesInFlight = 3;
case CURSOR_BOX:
[_blockCursorRenderer setCoord:cursorInfo.coord];
[_blockCursorRenderer setColor:cursorInfo.cursorColor];
[_frameCursorRenderer setCoord:cursorInfo.coord];
[_frameCursorRenderer setColor:cursorInfo.cursorColor];
break;
case CURSOR_VERTICAL:
[_barCursorRenderer setCoord:cursorInfo.coord];
Loading
Loading
@@ -501,6 +513,7 @@ static const NSInteger iTermMetalDriverMaximumNumberOfFramesInFlight = 3;
_underlineCursorRenderer,
_barCursorRenderer,
_blockCursorRenderer,
_frameCursorRenderer,
_copyModeCursorRenderer ];
}
 
Loading
Loading
Loading
Loading
@@ -188,10 +188,6 @@ static NSColor *ColorForVector(vector_float4 v) {
}
_cursorInfo = [[iTermMetalCursorInfo alloc] init];
#warning TODO: blinking cursor
NSLog(@"Visible range is [%d, %d), have %d lines of scrollback",
(int)_visibleRange.start.y,
(int)_visibleRange.end.y,
(int)_numberOfScrollbackLines);
NSInteger lineWithCursor = textView.dataSource.cursorY - 1 + _numberOfScrollbackLines;
if ([self shouldDrawCursor] &&
textView.cursorVisible &&
Loading
Loading
@@ -199,7 +195,6 @@ static NSColor *ColorForVector(vector_float4 v) {
lineWithCursor + 1 < _visibleRange.end.y) {
const int offset = _visibleRange.start.y - _numberOfScrollbackLines;
_cursorInfo.cursorVisible = YES;
NSLog(@"Cursor is visible on line %d (%d of visible region)", (int)lineWithCursor, (int)(lineWithCursor - _visibleRange.start.y));
_cursorInfo.type = textView.drawingHelper.cursorType;
_cursorInfo.coord = VT100GridCoordMake(textView.dataSource.cursorX - 1,
textView.dataSource.cursorY - 1 - offset);
Loading
Loading
@@ -233,7 +228,6 @@ static NSColor *ColorForVector(vector_float4 v) {
}
}
} else {
NSLog(@"Cursor is not visible");
_cursorInfo.cursorVisible = NO;
}
}
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