Cocoa Port:

- Optimize OpenGL blitter for better performance (now uses display lists instead of rendering in immediate mode).
- Some refactoring and code cleanup of the video output code.
This commit is contained in:
rogerman 2012-11-24 05:45:59 +00:00
parent ba35ebce6a
commit c87672f680
5 changed files with 550 additions and 326 deletions

View File

@ -95,23 +95,28 @@
@protocol CocoaDSDisplayDelegate <NSObject>
@required
- (void) doInitVideoOutput:(NSDictionary *)properties;
- (void) doProcessVideoFrame:(const void *)videoFrameData frameSize:(NSSize)frameSize;
- (void) doDisplayTypeChanged:(NSInteger)displayTypeID;
@property (retain) NSPort *sendPortDisplay;
@property (assign) BOOL isHudEnabled;
@property (assign) BOOL isHudEditingModeEnabled;
@end
@protocol CocoaDSDisplayVideoDelegate <CocoaDSDisplayDelegate>
@required
- (void) doInitVideoOutput:(NSDictionary *)properties;
- (void) doProcessVideoFrame:(const void *)videoFrameData frameSize:(NSSize)frameSize;
@optional
- (void) doResizeView:(NSRect)rect;
- (void) doRedraw;
- (void) doDisplayTypeChanged:(NSInteger)displayTypeID;
- (void) doDisplayOrientationChanged:(NSInteger)displayOrientationID;
- (void) doDisplayOrderChanged:(NSInteger)displayOrderID;
- (void) doBilinearOutputChanged:(BOOL)useBilinear;
- (void) doVerticalSyncChanged:(BOOL)useVerticalSync;
- (void) doVideoFilterChanged:(NSInteger)videoFilterTypeID;
@property (assign) BOOL isHudEnabled;
@property (assign) BOOL isHudEditingModeEnabled;
- (void) doVideoFilterChanged:(NSInteger)videoFilterTypeID frameSize:(NSSize)videoFilterDestSize;
@end
@ -121,14 +126,12 @@
UInt32 gpuStateFlags;
id <CocoaDSDisplayDelegate> delegate;
NSInteger displayType;
CocoaVideoFilter *vf;
NSSize frameSize;
pthread_mutex_t *mutexRender3D;
OSSpinLock spinlockDelegate;
OSSpinLock spinlockGpuState;
OSSpinLock spinlockDisplayType;
OSSpinLock spinlockVideoFilterType;
OSSpinLock spinlockVfSrcBuffer;
OSSpinLock spinlockRender3DRenderingEngine;
OSSpinLock spinlockRender3DHighPrecisionColorInterpolation;
OSSpinLock spinlockRender3DEdgeMarking;
@ -142,7 +145,7 @@
@property (assign) UInt32 gpuStateFlags;
@property (retain) id <CocoaDSDisplayDelegate> delegate;
@property (assign) NSInteger displayType;
@property (assign) CocoaVideoFilter *vf;
@property (readonly) NSSize frameSize;
@property (readonly) pthread_mutex_t *mutexRender3D;
- (void) setRender3DRenderingEngine:(NSInteger)methodID;
@ -162,15 +165,8 @@
- (void) setRender3DLineHack:(BOOL)state;
- (BOOL) render3DLineHack;
- (void) handleResizeView:(NSData *)rectData;
- (void) handleRedrawView;
- (void) handleChangeGpuStateFlags:(NSData *)flagsData;
- (void) handleChangeDisplayType:(NSData *)displayTypeIdData;
- (void) handleChangeDisplayOrientation:(NSData *)displayOrientationIdData;
- (void) handleChangeDisplayOrder:(NSData *)displayOrderIdData;
- (void) handleChangeBilinearOutput:(NSData *)bilinearStateData;
- (void) handleChangeVerticalSync:(NSData *)verticalSyncStateData;
- (void) handleChangeVideoFilter:(NSData *)videoFilterTypeIdData;
- (void) handleSetRender3DRenderingEngine:(NSData *)methodIdData;
- (void) handleSetRender3DHighPrecisionColorInterpolation:(NSData *)stateData;
- (void) handleSetRender3DEdgeMarking:(NSData *)stateData;
@ -196,6 +192,28 @@
@end
@interface CocoaDSDisplayVideo : CocoaDSDisplay
{
CocoaVideoFilter *vf;
id <CocoaDSDisplayVideoDelegate> videoDelegate;
OSSpinLock spinlockVideoFilterType;
OSSpinLock spinlockVfSrcBuffer;
}
@property (retain) id <CocoaDSDisplayVideoDelegate> delegate;
@property (assign) CocoaVideoFilter *vf;
- (void) handleResizeView:(NSData *)rectData;
- (void) handleRedrawView;
- (void) handleChangeDisplayOrientation:(NSData *)displayOrientationIdData;
- (void) handleChangeDisplayOrder:(NSData *)displayOrderIdData;
- (void) handleChangeBilinearOutput:(NSData *)bilinearStateData;
- (void) handleChangeVerticalSync:(NSData *)verticalSyncStateData;
- (void) handleChangeVideoFilter:(NSData *)videoFilterTypeIdData;
@end
#ifdef __cplusplus
extern "C"
{

View File

@ -434,9 +434,9 @@ GPU3DInterface *core3DList[] = {
@implementation CocoaDSDisplay
@synthesize gpuStateFlags;
@synthesize delegate;
@synthesize displayType;
@synthesize vf;
@dynamic delegate;
@dynamic displayType;
@dynamic frameSize;
@synthesize mutexRender3D;
- (id)init
@ -453,8 +453,6 @@ GPU3DInterface *core3DList[] = {
spinlockDelegate = OS_SPINLOCK_INIT;
spinlockGpuState = OS_SPINLOCK_INIT;
spinlockDisplayType = OS_SPINLOCK_INIT;
spinlockVideoFilterType = OS_SPINLOCK_INIT;
spinlockVfSrcBuffer = OS_SPINLOCK_INIT;
spinlockRender3DRenderingEngine = OS_SPINLOCK_INIT;
spinlockRender3DHighPrecisionColorInterpolation = OS_SPINLOCK_INIT;
spinlockRender3DEdgeMarking = OS_SPINLOCK_INIT;
@ -465,7 +463,7 @@ GPU3DInterface *core3DList[] = {
spinlockRender3DLineHack = OS_SPINLOCK_INIT;
displayType = DS_DISPLAY_TYPE_COMBO;
vf = [[CocoaVideoFilter alloc] initWithSize:NSMakeSize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT * 2) typeID:VideoFilterTypeID_None numberThreads:2];
frameSize = NSMakeSize((CGFloat)GPU_DISPLAY_WIDTH, (CGFloat)GPU_DISPLAY_HEIGHT * 2);
gpuStateFlags = GPUSTATE_MAIN_GPU_MASK |
GPUSTATE_MAIN_BG0_MASK |
@ -498,8 +496,6 @@ GPU3DInterface *core3DList[] = {
[property setValue:[NSNumber numberWithBool:YES] forKey:@"gpuStateSubOBJ"];
[property setValue:[NSNumber numberWithInteger:displayType] forKey:@"displayMode"];
[property setValue:NSSTRING_DISPLAYMODE_MAIN forKey:@"displayModeString"];
[property setValue:[NSNumber numberWithInteger:(NSInteger)VideoFilterTypeID_None] forKey:@"videoFilterType"];
[property setValue:[CocoaVideoFilter typeStringByID:VideoFilterTypeID_None] forKey:@"videoFilterTypeString"];
[property setValue:[NSNumber numberWithInteger:CORE3DLIST_NULL] forKey:@"render3DRenderingEngine"];
[property setValue:[NSNumber numberWithBool:YES] forKey:@"render3DHighPrecisionColorInterpolation"];
[property setValue:[NSNumber numberWithBool:YES] forKey:@"render3DEdgeMarking"];
@ -515,7 +511,6 @@ GPU3DInterface *core3DList[] = {
- (void)dealloc
{
self.delegate = nil;
[vf release];
pthread_mutex_destroy(self.mutexRender3D);
free(self.mutexRender3D);
@ -710,7 +705,7 @@ GPU3DInterface *core3DList[] = {
- (void) setDisplayType:(NSInteger)dispType
{
NSString *newDispString = nil;
NSSize newSrcSize = NSMakeSize((CGFloat)GPU_DISPLAY_WIDTH, (CGFloat)GPU_DISPLAY_HEIGHT);
NSSize newFrameSize = NSMakeSize((CGFloat)GPU_DISPLAY_WIDTH, (CGFloat)GPU_DISPLAY_HEIGHT);
switch (dispType)
{
@ -724,7 +719,7 @@ GPU3DInterface *core3DList[] = {
case DS_DISPLAY_TYPE_COMBO:
newDispString = NSSTRING_DISPLAYMODE_COMBO;
newSrcSize.height *= 2;
newFrameSize.height *= 2;
break;
default:
@ -734,13 +729,10 @@ GPU3DInterface *core3DList[] = {
OSSpinLockLock(&spinlockDisplayType);
displayType = dispType;
frameSize = newFrameSize;
[property setValue:[NSNumber numberWithInteger:dispType] forKey:@"displayMode"];
[property setValue:newDispString forKey:@"displayModeString"];
OSSpinLockUnlock(&spinlockDisplayType);
OSSpinLockLock(&spinlockVfSrcBuffer);
[vf setSourceSize:newSrcSize];
OSSpinLockUnlock(&spinlockVfSrcBuffer);
}
- (NSInteger) displayType
@ -752,23 +744,13 @@ GPU3DInterface *core3DList[] = {
return dispType;
}
- (void) setVfType:(NSInteger)videoFilterTypeID
- (NSSize) frameSize
{
[vf changeFilter:(VideoFilterTypeID)videoFilterTypeID];
OSSpinLockLock(&spinlockDisplayType);
NSSize size = frameSize;
OSSpinLockUnlock(&spinlockDisplayType);
OSSpinLockLock(&spinlockVideoFilterType);
[property setValue:[NSNumber numberWithInteger:videoFilterTypeID] forKey:@"videoFilterType"];
[property setValue:NSLocalizedString([vf typeString], nil) forKey:@"videoFilterTypeString"];
OSSpinLockUnlock(&spinlockVideoFilterType);
}
- (NSInteger) vfType
{
OSSpinLockLock(&spinlockVideoFilterType);
NSInteger theType = [(NSNumber *)[property valueForKey:@"videoFilterType"] integerValue];
OSSpinLockUnlock(&spinlockVideoFilterType);
return theType;
return size;
}
- (void) setRender3DRenderingEngine:(NSInteger)methodID
@ -943,15 +925,14 @@ GPU3DInterface *core3DList[] = {
}
pthread_mutex_lock(self.mutexProducer);
CommonSettings.num_cores = numberCores;
pthread_mutex_unlock(self.mutexProducer);
CommonSettings.num_cores = numberCores;
if ([self render3DRenderingEngine] == CORE3DLIST_SWRASTERIZE)
{
pthread_mutex_lock(self.mutexProducer);
NDS_3D_ChangeCore(CORE3DLIST_SWRASTERIZE);
pthread_mutex_unlock(self.mutexProducer);
}
pthread_mutex_unlock(self.mutexProducer);
}
- (NSUInteger) render3DThreads
@ -989,15 +970,6 @@ GPU3DInterface *core3DList[] = {
return state;
}
- (void) runThread:(id)object
{
NSAutoreleasePool *tempPool = [[NSAutoreleasePool alloc] init];
[delegate doInitVideoOutput:self.property];
[tempPool release];
[super runThread:object];
}
- (void) doCoreEmuFrame
{
NSData *gpuData = nil;
@ -1037,14 +1009,6 @@ GPU3DInterface *core3DList[] = {
[self handleEmuFrameProcessed:[messageComponents objectAtIndex:0]];
break;
case MESSAGE_RESIZE_VIEW:
[self handleResizeView:[messageComponents objectAtIndex:0]];
break;
case MESSAGE_REDRAW_VIEW:
[self handleRedrawView];
break;
case MESSAGE_SET_GPU_STATE_FLAGS:
[self handleChangeGpuStateFlags:[messageComponents objectAtIndex:0]];
break;
@ -1053,26 +1017,6 @@ GPU3DInterface *core3DList[] = {
[self handleChangeDisplayType:[messageComponents objectAtIndex:0]];
break;
case MESSAGE_CHANGE_DISPLAY_ORIENTATION:
[self handleChangeDisplayOrientation:[messageComponents objectAtIndex:0]];
break;
case MESSAGE_CHANGE_DISPLAY_ORDER:
[self handleChangeDisplayOrder:[messageComponents objectAtIndex:0]];
break;
case MESSAGE_CHANGE_BILINEAR_OUTPUT:
[self handleChangeBilinearOutput:[messageComponents objectAtIndex:0]];
break;
case MESSAGE_CHANGE_VERTICAL_SYNC:
[self handleChangeVerticalSync:[messageComponents objectAtIndex:0]];
break;
case MESSAGE_CHANGE_VIDEO_FILTER:
[self handleChangeVideoFilter:[messageComponents objectAtIndex:0]];
break;
case MESSAGE_SET_RENDER3D_METHOD:
[self handleSetRender3DRenderingEngine:[messageComponents objectAtIndex:0]];
break;
@ -1129,47 +1073,9 @@ GPU3DInterface *core3DList[] = {
- (void) handleEmuFrameProcessed:(NSData *)theData
{
// Tell the video output object to process the video frame with our copied GPU data.
if ([vf typeID] == VideoFilterTypeID_None)
{
[delegate doProcessVideoFrame:[theData bytes] frameSize:[vf destSize]];
}
else
{
NSSize srcSize = [vf srcSize];
OSSpinLockLock(&spinlockVfSrcBuffer);
RGBA5551ToRGBA8888Buffer((const uint16_t *)[theData bytes], (uint32_t *)[vf srcBufferPtr], ((unsigned int)srcSize.width * (unsigned int)srcSize.height));
OSSpinLockUnlock(&spinlockVfSrcBuffer);
const UInt32 *vfDestBufferPtr = [vf runFilter];
[delegate doProcessVideoFrame:vfDestBufferPtr frameSize:[vf destSize]];
}
[super handleEmuFrameProcessed:theData];
}
- (void) handleResizeView:(NSData *)rectData
{
if (delegate == nil || ![delegate respondsToSelector:@selector(doResizeView:)])
{
return;
}
const NSRect *resizeRect = (NSRect *)[rectData bytes];
[delegate doResizeView:*resizeRect];
}
- (void) handleRedrawView
{
if (delegate == nil || ![delegate respondsToSelector:@selector(doRedraw)])
{
return;
}
[delegate doRedraw];
}
- (void) handleChangeGpuStateFlags:(NSData *)flagsData
{
const NSInteger *flags = (NSInteger *)[flagsData bytes];
@ -1189,64 +1095,6 @@ GPU3DInterface *core3DList[] = {
[delegate doDisplayTypeChanged:*theType];
}
- (void) handleChangeDisplayOrientation:(NSData *)displayOrientationIdData
{
if (delegate == nil || ![delegate respondsToSelector:@selector(doDisplayOrientationChanged:)])
{
return;
}
const NSInteger *theOrientation = (NSInteger *)[displayOrientationIdData bytes];
[delegate doDisplayOrientationChanged:*theOrientation];
}
- (void) handleChangeDisplayOrder:(NSData *)displayOrderIdData
{
if (delegate == nil || ![delegate respondsToSelector:@selector(doDisplayOrderChanged:)])
{
return;
}
const NSInteger *theOrder = (NSInteger *)[displayOrderIdData bytes];
[delegate doDisplayOrderChanged:*theOrder];
}
- (void) handleChangeBilinearOutput:(NSData *)bilinearStateData
{
if (delegate == nil || ![delegate respondsToSelector:@selector(doBilinearOutputChanged:)])
{
return;
}
const BOOL *theState = (BOOL *)[bilinearStateData bytes];
[delegate doBilinearOutputChanged:*theState];
[self handleEmuFrameProcessed:self.frameData];
}
- (void) handleChangeVerticalSync:(NSData *)verticalSyncStateData
{
if (delegate == nil || ![delegate respondsToSelector:@selector(doVerticalSyncChanged:)])
{
return;
}
const BOOL *theState = (BOOL *)[verticalSyncStateData bytes];
[delegate doVerticalSyncChanged:*theState];
}
- (void) handleChangeVideoFilter:(NSData *)videoFilterTypeIdData
{
if (delegate == nil || ![delegate respondsToSelector:@selector(doVideoFilterChanged:)])
{
return;
}
const NSInteger *theType = (NSInteger *)[videoFilterTypeIdData bytes];
[self setVfType:*theType];
[delegate doVideoFilterChanged:*theType];
[self handleEmuFrameProcessed:self.frameData];
}
- (void) handleSetRender3DRenderingEngine:(NSData *)methodIdData
{
const NSInteger *methodID = (NSInteger *)[methodIdData bytes];
@ -1356,7 +1204,7 @@ GPU3DInterface *core3DList[] = {
- (NSImage *) image
{
NSImage *newImage = [[NSImage alloc] initWithSize:[vf srcSize]];
NSImage *newImage = [[NSImage alloc] initWithSize:self.frameSize];
if (newImage == nil)
{
return newImage;
@ -1384,7 +1232,7 @@ GPU3DInterface *core3DList[] = {
return nil;
}
NSSize srcSize = [vf srcSize];
NSSize srcSize = self.frameSize;
NSUInteger w = (NSUInteger)srcSize.width;
NSUInteger h = (NSUInteger)srcSize.height;
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
@ -1519,6 +1367,269 @@ GPU3DInterface *core3DList[] = {
@end
@implementation CocoaDSDisplayVideo
@synthesize vf;
- (id)init
{
self = [super init];
if (self == nil)
{
return self;
}
videoDelegate = nil;
spinlockVideoFilterType = OS_SPINLOCK_INIT;
spinlockVfSrcBuffer = OS_SPINLOCK_INIT;
vf = [[CocoaVideoFilter alloc] initWithSize:frameSize typeID:VideoFilterTypeID_None numberThreads:2];
[property setValue:[NSNumber numberWithInteger:(NSInteger)VideoFilterTypeID_None] forKey:@"videoFilterType"];
[property setValue:[CocoaVideoFilter typeStringByID:VideoFilterTypeID_None] forKey:@"videoFilterTypeString"];
return self;
}
- (void)dealloc
{
[vf release];
[super dealloc];
}
- (void) setDelegate:(id <CocoaDSDisplayVideoDelegate>)theDelegate
{
OSSpinLockLock(&spinlockDelegate);
if (theDelegate == videoDelegate)
{
OSSpinLockUnlock(&spinlockDelegate);
return;
}
if (theDelegate != nil)
{
[theDelegate retain];
[theDelegate setSendPortDisplay:self.receivePort];
}
[videoDelegate release];
videoDelegate = theDelegate;
OSSpinLockUnlock(&spinlockDelegate);
[super setDelegate:theDelegate];
}
- (id <CocoaDSDisplayVideoDelegate>) delegate
{
OSSpinLockLock(&spinlockDelegate);
id <CocoaDSDisplayVideoDelegate> theDelegate = videoDelegate;
OSSpinLockUnlock(&spinlockDelegate);
return theDelegate;
}
- (void) setDisplayType:(NSInteger)dispType
{
[super setDisplayType:dispType];
OSSpinLockLock(&spinlockVfSrcBuffer);
[vf setSourceSize:self.frameSize];
OSSpinLockUnlock(&spinlockVfSrcBuffer);
}
- (void) setVfType:(NSInteger)videoFilterTypeID
{
[vf changeFilter:(VideoFilterTypeID)videoFilterTypeID];
OSSpinLockLock(&spinlockVideoFilterType);
[property setValue:[NSNumber numberWithInteger:videoFilterTypeID] forKey:@"videoFilterType"];
[property setValue:NSLocalizedString([vf typeString], nil) forKey:@"videoFilterTypeString"];
OSSpinLockUnlock(&spinlockVideoFilterType);
}
- (NSInteger) vfType
{
OSSpinLockLock(&spinlockVideoFilterType);
NSInteger theType = [(NSNumber *)[property valueForKey:@"videoFilterType"] integerValue];
OSSpinLockUnlock(&spinlockVideoFilterType);
return theType;
}
- (void) runThread:(id)object
{
NSAutoreleasePool *tempPool = [[NSAutoreleasePool alloc] init];
[videoDelegate doInitVideoOutput:self.property];
[tempPool release];
[super runThread:object];
}
- (void)handlePortMessage:(NSPortMessage *)portMessage
{
NSInteger message = (NSInteger)[portMessage msgid];
NSArray *messageComponents = [portMessage components];
switch (message)
{
case MESSAGE_EMU_FRAME_PROCESSED:
[self handleEmuFrameProcessed:[messageComponents objectAtIndex:0]];
break;
case MESSAGE_RESIZE_VIEW:
[self handleResizeView:[messageComponents objectAtIndex:0]];
break;
case MESSAGE_REDRAW_VIEW:
[self handleRedrawView];
break;
case MESSAGE_CHANGE_DISPLAY_ORIENTATION:
[self handleChangeDisplayOrientation:[messageComponents objectAtIndex:0]];
break;
case MESSAGE_CHANGE_DISPLAY_ORDER:
[self handleChangeDisplayOrder:[messageComponents objectAtIndex:0]];
break;
case MESSAGE_CHANGE_BILINEAR_OUTPUT:
[self handleChangeBilinearOutput:[messageComponents objectAtIndex:0]];
break;
case MESSAGE_CHANGE_VERTICAL_SYNC:
[self handleChangeVerticalSync:[messageComponents objectAtIndex:0]];
break;
case MESSAGE_CHANGE_VIDEO_FILTER:
[self handleChangeVideoFilter:[messageComponents objectAtIndex:0]];
break;
default:
[super handlePortMessage:portMessage];
break;
}
}
- (void) handleEmuFrameProcessed:(NSData *)theData
{
if (theData == nil)
{
return;
}
NSSize destSize = [vf destSize];
size_t dataSize = (size_t)destSize.width * (size_t)destSize.height * sizeof(UInt32);
if ([vf typeID] == VideoFilterTypeID_None)
{
destSize = self.frameSize;
dataSize = (size_t)destSize.width * (size_t)destSize.height * sizeof(UInt16);
}
// Tell the video delegate to process the video frame with our copied GPU data.
if ([vf typeID] == VideoFilterTypeID_None)
{
[videoDelegate doProcessVideoFrame:[theData bytes] frameSize:self.frameSize];
}
else
{
NSSize srcSize = [vf srcSize];
OSSpinLockLock(&spinlockVfSrcBuffer);
RGBA5551ToRGBA8888Buffer((const uint16_t *)[theData bytes], (uint32_t *)[vf srcBufferPtr], ((unsigned int)srcSize.width * (unsigned int)srcSize.height));
OSSpinLockUnlock(&spinlockVfSrcBuffer);
UInt32 *vfDestBuffer = [vf runFilter];
[videoDelegate doProcessVideoFrame:vfDestBuffer frameSize:[vf destSize]];
}
[super handleEmuFrameProcessed:theData];
}
- (void) handleResizeView:(NSData *)rectData
{
if (videoDelegate == nil || ![videoDelegate respondsToSelector:@selector(doResizeView:)])
{
return;
}
const NSRect *resizeRect = (NSRect *)[rectData bytes];
[videoDelegate doResizeView:*resizeRect];
}
- (void) handleRedrawView
{
if (videoDelegate == nil || ![videoDelegate respondsToSelector:@selector(doRedraw)])
{
return;
}
[videoDelegate doRedraw];
}
- (void) handleChangeDisplayOrientation:(NSData *)displayOrientationIdData
{
if (videoDelegate == nil || ![videoDelegate respondsToSelector:@selector(doDisplayOrientationChanged:)])
{
return;
}
const NSInteger *theOrientation = (NSInteger *)[displayOrientationIdData bytes];
[videoDelegate doDisplayOrientationChanged:*theOrientation];
}
- (void) handleChangeDisplayOrder:(NSData *)displayOrderIdData
{
if (videoDelegate == nil || ![videoDelegate respondsToSelector:@selector(doDisplayOrderChanged:)])
{
return;
}
const NSInteger *theOrder = (NSInteger *)[displayOrderIdData bytes];
[videoDelegate doDisplayOrderChanged:*theOrder];
}
- (void) handleChangeBilinearOutput:(NSData *)bilinearStateData
{
if (videoDelegate == nil || ![videoDelegate respondsToSelector:@selector(doBilinearOutputChanged:)])
{
return;
}
const BOOL *theState = (BOOL *)[bilinearStateData bytes];
[videoDelegate doBilinearOutputChanged:*theState];
[self handleEmuFrameProcessed:self.frameData];
}
- (void) handleChangeVerticalSync:(NSData *)verticalSyncStateData
{
if (videoDelegate == nil || ![videoDelegate respondsToSelector:@selector(doVerticalSyncChanged:)])
{
return;
}
const BOOL *theState = (BOOL *)[verticalSyncStateData bytes];
[videoDelegate doVerticalSyncChanged:*theState];
}
- (void) handleChangeVideoFilter:(NSData *)videoFilterTypeIdData
{
if (videoDelegate == nil || ![videoDelegate respondsToSelector:@selector(doVideoFilterChanged:frameSize:)])
{
return;
}
const NSInteger *theType = (NSInteger *)[videoFilterTypeIdData bytes];
[self setVfType:*theType];
[videoDelegate doVideoFilterChanged:*theType frameSize:[vf destSize]];
[self handleEmuFrameProcessed:self.frameData];
}
@end
void HandleMessageEchoResponse(NSPortMessage *portMessage)
{
NSPortMessage *echo = [[NSPortMessage alloc] initWithSendPort:[portMessage receivePort] receivePort:[portMessage sendPort] components:nil];

View File

@ -181,9 +181,9 @@
[newDispViewDelegate setCdsController:newController];
// Init the DS displays.
CocoaDSDisplay *newComboDisplay = [[[CocoaDSDisplay alloc] init] autorelease];
[newComboDisplay setDelegate:newDispViewDelegate];
[newCore addOutput:newComboDisplay];
CocoaDSDisplayVideo *newVideoDisplay = [[[CocoaDSDisplayVideo alloc] init] autorelease];
[newVideoDisplay setDelegate:newDispViewDelegate];
[newCore addOutput:newVideoDisplay];
NSPort *guiPort = [NSPort port];
[[NSRunLoop currentRunLoop] addPort:guiPort forMode:NSDefaultRunLoopMode];
@ -202,11 +202,11 @@
}
// Start up the threads for our outputs.
[NSThread detachNewThreadSelector:@selector(runThread:) toTarget:newComboDisplay withObject:nil];
[NSThread detachNewThreadSelector:@selector(runThread:) toTarget:newVideoDisplay withObject:nil];
[NSThread detachNewThreadSelector:@selector(runThread:) toTarget:newSpeaker withObject:nil];
// Wait until the GPU and SPU are finished starting up.
while ([newComboDisplay thread] == nil || [newSpeaker thread] == nil)
while ([newVideoDisplay thread] == nil || [newSpeaker thread] == nil)
{
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
}

View File

@ -42,11 +42,11 @@
- (void) doDisplayOrderChanged:(NSInteger)displayOrderID;
- (void) doBilinearOutputChanged:(BOOL)useBilinear;
- (void) doVerticalSyncChanged:(BOOL)useVerticalSync;
- (void) doVideoFilterChanged:(NSInteger)videoFilterTypeID;
- (void) doVideoFilterChanged:(NSInteger)videoFilterTypeID frameSize:(NSSize)videoFilterDestSize;
@end
@interface DisplayViewDelegate : NSObject <CocoaDSDisplayDelegate>
@interface DisplayViewDelegate : NSObject <CocoaDSDisplayVideoDelegate>
{
NSView <DisplayViewDelegate> *view;
NSPort *sendPortDisplay;
@ -130,14 +130,14 @@
GLfloat swRasterizerMainVertex[4][2];
GLfloat swRasterizerTouchTexCoord[4][2];
GLfloat swRasterizerTouchVertex[4][2];
GLuint swRasterizerDisplayListIndex;
}
- (void) drawVideoFrame;
- (void) uploadSWRasterizerTexturesUsingSize:(NSSize)textureSize
mainBytes:(const GLvoid *)mainBytes
touchBytes:(const GLvoid *)touchBytes;
- (void) uploadSWRasterizerTextureData:(const GLvoid *)textureData textureSize:(NSSize)textureSize;
- (void) renderSWRasterizer;
- (void) setupSWRasterizerVertices;
- (void) updateDisplayLists;
@end

View File

@ -650,14 +650,14 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil;
[view doVerticalSyncChanged:useVerticalSync];
}
- (void) doVideoFilterChanged:(NSInteger)videoFilterTypeID
- (void) doVideoFilterChanged:(NSInteger)videoFilterTypeID frameSize:(NSSize)videoFilterDestSize
{
if (view == nil || ![view respondsToSelector:@selector(doVideoFilterChanged:)])
if (view == nil || ![view respondsToSelector:@selector(doVideoFilterChanged:frameSize:)])
{
return;
}
[view doVideoFilterChanged:videoFilterTypeID];
[view doVideoFilterChanged:videoFilterTypeID frameSize:videoFilterDestSize];
}
@end
@ -902,14 +902,45 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil;
glTexBackSize = NSMakeSize(w, h);
OSXDefaultOpenGLContext = [[self openGLContext] retain];
NSOpenGLContext *prevContext = [NSOpenGLContext currentContext];
[OSXDefaultOpenGLContext makeCurrentContext];
glGenTextures(2, swRasterizerDrawTexture);
swRasterizerDisplayListIndex = glGenLists(3);
SetOpenGLRendererFunctions(&OSXOpenGLRendererInit,
&OSXOpenGLRendererBegin,
&OSXOpenGLRendererEnd);
if (prevContext != nil)
{
[prevContext makeCurrentContext];
}
else
{
[NSOpenGLContext clearCurrentContext];
}
return self;
}
- (void)dealloc
{
[NSOpenGLContext clearCurrentContext];
NSOpenGLContext *prevContext = [NSOpenGLContext currentContext];
[[self openGLContext] makeCurrentContext];
glDeleteTextures(2, swRasterizerDrawTexture);
glDeleteLists(swRasterizerDisplayListIndex, 3);
if (prevContext != nil)
{
[prevContext makeCurrentContext];
}
else
{
[NSOpenGLContext clearCurrentContext];
}
free(glTexBack);
glTexBack = NULL;
@ -950,12 +981,6 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil;
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glGenTextures(2, &swRasterizerDrawTexture[0]);
SetOpenGLRendererFunctions(&OSXOpenGLRendererInit,
&OSXOpenGLRendererBegin,
&OSXOpenGLRendererEnd);
}
- (void) drawVideoFrame
@ -963,100 +988,75 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil;
CGLFlushDrawable((CGLContextObj)[[self openGLContext] CGLContextObj]);
}
- (void) uploadSWRasterizerTexturesUsingSize:(NSSize)textureSize
mainBytes:(const GLvoid *)mainBytes
touchBytes:(const GLvoid *)touchBytes
- (void) uploadSWRasterizerTextureData:(const GLvoid *)textureData textureSize:(NSSize)textureSize
{
uint32_t w = GetNearestPositivePOT((uint32_t)textureSize.width);
uint32_t h = GetNearestPositivePOT((uint32_t)textureSize.height);
NSInteger displayType = [dispViewDelegate displayType];
size_t bitDepth = sizeof(uint32_t);
if (glTexPixelFormat == GL_UNSIGNED_SHORT_1_5_5_5_REV)
if (textureData == NULL)
{
bitDepth = sizeof(uint16_t);
return;
}
if (glTexBackSize.width != w || glTexBackSize.height != h)
switch (displayType)
{
glTexBackSize.width = w;
glTexBackSize.height = h;
free(glTexBack);
glTexBack = (GLvoid *)calloc((size_t)w * (size_t)h, bitDepth);
if (glTexBack == NULL)
case DS_DISPLAY_TYPE_MAIN:
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)textureSize.width, (GLsizei)textureSize.height, GL_RGBA, glTexPixelFormat, textureData);
break;
case DS_DISPLAY_TYPE_TOUCH:
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[1]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)textureSize.width, (GLsizei)textureSize.height, GL_RGBA, glTexPixelFormat, textureData);
break;
case DS_DISPLAY_TYPE_COMBO:
{
return;
textureSize.height /= 2;
size_t offset = (size_t)textureSize.width * (size_t)textureSize.height;
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)textureSize.width, (GLsizei)textureSize.height, GL_RGBA, glTexPixelFormat, textureData);
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[1]);
if (glTexPixelFormat == GL_UNSIGNED_SHORT_1_5_5_5_REV)
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)textureSize.width, (GLsizei)textureSize.height, GL_RGBA, glTexPixelFormat, (uint16_t *)textureData + offset);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)textureSize.width, (GLsizei)textureSize.height, GL_RGBA, glTexPixelFormat, (uint32_t *)textureData + offset);
}
break;
}
default:
break;
}
swRasterizerMainTexCoord[0][0] = 0.0f;
swRasterizerMainTexCoord[0][1] = 0.0f;
swRasterizerMainTexCoord[1][0] = (GLfloat)(textureSize.width / w);
swRasterizerMainTexCoord[1][1] = 0.0f;
swRasterizerMainTexCoord[2][0] = (GLfloat)(textureSize.width / w);
swRasterizerMainTexCoord[2][1] = (GLfloat)(textureSize.height / h);
swRasterizerMainTexCoord[3][0] = 0.0f;
swRasterizerMainTexCoord[3][1] = (GLfloat)(textureSize.height / h);
swRasterizerTouchTexCoord[0][0] = 0.0f;
swRasterizerTouchTexCoord[0][1] = 0.0f;
swRasterizerTouchTexCoord[1][0] = (GLfloat)(textureSize.width / w);
swRasterizerTouchTexCoord[1][1] = 0.0f;
swRasterizerTouchTexCoord[2][0] = (GLfloat)(textureSize.width / w);
swRasterizerTouchTexCoord[2][1] = (GLfloat)(textureSize.height / h);
swRasterizerTouchTexCoord[3][0] = 0.0f;
swRasterizerTouchTexCoord[3][1] = (GLfloat)(textureSize.height / h);
// Main screen
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, glTexPixelFormat, glTexBack);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)textureSize.width, (GLsizei)textureSize.height, GL_RGBA, glTexPixelFormat, mainBytes);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glTexRenderStyle);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glTexRenderStyle);
// Touch screen
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, glTexPixelFormat, glTexBack);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)textureSize.width, (GLsizei)textureSize.height, GL_RGBA, glTexPixelFormat, touchBytes);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glTexRenderStyle);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glTexRenderStyle);
glBindTexture(GL_TEXTURE_2D, NULL);
}
- (void) renderSWRasterizer
{
NSInteger displayType = [dispViewDelegate displayType];
glClear(GL_COLOR_BUFFER_BIT);
// Render the main screen
if (displayType == DS_DISPLAY_TYPE_MAIN || displayType == DS_DISPLAY_TYPE_COMBO)
switch (displayType)
{
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[0]);
glBegin(GL_QUADS);
for (unsigned int i = 0; i < 4; i++)
{
glTexCoord2f(swRasterizerMainTexCoord[i][0], swRasterizerMainTexCoord[i][1]);
glVertex2f(swRasterizerMainVertex[i][0], swRasterizerMainVertex[i][1]);
}
glEnd();
}
// Render the touch screen
if (displayType == DS_DISPLAY_TYPE_TOUCH || displayType == DS_DISPLAY_TYPE_COMBO)
{
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[1]);
glBegin(GL_QUADS);
for (unsigned int i = 0; i < 4; i++)
{
glTexCoord2f(swRasterizerTouchTexCoord[i][0], swRasterizerTouchTexCoord[i][1]);
glVertex2f(swRasterizerTouchVertex[i][0], swRasterizerTouchVertex[i][1]);
}
glEnd();
case DS_DISPLAY_TYPE_MAIN:
glCallList(swRasterizerDisplayListIndex);
break;
case DS_DISPLAY_TYPE_TOUCH:
glCallList(swRasterizerDisplayListIndex + 1);
break;
case DS_DISPLAY_TYPE_COMBO:
glCallList(swRasterizerDisplayListIndex + 2);
break;
default:
break;
}
}
@ -1158,7 +1158,7 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil;
}
}
}
else
else // displayType == DS_DISPLAY_TYPE_MAIN || displayType == DS_DISPLAY_TYPE_TOUCH
{
swRasterizerMainVertex[0][0] = -w/2.0f;
swRasterizerMainVertex[0][1] = h/2.0f;
@ -1180,6 +1180,71 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil;
}
}
- (void) updateDisplayLists
{
// Main screen only
glNewList(swRasterizerDisplayListIndex, GL_COMPILE);
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[0]);
glBegin(GL_QUADS);
for (unsigned int i = 0; i < 4; i++)
{
glTexCoord2f(swRasterizerMainTexCoord[i][0], swRasterizerMainTexCoord[i][1]);
glVertex2f(swRasterizerMainVertex[i][0], swRasterizerMainVertex[i][1]);
}
glEnd();
glBindTexture(GL_TEXTURE_2D, NULL);
glEndList();
// Touch screen only
glNewList(swRasterizerDisplayListIndex + 1, GL_COMPILE);
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[1]);
glBegin(GL_QUADS);
for (unsigned int i = 0; i < 4; i++)
{
glTexCoord2f(swRasterizerTouchTexCoord[i][0], swRasterizerTouchTexCoord[i][1]);
glVertex2f(swRasterizerTouchVertex[i][0], swRasterizerTouchVertex[i][1]);
}
glEnd();
glBindTexture(GL_TEXTURE_2D, NULL);
glEndList();
// Combo screens
glNewList(swRasterizerDisplayListIndex + 2, GL_COMPILE);
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[0]);
glBegin(GL_QUADS);
for (unsigned int i = 0; i < 4; i++)
{
glTexCoord2f(swRasterizerMainTexCoord[i][0], swRasterizerMainTexCoord[i][1]);
glVertex2f(swRasterizerMainVertex[i][0], swRasterizerMainVertex[i][1]);
}
glEnd();
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[1]);
glBegin(GL_QUADS);
for (unsigned int i = 0; i < 4; i++)
{
glTexCoord2f(swRasterizerTouchTexCoord[i][0], swRasterizerTouchTexCoord[i][1]);
glVertex2f(swRasterizerTouchVertex[i][0], swRasterizerTouchVertex[i][1]);
}
glEnd();
glBindTexture(GL_TEXTURE_2D, NULL);
glEndList();
}
- (void)keyDown:(NSEvent *)theEvent
{
BOOL isHandled = [dispViewDelegate handleKeyPress:theEvent keyPressed:YES];
@ -1292,10 +1357,9 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil;
[[self openGLContext] makeCurrentContext];
SetupOpenGLView((GLsizei)rect.size.width, (GLsizei)rect.size.height, scale, rotation);
[[self openGLContext] update];
CGLUnlockContext((CGLContextObj)[[self openGLContext] CGLContextObj]);
[dispViewDelegate setViewToBlack];
}
- (void)doProcessVideoFrame:(const void *)videoFrameData frameSize:(NSSize)frameSize
@ -1304,44 +1368,7 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil;
[[self openGLContext] makeCurrentContext];
switch ([dispViewDelegate displayType])
{
case DS_DISPLAY_TYPE_MAIN:
[self uploadSWRasterizerTexturesUsingSize:frameSize
mainBytes:videoFrameData
touchBytes:videoFrameData];
break;
case DS_DISPLAY_TYPE_TOUCH:
[self uploadSWRasterizerTexturesUsingSize:frameSize
mainBytes:videoFrameData
touchBytes:videoFrameData];
break;
case DS_DISPLAY_TYPE_COMBO:
{
frameSize.height /= 2.0;
if (glTexPixelFormat == GL_UNSIGNED_SHORT_1_5_5_5_REV)
{
[self uploadSWRasterizerTexturesUsingSize:frameSize
mainBytes:videoFrameData
touchBytes:(const uint16_t *)videoFrameData + ((size_t)frameSize.width * (size_t)frameSize.height)];
}
else
{
[self uploadSWRasterizerTexturesUsingSize:frameSize
mainBytes:videoFrameData
touchBytes:(const uint32_t *)videoFrameData + ((size_t)frameSize.width * (size_t)frameSize.height)];
}
break;
}
default:
break;
}
[self uploadSWRasterizerTextureData:videoFrameData textureSize:frameSize];
[self renderSWRasterizer];
[self drawVideoFrame];
@ -1359,6 +1386,7 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil;
CGLUnlockContext((CGLContextObj)[[self openGLContext] CGLContextObj]);
[self setupSWRasterizerVertices];
[self updateDisplayLists];
}
- (void)doRedraw
@ -1375,6 +1403,7 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil;
- (void)doDisplayTypeChanged:(NSInteger)displayTypeID
{
[self setupSWRasterizerVertices];
[self updateDisplayLists];
}
- (void)doBilinearOutputChanged:(BOOL)useBilinear
@ -1384,16 +1413,28 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil;
{
glTexRenderStyle = GL_LINEAR;
}
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glTexRenderStyle);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glTexRenderStyle);
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glTexRenderStyle);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glTexRenderStyle);
glBindTexture(GL_TEXTURE_2D, NULL);
}
- (void) doDisplayOrientationChanged:(NSInteger)displayOrientationID
{
[self setupSWRasterizerVertices];
[self updateDisplayLists];
}
- (void) doDisplayOrderChanged:(NSInteger)displayOrderID
{
[self setupSWRasterizerVertices];
[self updateDisplayLists];
if ([dispViewDelegate displayType] == DS_DISPLAY_TYPE_COMBO)
{
@ -1413,13 +1454,67 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil;
[[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
}
- (void)doVideoFilterChanged:(NSInteger)videoFilterTypeID
- (void)doVideoFilterChanged:(NSInteger)videoFilterTypeID frameSize:(NSSize)videoFilterDestSize
{
size_t colorDepth = sizeof(uint32_t);
glTexPixelFormat = GL_UNSIGNED_INT_8_8_8_8_REV;
if (videoFilterTypeID == VideoFilterTypeID_None)
{
colorDepth = sizeof(uint16_t);
glTexPixelFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV;
}
if ([dispViewDelegate displayType] == DS_DISPLAY_TYPE_COMBO)
{
videoFilterDestSize.height /= 2.0;
}
uint32_t w = GetNearestPositivePOT((uint32_t)videoFilterDestSize.width);
uint32_t h = GetNearestPositivePOT((uint32_t)videoFilterDestSize.height);
if (glTexBackSize.width != w || glTexBackSize.height != h)
{
glTexBackSize.width = w;
glTexBackSize.height = h;
free(glTexBack);
glTexBack = (GLvoid *)calloc((size_t)w * (size_t)h, colorDepth);
if (glTexBack == NULL)
{
return;
}
}
// Main screen
swRasterizerMainTexCoord[0][0] = 0.0f;
swRasterizerMainTexCoord[0][1] = 0.0f;
swRasterizerMainTexCoord[1][0] = (GLfloat)(videoFilterDestSize.width / w);
swRasterizerMainTexCoord[1][1] = 0.0f;
swRasterizerMainTexCoord[2][0] = (GLfloat)(videoFilterDestSize.width / w);
swRasterizerMainTexCoord[2][1] = (GLfloat)(videoFilterDestSize.height / h);
swRasterizerMainTexCoord[3][0] = 0.0f;
swRasterizerMainTexCoord[3][1] = (GLfloat)(videoFilterDestSize.height / h);
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, glTexPixelFormat, glTexBack);
// Touch screen
swRasterizerTouchTexCoord[0][0] = 0.0f;
swRasterizerTouchTexCoord[0][1] = 0.0f;
swRasterizerTouchTexCoord[1][0] = (GLfloat)(videoFilterDestSize.width / w);
swRasterizerTouchTexCoord[1][1] = 0.0f;
swRasterizerTouchTexCoord[2][0] = (GLfloat)(videoFilterDestSize.width / w);
swRasterizerTouchTexCoord[2][1] = (GLfloat)(videoFilterDestSize.height / h);
swRasterizerTouchTexCoord[3][0] = 0.0f;
swRasterizerTouchTexCoord[3][1] = (GLfloat)(videoFilterDestSize.height / h);
glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, glTexPixelFormat, glTexBack);
glBindTexture(GL_TEXTURE_2D, NULL);
[self updateDisplayLists];
}
@end