mirror of
https://github.com/zakk4223/CocoaSplit.git
synced 2026-05-15 22:00:34 -06:00
Syphon sources now use a subclass of CAOpenGLLayer and render the texture directly via OpenGL, instead of going through a CIImage/IOSurface.
This commit is contained in:
parent
1c1ce046c5
commit
23162314c0
8 changed files with 265 additions and 8 deletions
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
3429A0491A41063900EE702C /* CSSyphonInjectCaptureViewNotInstalled.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3429A0481A41063900EE702C /* CSSyphonInjectCaptureViewNotInstalled.xib */; };
|
||||
3479A99A1A91C5A500A524F0 /* CSSyphonCaptureLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3479A9991A91C5A500A524F0 /* CSSyphonCaptureLayer.m */; };
|
||||
34AFC1D719B04EB90007C07B /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34AFC1D619B04EB90007C07B /* Cocoa.framework */; };
|
||||
34AFC1E119B04EB90007C07B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 34AFC1DF19B04EB90007C07B /* InfoPlist.strings */; };
|
||||
34AFC1F319B04F0B0007C07B /* SyphonCaptureViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34AFC1EF19B04F0B0007C07B /* SyphonCaptureViewController.m */; };
|
||||
|
|
@ -67,6 +68,8 @@
|
|||
344E1EAB1A79481C0081E5E7 /* CSPluginFactoryProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSPluginFactoryProtocol.h; path = PluginHeaders/CSPluginFactoryProtocol.h; sourceTree = "<group>"; };
|
||||
344E1EAC1A79481C0081E5E7 /* CSExtraPluginProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSExtraPluginProtocol.h; path = PluginHeaders/CSExtraPluginProtocol.h; sourceTree = "<group>"; };
|
||||
344E1EAD1A79481C0081E5E7 /* CSNotifications.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSNotifications.h; path = PluginHeaders/CSNotifications.h; sourceTree = "<group>"; };
|
||||
3479A9981A91C5A500A524F0 /* CSSyphonCaptureLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSyphonCaptureLayer.h; sourceTree = "<group>"; };
|
||||
3479A9991A91C5A500A524F0 /* CSSyphonCaptureLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSyphonCaptureLayer.m; sourceTree = "<group>"; };
|
||||
34AFC1D319B04EB90007C07B /* CSSyphonCapturePlugin.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CSSyphonCapturePlugin.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
34AFC1D619B04EB90007C07B /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
34AFC1D919B04EB90007C07B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
|
|
@ -177,6 +180,8 @@
|
|||
34C7B8CA1A34621C0033AC71 /* CSSyphonCaptureFactory.h */,
|
||||
34C7B8CB1A34621C0033AC71 /* CSSyphonCaptureFactory.m */,
|
||||
34AFC1DD19B04EB90007C07B /* Supporting Files */,
|
||||
3479A9981A91C5A500A524F0 /* CSSyphonCaptureLayer.h */,
|
||||
3479A9991A91C5A500A524F0 /* CSSyphonCaptureLayer.m */,
|
||||
);
|
||||
path = CSSyphonCapturePlugin;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -300,6 +305,7 @@
|
|||
34C7B8CC1A34621C0033AC71 /* CSSyphonCaptureFactory.m in Sources */,
|
||||
34C7B8DB1A3465010033AC71 /* CSSyphonInjectCaptureViewController.m in Sources */,
|
||||
34AFC1F519B04F0B0007C07B /* SyphonCapture.m in Sources */,
|
||||
3479A99A1A91C5A500A524F0 /* CSSyphonCaptureLayer.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// CSSyphonCaptureLayer.h
|
||||
// CSSyphonCapturePlugin
|
||||
//
|
||||
// Created by Zakk on 2/16/15.
|
||||
// Copyright (c) 2015 Zakk. All rights reserved.
|
||||
//
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import "SyphonBuildMacros.h"
|
||||
#import "Syphon.h"
|
||||
|
||||
@interface CSSyphonCaptureLayer : CAOpenGLLayer
|
||||
{
|
||||
CGLContextObj _myCGLContext;
|
||||
CGRect _lastBounds;
|
||||
CGSize _lastImageSize;
|
||||
CGRect _privateCropRect;
|
||||
CGRect _lastCrop;
|
||||
CGRect _calculatedCrop;
|
||||
bool _needsRedraw;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@property (strong) SyphonClient *syphonClient;
|
||||
@property (assign) bool flipImage;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
//
|
||||
// CSSyphonCaptureLayer.m
|
||||
// CSSyphonCapturePlugin
|
||||
//
|
||||
// Created by Zakk on 2/16/15.
|
||||
// Copyright (c) 2015 Zakk. All rights reserved.
|
||||
//
|
||||
|
||||
#import "CSSyphonCaptureLayer.h"
|
||||
|
||||
@implementation CSSyphonCaptureLayer
|
||||
|
||||
@synthesize flipImage = _flipImage;
|
||||
|
||||
-(instancetype)init
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
self.asynchronous = YES;
|
||||
self.needsDisplayOnBoundsChange = YES;
|
||||
self.flipImage = NO;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
-(void)calculateCrop:(CGSize)forSize;
|
||||
{
|
||||
CGRect newCrop;
|
||||
|
||||
newCrop.origin.x = forSize.width * _privateCropRect.origin.x;
|
||||
newCrop.origin.y = forSize.height * _privateCropRect.origin.y;
|
||||
newCrop.size.width = forSize.width * _privateCropRect.size.width;
|
||||
newCrop.size.height = forSize.height * _privateCropRect.size.height;
|
||||
//_lastImageSize = forSize;
|
||||
_calculatedCrop = newCrop;
|
||||
}
|
||||
|
||||
|
||||
-(void)setContentsRect:(CGRect)contentsRect
|
||||
{
|
||||
_privateCropRect = contentsRect;
|
||||
[self calculateCrop:_lastImageSize];
|
||||
_needsRedraw = YES;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
-(CGRect)contentsRect
|
||||
{
|
||||
return _privateCropRect;
|
||||
}
|
||||
|
||||
-(void)setFlipImage:(bool)flipImage
|
||||
{
|
||||
_flipImage = flipImage;
|
||||
_needsRedraw = YES;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
-(bool)flipImage
|
||||
{
|
||||
return _flipImage;
|
||||
}
|
||||
|
||||
|
||||
-(CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pf
|
||||
{
|
||||
_myCGLContext = [super copyCGLContextForPixelFormat:pf];
|
||||
|
||||
return _myCGLContext;
|
||||
}
|
||||
|
||||
|
||||
-(BOOL)canDrawInCGLContext:(CGLContextObj)ctx pixelFormat:(CGLPixelFormatObj)pf forLayerTime:(CFTimeInterval)t displayTime:(const CVTimeStamp *)ts
|
||||
{
|
||||
bool boundsChanged = !CGRectEqualToRect(self.bounds, _lastBounds);
|
||||
|
||||
if (boundsChanged || self.syphonClient.hasNewFrame || _needsRedraw)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
-(void)drawInCGLContext:(CGLContextObj)ctx pixelFormat:(CGLPixelFormatObj)pf forLayerTime:(CFTimeInterval)t displayTime:(const CVTimeStamp *)ts
|
||||
{
|
||||
CGLContextObj cgl_ctx = ctx;
|
||||
CGLSetCurrentContext(ctx);
|
||||
glClearColor(0,0,0,0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
|
||||
SyphonImage *image = [self.syphonClient newFrameImageForContext:cgl_ctx];
|
||||
|
||||
|
||||
if (!image)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool imageSizeChanged = !CGSizeEqualToSize(_lastImageSize, image.textureSize);
|
||||
|
||||
|
||||
|
||||
if (imageSizeChanged)
|
||||
{
|
||||
[self calculateCrop:image.textureSize];
|
||||
}
|
||||
|
||||
_lastCrop = _calculatedCrop;
|
||||
|
||||
_lastImageSize = image.textureSize;
|
||||
|
||||
_lastBounds = self.bounds;
|
||||
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0.0, self.bounds.size.width, 0.0, self.bounds.size.height, -1, 1);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
|
||||
|
||||
glTranslated(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5, 0.0);
|
||||
|
||||
glEnable(GL_TEXTURE_RECTANGLE_EXT);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, image.textureName);
|
||||
|
||||
GLfloat tex_coords[] =
|
||||
{
|
||||
_calculatedCrop.origin.x , _calculatedCrop.origin.y,
|
||||
_calculatedCrop.origin.x+_calculatedCrop.size.width, _calculatedCrop.origin.y,
|
||||
_calculatedCrop.origin.x+_calculatedCrop.size.width, _calculatedCrop.origin.y+_calculatedCrop.size.height,
|
||||
_calculatedCrop.origin.x, _calculatedCrop.origin.y+_calculatedCrop.size.height
|
||||
};
|
||||
|
||||
NSSize useSize = self.bounds.size;
|
||||
|
||||
if ([self.contentsGravity isEqualToString:kCAGravityResizeAspect])
|
||||
{
|
||||
float wr = _calculatedCrop.size.width / self.bounds.size.width;
|
||||
float hr = _calculatedCrop.size.height / self.bounds.size.height;
|
||||
|
||||
float ratio = (hr < wr ? wr : hr);
|
||||
useSize = NSMakeSize(_calculatedCrop.size.width / ratio, _calculatedCrop.size.height / ratio);
|
||||
|
||||
}
|
||||
|
||||
|
||||
float halfw = useSize.width * 0.5;
|
||||
float halfh = useSize.height * 0.5;
|
||||
|
||||
if (self.flipImage)
|
||||
{
|
||||
halfh *= -1;
|
||||
}
|
||||
|
||||
|
||||
GLfloat verts[] =
|
||||
{
|
||||
-halfw, halfh,
|
||||
halfw, halfh,
|
||||
halfw, -halfh,
|
||||
-halfw, -halfh
|
||||
};
|
||||
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, tex_coords );
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, verts );
|
||||
glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
|
||||
glDisable(GL_TEXTURE_RECTANGLE_EXT);
|
||||
[super drawInCGLContext:ctx pixelFormat:pf forLayerTime:t displayTime:ts];
|
||||
_needsRedraw = NO;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
#import "SyphonBuildMacros.h"
|
||||
#import "Syphon.h"
|
||||
#import "CSIOSurfaceLayer.h"
|
||||
#import "CSSyphonCaptureLayer.h"
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -107,7 +107,13 @@
|
|||
|
||||
-(CALayer *)createNewLayer
|
||||
{
|
||||
CSIOSurfaceLayer *newLayer = [CSIOSurfaceLayer layer];
|
||||
CSSyphonCaptureLayer *newLayer = [CSSyphonCaptureLayer layer];
|
||||
|
||||
if (_syphon_client)
|
||||
{
|
||||
newLayer.syphonClient = _syphon_client;
|
||||
}
|
||||
|
||||
|
||||
newLayer.flipImage = self.isFlipped;
|
||||
return newLayer;
|
||||
|
|
@ -133,6 +139,10 @@
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
-(void)publishSurface:(IOSurfaceRef)surface
|
||||
{
|
||||
|
||||
|
|
@ -140,14 +150,18 @@
|
|||
|
||||
if (newSeed != _surfaceSeed)
|
||||
{
|
||||
CIImage *newImage = [[CIImage alloc] initWithIOSurface:surface plane:0 format:kCIFormatARGB8 options:nil];
|
||||
CIImage *newImage = [[CIImage alloc] initWithIOSurface:surface plane:0 format:kCIFormatARGB8 options:@{kCIImageColorSpace:[NSNull null]}];
|
||||
|
||||
|
||||
|
||||
_surfaceSeed = newSeed;
|
||||
[self updateLayersWithBlock:^(CALayer *layer) {
|
||||
((CSIOSurfaceLayer *)layer).ioImage = newImage;
|
||||
}];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
-(void) startSyphon
|
||||
{
|
||||
|
|
@ -166,22 +180,32 @@
|
|||
if (_syphonServer)
|
||||
{
|
||||
_syphon_client = [[SyphonClient alloc] initWithServerDescription:_syphonServer.copy options:nil newFrameHandler:^(SyphonClient *client) {
|
||||
|
||||
|
||||
//[self publishFrame:client];
|
||||
/*
|
||||
//this call retains the surface, so be sure to release it if we don't care about it anymore
|
||||
IOSurfaceRef newSurface = [client IOSurface];
|
||||
|
||||
[self publishSurface:newSurface];
|
||||
|
||||
CFRelease(newSurface);
|
||||
*/
|
||||
}];
|
||||
|
||||
|
||||
|
||||
[self updateLayersWithBlock:^(CALayer *layer) {
|
||||
((CSSyphonCaptureLayer *)layer).syphonClient = _syphon_client;
|
||||
}];
|
||||
|
||||
/*
|
||||
IOSurfaceRef newSurface = [_syphon_client IOSurface];
|
||||
if (newSurface)
|
||||
{
|
||||
[self publishSurface:newSurface];
|
||||
CFRelease(newSurface);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
_syphon_uuid = [[_syphon_client serverDescription] objectForKey:SyphonServerDescriptionUUIDKey];
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6250" systemVersion="14B25" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6250" systemVersion="14C109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6250"/>
|
||||
|
|
|
|||
|
|
@ -99,6 +99,8 @@
|
|||
@interface CSIOSurfaceLayer()
|
||||
{
|
||||
CIFilter *_resizeFilter;
|
||||
CIFilter *_matrixFilter;
|
||||
|
||||
}
|
||||
@property (strong) CIImageWrapper *imageWrapper;
|
||||
@end
|
||||
|
|
@ -226,7 +228,7 @@
|
|||
CIImageWrapper *wrappedImage = self.imageWrapper;
|
||||
|
||||
CGLSetCurrentContext(ctx);
|
||||
glClearColor(0,0,0,0);
|
||||
glClearColor(1,0,0,0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
|
||||
|
|
@ -266,6 +268,8 @@
|
|||
croppedImage = [useImage imageByCroppingToRect:_calculatedCrop];
|
||||
|
||||
|
||||
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
if (self.flipImage)
|
||||
|
|
@ -304,6 +308,8 @@
|
|||
//croppedImage = [_resizeFilter valueForKey:kCIOutputImageKey];
|
||||
}
|
||||
|
||||
|
||||
|
||||
[_ciCtx drawImage:croppedImage inRect:inRect fromRect:croppedImage.extent];
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6250" systemVersion="14B25" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6250" systemVersion="14C109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6250"/>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue