1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-11 04:28:58 +00:00

Reintroduces screenshots.

This commit is contained in:
Thomas Harte 2020-09-14 20:33:05 -04:00
parent ceeadd6a33
commit c0c7818d5d

View File

@ -373,6 +373,26 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
} }
} }
- (id<MTLCommandBuffer>)copyTexture:(id<MTLTexture>)source to:(id<MTLTexture>)destination {
MTLRenderPassDescriptor *const copyTextureDescriptor = [[MTLRenderPassDescriptor alloc] init];
copyTextureDescriptor.colorAttachments[0].texture = destination;
copyTextureDescriptor.colorAttachments[0].loadAction = MTLLoadActionDontCare;
copyTextureDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor:copyTextureDescriptor];
[encoder setRenderPipelineState:_copyPipeline];
[encoder setVertexTexture:source atIndex:0];
[encoder setFragmentTexture:source atIndex:0];
[encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
[encoder endEncoding];
[commandBuffer commit];
return commandBuffer;
}
- (void)updateSizeBuffersToSize:(CGSize)size { - (void)updateSizeBuffersToSize:(CGSize)size {
const NSUInteger frameBufferWidth = NSUInteger(size.width * _view.layer.contentsScale) * (_isUsingSupersampling ? 2 : 1); const NSUInteger frameBufferWidth = NSUInteger(size.width * _view.layer.contentsScale) * (_isUsingSupersampling ? 2 : 1);
const NSUInteger frameBufferHeight = NSUInteger(size.height * _view.layer.contentsScale) * (_isUsingSupersampling ? 2 : 1); const NSUInteger frameBufferHeight = NSUInteger(size.height * _view.layer.contentsScale) * (_isUsingSupersampling ? 2 : 1);
@ -418,21 +438,7 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
// Draw from _oldFrameBuffer to _frameBuffer. // Draw from _oldFrameBuffer to _frameBuffer.
if(_oldFrameBuffer) { if(_oldFrameBuffer) {
MTLRenderPassDescriptor *const resizeFrameBufferDescriptor = [[MTLRenderPassDescriptor alloc] init]; [self copyTexture:_oldFrameBuffer to:_frameBuffer];
resizeFrameBufferDescriptor.colorAttachments[0].texture = _frameBuffer;
resizeFrameBufferDescriptor.colorAttachments[0].loadAction = MTLLoadActionDontCare;
resizeFrameBufferDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor:resizeFrameBufferDescriptor];
[encoder setRenderPipelineState:_copyPipeline];
[encoder setVertexTexture:_oldFrameBuffer atIndex:0];
[encoder setFragmentTexture:_oldFrameBuffer atIndex:0];
[encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
[encoder endEncoding];
[commandBuffer commit];
// Don't clear the framebuffer at the end of this frame. // Don't clear the framebuffer at the end of this frame.
_dontClearFrameBuffer = YES; _dontClearFrameBuffer = YES;
@ -1121,8 +1127,7 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
} }
- (NSBitmapImageRep *)imageRepresentation { - (NSBitmapImageRep *)imageRepresentation {
// TODO: create a temporary texture, copy, and do as below but not re: _frameBuffer. // Create an NSBitmapRep as somewhere to copy pixel data to.
NSBitmapImageRep *const result = NSBitmapImageRep *const result =
[[NSBitmapImageRep alloc] [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL initWithBitmapDataPlanes:NULL
@ -1136,11 +1141,39 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
bytesPerRow:4 * (NSInteger)_frameBuffer.width bytesPerRow:4 * (NSInteger)_frameBuffer.width
bitsPerPixel:0]; bitsPerPixel:0];
// [_frameBuffer // Create a CPU-accessible texture and copy the current contents of the _frameBuffer to it.
// getBytes:result.bitmapData // TODO: supersample rather than directly copy if appropriate?
// bytesPerRow:_frameBuffer.width*4 id<MTLTexture> cpuTexture;
// fromRegion:MTLRegionMake2D(0, 0, _frameBuffer.width, _frameBuffer.height) MTLTextureDescriptor *const textureDescriptor = [MTLTextureDescriptor
// mipmapLevel:0]; texture2DDescriptorWithPixelFormat:_view.colorPixelFormat
width:_frameBuffer.width
height:_frameBuffer.height
mipmapped:NO];
textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
textureDescriptor.resourceOptions = MTLResourceStorageModeManaged;
cpuTexture = [_view.device newTextureWithDescriptor:textureDescriptor];
[[self copyTexture:_frameBuffer to:cpuTexture] waitUntilCompleted];
// Copy from the CPU-visible texture to the bitmap image representation.
uint8_t *const bitmapData = result.bitmapData;
[cpuTexture
getBytes:bitmapData
bytesPerRow:_frameBuffer.width*4
fromRegion:MTLRegionMake2D(0, 0, _frameBuffer.width, _frameBuffer.height)
mipmapLevel:0];
// Set alpha to fully opaque and do some byte shuffling if necessary;
// Apple likes BGR for output but RGB is the best I can specify to NSBitmapImageRep.
const NSUInteger totalBytes = _frameBuffer.width * _frameBuffer.height * 4;
const bool flipRedBlue = _view.colorPixelFormat == MTLPixelFormatBGRA8Unorm;
for(NSUInteger offset = 0; offset < totalBytes; offset += 4) {
if(flipRedBlue) {
const uint8_t red = bitmapData[offset];
bitmapData[offset] = bitmapData[offset+2];
bitmapData[offset+2] = red;
}
bitmapData[offset+3] = 0xff;
}
return result; return result;
} }