Cocoa Port:
- Read the GPU_screen buffer directly and avoid making multiple copies of it. Improves performance when many display windows are used.
This commit is contained in:
parent
245586a978
commit
d880c58f75
|
@ -1470,11 +1470,11 @@ void OGLVideoOutput::SetViewportSizeOGL(GLsizei w, GLsizei h)
|
|||
}
|
||||
}
|
||||
|
||||
void OGLVideoOutput::ProcessOGL(const uint16_t *videoData, GLsizei w, GLsizei h)
|
||||
void OGLVideoOutput::ProcessOGL()
|
||||
{
|
||||
for (size_t i = 0; i < _layerList->size(); i++)
|
||||
{
|
||||
(*_layerList)[i]->ProcessOGL(videoData, w, h);
|
||||
(*_layerList)[i]->ProcessOGL();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1736,6 +1736,9 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO)
|
|||
_displayOrder = DS_DISPLAY_ORDER_MAIN_FIRST;
|
||||
_displayOrientation = DS_DISPLAY_ORIENTATION_VERTICAL;
|
||||
|
||||
_vtxElementCount = (_displayMode == DS_DISPLAY_TYPE_DUAL) ? 12 : 6;
|
||||
_vtxElementPointer = !(_displayMode == DS_DISPLAY_TYPE_TOUCH) ? 0 : (GLubyte *)(_vtxElementCount * sizeof(GLubyte));
|
||||
|
||||
_normalWidth = GPU_DISPLAY_WIDTH;
|
||||
_normalHeight = GPU_DISPLAY_HEIGHT*2.0 + (DS_DISPLAY_GAP*_gapScalar);
|
||||
_rotation = 0.0f;
|
||||
|
@ -1756,9 +1759,10 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO)
|
|||
|
||||
// Set up textures
|
||||
glGenTextures(1, &_texCPUFilterDstID);
|
||||
glGenTextures(1, &_texInputVideoDataID);
|
||||
_texOutputVideoDataID = _texInputVideoDataID;
|
||||
_texPrevOutputVideoDataID = _texInputVideoDataID;
|
||||
glGenTextures(1, &_texVideoInputDataID);
|
||||
_texVideoSourceID = _texVideoInputDataID;
|
||||
_texVideoPixelScalerID = _texVideoInputDataID;
|
||||
_texVideoOutputID = _texVideoInputDataID;
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texCPUFilterDstID);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
@ -1768,7 +1772,7 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO)
|
|||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE);
|
||||
glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, _vfDual->GetDstWidth() * _vfDual->GetDstHeight() * sizeof(uint32_t), _vfMasterDstBuffer);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texInputVideoDataID);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texVideoInputDataID);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
|
@ -1865,7 +1869,7 @@ OGLDisplayLayer::~OGLDisplayLayer()
|
|||
glDeleteBuffersARB(1, &this->_vboTexCoordID);
|
||||
glDeleteBuffersARB(1, &this->_vboElementID);
|
||||
glDeleteTextures(1, &this->_texCPUFilterDstID);
|
||||
glDeleteTextures(1, &this->_texInputVideoDataID);
|
||||
glDeleteTextures(1, &this->_texVideoInputDataID);
|
||||
|
||||
if (_canUseShaderOutput)
|
||||
{
|
||||
|
@ -1908,15 +1912,21 @@ void OGLDisplayLayer::SetMode(int dispMode)
|
|||
case DS_DISPLAY_TYPE_MAIN:
|
||||
this->_vfSingle->SetDstBufferPtr(_vfMasterDstBuffer);
|
||||
this->_vf = this->_vfSingle;
|
||||
this->_vtxElementCount = 6;
|
||||
this->_vtxElementPointer = 0;
|
||||
break;
|
||||
|
||||
case DS_DISPLAY_TYPE_TOUCH:
|
||||
this->_vfSingle->SetDstBufferPtr(_vfMasterDstBuffer + (this->_vfSingle->GetDstWidth() * this->_vfSingle->GetDstHeight()) );
|
||||
this->_vf = this->_vfSingle;
|
||||
this->_vtxElementCount = 6;
|
||||
this->_vtxElementPointer = (GLubyte *)(this->_vtxElementCount * sizeof(GLubyte));
|
||||
break;
|
||||
|
||||
case DS_DISPLAY_TYPE_DUAL:
|
||||
this->_vf = this->_vfDual;
|
||||
this->_vtxElementCount = 12;
|
||||
this->_vtxElementPointer = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -2279,8 +2289,8 @@ void OGLDisplayLayer::SetCPUFilterOGL(const VideoFilterTypeID videoFilterTypeID)
|
|||
const VideoFilterAttributes newFilterAttr = VideoFilter::GetAttributesByID(videoFilterTypeID);
|
||||
const size_t oldDstBufferWidth = this->_vfDual->GetDstWidth();
|
||||
const size_t oldDstBufferHeight = this->_vfDual->GetDstHeight();
|
||||
const GLsizei newDstBufferWidth = GPU_DISPLAY_WIDTH * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide;
|
||||
const GLsizei newDstBufferHeight = GPU_DISPLAY_HEIGHT * 2 * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide;
|
||||
const GLsizei newDstBufferWidth = this->_vfDual->GetSrcWidth() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide;
|
||||
const GLsizei newDstBufferHeight = this->_vfDual->GetSrcHeight() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide;
|
||||
|
||||
if (oldDstBufferWidth != newDstBufferWidth || oldDstBufferHeight != newDstBufferHeight)
|
||||
{
|
||||
|
@ -2327,73 +2337,80 @@ void OGLDisplayLayer::SetCPUFilterOGL(const VideoFilterTypeID videoFilterTypeID)
|
|||
this->_vfDual->ChangeFilterByID(videoFilterTypeID);
|
||||
}
|
||||
|
||||
void OGLDisplayLayer::ProcessOGL(const uint16_t *videoData, GLsizei w, GLsizei h)
|
||||
void OGLDisplayLayer::LoadFrameOGL(const uint16_t *frameData, GLsizei w, GLsizei h)
|
||||
{
|
||||
const GLint lineOffset = (this->_displayMode == DS_DISPLAY_TYPE_TOUCH) ? h : 0;
|
||||
const bool isUsingCPUPixelScaler = this->_pixelScaler != VideoFilterTypeID_None && !(this->_useShaderBasedPixelScaler && this->_filtersPreferGPU);
|
||||
|
||||
if (!isUsingCPUPixelScaler)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataID);
|
||||
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, lineOffset, w, h, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frameData);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
RGB555ToBGRA8888Buffer((const uint16_t *)frameData, this->_vf->GetSrcBufferPtr(), w * h);
|
||||
}
|
||||
}
|
||||
|
||||
void OGLDisplayLayer::ProcessOGL()
|
||||
{
|
||||
VideoFilter *currentFilter = this->_vf;
|
||||
GLint lineOffset = (this->_displayMode == DS_DISPLAY_TYPE_TOUCH) ? h : 0;
|
||||
const bool isUsingCPUPixelScaler = this->_pixelScaler != VideoFilterTypeID_None && !(this->_useShaderBasedPixelScaler && this->_filtersPreferGPU);
|
||||
|
||||
// Determine whether we should take CPU-based path or a GPU-based path
|
||||
if (this->_pixelScaler != VideoFilterTypeID_None && !(this->_useShaderBasedPixelScaler && this->_filtersPreferGPU) )
|
||||
// Source
|
||||
if (this->_useDeposterize)
|
||||
{
|
||||
if (!this->_useDeposterize) // Pure CPU-based path
|
||||
this->_texVideoSourceID = this->_filterDeposterize->RunFilterOGL(this->_texVideoInputDataID, this->_viewportWidth, this->_viewportHeight);
|
||||
|
||||
if (isUsingCPUPixelScaler) // Hybrid CPU/GPU-based path (may cause a performance hit on pixel download)
|
||||
{
|
||||
RGB555ToBGRA8888Buffer((const uint16_t *)videoData, (uint32_t *)currentFilter->GetSrcBufferPtr(), w * h);
|
||||
}
|
||||
else // Hybrid CPU/GPU-based path (may cause a performance hit on pixel download)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texInputVideoDataID);
|
||||
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, lineOffset, w, h, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, videoData);
|
||||
|
||||
this->_filterDeposterize->RunFilterOGL(this->_texInputVideoDataID, this->_viewportWidth, this->_viewportHeight);
|
||||
|
||||
const GLint lineOffset = (this->_displayMode == DS_DISPLAY_TYPE_TOUCH) ? GPU_DISPLAY_HEIGHT : 0;
|
||||
const GLsizei readLineCount = (this->_displayMode == DS_DISPLAY_TYPE_DUAL) ? GPU_DISPLAY_HEIGHT * 2 : GPU_DISPLAY_HEIGHT;
|
||||
this->_filterDeposterize->DownloadDstBufferOGL(currentFilter->GetSrcBufferPtr(), lineOffset, readLineCount);
|
||||
}
|
||||
|
||||
uint32_t *texData = currentFilter->RunFilter();
|
||||
w = currentFilter->GetDstWidth();
|
||||
h = currentFilter->GetDstHeight();
|
||||
lineOffset = (this->_displayMode == DS_DISPLAY_TYPE_TOUCH) ? h : 0;
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID);
|
||||
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, lineOffset, w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, texData);
|
||||
|
||||
this->_texOutputVideoDataID = this->_texCPUFilterDstID;
|
||||
this->UpdateTexCoords(w, (this->_displayMode == DS_DISPLAY_TYPE_DUAL) ? h : h*2);
|
||||
}
|
||||
else // Pure GPU-based path
|
||||
else
|
||||
{
|
||||
this->_texVideoSourceID = this->_texVideoInputDataID;
|
||||
}
|
||||
|
||||
// Pixel scaler
|
||||
if (!isUsingCPUPixelScaler)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texInputVideoDataID);
|
||||
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, lineOffset, w, h, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, videoData);
|
||||
|
||||
if (this->_useDeposterize)
|
||||
{
|
||||
this->_texOutputVideoDataID = this->_filterDeposterize->RunFilterOGL(this->_texInputVideoDataID, this->_viewportWidth, this->_viewportHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_texOutputVideoDataID = this->_texInputVideoDataID;
|
||||
}
|
||||
|
||||
if (this->_displayMode != DS_DISPLAY_TYPE_DUAL)
|
||||
{
|
||||
h *= 2;
|
||||
}
|
||||
|
||||
if (this->_useShaderBasedPixelScaler)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texOutputVideoDataID);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoSourceID);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
this->_texOutputVideoDataID = this->_shaderFilter->RunFilterOGL(this->_texOutputVideoDataID, this->_viewportWidth, this->_viewportHeight);
|
||||
w = this->_shaderFilter->GetDstWidth();
|
||||
h = this->_shaderFilter->GetDstHeight();
|
||||
this->_texVideoPixelScalerID = this->_shaderFilter->RunFilterOGL(this->_texVideoSourceID, this->_viewportWidth, this->_viewportHeight);
|
||||
|
||||
this->UpdateTexCoords(this->_shaderFilter->GetDstWidth(), this->_shaderFilter->GetDstHeight());
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_texVideoPixelScalerID = this->_texVideoSourceID;
|
||||
this->UpdateTexCoords(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT*2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t *texData = currentFilter->RunFilter();
|
||||
|
||||
this->UpdateTexCoords(w, h);
|
||||
const GLfloat w = currentFilter->GetDstWidth();
|
||||
const GLfloat h = currentFilter->GetDstHeight();
|
||||
const GLsizei lineOffset = (this->_displayMode == DS_DISPLAY_TYPE_TOUCH) ? h : 0;
|
||||
this->_texVideoPixelScalerID = this->_texCPUFilterDstID;
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoPixelScalerID);
|
||||
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, lineOffset, w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, texData);
|
||||
this->UpdateTexCoords(w, (this->_displayMode == DS_DISPLAY_TYPE_DUAL) ? h : h*2);
|
||||
}
|
||||
|
||||
// Output
|
||||
this->_texVideoOutputID = this->_texVideoPixelScalerID;
|
||||
this->UploadTexCoordsOGL();
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
}
|
||||
|
@ -2403,7 +2420,7 @@ void OGLDisplayLayer::RenderOGL()
|
|||
glUseProgram(this->_finalOutputProgram->GetProgramID());
|
||||
this->UploadTransformationOGL();
|
||||
|
||||
if (_needUploadVertices)
|
||||
if (this->_needUploadVertices)
|
||||
{
|
||||
this->UploadVerticesOGL();
|
||||
}
|
||||
|
@ -2411,14 +2428,11 @@ void OGLDisplayLayer::RenderOGL()
|
|||
// Enable vertex attributes
|
||||
glBindVertexArrayAPPLE(this->_vaoMainStatesID);
|
||||
|
||||
const GLsizei vtxElementCount = (this->_displayMode == DS_DISPLAY_TYPE_DUAL) ? 12 : 6;
|
||||
const GLubyte *elementPointer = !(this->_displayMode == DS_DISPLAY_TYPE_TOUCH) ? 0 : (GLubyte *)(vtxElementCount * sizeof(GLubyte));
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texOutputVideoDataID);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoOutputID);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter);
|
||||
glDrawElements(GL_TRIANGLES, vtxElementCount, GL_UNSIGNED_BYTE, elementPointer);
|
||||
glDrawElements(GL_TRIANGLES, this->_vtxElementCount, GL_UNSIGNED_BYTE, this->_vtxElementPointer);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
|
||||
// Disable vertex attributes
|
||||
|
|
|
@ -185,7 +185,7 @@ public:
|
|||
this->_viewportHeight = h;
|
||||
};
|
||||
|
||||
virtual void ProcessOGL(const uint16_t *videoData, GLsizei w, GLsizei h) {};
|
||||
virtual void ProcessOGL() {};
|
||||
virtual void RenderOGL() {};
|
||||
};
|
||||
|
||||
|
@ -219,6 +219,9 @@ protected:
|
|||
GLfloat _gapScalar;
|
||||
GLfloat _rotation;
|
||||
|
||||
GLsizei _vtxElementCount;
|
||||
GLubyte *_vtxElementPointer;
|
||||
|
||||
GLint _displayTexFilter;
|
||||
GLuint _texCPUFilterDstID;
|
||||
|
||||
|
@ -226,9 +229,10 @@ protected:
|
|||
GLfloat texCoordBuffer[2 * 8];
|
||||
size_t _vtxBufferOffset;
|
||||
|
||||
GLuint _texInputVideoDataID;
|
||||
GLuint _texOutputVideoDataID;
|
||||
GLuint _texPrevOutputVideoDataID;
|
||||
GLuint _texVideoInputDataID;
|
||||
GLuint _texVideoSourceID;
|
||||
GLuint _texVideoPixelScalerID;
|
||||
GLuint _texVideoOutputID;
|
||||
GLuint _vaoMainStatesID;
|
||||
GLuint _vboVertexID;
|
||||
GLuint _vboTexCoordID;
|
||||
|
@ -275,7 +279,8 @@ public:
|
|||
int GetPixelScaler();
|
||||
virtual void SetPixelScalerOGL(const int filterID);
|
||||
virtual void SetCPUFilterOGL(const VideoFilterTypeID videoFilterTypeID);
|
||||
virtual void ProcessOGL(const uint16_t *videoData, GLsizei w, GLsizei h);
|
||||
virtual void LoadFrameOGL(const uint16_t *frameData, GLsizei w, GLsizei h);
|
||||
virtual void ProcessOGL();
|
||||
virtual void RenderOGL();
|
||||
};
|
||||
|
||||
|
@ -297,7 +302,7 @@ public:
|
|||
virtual GLsizei GetViewportHeight();
|
||||
OGLDisplayLayer* GetDisplayLayer();
|
||||
|
||||
virtual void ProcessOGL(const uint16_t *videoData, GLsizei w, GLsizei h);
|
||||
virtual void ProcessOGL();
|
||||
virtual void RenderOGL();
|
||||
virtual void SetViewportSizeOGL(GLsizei w, GLsizei h);
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2013-2014 DeSmuME team
|
||||
Copyright (C) 2013-2015 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -70,6 +70,7 @@ extern "C"
|
|||
{
|
||||
#endif
|
||||
|
||||
void GPU_FillScreenWithBGRA5551(const uint16_t colorValue);
|
||||
void SetGPULayerState(const int gpuType, const unsigned int i, const bool state);
|
||||
bool GetGPULayerState(const int gpuType, const unsigned int i);
|
||||
void SetGPUDisplayState(const int gpuType, const bool state);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2013-2014 DeSmuME team
|
||||
Copyright (C) 2013-2015 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -100,6 +100,8 @@ GPU3DInterface *core3DList[] = {
|
|||
&OSXOpenGLRendererBegin,
|
||||
&OSXOpenGLRendererEnd);
|
||||
|
||||
GPU_FillScreenWithBGRA5551(0x8000);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -821,6 +823,26 @@ bool GetGPUDisplayState(const int gpuType)
|
|||
return theState;
|
||||
}
|
||||
|
||||
void GPU_FillScreenWithBGRA5551(const uint16_t colorValue)
|
||||
{
|
||||
const size_t pixCount = sizeof(GPU_screen) / sizeof(uint16_t);
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (pixCount % 16 == 0)
|
||||
{
|
||||
const uint16_t colorValuePattern[] = {colorValue, colorValue, colorValue, colorValue, colorValue, colorValue, colorValue, colorValue};
|
||||
memset_pattern16(GPU_screen, colorValuePattern, sizeof(GPU_screen));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
for (size_t i = 0; i < pixCount; i++)
|
||||
{
|
||||
((uint16_t *)GPU_screen)[i] = colorValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CGLContextObj OSXOpenGLRendererContext = NULL;
|
||||
CGLPBufferObj OSXOpenGLRendererPBuffer = NULL;
|
||||
|
||||
|
|
|
@ -890,6 +890,7 @@ volatile bool execute = true;
|
|||
|
||||
pthread_mutex_lock(&threadParam.mutexThreadExecute);
|
||||
NDS_Reset();
|
||||
GPU_FillScreenWithBGRA5551(0xFFFF);
|
||||
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
|
||||
|
||||
[self restoreCoreState];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2011 Roger Manuel
|
||||
Copyright (C) 2012-2014 DeSmuME Team
|
||||
Copyright (C) 2012-2015 DeSmuME Team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -438,8 +438,6 @@ enum
|
|||
MESSAGE_SET_RENDER3D_THREADS,
|
||||
MESSAGE_SET_RENDER3D_LINE_HACK,
|
||||
MESSAGE_SET_RENDER3D_MULTISAMPLE,
|
||||
MESSAGE_SET_VIEW_TO_BLACK,
|
||||
MESSAGE_SET_VIEW_TO_WHITE,
|
||||
|
||||
MESSAGE_SET_AUDIO_PROCESS_METHOD,
|
||||
MESSAGE_SET_SPU_ADVANCED_LOGIC,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2011 Roger Manuel
|
||||
Copyright (C) 2011-2014 DeSmuME team
|
||||
Copyright (C) 2011-2015 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -36,18 +36,17 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
int32_t videoSourceID;
|
||||
int32_t displayModeID;
|
||||
uint16_t width; // Measured in pixels
|
||||
uint16_t height; // Measured in pixels
|
||||
} DisplaySrcPixelAttributes;
|
||||
uint16_t *buffer; // Pointer to frame buffer
|
||||
size_t bufferSize; // Size (in bytes) of frame buffer
|
||||
int32_t displayModeID; // The selected display to read from
|
||||
uint16_t width; // Measured in pixels
|
||||
uint16_t height; // Measured in pixels
|
||||
} GPUFrame;
|
||||
|
||||
@interface CocoaDSOutput : CocoaDSThread
|
||||
{
|
||||
BOOL isStateChanged;
|
||||
NSUInteger frameCount;
|
||||
NSData *frameData;
|
||||
NSData *frameAttributesData;
|
||||
NSMutableDictionary *property;
|
||||
|
||||
pthread_mutex_t *mutexConsume;
|
||||
|
@ -56,14 +55,12 @@ typedef struct
|
|||
|
||||
@property (assign) BOOL isStateChanged;
|
||||
@property (assign) NSUInteger frameCount;
|
||||
@property (retain) NSData *frameData;
|
||||
@property (retain) NSData *frameAttributesData;
|
||||
@property (readonly) NSMutableDictionary *property;
|
||||
@property (assign) pthread_rwlock_t *rwlockProducer;
|
||||
@property (readonly) pthread_mutex_t *mutexConsume;
|
||||
|
||||
- (void) doCoreEmuFrame;
|
||||
- (void) handleEmuFrameProcessed:(NSData *)mainData attributes:(NSData *)attributesData;
|
||||
- (void) handleEmuFrameProcessed;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -127,7 +124,8 @@ typedef struct
|
|||
|
||||
@required
|
||||
- (void) doInitVideoOutput:(NSDictionary *)properties;
|
||||
- (void) doProcessVideoFrame:(const void *)videoFrameData displayMode:(const NSInteger)frameDisplayMode width:(const NSInteger)frameWidth height:(const NSInteger)frameHeight;
|
||||
- (void) doLoadVideoFrame:(const void *)videoFrameData displayMode:(const NSInteger)frameDisplayMode width:(const NSInteger)frameWidth height:(const NSInteger)frameHeight;
|
||||
- (void) doProcessVideoFrame;
|
||||
|
||||
@optional
|
||||
- (void) doResizeView:(NSRect)rect;
|
||||
|
@ -145,6 +143,7 @@ typedef struct
|
|||
id <CocoaDSDisplayDelegate> delegate;
|
||||
NSInteger displayMode;
|
||||
NSSize frameSize;
|
||||
GPUFrame _gpuFrame;
|
||||
|
||||
OSSpinLock spinlockDisplayType;
|
||||
}
|
||||
|
@ -154,14 +153,9 @@ typedef struct
|
|||
@property (readonly) NSSize frameSize;
|
||||
|
||||
- (void) handleChangeDisplayMode:(NSData *)displayModeData;
|
||||
- (void) handleSetViewToBlack;
|
||||
- (void) handleSetViewToWhite;
|
||||
- (void) handleRequestScreenshot:(NSData *)fileURLStringData fileTypeData:(NSData *)fileTypeData;
|
||||
- (void) handleCopyToPasteboard;
|
||||
|
||||
- (NSData *) videoFrameUsingRGBA5551:(uint16_t)colorValue pixelCount:(size_t)pixCount;
|
||||
- (void) sendVideoFrameOfRGBA5551:(uint16_t)colorValue;
|
||||
|
||||
- (NSImage *) image;
|
||||
- (NSBitmapImageRep *) bitmapImageRep;
|
||||
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
|
||||
@synthesize isStateChanged;
|
||||
@synthesize frameCount;
|
||||
@synthesize frameData;
|
||||
@synthesize frameAttributesData;
|
||||
@synthesize property;
|
||||
@synthesize mutexConsume;
|
||||
@synthesize rwlockProducer;
|
||||
|
@ -52,8 +50,6 @@
|
|||
|
||||
isStateChanged = NO;
|
||||
frameCount = 0;
|
||||
frameData = nil;
|
||||
frameAttributesData = nil;
|
||||
|
||||
property = [[NSMutableDictionary alloc] init];
|
||||
[property setValue:[NSDate date] forKey:@"outputTime"];
|
||||
|
@ -69,8 +65,6 @@
|
|||
// Force the thread to exit now so that we can safely release other resources.
|
||||
[self forceThreadExit];
|
||||
|
||||
self.frameData = nil;
|
||||
self.frameAttributesData = nil;
|
||||
[property release];
|
||||
|
||||
pthread_mutex_destroy(mutexConsume);
|
||||
|
@ -93,7 +87,7 @@
|
|||
switch (message)
|
||||
{
|
||||
case MESSAGE_EMU_FRAME_PROCESSED:
|
||||
[self handleEmuFrameProcessed:[messageComponents objectAtIndex:0] attributes:[messageComponents objectAtIndex:1]];
|
||||
[self handleEmuFrameProcessed];
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -102,11 +96,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void) handleEmuFrameProcessed:(NSData *)mainData attributes:(NSData *)attributesData
|
||||
- (void) handleEmuFrameProcessed
|
||||
{
|
||||
self.frameCount++;
|
||||
self.frameData = mainData;
|
||||
self.frameAttributesData = attributesData;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -433,10 +425,6 @@
|
|||
|
||||
switch (message)
|
||||
{
|
||||
case MESSAGE_EMU_FRAME_PROCESSED:
|
||||
[self handleEmuFrameProcessed:nil attributes:nil];
|
||||
break;
|
||||
|
||||
case MESSAGE_SET_AUDIO_PROCESS_METHOD:
|
||||
[self handleSetAudioOutputEngine:[messageComponents objectAtIndex:0]];
|
||||
break;
|
||||
|
@ -467,11 +455,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void) handleEmuFrameProcessed:(NSData *)mainData attributes:(NSData *)attributesData
|
||||
- (void) handleEmuFrameProcessed
|
||||
{
|
||||
SPU_Emulate_user();
|
||||
|
||||
[super handleEmuFrameProcessed:mainData attributes:attributesData];
|
||||
[super handleEmuFrameProcessed];
|
||||
}
|
||||
|
||||
- (void) handleSetVolume:(NSData *)volumeData
|
||||
|
@ -533,6 +521,12 @@
|
|||
displayMode = DS_DISPLAY_TYPE_DUAL;
|
||||
frameSize = NSMakeSize((CGFloat)GPU_DISPLAY_WIDTH, (CGFloat)GPU_DISPLAY_HEIGHT * 2);
|
||||
|
||||
_gpuFrame.buffer = (uint16_t *)GPU_screen;
|
||||
_gpuFrame.bufferSize = GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT * 2 * sizeof(uint16_t);
|
||||
_gpuFrame.displayModeID = DS_DISPLAY_TYPE_DUAL;
|
||||
_gpuFrame.width = frameSize.width;
|
||||
_gpuFrame.height = frameSize.height;
|
||||
|
||||
[property setValue:[NSNumber numberWithInteger:displayMode] forKey:@"displayMode"];
|
||||
[property setValue:NSSTRING_DISPLAYMODE_MAIN forKey:@"displayModeString"];
|
||||
|
||||
|
@ -542,7 +536,7 @@
|
|||
- (void)dealloc
|
||||
{
|
||||
[self setDelegate:nil];
|
||||
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
@ -597,31 +591,6 @@
|
|||
return size;
|
||||
}
|
||||
|
||||
- (void) doCoreEmuFrame
|
||||
{
|
||||
NSInteger displayModeID = [self displayMode];
|
||||
NSSize displayFrameSize = [self frameSize];
|
||||
|
||||
// We will be ignoring the actual video data here since we will be pulling the video data
|
||||
// from the consumer thread instead.
|
||||
NSData *gpuData = [[NSData alloc] init];
|
||||
|
||||
DisplaySrcPixelAttributes attr;
|
||||
attr.videoSourceID = VIDEO_SOURCE_EMULATOR;
|
||||
attr.displayModeID = (int32_t)displayModeID;
|
||||
attr.width = (uint16_t)displayFrameSize.width;
|
||||
attr.height = (uint16_t)displayFrameSize.height;
|
||||
|
||||
NSData *attributesData = [[NSData alloc] initWithBytes:&attr length:sizeof(DisplaySrcPixelAttributes)];
|
||||
|
||||
NSArray *messageComponents = [[NSArray alloc] initWithObjects:gpuData, attributesData, nil];
|
||||
[CocoaDSUtil messageSendOneWayWithMessageComponents:self.receivePort msgID:MESSAGE_EMU_FRAME_PROCESSED array:messageComponents];
|
||||
|
||||
[gpuData release];
|
||||
[attributesData release];
|
||||
[messageComponents release];
|
||||
}
|
||||
|
||||
- (void)handlePortMessage:(NSPortMessage *)portMessage
|
||||
{
|
||||
NSInteger message = (NSInteger)[portMessage msgid];
|
||||
|
@ -629,22 +598,10 @@
|
|||
|
||||
switch (message)
|
||||
{
|
||||
case MESSAGE_EMU_FRAME_PROCESSED:
|
||||
[self handleEmuFrameProcessed:[messageComponents objectAtIndex:0] attributes:[messageComponents objectAtIndex:1]];
|
||||
break;
|
||||
|
||||
case MESSAGE_CHANGE_DISPLAY_TYPE:
|
||||
[self handleChangeDisplayMode:[messageComponents objectAtIndex:0]];
|
||||
break;
|
||||
|
||||
case MESSAGE_SET_VIEW_TO_BLACK:
|
||||
[self handleSetViewToBlack];
|
||||
break;
|
||||
|
||||
case MESSAGE_SET_VIEW_TO_WHITE:
|
||||
[self handleSetViewToWhite];
|
||||
break;
|
||||
|
||||
case MESSAGE_REQUEST_SCREENSHOT:
|
||||
[self handleRequestScreenshot:[messageComponents objectAtIndex:0] fileTypeData:[messageComponents objectAtIndex:1]];
|
||||
break;
|
||||
|
@ -659,9 +616,34 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void) handleEmuFrameProcessed:(NSData *)mainData attributes:(NSData *)attributesData
|
||||
- (void) handleEmuFrameProcessed
|
||||
{
|
||||
[super handleEmuFrameProcessed:mainData attributes:attributesData];
|
||||
_gpuFrame.displayModeID = [self displayMode];
|
||||
_gpuFrame.width = [self frameSize].width;
|
||||
_gpuFrame.height = [self frameSize].height;
|
||||
|
||||
switch (_gpuFrame.displayModeID)
|
||||
{
|
||||
case DS_DISPLAY_TYPE_MAIN:
|
||||
_gpuFrame.buffer = (uint16_t *)GPU_screen;
|
||||
_gpuFrame.bufferSize = GPU_SCREEN_SIZE_BYTES;
|
||||
break;
|
||||
|
||||
case DS_DISPLAY_TYPE_TOUCH:
|
||||
_gpuFrame.buffer = (uint16_t *)GPU_screen + (GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT);
|
||||
_gpuFrame.bufferSize = GPU_SCREEN_SIZE_BYTES;
|
||||
break;
|
||||
|
||||
case DS_DISPLAY_TYPE_DUAL:
|
||||
_gpuFrame.buffer = (uint16_t *)GPU_screen;
|
||||
_gpuFrame.bufferSize = GPU_SCREEN_SIZE_BYTES * 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
[super handleEmuFrameProcessed];
|
||||
}
|
||||
|
||||
- (void) handleChangeDisplayMode:(NSData *)displayModeData
|
||||
|
@ -676,16 +658,6 @@
|
|||
[delegate doDisplayModeChanged:displayModeID];
|
||||
}
|
||||
|
||||
- (void) handleSetViewToBlack
|
||||
{
|
||||
[self sendVideoFrameOfRGBA5551:0x8000];
|
||||
}
|
||||
|
||||
- (void) handleSetViewToWhite
|
||||
{
|
||||
[self sendVideoFrameOfRGBA5551:0xFFFF];
|
||||
}
|
||||
|
||||
- (void) handleRequestScreenshot:(NSData *)fileURLStringData fileTypeData:(NSData *)fileTypeData
|
||||
{
|
||||
NSString *fileURLString = [[NSString alloc] initWithData:fileURLStringData encoding:NSUTF8StringEncoding];
|
||||
|
@ -717,54 +689,6 @@
|
|||
[pboard setData:[screenshot TIFFRepresentationUsingCompression:NSTIFFCompressionLZW factor:1.0f] forType:NSTIFFPboardType];
|
||||
}
|
||||
|
||||
- (NSData *) videoFrameUsingRGBA5551:(uint16_t)colorValue pixelCount:(size_t)pixCount
|
||||
{
|
||||
NSData *gpuData = nil;
|
||||
const size_t bufSize = pixCount * sizeof(uint16_t);
|
||||
uint16_t *gpuBytes = (uint16_t *)malloc(bufSize);
|
||||
if (gpuBytes == NULL)
|
||||
{
|
||||
return gpuData;
|
||||
}
|
||||
|
||||
if (pixCount % 16 == 0)
|
||||
{
|
||||
const uint16_t colorValuePattern[] = {colorValue, colorValue, colorValue, colorValue, colorValue, colorValue, colorValue, colorValue};
|
||||
memset_pattern16(gpuBytes, colorValuePattern, bufSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(gpuBytes, colorValue, bufSize);
|
||||
}
|
||||
|
||||
|
||||
gpuData = [NSData dataWithBytes:gpuBytes length:bufSize];
|
||||
|
||||
free(gpuBytes);
|
||||
gpuBytes = nil;
|
||||
|
||||
return gpuData;
|
||||
}
|
||||
|
||||
- (void) sendVideoFrameOfRGBA5551:(uint16_t)colorValue
|
||||
{
|
||||
const NSInteger displayModeID = [self displayMode];
|
||||
const NSSize displayFrameSize = [self frameSize];
|
||||
const size_t pixCount = (displayModeID == DS_DISPLAY_TYPE_DUAL) ? GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT * 2 : GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT;
|
||||
|
||||
NSData *videoData = [self videoFrameUsingRGBA5551:colorValue pixelCount:pixCount];
|
||||
|
||||
DisplaySrcPixelAttributes attr;
|
||||
attr.videoSourceID = VIDEO_SOURCE_INTERNAL;
|
||||
attr.displayModeID = (int32_t)displayModeID;
|
||||
attr.width = (uint16_t)displayFrameSize.width;
|
||||
attr.height = (uint16_t)displayFrameSize.height;
|
||||
|
||||
NSData *attributesData = [NSData dataWithBytes:&attr length:sizeof(DisplaySrcPixelAttributes)];
|
||||
|
||||
[self handleEmuFrameProcessed:videoData attributes:attributesData];
|
||||
}
|
||||
|
||||
- (NSImage *) image
|
||||
{
|
||||
NSImage *newImage = [[NSImage alloc] initWithSize:self.frameSize];
|
||||
|
@ -790,7 +714,7 @@
|
|||
|
||||
- (NSBitmapImageRep *) bitmapImageRep
|
||||
{
|
||||
if (self.frameData == nil)
|
||||
if (_gpuFrame.buffer == NULL)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
@ -815,7 +739,9 @@
|
|||
}
|
||||
|
||||
uint32_t *bitmapData = (uint32_t *)[imageRep bitmapData];
|
||||
RGB555ToRGBA8888Buffer((const uint16_t *)[self.frameData bytes], bitmapData, (w * h));
|
||||
pthread_rwlock_rdlock(self.rwlockProducer);
|
||||
RGB555ToRGBA8888Buffer((const uint16_t *)_gpuFrame.buffer, bitmapData, (w * h));
|
||||
pthread_rwlock_unlock(self.rwlockProducer);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uint32_t *bitmapDataEnd = bitmapData + (w * h);
|
||||
|
@ -867,10 +793,6 @@
|
|||
|
||||
switch (message)
|
||||
{
|
||||
case MESSAGE_EMU_FRAME_PROCESSED:
|
||||
[self handleEmuFrameProcessed:[messageComponents objectAtIndex:0] attributes:[messageComponents objectAtIndex:1]];
|
||||
break;
|
||||
|
||||
case MESSAGE_REPROCESS_AND_REDRAW:
|
||||
[self handleReprocessAndRedraw];
|
||||
break;
|
||||
|
@ -905,60 +827,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void) handleEmuFrameProcessed:(NSData *)mainData attributes:(NSData *)attributesData
|
||||
- (void) handleEmuFrameProcessed
|
||||
{
|
||||
if (mainData == nil || attributesData == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
[super handleEmuFrameProcessed];
|
||||
|
||||
NSData *newVideoFrame = mainData;
|
||||
DisplaySrcPixelAttributes attr = *(DisplaySrcPixelAttributes *)[attributesData bytes];
|
||||
const NSInteger frameDisplayMode = attr.displayModeID;
|
||||
const NSInteger frameSource = attr.videoSourceID;
|
||||
const NSInteger frameWidth = attr.width;
|
||||
const NSInteger frameHeight = attr.height;
|
||||
pthread_rwlock_rdlock(self.rwlockProducer);
|
||||
[(id<CocoaDSDisplayVideoDelegate>)delegate doLoadVideoFrame:_gpuFrame.buffer
|
||||
displayMode:_gpuFrame.displayModeID
|
||||
width:_gpuFrame.width
|
||||
height:_gpuFrame.height];
|
||||
pthread_rwlock_unlock(self.rwlockProducer);
|
||||
|
||||
if (frameSource == VIDEO_SOURCE_EMULATOR)
|
||||
{
|
||||
// Note that we simply received the attributes of the video data, not the actual
|
||||
// video data itself. So from here, we need to pull the video data from the
|
||||
// emulator and copy it to this thread.
|
||||
//
|
||||
// The video data contains the pixels from both the main and touch screens. So
|
||||
// depending on the display mode, we copy only the pixels from the respective
|
||||
// screen.
|
||||
|
||||
pthread_rwlock_rdlock(self.rwlockProducer);
|
||||
|
||||
switch (frameDisplayMode)
|
||||
{
|
||||
case DS_DISPLAY_TYPE_MAIN:
|
||||
newVideoFrame = [NSData dataWithBytes:GPU_screen length:GPU_SCREEN_SIZE_BYTES];
|
||||
break;
|
||||
|
||||
case DS_DISPLAY_TYPE_TOUCH:
|
||||
newVideoFrame = [NSData dataWithBytes:(GPU_screen + GPU_SCREEN_SIZE_BYTES) length:GPU_SCREEN_SIZE_BYTES];
|
||||
break;
|
||||
|
||||
case DS_DISPLAY_TYPE_DUAL:
|
||||
newVideoFrame = [NSData dataWithBytes:GPU_screen length:GPU_SCREEN_SIZE_BYTES*2];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_rwlock_unlock(self.rwlockProducer);
|
||||
}
|
||||
|
||||
[(id<CocoaDSDisplayVideoDelegate>)delegate doProcessVideoFrame:[newVideoFrame bytes] displayMode:frameDisplayMode width:frameWidth height:frameHeight];
|
||||
|
||||
// If we need to use our saved frame data, make sure that we don't pull from the
|
||||
// emulation thread again.
|
||||
attr.videoSourceID = VIDEO_SOURCE_INTERNAL;
|
||||
NSData *savedAttributesData = [NSData dataWithBytes:&attr length:sizeof(DisplaySrcPixelAttributes)];
|
||||
[super handleEmuFrameProcessed:newVideoFrame attributes:savedAttributesData];
|
||||
[(id<CocoaDSDisplayVideoDelegate>)delegate doProcessVideoFrame];
|
||||
}
|
||||
|
||||
- (void) handleResizeView:(NSData *)rectData
|
||||
|
@ -994,7 +874,7 @@
|
|||
|
||||
- (void) handleReprocessAndRedraw
|
||||
{
|
||||
[self handleEmuFrameProcessed:self.frameData attributes:self.frameAttributesData];
|
||||
[self handleEmuFrameProcessed];
|
||||
}
|
||||
|
||||
- (void) handleChangeDisplayOrientation:(NSData *)displayOrientationIdData
|
||||
|
|
Loading…
Reference in New Issue