From e90ac6cc43be3a7d8d1ff0ea643e14fe417af346 Mon Sep 17 00:00:00 2001 From: rogerman Date: Fri, 6 May 2022 03:12:01 -0700 Subject: [PATCH] Cocoa Port (OpenEmu Plug-in): Fix a crash with HUD rendering when running on macOS Monterey. - So apparently, the buffers used to upload the font texture data must remain in memory for the entire lifetime of the texture when running on Monterey. It is a mystery why the OpenEmu plug-in requires this for Monterey, as this is not required for older macOS versions, nor is it required in any way on the standalone app. - Also remove the copy of the HUD font path. Since we're now copying the font file itself into memory, retaining a copy of the font path is no longer necessary. --- .../src/frontend/cocoa/OGLDisplayOutput.cpp | 38 ++++++++----------- desmume/src/frontend/cocoa/OGLDisplayOutput.h | 2 + .../src/frontend/cocoa/openemu/NDSGameCore.h | 1 - .../src/frontend/cocoa/openemu/NDSGameCore.mm | 13 ++----- 4 files changed, 22 insertions(+), 32 deletions(-) diff --git a/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp b/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp index 663643a77..227ccb601 100644 --- a/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp +++ b/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp @@ -6301,6 +6301,8 @@ OGLHUDLayer::OGLHUDLayer(OGLVideoOutput *oglVO) } glGenTextures(1, &_texCharMap); + _workingCharBufferList = new std::vector; + _workingCharBufferList->reserve(16); // Set up VBOs glGenBuffersARB(1, &_vboPositionVertexID); @@ -6384,13 +6386,20 @@ OGLHUDLayer::~OGLHUDLayer() glDeleteBuffersARB(1, &this->_vboElementID); glDeleteTextures(1, &this->_texCharMap); + + // We can only deallocate the working buffers now because some clients + // require that these buffers remain for the entire lifetime of the + // texture. Do this to avoid crashes. + for (size_t i = 0; i < this->_workingCharBufferList->size(); i++) + { + free((*this->_workingCharBufferList)[i]); + } + delete this->_workingCharBufferList; } void OGLHUDLayer::CopyHUDFont(const FT_Face &fontFace, const size_t glyphSize, const size_t glyphTileSize, GlyphInfo *glyphInfo) { FT_Error error = FT_Err_Ok; - std::vector workingBufferList; - workingBufferList.reserve(16); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, this->_texCharMap); @@ -6404,10 +6413,10 @@ void OGLHUDLayer::CopyHUDFont(const FT_Face &fontFace, const size_t glyphSize, c const uint32_t fontColor = 0x00FFFFFF; // Allocate a working buffer for FreeType to draw in. We then need to add - // it to a list so that we can deallocate the working buffer after OpenGL - // has copied the buffer to its associated texture. + // it to a list so that we can deallocate the working buffer at texture + // deletion time. uint32_t *charMapBuffer = (uint32_t *)malloc(charMapBufferPixCount * 2 * sizeof(uint32_t)); - workingBufferList.push_back(charMapBuffer); + this->_workingCharBufferList->push_back(charMapBuffer); for (size_t i = 0; i < charMapBufferPixCount; i++) { charMapBuffer[i] = fontColor; @@ -6477,13 +6486,6 @@ void OGLHUDLayer::CopyHUDFont(const FT_Face &fontFace, const size_t glyphSize, c glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, texLevel - 1); glBindTexture(GL_TEXTURE_2D, 0); - - // Synchronize here, then free all previously allocated working buffers. - glFinish(); - for (size_t i = 0; i < workingBufferList.size(); i++) - { - free(workingBufferList[i]); - } } void OGLHUDLayer::_UpdateVerticesOGL() @@ -6642,7 +6644,7 @@ void OGLHUDLayer::RenderOGL(bool isRenderingFlipped) // Finally, draw each character inside the box. const GLfloat textBoxScale = (GLfloat)HUD_TEXTBOX_BASE_SCALE * this->_output->GetHUDObjectScale(); - if (textBoxScale >= (2.0/3.0)) + if ( (textBoxScale >= (2.0/3.0)) || !this->_output->WillHUDRenderMipmapped() ) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -6650,15 +6652,7 @@ void OGLHUDLayer::RenderOGL(bool isRenderingFlipped) } else { - if (this->_output->WillHUDRenderMipmapped()) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -0.50f); } diff --git a/desmume/src/frontend/cocoa/OGLDisplayOutput.h b/desmume/src/frontend/cocoa/OGLDisplayOutput.h index 6b4baf4cc..5136d88e5 100644 --- a/desmume/src/frontend/cocoa/OGLDisplayOutput.h +++ b/desmume/src/frontend/cocoa/OGLDisplayOutput.h @@ -296,6 +296,8 @@ protected: GLuint _vboElementID; GLuint _texCharMap; + std::vector *_workingCharBufferList; + void _UpdateVerticesOGL(); public: diff --git a/desmume/src/frontend/cocoa/openemu/NDSGameCore.h b/desmume/src/frontend/cocoa/openemu/NDSGameCore.h index b3fc3a232..4801ca831 100644 --- a/desmume/src/frontend/cocoa/openemu/NDSGameCore.h +++ b/desmume/src/frontend/cocoa/openemu/NDSGameCore.h @@ -254,7 +254,6 @@ typedef struct OEMenuItemDesc OEMenuItemDesc; @interface NDSGameCore : OEGameCore { - char _hudFontPath[4096]; // This should be plenty for storing a file path! apple_unfairlock_t unfairlockDisplayMode; pthread_rwlock_t rwlockCoreExecute; diff --git a/desmume/src/frontend/cocoa/openemu/NDSGameCore.mm b/desmume/src/frontend/cocoa/openemu/NDSGameCore.mm index a7380a073..97f51a6a7 100644 --- a/desmume/src/frontend/cocoa/openemu/NDSGameCore.mm +++ b/desmume/src/frontend/cocoa/openemu/NDSGameCore.mm @@ -124,14 +124,6 @@ volatile bool execute = true; return self; } - // Retrieve the file path for the HUD font file. - // Because this file must be reloaded due to repeated context changes, we'll - // need to maintain a copy of the file path. - NSString *fontPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"SourceSansPro-Bold" ofType:@"otf"]; - const char *gameCoreFontPath = [[NSFileManager defaultManager] fileSystemRepresentationWithPath:fontPath]; - memset(_hudFontPath, 0, sizeof(_hudFontPath)); - strlcpy(_hudFontPath, gameCoreFontPath, sizeof(_hudFontPath)); - _fpsTimer = nil; _willUseOpenGL3Context = true; _videoContext = NULL; @@ -355,9 +347,12 @@ volatile bool execute = true; // Set up the presenter if (_cdp == NULL) { + NSString *gameCoreFontPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"SourceSansPro-Bold" ofType:@"otf"]; + const char *hudFontPath = [[NSFileManager defaultManager] fileSystemRepresentationWithPath:gameCoreFontPath]; + _cdp = new OE_OGLDisplayPresenter(fetchObj); _cdp->Init(); - _cdp->SetHUDFontPath(_hudFontPath); + _cdp->SetHUDFontPath(hudFontPath); _cdp->SetHUDRenderMipmapped(false); // Mipmapped HUD rendering doesn't work on OpenEmu! // OpenEmu doesn't provide us with the backing scaling factor, which is used to