From db06a04d73bf0b2638f331e83783fed4a916dae1 Mon Sep 17 00:00:00 2001 From: rogerman Date: Wed, 10 Jun 2015 03:53:19 +0000 Subject: [PATCH] Cocoa Port: - Give the video blitter the ability to handle any arbitrary dimensions of video input. --- desmume/src/cocoa/OGLDisplayOutput.cpp | 250 ++++++++++++------ desmume/src/cocoa/OGLDisplayOutput.h | 16 +- desmume/src/cocoa/cocoa_GPU.h | 21 +- desmume/src/cocoa/cocoa_GPU.mm | 113 +++++--- desmume/src/cocoa/cocoa_globals.h | 13 +- desmume/src/cocoa/cocoa_output.h | 10 +- desmume/src/cocoa/cocoa_output.mm | 74 +++--- .../userinterface/DisplayWindowController.h | 2 - .../userinterface/DisplayWindowController.mm | 93 +++---- 9 files changed, 349 insertions(+), 243 deletions(-) diff --git a/desmume/src/cocoa/OGLDisplayOutput.cpp b/desmume/src/cocoa/OGLDisplayOutput.cpp index ad748c948..dfd771ce0 100644 --- a/desmume/src/cocoa/OGLDisplayOutput.cpp +++ b/desmume/src/cocoa/OGLDisplayOutput.cpp @@ -4587,6 +4587,33 @@ OGLFilterDeposterize::~OGLFilterDeposterize() glDeleteTextures(1, &this->_texIntermediateID); } +void OGLFilterDeposterize::SetSrcSizeOGL(GLsizei w, GLsizei h) +{ + this->_srcWidth = w; + this->_srcHeight = h; + this->_dstWidth = this->_srcWidth * this->_scale; + this->_dstHeight = this->_srcHeight * this->_scale; + + this->_texCoordBuffer[2] = w; + this->_texCoordBuffer[4] = w; + this->_texCoordBuffer[5] = h; + this->_texCoordBuffer[7] = h; + + glBindBuffer(GL_ARRAY_BUFFER, this->_vboTexCoordID); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(this->_texCoordBuffer) , this->_texCoordBuffer); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + uint32_t *tempDstBuffer = (uint32_t *)calloc(this->_dstWidth * this->_dstHeight, sizeof(uint32_t)); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texDstID); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_dstWidth, this->_dstHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, tempDstBuffer); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texIntermediateID); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_dstWidth, this->_dstHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, tempDstBuffer); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + free(tempDstBuffer); +} + GLuint OGLFilterDeposterize::RunFilterOGL(GLuint srcTexID) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->_fboID); @@ -4869,15 +4896,10 @@ bool OGLImage::CanUseShaderBasedFilters() return this->_canUseShaderBasedFilters; } -void OGLImage::GetNormalSize(double *w, double *h) +void OGLImage::GetNormalSize(double &w, double &h) { - if (w == NULL || h == NULL) - { - return; - } - - *w = this->_normalWidth; - *h = this->_normalHeight; + w = this->_normalWidth; + h = this->_normalHeight; } void OGLImage::UploadVerticesOGL() @@ -5372,19 +5394,22 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO) { _output = oglVO; _needUploadVertices = true; + _needUploadTexCoords = true; _useDeposterize = false; + _displayWidth = GPU_DISPLAY_WIDTH; + _displayHeight = GPU_DISPLAY_HEIGHT; _displayMode = DS_DISPLAY_TYPE_DUAL; _displayOrder = DS_DISPLAY_ORDER_MAIN_FIRST; _displayOrientation = DS_DISPLAY_ORIENTATION_VERTICAL; _gapScalar = 0.0f; _rotation = 0.0f; - _normalWidth = GPU_DISPLAY_WIDTH; - _normalHeight = GPU_DISPLAY_HEIGHT*2.0 + (DS_DISPLAY_GAP*_gapScalar); + _normalWidth = _displayWidth; + _normalHeight = _displayHeight*2.0 + ((_displayHeight * DS_DISPLAY_VERTICAL_GAP_TO_HEIGHT_RATIO) * _gapScalar); - _vf[0] = new VideoFilter(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, VideoFilterTypeID_None, 0); - _vf[1] = new VideoFilter(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, VideoFilterTypeID_None, 0); + _vf[0] = new VideoFilter(_displayWidth, _displayHeight, VideoFilterTypeID_None, 0); + _vf[1] = new VideoFilter(_displayWidth, _displayHeight, VideoFilterTypeID_None, 0); _vfDual = new VideoFilter(_vf[0]->GetSrcWidth(), _vf[0]->GetSrcHeight() + _vf[1]->GetSrcHeight(), VideoFilterTypeID_None, 2); _vfMasterDstBuffer = (uint32_t *)calloc(_vfDual->GetDstWidth() * _vfDual->GetDstHeight(), sizeof(uint32_t)); @@ -5414,16 +5439,12 @@ 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_CACHED_APPLE); - glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, _vf[0]->GetDstWidth() * _vf[0]->GetDstHeight() * sizeof(uint32_t), _vfMasterDstBuffer); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texCPUFilterDstID[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); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE); - glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, _vf[1]->GetDstWidth() * _vf[1]->GetDstHeight() * sizeof(uint32_t), _vfMasterDstBuffer + (_vf[0]->GetDstWidth() * _vf[0]->GetDstHeight())); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texVideoInputDataID[0]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -5624,6 +5645,70 @@ void OGLDisplayLayer::SetFiltersPreferGPUOGL(bool preferGPU) { this->_filtersPreferGPU = preferGPU; this->_useShaderBasedPixelScaler = (preferGPU) ? this->SetGPUPixelScalerOGL(this->_pixelScaler) : false; + + if (this->_useShaderBasedPixelScaler) + { + this->UpdateTexCoords(this->_shaderFilter[0]->GetDstWidth(), this->_shaderFilter[0]->GetDstHeight()); + } + else + { + this->UpdateTexCoords(this->_vf[0]->GetDstWidth(), this->_vf[0]->GetDstHeight()); + } +} + +uint16_t OGLDisplayLayer::GetDisplayWidth() +{ + return this->_displayWidth; +} + +uint16_t OGLDisplayLayer::GetDisplayHeight() +{ + return this->_displayHeight; +} + +void OGLDisplayLayer::SetDisplaySize(uint16_t w, uint16_t h) +{ + this->_displayWidth = w; + this->_displayHeight = h; + this->GetNormalSize(this->_normalWidth, this->_normalHeight); + + const VideoFilterAttributes filterAttr = this->_vf[0]->GetAttributes(); + this->ResizeCPUPixelScalerOGL(w, h, w, h, filterAttr.scaleMultiply, filterAttr.scaleDivide); + this->_vf[0]->SetSourceSize(w, h); + this->_vf[1]->SetSourceSize(w, h); + this->_vfDual->SetSourceSize(w, this->_vf[0]->GetSrcHeight() + this->_vf[1]->GetSrcHeight()); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataID[0]); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_vf[0]->GetSrcWidth(), this->_vf[0]->GetSrcHeight(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, this->_vf[0]->GetSrcBufferPtr()); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataID[1]); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_vf[1]->GetSrcWidth(), this->_vf[1]->GetSrcHeight(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, this->_vf[1]->GetSrcBufferPtr()); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + + if (this->_canUseShaderBasedFilters) + { + for (size_t i = 0; i < 2; i++) + { + this->_filterDeposterize[i]->SetSrcSizeOGL(this->_vf[i]->GetSrcWidth(), this->_vf[i]->GetSrcHeight()); + this->_shaderFilter[i]->SetSrcSizeOGL(this->_vf[i]->GetSrcWidth(), this->_vf[i]->GetSrcHeight()); + } + } + + if (this->_useShaderBasedPixelScaler) + { + this->UpdateTexCoords(this->_shaderFilter[0]->GetDstWidth(), this->_shaderFilter[0]->GetDstHeight()); + } + else + { + this->UpdateTexCoords(this->_vf[0]->GetDstWidth(), this->_vf[0]->GetDstHeight()); + } + + this->UpdateVertices(); } int OGLDisplayLayer::GetMode() @@ -5634,7 +5719,7 @@ int OGLDisplayLayer::GetMode() void OGLDisplayLayer::SetMode(int dispMode) { this->_displayMode = dispMode; - this->GetNormalSize(&this->_normalWidth, &this->_normalHeight); + this->GetNormalSize(this->_normalWidth, this->_normalHeight); this->UpdateVertices(); } @@ -5646,7 +5731,7 @@ int OGLDisplayLayer::GetOrientation() void OGLDisplayLayer::SetOrientation(int dispOrientation) { this->_displayOrientation = dispOrientation; - this->GetNormalSize(&this->_normalWidth, &this->_normalHeight); + this->GetNormalSize(this->_normalWidth, this->_normalHeight); this->UpdateVertices(); } @@ -5658,7 +5743,7 @@ GLfloat OGLDisplayLayer::GetGapScalar() void OGLDisplayLayer::SetGapScalar(GLfloat theScalar) { this->_gapScalar = theScalar; - this->GetNormalSize(&this->_normalWidth, &this->_normalHeight); + this->GetNormalSize(this->_normalWidth, this->_normalHeight); this->UpdateVertices(); } @@ -5705,9 +5790,9 @@ void OGLDisplayLayer::SetOrder(int dispOrder) void OGLDisplayLayer::UpdateVertices() { - const GLfloat w = GPU_DISPLAY_WIDTH; - const GLfloat h = GPU_DISPLAY_HEIGHT; - const GLfloat gap = DS_DISPLAY_GAP * this->_gapScalar / 2.0; + const GLfloat w = this->_displayWidth; + const GLfloat h = this->_displayHeight; + const GLfloat gap = (h * DS_DISPLAY_VERTICAL_GAP_TO_HEIGHT_RATIO) * this->_gapScalar / 2.0; if (this->_displayMode == DS_DISPLAY_TYPE_DUAL) { @@ -5763,6 +5848,8 @@ void OGLDisplayLayer::UpdateTexCoords(GLfloat s, GLfloat t) texCoordBuffer[6] = 0.0f; texCoordBuffer[7] = t; memcpy(texCoordBuffer + (1 * 8), texCoordBuffer + (0 * 8), sizeof(GLint) * (1 * 8)); + + this->_needUploadTexCoords = true; } bool OGLDisplayLayer::CanUseShaderBasedFilters() @@ -5770,32 +5857,59 @@ bool OGLDisplayLayer::CanUseShaderBasedFilters() return this->_canUseShaderBasedFilters; } -void OGLDisplayLayer::GetNormalSize(double *w, double *h) +void OGLDisplayLayer::GetNormalSize(double &w, double &h) { - if (w == NULL || h == NULL) - { - return; - } - if (this->_displayMode != DS_DISPLAY_TYPE_DUAL) { - *w = GPU_DISPLAY_WIDTH; - *h = GPU_DISPLAY_HEIGHT; - return; + w = this->_displayWidth; + h = this->_displayHeight; } - - if (this->_displayOrientation == DS_DISPLAY_ORIENTATION_VERTICAL) + else if (this->_displayOrientation == DS_DISPLAY_ORIENTATION_VERTICAL) { - *w = GPU_DISPLAY_WIDTH; - *h = GPU_DISPLAY_HEIGHT * 2.0 + (DS_DISPLAY_GAP * this->_gapScalar); + w = this->_displayWidth; + h = this->_displayHeight * 2.0 + ((this->_displayHeight * DS_DISPLAY_VERTICAL_GAP_TO_HEIGHT_RATIO) * this->_gapScalar); } else { - *w = GPU_DISPLAY_WIDTH * 2.0 + (DS_DISPLAY_GAP * this->_gapScalar); - *h = GPU_DISPLAY_HEIGHT; + w = this->_displayWidth * 2.0 + ((this->_displayHeight * DS_DISPLAY_VERTICAL_GAP_TO_HEIGHT_RATIO) * this->_gapScalar); + h = this->_displayHeight; } } +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) +{ + const GLsizei newDstBufferWidth = (srcWidthMain + srcWidthTouch) * scaleMultiply / scaleDivide; + const GLsizei newDstBufferHeight = (srcHeightMain + srcHeightTouch) * scaleMultiply / scaleDivide; + + uint32_t *oldMasterBuffer = _vfMasterDstBuffer; + uint32_t *newMasterBuffer = (uint32_t *)calloc(newDstBufferWidth * newDstBufferHeight, sizeof(uint32_t)); + this->_vf[0]->SetDstBufferPtr(newMasterBuffer); + this->_vf[1]->SetDstBufferPtr(newMasterBuffer + ((srcWidthMain * scaleMultiply / scaleDivide) * (srcHeightMain * scaleMultiply / scaleDivide)) ); + this->_vfDual->SetDstBufferPtr(newMasterBuffer); + + const GLsizei newDstBufferSingleWidth = srcWidthMain * scaleMultiply / scaleDivide; + const GLsizei newDstBufferSingleHeight = srcHeightMain * scaleMultiply / scaleDivide; + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[0]); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE); + glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, newDstBufferSingleWidth * newDstBufferSingleHeight * sizeof(uint32_t), newMasterBuffer); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, newDstBufferSingleWidth, newDstBufferSingleHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, newMasterBuffer); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[1]); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE); + glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, newDstBufferSingleWidth * newDstBufferSingleHeight * sizeof(uint32_t), newMasterBuffer + (newDstBufferSingleWidth * newDstBufferSingleHeight)); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, newDstBufferSingleWidth, newDstBufferSingleHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, newMasterBuffer + (newDstBufferSingleWidth * newDstBufferSingleHeight)); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + + _vfMasterDstBuffer = newMasterBuffer; + free(oldMasterBuffer); +} + void OGLDisplayLayer::UploadVerticesOGL() { glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboVertexID); @@ -5809,6 +5923,7 @@ void OGLDisplayLayer::UploadTexCoordsOGL() glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboTexCoordID); glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(GLfloat) * (2 * 8), this->texCoordBuffer); glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + this->_needUploadTexCoords = false; } void OGLDisplayLayer::UploadTransformationOGL() @@ -5928,6 +6043,15 @@ void OGLDisplayLayer::SetPixelScalerOGL(const int filterID) this->SetCPUPixelScalerOGL(newFilterID); this->_useShaderBasedPixelScaler = (this->GetFiltersPreferGPU()) ? this->SetGPUPixelScalerOGL(newFilterID) : false; this->_pixelScaler = newFilterID; + + if (this->_useShaderBasedPixelScaler) + { + this->UpdateTexCoords(this->_shaderFilter[0]->GetDstWidth(), this->_shaderFilter[0]->GetDstHeight()); + } + else + { + this->UpdateTexCoords(this->_vf[0]->GetDstWidth(), this->_vf[0]->GetDstHeight()); + } } bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) @@ -6139,7 +6263,6 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) break; } - case VideoFilterTypeID_5xBRZ: { if (this->_shaderSupport >= ShaderSupport_MidTier) @@ -6160,7 +6283,7 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) if (willUseShaderBasedPixelScaler) { - _shaderFilter[i]->SetScaleOGL(vfScale); + this->_shaderFilter[i]->SetScaleOGL(vfScale); } } @@ -6169,7 +6292,6 @@ bool OGLDisplayLayer::SetGPUPixelScalerOGL(const VideoFilterTypeID filterID) void OGLDisplayLayer::SetCPUPixelScalerOGL(const VideoFilterTypeID filterID) { - bool needResizeTexture = false; const VideoFilterAttributes newFilterAttr = VideoFilter::GetAttributesByID(filterID); const GLsizei oldDstBufferWidth = this->_vf[0]->GetDstWidth() + this->_vf[1]->GetDstWidth(); const GLsizei oldDstBufferHeight = this->_vf[0]->GetDstHeight() + this->_vf[1]->GetDstHeight(); @@ -6178,38 +6300,7 @@ void OGLDisplayLayer::SetCPUPixelScalerOGL(const VideoFilterTypeID filterID) if (oldDstBufferWidth != newDstBufferWidth || oldDstBufferHeight != newDstBufferHeight) { - needResizeTexture = true; - } - - if (needResizeTexture) - { - uint32_t *oldMasterBuffer = _vfMasterDstBuffer; - uint32_t *newMasterBuffer = (uint32_t *)calloc(newDstBufferWidth * newDstBufferHeight, sizeof(uint32_t)); - this->_vf[0]->SetDstBufferPtr(newMasterBuffer); - this->_vf[1]->SetDstBufferPtr(newMasterBuffer + ((this->_vf[0]->GetSrcWidth() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide) * (this->_vf[0]->GetSrcHeight() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide)) ); - this->_vfDual->SetDstBufferPtr(newMasterBuffer); - - const GLsizei newDstBufferSingleWidth = this->_vf[0]->GetSrcWidth() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide; - const GLsizei newDstBufferSingleHeight = this->_vf[0]->GetSrcHeight() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide; - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[0]); - glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, newDstBufferSingleWidth * newDstBufferSingleHeight * sizeof(uint32_t), newMasterBuffer); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE); - glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, newDstBufferSingleWidth, newDstBufferSingleHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, newMasterBuffer); - glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[1]); - glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, newDstBufferSingleWidth * newDstBufferSingleHeight * sizeof(uint32_t), newMasterBuffer + (newDstBufferSingleWidth * newDstBufferSingleHeight)); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE); - glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, newDstBufferSingleWidth, newDstBufferSingleHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, newMasterBuffer + (newDstBufferSingleWidth * newDstBufferSingleHeight)); - glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - - _vfMasterDstBuffer = newMasterBuffer; - free(oldMasterBuffer); + this->ResizeCPUPixelScalerOGL(this->_vf[0]->GetSrcWidth(), this->_vf[0]->GetSrcHeight(), this->_vf[1]->GetSrcWidth(), this->_vf[1]->GetSrcHeight(), newFilterAttr.scaleMultiply, newFilterAttr.scaleDivide); } this->_vf[0]->ChangeFilterByID(filterID); @@ -6220,7 +6311,7 @@ void OGLDisplayLayer::SetCPUPixelScalerOGL(const VideoFilterTypeID filterID) void OGLDisplayLayer::LoadFrameOGL(const uint16_t *frameData, GLint x, GLint y, GLsizei w, GLsizei h) { const bool isUsingCPUPixelScaler = this->_pixelScaler != VideoFilterTypeID_None && !this->_useShaderBasedPixelScaler; - bool loadDualScreen = (y == 0) && (h > GPU_DISPLAY_HEIGHT); + bool loadDualScreen = (y == 0) && (h > this->_displayHeight); bool loadSingleMainScreen = (y == 0); bool loadSingleTouchScreen = (y > 0); @@ -6241,7 +6332,7 @@ void OGLDisplayLayer::LoadFrameOGL(const uint16_t *frameData, GLint x, GLint y, else if (loadSingleTouchScreen) { glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataID[1]); - glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frameData); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frameData + (w * h)); } glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); @@ -6298,13 +6389,11 @@ void OGLDisplayLayer::ProcessOGL() { this->_texVideoPixelScalerID[0] = this->_shaderFilter[0]->RunFilterOGL(this->_texVideoSourceID[0]); this->_texVideoPixelScalerID[1] = this->_shaderFilter[1]->RunFilterOGL(this->_texVideoSourceID[1]); - this->UpdateTexCoords(this->_shaderFilter[0]->GetDstWidth(), this->_shaderFilter[0]->GetDstHeight()); } else { this->_texVideoPixelScalerID[0] = this->_texVideoSourceID[0]; this->_texVideoPixelScalerID[1] = this->_texVideoSourceID[1]; - this->UpdateTexCoords(this->_vf[0]->GetSrcWidth(), this->_vf[0]->GetSrcHeight()); } } else @@ -6345,14 +6434,17 @@ void OGLDisplayLayer::ProcessOGL() default: break; } - - this->UpdateTexCoords(this->_vf[0]->GetDstWidth(), this->_vf[0]->GetDstHeight()); } // Output this->_texVideoOutputID[0] = this->_texVideoPixelScalerID[0]; this->_texVideoOutputID[1] = this->_texVideoPixelScalerID[1]; - this->UploadTexCoordsOGL(); + + if (this->_needUploadTexCoords) + { + this->UploadTexCoordsOGL(); + } + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); } diff --git a/desmume/src/cocoa/OGLDisplayOutput.h b/desmume/src/cocoa/OGLDisplayOutput.h index 053aa6e90..6904353bc 100644 --- a/desmume/src/cocoa/OGLDisplayOutput.h +++ b/desmume/src/cocoa/OGLDisplayOutput.h @@ -150,7 +150,7 @@ public: GLsizei GetSrcHeight(); GLsizei GetDstWidth(); GLsizei GetDstHeight(); - void SetSrcSizeOGL(GLsizei w, GLsizei h); + virtual void SetSrcSizeOGL(GLsizei w, GLsizei h); GLfloat GetScale(); void SetScaleOGL(GLfloat scale); virtual GLuint RunFilterOGL(GLuint srcTexID); @@ -166,6 +166,7 @@ public: OGLFilterDeposterize(GLsizei srcWidth, GLsizei srcHeight, ShaderSupportTier theTier, bool useShader150); ~OGLFilterDeposterize(); + virtual void SetSrcSizeOGL(GLsizei w, GLsizei h); virtual GLuint RunFilterOGL(GLuint srcTexID); }; @@ -264,7 +265,7 @@ public: void SetSourceDeposterize(bool useDeposterize); bool CanUseShaderBasedFilters(); - void GetNormalSize(double *w, double *h); + void GetNormalSize(double &w, double &h); int GetOutputFilter(); virtual void SetOutputFilterOGL(const int filterID); @@ -287,6 +288,7 @@ protected: ShaderSupportTier _shaderSupport; bool _needUploadVertices; + bool _needUploadTexCoords; bool _useDeposterize; bool _useShaderBasedPixelScaler; bool _filtersPreferGPU; @@ -307,7 +309,9 @@ protected: VideoFilter *_vf[2]; VideoFilter *_vfDual; GLuint _texCPUFilterDstID[2]; - + + uint16_t _displayWidth; + uint16_t _displayHeight; int _displayMode; int _displayOrder; int _displayOrientation; @@ -335,6 +339,7 @@ protected: void UploadHQnxLUTs(); + virtual 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); virtual void UploadVerticesOGL(); virtual void UploadTexCoordsOGL(); virtual void UploadTransformationOGL(); @@ -350,6 +355,9 @@ public: bool GetFiltersPreferGPU(); void SetFiltersPreferGPUOGL(bool preferGPU); + uint16_t GetDisplayWidth(); + uint16_t GetDisplayHeight(); + void SetDisplaySize(uint16_t w, uint16_t h); int GetMode(); void SetMode(int dispMode); int GetOrientation(); @@ -364,7 +372,7 @@ public: void SetSourceDeposterize(bool useDeposterize); bool CanUseShaderBasedFilters(); - void GetNormalSize(double *w, double *h); + void GetNormalSize(double &w, double &h); int GetOutputFilter(); virtual void SetOutputFilterOGL(const int filterID); diff --git a/desmume/src/cocoa/cocoa_GPU.h b/desmume/src/cocoa/cocoa_GPU.h index 5576dd1ca..505950ff4 100644 --- a/desmume/src/cocoa/cocoa_GPU.h +++ b/desmume/src/cocoa/cocoa_GPU.h @@ -19,10 +19,17 @@ #include #include +enum GPUType +{ + DS_GPU_TYPE_MAIN = 0, + DS_GPU_TYPE_SUB, + DS_GPU_TYPE_MAIN_AND_SUB +}; @interface CocoaDSGPU : NSObject { UInt32 gpuStateFlags; + uint8_t _gpuScale; BOOL isCPUCoreCountAuto; OSSpinLock spinlockGpuState; @@ -30,6 +37,8 @@ } @property (assign) UInt32 gpuStateFlags; +@property (assign) NSSize gpuDimensions; +@property (assign) NSUInteger gpuScale; @property (assign) pthread_rwlock_t *rwlockProducer; @property (assign) BOOL layerMainGPU; @@ -71,21 +80,23 @@ extern "C" #endif void GPU_FillScreenWithBGRA5551(const uint16_t colorValue); -void SetGPULayerState(const int gpuType, const unsigned int i, const bool state); -bool GetGPULayerState(const int gpuType, const unsigned int i); -void SetGPUDisplayState(const int gpuType, const bool state); -bool GetGPUDisplayState(const int gpuType); +void SetGPULayerState(const GPUType gpuType, const unsigned int i, const bool state); +bool GetGPULayerState(const GPUType gpuType, const unsigned int i); +void SetGPUDisplayState(const GPUType gpuType, const bool state); +bool GetGPUDisplayState(const GPUType gpuType); bool OSXOpenGLRendererInit(); bool OSXOpenGLRendererBegin(); void OSXOpenGLRendererEnd(); +bool OSXOpenGLRendererFramebufferDidResize(size_t w, size_t h); bool CreateOpenGLRenderer(); void DestroyOpenGLRenderer(); void RequestOpenGLRenderer_3_2(bool request_3_2); void SetOpenGLRendererFunctions(bool (*initFunction)(), bool (*beginOGLFunction)(), - void (*endOGLFunction)()); + void (*endOGLFunction)(), + bool (*resizeOGLFunction)(size_t w, size_t h)); #ifdef __cplusplus } diff --git a/desmume/src/cocoa/cocoa_GPU.mm b/desmume/src/cocoa/cocoa_GPU.mm index 0b6a20b1b..0948fa735 100644 --- a/desmume/src/cocoa/cocoa_GPU.mm +++ b/desmume/src/cocoa/cocoa_GPU.mm @@ -43,6 +43,8 @@ GPU3DInterface *core3DList[] = { @implementation CocoaDSGPU @dynamic gpuStateFlags; +@dynamic gpuDimensions; +@dynamic gpuScale; @synthesize rwlockProducer; @dynamic layerMainGPU; @@ -81,6 +83,7 @@ GPU3DInterface *core3DList[] = { spinlockGpuState = OS_SPINLOCK_INIT; rwlockProducer = NULL; + _gpuScale = 1; gpuStateFlags = GPUSTATE_MAIN_GPU_MASK | GPUSTATE_MAIN_BG0_MASK | GPUSTATE_MAIN_BG1_MASK | @@ -95,10 +98,11 @@ GPU3DInterface *core3DList[] = { GPUSTATE_SUB_OBJ_MASK; isCPUCoreCountAuto = NO; - + SetOpenGLRendererFunctions(&OSXOpenGLRendererInit, &OSXOpenGLRendererBegin, - &OSXOpenGLRendererEnd); + &OSXOpenGLRendererEnd, + &OSXOpenGLRendererFramebufferDidResize); GPU_FillScreenWithBGRA5551(0x8000); @@ -143,6 +147,33 @@ GPU3DInterface *core3DList[] = { return flags; } +- (void) setGpuDimensions:(NSSize)theDimensions +{ + pthread_rwlock_wrlock(self.rwlockProducer); + GPU_SetFramebufferSize(theDimensions.width, theDimensions.height); + pthread_rwlock_unlock(self.rwlockProducer); +} + +- (NSSize) gpuDimensions +{ + pthread_rwlock_rdlock(self.rwlockProducer); + const NSSize dimensions = NSMakeSize(GPU_GetFramebufferWidth(), GPU_GetFramebufferHeight()); + pthread_rwlock_unlock(self.rwlockProducer); + + return dimensions; +} + +- (void) setGpuScale:(NSUInteger)theScale +{ + _gpuScale = (uint8_t)theScale; + [self setGpuDimensions:NSMakeSize(GPU_DISPLAY_WIDTH * theScale, GPU_DISPLAY_HEIGHT * theScale)]; +} + +- (NSUInteger) gpuScale +{ + return (NSUInteger)_gpuScale; +} + - (void) setRender3DRenderingEngine:(NSInteger)methodID { pthread_rwlock_wrlock(self.rwlockProducer); @@ -694,12 +725,12 @@ GPU3DInterface *core3DList[] = { @end -void SetGPULayerState(const int gpuType, const unsigned int i, const bool state) +void SetGPULayerState(const GPUType gpuType, const unsigned int i, const bool state) { GPU *theGpu = NULL; // Check bounds on the layer index. - if(i > 4) + if (i > 4) { return; } @@ -736,12 +767,12 @@ void SetGPULayerState(const int gpuType, const unsigned int i, const bool state) } } -bool GetGPULayerState(const int gpuType, const unsigned int i) +bool GetGPULayerState(const GPUType gpuType, const unsigned int i) { bool theState = false; // Check bounds on the layer index. - if(i > 4) + if (i > 4) { return theState; } @@ -776,7 +807,7 @@ bool GetGPULayerState(const int gpuType, const unsigned int i) return theState; } -void SetGPUDisplayState(const int gpuType, const bool state) +void SetGPUDisplayState(const GPUType gpuType, const bool state) { switch (gpuType) { @@ -798,7 +829,7 @@ void SetGPUDisplayState(const int gpuType, const bool state) } } -bool GetGPUDisplayState(const int gpuType) +bool GetGPUDisplayState(const GPUType gpuType) { bool theState = false; @@ -825,20 +856,20 @@ bool GetGPUDisplayState(const int gpuType) void GPU_FillScreenWithBGRA5551(const uint16_t colorValue) { - const size_t pixCount = sizeof(GPU_screen) / sizeof(uint16_t); + const size_t pixCount = GPU_GetFramebufferWidth() * GPU_GetFramebufferHeight() * 2; #ifdef __APPLE__ if (pixCount % 16 == 0) { const uint16_t colorValuePattern[] = {colorValue, colorValue, colorValue, colorValue, colorValue, colorValue, colorValue, colorValue}; - memset_pattern16(GPU_screen, colorValuePattern, sizeof(GPU_screen)); + memset_pattern16(GPU_screen, colorValuePattern, pixCount * sizeof(uint16_t)); } else #endif { for (size_t i = 0; i < pixCount; i++) { - ((uint16_t *)GPU_screen)[i] = colorValue; + GPU_screen[i] = colorValue; } } } @@ -870,13 +901,46 @@ void OSXOpenGLRendererEnd() } +bool OSXOpenGLRendererFramebufferDidResize(size_t w, size_t h) +{ + bool result = false; + CGLPBufferObj newPBuffer = NULL; + + if (OGLCreateRenderer_3_2_Func != NULL) + { + result = true; + return result; + } + + // Create a PBuffer for legacy contexts since the availability of FBOs + // is not guaranteed. + CGLCreatePBuffer(w, h, GL_TEXTURE_2D, GL_RGBA, 0, &newPBuffer); + + if (newPBuffer == NULL) + { + return result; + } + else + { + GLint virtualScreenID = 0; + CGLGetVirtualScreen(OSXOpenGLRendererContext, &virtualScreenID); + CGLSetPBuffer(OSXOpenGLRendererContext, newPBuffer, 0, 0, virtualScreenID); + } + + CGLPBufferObj oldPBuffer = OSXOpenGLRendererPBuffer; + OSXOpenGLRendererPBuffer = newPBuffer; + CGLReleasePBuffer(oldPBuffer); + + result = true; + return result; +} + bool CreateOpenGLRenderer() { bool result = false; bool useContext_3_2 = false; CGLPixelFormatObj cglPixFormat = NULL; CGLContextObj newContext = NULL; - CGLPBufferObj newPBuffer = NULL; GLint virtualScreenCount = 0; CGLPixelFormatAttribute attrs[] = { @@ -916,29 +980,8 @@ bool CreateOpenGLRenderer() CGLCreateContext(cglPixFormat, NULL, &newContext); CGLReleasePixelFormat(cglPixFormat); - // Create a PBuffer for legacy contexts since the availability of FBOs - // is not guaranteed. - if (!useContext_3_2) - { - CGLCreatePBuffer(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, GL_TEXTURE_2D, GL_RGBA, 0, &newPBuffer); - - if (newPBuffer == NULL) - { - CGLReleaseContext(newContext); - return result; - } - else - { - GLint virtualScreenID = 0; - - CGLGetVirtualScreen(newContext, &virtualScreenID); - CGLSetPBuffer(newContext, newPBuffer, 0, 0, virtualScreenID); - } - } - RequestOpenGLRenderer_3_2(useContext_3_2); OSXOpenGLRendererContext = newContext; - OSXOpenGLRendererPBuffer = newPBuffer; result = true; return result; @@ -973,9 +1016,11 @@ void RequestOpenGLRenderer_3_2(bool request_3_2) void SetOpenGLRendererFunctions(bool (*initFunction)(), bool (*beginOGLFunction)(), - void (*endOGLFunction)()) + void (*endOGLFunction)(), + bool (*resizeOGLFunction)(size_t w, size_t h)) { oglrender_init = initFunction; oglrender_beginOpenGL = beginOGLFunction; oglrender_endOpenGL = endOGLFunction; + oglrender_framebufferDidResizeCallback = resizeOGLFunction; } diff --git a/desmume/src/cocoa/cocoa_globals.h b/desmume/src/cocoa/cocoa_globals.h index 60f87409e..b1b3701b9 100644 --- a/desmume/src/cocoa/cocoa_globals.h +++ b/desmume/src/cocoa/cocoa_globals.h @@ -202,10 +202,9 @@ #define GPU_DISPLAY_WIDTH 256 #define GPU_DISPLAY_HEIGHT 192 #define GPU_DISPLAY_COLOR_DEPTH sizeof(UInt16) -#define GPU_SCREEN_SIZE_BYTES (GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT * GPU_DISPLAY_COLOR_DEPTH) // The numbers are: 256px width, 192px height, 16bit color depth #define DS_DISPLAY_VERTICAL_GAP_TO_HEIGHT_RATIO (21.0/46.0) // Based on the official DS specification: 21mm/46mm -#define DS_DISPLAY_GAP (GPU_DISPLAY_HEIGHT * DS_DISPLAY_VERTICAL_GAP_TO_HEIGHT_RATIO) +#define DS_DISPLAY_UNSCALED_GAP (GPU_DISPLAY_HEIGHT * DS_DISPLAY_VERTICAL_GAP_TO_HEIGHT_RATIO) #define WINDOW_STATUS_BAR_HEIGHT 24 // Height of an emulation window status bar in pixels. @@ -486,16 +485,6 @@ enum DS_DISPLAY_ORDER_TOUCH_FIRST }; -/* - DS GPU TYPES - */ -enum -{ - DS_GPU_TYPE_MAIN = 0, - DS_GPU_TYPE_SUB, - DS_GPU_TYPE_MAIN_AND_SUB -}; - /* COCOA DS CORE STATES */ diff --git a/desmume/src/cocoa/cocoa_output.h b/desmume/src/cocoa/cocoa_output.h index 3aee00f1c..fde92b55e 100644 --- a/desmume/src/cocoa/cocoa_output.h +++ b/desmume/src/cocoa/cocoa_output.h @@ -37,7 +37,6 @@ typedef struct typedef struct { uint16_t *buffer; // Pointer to frame buffer - size_t bufferSize; // Size (in bytes) of frame buffer int32_t displayModeID; // The selected display to read from uint16_t width; // Measured in pixels uint16_t height; // Measured in pixels @@ -118,6 +117,9 @@ typedef struct @required - (void) doDisplayModeChanged:(NSInteger)displayModeID; +@optional +- (void) doDisplaySizeChanged:(NSSize)displaySize; + @end @protocol CocoaDSDisplayVideoDelegate @@ -141,16 +143,18 @@ typedef struct @interface CocoaDSDisplay : CocoaDSOutput { id delegate; + NSSize displaySize; NSInteger displayMode; - NSSize frameSize; GPUFrame _gpuFrame; + size_t _gpuCurrentWidth; + size_t _gpuCurrentHeight; OSSpinLock spinlockDisplayType; } @property (retain) id delegate; +@property (readonly) NSSize displaySize; @property (assign) NSInteger displayMode; -@property (readonly) NSSize frameSize; - (void) handleChangeDisplayMode:(NSData *)displayModeData; - (void) handleRequestScreenshot:(NSData *)fileURLStringData fileTypeData:(NSData *)fileTypeData; diff --git a/desmume/src/cocoa/cocoa_output.mm b/desmume/src/cocoa/cocoa_output.mm index 24548d39f..9ef76612e 100644 --- a/desmume/src/cocoa/cocoa_output.mm +++ b/desmume/src/cocoa/cocoa_output.mm @@ -503,8 +503,8 @@ @implementation CocoaDSDisplay @synthesize delegate; +@dynamic displaySize; @dynamic displayMode; -@dynamic frameSize; - (id)init @@ -519,13 +519,14 @@ delegate = nil; displayMode = DS_DISPLAY_TYPE_DUAL; - frameSize = NSMakeSize((CGFloat)GPU_DISPLAY_WIDTH, (CGFloat)GPU_DISPLAY_HEIGHT * 2); _gpuFrame.buffer = (uint16_t *)GPU_screen; - _gpuFrame.bufferSize = GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT * 2 * sizeof(uint16_t); _gpuFrame.displayModeID = DS_DISPLAY_TYPE_DUAL; - _gpuFrame.width = frameSize.width; - _gpuFrame.height = frameSize.height; + _gpuFrame.width = GPU_DISPLAY_WIDTH; + _gpuFrame.height = GPU_DISPLAY_HEIGHT * 2; + + _gpuCurrentWidth = GPU_DISPLAY_WIDTH; + _gpuCurrentHeight = GPU_DISPLAY_HEIGHT; [property setValue:[NSNumber numberWithInteger:displayMode] forKey:@"displayMode"]; [property setValue:NSSTRING_DISPLAYMODE_MAIN forKey:@"displayModeString"]; @@ -540,10 +541,18 @@ [super dealloc]; } +- (NSSize) displaySize +{ + OSSpinLockLock(&spinlockDisplayType); + NSSize size = NSMakeSize((CGFloat)GPU_GetFramebufferWidth(), (displayMode == DS_DISPLAY_TYPE_DUAL) ? (CGFloat)(GPU_GetFramebufferHeight() * 2): (CGFloat)GPU_GetFramebufferHeight()); + OSSpinLockUnlock(&spinlockDisplayType); + + return size; +} + - (void) setDisplayMode:(NSInteger)displayModeID { NSString *newDispString = nil; - NSSize newFrameSize = NSMakeSize((CGFloat)GPU_DISPLAY_WIDTH, (CGFloat)GPU_DISPLAY_HEIGHT); switch (displayModeID) { @@ -557,7 +566,6 @@ case DS_DISPLAY_TYPE_DUAL: newDispString = NSSTRING_DISPLAYMODE_DUAL; - newFrameSize.height *= 2; break; default: @@ -567,7 +575,6 @@ OSSpinLockLock(&spinlockDisplayType); displayMode = displayModeID; - frameSize = newFrameSize; [property setValue:[NSNumber numberWithInteger:displayModeID] forKey:@"displayMode"]; [property setValue:newDispString forKey:@"displayModeString"]; OSSpinLockUnlock(&spinlockDisplayType); @@ -582,15 +589,6 @@ return displayModeID; } -- (NSSize) frameSize -{ - OSSpinLockLock(&spinlockDisplayType); - NSSize size = frameSize; - OSSpinLockUnlock(&spinlockDisplayType); - - return size; -} - - (void)handlePortMessage:(NSPortMessage *)portMessage { NSInteger message = (NSInteger)[portMessage msgid]; @@ -618,29 +616,23 @@ - (void) handleEmuFrameProcessed { - _gpuFrame.displayModeID = [self displayMode]; - _gpuFrame.width = [self frameSize].width; - _gpuFrame.height = [self frameSize].height; + const uint16_t newGpuWidth = GPU_GetFramebufferWidth(); + const uint16_t newGpuHeight = GPU_GetFramebufferHeight(); - switch (_gpuFrame.displayModeID) + _gpuFrame.buffer = (uint16_t *)GPU_screen; + _gpuFrame.displayModeID = [self displayMode]; + _gpuFrame.width = newGpuWidth; + _gpuFrame.height = (_gpuFrame.displayModeID == DS_DISPLAY_TYPE_DUAL) ? newGpuHeight * 2 : newGpuHeight; + + if (newGpuWidth != _gpuCurrentWidth || newGpuHeight != _gpuCurrentHeight) { - case DS_DISPLAY_TYPE_MAIN: - _gpuFrame.buffer = (uint16_t *)GPU_screen; - _gpuFrame.bufferSize = GPU_SCREEN_SIZE_BYTES; - break; - - case DS_DISPLAY_TYPE_TOUCH: - _gpuFrame.buffer = (uint16_t *)GPU_screen + (GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT); - _gpuFrame.bufferSize = GPU_SCREEN_SIZE_BYTES; - break; - - case DS_DISPLAY_TYPE_DUAL: - _gpuFrame.buffer = (uint16_t *)GPU_screen; - _gpuFrame.bufferSize = GPU_SCREEN_SIZE_BYTES * 2; - break; - - default: - break; + if (delegate != nil && [delegate respondsToSelector:@selector(doDisplaySizeChanged:)]) + { + [(id)delegate doDisplaySizeChanged:NSMakeSize(newGpuWidth, newGpuHeight)]; + } + + _gpuCurrentWidth = newGpuWidth; + _gpuCurrentHeight = newGpuHeight; } [super handleEmuFrameProcessed]; @@ -655,7 +647,7 @@ const NSInteger displayModeID = *(NSInteger *)[displayModeData bytes]; [self setDisplayMode:displayModeID]; - [delegate doDisplayModeChanged:displayModeID]; + [(id)delegate doDisplayModeChanged:displayModeID]; } - (void) handleRequestScreenshot:(NSData *)fileURLStringData fileTypeData:(NSData *)fileTypeData @@ -691,7 +683,7 @@ - (NSImage *) image { - NSImage *newImage = [[NSImage alloc] initWithSize:self.frameSize]; + NSImage *newImage = [[NSImage alloc] initWithSize:[self displaySize]]; if (newImage == nil) { return newImage; @@ -719,7 +711,7 @@ return nil; } - NSSize srcSize = self.frameSize; + NSSize srcSize = [self displaySize]; NSUInteger w = (NSUInteger)srcSize.width; NSUInteger h = (NSUInteger)srcSize.height; NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL diff --git a/desmume/src/cocoa/userinterface/DisplayWindowController.h b/desmume/src/cocoa/userinterface/DisplayWindowController.h index f9670fc21..57cf43d48 100644 --- a/desmume/src/cocoa/userinterface/DisplayWindowController.h +++ b/desmume/src/cocoa/userinterface/DisplayWindowController.h @@ -91,7 +91,6 @@ class OGLVideoOutput; NSScreen *assignedScreen; NSWindow *masterWindow; - NSSize _normalSize; double _displayScale; double _displayRotation; NSInteger _displayMode; @@ -105,7 +104,6 @@ class OGLVideoOutput; NSUInteger _statusBarHeight; BOOL _isWindowResizing; - OSSpinLock spinlockNormalSize; OSSpinLock spinlockScale; OSSpinLock spinlockRotation; OSSpinLock spinlockDisplayMode; diff --git a/desmume/src/cocoa/userinterface/DisplayWindowController.mm b/desmume/src/cocoa/userinterface/DisplayWindowController.mm index b49187b9d..5528c998d 100644 --- a/desmume/src/cocoa/userinterface/DisplayWindowController.mm +++ b/desmume/src/cocoa/userinterface/DisplayWindowController.mm @@ -95,7 +95,6 @@ static std::unordered_map _screenMap; // assignedScreen = nil; masterWindow = nil; - spinlockNormalSize = OS_SPINLOCK_INIT; spinlockScale = OS_SPINLOCK_INIT; spinlockRotation = OS_SPINLOCK_INIT; spinlockDisplayMode = OS_SPINLOCK_INIT; @@ -110,7 +109,7 @@ static std::unordered_map _screenMap; // _displayMode = DS_DISPLAY_TYPE_DUAL; _displayOrientation = DS_DISPLAY_ORIENTATION_VERTICAL; - _minDisplayViewSize = NSMakeSize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT*2.0 + (DS_DISPLAY_GAP*_displayGap)); + _minDisplayViewSize = NSMakeSize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT*2.0 + (DS_DISPLAY_UNSCALED_GAP*_displayGap)); _isMinSizeNormal = YES; _statusBarHeight = WINDOW_STATUS_BAR_HEIGHT; _isWindowResizing = NO; @@ -140,15 +139,6 @@ static std::unordered_map _screenMap; // #pragma mark Dynamic Property Methods -- (NSSize) normalSize -{ - OSSpinLockLock(&spinlockNormalSize); - const NSSize theSize = _normalSize; - OSSpinLockUnlock(&spinlockNormalSize); - - return theSize; -} - - (void) setDisplayScale:(double)s { if (_isWindowResizing) @@ -240,7 +230,6 @@ static std::unordered_map _screenMap; // - (void) setDisplayMode:(NSInteger)displayModeID { - NSSize newDisplaySize = NSMakeSize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT); NSString *modeString = @"Unknown"; switch (displayModeID) @@ -254,21 +243,8 @@ static std::unordered_map _screenMap; // break; case DS_DISPLAY_TYPE_DUAL: - { - const double gapScalar = [self displayGap]; modeString = NSSTRING_DISPLAYMODE_DUAL; - - if ([self displayOrientation] == DS_DISPLAY_ORIENTATION_VERTICAL) - { - newDisplaySize.height = newDisplaySize.height * 2.0 + (DS_DISPLAY_GAP * gapScalar); - } - else - { - newDisplaySize.width = newDisplaySize.width * 2.0 + (DS_DISPLAY_GAP * gapScalar); - } - break; - } default: break; @@ -278,10 +254,6 @@ static std::unordered_map _screenMap; // _displayMode = displayModeID; OSSpinLockUnlock(&spinlockDisplayMode); - OSSpinLockLock(&spinlockNormalSize); - _normalSize = newDisplaySize; - OSSpinLockUnlock(&spinlockNormalSize); - [self setIsMinSizeNormal:[self isMinSizeNormal]]; [self resizeWithTransform:[self normalSize] scalar:[self displayScale] rotation:[self displayRotation]]; @@ -305,22 +277,6 @@ static std::unordered_map _screenMap; // if ([self displayMode] == DS_DISPLAY_TYPE_DUAL) { - const double gapScalar = [self displayGap]; - NSSize newDisplaySize = NSMakeSize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT); - - if (theOrientation == DS_DISPLAY_ORIENTATION_VERTICAL) - { - newDisplaySize.height = newDisplaySize.height * 2.0 + (DS_DISPLAY_GAP * gapScalar); - } - else - { - newDisplaySize.width = newDisplaySize.width * 2.0 + (DS_DISPLAY_GAP * gapScalar); - } - - OSSpinLockLock(&spinlockNormalSize); - _normalSize = newDisplaySize; - OSSpinLockUnlock(&spinlockNormalSize); - [self setIsMinSizeNormal:[self isMinSizeNormal]]; [self resizeWithTransform:[self normalSize] scalar:[self displayScale] rotation:[self displayRotation]]; } @@ -363,21 +319,6 @@ static std::unordered_map _screenMap; // if ([self displayMode] == DS_DISPLAY_TYPE_DUAL) { - NSSize newDisplaySize = NSMakeSize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT); - - if ([self displayOrientation] == DS_DISPLAY_ORIENTATION_VERTICAL) - { - newDisplaySize.height = newDisplaySize.height * 2.0 + (DS_DISPLAY_GAP * gapScalar); - } - else - { - newDisplaySize.width = newDisplaySize.width * 2.0 + (DS_DISPLAY_GAP * gapScalar); - } - - OSSpinLockLock(&spinlockNormalSize); - _normalSize = newDisplaySize; - OSSpinLockUnlock(&spinlockNormalSize); - [self setIsMinSizeNormal:[self isMinSizeNormal]]; [self resizeWithTransform:[self normalSize] scalar:[self displayScale] rotation:[self displayRotation]]; } @@ -450,13 +391,13 @@ static std::unordered_map _screenMap; // { if ([self displayOrientation] == DS_DISPLAY_ORIENTATION_HORIZONTAL) { - _minDisplayViewSize.width = GPU_DISPLAY_WIDTH*2.0 + (DS_DISPLAY_GAP*gapScalar); + _minDisplayViewSize.width = GPU_DISPLAY_WIDTH*2.0 + (DS_DISPLAY_UNSCALED_GAP*gapScalar); _minDisplayViewSize.height = GPU_DISPLAY_HEIGHT; } else { _minDisplayViewSize.width = GPU_DISPLAY_WIDTH; - _minDisplayViewSize.height = GPU_DISPLAY_HEIGHT*2.0 + (DS_DISPLAY_GAP*gapScalar); + _minDisplayViewSize.height = GPU_DISPLAY_HEIGHT*2.0 + (DS_DISPLAY_UNSCALED_GAP*gapScalar); } } else @@ -544,6 +485,25 @@ static std::unordered_map _screenMap; // [[self view] setUseVerticalSync:[[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayView_UseVerticalSync"]]; } +- (NSSize) normalSize +{ + NSSize normalSize = NSMakeSize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT); + + if ([self displayMode] == DS_DISPLAY_TYPE_DUAL) + { + if ([self displayOrientation] == DS_DISPLAY_ORIENTATION_VERTICAL) + { + normalSize.height = GPU_DISPLAY_HEIGHT * 2.0 + (DS_DISPLAY_UNSCALED_GAP * _displayGap); + } + else + { + normalSize.width = GPU_DISPLAY_WIDTH * 2.0 + (DS_DISPLAY_UNSCALED_GAP * _displayGap); + } + } + + return normalSize; +} + - (double) resizeWithTransform:(NSSize)normalBounds scalar:(double)scalar rotation:(double)angleDegrees { if ([self assignedScreen] != nil) @@ -1534,7 +1494,7 @@ static std::unordered_map _screenMap; // { const NSInteger theOrientation = [windowController displayOrientation]; const NSInteger theOrder = [windowController displayOrder]; - const double gap = DS_DISPLAY_GAP * [windowController displayGap]; + const double gap = DS_DISPLAY_UNSCALED_GAP * [windowController displayGap]; if (theOrientation == DS_DISPLAY_ORIENTATION_VERTICAL && theOrder == DS_DISPLAY_ORDER_TOUCH_FIRST) { @@ -1861,6 +1821,13 @@ static std::unordered_map _screenMap; // CGLUnlockContext(cglDisplayContext); } +- (void)doDisplaySizeChanged:(NSSize)displaySize +{ + OGLDisplayLayer *display = oglv->GetDisplayLayer(); + display->SetDisplaySize((uint16_t)displaySize.width, (uint16_t)displaySize.height); + [self doRedraw]; +} + - (void)doDisplayModeChanged:(NSInteger)displayModeID { OGLDisplayLayer *display = oglv->GetDisplayLayer();