Skip to content

Commit

Permalink
Merge pull request #23 from tillt/till/fix-vimage-on-hackintosh
Browse files Browse the repository at this point in the history
Trying to fix vimage failures
  • Loading branch information
tillt authored Nov 27, 2023
2 parents 35a6f4e + 2742780 commit 9a4f841
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 29 deletions.
11 changes: 4 additions & 7 deletions KompleteSynthesia.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
BB229913299040C500CFFB7C /* ApplicationObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = BB229912299040C500CFFB7C /* ApplicationObserver.m */; };
BB31821629679983005EB410 /* MIDIController.m in Sources */ = {isa = PBXBuildFile; fileRef = BB31821529679983005EB410 /* MIDIController.m */; };
BB3182192967A037005EB410 /* HIDController.m in Sources */ = {isa = PBXBuildFile; fileRef = BB3182182967A037005EB410 /* HIDController.m */; };
BB34BC1F2B081E45004CF123 /* build_dmg.sh in Resources */ = {isa = PBXBuildFile; fileRef = BB34BC1D2B081E45004CF123 /* build_dmg.sh */; };
BB34BC202B081E45004CF123 /* set_build_number.sh in Resources */ = {isa = PBXBuildFile; fileRef = BB34BC1E2B081E45004CF123 /* set_build_number.sh */; };
BB49B3B2295CC8AE00D18605 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BB49B3B1295CC8AE00D18605 /* AppDelegate.m */; };
BB49B3B4295CC8AF00D18605 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BB49B3B3295CC8AF00D18605 /* Assets.xcassets */; };
BB49B3B7295CC8AF00D18605 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = BB49B3B5295CC8AF00D18605 /* MainMenu.xib */; };
Expand Down Expand Up @@ -194,7 +192,7 @@
BB49B3A9295CC8AE00D18605 /* Sources */,
BB49B3AA295CC8AE00D18605 /* Frameworks */,
BB49B3AB295CC8AE00D18605 /* Resources */,
BB34BC1A2B081D23004CF123 /* ShellScript */,
BB34BC1A2B081D23004CF123 /* Run Script */,
);
buildRules = (
);
Expand Down Expand Up @@ -244,8 +242,6 @@
files = (
BB49B3C4295CC91000D18605 /* LogViewController.xib in Resources */,
BB76A1A5297B333D00A869D8 /* PreferencesWindowController.xib in Resources */,
BB34BC202B081E45004CF123 /* set_build_number.sh in Resources */,
BB34BC1F2B081E45004CF123 /* build_dmg.sh in Resources */,
BB49B3B4295CC8AF00D18605 /* Assets.xcassets in Resources */,
BB7AB64329807A700081B05E /* PaletteViewController.xib in Resources */,
BB49B3B7295CC8AF00D18605 /* MainMenu.xib in Resources */,
Expand All @@ -255,9 +251,9 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
BB34BC1A2B081D23004CF123 /* ShellScript */ = {
BB34BC1A2B081D23004CF123 /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
buildActionMask = 12;
files = (
);
inputFileListPaths = (
Expand All @@ -266,6 +262,7 @@
" $(TARGET_BUILD_DIR)/$(INFOPLIST_PATH)",
"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)/Contents/Info.plist",
);
name = "Run Script";
outputFileListPaths = (
);
outputPaths = (
Expand Down
75 changes: 53 additions & 22 deletions KompleteSynthesia/VideoController.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
@implementation VideoController
{
void* screenBuffer[2];
void* resizeBuffer;
void* tempBuffer;
void* imageConversionScaleBuffer;
void* imageConversionTempBuffer;
CGSize imageConversionTempBufferDimensions;

USBController* usb;
LogViewController* log;
atomic_int stopMirroring;
Expand All @@ -44,7 +46,11 @@ - (id)initWithLogViewController:(LogViewController*)lc error:(NSError**)error
screenBuffer[1] = NULL;
atomic_fetch_and(&stopMirroring, 0);
atomic_fetch_and(&mirrorActive, 0);


imageConversionTempBuffer = NULL;
imageConversionTempBufferDimensions = CGSizeMake(0,0);
imageConversionScaleBuffer = NULL;

log = lc;

usb = [[USBController alloc] initWithError:error];
Expand All @@ -55,9 +61,9 @@ - (id)initWithLogViewController:(LogViewController*)lc error:(NSError**)error

if (usb.mk > 1) {
_screenCount = usb.mk == 2 ? 2 : 1;
// FIXME: We don't know the resolution the MK3 screen.
_screenSize = usb.mk == 2 ? CGSizeMake(480.0f, 272.0f) : CGSizeMake(480.0f, 272.0f);
tempBuffer = malloc(_screenSize.width * 4 * _screenSize.height);
resizeBuffer = malloc(_screenSize.width * 4 * _screenSize.height);

// width * height * 2 (261120) + commands (36)
stream = [[NSMutableData alloc] initWithCapacity:(_screenSize.width * 2 * _screenSize.height) + 36];

Expand Down Expand Up @@ -90,6 +96,9 @@ - (void)teardown
{
[self stopMirroringAndWait:YES];

// FIXME: We are transmitting data via USB but not waiting for the transfer
// to be done here. That has the risk of interfering with other transfers. The right
// solution here would be a producer/consumer pattern on two threads.
[self clearScreen:0 error:nil];
[self clearScreen:1 error:nil];

Expand All @@ -100,6 +109,9 @@ - (BOOL)startMirroring
{
atomic_fetch_and(&stopMirroring, 0);

// FIXME: We are transmitting data via USB but not waiting for the transfer
// to be done here. That has the risk of interfering with other transfers. The right
// solution here would be a producer/consumer pattern on two threads.
if ([self clearScreen:0 error:nil] == NO) {
return NO;
}
Expand Down Expand Up @@ -167,14 +179,17 @@ - (BOOL)reset:(NSError**)error
NSLog(@"we need the USB device to be accessable");
return NO;
}

NSImage* image = [NSImage imageNamed:@"ScreenOne"];
CGImageRef cgi = [image CGImageForProposedRect:NULL context:NULL hints:NULL];
[self drawCGImage:cgi screen:1 x:0 y:0 error:nil];

dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
[self stopMirroringAndWait:YES];

NSImage* image = [NSImage imageNamed:@"ScreenOne"];
CGImageRef cgi = [image CGImageForProposedRect:NULL context:NULL hints:NULL];
[self drawCGImage:cgi screen:1 x:0 y:0 error:nil];

// Assure extreme delay after sending data to screen 2 to make sure the first screen transfer does not interfere.
[NSThread sleepForTimeInterval:0.05f];

dispatch_async(dispatch_get_main_queue(), ^{
[self startMirroring];
});
Expand All @@ -189,13 +204,29 @@ - (void)NIImageFromCGImage:(CGImageRef)source destination:(NIImage*)destination
unsigned long width = CGImageGetWidth(source);
unsigned long height = CGImageGetHeight(source);

// We make use of the vImage tempBuffer feature, allowing us to provide an operational
// buffer for conversion and scaling. The source of our operation is resizeable during
// runtime and thus we need to make sure the tempBuffer is properly sized.
if (imageConversionTempBufferDimensions.width != width ||
imageConversionTempBufferDimensions.height != height) {
if (imageConversionTempBuffer != NULL) {
free(imageConversionTempBuffer);
}
if (imageConversionScaleBuffer != NULL) {
free(imageConversionScaleBuffer);
}
imageConversionTempBufferDimensions = CGSizeMake(width, height);
imageConversionTempBuffer = malloc(CGImageGetBytesPerRow(source) * height);
imageConversionScaleBuffer = malloc(CGImageGetBytesPerRow(source) * _screenSize.height);
}

CFDataRef raw = CGDataProviderCopyData(CGImageGetDataProvider(source));

vImage_Buffer sourceBuffer = {
(void*)CFDataGetBytePtr(raw),
height,
width,
(((width + 31) >> 5) << 5) * 4 // Stride is remains for chunks of 32 pixels.
CGImageGetBytesPerRow(source)
};

vImage_CGImageFormat sourceFormat = {
Expand All @@ -209,22 +240,26 @@ - (void)NIImageFromCGImage:(CGImageRef)source destination:(NIImage*)destination
if (width > _screenSize.width || height > _screenSize.height ) {
// We want to skip the header part of the application window, that does not add any
// value in the mirrored image.
// FIXME: This is a rather surprising way of cropping the header off - but efficient.
sourceBuffer.data += kHeaderHeight * sourceBuffer.rowBytes;
sourceBuffer.height -= kHeaderHeight;

vImage_Buffer resizedBuffer = {
resizeBuffer,
imageConversionScaleBuffer,
_screenSize.height,
_screenSize.width,
_screenSize.width * 4
_screenSize.width * (((unsigned int)CGImageGetBitsPerPixel(source)) >> 3)
};

vImageScale_ARGB8888(&sourceBuffer, &resizedBuffer, nil, kvImageHighQualityResampling | kvImageDoNotTile);
vImageScale_ARGB8888(&sourceBuffer,
&resizedBuffer,
imageConversionTempBuffer,
kvImageDoNotTile);

sourceBuffer.data = resizeBuffer;
sourceBuffer.height = _screenSize.height;
sourceBuffer.width = _screenSize.width;
sourceBuffer.rowBytes = _screenSize.width * 4;
sourceBuffer.data = imageConversionScaleBuffer;
sourceBuffer.height = resizedBuffer.height;
sourceBuffer.width = resizedBuffer.width;
sourceBuffer.rowBytes = resizedBuffer.rowBytes;
}

vImage_CGImageFormat screenFormat = {
Expand All @@ -235,8 +270,6 @@ - (void)NIImageFromCGImage:(CGImageRef)source destination:(NIImage*)destination
};

vImage_Error err = kvImageNoError;
// Do not attempt to invoke internal tiling with the image converter: `kvImageDoNotTile`
// should prevent https://github.com/tillt/KompleteSynthesia/issues/21.
vImageConverterRef converter = vImageConverter_CreateWithCGImageFormat(&sourceFormat,
&screenFormat,
NULL,
Expand All @@ -249,12 +282,10 @@ - (void)NIImageFromCGImage:(CGImageRef)source destination:(NIImage*)destination
destination->width * 2
};

// Do not attempt to invoke internal tiling with the image converter: `kvImageDoNotTile`
// should prevent https://github.com/tillt/KompleteSynthesia/issues/21.
vImageConvert_AnyToAny(converter,
&sourceBuffer,
&destinationBuffer,
tempBuffer,
imageConversionTempBuffer,
kvImageDoNotTile);

vImageConverter_Release(converter);
Expand Down

0 comments on commit 9a4f841

Please sign in to comment.