diff --git a/desmume/src/frontend/cocoa/ClientDisplayView.cpp b/desmume/src/frontend/cocoa/ClientDisplayView.cpp index 708e7b9e7..7531add7c 100644 --- a/desmume/src/frontend/cocoa/ClientDisplayView.cpp +++ b/desmume/src/frontend/cocoa/ClientDisplayView.cpp @@ -21,6 +21,8 @@ ClientDisplayView::ClientDisplayView() { + _fetchObject = NULL; + ClientDisplayViewProperties defaultProperty; defaultProperty.normalWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH; defaultProperty.normalHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2.0; @@ -80,6 +82,7 @@ void ClientDisplayView::__InstanceInit(const ClientDisplayViewProperties &props) memset(&_emuFrameInfo, 0, sizeof(_emuFrameInfo)); _hudString = "\x01"; // Char value 0x01 will represent the "text box" character, which will always be first in the string. _hudNeedsUpdate = true; + _allowViewUpdates = true; FT_Error error = FT_Init_FreeType(&_ftLibrary); if (error) @@ -481,14 +484,24 @@ void ClientDisplayView::ClearHUDNeedsUpdate() } // NDS GPU Interface -void ClientDisplayView::_FetchNativeDisplayByID(const NDSDisplayID displayID) +const GPUClientFetchObject& ClientDisplayView::GetFetchObject() const { - // Do nothing. This is implementation dependent. + return *this->_fetchObject; } -void ClientDisplayView::_FetchCustomDisplayByID(const NDSDisplayID displayID) +void ClientDisplayView::SetFetchObject(GPUClientFetchObject *fetchObject) { - // Do nothing. This is implementation dependent. + this->_fetchObject = fetchObject; +} + +bool ClientDisplayView::GetAllowViewUpdates() const +{ + return this->_allowViewUpdates; +} + +void ClientDisplayView::SetAllowViewUpdates(const bool allowUpdates) +{ + this->_allowViewUpdates = allowUpdates; } void ClientDisplayView::_LoadNativeDisplayByID(const NDSDisplayID displayID) @@ -501,38 +514,10 @@ void ClientDisplayView::_LoadCustomDisplayByID(const NDSDisplayID displayID) // Do nothing. This is implementation dependent. } -void ClientDisplayView::FetchDisplays() -{ - const bool loadMainScreen = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Main] && ((this->_renderProperty.mode == ClientDisplayMode_Main) || (this->_renderProperty.mode == ClientDisplayMode_Dual)); - const bool loadTouchScreen = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Touch] && ((this->_renderProperty.mode == ClientDisplayMode_Touch) || (this->_renderProperty.mode == ClientDisplayMode_Dual)); - - if (loadMainScreen) - { - if (!this->_emuDisplayInfo.didPerformCustomRender[NDSDisplayID_Main]) - { - this->_FetchNativeDisplayByID(NDSDisplayID_Main); - } - else - { - this->_FetchCustomDisplayByID(NDSDisplayID_Main); - } - } - - if (loadTouchScreen) - { - if (!this->_emuDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch]) - { - this->_FetchNativeDisplayByID(NDSDisplayID_Touch); - } - else - { - this->_FetchCustomDisplayByID(NDSDisplayID_Touch); - } - } -} - void ClientDisplayView::LoadDisplays() { + this->_emuDisplayInfo = this->_fetchObject->GetFetchDisplayInfoForBufferIndex(this->_fetchObject->GetLastFetchIndex()); + const bool loadMainScreen = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Main] && ((this->_renderProperty.mode == ClientDisplayMode_Main) || (this->_renderProperty.mode == ClientDisplayMode_Dual)); const bool loadTouchScreen = this->_emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Touch] && ((this->_renderProperty.mode == ClientDisplayMode_Touch) || (this->_renderProperty.mode == ClientDisplayMode_Dual)); @@ -987,16 +972,6 @@ void ClientDisplay3DView::SetSourceDeposterize(bool useDeposterize) this->_useDeposterize = (this->_canFilterOnGPU) ? useDeposterize : false; } -void ClientDisplay3DView::SetVideoBuffers(const uint32_t colorFormat, - const void *videoBufferHead, - const void *nativeBuffer0, - const void *nativeBuffer1, - const void *customBuffer0, const size_t customWidth0, const size_t customHeight0, - const void *customBuffer1, const size_t customWidth1, const size_t customHeight1) -{ - // Do nothing. This is implementation dependent. -} - void ClientDisplay3DView::SetHUDVertices(float viewportWidth, float viewportHeight, float *vtxBufferPtr) { const char *cString = this->_hudString.c_str(); diff --git a/desmume/src/frontend/cocoa/ClientDisplayView.h b/desmume/src/frontend/cocoa/ClientDisplayView.h index edcfc1c3a..be22e0909 100644 --- a/desmume/src/frontend/cocoa/ClientDisplayView.h +++ b/desmume/src/frontend/cocoa/ClientDisplayView.h @@ -114,6 +114,7 @@ protected: ClientDisplayViewProperties _renderProperty; ClientDisplayViewProperties _stagedProperty; InitialTouchPressMap *_initialTouchInMajorDisplay; + GPUClientFetchObject *_fetchObject; bool _useDeposterize; VideoFilterTypeID _pixelScaler; @@ -135,6 +136,7 @@ protected: NDSFrameInfo _emuFrameInfo; std::string _hudString; bool _hudNeedsUpdate; + bool _allowViewUpdates; FT_Library _ftLibrary; const char *_lastFontFilePath; @@ -151,8 +153,6 @@ protected: virtual void _UpdateClientSize(); virtual void _UpdateViewScale(); - virtual void _FetchNativeDisplayByID(const NDSDisplayID displayID); - virtual void _FetchCustomDisplayByID(const NDSDisplayID displayID); virtual void _LoadNativeDisplayByID(const NDSDisplayID displayID); virtual void _LoadCustomDisplayByID(const NDSDisplayID displayID); @@ -218,11 +218,16 @@ public: void ClearHUDNeedsUpdate(); // Client view interface - virtual void FetchDisplays(); + const GPUClientFetchObject& GetFetchObject() const; + void SetFetchObject(GPUClientFetchObject *fetchObject); + + bool GetAllowViewUpdates() const; + void SetAllowViewUpdates(const bool allowUpdates); + virtual void LoadDisplays(); virtual void ProcessDisplays(); virtual void UpdateView(); - virtual void FrameFinish() = 0; + virtual void FinishFrameAtIndex(const u8 bufferIndex) = 0; // Emulator interface const NDSDisplayInfo& GetEmuDisplayInfo() const; @@ -269,13 +274,6 @@ public: virtual void SetSourceDeposterize(const bool useDeposterize); - virtual void SetVideoBuffers(const uint32_t colorFormat, - const void *videoBufferHead, - const void *nativeBuffer0, - const void *nativeBuffer1, - const void *customBuffer0, const size_t customWidth0, const size_t customHeight0, - const void *customBuffer1, const size_t customWidth1, const size_t customHeight1); - void SetHUDVertices(float viewportWidth, float viewportHeight, float *vtxBufferPtr); void SetHUDTextureCoordinates(float *texCoordBufferPtr); void SetScreenVertices(float *vtxBufferPtr); diff --git a/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp b/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp index 0e8358970..2acbf0388 100644 --- a/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp +++ b/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp @@ -18,6 +18,7 @@ #include "OGLDisplayOutput.h" #include "cocoa_globals.h" #include "utilities.h" +#include "../../common.h" #include "../../utils/colorspacehandler/colorspacehandler.h" #include "../../filter/videofilter.h" @@ -4232,6 +4233,8 @@ static void InitHQnxLUTs() return; } + lutValuesInited = true; + _LQ2xLUT = (LUTValues *)malloc(256*(2*2)*16 * sizeof(LUTValues)); _HQ2xLUT = (LUTValues *)malloc(256*(2*2)*16 * sizeof(LUTValues)); _HQ3xLUT = (LUTValues *)malloc(256*(3*3)*16 * sizeof(LUTValues) + 2); @@ -4350,8 +4353,59 @@ static void InitHQnxLUTs() #undef I97 #undef I1411 #undef I151 +} + +void SetupHQnxLUTs(GLenum textureIndex, GLuint &texLQ2xLUT, GLuint &texHQ2xLUT, GLuint &texHQ3xLUT, GLuint &texHQ4xLUT) +{ + InitHQnxLUTs(); - lutValuesInited = true; + glGenTextures(1, &texLQ2xLUT); + glGenTextures(1, &texHQ2xLUT); + glGenTextures(1, &texHQ3xLUT); + glGenTextures(1, &texHQ4xLUT); + glActiveTexture(textureIndex); + + glBindTexture(GL_TEXTURE_3D, texLQ2xLUT); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 256*2, 4, 16, 0, GL_BGR, GL_UNSIGNED_BYTE, _LQ2xLUT); + + glBindTexture(GL_TEXTURE_3D, texHQ2xLUT); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 256*2, 4, 16, 0, GL_BGR, GL_UNSIGNED_BYTE, _HQ2xLUT); + + glBindTexture(GL_TEXTURE_3D, texHQ3xLUT); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 256*2, 9, 16, 0, GL_BGR, GL_UNSIGNED_BYTE, _HQ3xLUT); + + glBindTexture(GL_TEXTURE_3D, texHQ4xLUT); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 256*2, 16, 16, 0, GL_BGR, GL_UNSIGNED_BYTE, _HQ4xLUT); + + glBindTexture(GL_TEXTURE_3D, 0); + glActiveTexture(GL_TEXTURE0); +} + +void DeleteHQnxLUTs(GLenum textureIndex, GLuint &texLQ2xLUT, GLuint &texHQ2xLUT, GLuint &texHQ3xLUT, GLuint &texHQ4xLUT) +{ + glActiveTexture(textureIndex); + glBindTexture(GL_TEXTURE_3D, 0); + glDeleteTextures(1, &texLQ2xLUT); + glDeleteTextures(1, &texHQ2xLUT); + glDeleteTextures(1, &texHQ3xLUT); + glDeleteTextures(1, &texHQ4xLUT); + glActiveTexture(GL_TEXTURE0); } #pragma mark - @@ -4812,6 +4866,251 @@ bool OGLShaderProgram::LinkOGL() #pragma mark - +OGLClientFetchObject::OGLClientFetchObject() +{ + _contextInfo = NULL; + _useCPUFilterPipeline = true; + _fetchColorFormatOGL = GL_UNSIGNED_SHORT_1_5_5_5_REV; + + pthread_rwlock_init(&_srcCloneRWLock[NDSDisplayID_Main][0], NULL); + pthread_rwlock_init(&_srcCloneRWLock[NDSDisplayID_Touch][0], NULL); + pthread_rwlock_init(&_srcCloneRWLock[NDSDisplayID_Main][1], NULL); + pthread_rwlock_init(&_srcCloneRWLock[NDSDisplayID_Touch][1], NULL); + + _srcNativeCloneMaster = (uint32_t *)malloc_alignedPage(GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * 2 * sizeof(uint32_t)); + _srcNativeClone[NDSDisplayID_Main][0] = _srcNativeCloneMaster + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 0); + _srcNativeClone[NDSDisplayID_Touch][0] = _srcNativeCloneMaster + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 1); + _srcNativeClone[NDSDisplayID_Main][1] = _srcNativeCloneMaster + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2); + _srcNativeClone[NDSDisplayID_Touch][1] = _srcNativeCloneMaster + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 3); + memset(_srcNativeCloneMaster, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * sizeof(uint32_t)); +} + +OGLClientFetchObject::~OGLClientFetchObject() +{ + if (this->_contextInfo->IsShaderSupported()) + { + DeleteHQnxLUTs(GL_TEXTURE0 + 1, this->_texLQ2xLUT, this->_texHQ2xLUT, this->_texHQ3xLUT, this->_texHQ4xLUT); + } + + glDeleteTextures(4, &this->_texDisplayFetchNative[0][0]); + glDeleteTextures(4, &this->_texDisplayFetchCustom[0][0]); + + pthread_rwlock_wrlock(&this->_srcCloneRWLock[NDSDisplayID_Main][0]); + pthread_rwlock_wrlock(&this->_srcCloneRWLock[NDSDisplayID_Touch][0]); + pthread_rwlock_wrlock(&this->_srcCloneRWLock[NDSDisplayID_Main][1]); + pthread_rwlock_wrlock(&this->_srcCloneRWLock[NDSDisplayID_Touch][1]); + free_aligned(this->_srcNativeCloneMaster); + this->_srcNativeCloneMaster = NULL; + this->_srcNativeClone[NDSDisplayID_Main][0] = NULL; + this->_srcNativeClone[NDSDisplayID_Touch][0] = NULL; + this->_srcNativeClone[NDSDisplayID_Main][1] = NULL; + this->_srcNativeClone[NDSDisplayID_Touch][1] = NULL; + pthread_rwlock_unlock(&this->_srcCloneRWLock[NDSDisplayID_Touch][1]); + pthread_rwlock_unlock(&this->_srcCloneRWLock[NDSDisplayID_Main][1]); + pthread_rwlock_unlock(&this->_srcCloneRWLock[NDSDisplayID_Touch][0]); + pthread_rwlock_unlock(&this->_srcCloneRWLock[NDSDisplayID_Main][0]); + + pthread_rwlock_destroy(&this->_srcCloneRWLock[NDSDisplayID_Main][0]); + pthread_rwlock_destroy(&this->_srcCloneRWLock[NDSDisplayID_Touch][0]); + pthread_rwlock_destroy(&this->_srcCloneRWLock[NDSDisplayID_Main][1]); + pthread_rwlock_destroy(&this->_srcCloneRWLock[NDSDisplayID_Touch][1]); +} + +OGLContextInfo* OGLClientFetchObject::GetContextInfo() const +{ + return this->_contextInfo; +} + +uint32_t* OGLClientFetchObject::GetSrcClone(const NDSDisplayID displayID, const u8 bufferIndex) const +{ + return this->_srcNativeClone[displayID][bufferIndex]; +} + +GLuint OGLClientFetchObject::GetTexNative(const NDSDisplayID displayID, const u8 bufferIndex) const +{ + return this->_texDisplayFetchNative[displayID][bufferIndex]; +} + +GLuint OGLClientFetchObject::GetTexCustom(const NDSDisplayID displayID, const u8 bufferIndex) const +{ + return this->_texDisplayFetchCustom[displayID][bufferIndex]; +} + +GLuint OGLClientFetchObject::GetTexLQ2xLUT() const +{ + return this->_texLQ2xLUT; +} + +GLuint OGLClientFetchObject::GetTexHQ2xLUT() const +{ + return this->_texHQ2xLUT; +} + +GLuint OGLClientFetchObject::GetTexHQ3xLUT() const +{ + return this->_texHQ3xLUT; +} + +GLuint OGLClientFetchObject::GetTexHQ4xLUT() const +{ + return this->_texHQ4xLUT; +} + +void OGLClientFetchObject::CopyFromSrcClone(uint32_t *dstBufferPtr, const NDSDisplayID displayID, const u8 bufferIndex) +{ + pthread_rwlock_rdlock(&this->_srcCloneRWLock[displayID][bufferIndex]); + memcpy(dstBufferPtr, this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * sizeof(uint32_t)); + pthread_rwlock_unlock(&this->_srcCloneRWLock[displayID][bufferIndex]); +} + +void OGLClientFetchObject::Init() +{ + glGenTextures(4, &_texDisplayFetchNative[0][0]); + glGenTextures(4, &_texDisplayFetchCustom[0][0]); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texDisplayFetchNative[NDSDisplayID_Main][0]); + 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); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, _srcNativeClone[NDSDisplayID_Main][0]); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texDisplayFetchNative[NDSDisplayID_Main][1]); + 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); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, _srcNativeClone[NDSDisplayID_Main][1]); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texDisplayFetchNative[NDSDisplayID_Touch][0]); + 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); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, _srcNativeClone[NDSDisplayID_Touch][0]); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texDisplayFetchNative[NDSDisplayID_Touch][1]); + 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); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, _srcNativeClone[NDSDisplayID_Touch][1]); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texDisplayFetchCustom[NDSDisplayID_Main][0]); + 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); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, _srcNativeClone[NDSDisplayID_Main][0]); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texDisplayFetchCustom[NDSDisplayID_Main][1]); + 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); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, _srcNativeClone[NDSDisplayID_Main][1]); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texDisplayFetchCustom[NDSDisplayID_Touch][0]); + 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); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, _srcNativeClone[NDSDisplayID_Touch][0]); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texDisplayFetchCustom[NDSDisplayID_Touch][1]); + 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); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, _srcNativeClone[NDSDisplayID_Touch][1]); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + + if (this->_contextInfo->IsShaderSupported()) + { + SetupHQnxLUTs(GL_TEXTURE0 + 1, this->_texLQ2xLUT, this->_texHQ2xLUT, this->_texHQ3xLUT, this->_texHQ4xLUT); + } +} + +void OGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo ¤tDisplayInfo) +{ + this->_fetchColorFormatOGL = (currentDisplayInfo.pixelBytes == 2) ? GL_UNSIGNED_SHORT_1_5_5_5_REV : GL_UNSIGNED_INT_8_8_8_8_REV; + + const size_t nativeSize = GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * currentDisplayInfo.pixelBytes; + const size_t customSize = currentDisplayInfo.customWidth * currentDisplayInfo.customHeight * currentDisplayInfo.pixelBytes; + + glFinish(); + + glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, currentDisplayInfo.framebufferSize * 2, currentDisplayInfo.masterFramebufferHead); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[NDSDisplayID_Main][0]); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, (u8 *)currentDisplayInfo.masterFramebufferHead); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[NDSDisplayID_Main][1]); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, (u8 *)currentDisplayInfo.masterFramebufferHead + currentDisplayInfo.framebufferSize); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[NDSDisplayID_Touch][0]); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 1)); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[NDSDisplayID_Touch][1]); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_fetchColorFormatOGL, (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 1) + currentDisplayInfo.framebufferSize); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[NDSDisplayID_Main][0]); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, currentDisplayInfo.customWidth, currentDisplayInfo.customHeight, 0, GL_RGBA, this->_fetchColorFormatOGL, (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 2)); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[NDSDisplayID_Main][1]); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, currentDisplayInfo.customWidth, currentDisplayInfo.customHeight, 0, GL_RGBA, this->_fetchColorFormatOGL, (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 2) + currentDisplayInfo.framebufferSize); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[NDSDisplayID_Touch][0]); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, currentDisplayInfo.customWidth, currentDisplayInfo.customHeight, 0, GL_RGBA, this->_fetchColorFormatOGL, (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 2) + customSize); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[NDSDisplayID_Touch][1]); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, currentDisplayInfo.customWidth, currentDisplayInfo.customHeight, 0, GL_RGBA, this->_fetchColorFormatOGL, (u8 *)currentDisplayInfo.masterFramebufferHead + (nativeSize * 2) + customSize + currentDisplayInfo.framebufferSize); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + + glFinish(); +} + +void OGLClientFetchObject::_FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex) +{ + if (this->_useCPUFilterPipeline) + { + pthread_rwlock_wrlock(&this->_srcCloneRWLock[displayID][bufferIndex]); + + if (this->_fetchColorFormatOGL == GL_UNSIGNED_SHORT_1_5_5_5_REV) + { + ColorspaceConvertBuffer555To8888Opaque((const uint16_t *)this->_fetchDisplayInfo[bufferIndex].nativeBuffer[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); + } + else + { + ColorspaceConvertBuffer888XTo8888Opaque((const uint32_t *)this->_fetchDisplayInfo[bufferIndex].nativeBuffer[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); + } + + pthread_rwlock_unlock(&this->_srcCloneRWLock[displayID][bufferIndex]); + } + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchNative[displayID][bufferIndex]); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, this->_fetchColorFormatOGL, this->_fetchDisplayInfo[bufferIndex].nativeBuffer[displayID]); +} + +void OGLClientFetchObject::_FetchCustomDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex) +{ + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDisplayFetchCustom[displayID][bufferIndex]); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, this->_fetchDisplayInfo[bufferIndex].customWidth, this->_fetchDisplayInfo[bufferIndex].customHeight, GL_RGBA, this->_fetchColorFormatOGL, this->_fetchDisplayInfo[bufferIndex].customBuffer[displayID]); +} + +#pragma mark - + OGLVideoOutput::OGLVideoOutput() { _contextInfo = NULL; @@ -4880,26 +5179,11 @@ void OGLVideoOutput::_UpdateViewport() } } -void OGLVideoOutput::_FetchNativeDisplayByID(const NDSDisplayID displayID) -{ - this->GetDisplayLayer()->CopyNativeDisplayByID_OGL(displayID); -} - -void OGLVideoOutput::_FetchCustomDisplayByID(const NDSDisplayID displayID) -{ - this->GetDisplayLayer()->CopyCustomDisplayByID_OGL(displayID); -} - void OGLVideoOutput::_LoadNativeDisplayByID(const NDSDisplayID displayID) { this->GetDisplayLayer()->LoadNativeDisplayByID_OGL(displayID); } -void OGLVideoOutput::_LoadCustomDisplayByID(const NDSDisplayID displayID) -{ - this->GetDisplayLayer()->LoadCustomDisplayByID_OGL(displayID); -} - OGLContextInfo* OGLVideoOutput::GetContextInfo() { return this->_contextInfo; @@ -4974,21 +5258,6 @@ void OGLVideoOutput::SetFiltersPreferGPU(const bool preferGPU) { this->_filtersPreferGPU = preferGPU; this->_willFilterOnGPU = (preferGPU) ? this->GetDisplayLayer()->SetGPUPixelScalerOGL(this->_pixelScaler) : false; - - this->GetDisplayLayer()->SetFiltersPreferGPUOGL(); -} - -void OGLVideoOutput::SetVideoBuffers(const uint32_t colorFormat, - const void *videoBufferHead, - const void *nativeBuffer0, - const void *nativeBuffer1, - const void *customBuffer0, const size_t customWidth0, const size_t customHeight0, - const void *customBuffer1, const size_t customWidth1, const size_t customHeight1) -{ - this->GetDisplayLayer()->SetVideoBuffers(colorFormat, videoBufferHead, - nativeBuffer0, nativeBuffer1, - customBuffer0, customWidth0, customHeight0, - customBuffer1, customWidth1, customHeight1); } GLsizei OGLVideoOutput::GetViewportWidth() @@ -5020,7 +5289,7 @@ void OGLVideoOutput::ProcessDisplays() } } -void OGLVideoOutput::FrameFinish() +void OGLVideoOutput::FinishFrameAtIndex(const u8 bufferIndex) { for (size_t i = 0; i < _layerList->size(); i++) { @@ -5028,7 +5297,7 @@ void OGLVideoOutput::FrameFinish() if (theLayer->IsVisible()) { - theLayer->FinishOGL(); + theLayer->FinishOGL(bufferIndex); } } } @@ -5054,6 +5323,16 @@ void OGLVideoOutput::RenderViewOGL() } } +void OGLVideoOutput::LockDisplayTextures() +{ + // Do nothing. This is implementation dependent. +} + +void OGLVideoOutput::UnlockDisplayTextures() +{ + // Do nothing. This is implementation dependent. +} + #pragma mark - OGLFilter::OGLFilter() @@ -5447,7 +5726,7 @@ OGLImage::OGLImage(OGLContextInfo *contextInfo, GLsizei imageWidth, GLsizei imag shaderFilterProgram->SetShaderSupport(_shaderSupport); shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, _useShader150); - UploadHQnxLUTs(); + SetupHQnxLUTs(GL_TEXTURE0 + 1, _texLQ2xLUT, _texHQ2xLUT, _texHQ3xLUT, _texHQ4xLUT); } else { @@ -5473,14 +5752,6 @@ OGLImage::~OGLImage() glDeleteTextures(1, &this->_texCPUFilterDstID); glDeleteTextures(1, &this->_texVideoInputDataID); - glActiveTexture(GL_TEXTURE0 + 1); - glBindTexture(GL_TEXTURE_3D, 0); - glDeleteTextures(1, &this->_texLQ2xLUT); - glDeleteTextures(1, &this->_texHQ2xLUT); - glDeleteTextures(1, &this->_texHQ3xLUT); - glDeleteTextures(1, &this->_texHQ4xLUT); - glActiveTexture(GL_TEXTURE0); - if (_canUseShaderOutput) { glUseProgram(0); @@ -5491,54 +5762,13 @@ OGLImage::~OGLImage() { delete this->_filterDeposterize; delete this->_shaderFilter; + DeleteHQnxLUTs(GL_TEXTURE0 + 1, this->_texLQ2xLUT, this->_texHQ2xLUT, this->_texHQ3xLUT, this->_texHQ4xLUT); } delete this->_vf; free(_vfMasterDstBuffer); } -void OGLImage::UploadHQnxLUTs() -{ - InitHQnxLUTs(); - - glGenTextures(1, &_texLQ2xLUT); - glGenTextures(1, &_texHQ2xLUT); - glGenTextures(1, &_texHQ3xLUT); - glGenTextures(1, &_texHQ4xLUT); - glActiveTexture(GL_TEXTURE0 + 1); - - glBindTexture(GL_TEXTURE_3D, _texLQ2xLUT); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 256*2, 4, 16, 0, GL_BGR, GL_UNSIGNED_BYTE, _LQ2xLUT); - - glBindTexture(GL_TEXTURE_3D, _texHQ2xLUT); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 256*2, 4, 16, 0, GL_BGR, GL_UNSIGNED_BYTE, _HQ2xLUT); - - glBindTexture(GL_TEXTURE_3D, _texHQ3xLUT); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 256*2, 9, 16, 0, GL_BGR, GL_UNSIGNED_BYTE, _HQ3xLUT); - - glBindTexture(GL_TEXTURE_3D, _texHQ4xLUT); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 256*2, 16, 16, 0, GL_BGR, GL_UNSIGNED_BYTE, _HQ4xLUT); - - glBindTexture(GL_TEXTURE_3D, 0); - glActiveTexture(GL_TEXTURE0); -} - bool OGLImage::GetFiltersPreferGPU() { return this->_filtersPreferGPU; @@ -6407,7 +6637,6 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO) { _isVisible = true; _output = oglVO; - _useClientStorage = GL_FALSE; _needUpdateViewport = true; _needUpdateRotationScale = true; _needUpdateVertices = true; @@ -6423,25 +6652,19 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO) _displayTexFilter[0] = GL_NEAREST; _displayTexFilter[1] = GL_NEAREST; - _videoColorFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV; - _videoSrcBufferHead = NULL; - _videoSrcNativeBuffer[0] = NULL; - _videoSrcNativeBuffer[1] = NULL; - _videoSrcCustomBuffer[0] = NULL; - _videoSrcCustomBuffer[1] = NULL; - // Set up textures glGenTextures(2, _texCPUFilterDstID); - glGenTextures(2, _texVideoInputDataNativeID); - glGenTextures(2, _texVideoInputDataCustomID); - _texVideoOutputID[0] = _texVideoInputDataNativeID[0]; - _texVideoOutputID[1] = _texVideoInputDataNativeID[1]; + _texVideoOutputID[0] = 0; + _texVideoOutputID[1] = 0; + + glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, _vfMasterDstBufferSize, _vfMasterDstBuffer); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texCPUFilterDstID[0]); 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); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, _vf[0]->GetDstWidth(), _vf[0]->GetDstHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, _vf[0]->GetDstBufferPtr()); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texCPUFilterDstID[1]); @@ -6449,36 +6672,9 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, _vf[1]->GetDstWidth(), _vf[1]->GetDstHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, _vf[1]->GetDstBufferPtr()); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texVideoInputDataNativeID[0]); - 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); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, _vf[0]->GetSrcBufferPtr()); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texVideoInputDataNativeID[1]); - 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); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, _vf[1]->GetSrcBufferPtr()); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texVideoInputDataCustomID[0]); - 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); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, _vf[0]->GetSrcBufferPtr()); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texVideoInputDataCustomID[1]); - 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); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, _vf[1]->GetSrcBufferPtr()); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); // Set up VBOs @@ -6549,8 +6745,6 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO) shaderFilterProgram->SetShaderSupport(_shaderSupport); shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, _useShader150); } - - _UploadHQnxLUTs(); } else { @@ -6559,6 +6753,8 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO) _shaderFilter[0] = NULL; _shaderFilter[1] = NULL; } + + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); } OGLDisplayLayer::~OGLDisplayLayer() @@ -6571,16 +6767,6 @@ OGLDisplayLayer::~OGLDisplayLayer() glDeleteBuffersARB(1, &this->_vboVertexID); glDeleteBuffersARB(1, &this->_vboTexCoordID); glDeleteTextures(2, this->_texCPUFilterDstID); - glDeleteTextures(2, this->_texVideoInputDataNativeID); - glDeleteTextures(2, this->_texVideoInputDataCustomID); - - glActiveTexture(GL_TEXTURE0 + 1); - glBindTexture(GL_TEXTURE_3D, 0); - glDeleteTextures(1, &this->_texLQ2xLUT); - glDeleteTextures(1, &this->_texHQ2xLUT); - glDeleteTextures(1, &this->_texHQ3xLUT); - glDeleteTextures(1, &this->_texHQ4xLUT); - glActiveTexture(GL_TEXTURE0); if (_output->GetContextInfo()->IsShaderSupported()) { @@ -6602,161 +6788,12 @@ OGLDisplayLayer::~OGLDisplayLayer() _vfMasterDstBufferSize = 0; } -void OGLDisplayLayer::_UploadHQnxLUTs() -{ - InitHQnxLUTs(); - - glGenTextures(1, &_texLQ2xLUT); - glGenTextures(1, &_texHQ2xLUT); - glGenTextures(1, &_texHQ3xLUT); - glGenTextures(1, &_texHQ4xLUT); - glActiveTexture(GL_TEXTURE0 + 1); - - glBindTexture(GL_TEXTURE_3D, _texLQ2xLUT); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 256*2, 4, 16, 0, GL_BGR, GL_UNSIGNED_BYTE, _LQ2xLUT); - - glBindTexture(GL_TEXTURE_3D, _texHQ2xLUT); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 256*2, 4, 16, 0, GL_BGR, GL_UNSIGNED_BYTE, _HQ2xLUT); - - glBindTexture(GL_TEXTURE_3D, _texHQ3xLUT); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 256*2, 9, 16, 0, GL_BGR, GL_UNSIGNED_BYTE, _HQ3xLUT); - - glBindTexture(GL_TEXTURE_3D, _texHQ4xLUT); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 256*2, 16, 16, 0, GL_BGR, GL_UNSIGNED_BYTE, _HQ4xLUT); - - glBindTexture(GL_TEXTURE_3D, 0); - glActiveTexture(GL_TEXTURE0); -} - -void OGLDisplayLayer::_DetermineTextureStorageHints(GLint &videoSrcTexStorageHint, GLint &cpuFilterTexStorageHint) -{ - const bool isUsingCPUPixelScaler = (this->_output->GetPixelScaler() != VideoFilterTypeID_None) && !this->_output->WillFilterOnGPU(); - videoSrcTexStorageHint = GL_STORAGE_PRIVATE_APPLE; - cpuFilterTexStorageHint = GL_STORAGE_PRIVATE_APPLE; - - glFinish(); - - if (this->_videoSrcBufferHead == NULL) - { - glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, 0, NULL); - this->_useClientStorage = GL_FALSE; - } - else - { - if (isUsingCPUPixelScaler && (this->_vfMasterDstBufferSize >= this->_videoSrcBufferSize)) - { - cpuFilterTexStorageHint = GL_STORAGE_SHARED_APPLE; - glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, this->_vfMasterDstBufferSize, this->_vfMasterDstBuffer); - } - else - { - videoSrcTexStorageHint = GL_STORAGE_SHARED_APPLE; - glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, this->_videoSrcBufferSize, this->_videoSrcBufferHead); - } - - this->_useClientStorage = GL_TRUE; - } - - glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, this->_useClientStorage); -} - -void OGLDisplayLayer::SetVideoBuffers(const uint32_t colorFormat, - const void *videoBufferHead, - const void *nativeBuffer0, - const void *nativeBuffer1, - const void *customBuffer0, const size_t customWidth0, const size_t customHeight0, - const void *customBuffer1, const size_t customWidth1, const size_t customHeight1) -{ - GLint videoSrcTexStorageHint = GL_STORAGE_PRIVATE_APPLE; - GLint cpuFilterTexStorageHint = GL_STORAGE_PRIVATE_APPLE; - - const u8 bitCount = (colorFormat & 0x0000003F); - const GLenum glColorFormat = (bitCount == 5) ? GL_UNSIGNED_SHORT_1_5_5_5_REV : GL_UNSIGNED_INT_8_8_8_8_REV; - const size_t pixelBytes = (glColorFormat == GL_UNSIGNED_SHORT_1_5_5_5_REV) ? sizeof(uint16_t) : sizeof(uint32_t); - - this->_videoColorFormat = glColorFormat; - this->_videoSrcBufferHead = videoBufferHead; - this->_videoSrcBufferSize = (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * pixelBytes) + (customWidth0 * customHeight0 * pixelBytes) + (customWidth1 * customHeight1 * pixelBytes); - this->_videoSrcNativeBuffer[0] = (void *)nativeBuffer0; - this->_videoSrcNativeBuffer[1] = (void *)nativeBuffer1; - this->_videoSrcCustomBuffer[0] = (void *)customBuffer0; - this->_videoSrcCustomBuffer[1] = (void *)customBuffer1; - - this->_DetermineTextureStorageHints(videoSrcTexStorageHint, cpuFilterTexStorageHint); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[0]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, cpuFilterTexStorageHint); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, _vf[0]->GetDstWidth(), _vf[0]->GetDstHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, _vf[0]->GetDstBufferPtr()); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[1]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, cpuFilterTexStorageHint); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, _vf[1]->GetDstWidth(), _vf[1]->GetDstHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, _vf[1]->GetDstBufferPtr()); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[0]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_videoColorFormat, this->_videoSrcNativeBuffer[0]); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[1]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, this->_videoColorFormat, this->_videoSrcNativeBuffer[1]); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataCustomID[0]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, customWidth0, customHeight0, 0, GL_RGBA, this->_videoColorFormat, this->_videoSrcCustomBuffer[0]); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataCustomID[1]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, customWidth1, customHeight1, 0, GL_RGBA, this->_videoColorFormat, this->_videoSrcCustomBuffer[1]); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - - glFinish(); -} - void OGLDisplayLayer::SetNeedsUpdateRotationScale() { this->_needUpdateRotationScale = true; this->_needUpdateVertices = true; } -void OGLDisplayLayer::SetFiltersPreferGPUOGL() -{ - GLint videoSrcTexStorageHint = GL_STORAGE_PRIVATE_APPLE; - GLint cpuFilterTexStorageHint = GL_STORAGE_PRIVATE_APPLE; - this->_DetermineTextureStorageHints(videoSrcTexStorageHint, cpuFilterTexStorageHint); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[0]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, cpuFilterTexStorageHint); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[1]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, cpuFilterTexStorageHint); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[0]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[1]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataCustomID[0]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataCustomID[1]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); -} - void OGLDisplayLayer::_UpdateRotationScaleOGL() { const ClientDisplayViewProperties &cdv = this->_output->GetViewProperties(); @@ -6784,18 +6821,16 @@ void OGLDisplayLayer::_UpdateVerticesOGL() { glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboVertexID); float *vtxBufferPtr = (float *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); - this->_output->SetScreenVertices(vtxBufferPtr); - glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); this->_needUpdateVertices = false; } void OGLDisplayLayer::_ResizeCPUPixelScalerOGL(const size_t srcWidthMain, const size_t srcHeightMain, const size_t srcWidthTouch, const size_t srcHeightTouch, const size_t scaleMultiply, const size_t scaleDivide) { - this->FinishOGL(); + this->FinishOGL(0); + this->FinishOGL(1); const GLsizei newDstBufferWidth = (srcWidthMain + srcWidthTouch) * scaleMultiply / scaleDivide; const GLsizei newDstBufferHeight = (srcHeightMain + srcHeightTouch) * scaleMultiply / scaleDivide; @@ -6808,31 +6843,24 @@ void OGLDisplayLayer::_ResizeCPUPixelScalerOGL(const size_t srcWidthMain, const const GLsizei newDstBufferSingleWidth = srcWidthMain * scaleMultiply / scaleDivide; const GLsizei newDstBufferSingleHeight = srcHeightMain * scaleMultiply / scaleDivide; - GLint videoSrcTexStorageHint = GL_STORAGE_PRIVATE_APPLE; - GLint cpuFilterTexStorageHint = GL_STORAGE_PRIVATE_APPLE; - this->_DetermineTextureStorageHints(videoSrcTexStorageHint, cpuFilterTexStorageHint); + glFinish(); + + this->_vfMasterDstBuffer = newMasterBuffer; + this->_vfMasterDstBufferSize = newDstBufferWidth * newDstBufferHeight * sizeof(uint32_t); + + glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, this->_vfMasterDstBufferSize, this->_vfMasterDstBuffer); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[0]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, cpuFilterTexStorageHint); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, newDstBufferSingleWidth, newDstBufferSingleHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, newMasterBuffer); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[1]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, cpuFilterTexStorageHint); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, srcWidthTouch * scaleMultiply / scaleDivide, srcHeightTouch * scaleMultiply / scaleDivide, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, newMasterBuffer + (newDstBufferSingleWidth * newDstBufferSingleHeight)); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[0]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[1]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataCustomID[0]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataCustomID[1]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - _vfMasterDstBuffer = newMasterBuffer; - _vfMasterDstBufferSize = newDstBufferWidth * newDstBufferHeight * sizeof(uint32_t); + glFinish(); + free(oldMasterBuffer); } @@ -6960,7 +6988,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) case VideoFilterTypeID_LQ2X: { glActiveTexture(GL_TEXTURE0 + 1); - glBindTexture(GL_TEXTURE_3D, this->_texLQ2xLUT); + glBindTexture(GL_TEXTURE_3D, ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexLQ2xLUT()); glActiveTexture(GL_TEXTURE0); shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerLQ2xFragShader_110, _useShader150); @@ -6978,7 +7006,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) case VideoFilterTypeID_LQ2XS: { glActiveTexture(GL_TEXTURE0 + 1); - glBindTexture(GL_TEXTURE_3D, this->_texLQ2xLUT); + glBindTexture(GL_TEXTURE_3D, ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexLQ2xLUT()); glActiveTexture(GL_TEXTURE0); shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerLQ2xSFragShader_110, _useShader150); @@ -6996,7 +7024,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) case VideoFilterTypeID_HQ2X: { glActiveTexture(GL_TEXTURE0 + 1); - glBindTexture(GL_TEXTURE_3D, this->_texHQ2xLUT); + glBindTexture(GL_TEXTURE_3D, ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ2xLUT()); glActiveTexture(GL_TEXTURE0); shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ2xFragShader_110, _useShader150); @@ -7014,7 +7042,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) case VideoFilterTypeID_HQ2XS: { glActiveTexture(GL_TEXTURE0 + 1); - glBindTexture(GL_TEXTURE_3D, this->_texHQ2xLUT); + glBindTexture(GL_TEXTURE_3D, ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ2xLUT()); glActiveTexture(GL_TEXTURE0); shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ2xSFragShader_110, _useShader150); @@ -7032,7 +7060,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) case VideoFilterTypeID_HQ3X: { glActiveTexture(GL_TEXTURE0 + 1); - glBindTexture(GL_TEXTURE_3D, this->_texHQ3xLUT); + glBindTexture(GL_TEXTURE_3D, ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ3xLUT()); glActiveTexture(GL_TEXTURE0); shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ3xFragShader_110, _useShader150); @@ -7050,7 +7078,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) case VideoFilterTypeID_HQ3XS: { glActiveTexture(GL_TEXTURE0 + 1); - glBindTexture(GL_TEXTURE_3D, this->_texHQ3xLUT); + glBindTexture(GL_TEXTURE_3D, ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ3xLUT()); glActiveTexture(GL_TEXTURE0); shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ3xSFragShader_110, _useShader150); @@ -7068,7 +7096,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) case VideoFilterTypeID_HQ4X: { glActiveTexture(GL_TEXTURE0 + 1); - glBindTexture(GL_TEXTURE_3D, this->_texHQ4xLUT); + glBindTexture(GL_TEXTURE_3D, ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ4xLUT()); glActiveTexture(GL_TEXTURE0); shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ4xFragShader_110, _useShader150); @@ -7086,7 +7114,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) case VideoFilterTypeID_HQ4XS: { glActiveTexture(GL_TEXTURE0 + 1); - glBindTexture(GL_TEXTURE_3D, this->_texHQ4xLUT); + glBindTexture(GL_TEXTURE_3D, ((const OGLClientFetchObject &)this->_output->GetFetchObject()).GetTexHQ4xLUT()); glActiveTexture(GL_TEXTURE0); shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample3x3_VertShader_110, ScalerHQ4xSFragShader_110, _useShader150); @@ -7183,7 +7211,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) { glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); this->_shaderFilter[i]->SetScaleOGL(vfScale); - glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, this->_useClientStorage); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); } } @@ -7207,59 +7235,15 @@ void OGLDisplayLayer::SetCPUPixelScalerOGL(const VideoFilterTypeID filterID) this->_vf[1]->ChangeFilterByID(filterID); } -void OGLDisplayLayer::CopyNativeDisplayByID_OGL(const NDSDisplayID displayID) -{ - const NDSDisplayInfo &emuDisplayInfo = this->_output->GetEmuDisplayInfo(); - const bool useDeposterize = this->_output->GetSourceDeposterize(); - const bool isUsingCPUPixelScaler = (this->_output->GetPixelScaler() != VideoFilterTypeID_None) && !this->_output->WillFilterOnGPU(); - - if (!isUsingCPUPixelScaler || useDeposterize) - { - memcpy(this->_videoSrcNativeBuffer[displayID], emuDisplayInfo.nativeBuffer[displayID], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * emuDisplayInfo.pixelBytes); - } - else - { - if (this->_videoColorFormat == GL_UNSIGNED_SHORT_1_5_5_5_REV) - { - ColorspaceConvertBuffer555To8888Opaque((const uint16_t *)emuDisplayInfo.nativeBuffer[displayID], this->_vf[displayID]->GetSrcBufferPtr(), GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); - } - else - { - ColorspaceConvertBuffer888XTo8888Opaque((const uint32_t *)emuDisplayInfo.nativeBuffer[displayID], this->_vf[displayID]->GetSrcBufferPtr(), GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); - } - } -} - -void OGLDisplayLayer::CopyCustomDisplayByID_OGL(const NDSDisplayID displayID) -{ - const NDSDisplayInfo &emuDisplayInfo = this->_output->GetEmuDisplayInfo(); - memcpy(this->_videoSrcCustomBuffer[displayID], emuDisplayInfo.customBuffer[displayID], emuDisplayInfo.customWidth * emuDisplayInfo.customHeight * emuDisplayInfo.pixelBytes); -} - void OGLDisplayLayer::LoadNativeDisplayByID_OGL(const NDSDisplayID displayID) { - const bool useDeposterize = this->_output->GetSourceDeposterize(); - const bool isUsingCPUPixelScaler = (this->_output->GetPixelScaler() != VideoFilterTypeID_None) && !this->_output->WillFilterOnGPU(); - - if (!isUsingCPUPixelScaler || useDeposterize) + if ((this->_output->GetPixelScaler() != VideoFilterTypeID_None) && !this->_output->WillFilterOnGPU()) { - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[displayID]); - glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, this->_videoColorFormat, this->_videoSrcNativeBuffer[displayID]); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - glFlush(); + OGLClientFetchObject &fetchObjMutable = (OGLClientFetchObject &)this->_output->GetFetchObject(); + fetchObjMutable.CopyFromSrcClone(this->_vf[displayID]->GetSrcBufferPtr(), displayID, this->_output->GetEmuDisplayInfo().bufferIndex); } } -void OGLDisplayLayer::LoadCustomDisplayByID_OGL(const NDSDisplayID displayID) -{ - const NDSDisplayInfo &emuDisplayInfo = this->_output->GetEmuDisplayInfo(); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataCustomID[displayID]); - glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, emuDisplayInfo.customWidth, emuDisplayInfo.customHeight, GL_RGBA, this->_videoColorFormat, this->_videoSrcCustomBuffer[displayID]); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - glFlush(); -} - void OGLDisplayLayer::_ProcessDisplayByID(const NDSDisplayID displayID, GLsizei &inoutWidth, GLsizei &inoutHeight, GLuint &inoutTexID) { const bool willFilterOnGPU = this->_output->WillFilterOnGPU(); @@ -7274,7 +7258,7 @@ void OGLDisplayLayer::_ProcessDisplayByID(const NDSDisplayID displayID, GLsizei // so using client-backed buffers for filtered images would simply waste memory here. glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); inoutTexID = this->_filterDeposterize[displayID]->RunFilterOGL(inoutTexID); - glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, this->_useClientStorage); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); if (isUsingCPUPixelScaler) // Hybrid CPU/GPU-based path (may cause a performance hit on pixel download) { @@ -7289,7 +7273,7 @@ void OGLDisplayLayer::_ProcessDisplayByID(const NDSDisplayID displayID, GLsizei { glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); inoutTexID = this->_shaderFilter[displayID]->RunFilterOGL(inoutTexID); - glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, this->_useClientStorage); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); inoutWidth = this->_shaderFilter[displayID]->GetDstWidth(); inoutHeight = this->_shaderFilter[displayID]->GetDstHeight(); @@ -7301,7 +7285,6 @@ void OGLDisplayLayer::_ProcessDisplayByID(const NDSDisplayID displayID, GLsizei inoutTexID = this->_texCPUFilterDstID[displayID]; glBindTexture(GL_TEXTURE_RECTANGLE_ARB, inoutTexID); glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, this->_vf[displayID]->GetDstWidth(), this->_vf[displayID]->GetDstHeight(), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, texData); - glFlush(); inoutWidth = (GLsizei)this->_vf[displayID]->GetDstWidth(); inoutHeight = (GLsizei)this->_vf[displayID]->GetDstHeight(); @@ -7310,25 +7293,43 @@ void OGLDisplayLayer::_ProcessDisplayByID(const NDSDisplayID displayID, GLsizei void OGLDisplayLayer::ProcessOGL() { + const OGLClientFetchObject &fetchObj = (const OGLClientFetchObject &)this->_output->GetFetchObject(); const NDSDisplayInfo &emuDisplayInfo = this->_output->GetEmuDisplayInfo(); const ClientDisplayMode mode = this->_output->GetViewProperties().mode; - GLuint texVideoSourceID[2] = { (!emuDisplayInfo.didPerformCustomRender[NDSDisplayID_Main]) ? this->_texVideoInputDataNativeID[0] : this->_texVideoInputDataCustomID[0], - (!emuDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch]) ? this->_texVideoInputDataNativeID[1] : this->_texVideoInputDataCustomID[1] }; + const bool didRenderNative[2] = { !emuDisplayInfo.didPerformCustomRender[NDSDisplayID_Main], !emuDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch] }; + GLuint texVideoSourceID[2] = { (didRenderNative[NDSDisplayID_Main]) ? fetchObj.GetTexNative(NDSDisplayID_Main, emuDisplayInfo.bufferIndex) : fetchObj.GetTexCustom(NDSDisplayID_Main, emuDisplayInfo.bufferIndex), + (didRenderNative[NDSDisplayID_Touch]) ? fetchObj.GetTexNative(NDSDisplayID_Touch, emuDisplayInfo.bufferIndex) : fetchObj.GetTexCustom(NDSDisplayID_Touch, emuDisplayInfo.bufferIndex) }; GLsizei width[2] = { emuDisplayInfo.renderedWidth[NDSDisplayID_Main], emuDisplayInfo.renderedWidth[NDSDisplayID_Touch] }; GLsizei height[2] = { emuDisplayInfo.renderedHeight[NDSDisplayID_Main], emuDisplayInfo.renderedHeight[NDSDisplayID_Touch] }; // Run the video source filters and the pixel scalers - if ( !emuDisplayInfo.didPerformCustomRender[NDSDisplayID_Main] && emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Main] && (mode == ClientDisplayMode_Main || mode == ClientDisplayMode_Dual) ) + const bool willFilterOnGPU = this->_output->WillFilterOnGPU(); + const bool useDeposterize = this->_output->GetSourceDeposterize(); + const bool needProcessDisplay[2] = { didRenderNative[NDSDisplayID_Main] && emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Main] && (mode == ClientDisplayMode_Main || mode == ClientDisplayMode_Dual), + didRenderNative[NDSDisplayID_Touch] && emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Touch] && (mode == ClientDisplayMode_Touch || mode == ClientDisplayMode_Dual) }; + const bool needsLock = (willFilterOnGPU || useDeposterize) && (needProcessDisplay[NDSDisplayID_Main] || needProcessDisplay[NDSDisplayID_Touch]); + + if (needsLock) { - this->_ProcessDisplayByID(NDSDisplayID_Main, width[NDSDisplayID_Main], height[NDSDisplayID_Main], texVideoSourceID[NDSDisplayID_Main]); + this->_output->LockDisplayTextures(); } - if ( !emuDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch] && emuDisplayInfo.isDisplayEnabled[NDSDisplayID_Touch] && (mode == ClientDisplayMode_Touch || mode == ClientDisplayMode_Dual) ) + if (needProcessDisplay[NDSDisplayID_Main]) + { + this->_ProcessDisplayByID(NDSDisplayID_Main, width[NDSDisplayID_Main], height[NDSDisplayID_Main], texVideoSourceID[NDSDisplayID_Main]); + } + + if (needProcessDisplay[NDSDisplayID_Touch]) { this->_ProcessDisplayByID(NDSDisplayID_Touch, width[NDSDisplayID_Touch], height[NDSDisplayID_Touch], texVideoSourceID[NDSDisplayID_Touch]); } + if (needsLock) + { + this->_output->UnlockDisplayTextures(); + } + // Set the final output texture IDs this->_texVideoOutputID[NDSDisplayID_Main] = texVideoSourceID[NDSDisplayID_Main]; this->_texVideoOutputID[NDSDisplayID_Touch] = texVideoSourceID[NDSDisplayID_Touch]; @@ -7343,9 +7344,6 @@ void OGLDisplayLayer::ProcessOGL() texCoordPtr); glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); // OpenGL shader-based filters can modify the viewport, so it needs to be reset here. glViewport(0, 0, this->_output->GetViewportWidth(), this->_output->GetViewportHeight()); @@ -7388,7 +7386,7 @@ void OGLDisplayLayer::RenderOGL() this->_UpdateVerticesOGL(); } - // Enable vertex attributes + this->_output->LockDisplayTextures(); glBindVertexArrayDESMUME(this->_vaoMainStatesID); switch (this->_output->GetViewProperties().mode) @@ -7402,7 +7400,6 @@ void OGLDisplayLayer::RenderOGL() glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter[NDSDisplayID_Main]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } - break; } @@ -7464,17 +7461,16 @@ void OGLDisplayLayer::RenderOGL() break; } - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - - // Disable vertex attributes glBindVertexArrayDESMUME(0); + this->_output->UnlockDisplayTextures(); } -void OGLDisplayLayer::FinishOGL() +void OGLDisplayLayer::FinishOGL(const u8 bufferIndex) { - const NDSDisplayInfo &emuDisplayInfo = this->_output->GetEmuDisplayInfo(); - const bool isUsingCPUPixelScaler = (this->_output->GetPixelScaler() != VideoFilterTypeID_None) && !this->_output->WillFilterOnGPU(); + const OGLClientFetchObject &fetchObj = (const OGLClientFetchObject &)this->_output->GetFetchObject(); - glFinishObjectAPPLE(GL_TEXTURE_RECTANGLE_ARB, (isUsingCPUPixelScaler) ? this->_texCPUFilterDstID[0] : ( (!emuDisplayInfo.didPerformCustomRender[NDSDisplayID_Main]) ? this->_texVideoInputDataNativeID[0] : this->_texVideoInputDataCustomID[0]) ); - glFinishObjectAPPLE(GL_TEXTURE_RECTANGLE_ARB, (isUsingCPUPixelScaler) ? this->_texCPUFilterDstID[1] : ( (!emuDisplayInfo.didPerformCustomRender[NDSDisplayID_Touch]) ? this->_texVideoInputDataNativeID[1] : this->_texVideoInputDataCustomID[1]) ); + glFinishObjectAPPLE(GL_TEXTURE_RECTANGLE_ARB, fetchObj.GetTexNative(NDSDisplayID_Main, bufferIndex)); + glFinishObjectAPPLE(GL_TEXTURE_RECTANGLE_ARB, fetchObj.GetTexNative(NDSDisplayID_Touch, bufferIndex)); + glFinishObjectAPPLE(GL_TEXTURE_RECTANGLE_ARB, fetchObj.GetTexCustom(NDSDisplayID_Main, bufferIndex)); + glFinishObjectAPPLE(GL_TEXTURE_RECTANGLE_ARB, fetchObj.GetTexCustom(NDSDisplayID_Touch, bufferIndex)); } diff --git a/desmume/src/frontend/cocoa/OGLDisplayOutput.h b/desmume/src/frontend/cocoa/OGLDisplayOutput.h index f5f714305..4fc96b1ab 100644 --- a/desmume/src/frontend/cocoa/OGLDisplayOutput.h +++ b/desmume/src/frontend/cocoa/OGLDisplayOutput.h @@ -30,6 +30,7 @@ #include #include +#include #include "../../filter/videofilter.h" #include "ClientDisplayView.h" @@ -217,8 +218,6 @@ protected: GLint _uniformFinalOutputScalar; GLint _uniformFinalOutputViewSize; - void UploadHQnxLUTs(); - void UploadVerticesOGL(); void UploadTexCoordsOGL(); void UploadTransformationOGL(); @@ -270,7 +269,7 @@ public: virtual void SetVisibility(const bool visibleState); virtual void RenderOGL() = 0; - virtual void FinishOGL() {}; + virtual void FinishOGL(const u8 bufferIndex) {}; }; class OGLHUDLayer : public OGLVideoLayer @@ -301,33 +300,19 @@ class OGLDisplayLayer : public OGLVideoLayer protected: bool _useShader150; ShaderSupportTier _shaderSupport; - GLboolean _useClientStorage; OGLShaderProgram *_finalOutputProgram; OGLFilter *_filterDeposterize[2]; OGLFilter *_shaderFilter[2]; GLint _displayTexFilter[2]; - GLuint _texVideoInputDataNativeID[2]; - GLuint _texVideoInputDataCustomID[2]; GLuint _texVideoOutputID[2]; - GLenum _videoColorFormat; - const void *_videoSrcBufferHead; - void *_videoSrcNativeBuffer[2]; - void *_videoSrcCustomBuffer[2]; - size_t _videoSrcBufferSize; - uint32_t *_vfMasterDstBuffer; size_t _vfMasterDstBufferSize; VideoFilter *_vf[2]; GLuint _texCPUFilterDstID[2]; - GLuint _texLQ2xLUT; - GLuint _texHQ2xLUT; - GLuint _texHQ3xLUT; - GLuint _texHQ4xLUT; - GLuint _vaoMainStatesID; GLuint _vboVertexID; GLuint _vboTexCoordID; @@ -336,9 +321,6 @@ protected: GLint _uniformFinalOutputScalar; GLint _uniformFinalOutputViewSize; - void _UploadHQnxLUTs(); - void _DetermineTextureStorageHints(GLint &videoSrcTexStorageHint, GLint &cpuFilterTexStorageHint); - void _ResizeCPUPixelScalerOGL(const size_t srcWidthMain, const size_t srcHeightMain, const size_t srcWidthTouch, const size_t srcHeightTouch, const size_t scaleMultiply, const size_t scaleDivide); void _UpdateRotationScaleOGL(); @@ -351,30 +333,60 @@ public: OGLDisplayLayer(OGLVideoOutput *oglVO); virtual ~OGLDisplayLayer(); - void SetVideoBuffers(const uint32_t colorFormat, - const void *videoBufferHead, - const void *nativeBuffer0, - const void *nativeBuffer1, - const void *customBuffer0, const size_t customWidth0, const size_t customHeight0, - const void *customBuffer1, const size_t customWidth1, const size_t customHeight1); - void SetNeedsUpdateRotationScale(); - void SetFiltersPreferGPUOGL(); - - bool CanUseShaderBasedFilters(); OutputFilterTypeID SetOutputFilterOGL(const OutputFilterTypeID filterID); bool SetGPUPixelScalerOGL(const VideoFilterTypeID filterID); void SetCPUPixelScalerOGL(const VideoFilterTypeID filterID); - void CopyNativeDisplayByID_OGL(const NDSDisplayID displayID); - void CopyCustomDisplayByID_OGL(const NDSDisplayID displayID); void LoadNativeDisplayByID_OGL(const NDSDisplayID displayID); - void LoadCustomDisplayByID_OGL(const NDSDisplayID displayID); void ProcessOGL(); virtual void RenderOGL(); - virtual void FinishOGL(); + virtual void FinishOGL(const u8 bufferIndex); +}; + +class OGLClientFetchObject : public GPUClientFetchObject +{ +protected: + OGLContextInfo *_contextInfo; + GLenum _fetchColorFormatOGL; + GLuint _texDisplayFetchNative[2][2]; + GLuint _texDisplayFetchCustom[2][2]; + + GLuint _texLQ2xLUT; + GLuint _texHQ2xLUT; + GLuint _texHQ3xLUT; + GLuint _texHQ4xLUT; + + bool _useCPUFilterPipeline; + uint32_t *_srcNativeCloneMaster; + uint32_t *_srcNativeClone[2][2]; + pthread_rwlock_t _srcCloneRWLock[2][2]; + + virtual void _FetchNativeDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex); + virtual void _FetchCustomDisplayByID(const NDSDisplayID displayID, const u8 bufferIndex); + +public: + OGLClientFetchObject(); + virtual ~OGLClientFetchObject(); + + OGLContextInfo* GetContextInfo() const; + uint32_t* GetSrcClone(const NDSDisplayID displayID, const u8 bufferIndex) const; + GLuint GetTexNative(const NDSDisplayID displayID, const u8 bufferIndex) const; + GLuint GetTexCustom(const NDSDisplayID displayID, const u8 bufferIndex) const; + + // For lack of a better place, we're putting the HQnx LUTs in the fetch object because + // we know that it will be shared for all display views. + GLuint GetTexLQ2xLUT() const; + GLuint GetTexHQ2xLUT() const; + GLuint GetTexHQ3xLUT() const; + GLuint GetTexHQ4xLUT() const; + + void CopyFromSrcClone(uint32_t *dstBufferPtr, const NDSDisplayID displayID, const u8 bufferIndex); + + virtual void Init(); + virtual void SetFetchBuffers(const NDSDisplayInfo ¤tDisplayInfo); }; class OGLVideoOutput : public ClientDisplay3DView @@ -394,10 +406,7 @@ protected: virtual void _UpdateClientSize(); virtual void _UpdateViewScale(); - virtual void _FetchNativeDisplayByID(const NDSDisplayID displayID); - virtual void _FetchCustomDisplayByID(const NDSDisplayID displayID); virtual void _LoadNativeDisplayByID(const NDSDisplayID displayID); - virtual void _LoadCustomDisplayByID(const NDSDisplayID displayID); public: OGLVideoOutput(); @@ -421,17 +430,12 @@ public: virtual void SetFiltersPreferGPU(const bool preferGPU); - virtual void SetVideoBuffers(const uint32_t colorFormat, - const void *videoBufferHead, - const void *nativeBuffer0, - const void *nativeBuffer1, - const void *customBuffer0, const size_t customWidth0, const size_t customHeight0, - const void *customBuffer1, const size_t customWidth1, const size_t customHeight1); - // Client view interface virtual void ProcessDisplays(); - virtual void FrameFinish(); + virtual void FinishFrameAtIndex(const u8 bufferIndex); virtual void RenderViewOGL(); + virtual void LockDisplayTextures(); + virtual void UnlockDisplayTextures(); }; extern void (*glBindVertexArrayDESMUME)(GLuint id); diff --git a/desmume/src/frontend/cocoa/cocoa_GPU.h b/desmume/src/frontend/cocoa/cocoa_GPU.h index 4e0b67e68..32d111207 100644 --- a/desmume/src/frontend/cocoa/cocoa_GPU.h +++ b/desmume/src/frontend/cocoa/cocoa_GPU.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2015 DeSmuME team + Copyright (C) 2013-2017 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 @@ -19,9 +19,39 @@ #include #include +#import "cocoa_util.h" +#include "../../GPU.h" + +#ifdef BOOL +#undef BOOL +#endif + +#if defined(MAC_OS_X_VERSION_10_11) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) +//#define ENABLE_APPLE_METAL +#endif class GPUEventHandlerOSX; +@interface MacClientSharedObject : CocoaDSThread +{ + GPUClientFetchObject *GPUFetchObject; + pthread_rwlock_t *_rwlockFramebuffer[2]; + pthread_mutex_t *_mutexOutputList; + NSMutableArray *_cdsOutputList; +} + +@property (assign, nonatomic) GPUClientFetchObject *GPUFetchObject; + +- (const NDSDisplayInfo &) fetchDisplayInfoForIndex:(const u8)bufferIndex; +- (pthread_rwlock_t *) rwlockFramebufferAtIndex:(const u8)bufferIndex; +- (void) setOutputList:(NSMutableArray *)theOutputList mutex:(pthread_mutex_t *)theMutex; +- (BOOL) isCPUFilteringNeeded; +- (void) handleFetchFromBufferIndexAndPushVideo:(NSData *)indexData; +- (void) pushVideoDataToAllDisplayViews; +- (void) finishAllDisplayViewsAtIndex:(const u8)bufferIndex; + +@end + @interface CocoaDSGPU : NSObject { UInt32 gpuStateFlags; @@ -32,6 +62,7 @@ class GPUEventHandlerOSX; OSSpinLock spinlockGpuState; GPUEventHandlerOSX *gpuEvent; + GPUClientFetchObject *fetchObject; } @property (assign) UInt32 gpuStateFlags; @@ -39,6 +70,8 @@ class GPUEventHandlerOSX; @property (assign) NSUInteger gpuScale; @property (assign) NSUInteger gpuColorFormat; @property (readonly) pthread_rwlock_t *gpuFrameRWLock; +@property (readonly, nonatomic) GPUClientFetchObject *fetchObject; +@property (readonly, nonatomic) MacClientSharedObject *sharedData; @property (assign) BOOL layerMainGPU; @property (assign) BOOL layerMainBG0; diff --git a/desmume/src/frontend/cocoa/cocoa_GPU.mm b/desmume/src/frontend/cocoa/cocoa_GPU.mm index 160976bbf..c50ac77b2 100644 --- a/desmume/src/frontend/cocoa/cocoa_GPU.mm +++ b/desmume/src/frontend/cocoa/cocoa_GPU.mm @@ -21,7 +21,6 @@ #include "utilities.h" #include "../../NDSSystem.h" -#include "../../GPU.h" #include "../../rasterize.h" #ifdef MAC_OS_X_VERSION_10_7 @@ -31,8 +30,12 @@ #endif #include +#include "userinterface/MacOGLDisplayView.h" +#include "userinterface/MacMetalDisplayView.h" +#ifdef BOOL #undef BOOL +#endif GPU3DInterface *core3DList[] = { &gpu3DNull, @@ -44,28 +47,26 @@ GPU3DInterface *core3DList[] = { class GPUEventHandlerOSX : public GPUEventHandlerDefault { private: + GPUClientFetchObject *_fetchObject; + pthread_rwlock_t _rwlockFrame; pthread_mutex_t _mutex3DRender; - pthread_mutex_t *_mutexOutputList; - NSMutableArray *_cdsOutputList; bool _render3DNeedsFinish; public: GPUEventHandlerOSX(); ~GPUEventHandlerOSX(); + GPUClientFetchObject* GetFetchObject() const; + void SetFetchObject(GPUClientFetchObject *fetchObject); + void FramebufferLockWrite(); void FramebufferLockRead(); void FramebufferUnlock(); void Render3DLock(); void Render3DUnlock(); - void FrameFinish(); - void SetVideoBuffers(); - pthread_rwlock_t* GetFrameRWLock(); - NSMutableArray* GetOutputList(); - void SetOutputList(NSMutableArray *outputList, pthread_mutex_t *theMutex); bool GetRender3DNeedsFinish(); virtual void DidFrameBegin(bool isFrameSkipRequested, const u8 targetBufferIndex, const size_t line); @@ -81,6 +82,8 @@ public: @dynamic gpuScale; @dynamic gpuColorFormat; @dynamic gpuFrameRWLock; +@synthesize fetchObject; +@dynamic sharedData; @dynamic layerMainGPU; @dynamic layerMainBG0; @@ -147,6 +150,20 @@ public: GPU->SetEventHandler(gpuEvent); GPU->SetWillAutoResolveToCustomBuffer(false); +#ifdef ENABLE_APPLE_METAL + if (IsOSXVersionSupported(10, 11, 0)) + { + fetchObject = new MacMetalFetchObject; + } + else +#endif + { + fetchObject = new MacOGLClientFetchObject; + } + + fetchObject->Init(); + gpuEvent->SetFetchObject(fetchObject); + return self; } @@ -154,11 +171,22 @@ public: { DestroyOpenGLRenderer(); + delete fetchObject; delete gpuEvent; [super dealloc]; } +- (GPUClientFetchObject *) fetchObject +{ + return fetchObject; +} + +- (MacClientSharedObject *) sharedData +{ + return (MacClientSharedObject *)fetchObject->GetClientData(); +} + - (void) setGpuStateFlags:(UInt32)flags { OSSpinLockLock(&spinlockGpuState); @@ -191,13 +219,15 @@ public: - (void) setGpuDimensions:(NSSize)theDimensions { - gpuEvent->FrameFinish(); + [[self sharedData] finishAllDisplayViewsAtIndex:0]; + [[self sharedData] finishAllDisplayViewsAtIndex:1]; + gpuEvent->Render3DLock(); gpuEvent->FramebufferLockWrite(); GPU->SetCustomFramebufferSize(theDimensions.width, theDimensions.height); + fetchObject->SetFetchBuffers(GPU->GetDisplayInfo()); - gpuEvent->SetVideoBuffers(); gpuEvent->FramebufferUnlock(); gpuEvent->Render3DUnlock(); } @@ -226,13 +256,15 @@ public: - (void) setGpuColorFormat:(NSUInteger)colorFormat { - gpuEvent->FrameFinish(); + [[self sharedData] finishAllDisplayViewsAtIndex:0]; + [[self sharedData] finishAllDisplayViewsAtIndex:1]; + gpuEvent->Render3DLock(); gpuEvent->FramebufferLockWrite(); GPU->SetColorFormat((NDSColorFormat)colorFormat); + fetchObject->SetFetchBuffers(GPU->GetDisplayInfo()); - gpuEvent->SetVideoBuffers(); gpuEvent->FramebufferUnlock(); gpuEvent->Render3DUnlock(); } @@ -255,7 +287,7 @@ public: - (void) setOutputList:(NSMutableArray *)theOutputList mutexPtr:(pthread_mutex_t *)theMutex { - gpuEvent->SetOutputList(theOutputList, theMutex); + [(MacClientSharedObject *)fetchObject->GetClientData() setOutputList:theOutputList mutex:theMutex]; } - (void) setRender3DRenderingEngine:(NSInteger)methodID @@ -814,10 +846,196 @@ public: @end +@implementation MacClientSharedObject + +@synthesize GPUFetchObject; + +- (id)init +{ + self = [super init]; + if (self == nil) + { + return self; + } + + _rwlockFramebuffer[0] = (pthread_rwlock_t *)malloc(sizeof(pthread_rwlock_t)); + _rwlockFramebuffer[1] = (pthread_rwlock_t *)malloc(sizeof(pthread_rwlock_t)); + + pthread_rwlock_init(_rwlockFramebuffer[0], NULL); + pthread_rwlock_init(_rwlockFramebuffer[1], NULL); + + GPUFetchObject = nil; + _mutexOutputList = NULL; + _cdsOutputList = nil; + + return self; +} + +- (void)dealloc +{ + pthread_mutex_t *currentMutex = _mutexOutputList; + + if (currentMutex != NULL) + { + pthread_mutex_lock(currentMutex); + } + + [_cdsOutputList release]; + + if (currentMutex != NULL) + { + pthread_mutex_unlock(currentMutex); + } + + pthread_rwlock_destroy(_rwlockFramebuffer[0]); + pthread_rwlock_destroy(_rwlockFramebuffer[1]); + + [super dealloc]; +} + +- (void)handlePortMessage:(NSPortMessage *)portMessage +{ + NSInteger message = (NSInteger)[portMessage msgid]; + NSArray *messageComponents = [portMessage components]; + + switch (message) + { + case MESSAGE_FETCH_AND_PUSH_VIDEO: + [self handleFetchFromBufferIndexAndPushVideo:[messageComponents objectAtIndex:0]]; + break; + + default: + [super handlePortMessage:portMessage]; + break; + } +} + +- (void) handleFetchFromBufferIndexAndPushVideo:(NSData *)indexData +{ + const NSInteger index = *(NSInteger *)[indexData bytes]; + + GPUFetchObject->FetchFromBufferIndex(index); + [self pushVideoDataToAllDisplayViews]; +} + +- (const NDSDisplayInfo &) fetchDisplayInfoForIndex:(const u8)bufferIndex +{ + return GPUFetchObject->GetFetchDisplayInfoForBufferIndex(bufferIndex); +} + +- (pthread_rwlock_t *) rwlockFramebufferAtIndex:(const u8)bufferIndex +{ + return _rwlockFramebuffer[bufferIndex]; +} + +- (void) setOutputList:(NSMutableArray *)theOutputList mutex:(pthread_mutex_t *)theMutex +{ + pthread_mutex_t *currentMutex = _mutexOutputList; + + if (currentMutex != NULL) + { + pthread_mutex_lock(currentMutex); + } + + [_cdsOutputList release]; + _cdsOutputList = theOutputList; + [_cdsOutputList retain]; + + if (currentMutex != NULL) + { + pthread_mutex_unlock(currentMutex); + } + + _mutexOutputList = theMutex; +} + +- (BOOL) isCPUFilteringNeeded +{ + bool useCPUFilterPipeline = NO; + pthread_mutex_t *currentMutex = _mutexOutputList; + + if (currentMutex != NULL) + { + pthread_mutex_lock(currentMutex); + } + + for (CocoaDSOutput *cdsOutput in _cdsOutputList) + { + if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]]) + { + ClientDisplay3DView *cdv = [(CocoaDSDisplay *)cdsOutput clientDisplayView]; + + if (!cdv->WillFilterOnGPU() && (cdv->GetPixelScaler() != VideoFilterTypeID_None)) + { + useCPUFilterPipeline = YES; + break; + } + } + } + + if (currentMutex != NULL) + { + pthread_mutex_unlock(currentMutex); + } + + return useCPUFilterPipeline; +} + +- (void) pushVideoDataToAllDisplayViews +{ + pthread_mutex_t *currentMutex = _mutexOutputList; + + if (currentMutex != NULL) + { + pthread_mutex_lock(currentMutex); + } + + for (CocoaDSOutput *cdsOutput in _cdsOutputList) + { + if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]]) + { + [CocoaDSUtil messageSendOneWay:[cdsOutput receivePort] msgID:MESSAGE_RECEIVE_GPU_FRAME]; + } + } + + if (currentMutex != NULL) + { + pthread_mutex_unlock(currentMutex); + } +} + +- (void) finishAllDisplayViewsAtIndex:(const u8)bufferIndex +{ + pthread_mutex_t *currentMutex = _mutexOutputList; + + if (currentMutex != NULL) + { + pthread_mutex_lock(currentMutex); + } + + for (CocoaDSOutput *cdsOutput in _cdsOutputList) + { + if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]]) + { + ClientDisplay3DView *cdv = [(CocoaDSDisplay *)cdsOutput clientDisplayView]; + cdv->FinishFrameAtIndex(bufferIndex); + } + } + + if (currentMutex != NULL) + { + pthread_mutex_unlock(currentMutex); + } +} + +@end + +#pragma mark - + GPUEventHandlerOSX::GPUEventHandlerOSX() { + _fetchObject = nil; _render3DNeedsFinish = false; - _mutexOutputList = NULL; pthread_rwlock_init(&_rwlockFrame, NULL); pthread_mutex_init(&_mutex3DRender, NULL); } @@ -833,37 +1051,46 @@ GPUEventHandlerOSX::~GPUEventHandlerOSX() pthread_mutex_destroy(&this->_mutex3DRender); } +GPUClientFetchObject* GPUEventHandlerOSX::GetFetchObject() const +{ + return this->_fetchObject; +} + +void GPUEventHandlerOSX::SetFetchObject(GPUClientFetchObject *fetchObject) +{ + this->_fetchObject = fetchObject; +} + void GPUEventHandlerOSX::DidFrameBegin(bool isFrameSkipRequested, const u8 targetBufferIndex, const size_t line) { this->FramebufferLockWrite(); + +#if !defined(PORT_VERSION_OPENEMU) + if (!isFrameSkipRequested) + { + MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_fetchObject->GetClientData(); + pthread_rwlock_wrlock([sharedViewObject rwlockFramebufferAtIndex:targetBufferIndex]); + } +#endif } void GPUEventHandlerOSX::DidFrameEnd(bool isFrameSkipped, const NDSDisplayInfo &latestDisplayInfo) { +#if !defined(PORT_VERSION_OPENEMU) + MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_fetchObject->GetClientData(); + if (!isFrameSkipped) + { + this->_fetchObject->SetFetchDisplayInfo(latestDisplayInfo); + pthread_rwlock_unlock([sharedViewObject rwlockFramebufferAtIndex:latestDisplayInfo.bufferIndex]); + } +#endif + this->FramebufferUnlock(); #if !defined(PORT_VERSION_OPENEMU) if (!isFrameSkipped) { - if (this->_mutexOutputList != NULL) - { - pthread_mutex_lock(this->_mutexOutputList); - } - - NSMutableArray *outputList = this->_cdsOutputList; - - for (CocoaDSOutput *cdsOutput in outputList) - { - if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]]) - { - [(CocoaDSDisplay *)cdsOutput doReceiveGPUFrame]; - } - } - - if (this->_mutexOutputList != NULL) - { - pthread_mutex_unlock(this->_mutexOutputList); - } + [CocoaDSUtil messageSendOneWayWithInteger:[sharedViewObject receivePort] msgID:MESSAGE_FETCH_AND_PUSH_VIDEO integerValue:latestDisplayInfo.bufferIndex]; } #endif } @@ -905,56 +1132,6 @@ void GPUEventHandlerOSX::Render3DUnlock() pthread_mutex_unlock(&this->_mutex3DRender); } -void GPUEventHandlerOSX::FrameFinish() -{ -#if !defined(PORT_VERSION_OPENEMU) - if (this->_mutexOutputList != NULL) - { - pthread_mutex_lock(this->_mutexOutputList); - } - - NSMutableArray *outputList = this->_cdsOutputList; - - for (CocoaDSOutput *cdsOutput in outputList) - { - if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]]) - { - [(CocoaDSDisplay *)cdsOutput finishFrame]; - } - } - - if (this->_mutexOutputList != NULL) - { - pthread_mutex_unlock(this->_mutexOutputList); - } -#endif -} - -void GPUEventHandlerOSX::SetVideoBuffers() -{ -#if !defined(PORT_VERSION_OPENEMU) - if (this->_mutexOutputList != NULL) - { - pthread_mutex_lock(this->_mutexOutputList); - } - - NSMutableArray *outputList = this->_cdsOutputList; - - for (CocoaDSOutput *cdsOutput in outputList) - { - if ([cdsOutput isKindOfClass:[CocoaDSDisplayVideo class]]) - { - [(CocoaDSDisplayVideo *)cdsOutput resetVideoBuffers]; - } - } - - if (this->_mutexOutputList != NULL) - { - pthread_mutex_unlock(this->_mutexOutputList); - } -#endif -} - bool GPUEventHandlerOSX::GetRender3DNeedsFinish() { return this->_render3DNeedsFinish; @@ -965,16 +1142,7 @@ pthread_rwlock_t* GPUEventHandlerOSX::GetFrameRWLock() return &this->_rwlockFrame; } -NSMutableArray* GPUEventHandlerOSX::GetOutputList() -{ - return this->_cdsOutputList; -} - -void GPUEventHandlerOSX::SetOutputList(NSMutableArray *outputList, pthread_mutex_t *theMutex) -{ - this->_cdsOutputList = outputList; - this->_mutexOutputList = theMutex; -} +#pragma mark - CGLContextObj OSXOpenGLRendererContext = NULL; diff --git a/desmume/src/frontend/cocoa/cocoa_globals.h b/desmume/src/frontend/cocoa/cocoa_globals.h index 614f841be..6cc78f70b 100644 --- a/desmume/src/frontend/cocoa/cocoa_globals.h +++ b/desmume/src/frontend/cocoa/cocoa_globals.h @@ -404,6 +404,7 @@ enum MESSAGE_SET_EMULATION_FLAGS, // Video Messages + MESSAGE_FETCH_AND_PUSH_VIDEO, MESSAGE_RECEIVE_GPU_FRAME, MESSAGE_CHANGE_VIEW_PROPERTIES, MESSAGE_REDRAW_VIEW, diff --git a/desmume/src/frontend/cocoa/cocoa_output.h b/desmume/src/frontend/cocoa/cocoa_output.h index 214c3dcc4..36f13ca98 100644 --- a/desmume/src/frontend/cocoa/cocoa_output.h +++ b/desmume/src/frontend/cocoa/cocoa_output.h @@ -1,6 +1,6 @@ /* Copyright (C) 2011 Roger Manuel - Copyright (C) 2011-2016 DeSmuME team + Copyright (C) 2011-2017 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 @@ -118,13 +118,11 @@ struct NDSFrameInfo; - (void) commitViewProperties:(const ClientDisplayViewProperties &)viewProps; -- (void) doReceiveGPUFrame; - (void) handleReceiveGPUFrame; - (void) handleChangeViewProperties; - (void) handleRequestScreenshot:(NSData *)fileURLStringData fileTypeData:(NSData *)fileTypeData; - (void) handleCopyToPasteboard; -- (void) finishFrame; - (void) takeFrameCount; - (void) setCPULoadAvgARM9:(uint32_t)loadAvgARM9 ARM7:(uint32_t)loadAvgARM7; - (NSImage *) image; @@ -133,11 +131,7 @@ struct NDSFrameInfo; @end @interface CocoaDSDisplayVideo : CocoaDSDisplay -{ - void *_videoBuffer; - void *_nativeBuffer[2]; - void *_customBuffer[2]; - +{ OSSpinLock spinlockIsHUDVisible; OSSpinLock spinlockUseVerticalSync; OSSpinLock spinlockVideoFiltersPreferGPU; @@ -165,7 +159,6 @@ struct NDSFrameInfo; - (void) handleReprocessRedraw; - (void) handleRedraw; -- (void) resetVideoBuffers; - (void) setScaleFactor:(float)theScaleFactor; @end diff --git a/desmume/src/frontend/cocoa/cocoa_output.mm b/desmume/src/frontend/cocoa/cocoa_output.mm index 5e11acabf..08d55401c 100644 --- a/desmume/src/frontend/cocoa/cocoa_output.mm +++ b/desmume/src/frontend/cocoa/cocoa_output.mm @@ -1,6 +1,6 @@ /* Copyright (C) 2011 Roger Manuel - Copyright (C) 2011-2016 DeSmuME team + Copyright (C) 2011-2017 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 @@ -561,11 +561,6 @@ return size; } -- (void) doReceiveGPUFrame -{ - [CocoaDSUtil messageSendOneWay:self.receivePort msgID:MESSAGE_RECEIVE_GPU_FRAME]; -} - - (void)handlePortMessage:(NSPortMessage *)portMessage { NSInteger message = (NSInteger)[portMessage msgid]; @@ -642,11 +637,6 @@ [pboard setData:[screenshot TIFFRepresentationUsingCompression:NSTIFFCompressionLZW factor:1.0f] forType:NSTIFFPboardType]; } -- (void) finishFrame -{ - _cdv->FrameFinish(); -} - - (void) takeFrameCount { OSSpinLockLock(&spinlockReceivedFrameIndex); @@ -764,12 +754,6 @@ return self; } - _videoBuffer = NULL; - _nativeBuffer[NDSDisplayID_Main] = NULL; - _nativeBuffer[NDSDisplayID_Touch] = NULL; - _customBuffer[NDSDisplayID_Main] = NULL; - _customBuffer[NDSDisplayID_Touch] = NULL; - spinlockIsHUDVisible = OS_SPINLOCK_INIT; spinlockUseVerticalSync = OS_SPINLOCK_INIT; spinlockVideoFiltersPreferGPU = OS_SPINLOCK_INIT; @@ -782,12 +766,6 @@ - (void)dealloc { - free_aligned(_videoBuffer); - _nativeBuffer[NDSDisplayID_Main] = NULL; - _nativeBuffer[NDSDisplayID_Touch] = NULL; - _customBuffer[NDSDisplayID_Main] = NULL; - _customBuffer[NDSDisplayID_Touch] = NULL; - [super dealloc]; } @@ -1038,15 +1016,6 @@ - (void) handleReceiveGPUFrame { [super handleReceiveGPUFrame]; - [self finishFrame]; - - pthread_rwlock_rdlock(self.rwlockProducer); - - const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); - _cdv->SetEmuDisplayInfo(dispInfo); - _cdv->FetchDisplays(); - - pthread_rwlock_unlock(self.rwlockProducer); _cdv->LoadDisplays(); _cdv->ProcessDisplays(); @@ -1054,13 +1023,20 @@ - (void) handleReloadReprocessRedraw { - [self handleReceiveGPUFrame]; + GPUClientFetchObject &fetchObjMutable = (GPUClientFetchObject &)_cdv->GetFetchObject(); + const u8 bufferIndex = fetchObjMutable.GetLastFetchIndex(); + + fetchObjMutable.FetchFromBufferIndex(bufferIndex); + _cdv->LoadDisplays(); + _cdv->ProcessDisplays(); + [self handleEmuFrameProcessed]; } - (void) handleReprocessRedraw -{ - [self handleEmuFrameProcessed]; +{ + _cdv->ProcessDisplays(); + _cdv->UpdateView(); } - (void) handleRedraw @@ -1068,33 +1044,6 @@ _cdv->UpdateView(); } -- (void) resetVideoBuffers -{ - const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); - - void *oldVideoBuffer = _videoBuffer; - uint8_t *newVideoBuffer = (uint8_t *)malloc_alignedCacheLine( ((GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT) + (dispInfo.customWidth * dispInfo.customHeight)) * 2 * dispInfo.pixelBytes ); - - _cdv->SetVideoBuffers(dispInfo.colorFormat, - newVideoBuffer, - newVideoBuffer, - newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * dispInfo.pixelBytes), - newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * dispInfo.pixelBytes), - dispInfo.customWidth, - dispInfo.customHeight, - newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * dispInfo.pixelBytes) + (dispInfo.customWidth * dispInfo.customHeight * dispInfo.pixelBytes), - dispInfo.customWidth, - dispInfo.customHeight); - - _videoBuffer = newVideoBuffer; - _nativeBuffer[NDSDisplayID_Main] = newVideoBuffer; - _nativeBuffer[NDSDisplayID_Touch] = newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * dispInfo.pixelBytes); - _customBuffer[NDSDisplayID_Main] = newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * dispInfo.pixelBytes); - _customBuffer[NDSDisplayID_Touch] = newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * dispInfo.pixelBytes) + (dispInfo.customWidth * dispInfo.customHeight * dispInfo.pixelBytes); - - free_aligned(oldVideoBuffer); -} - - (void) setScaleFactor:(float)theScaleFactor { OSSpinLockLock(&spinlockIsHUDVisible); diff --git a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.h b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.h index 055c78b1e..b90f10583 100644 --- a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.h +++ b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.h @@ -47,6 +47,7 @@ class OGLVideoOutput; @property (retain) CocoaDSDisplayVideo *cdsVideoOutput; @property (readonly, nonatomic) ClientDisplay3DView *clientDisplay3DView; @property (readonly) BOOL canUseShaderBasedFilters; +@property (assign, nonatomic) BOOL allowViewUpdates; @property (assign) BOOL isHUDVisible; @property (assign) BOOL isHUDVideoFPSVisible; @property (assign) BOOL isHUDRender3DFPSVisible; @@ -60,7 +61,7 @@ class OGLVideoOutput; @property (assign) NSInteger outputFilter; @property (assign) NSInteger pixelScaler; -- (void) reassignLocalCALayer; +- (void) setupLayer; - (BOOL) handleKeyPress:(NSEvent *)theEvent keyPressed:(BOOL)keyPressed; - (BOOL) handleMouseButton:(NSEvent *)theEvent buttonPressed:(BOOL)buttonPressed; diff --git a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm index 56f14da41..99f4c88cc 100644 --- a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm +++ b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm @@ -20,6 +20,7 @@ #import "InputManager.h" #import "cocoa_core.h" +#import "cocoa_GPU.h" #import "cocoa_file.h" #import "cocoa_input.h" #import "cocoa_globals.h" @@ -28,9 +29,7 @@ #include "MacOGLDisplayView.h" -//#define ENABLE_APPLE_METAL - -#if defined(MAC_OS_X_VERSION_10_11) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) && defined(ENABLE_APPLE_METAL) +#ifdef ENABLE_APPLE_METAL #include "MacMetalDisplayView.h" #endif @@ -356,7 +355,7 @@ static std::unordered_map _screenMap; // - (void) setVideoOutputFilter:(NSInteger)filterID { [[self view] setOutputFilter:filterID]; - [CocoaDSUtil messageSendOneWay:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_REPROCESS_AND_REDRAW]; + [CocoaDSUtil messageSendOneWay:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_REDRAW_VIEW]; } - (NSInteger) videoOutputFilter @@ -668,6 +667,7 @@ static std::unordered_map _screenMap; // // Show the full screen window. [self setWindow:newFullScreenWindow]; [newFullScreenWindow makeKeyAndOrderFront:self]; + [newFullScreenWindow makeMainWindow]; [newFullScreenWindow display]; [self setAssignedScreen:targetScreen]; @@ -697,6 +697,7 @@ static std::unordered_map _screenMap; // [[masterWindow contentView] addSubview:view]; [masterWindow setInitialFirstResponder:view]; [masterWindow makeKeyAndOrderFront:self]; + [masterWindow makeMainWindow]; [masterWindow display]; } @@ -1272,7 +1273,7 @@ static std::unordered_map _screenMap; // [[emuControl windowList] addObject:self]; [emuControl updateAllWindowTitles]; - [view reassignLocalCALayer]; + [view setupLayer]; [view setInputManager:[emuControl inputManager]]; // Set up the scaling factor if this is a Retina window @@ -1305,7 +1306,6 @@ static std::unordered_map _screenMap; // cdv->LoadHUDFont(); } - [newDisplayOutput resetVideoBuffers]; [self setCdsVideoOutput:newDisplayOutput]; [view setCdsVideoOutput:newDisplayOutput]; @@ -1600,6 +1600,7 @@ static std::unordered_map _screenMap; // @synthesize cdsVideoOutput; @dynamic clientDisplay3DView; @dynamic canUseShaderBasedFilters; +@dynamic allowViewUpdates; @dynamic isHUDVisible; @dynamic isHUDVideoFPSVisible; @dynamic isHUDRender3DFPSVisible; @@ -1625,45 +1626,6 @@ static std::unordered_map _screenMap; // cdsVideoOutput = nil; localLayer = nil; localOGLContext = nil; - -#if defined(MAC_OS_X_VERSION_10_11) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) && defined(ENABLE_APPLE_METAL) - if (IsOSXVersionSupported(10, 11, 0)) - { - localLayer = [[DisplayViewMetalLayer alloc] init]; - - if ([(DisplayViewMetalLayer *)localLayer device] == nil) - { - [localLayer release]; - localLayer = nil; - } - } -#endif - - if (localLayer == nil) - { - localLayer = [[DisplayViewOpenGLLayer alloc] init]; - MacOGLDisplayView *macOGLCDV = (MacOGLDisplayView *)[(id)localLayer clientDisplay3DView]; - - // For macOS 10.8 Mountain Lion and later, we can use the CAOpenGLLayer directly. But for - // earlier versions of macOS, using the CALayer directly will cause too many strange issues, - // so we'll just keep using the old-school NSOpenGLContext for these older macOS versions. - if (IsOSXVersionSupported(10, 8, 0)) - { - macOGLCDV->SetRenderToCALayer(true); - } - else - { -#if defined(MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7) - if ([self respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) - { - [self setWantsBestResolutionOpenGLSurface:YES]; - } -#endif - localOGLContext = macOGLCDV->GetNSContext(); - [localOGLContext retain]; - macOGLCDV->SetRenderToCALayer(false); - } - } return self; } @@ -1697,6 +1659,16 @@ static std::unordered_map _screenMap; // return [[self cdsVideoOutput] canFilterOnGPU]; } +- (BOOL) allowViewUpdates +{ + return ([self clientDisplay3DView]->GetAllowViewUpdates()) ? YES : NO; +} + +- (void) setAllowViewUpdates:(BOOL)allowUpdates +{ + [self clientDisplay3DView]->SetAllowViewUpdates((allowUpdates) ? true : false); +} + - (void) setIsHUDVisible:(BOOL)theState { [[self cdsVideoOutput] setIsHUDVisible:theState]; @@ -1818,8 +1790,59 @@ static std::unordered_map _screenMap; // } #pragma mark Class Methods -- (void) reassignLocalCALayer +- (void) setupLayer { + DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate]; + CocoaDSCore *cdsCore = (CocoaDSCore *)[[[windowController emuControl] cdsCoreController] content]; + CocoaDSGPU *cdsGPU = [cdsCore cdsGPU]; + +#ifdef ENABLE_APPLE_METAL + MacClientSharedObject *macSharedData = [cdsGPU sharedData]; + if ((macSharedData != nil) && [macSharedData isKindOfClass:[MetalDisplayViewSharedData class]]) + { + localLayer = [[DisplayViewMetalLayer alloc] init]; + [(DisplayViewMetalLayer *)localLayer setSharedData:(MetalDisplayViewSharedData *)macSharedData]; + + MacMetalDisplayView *cdv = (MacMetalDisplayView *)[(id)localLayer clientDisplay3DView]; + cdv->SetFetchObject([cdsGPU fetchObject]); + cdv->Init(); + + if ([(DisplayViewMetalLayer *)localLayer device] == nil) + { + [localLayer release]; + localLayer = nil; + } + } +#endif + + if (localLayer == nil) + { + localLayer = [[DisplayViewOpenGLLayer alloc] init]; + MacOGLDisplayView *macOGLCDV = (MacOGLDisplayView *)[(id)localLayer clientDisplay3DView]; + macOGLCDV->SetFetchObject([cdsGPU fetchObject]); + macOGLCDV->Init(); + + // For macOS 10.8 Mountain Lion and later, we can use the CAOpenGLLayer directly. But for + // earlier versions of macOS, using the CALayer directly will cause too many strange issues, + // so we'll just keep using the old-school NSOpenGLContext for these older macOS versions. + if (IsOSXVersionSupported(10, 8, 0)) + { + macOGLCDV->SetRenderToCALayer(true); + } + else + { +#if defined(MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7) + if ([self respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) + { + [self setWantsBestResolutionOpenGLSurface:YES]; + } +#endif + localOGLContext = macOGLCDV->GetNSContext(); + [localOGLContext retain]; + macOGLCDV->SetRenderToCALayer(false); + } + } + if (localOGLContext != nil) { // If localOGLContext isn't nil, then we will not assign the local layer @@ -1978,14 +2001,12 @@ static std::unordered_map _screenMap; // - (void)updateLayer { - ClientDisplay3DView *cdv = [(id)localLayer clientDisplay3DView]; - cdv->UpdateView(); + [self clientDisplay3DView]->UpdateView(); } - (void)drawRect:(NSRect)dirtyRect { - ClientDisplay3DView *cdv = [(id)localLayer clientDisplay3DView]; - cdv->UpdateView(); + [self clientDisplay3DView]->UpdateView(); } - (void)setFrame:(NSRect)rect @@ -2023,7 +2044,7 @@ static std::unordered_map _screenMap; // { [localLayer setBounds:CGRectMake(0.0f, 0.0f, props.clientWidth, props.clientHeight)]; } -#if defined(MAC_OS_X_VERSION_10_11) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) && defined(ENABLE_APPLE_METAL) +#ifdef ENABLE_APPLE_METAL else if ([[self layer] isKindOfClass:[CAMetalLayer class]]) { [(CAMetalLayer *)localLayer setDrawableSize:CGSizeMake(props.clientWidth, props.clientHeight)]; diff --git a/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm b/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm index aab0f53cb..7bb3e639a 100644 --- a/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm +++ b/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2015 DeSmuME Team + Copyright (C) 2013-2017 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 @@ -347,8 +347,9 @@ { DisplayWindowController *newWindowController = [[DisplayWindowController alloc] initWithWindowNibName:@"DisplayWindow" emuControlDelegate:self]; - [CocoaDSUtil messageSendOneWay:[[newWindowController cdsVideoOutput] receivePort] msgID:MESSAGE_RELOAD_REPROCESS_REDRAW]; - + [newWindowController window]; // Just reference the window to force the nib to load. + [[newWindowController view] setAllowViewUpdates:YES]; + [[newWindowController cdsVideoOutput] handleReloadReprocessRedraw]; [[newWindowController window] makeKeyAndOrderFront:self]; [[newWindowController window] makeMainWindow]; } diff --git a/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.h b/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.h index b21839a2e..764513fa0 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.h +++ b/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.h @@ -22,6 +22,7 @@ #import #import "DisplayViewCALayer.h" +#import "../cocoa_GPU.h" #ifdef MAC_OS_X_VERSION_10_7 #include "../OGLDisplayOutput_3_2.h" @@ -29,7 +30,9 @@ #include "../OGLDisplayOutput.h" #endif +#ifdef BOOL #undef BOOL +#endif class MacOGLDisplayView; @@ -39,6 +42,24 @@ class MacOGLDisplayView; } @end +class MacOGLClientFetchObject : public OGLClientFetchObject +{ +protected: + NSOpenGLContext *_nsContext; + CGLContextObj _context; + +public: + void operator delete(void *ptr); + MacOGLClientFetchObject(); + + NSOpenGLContext* GetNSContext() const; + CGLContextObj GetContext() const; + + virtual void Init(); + virtual void SetFetchBuffers(const NDSDisplayInfo ¤tDisplayInfo); + virtual void FetchFromBufferIndex(const u8 index); +}; + class MacOGLDisplayView : public OGLVideoOutput, public DisplayViewCALayerInterface { protected: @@ -64,13 +85,6 @@ public: virtual void LoadHUDFont(); - virtual void SetVideoBuffers(const uint32_t colorFormat, - const void *videoBufferHead, - const void *nativeBuffer0, - const void *nativeBuffer1, - const void *customBuffer0, const size_t customWidth0, const size_t customHeight0, - const void *customBuffer1, const size_t customWidth1, const size_t customHeight1); - virtual void SetUseVerticalSync(const bool useVerticalSync); virtual void SetScaleFactor(const double scaleFactor); @@ -83,7 +97,9 @@ public: virtual void LoadDisplays(); virtual void ProcessDisplays(); virtual void UpdateView(); - virtual void FrameFinish(); + virtual void FinishFrameAtIndex(const u8 bufferIndex); + virtual void LockDisplayTextures(); + virtual void UnlockDisplayTextures(); }; #endif // _MAC_OGLDISPLAYOUTPUT_H_ diff --git a/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.mm b/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.mm index 10bf7f1fa..8db823f2b 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.mm +++ b/desmume/src/frontend/cocoa/userinterface/MacOGLDisplayView.mm @@ -18,6 +18,7 @@ #include "MacOGLDisplayView.h" #include "../utilities.h" + @implementation DisplayViewOpenGLLayer - (id)init @@ -30,7 +31,6 @@ _cdv = new MacOGLDisplayView(); _cdv->SetFrontendLayer(self); - _cdv->Init(); [self setBounds:CGRectMake(0.0f, 0.0f, (float)GPU_FRAMEBUFFER_NATIVE_WIDTH, (float)GPU_FRAMEBUFFER_NATIVE_HEIGHT)]; [self setAsynchronous:NO]; @@ -82,6 +82,137 @@ @end +#pragma mark - + +void MacOGLClientFetchObject::operator delete(void *ptr) +{ + MacOGLClientFetchObject *fetchObjectPtr = (MacOGLClientFetchObject *)ptr; + [(MacClientSharedObject *)(fetchObjectPtr->GetClientData()) release]; + + CGLContextObj context = fetchObjectPtr->GetContext(); + OGLContextInfo *contextInfo = fetchObjectPtr->GetContextInfo(); + + if (context != NULL) + { + CGLContextObj prevContext = CGLGetCurrentContext(); + CGLSetCurrentContext(context); + ::operator delete(ptr); + CGLSetCurrentContext(prevContext); + + delete contextInfo; + [fetchObjectPtr->GetNSContext() release]; + } +} + +MacOGLClientFetchObject::MacOGLClientFetchObject() +{ + // Initialize the OpenGL context. + // + // We create an NSOpenGLContext and extract the CGLContextObj from it because + // [NSOpenGLContext CGLContextObj] is available on macOS 10.5 Leopard, but + // [NSOpenGLContext initWithCGLContextObj:] is only available on macOS 10.6 + // Snow Leopard. + bool useContext_3_2 = false; + NSOpenGLPixelFormatAttribute attributes[] = { + NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute)24, + NSOpenGLPFAAlphaSize, (NSOpenGLPixelFormatAttribute)8, + NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)0, + NSOpenGLPFAStencilSize, (NSOpenGLPixelFormatAttribute)0, + (NSOpenGLPixelFormatAttribute)0, (NSOpenGLPixelFormatAttribute)0, + (NSOpenGLPixelFormatAttribute)0 + }; + +#ifdef _OGLDISPLAYOUTPUT_3_2_H_ + // If we can support a 3.2 Core Profile context, then request that in our + // pixel format attributes. + useContext_3_2 = IsOSXVersionSupported(10, 7, 0); + if (useContext_3_2) + { + attributes[8] = NSOpenGLPFAOpenGLProfile; + attributes[9] = (NSOpenGLPixelFormatAttribute)NSOpenGLProfileVersion3_2Core; + } +#endif + + NSOpenGLPixelFormat *nsPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; + if (nsPixelFormat == nil) + { + // If we can't get a 3.2 Core Profile context, then switch to using a + // legacy context instead. + useContext_3_2 = false; + attributes[9] = (NSOpenGLPixelFormatAttribute)0; + attributes[10] = (NSOpenGLPixelFormatAttribute)0; + nsPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; + } + + _nsContext = [[NSOpenGLContext alloc] initWithFormat:nsPixelFormat shareContext:nil]; + _context = (CGLContextObj)[_nsContext CGLContextObj]; + + [nsPixelFormat release]; + + CGLContextObj prevContext = CGLGetCurrentContext(); + CGLSetCurrentContext(_context); + +#ifdef _OGLDISPLAYOUTPUT_3_2_H_ + if (useContext_3_2) + { + _contextInfo = new OGLContextInfo_3_2; + } + else +#endif + { + _contextInfo = new OGLContextInfo_Legacy; + } + + CGLSetCurrentContext(prevContext); + + _clientData = [[MacClientSharedObject alloc] init]; +} + +NSOpenGLContext* MacOGLClientFetchObject::GetNSContext() const +{ + return this->_nsContext; +} + +CGLContextObj MacOGLClientFetchObject::GetContext() const +{ + return this->_context; +} + +void MacOGLClientFetchObject::Init() +{ + [(MacClientSharedObject *)this->_clientData setGPUFetchObject:this]; + + CGLContextObj prevContext = CGLGetCurrentContext(); + CGLSetCurrentContext(_context); + this->OGLClientFetchObject::Init(); + CGLSetCurrentContext(prevContext); +} + +void MacOGLClientFetchObject::SetFetchBuffers(const NDSDisplayInfo ¤tDisplayInfo) +{ + CGLLockContext(this->_context); + CGLSetCurrentContext(this->_context); + this->OGLClientFetchObject::SetFetchBuffers(currentDisplayInfo); + CGLUnlockContext(this->_context); +} + +void MacOGLClientFetchObject::FetchFromBufferIndex(const u8 index) +{ + MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)this->_clientData; + this->_useCPUFilterPipeline = ([sharedViewObject isCPUFilteringNeeded]) ? true : false; + + pthread_rwlock_rdlock([sharedViewObject rwlockFramebufferAtIndex:index]); + + CGLLockContext(this->_context); + CGLSetCurrentContext(this->_context); + this->GPUClientFetchObject::FetchFromBufferIndex(index); + CGLUnlockContext(this->_context); + + pthread_rwlock_unlock([sharedViewObject rwlockFramebufferAtIndex:index]); +} + +#pragma mark - + void MacOGLDisplayView::operator delete(void *ptr) { CGLContextObj context = ((MacOGLDisplayView *)ptr)->GetContext(); @@ -141,33 +272,37 @@ MacOGLDisplayView::MacOGLDisplayView() _nsPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; } - _nsContext = [[NSOpenGLContext alloc] initWithFormat:_nsPixelFormat shareContext:nil]; - _context = (CGLContextObj)[_nsContext CGLContextObj]; _pixelFormat = (CGLPixelFormatObj)[_nsPixelFormat CGLPixelFormatObj]; - CGLContextObj prevContext = CGLGetCurrentContext(); - CGLSetCurrentContext(_context); - -#ifdef _OGLDISPLAYOUTPUT_3_2_H_ - if (useContext_3_2) - { - _contextInfo = new OGLContextInfo_3_2; - } - else -#endif - { - _contextInfo = new OGLContextInfo_Legacy; - } - - CGLSetCurrentContext(prevContext); - + _nsContext = nil; + _context = nil; _willRenderToCALayer = false; + _allowViewUpdates = false; } void MacOGLDisplayView::Init() { + this->_nsContext = [[NSOpenGLContext alloc] initWithFormat:this->_nsPixelFormat + shareContext:((MacOGLClientFetchObject *)this->_fetchObject)->GetNSContext()]; + this->_context = (CGLContextObj)[this->_nsContext CGLContextObj]; + CGLContextObj prevContext = CGLGetCurrentContext(); CGLSetCurrentContext(this->_context); + +#ifdef _OGLDISPLAYOUTPUT_3_2_H_ + GLint profileVersion = 0; + CGLDescribePixelFormat(this->_pixelFormat, 0, kCGLPFAOpenGLProfile, &profileVersion); + + if (profileVersion == kCGLOGLPVersion_3_2_Core) + { + this->_contextInfo = new OGLContextInfo_3_2; + } + else +#endif + { + this->_contextInfo = new OGLContextInfo_Legacy; + } + this->OGLVideoOutput::Init(); CGLSetCurrentContext(prevContext); } @@ -210,26 +345,6 @@ void MacOGLDisplayView::LoadHUDFont() CGLUnlockContext(this->_context); } -void MacOGLDisplayView::SetVideoBuffers(const uint32_t colorFormat, - const void *videoBufferHead, - const void *nativeBuffer0, - const void *nativeBuffer1, - const void *customBuffer0, const size_t customWidth0, const size_t customHeight0, - const void *customBuffer1, const size_t customWidth1, const size_t customHeight1) -{ - CGLLockContext(this->_context); - CGLSetCurrentContext(this->_context); - - this->OGLVideoOutput::SetVideoBuffers(colorFormat, - videoBufferHead, - nativeBuffer0, - nativeBuffer1, - customBuffer0, customWidth0, customHeight0, - customBuffer1, customWidth1, customHeight1); - - CGLUnlockContext(this->_context); -} - void MacOGLDisplayView::SetUseVerticalSync(const bool useVerticalSync) { const GLint swapInt = (useVerticalSync) ? 1 : 0; @@ -292,6 +407,11 @@ void MacOGLDisplayView::ProcessDisplays() void MacOGLDisplayView::UpdateView() { + if (!this->_allowViewUpdates) + { + return; + } + if (this->_willRenderToCALayer) { this->CALayerDisplay(); @@ -306,10 +426,28 @@ void MacOGLDisplayView::UpdateView() } } -void MacOGLDisplayView::FrameFinish() +void MacOGLDisplayView::FinishFrameAtIndex(const u8 bufferIndex) { CGLLockContext(this->_context); CGLSetCurrentContext(this->_context); - this->OGLVideoOutput::FrameFinish(); + this->OGLVideoOutput::FinishFrameAtIndex(bufferIndex); CGLUnlockContext(this->_context); } + +void MacOGLDisplayView::LockDisplayTextures() +{ + const GPUClientFetchObject &fetchObj = this->GetFetchObject(); + const u8 bufferIndex = this->_emuDisplayInfo.bufferIndex; + MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData(); + + pthread_rwlock_rdlock([sharedViewObject rwlockFramebufferAtIndex:bufferIndex]); +} + +void MacOGLDisplayView::UnlockDisplayTextures() +{ + const GPUClientFetchObject &fetchObj = this->GetFetchObject(); + const u8 bufferIndex = this->_emuDisplayInfo.bufferIndex; + MacClientSharedObject *sharedViewObject = (MacClientSharedObject *)fetchObj.GetClientData(); + + pthread_rwlock_unlock([sharedViewObject rwlockFramebufferAtIndex:bufferIndex]); +} diff --git a/desmume/src/frontend/cocoa/userinterface/appDelegate.mm b/desmume/src/frontend/cocoa/userinterface/appDelegate.mm index 6e434bc3c..63ac0b078 100644 --- a/desmume/src/frontend/cocoa/userinterface/appDelegate.mm +++ b/desmume/src/frontend/cocoa/userinterface/appDelegate.mm @@ -28,6 +28,7 @@ #import "inputPrefsView.h" #import "cocoa_core.h" +#import "cocoa_GPU.h" #import "cocoa_file.h" #import "cocoa_firmware.h" #import "cocoa_globals.h" @@ -178,6 +179,14 @@ // Init the DS emulation core. CocoaDSCore *newCore = [[[CocoaDSCore alloc] init] autorelease]; + MacClientSharedObject *sharedViewObject = [[newCore cdsGPU] sharedData]; + [NSThread detachNewThreadSelector:@selector(runThread:) toTarget:sharedViewObject withObject:nil]; + + // Wait until the SPU is finished starting up. + while ([sharedViewObject thread] == nil) + { + [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; + } // Init the DS controller. CocoaDSController *newController = [[[CocoaDSController alloc] init] autorelease]; @@ -683,6 +692,9 @@ // If this is the last window in the list, make this window key and main. // Otherwise, just order the window to the front so that the windows will // stack in a deterministic order. + [[windowController view] setAllowViewUpdates:YES]; + [[windowController cdsVideoOutput] handleReloadReprocessRedraw]; + if (windowProperties == [windowPropertiesList lastObject]) { [[windowController window] makeKeyAndOrderFront:self]; @@ -693,9 +705,6 @@ [[windowController window] orderFront:self]; } - // Draw the display view now so that we guarantee that its drawn at least once. - [CocoaDSUtil messageSendOneWay:[[windowController cdsVideoOutput] receivePort] msgID:MESSAGE_RELOAD_REPROCESS_REDRAW]; - // If this window is set to full screen mode, its associated screen index must // exist. If not, this window will not enter full screen mode. This is necessary, // since the user's screen configuration could change in between app launches, @@ -704,8 +713,6 @@ ([[NSScreen screens] indexOfObject:[[windowController window] screen]] == screenIndex)) { [windowController toggleFullScreenDisplay:self]; - [[windowController window] makeKeyAndOrderFront:self]; - [[windowController window] makeMainWindow]; } } }