mirror of
https://github.com/libretro/FBNeo.git
synced 2024-11-27 02:50:29 +00:00
Fixed flipped rendering
This commit is contained in:
parent
314d90dbd5
commit
de30f6a28d
@ -11,7 +11,7 @@
|
||||
// FIXME: errors during load
|
||||
// FIXME: starting without ROM selected
|
||||
// FIXME: dropping file into window
|
||||
// FIXME: rotation (mimonkey)
|
||||
// FIXME: sound when load fails
|
||||
@interface AppDelegate ()
|
||||
|
||||
@property (weak) IBOutlet NSWindow *window;
|
||||
|
@ -14,7 +14,7 @@ int MainInit(const char *path, const char *setname)
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Initializing '%s' with path '%s'\n", setname, path);
|
||||
fprintf(stderr, "Initializing '%s' in '%s'\n", setname, path);
|
||||
|
||||
SDL_Init(SDL_INIT_AUDIO);
|
||||
BurnLibInit();
|
||||
|
@ -24,19 +24,20 @@
|
||||
|
||||
@implementation FBScreenView
|
||||
{
|
||||
GLuint screenTextureId;
|
||||
unsigned char *texture;
|
||||
int imageWidth;
|
||||
int imageHeight;
|
||||
BOOL isRotated;
|
||||
int textureWidth;
|
||||
int textureHeight;
|
||||
int textureBytesPerPixel;
|
||||
NSLock *renderLock;
|
||||
NSSize screenSize;
|
||||
CFAbsoluteTime _lastMouseAction;
|
||||
NSPoint _lastCursorPosition;
|
||||
NSTrackingArea *_trackingArea;
|
||||
GLuint screenTextureId;
|
||||
unsigned char *texture;
|
||||
int imageWidth;
|
||||
int imageHeight;
|
||||
BOOL isRotated;
|
||||
BOOL isFlipped;
|
||||
int textureWidth;
|
||||
int textureHeight;
|
||||
int textureBytesPerPixel;
|
||||
NSLock *renderLock;
|
||||
NSSize screenSize;
|
||||
CFAbsoluteTime _lastMouseAction;
|
||||
NSPoint _lastCursorPosition;
|
||||
NSTrackingArea *_trackingArea;
|
||||
NSRect viewBounds; // Access from non-UI thread
|
||||
}
|
||||
|
||||
@ -45,16 +46,16 @@
|
||||
- (void) dealloc
|
||||
{
|
||||
glDeleteTextures(1, &screenTextureId);
|
||||
free(self->texture);
|
||||
free(texture);
|
||||
}
|
||||
|
||||
- (void) awakeFromNib
|
||||
{
|
||||
self->renderLock = [[NSLock alloc] init];
|
||||
_lastMouseAction = CFAbsoluteTimeGetCurrent();
|
||||
_lastCursorPosition = NSMakePoint(-1, -1);
|
||||
renderLock = [[NSLock alloc] init];
|
||||
_lastMouseAction = CFAbsoluteTimeGetCurrent();
|
||||
_lastCursorPosition = NSMakePoint(-1, -1);
|
||||
|
||||
[self resetTrackingArea];
|
||||
[self resetTrackingArea];
|
||||
}
|
||||
|
||||
#pragma mark - Cocoa Callbacks
|
||||
@ -62,43 +63,43 @@
|
||||
- (void) prepareOpenGL
|
||||
{
|
||||
[super prepareOpenGL];
|
||||
|
||||
|
||||
NSLog(@"FBScreenView/prepareOpenGL");
|
||||
|
||||
[self->renderLock lock];
|
||||
|
||||
|
||||
[renderLock lock];
|
||||
|
||||
// Synchronize buffer swaps with vertical refresh rate
|
||||
GLint swapInt = 1;
|
||||
[[self openGLContext] setValues:&swapInt
|
||||
forParameter:NSOpenGLCPSwapInterval];
|
||||
|
||||
forParameter:NSOpenGLCPSwapInterval];
|
||||
|
||||
glClearColor(0, 0, 0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
|
||||
glGenTextures(1, &screenTextureId);
|
||||
|
||||
[self->renderLock unlock];
|
||||
|
||||
[renderLock unlock];
|
||||
}
|
||||
|
||||
- (void) drawRect:(NSRect)dirtyRect
|
||||
{
|
||||
[self->renderLock lock];
|
||||
|
||||
[renderLock lock];
|
||||
|
||||
NSOpenGLContext *nsContext = [self openGLContext];
|
||||
[nsContext makeCurrentContext];
|
||||
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
GLfloat coordX = (GLfloat)self->imageWidth / self->textureWidth;
|
||||
GLfloat coordY = (GLfloat)self->imageHeight / self->textureHeight;
|
||||
|
||||
|
||||
GLfloat coordX = (GLfloat)imageWidth / textureWidth;
|
||||
GLfloat coordY = (GLfloat)imageHeight / textureHeight;
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, screenTextureId);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
|
||||
NSSize size = [self bounds].size;
|
||||
CGFloat offset = 0;
|
||||
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0);
|
||||
glVertex3f(-offset, 0.0, 0.0);
|
||||
@ -110,109 +111,111 @@
|
||||
glVertex3f(-offset, size.height, 0.0);
|
||||
glEnd();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
|
||||
[nsContext flushBuffer];
|
||||
|
||||
[self->renderLock unlock];
|
||||
|
||||
[renderLock unlock];
|
||||
}
|
||||
|
||||
- (void) reshape
|
||||
{
|
||||
viewBounds = [self bounds];
|
||||
[self->renderLock lock];
|
||||
|
||||
[renderLock lock];
|
||||
|
||||
[[self openGLContext] makeCurrentContext];
|
||||
[[self openGLContext] update];
|
||||
|
||||
|
||||
[self resetProjection];
|
||||
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
[self->renderLock unlock];
|
||||
|
||||
[renderLock unlock];
|
||||
}
|
||||
|
||||
#pragma mark - FBVideoRenderDelegate
|
||||
|
||||
- (void)initTextureOfWidth:(int)width
|
||||
height:(int)height
|
||||
isRotated:(BOOL)rotated
|
||||
bytesPerPixel:(int)bytesPerPixel
|
||||
- (void)initTextureOfWidth:(int) width
|
||||
height:(int) height
|
||||
isRotated:(BOOL) rotated
|
||||
isFlipped:(BOOL) flipped
|
||||
bytesPerPixel:(int) bytesPerPixel
|
||||
{
|
||||
NSLog(@"FBScreenView/initTexture");
|
||||
|
||||
[self->renderLock lock];
|
||||
|
||||
|
||||
[renderLock lock];
|
||||
|
||||
NSOpenGLContext *nsContext = [self openGLContext];
|
||||
[nsContext makeCurrentContext];
|
||||
|
||||
free(self->texture);
|
||||
|
||||
self->imageWidth = width;
|
||||
self->imageHeight = height;
|
||||
self->isRotated = rotated;
|
||||
self->textureWidth = [FBScreenView powerOfTwoClosestTo:self->imageWidth];
|
||||
self->textureHeight = [FBScreenView powerOfTwoClosestTo:self->imageHeight];
|
||||
self->textureBytesPerPixel = bytesPerPixel;
|
||||
self->screenSize = NSMakeSize((CGFloat)width, (CGFloat)height);
|
||||
|
||||
int texSize = self->textureWidth * self->textureHeight * bytesPerPixel;
|
||||
self->texture = (unsigned char *)malloc(texSize);
|
||||
|
||||
|
||||
free(texture);
|
||||
|
||||
imageWidth = width;
|
||||
imageHeight = height;
|
||||
isRotated = rotated;
|
||||
isFlipped = flipped;
|
||||
textureWidth = [FBScreenView powerOfTwoClosestTo:imageWidth];
|
||||
textureHeight = [FBScreenView powerOfTwoClosestTo:imageHeight];
|
||||
textureBytesPerPixel = bytesPerPixel;
|
||||
screenSize = NSMakeSize((CGFloat)width, (CGFloat)height);
|
||||
|
||||
int texSize = textureWidth * textureHeight * bytesPerPixel;
|
||||
texture = (unsigned char *)malloc(texSize);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, screenTextureId);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, bytesPerPixel,
|
||||
self->textureWidth, self->textureHeight,
|
||||
0, GL_BGR, GL_UNSIGNED_BYTE, self->texture);
|
||||
|
||||
textureWidth, textureHeight,
|
||||
0, GL_BGR, GL_UNSIGNED_BYTE, texture);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
|
||||
[self resetProjection];
|
||||
|
||||
[self->renderLock unlock];
|
||||
|
||||
[renderLock unlock];
|
||||
}
|
||||
|
||||
- (void)renderFrame:(unsigned char *)bitmap
|
||||
{
|
||||
if (NSPointInRect(_lastCursorPosition, viewBounds)) {
|
||||
CFAbsoluteTime interval = CFAbsoluteTimeGetCurrent() - _lastMouseAction;
|
||||
if (interval > HIDE_CURSOR_TIMEOUT_SECONDS) {
|
||||
if ([_delegate respondsToSelector:@selector(mouseDidIdle)]) {
|
||||
[_delegate mouseDidIdle];
|
||||
}
|
||||
_lastCursorPosition.x = -1;
|
||||
}
|
||||
}
|
||||
|
||||
[self->renderLock lock];
|
||||
|
||||
if (NSPointInRect(_lastCursorPosition, viewBounds)) {
|
||||
CFAbsoluteTime interval = CFAbsoluteTimeGetCurrent() - _lastMouseAction;
|
||||
if (interval > HIDE_CURSOR_TIMEOUT_SECONDS) {
|
||||
if ([_delegate respondsToSelector:@selector(mouseDidIdle)]) {
|
||||
[_delegate mouseDidIdle];
|
||||
}
|
||||
_lastCursorPosition.x = -1;
|
||||
}
|
||||
}
|
||||
|
||||
[renderLock lock];
|
||||
|
||||
NSOpenGLContext *nsContext = [self openGLContext];
|
||||
[nsContext makeCurrentContext];
|
||||
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
GLfloat coordX = (GLfloat)self->imageWidth / self->textureWidth;
|
||||
GLfloat coordY = (GLfloat)self->imageHeight / self->textureHeight;
|
||||
|
||||
|
||||
GLfloat coordX = (GLfloat)imageWidth / textureWidth;
|
||||
GLfloat coordY = (GLfloat)imageHeight / textureHeight;
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, screenTextureId);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
for (int y = 0; y < self->imageHeight; y += 1) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, self->imageWidth, 1,
|
||||
|
||||
for (int y = 0; y < imageHeight; y += 1) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, imageWidth, 1,
|
||||
GL_BGR, GL_UNSIGNED_BYTE,
|
||||
bitmap + y * self->imageWidth * self->textureBytesPerPixel);
|
||||
bitmap + y * imageWidth * textureBytesPerPixel);
|
||||
}
|
||||
|
||||
|
||||
NSSize size = viewBounds.size;
|
||||
CGFloat offset = 0;
|
||||
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0);
|
||||
glVertex3f(-offset, 0.0, 0.0);
|
||||
@ -224,10 +227,10 @@
|
||||
glVertex3f(-offset, size.height, 0.0);
|
||||
glEnd();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
|
||||
[nsContext flushBuffer];
|
||||
|
||||
[self->renderLock unlock];
|
||||
[renderLock unlock];
|
||||
}
|
||||
|
||||
#pragma mark - Keyboard
|
||||
@ -259,80 +262,78 @@
|
||||
|
||||
- (void) mouseEntered:(NSEvent *) event
|
||||
{
|
||||
[self handleMouseChange:[event locationInWindow]];
|
||||
[self handleMouseChange:[event locationInWindow]];
|
||||
}
|
||||
|
||||
- (void) mouseMoved:(NSEvent *) event
|
||||
{
|
||||
[self handleMouseChange:[event locationInWindow]];
|
||||
[self handleMouseChange:[event locationInWindow]];
|
||||
}
|
||||
|
||||
- (void) mouseExited:(NSEvent *) event
|
||||
{
|
||||
[self handleMouseChange:NSMakePoint(-1, -1)];
|
||||
[self handleMouseChange:NSMakePoint(-1, -1)];
|
||||
}
|
||||
|
||||
- (void) mouseDown:(NSEvent *) event
|
||||
{
|
||||
[self handleMouseChange:[event locationInWindow]];
|
||||
[self handleMouseChange:[event locationInWindow]];
|
||||
}
|
||||
|
||||
- (void) rightMouseDown:(NSEvent *) event
|
||||
{
|
||||
[self handleMouseChange:[event locationInWindow]];
|
||||
[self handleMouseChange:[event locationInWindow]];
|
||||
}
|
||||
|
||||
#pragma mark - Public methods
|
||||
|
||||
- (NSSize) screenSize
|
||||
{
|
||||
return self->screenSize;
|
||||
return screenSize;
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
- (void) resetTrackingArea
|
||||
{
|
||||
if (_trackingArea) {
|
||||
[self removeTrackingArea:_trackingArea];
|
||||
}
|
||||
if (_trackingArea) {
|
||||
[self removeTrackingArea:_trackingArea];
|
||||
}
|
||||
|
||||
NSTrackingAreaOptions opts = NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect;
|
||||
_trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect
|
||||
options:opts
|
||||
owner:self
|
||||
userInfo:nil];
|
||||
[self addTrackingArea:_trackingArea];
|
||||
NSTrackingAreaOptions opts = NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect;
|
||||
_trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect
|
||||
options:opts
|
||||
owner:self
|
||||
userInfo:nil];
|
||||
[self addTrackingArea:_trackingArea];
|
||||
}
|
||||
|
||||
- (void) handleMouseChange:(NSPoint) position
|
||||
{
|
||||
_lastMouseAction = CFAbsoluteTimeGetCurrent();
|
||||
_lastCursorPosition = [self convertPoint:position
|
||||
fromView:nil];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(mouseStateDidChange)]) {
|
||||
[_delegate mouseStateDidChange];
|
||||
}
|
||||
_lastMouseAction = CFAbsoluteTimeGetCurrent();
|
||||
_lastCursorPosition = [self convertPoint:position
|
||||
fromView:nil];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(mouseStateDidChange)]) {
|
||||
[_delegate mouseStateDidChange];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)resetProjection
|
||||
{
|
||||
NSSize size = [self bounds].size;
|
||||
|
||||
|
||||
glViewport(0, 0, size.width, size.height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
if (!self->isRotated) {
|
||||
glOrtho(0, size.width, size.height, 0, -1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
glRotatef(90.0, 0.0, 0.0, 1.0);
|
||||
glOrtho(0, size.width, size.height, 0, -1, 5);
|
||||
}
|
||||
|
||||
|
||||
if (!isRotated) {
|
||||
glOrtho(0, size.width, size.height, 0, -1, 1);
|
||||
} else {
|
||||
glRotatef(isFlipped ? 270 : 90.0, 0.0, 0.0, 1.0);
|
||||
glOrtho(0, size.width, size.height, 0, -1, 5);
|
||||
}
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
|
@ -10,12 +10,13 @@
|
||||
@protocol FBVideoDelegate<NSObject>
|
||||
|
||||
@optional
|
||||
- (void)screenSizeDidChange:(NSSize)newSize;
|
||||
- (void)initTextureOfWidth:(int)width
|
||||
height:(int)height
|
||||
isRotated:(BOOL)rotated
|
||||
bytesPerPixel:(int)bytesPerPixel;
|
||||
- (void)renderFrame:(unsigned char *)bitmap;
|
||||
- (void) screenSizeDidChange:(NSSize) newSize;
|
||||
- (void) initTextureOfWidth:(int) width
|
||||
height:(int) height
|
||||
isRotated:(BOOL) rotated
|
||||
isFlipped:(BOOL) flipped
|
||||
bytesPerPixel:(int) bytesPerPixel;
|
||||
- (void) renderFrame:(unsigned char *) bitmap;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -42,16 +42,18 @@
|
||||
- (void) notifyTextureReadyOfWidth:(int) texWidth
|
||||
height:(int) texHeight
|
||||
isRotated:(BOOL) isRotated
|
||||
isFlipped:(BOOL) isFlipped
|
||||
bytesPerPixel:(int) bpp
|
||||
screenSize:(NSSize) size
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
id<FBVideoDelegate> vd = [self delegate];
|
||||
if ([vd respondsToSelector:@selector(initTextureOfWidth:height:isRotated:bytesPerPixel:)])
|
||||
if ([vd respondsToSelector:@selector(initTextureOfWidth:height:isRotated:isFlipped:bytesPerPixel:)])
|
||||
[vd initTextureOfWidth:texWidth
|
||||
height:texHeight
|
||||
isRotated:isRotated
|
||||
bytesPerPixel:bpp];
|
||||
height:texHeight
|
||||
isRotated:isRotated
|
||||
isFlipped:isFlipped
|
||||
bytesPerPixel:bpp];
|
||||
|
||||
if ([vd respondsToSelector:@selector(screenSizeDidChange:)])
|
||||
[vd screenSizeDidChange:size];
|
||||
@ -82,14 +84,15 @@ static int MacOSVideoInit()
|
||||
int gameWidth;
|
||||
int gameHeight;
|
||||
int rotationMode = 0;
|
||||
int flags = BurnDrvGetFlags();
|
||||
|
||||
BurnDrvGetVisibleSize(&gameWidth, &gameHeight);
|
||||
|
||||
if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) {
|
||||
if (flags & BDF_ORIENTATION_VERTICAL) {
|
||||
rotationMode |= 1;
|
||||
}
|
||||
|
||||
if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) {
|
||||
if (flags & BDF_ORIENTATION_FLIPPED) {
|
||||
rotationMode ^= 2;
|
||||
}
|
||||
|
||||
@ -140,6 +143,7 @@ static int MacOSVideoInit()
|
||||
[AppDelegate.sharedInstance.video notifyTextureReadyOfWidth:textureWidth
|
||||
height:textureHeight
|
||||
isRotated:isRotated
|
||||
isFlipped:flags & BDF_ORIENTATION_FLIPPED
|
||||
bytesPerPixel:bufferBytesPerPixel
|
||||
screenSize:screenSize];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user