From ce494a2eaa9265ae4be9c99d9967d03a24f1d23f Mon Sep 17 00:00:00 2001 From: rogerman Date: Mon, 2 Jan 2017 22:39:25 -0800 Subject: [PATCH] Cocoa Port: Begin refactoring display view code to reduce the dependence on port-specific code. --- .../src/frontend/cocoa/ClientDisplayView.cpp | 508 ++++++++++++++++++ .../src/frontend/cocoa/ClientDisplayView.h | 118 ++++ .../project.pbxproj | 10 + .../project.pbxproj | 14 + .../src/frontend/cocoa/OGLDisplayOutput.cpp | 156 +++--- desmume/src/frontend/cocoa/OGLDisplayOutput.h | 28 +- desmume/src/frontend/cocoa/cocoa_GPU.mm | 4 +- desmume/src/frontend/cocoa/cocoa_globals.h | 9 +- .../src/frontend/cocoa/openemu/NDSGameCore.mm | 20 +- .../userinterface/DisplayWindowController.h | 23 +- .../userinterface/DisplayWindowController.mm | 329 ++++-------- .../cocoa/userinterface/appDelegate.mm | 12 +- desmume/src/frontend/cocoa/utilities.c | 262 +-------- desmume/src/frontend/cocoa/utilities.h | 15 +- 14 files changed, 859 insertions(+), 649 deletions(-) create mode 100644 desmume/src/frontend/cocoa/ClientDisplayView.cpp create mode 100644 desmume/src/frontend/cocoa/ClientDisplayView.h diff --git a/desmume/src/frontend/cocoa/ClientDisplayView.cpp b/desmume/src/frontend/cocoa/ClientDisplayView.cpp new file mode 100644 index 000000000..a62cc1205 --- /dev/null +++ b/desmume/src/frontend/cocoa/ClientDisplayView.cpp @@ -0,0 +1,508 @@ +/* + Copyright (C) 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 + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the this software. If not, see . + */ + +#include "ClientDisplayView.h" + +ClientDisplayView::ClientDisplayView() +{ + _property.normalWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH; + _property.normalHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2.0; + _property.clientWidth = _property.normalWidth; + _property.clientHeight = _property.normalHeight; + _property.rotation = 0.0; + _property.viewScale = 1.0; + _property.gapScale = 0.0; + _property.gapDistance = DS_DISPLAY_UNSCALED_GAP * _property.gapScale; + _property.mode = ClientDisplayMode_Dual; + _property.layout = ClientDisplayLayout_Vertical; + _property.order = ClientDisplayOrder_MainFirst; + + _initialTouchInMajorDisplay = new InitialTouchPressMap; +} + +ClientDisplayView::ClientDisplayView(const ClientDisplayViewProperties props) +{ + _property = props; + _initialTouchInMajorDisplay = new InitialTouchPressMap; +} + +ClientDisplayView::~ClientDisplayView() +{ + delete _initialTouchInMajorDisplay; +} + +ClientDisplayViewProperties ClientDisplayView::GetProperties() const +{ + return this->_property; +} + +void ClientDisplayView::SetProperties(const ClientDisplayViewProperties props) +{ + this->_property = props; + + ClientDisplayView::CalculateNormalSize(props.mode, props.layout, props.gapScale, this->_property.normalWidth, this->_property.normalHeight); +} + +void ClientDisplayView::SetClientSize(const double w, const double h) +{ + this->_property.clientWidth = w; + this->_property.clientHeight = h; + this->_property.viewScale = ClientDisplayView::GetMaxScalarWithinBounds(this->_property.normalWidth, this->_property.normalHeight, w, h); +} + +double ClientDisplayView::GetRotation() const +{ + return this->_property.rotation; +} + +void ClientDisplayView::SetRotation(const double r) +{ + this->_property.rotation = r; + + double checkWidth = this->_property.normalWidth; + double checkHeight = this->_property.normalHeight; + ClientDisplayView::ConvertNormalToTransformedBounds(1.0, r, checkWidth, checkHeight); + this->_property.viewScale = ClientDisplayView::GetMaxScalarWithinBounds(checkWidth, checkHeight, this->_property.clientWidth, this->_property.clientHeight); +} + +double ClientDisplayView::GetViewScale() const +{ + return this->_property.viewScale; +} + +ClientDisplayMode ClientDisplayView::GetMode() const +{ + return this->_property.mode; +} + +void ClientDisplayView::SetMode(const ClientDisplayMode mode) +{ + this->_property.mode = mode; + ClientDisplayView::CalculateNormalSize(this->_property.mode, this->_property.layout, this->_property.gapScale, this->_property.normalWidth, this->_property.normalHeight); + this->_property.viewScale = ClientDisplayView::GetMaxScalarWithinBounds(this->_property.normalWidth, this->_property.normalHeight, this->_property.clientWidth, this->_property.clientHeight); +} + +ClientDisplayLayout ClientDisplayView::GetLayout() const +{ + return this->_property.layout; +} + +void ClientDisplayView::SetLayout(const ClientDisplayLayout layout) +{ + this->_property.layout = layout; + ClientDisplayView::CalculateNormalSize(this->_property.mode, this->_property.layout, this->_property.gapScale, this->_property.normalWidth, this->_property.normalHeight); + this->_property.viewScale = ClientDisplayView::GetMaxScalarWithinBounds(this->_property.normalWidth, this->_property.normalHeight, this->_property.clientWidth, this->_property.clientHeight); +} + +ClientDisplayOrder ClientDisplayView::GetOrder() const +{ + return this->_property.order; +} + +void ClientDisplayView::SetOrder(const ClientDisplayOrder order) +{ + this->_property.order = order; +} + +double ClientDisplayView::GetGapScale() const +{ + return this->_property.gapScale; +} + +void ClientDisplayView::SetGapWithScalar(const double gapScale) +{ + this->_property.gapScale = gapScale; + this->_property.gapDistance = (double)DS_DISPLAY_UNSCALED_GAP * gapScale; +} + +double ClientDisplayView::GetGapDistance() const +{ + return this->_property.gapDistance; +} + +void ClientDisplayView::SetGapWithDistance(const double gapDistance) +{ + this->_property.gapScale = gapDistance / (double)DS_DISPLAY_UNSCALED_GAP; + this->_property.gapDistance = gapDistance; +} + +void ClientDisplayView::GetNDSPoint(const int inputID, const bool isInitialTouchPress, + const double clientX, const double clientY, + u8 &outX, u8 &outY) const +{ + double x = clientX; + double y = clientY; + double w = this->_property.normalWidth; + double h = this->_property.normalHeight; + + ClientDisplayView::ConvertNormalToTransformedBounds(1.0, this->_property.rotation, w, h); + const double s = ClientDisplayView::GetMaxScalarWithinBounds(w, h, this->_property.clientWidth, this->_property.clientHeight); + + ClientDisplayView::ConvertClientToNormalPoint(this->_property.normalWidth, this->_property.normalHeight, + this->_property.clientWidth, this->_property.clientHeight, + s, + 360.0 - this->_property.rotation, + x, y); + + // Normalize the touch location to the DS. + if (this->_property.mode == ClientDisplayMode_Dual) + { + switch (this->_property.layout) + { + case ClientDisplayLayout_Horizontal: + { + if (this->_property.order == ClientDisplayOrder_MainFirst) + { + x -= GPU_FRAMEBUFFER_NATIVE_WIDTH; + } + break; + } + + case ClientDisplayLayout_Hybrid_3_2: + case ClientDisplayLayout_Hybrid_16_9: + case ClientDisplayLayout_Hybrid_16_10: + { + if (isInitialTouchPress) + { + const bool isClickWithinMajorDisplay = (this->_property.order == ClientDisplayOrder_TouchFirst) && (x >= 0.0) && (x < 256.0); + (*_initialTouchInMajorDisplay)[inputID] = isClickWithinMajorDisplay; + } + + const bool handleClickInMajorDisplay = (*_initialTouchInMajorDisplay)[inputID]; + if (!handleClickInMajorDisplay) + { + const double minorDisplayScale = (this->_property.normalWidth - (double)GPU_FRAMEBUFFER_NATIVE_WIDTH) / (double)GPU_FRAMEBUFFER_NATIVE_WIDTH; + x = (x - GPU_FRAMEBUFFER_NATIVE_WIDTH) / minorDisplayScale; + y = y / minorDisplayScale; + } + break; + } + + default: // Default to vertical orientation. + { + if (this->_property.order == ClientDisplayOrder_TouchFirst) + { + y -= ((double)GPU_FRAMEBUFFER_NATIVE_HEIGHT + this->_property.gapDistance); + } + break; + } + } + } + + y = GPU_FRAMEBUFFER_NATIVE_HEIGHT - y; + + // Constrain the touch point to the DS dimensions. + if (x < 0.0) + { + x = 0.0; + } + else if (x > (GPU_FRAMEBUFFER_NATIVE_WIDTH - 1.0)) + { + x = (GPU_FRAMEBUFFER_NATIVE_WIDTH - 1.0); + } + + if (y < 0.0) + { + y = 0.0; + } + else if (y > (GPU_FRAMEBUFFER_NATIVE_HEIGHT - 1.0)) + { + y = (GPU_FRAMEBUFFER_NATIVE_HEIGHT - 1.0); + } + + outX = (u8)(x + 0.001); + outY = (u8)(y + 0.001); +} + +/******************************************************************************************** + ConvertNormalToTransformedBounds() + + Returns the bounds of a normalized 2D surface using affine transformations. + + Takes: + scalar - The scalar used to transform the 2D surface. + angleDegrees - The rotation angle, in degrees, to transform the 2D surface. + inoutWidth - The width of the normal 2D surface. + inoutHeight - The height of the normal 2D surface. + + Returns: + The bounds of a normalized 2D surface using affine transformations. + + Details: + The returned bounds is always a normal rectangle. Ignoring the scaling, the + returned bounds will always be at its smallest when the angle is at 0, 90, 180, + or 270 degrees, and largest when the angle is at 45, 135, 225, or 315 degrees. + ********************************************************************************************/ +void ClientDisplayView::ConvertNormalToTransformedBounds(const double scalar, + const double angleDegrees, + double &inoutWidth, double &inoutHeight) +{ + const double angleRadians = angleDegrees * (M_PI/180.0); + + // The points are as follows: + // + // (x[3], y[3]) (x[2], y[2]) + // + // + // + // (x[0], y[0]) (x[1], y[1]) + + // Do our scale and rotate transformations. +#ifdef __ACCELERATE__ + + // Note that although we only need to calculate 3 points, we include 4 points + // here because Accelerate prefers 16-byte alignment. + double x[] = {0.0, inoutWidth, inoutWidth, 0.0}; + double y[] = {0.0, 0.0, inoutHeight, inoutHeight}; + + cblas_drot(4, x, 1, y, 1, scalar * cos(angleRadians), scalar * sin(angleRadians)); + +#else // Keep a C-version of this transformation for reference purposes. + + const double w = scalar * inoutWidth; + const double h = scalar * inoutHeight; + const double d = hypot(w, h); + const double dAngle = atan2(h, w); + + const double px = w * cos(angleRadians); + const double py = w * sin(angleRadians); + const double qx = d * cos(dAngle + angleRadians); + const double qy = d * sin(dAngle + angleRadians); + const double rx = h * cos((M_PI/2.0) + angleRadians); + const double ry = h * sin((M_PI/2.0) + angleRadians); + + const double x[] = {0.0, px, qx, rx}; + const double y[] = {0.0, py, qy, ry}; + +#endif + + // Determine the transformed width, which is dependent on the location of + // the x-coordinate of point (x[2], y[2]). + if (x[2] > 0.0) + { + if (x[2] < x[3]) + { + inoutWidth = x[3] - x[1]; + } + else if (x[2] < x[1]) + { + inoutWidth = x[1] - x[3]; + } + else + { + inoutWidth = x[2]; + } + } + else if (x[2] < 0.0) + { + if (x[2] > x[3]) + { + inoutWidth = -(x[3] - x[1]); + } + else if (x[2] > x[1]) + { + inoutWidth = -(x[1] - x[3]); + } + else + { + inoutWidth = -x[2]; + } + } + else + { + inoutWidth = fabs(x[1] - x[3]); + } + + // Determine the transformed height, which is dependent on the location of + // the y-coordinate of point (x[2], y[2]). + if (y[2] > 0.0) + { + if (y[2] < y[3]) + { + inoutHeight = y[3] - y[1]; + } + else if (y[2] < y[1]) + { + inoutHeight = y[1] - y[3]; + } + else + { + inoutHeight = y[2]; + } + } + else if (y[2] < 0.0) + { + if (y[2] > y[3]) + { + inoutHeight = -(y[3] - y[1]); + } + else if (y[2] > y[1]) + { + inoutHeight = -(y[1] - y[3]); + } + else + { + inoutHeight = -y[2]; + } + } + else + { + inoutHeight = fabs(y[3] - y[1]); + } +} + +/******************************************************************************************** + GetMaxScalarWithinBounds() + + Returns the maximum scalar that a rectangle can grow, while maintaining its aspect + ratio, within a boundary. + + Takes: + normalBoundsWidth - The width of the normal 2D surface. + normalBoundsHeight - The height of the normal 2D surface. + keepInBoundsWidth - The width of the keep-in 2D surface. + keepInBoundsHeight - The height of the keep-in 2D surface. + + Returns: + The maximum scalar that a rectangle can grow, while maintaining its aspect ratio, + within a boundary. + + Details: + If keepInBoundsWidth or keepInBoundsHeight are less than or equal to zero, the + returned scalar will be zero. + ********************************************************************************************/ +double ClientDisplayView::GetMaxScalarWithinBounds(const double normalBoundsWidth, const double normalBoundsHeight, + const double keepInBoundsWidth, const double keepInBoundsHeight) +{ + const double maxX = (normalBoundsWidth <= 0.0) ? 0.0 : keepInBoundsWidth / normalBoundsWidth; + const double maxY = (normalBoundsHeight <= 0.0) ? 0.0 : keepInBoundsHeight / normalBoundsHeight; + + return (maxX <= maxY) ? maxX : maxY; +} + +/******************************************************************************************** + ConvertClientToNormalPoint() + + Returns a normalized point from a point from a 2D transformed surface. + + Takes: + normalWidth - The width of the normal 2D surface. + normalHeight - The height of the normal 2D surface. + clientWidth - The width of the client 2D surface. + clientHeight - The height of the client 2D surface. + scalar - The scalar used on the transformed 2D surface. + angleDegrees - The rotation angle, in degrees, of the transformed 2D surface. + inoutX - The X coordinate of a 2D point as it exists on a 2D transformed surface. + inoutY - The Y coordinate of a 2D point as it exists on a 2D transformed surface. + + Returns: + A normalized point from a point from a 2D transformed surface. + + Details: + It may help to call GetMaxScalarWithinBounds() for the scalar parameter. + ********************************************************************************************/ +void ClientDisplayView::ConvertClientToNormalPoint(const double normalWidth, const double normalHeight, + const double clientWidth, const double clientHeight, + const double scalar, + const double angleDegrees, + double &inoutX, double &inoutY) +{ + // Get the coordinates of the client point and translate the coordinate + // system so that the origin becomes the center. + const double clientX = inoutX - (clientWidth / 2.0); + const double clientY = inoutY - (clientHeight / 2.0); + + // Perform rect-polar conversion. + + // Get the radius r with respect to the origin. + const double r = hypot(clientX, clientY) / scalar; + + // Get the angle theta with respect to the origin. + double theta = 0.0; + + if (clientX == 0.0) + { + if (clientY > 0.0) + { + theta = M_PI / 2.0; + } + else if (clientY < 0.0) + { + theta = M_PI * 1.5; + } + } + else if (clientX < 0.0) + { + theta = M_PI - atan2(clientY, -clientX); + } + else if (clientY < 0.0) + { + theta = atan2(clientY, clientX) + (M_PI * 2.0); + } + else + { + theta = atan2(clientY, clientX); + } + + // Get the normalized angle and use it to rotate about the origin. + // Then do polar-rect conversion and translate back to normal coordinates + // with a 0 degree rotation. + const double angleRadians = angleDegrees * (M_PI/180.0); + const double normalizedAngle = theta - angleRadians; + inoutX = (r * cos(normalizedAngle)) + (normalWidth / 2.0); + inoutY = (r * sin(normalizedAngle)) + (normalHeight / 2.0); +} + +void ClientDisplayView::CalculateNormalSize(const ClientDisplayMode mode, const ClientDisplayLayout layout, const double gapScale, + double &outWidth, double &outHeight) +{ + if (mode == ClientDisplayMode_Dual) + { + switch (layout) + { + case ClientDisplayLayout_Horizontal: + outWidth = (double)GPU_FRAMEBUFFER_NATIVE_WIDTH*2.0; + outHeight = (double)GPU_FRAMEBUFFER_NATIVE_HEIGHT; + break; + + case ClientDisplayLayout_Hybrid_3_2: + outWidth = (double)GPU_FRAMEBUFFER_NATIVE_WIDTH + (128.0); + outHeight = (double)GPU_FRAMEBUFFER_NATIVE_HEIGHT; + break; + + case ClientDisplayLayout_Hybrid_16_9: + outWidth = (double)GPU_FRAMEBUFFER_NATIVE_WIDTH + (64.0 * 4.0 / 3.0); + outHeight = (double)GPU_FRAMEBUFFER_NATIVE_HEIGHT; + break; + + case ClientDisplayLayout_Hybrid_16_10: + outWidth = (double)GPU_FRAMEBUFFER_NATIVE_WIDTH + (51.2); + outHeight = (double)GPU_FRAMEBUFFER_NATIVE_HEIGHT; + break; + + default: // Default to vertical orientation. + outWidth = (double)GPU_FRAMEBUFFER_NATIVE_WIDTH; + outHeight = (double)GPU_FRAMEBUFFER_NATIVE_HEIGHT*2.0 + (DS_DISPLAY_UNSCALED_GAP*gapScale); + break; + } + } + else + { + outWidth = (double)GPU_FRAMEBUFFER_NATIVE_WIDTH; + outHeight = (double)GPU_FRAMEBUFFER_NATIVE_HEIGHT; + } +} diff --git a/desmume/src/frontend/cocoa/ClientDisplayView.h b/desmume/src/frontend/cocoa/ClientDisplayView.h new file mode 100644 index 000000000..e6eb7ee83 --- /dev/null +++ b/desmume/src/frontend/cocoa/ClientDisplayView.h @@ -0,0 +1,118 @@ +/* + Copyright (C) 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 + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the this software. If not, see . + */ + +#ifndef _CLIENT_DISPLAY_VIEW_H_ +#define _CLIENT_DISPLAY_VIEW_H_ + +#include +#include "../../GPU.h" + +#define DS_DISPLAY_VERTICAL_GAP_TO_HEIGHT_RATIO (21.0/46.0) // Based on the official DS specification: 21mm/46mm +#define DS_DISPLAY_UNSCALED_GAP (GPU_FRAMEBUFFER_NATIVE_HEIGHT * DS_DISPLAY_VERTICAL_GAP_TO_HEIGHT_RATIO) + +enum ClientDisplayMode +{ + ClientDisplayMode_Main = 0, + ClientDisplayMode_Touch, + ClientDisplayMode_Dual +}; + +enum ClientDisplayLayout +{ + ClientDisplayLayout_Vertical = 0, + ClientDisplayLayout_Horizontal = 1, + ClientDisplayLayout_Hybrid_3_2 = 1000, + ClientDisplayLayout_Hybrid_16_9 = 1001, + ClientDisplayLayout_Hybrid_16_10 = 1002 +}; + +enum ClientDisplayOrder +{ + ClientDisplayOrder_MainFirst = 0, + ClientDisplayOrder_TouchFirst +}; + +typedef std::map InitialTouchPressMap; // Key = An ID number of the host input, Value = Flag that indicates if the initial touch press was in the major display + +typedef struct +{ + double normalWidth; + double normalHeight; + double clientWidth; + double clientHeight; + double rotation; + double viewScale; + double gapScale; + double gapDistance; + ClientDisplayMode mode; + ClientDisplayLayout layout; + ClientDisplayOrder order; +} ClientDisplayViewProperties; + +class ClientDisplayView +{ +protected: + ClientDisplayViewProperties _property; + InitialTouchPressMap *_initialTouchInMajorDisplay; + +public: + ClientDisplayView(); + ClientDisplayView(const ClientDisplayViewProperties props); + ~ClientDisplayView(); + + ClientDisplayViewProperties GetProperties() const; + void SetProperties(const ClientDisplayViewProperties properties); + + void SetClientSize(const double w, const double h); + + double GetRotation() const; + void SetRotation(const double r); + double GetViewScale() const; + ClientDisplayMode GetMode() const; + void SetMode(const ClientDisplayMode mode); + ClientDisplayLayout GetLayout() const; + void SetLayout(const ClientDisplayLayout layout); + ClientDisplayOrder GetOrder() const; + void SetOrder(const ClientDisplayOrder order); + + double GetGapScale() const; + void SetGapWithScalar(const double gapScale); + double GetGapDistance() const; + void SetGapWithDistance(const double gapDistance); + + void GetNDSPoint(const int inputID, const bool isInitialTouchPress, + const double clientX, const double clientY, + u8 &outX, u8 &outY) const; + + static void ConvertNormalToTransformedBounds(const double scalar, + const double angleDegrees, + double &inoutWidth, double &inoutHeight); + + static double GetMaxScalarWithinBounds(const double normalBoundsWidth, const double normalBoundsHeight, + const double keepInBoundsWidth, const double keepInBoundsHeight); + + static void ConvertClientToNormalPoint(const double normalBoundsWidth, const double normalBoundsHeight, + const double transformBoundsWidth, const double transformBoundsHeight, + const double scalar, + const double angleDegrees, + double &inoutX, double &inoutY); + + static void CalculateNormalSize(const ClientDisplayMode mode, const ClientDisplayLayout layout, const double gapScale, + double &outWidth, double &outHeight); +}; + +#endif // _CLIENT_DISPLAY_VIEW_H_ diff --git a/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj b/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj index f07c0c034..2874a4020 100644 --- a/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj +++ b/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj @@ -835,6 +835,9 @@ ABACB8DC1710B621003B845D /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABACB8DB1710B621003B845D /* AudioToolbox.framework */; }; ABACB8DD1710B656003B845D /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABACB8DB1710B621003B845D /* AudioToolbox.framework */; }; ABACB8DE1710B65F003B845D /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABACB8DB1710B621003B845D /* AudioToolbox.framework */; }; + ABAD07DC1E19CAA6007867CA /* ClientDisplayView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABAD07DA1E19CAA6007867CA /* ClientDisplayView.cpp */; }; + ABAD07DD1E19CAA6007867CA /* ClientDisplayView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABAD07DA1E19CAA6007867CA /* ClientDisplayView.cpp */; }; + ABAD07DE1E19CAA6007867CA /* ClientDisplayView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABAD07DA1E19CAA6007867CA /* ClientDisplayView.cpp */; }; ABAD3E7113AF1D6D00502E1E /* AAFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABAD3E6513AF1D6D00502E1E /* AAFilter.cpp */; }; ABAD3E7413AF1D6D00502E1E /* FIFOSampleBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABAD3E6813AF1D6D00502E1E /* FIFOSampleBuffer.cpp */; }; ABAD3E7513AF1D6D00502E1E /* FIRFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABAD3E6913AF1D6D00502E1E /* FIRFilter.cpp */; }; @@ -1499,6 +1502,8 @@ ABA731671BB51FDC00B26147 /* type1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = type1.c; path = type1/type1.c; sourceTree = ""; }; ABAB454E187CDB70007BE20C /* Image_GuitarGrip.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Image_GuitarGrip.png; path = images/Image_GuitarGrip.png; sourceTree = ""; }; ABACB8DB1710B621003B845D /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + ABAD07DA1E19CAA6007867CA /* ClientDisplayView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClientDisplayView.cpp; sourceTree = ""; }; + ABAD07DB1E19CAA6007867CA /* ClientDisplayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientDisplayView.h; sourceTree = ""; }; ABAD3E5913AF1D6D00502E1E /* AAFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AAFilter.h; sourceTree = ""; }; ABAD3E5A13AF1D6D00502E1E /* BPMDetect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BPMDetect.h; sourceTree = ""; }; ABAD3E5B13AF1D6D00502E1E /* cpu_detect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu_detect.h; sourceTree = ""; }; @@ -1953,6 +1958,7 @@ AB3ACB6514C2361100D7D192 /* userinterface */, AB82445A1704AE9A00B8EE20 /* utilities.c */, ABD10AE51715FCDD00B5729D /* audiosamplegenerator.cpp */, + ABAD07DA1E19CAA6007867CA /* ClientDisplayView.cpp */, AB1B9E5F1501A78000464647 /* coreaudiosound.cpp */, AB23567216C2F6F400DA782E /* macosx_10_5_compat.cpp */, ABD10AE61715FCDD00B5729D /* mic_ext.cpp */, @@ -1961,6 +1967,7 @@ AB1B9E601501A78000464647 /* ringbuffer.cpp */, ABD104141346652500AF11D1 /* sndOSX.cpp */, ABD10AE31715FCDD00B5729D /* audiosamplegenerator.h */, + ABAD07DB1E19CAA6007867CA /* ClientDisplayView.h */, ABA6574914511EC90077E5E9 /* cocoa_cheat.h */, ABD103FE1346652500AF11D1 /* cocoa_core.h */, AB58F32B1364F44B0074C376 /* cocoa_file.h */, @@ -3781,6 +3788,7 @@ AB6FBEF6139B6258007BB045 /* slot1_retail_nand.cpp in Sources */, ABCFA9F5178BDE920030C8BA /* encrypt.cpp in Sources */, ABD1FF0E1345AC9C00AF11D1 /* slot2_expMemory.cpp in Sources */, + ABAD07DE1E19CAA6007867CA /* ClientDisplayView.cpp in Sources */, ABD1FF0F1345AC9C00AF11D1 /* slot2_gbagame.cpp in Sources */, ABD1FF101345AC9C00AF11D1 /* slot2_guitarGrip.cpp in Sources */, AB000DD21CCC6B3A00413F02 /* file_path.c in Sources */, @@ -3938,6 +3946,7 @@ ABFEA8341BB4EC1100B08C25 /* ftmm.c in Sources */, AB4C81E41B21676C00ACECD5 /* hq3x.cpp in Sources */, AB796CF815CDCBA200C59155 /* cp15.cpp in Sources */, + ABAD07DC1E19CAA6007867CA /* ClientDisplayView.cpp in Sources */, AB796CF915CDCBA200C59155 /* cpu_detect_x86_gcc.cpp in Sources */, AB796CFA15CDCBA200C59155 /* crc.cpp in Sources */, AB301BDF1D9C8BAC00246A93 /* deposterize.cpp in Sources */, @@ -4266,6 +4275,7 @@ AB8F3CD11A53AC2600A80BF6 /* slot2_passme.cpp in Sources */, AB8F3CD21A53AC2600A80BF6 /* WavFile.cpp in Sources */, AB8F3CD31A53AC2600A80BF6 /* wifi.cpp in Sources */, + ABAD07DD1E19CAA6007867CA /* ClientDisplayView.cpp in Sources */, AB8F3CD41A53AC2600A80BF6 /* slot1_retail_mcrom.cpp in Sources */, AB8F3CD51A53AC2600A80BF6 /* xstring.cpp in Sources */, AB8F3CD61A53AC2600A80BF6 /* main.m in Sources */, diff --git a/desmume/src/frontend/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj b/desmume/src/frontend/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj index f2af3f413..52abb1722 100644 --- a/desmume/src/frontend/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj +++ b/desmume/src/frontend/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj @@ -262,6 +262,11 @@ AB081A091B4E64AE008CE1EC /* Icon_VolumeMute_16x16@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AB0819E61B4E64AE008CE1EC /* Icon_VolumeMute_16x16@2x.png */; }; AB081A0A1B4E64AE008CE1EC /* Icon_VolumeOneThird_16x16@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AB0819E71B4E64AE008CE1EC /* Icon_VolumeOneThird_16x16@2x.png */; }; AB081A0B1B4E64AE008CE1EC /* Icon_VolumeTwoThird_16x16@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AB0819E81B4E64AE008CE1EC /* Icon_VolumeTwoThird_16x16@2x.png */; }; + AB0F13921E1B7C320075684F /* ClientDisplayView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB0F13911E1B7C320075684F /* ClientDisplayView.cpp */; }; + AB0F13931E1B7C320075684F /* ClientDisplayView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB0F13911E1B7C320075684F /* ClientDisplayView.cpp */; }; + AB0F13941E1B7C320075684F /* ClientDisplayView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB0F13911E1B7C320075684F /* ClientDisplayView.cpp */; }; + AB0F13951E1B7C320075684F /* ClientDisplayView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB0F13911E1B7C320075684F /* ClientDisplayView.cpp */; }; + AB0F13961E1B7C320075684F /* ClientDisplayView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB0F13911E1B7C320075684F /* ClientDisplayView.cpp */; }; AB0F290614BE6E68009ABC6F /* Icon_Execute_420x420.png in Resources */ = {isa = PBXBuildFile; fileRef = AB0F28FE14BE6E68009ABC6F /* Icon_Execute_420x420.png */; }; AB0F290714BE6E68009ABC6F /* Icon_Pause_420x420.png in Resources */ = {isa = PBXBuildFile; fileRef = AB0F28FF14BE6E68009ABC6F /* Icon_Pause_420x420.png */; }; AB0F290814BE6E68009ABC6F /* Icon_Speed1x_420x420.png in Resources */ = {isa = PBXBuildFile; fileRef = AB0F290014BE6E68009ABC6F /* Icon_Speed1x_420x420.png */; }; @@ -1782,6 +1787,8 @@ AB0819E71B4E64AE008CE1EC /* Icon_VolumeOneThird_16x16@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon_VolumeOneThird_16x16@2x.png"; path = "images/Icon_VolumeOneThird_16x16@2x.png"; sourceTree = ""; }; AB0819E81B4E64AE008CE1EC /* Icon_VolumeTwoThird_16x16@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon_VolumeTwoThird_16x16@2x.png"; path = "images/Icon_VolumeTwoThird_16x16@2x.png"; sourceTree = ""; }; AB0A0D1914AACA9600E83E91 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; + AB0F13901E1B7C320075684F /* ClientDisplayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientDisplayView.h; sourceTree = ""; }; + AB0F13911E1B7C320075684F /* ClientDisplayView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClientDisplayView.cpp; sourceTree = ""; }; AB0F28FE14BE6E68009ABC6F /* Icon_Execute_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Execute_420x420.png; path = images/Icon_Execute_420x420.png; sourceTree = ""; }; AB0F28FF14BE6E68009ABC6F /* Icon_Pause_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Pause_420x420.png; path = images/Icon_Pause_420x420.png; sourceTree = ""; }; AB0F290014BE6E68009ABC6F /* Icon_Speed1x_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Speed1x_420x420.png; path = images/Icon_Speed1x_420x420.png; sourceTree = ""; }; @@ -2345,12 +2352,14 @@ AB3ACB6514C2361100D7D192 /* userinterface */, AB2F56EF1704C86900E28885 /* utilities.c */, AB2145221714DFF4006DDB0F /* audiosamplegenerator.cpp */, + AB0F13911E1B7C320075684F /* ClientDisplayView.cpp */, ABD0A5341501AA5A0074A094 /* coreaudiosound.cpp */, ABD9A46413DB99B300777194 /* mic_ext.cpp */, ABECB51318A460910052D52A /* OGLDisplayOutput.cpp */, ABD0A5351501AA5A0074A094 /* ringbuffer.cpp */, ABD104141346652500AF11D1 /* sndOSX.cpp */, AB2145211714DFF4006DDB0F /* audiosamplegenerator.h */, + AB0F13901E1B7C320075684F /* ClientDisplayView.h */, ABA6574914511EC90077E5E9 /* cocoa_cheat.h */, ABD103FE1346652500AF11D1 /* cocoa_core.h */, AB58F32B1364F44B0074C376 /* cocoa_file.h */, @@ -4529,6 +4538,7 @@ ABD21B5C1DE900D3001D2DFA /* Database.cpp in Sources */, ABD21B631DE9010B001D2DFA /* features_cpu.c in Sources */, AB2C25081DEBFBD400706BFC /* encoding_utf.c in Sources */, + AB0F13931E1B7C320075684F /* ClientDisplayView.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4710,6 +4720,7 @@ ABD21B5D1DE900D3001D2DFA /* Database.cpp in Sources */, ABD21B641DE9010B001D2DFA /* features_cpu.c in Sources */, AB2C25091DEBFBD400706BFC /* encoding_utf.c in Sources */, + AB0F13941E1B7C320075684F /* ClientDisplayView.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4921,6 +4932,7 @@ ABD21B5B1DE900D3001D2DFA /* Database.cpp in Sources */, ABD21B621DE9010B001D2DFA /* features_cpu.c in Sources */, AB2C25071DEBFBD400706BFC /* encoding_utf.c in Sources */, + AB0F13921E1B7C320075684F /* ClientDisplayView.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5132,6 +5144,7 @@ ABD21B5F1DE900D3001D2DFA /* Database.cpp in Sources */, ABD21B661DE9010B001D2DFA /* features_cpu.c in Sources */, AB2C250B1DEBFBD400706BFC /* encoding_utf.c in Sources */, + AB0F13961E1B7C320075684F /* ClientDisplayView.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5313,6 +5326,7 @@ ABD21B5E1DE900D3001D2DFA /* Database.cpp in Sources */, ABD21B651DE9010B001D2DFA /* features_cpu.c in Sources */, AB2C250A1DEBFBD400706BFC /* encoding_utf.c in Sources */, + AB0F13951E1B7C320075684F /* ClientDisplayView.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp b/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp index 9981ced45..42f249a78 100644 --- a/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp +++ b/desmume/src/frontend/cocoa/OGLDisplayOutput.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2016 DeSmuME team + Copyright (C) 2014-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 @@ -5609,7 +5609,7 @@ void OGLImage::UploadTransformationOGL() { const double w = this->_viewportWidth; const double h = this->_viewportHeight; - const GLdouble s = GetMaxScalarInBounds(this->_normalWidth, this->_normalHeight, w, h); + const GLdouble s = ClientDisplayView::GetMaxScalarWithinBounds(this->_normalWidth, this->_normalHeight, w, h); if (this->_canUseShaderOutput) { @@ -6742,11 +6742,11 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO) _gapScalar = 0.0f; _rotation = 0.0f; - _normalWidth = GPU_DISPLAY_WIDTH; - _normalHeight = GPU_DISPLAY_HEIGHT*2.0 + (DS_DISPLAY_UNSCALED_GAP*_gapScalar); + _normalWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH; + _normalHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT*2.0 + (DS_DISPLAY_UNSCALED_GAP*_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(GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, VideoFilterTypeID_None, 0); + _vf[1] = new VideoFilter(GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, VideoFilterTypeID_None, 0); _vfMasterDstBuffer = (uint32_t *)calloc(_vf[0]->GetDstWidth() * (_vf[0]->GetDstHeight() + _vf[1]->GetDstHeight()), sizeof(uint32_t)); _vfMasterDstBufferSize = _vf[0]->GetDstWidth() * (_vf[0]->GetDstHeight() + _vf[1]->GetDstHeight()) * sizeof(uint32_t); @@ -6758,10 +6758,10 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO) _isTexVideoInputDataNative[0] = true; _isTexVideoInputDataNative[1] = true; - _texLoadedWidth[0] = (GLfloat)GPU_DISPLAY_WIDTH; - _texLoadedWidth[1] = (GLfloat)GPU_DISPLAY_WIDTH; - _texLoadedHeight[0] = (GLfloat)GPU_DISPLAY_HEIGHT; - _texLoadedHeight[1] = (GLfloat)GPU_DISPLAY_HEIGHT; + _texLoadedWidth[0] = (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; + _texLoadedWidth[1] = (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; + _texLoadedHeight[0] = (GLfloat)GPU_FRAMEBUFFER_NATIVE_HEIGHT; + _texLoadedHeight[1] = (GLfloat)GPU_FRAMEBUFFER_NATIVE_HEIGHT; _videoColorFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV; _videoSrcBufferHead = NULL; @@ -6769,10 +6769,10 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO) _videoSrcNativeBuffer[1] = NULL; _videoSrcCustomBuffer[0] = NULL; _videoSrcCustomBuffer[1] = NULL; - _videoSrcCustomBufferWidth[0] = GPU_DISPLAY_WIDTH; - _videoSrcCustomBufferWidth[1] = GPU_DISPLAY_WIDTH; - _videoSrcCustomBufferHeight[0] = GPU_DISPLAY_HEIGHT; - _videoSrcCustomBufferHeight[1] = GPU_DISPLAY_HEIGHT; + _videoSrcCustomBufferWidth[0] = GPU_FRAMEBUFFER_NATIVE_WIDTH; + _videoSrcCustomBufferWidth[1] = GPU_FRAMEBUFFER_NATIVE_WIDTH; + _videoSrcCustomBufferHeight[0] = GPU_FRAMEBUFFER_NATIVE_HEIGHT; + _videoSrcCustomBufferHeight[1] = GPU_FRAMEBUFFER_NATIVE_HEIGHT; // Set up textures glGenTextures(2, _texCPUFilterDstID); @@ -6800,28 +6800,28 @@ 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); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, _vf[0]->GetSrcBufferPtr()); + 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_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, _vf[1]->GetSrcBufferPtr()); + 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_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, _vf[0]->GetSrcBufferPtr()); + 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_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, _vf[1]->GetSrcBufferPtr()); + 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); @@ -7045,7 +7045,7 @@ void OGLDisplayLayer::SetVideoBuffers(const uint32_t colorFormat, this->_videoColorFormat = glColorFormat; this->_videoSrcBufferHead = videoBufferHead; - this->_videoSrcBufferSize = (GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT * 2 * pixelBytes) + (customWidth0 * customHeight0 * pixelBytes) + (customWidth1 * customHeight1 * pixelBytes); + this->_videoSrcBufferSize = (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * pixelBytes) + (customWidth0 * customHeight0 * pixelBytes) + (customWidth1 * customHeight1 * pixelBytes); this->_videoSrcNativeBuffer[0] = nativeBuffer0; this->_videoSrcNativeBuffer[1] = nativeBuffer1; this->_videoSrcCustomBuffer[0] = customBuffer0; @@ -7067,11 +7067,11 @@ void OGLDisplayLayer::SetVideoBuffers(const uint32_t colorFormat, 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_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, 0, GL_RGBA, this->_videoColorFormat, this->_videoSrcNativeBuffer[0]); + 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_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, 0, GL_RGBA, this->_videoColorFormat, this->_videoSrcNativeBuffer[1]); + 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); @@ -7124,7 +7124,7 @@ ClientDisplayMode OGLDisplayLayer::GetMode() const void OGLDisplayLayer::SetMode(const ClientDisplayMode dispMode) { this->_displayMode = dispMode; - OGLDisplayLayer::CalculateNormalSize(this->_displayMode, this->_displayOrientation, this->_gapScalar, this->_normalWidth, this->_normalHeight); + ClientDisplayView::CalculateNormalSize(this->_displayMode, this->_displayOrientation, this->_gapScalar, this->_normalWidth, this->_normalHeight); this->_needUpdateVertices = true; } @@ -7136,7 +7136,7 @@ ClientDisplayLayout OGLDisplayLayer::GetOrientation() const void OGLDisplayLayer::SetOrientation(ClientDisplayLayout dispOrientation) { this->_displayOrientation = dispOrientation; - OGLDisplayLayer::CalculateNormalSize(this->_displayMode, this->_displayOrientation, this->_gapScalar, this->_normalWidth, this->_normalHeight); + ClientDisplayView::CalculateNormalSize(this->_displayMode, this->_displayOrientation, this->_gapScalar, this->_normalWidth, this->_normalHeight); this->_needUpdateVertices = true; } @@ -7148,7 +7148,7 @@ double OGLDisplayLayer::GetGapScalar() const void OGLDisplayLayer::SetGapScalar(double theScalar) { this->_gapScalar = theScalar; - OGLDisplayLayer::CalculateNormalSize(this->_displayMode, this->_displayOrientation, this->_gapScalar, this->_normalWidth, this->_normalHeight); + ClientDisplayView::CalculateNormalSize(this->_displayMode, this->_displayOrientation, this->_gapScalar, this->_normalWidth, this->_normalHeight); this->_needUpdateVertices = true; } @@ -7214,20 +7214,20 @@ void OGLDisplayLayer::UpdateVerticesOGL() case ClientDisplayLayout_Hybrid_3_2: { - vtxBufferPtr[0] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[1] = -h + (96.0f * 2.0f); // Minor top display, top left + vtxBufferPtr[0] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[1] = -h + (96.0f * 2.0f); // Minor top display, top left vtxBufferPtr[2] = w; vtxBufferPtr[3] = -h + (96.0f * 2.0f); // Minor top display, top right - vtxBufferPtr[4] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[5] = -h + 96.0f; // Minor top display, bottom left + vtxBufferPtr[4] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[5] = -h + 96.0f; // Minor top display, bottom left vtxBufferPtr[6] = w; vtxBufferPtr[7] = -h + 96.0f; // Minor top display, bottom right - vtxBufferPtr[8] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[9] = -h + 96.0f; // Minor bottom display, top left + vtxBufferPtr[8] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[9] = -h + 96.0f; // Minor bottom display, top left vtxBufferPtr[10] = w; vtxBufferPtr[11] = -h + 96.0f; // Minor bottom display, top right - vtxBufferPtr[12] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[13] = -h; // Minor bottom display, bottom left + vtxBufferPtr[12] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[13] = -h; // Minor bottom display, bottom left vtxBufferPtr[14] = w; vtxBufferPtr[15] = -h; // Minor bottom display, bottom right vtxBufferPtr[16] = -w; vtxBufferPtr[17] = h; // Major display, top left - vtxBufferPtr[18] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[19] = h; // Major display, top right + vtxBufferPtr[18] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[19] = h; // Major display, top right vtxBufferPtr[20] = -w; vtxBufferPtr[21] = -h; // Major display, bottom left - vtxBufferPtr[22] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[23] = -h; // Major display, bottom right + vtxBufferPtr[22] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[23] = -h; // Major display, bottom right memcpy(vtxBufferPtr + (3 * 8), vtxBufferPtr + (2 * 8), sizeof(GLfloat) * (1 * 8)); // Major display (bottom screen) break; @@ -7235,22 +7235,22 @@ void OGLDisplayLayer::UpdateVerticesOGL() case ClientDisplayLayout_Hybrid_16_9: { - const GLfloat g = (GLfloat)DS_DISPLAY_UNSCALED_GAP * this->_gapScalar * (this->_normalWidth - (GLfloat)GPU_DISPLAY_WIDTH) / (GLfloat)GPU_DISPLAY_WIDTH; + const GLfloat g = (GLfloat)DS_DISPLAY_UNSCALED_GAP * this->_gapScalar * (this->_normalWidth - (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH) / (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; - vtxBufferPtr[0] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[1] = -h + g + (64.0f * 2.0f); // Minor top display, top left + vtxBufferPtr[0] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[1] = -h + g + (64.0f * 2.0f); // Minor top display, top left vtxBufferPtr[2] = w; vtxBufferPtr[3] = -h + g + (64.0f * 2.0f); // Minor top display, top right - vtxBufferPtr[4] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[5] = -h + g + 64.0f; // Minor top display, bottom left + vtxBufferPtr[4] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[5] = -h + g + 64.0f; // Minor top display, bottom left vtxBufferPtr[6] = w; vtxBufferPtr[7] = -h + g + 64.0f; // Minor top display, bottom right - vtxBufferPtr[8] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[9] = -h + 64.0f; // Minor bottom display, top left + vtxBufferPtr[8] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[9] = -h + 64.0f; // Minor bottom display, top left vtxBufferPtr[10] = w; vtxBufferPtr[11] = -h + 64.0f; // Minor bottom display, top right - vtxBufferPtr[12] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[13] = -h; // Minor bottom display, bottom left + vtxBufferPtr[12] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[13] = -h; // Minor bottom display, bottom left vtxBufferPtr[14] = w; vtxBufferPtr[15] = -h; // Minor bottom display, bottom right vtxBufferPtr[16] = -w; vtxBufferPtr[17] = h; // Major display, top left - vtxBufferPtr[18] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[19] = h; // Major display, top right + vtxBufferPtr[18] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[19] = h; // Major display, top right vtxBufferPtr[20] = -w; vtxBufferPtr[21] = -h; // Major display, bottom left - vtxBufferPtr[22] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[23] = -h; // Major display, bottom right + vtxBufferPtr[22] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[23] = -h; // Major display, bottom right memcpy(vtxBufferPtr + (3 * 8), vtxBufferPtr + (2 * 8), sizeof(GLfloat) * (1 * 8)); // Major display (bottom screen) break; @@ -7258,22 +7258,22 @@ void OGLDisplayLayer::UpdateVerticesOGL() case ClientDisplayLayout_Hybrid_16_10: { - const GLfloat g = (GLfloat)DS_DISPLAY_UNSCALED_GAP * this->_gapScalar * (this->_normalWidth - (GLfloat)GPU_DISPLAY_WIDTH) / (GLfloat)GPU_DISPLAY_WIDTH; + const GLfloat g = (GLfloat)DS_DISPLAY_UNSCALED_GAP * this->_gapScalar * (this->_normalWidth - (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH) / (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; - vtxBufferPtr[0] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[1] = -h + g + (38.4f * 2.0f); // Minor top display, top left + vtxBufferPtr[0] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[1] = -h + g + (38.4f * 2.0f); // Minor top display, top left vtxBufferPtr[2] = w; vtxBufferPtr[3] = -h + g + (38.4f * 2.0f); // Minor top display, top right - vtxBufferPtr[4] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[5] = -h + g + 38.4f; // Minor top display, bottom left + vtxBufferPtr[4] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[5] = -h + g + 38.4f; // Minor top display, bottom left vtxBufferPtr[6] = w; vtxBufferPtr[7] = -h + g + 38.4f; // Minor top display, bottom right - vtxBufferPtr[8] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[9] = -h + 38.4f; // Minor bottom display, top left + vtxBufferPtr[8] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[9] = -h + 38.4f; // Minor bottom display, top left vtxBufferPtr[10] = w; vtxBufferPtr[11] = -h + 38.4f; // Minor bottom display, top right - vtxBufferPtr[12] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[13] = -h; // Minor bottom display, bottom left + vtxBufferPtr[12] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[13] = -h; // Minor bottom display, bottom left vtxBufferPtr[14] = w; vtxBufferPtr[15] = -h; // Minor bottom display, bottom right vtxBufferPtr[16] = -w; vtxBufferPtr[17] = h; // Major display, top left - vtxBufferPtr[18] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[19] = h; // Major display, top right + vtxBufferPtr[18] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[19] = h; // Major display, top right vtxBufferPtr[20] = -w; vtxBufferPtr[21] = -h; // Major display, bottom left - vtxBufferPtr[22] = -w + (GLfloat)GPU_DISPLAY_WIDTH; vtxBufferPtr[23] = -h; // Major display, bottom right + vtxBufferPtr[22] = -w + (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH; vtxBufferPtr[23] = -h; // Major display, bottom right memcpy(vtxBufferPtr + (3 * 8), vtxBufferPtr + (2 * 8), sizeof(GLfloat) * (1 * 8)); // Major display (bottom screen) break; @@ -7374,8 +7374,11 @@ void OGLDisplayLayer::UploadTransformationOGL() { const GLdouble w = this->_viewportWidth; const GLdouble h = this->_viewportHeight; - const CGSize checkSize = GetTransformedBounds(this->_normalWidth, this->_normalHeight, 1.0, this->_rotation); - const GLdouble s = GetMaxScalarInBounds(checkSize.width, checkSize.height, w, h); + + double checkWidth = this->_normalWidth; + double checkHeight = this->_normalHeight; + ClientDisplayView::ConvertNormalToTransformedBounds(1.0, this->_rotation, checkWidth, checkHeight); + const GLdouble s = ClientDisplayView::GetMaxScalarWithinBounds(checkWidth, checkHeight, w, h); if (this->_output->GetInfo()->IsShaderSupported()) { @@ -7391,7 +7394,7 @@ void OGLDisplayLayer::UploadTransformationOGL() glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glRotatef(CLOCKWISE_DEGREES(this->_rotation), 0.0f, 0.0f, 1.0f); + glRotatef(this->_rotation, 0.0f, 0.0f, 1.0f); glScalef(s, s, 1.0f); } @@ -7802,10 +7805,10 @@ void OGLDisplayLayer::LoadFrameOGL(bool isMainSizeNative, bool isTouchSizeNative this->_isTexVideoInputDataNative[0] = isMainSizeNative; this->_isTexVideoInputDataNative[1] = isTouchSizeNative; - this->_texLoadedWidth[0] = (this->_isTexVideoInputDataNative[0]) ? (GLfloat)GPU_DISPLAY_WIDTH : (GLfloat)this->_videoSrcCustomBufferWidth[0]; - this->_texLoadedHeight[0] = (this->_isTexVideoInputDataNative[0]) ? (GLfloat)GPU_DISPLAY_HEIGHT : (GLfloat)this->_videoSrcCustomBufferHeight[0]; - this->_texLoadedWidth[1] = (this->_isTexVideoInputDataNative[1]) ? (GLfloat)GPU_DISPLAY_WIDTH : (GLfloat)this->_videoSrcCustomBufferWidth[1]; - this->_texLoadedHeight[1] = (this->_isTexVideoInputDataNative[1]) ? (GLfloat)GPU_DISPLAY_HEIGHT : (GLfloat)this->_videoSrcCustomBufferHeight[1]; + this->_texLoadedWidth[0] = (this->_isTexVideoInputDataNative[0]) ? (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH : (GLfloat)this->_videoSrcCustomBufferWidth[0]; + this->_texLoadedHeight[0] = (this->_isTexVideoInputDataNative[0]) ? (GLfloat)GPU_FRAMEBUFFER_NATIVE_HEIGHT : (GLfloat)this->_videoSrcCustomBufferHeight[0]; + this->_texLoadedWidth[1] = (this->_isTexVideoInputDataNative[1]) ? (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH : (GLfloat)this->_videoSrcCustomBufferWidth[1]; + this->_texLoadedHeight[1] = (this->_isTexVideoInputDataNative[1]) ? (GLfloat)GPU_FRAMEBUFFER_NATIVE_HEIGHT : (GLfloat)this->_videoSrcCustomBufferHeight[1]; if (loadMainScreen) { @@ -7824,7 +7827,7 @@ void OGLDisplayLayer::LoadFrameOGL(bool isMainSizeNative, bool isTouchSizeNative if (!isUsingCPUPixelScaler || this->_useDeposterize) { glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[0]); - glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, GL_RGBA, this->_videoColorFormat, this->_videoSrcNativeBuffer[0]); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, this->_videoColorFormat, this->_videoSrcNativeBuffer[0]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glFlush(); } @@ -7832,11 +7835,11 @@ void OGLDisplayLayer::LoadFrameOGL(bool isMainSizeNative, bool isTouchSizeNative { if (this->_videoColorFormat == GL_UNSIGNED_SHORT_1_5_5_5_REV) { - RGB555ToBGRA8888Buffer((const uint16_t *)this->_videoSrcNativeBuffer[0], this->_vf[0]->GetSrcBufferPtr(), GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT); + RGB555ToBGRA8888Buffer((const uint16_t *)this->_videoSrcNativeBuffer[0], this->_vf[0]->GetSrcBufferPtr(), GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); } else { - RGB888ToBGRA8888Buffer((const uint32_t *)this->_videoSrcNativeBuffer[0], this->_vf[0]->GetSrcBufferPtr(), GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT); + RGB888ToBGRA8888Buffer((const uint32_t *)this->_videoSrcNativeBuffer[0], this->_vf[0]->GetSrcBufferPtr(), GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); } } } @@ -7866,7 +7869,7 @@ void OGLDisplayLayer::LoadFrameOGL(bool isMainSizeNative, bool isTouchSizeNative if (!isUsingCPUPixelScaler || this->_useDeposterize) { glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[1]); - glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, GL_RGBA, this->_videoColorFormat, this->_videoSrcNativeBuffer[1]); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, this->_videoColorFormat, this->_videoSrcNativeBuffer[1]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glFlush(); } @@ -7874,11 +7877,11 @@ void OGLDisplayLayer::LoadFrameOGL(bool isMainSizeNative, bool isTouchSizeNative { if (this->_videoColorFormat == GL_UNSIGNED_SHORT_1_5_5_5_REV) { - RGB555ToBGRA8888Buffer((const uint16_t *)this->_videoSrcNativeBuffer[1], this->_vf[1]->GetSrcBufferPtr(), GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT); + RGB555ToBGRA8888Buffer((const uint16_t *)this->_videoSrcNativeBuffer[1], this->_vf[1]->GetSrcBufferPtr(), GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); } else { - RGB888ToBGRA8888Buffer((const uint32_t *)this->_videoSrcNativeBuffer[1], this->_vf[1]->GetSrcBufferPtr(), GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT); + RGB888ToBGRA8888Buffer((const uint32_t *)this->_videoSrcNativeBuffer[1], this->_vf[1]->GetSrcBufferPtr(), GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); } } } @@ -8097,42 +8100,3 @@ void OGLDisplayLayer::FinishOGL() glFinishObjectAPPLE(GL_TEXTURE_RECTANGLE_ARB, (isUsingCPUPixelScaler) ? this->_texCPUFilterDstID[0] : ( (this->_isTexVideoInputDataNative[0]) ? this->_texVideoInputDataNativeID[0] : this->_texVideoInputDataCustomID[0]) ); glFinishObjectAPPLE(GL_TEXTURE_RECTANGLE_ARB, (isUsingCPUPixelScaler) ? this->_texCPUFilterDstID[1] : ( (this->_isTexVideoInputDataNative[1]) ? this->_texVideoInputDataNativeID[1] : this->_texVideoInputDataCustomID[1]) ); } - -void OGLDisplayLayer::CalculateNormalSize(const ClientDisplayMode mode, const ClientDisplayLayout layout, const double gapScalar, double &outWidth, double &outHeight) -{ - if (mode == ClientDisplayMode_Dual) - { - switch (layout) - { - case ClientDisplayLayout_Horizontal: - outWidth = GPU_DISPLAY_WIDTH*2.0; - outHeight = GPU_DISPLAY_HEIGHT; - break; - - case ClientDisplayLayout_Hybrid_3_2: - outWidth = (float)GPU_DISPLAY_WIDTH + (128.0); - outHeight = GPU_DISPLAY_HEIGHT; - break; - - case ClientDisplayLayout_Hybrid_16_9: - outWidth = (float)GPU_DISPLAY_WIDTH + (64.0 * 4.0 / 3.0); - outHeight = GPU_DISPLAY_HEIGHT; - break; - - case ClientDisplayLayout_Hybrid_16_10: - outWidth = (float)GPU_DISPLAY_WIDTH + (51.2); - outHeight = GPU_DISPLAY_HEIGHT; - break; - - default: // Default to vertical orientation. - outWidth = GPU_DISPLAY_WIDTH; - outHeight = GPU_DISPLAY_HEIGHT*2.0 + (DS_DISPLAY_UNSCALED_GAP*gapScalar); - break; - } - } - else - { - outWidth = GPU_DISPLAY_WIDTH; - outHeight = GPU_DISPLAY_HEIGHT; - } -} diff --git a/desmume/src/frontend/cocoa/OGLDisplayOutput.h b/desmume/src/frontend/cocoa/OGLDisplayOutput.h index c1dcf8577..07d492ca3 100644 --- a/desmume/src/frontend/cocoa/OGLDisplayOutput.h +++ b/desmume/src/frontend/cocoa/OGLDisplayOutput.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2016 DeSmuME team + Copyright (C) 2014-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 @@ -31,6 +31,8 @@ #include #include "../../filter/videofilter.h" +#include "ClientDisplayView.h" + #include #include FT_FREETYPE_H @@ -43,28 +45,6 @@ class OGLVideoOutput; struct NDSFrameInfo; -enum ClientDisplayMode -{ - ClientDisplayMode_Main = 0, - ClientDisplayMode_Touch, - ClientDisplayMode_Dual -}; - -enum ClientDisplayLayout -{ - ClientDisplayLayout_Vertical = 0, - ClientDisplayLayout_Horizontal = 1, - ClientDisplayLayout_Hybrid_3_2 = 1000, - ClientDisplayLayout_Hybrid_16_9 = 1001, - ClientDisplayLayout_Hybrid_16_10 = 1002 -}; - -enum ClientDisplayOrder -{ - ClientDisplayOrder_MainFirst = 0, - ClientDisplayOrder_TouchFirst -}; - enum OutputFilterTypeID { OutputFilterTypeID_NearestNeighbor = 0, @@ -504,8 +484,6 @@ public: virtual void ProcessOGL(); virtual void RenderOGL(); virtual void FinishOGL(); - - static void CalculateNormalSize(const ClientDisplayMode mode, const ClientDisplayLayout layout, const double gapScalar, double &outWidth, double &outHeight); }; class OGLVideoOutput diff --git a/desmume/src/frontend/cocoa/cocoa_GPU.mm b/desmume/src/frontend/cocoa/cocoa_GPU.mm index 50d82fa77..e0813c28f 100644 --- a/desmume/src/frontend/cocoa/cocoa_GPU.mm +++ b/desmume/src/frontend/cocoa/cocoa_GPU.mm @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2016 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 @@ -216,7 +216,7 @@ public: - (void) setGpuScale:(NSUInteger)theScale { _gpuScale = (uint8_t)theScale; - [self setGpuDimensions:NSMakeSize(GPU_DISPLAY_WIDTH * theScale, GPU_DISPLAY_HEIGHT * theScale)]; + [self setGpuDimensions:NSMakeSize(GPU_FRAMEBUFFER_NATIVE_WIDTH * theScale, GPU_FRAMEBUFFER_NATIVE_HEIGHT * theScale)]; } - (NSUInteger) gpuScale diff --git a/desmume/src/frontend/cocoa/cocoa_globals.h b/desmume/src/frontend/cocoa/cocoa_globals.h index 9d4f04574..a52db5e73 100644 --- a/desmume/src/frontend/cocoa/cocoa_globals.h +++ b/desmume/src/frontend/cocoa/cocoa_globals.h @@ -1,6 +1,6 @@ /* Copyright (C) 2011 Roger Manuel - Copyright (C) 2012-2015 DeSmuME Team + Copyright (C) 2012-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 @@ -185,13 +185,6 @@ #define CHEAT_DESCRIPTION_LENGTH 1024 -#define GPU_DISPLAY_WIDTH 256 -#define GPU_DISPLAY_HEIGHT 192 -#define GPU_DISPLAY_COLOR_DEPTH sizeof(UInt16) - -#define DS_DISPLAY_VERTICAL_GAP_TO_HEIGHT_RATIO (21.0/46.0) // Based on the official DS specification: 21mm/46mm -#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. #define SPEED_SCALAR_QUARTER 0.25 // Speed scalar for quarter execution speed. diff --git a/desmume/src/frontend/cocoa/openemu/NDSGameCore.mm b/desmume/src/frontend/cocoa/openemu/NDSGameCore.mm index 570241ac0..e952f428f 100644 --- a/desmume/src/frontend/cocoa/openemu/NDSGameCore.mm +++ b/desmume/src/frontend/cocoa/openemu/NDSGameCore.mm @@ -115,7 +115,7 @@ volatile bool execute = true; // Set up the DS display displayMode = ClientDisplayMode_Dual; - displayRect = OEIntRectMake(0, 0, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT * 2); + displayRect = OEIntRectMake(0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2); displayAspectRatio = OEIntSizeMake(2, 3); return self; @@ -154,17 +154,17 @@ volatile bool execute = true; switch (theMode) { case ClientDisplayMode_Main: - newDisplayRect = OEIntRectMake(0, 0, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT); + newDisplayRect = OEIntRectMake(0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT); newDisplayAspectRatio = OEIntSizeMake(4, 3); break; case ClientDisplayMode_Touch: - newDisplayRect = OEIntRectMake(0, GPU_DISPLAY_HEIGHT + 1, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT); + newDisplayRect = OEIntRectMake(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT + 1, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT); newDisplayAspectRatio = OEIntSizeMake(4, 3); break; case ClientDisplayMode_Dual: - newDisplayRect = OEIntRectMake(0, 0, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT * 2); + newDisplayRect = OEIntRectMake(0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2); newDisplayAspectRatio = OEIntSizeMake(2, 3); break; @@ -280,7 +280,7 @@ volatile bool execute = true; - (OEIntSize)bufferSize { - return OEIntSizeMake(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT * 2); + return OEIntSizeMake(GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2); } - (const void *)videoBuffer @@ -396,7 +396,7 @@ volatile bool execute = true; case ClientDisplayMode_Dual: isTouchPressed = YES; - aPoint.y -= GPU_DISPLAY_HEIGHT; // Normalize the y-coordinate to the DS. + aPoint.y -= GPU_FRAMEBUFFER_NATIVE_HEIGHT; // Normalize the y-coordinate to the DS. break; default: @@ -409,18 +409,18 @@ volatile bool execute = true; { aPoint.x = 0; } - else if (aPoint.x > (GPU_DISPLAY_WIDTH - 1)) + else if (aPoint.x > (GPU_FRAMEBUFFER_NATIVE_WIDTH - 1)) { - aPoint.x = (GPU_DISPLAY_WIDTH - 1); + aPoint.x = (GPU_FRAMEBUFFER_NATIVE_WIDTH - 1); } if (aPoint.y < 0) { aPoint.y = 0; } - else if (aPoint.y > (GPU_DISPLAY_HEIGHT - 1)) + else if (aPoint.y > (GPU_FRAMEBUFFER_NATIVE_HEIGHT - 1)) { - aPoint.y = (GPU_DISPLAY_HEIGHT - 1); + aPoint.y = (GPU_FRAMEBUFFER_NATIVE_HEIGHT - 1); } touchLocation = NSMakePoint(aPoint.x, aPoint.y); diff --git a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.h b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.h index f1136aa4a..fae0db596 100644 --- a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.h +++ b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.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 @@ -23,12 +23,13 @@ #import "InputManager.h" #import "cocoa_output.h" +#include "../ClientDisplayView.h" +#undef BOOL + @class CocoaDSController; @class EmuControllerDelegate; class OGLVideoOutput; -typedef std::map InitialTouchPressMap; // Key = An ID number of the host input, Value = Flag that indicates if the initial touch press was in the major display - // Subclass NSWindow for full screen windows so that we can override some methods. @interface DisplayFullScreenWindow : NSWindow { } @@ -37,7 +38,7 @@ typedef std::map InitialTouchPressMap; // Key = An ID number of the @interface DisplayView : NSView { InputManager *inputManager; - InitialTouchPressMap *_initialTouchInMajorDisplay; + ClientDisplayView *_cdv; OGLVideoOutput *oglv; BOOL canUseShaderBasedFilters; @@ -56,7 +57,6 @@ typedef std::map InitialTouchPressMap; // Key = An ID number of the } @property (retain) InputManager *inputManager; -@property (readonly) NSSize normalSize; @property (readonly) BOOL canUseShaderBasedFilters; @property (assign) BOOL isHUDVisible; @property (assign) BOOL isHUDVideoFPSVisible; @@ -74,13 +74,10 @@ typedef std::map InitialTouchPressMap; // Key = An ID number of the - (void) setScaleFactor:(float)theScaleFactor; - (void) drawVideoFrame; - (NSPoint) dsPointFromEvent:(NSEvent *)theEvent inputID:(const NSInteger)inputID; -- (NSPoint) convertPointToDS:(NSPoint)clickLoc inputID:(const NSInteger)inputID initialTouchPress:(BOOL)isInitialTouchPress; - (BOOL) handleKeyPress:(NSEvent *)theEvent keyPressed:(BOOL)keyPressed; - (BOOL) handleMouseButton:(NSEvent *)theEvent buttonPressed:(BOOL)buttonPressed; - (void) requestScreenshot:(NSURL *)fileURL fileType:(NSBitmapImageFileType)fileType; -+ (NSSize) calculateNormalSizeUsingMode:(const NSInteger)mode layout:(const NSInteger)layout gapScalar:(const double)gapScalar; - @end #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 @@ -92,6 +89,7 @@ typedef std::map InitialTouchPressMap; // Key = An ID number of the NSObject *dummyObject; DisplayView *view; + ClientDisplayViewProperties _localViewProps; NSView *saveScreenshotPanelAccessoryView; NSView *outputVolumeControlView; NSView *microphoneGainControlView; @@ -105,12 +103,6 @@ typedef std::map InitialTouchPressMap; // Key = An ID number of the NSScreen *assignedScreen; NSWindow *masterWindow; - double _displayScale; - double _displayRotation; - NSInteger _displayMode; - NSInteger _displayOrientation; - NSInteger _displayOrder; - double _displayGap; NSInteger screenshotFileFormat; NSSize _minDisplayViewSize; @@ -146,7 +138,6 @@ typedef std::map InitialTouchPressMap; // Key = An ID number of the @property (assign) NSScreen *assignedScreen; @property (retain) NSWindow *masterWindow; -@property (readonly) NSSize normalSize; @property (assign) double displayScale; @property (assign) double displayRotation; @property (assign) BOOL videoFiltersPreferGPU; @@ -167,7 +158,7 @@ typedef std::map InitialTouchPressMap; // Key = An ID number of the - (BOOL) masterStatusBarState; - (NSRect) masterWindowFrame; - (double) masterWindowScale; -- (double) resizeWithTransform:(NSSize)normalBounds scalar:(double)scalar rotation:(double)angleDegrees; +- (void) resizeWithTransform; - (double) maxScalarForContentBoundsWidth:(double)contentBoundsWidth height:(double)contentBoundsHeight; - (void) enterFullScreen; - (void) exitFullScreen; diff --git a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm index 6bbbcf1ad..6552ecbea 100644 --- a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm +++ b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2016 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 @@ -59,7 +59,6 @@ @synthesize microphoneGainSlider; @synthesize microphoneMuteButton; -@dynamic normalSize; @dynamic displayScale; @dynamic displayRotation; @dynamic videoFiltersPreferGPU; @@ -106,17 +105,25 @@ static std::unordered_map _screenMap; // screenshotFileFormat = NSTIFFFileType; // These need to be initialized first since there are dependencies on these. - _displayGap = 0.0; - _displayMode = ClientDisplayMode_Dual; - _displayOrientation = ClientDisplayLayout_Vertical; + _localViewProps.normalWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH; + _localViewProps.normalHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2.0; + _localViewProps.clientWidth = _localViewProps.normalWidth; + _localViewProps.clientHeight = _localViewProps.normalHeight; + _localViewProps.rotation = 0.0; + _localViewProps.viewScale = 1.0; + _localViewProps.gapScale = 0.0; + _localViewProps.gapDistance = DS_DISPLAY_UNSCALED_GAP * _localViewProps.gapScale; + _localViewProps.mode = ClientDisplayMode_Dual; + _localViewProps.layout = ClientDisplayLayout_Vertical; + _localViewProps.order = ClientDisplayOrder_MainFirst; - _minDisplayViewSize = NSMakeSize(GPU_DISPLAY_WIDTH, (GPU_DISPLAY_HEIGHT*2.0) + (DS_DISPLAY_UNSCALED_GAP*_displayGap)); + _minDisplayViewSize = NSMakeSize(_localViewProps.clientWidth, _localViewProps.clientHeight + _localViewProps.gapDistance); _isMinSizeNormal = YES; _statusBarHeight = WINDOW_STATUS_BAR_HEIGHT; _isUpdatingDisplayScaleValueOnly = NO; _useMavericksFullScreen = IsOSXVersionSupported(10, 9, 0); _masterWindowScale = 1.0; - _masterWindowFrame = NSMakeRect(0.0, 0.0, GPU_DISPLAY_WIDTH, (GPU_DISPLAY_HEIGHT*2.0) + (DS_DISPLAY_UNSCALED_GAP*_displayGap)); + _masterWindowFrame = NSMakeRect(0.0, 0.0, _localViewProps.clientWidth, _localViewProps.clientHeight + _localViewProps.gapDistance); _masterStatusBarState = NO; [[NSNotificationCenter defaultCenter] addObserver:self @@ -147,30 +154,25 @@ static std::unordered_map _screenMap; // - (void) setDisplayScale:(double)s { // There are two ways that this property is used: - // 1. Update the displayScale value (usually as the result of a window resize) + // 1. Update the displayScale value only (usually as the result of a window resize) // 2. Resize the window as a result of setting displayScale // // Use the _isUpdatingDisplayScaleValueOnly flag to control this property's behavior. + OSSpinLockLock(&spinlockScale); + _localViewProps.viewScale = s; + OSSpinLockUnlock(&spinlockScale); - if (_isUpdatingDisplayScaleValueOnly) + if (!_isUpdatingDisplayScaleValueOnly) { - // Update the displayScale value only - OSSpinLockLock(&spinlockScale); - _displayScale = s; - OSSpinLockUnlock(&spinlockScale); - } - else - { - // Resize the window. // When the window resizes, this property's value will be implicitly updated using _isUpdatingDisplayScaleValueOnly. - [self resizeWithTransform:[self normalSize] scalar:s rotation:[self displayRotation]]; + [self resizeWithTransform]; } } - (double) displayScale { OSSpinLockLock(&spinlockScale); - const double s = _displayScale; + const double s = _localViewProps.viewScale; OSSpinLockUnlock(&spinlockScale); return s; @@ -190,26 +192,23 @@ static std::unordered_map _screenMap; // } OSSpinLockLock(&spinlockRotation); - _displayRotation = newAngleDegrees; + _localViewProps.rotation = newAngleDegrees; OSSpinLockUnlock(&spinlockRotation); NSWindow *theWindow = [self window]; // Set the minimum content size for the window, since this will change based on rotation. - CGSize minContentSize = GetTransformedBounds(_minDisplayViewSize.width, _minDisplayViewSize.height, 1.0, CLOCKWISE_DEGREES(newAngleDegrees)); - minContentSize.height += _statusBarHeight; - [theWindow setContentMinSize:NSMakeSize(minContentSize.width, minContentSize.height)]; + double contentMinWidth = _minDisplayViewSize.width; + double contentMinHeight = _minDisplayViewSize.height; + ClientDisplayView::ConvertNormalToTransformedBounds(1.0, CLOCKWISE_DEGREES(newAngleDegrees), contentMinWidth, contentMinHeight); + contentMinHeight += _statusBarHeight; + [theWindow setContentMinSize:NSMakeSize(contentMinWidth, contentMinHeight)]; // Resize the window. const NSSize oldBounds = [theWindow frame].size; - const NSSize newNormalSize = [DisplayView calculateNormalSizeUsingMode:[self displayMode] layout:[self displayOrientation] gapScalar:[self displayGap]]; - const double constrainedScale = [self resizeWithTransform:newNormalSize scalar:[self displayScale] rotation:newAngleDegrees]; + [self resizeWithTransform]; const NSSize newBounds = [theWindow frame].size; - OSSpinLockLock(&spinlockScale); - _displayScale = constrainedScale; - OSSpinLockUnlock(&spinlockScale); - // If the window size didn't change, it is possible that the old and new rotation angles // are 180 degrees offset from each other. In this case, we'll need to force the // display view to update itself. @@ -218,8 +217,8 @@ static std::unordered_map _screenMap; // [view setNeedsDisplay:YES]; } - DisplayOutputTransformData transformData = { constrainedScale, - angleDegrees, + DisplayOutputTransformData transformData = { _localViewProps.viewScale, + newAngleDegrees, 0.0, 0.0, 0.0 }; @@ -232,7 +231,7 @@ static std::unordered_map _screenMap; // - (double) displayRotation { OSSpinLockLock(&spinlockRotation); - const double angleDegrees = _displayRotation; + const double angleDegrees = _localViewProps.rotation; OSSpinLockUnlock(&spinlockRotation); return angleDegrees; @@ -261,12 +260,12 @@ static std::unordered_map _screenMap; // } OSSpinLockLock(&spinlockDisplayMode); - _displayMode = displayModeID; + _localViewProps.mode = (ClientDisplayMode)displayModeID; OSSpinLockUnlock(&spinlockDisplayMode); - const NSSize newNormalSize = [DisplayView calculateNormalSizeUsingMode:[self displayMode] layout:[self displayOrientation] gapScalar:[self displayGap]]; + ClientDisplayView::CalculateNormalSize((ClientDisplayMode)[self displayMode], (ClientDisplayLayout)[self displayOrientation], [self displayGap], _localViewProps.normalWidth, _localViewProps.normalHeight); [self setIsMinSizeNormal:[self isMinSizeNormal]]; - [self resizeWithTransform:newNormalSize scalar:[self displayScale] rotation:[self displayRotation]]; + [self resizeWithTransform]; [CocoaDSUtil messageSendOneWayWithInteger:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_CHANGE_DISPLAY_TYPE integerValue:displayModeID]; } @@ -274,7 +273,7 @@ static std::unordered_map _screenMap; // - (NSInteger) displayMode { OSSpinLockLock(&spinlockDisplayMode); - const NSInteger displayModeID = _displayMode; + const NSInteger displayModeID = _localViewProps.mode; OSSpinLockUnlock(&spinlockDisplayMode); return displayModeID; @@ -283,14 +282,15 @@ static std::unordered_map _screenMap; // - (void) setDisplayOrientation:(NSInteger)theOrientation { OSSpinLockLock(&spinlockDisplayOrientation); - _displayOrientation = theOrientation; + _localViewProps.layout = (ClientDisplayLayout)theOrientation; OSSpinLockUnlock(&spinlockDisplayOrientation); + ClientDisplayView::CalculateNormalSize((ClientDisplayMode)[self displayMode], (ClientDisplayLayout)[self displayOrientation], [self displayGap], _localViewProps.normalWidth, _localViewProps.normalHeight); + [self setIsMinSizeNormal:[self isMinSizeNormal]]; + if ([self displayMode] == ClientDisplayMode_Dual) { - const NSSize newNormalSize = [DisplayView calculateNormalSizeUsingMode:[self displayMode] layout:[self displayOrientation] gapScalar:[self displayGap]]; - [self setIsMinSizeNormal:[self isMinSizeNormal]]; - [self resizeWithTransform:newNormalSize scalar:[self displayScale] rotation:[self displayRotation]]; + [self resizeWithTransform]; } [CocoaDSUtil messageSendOneWayWithInteger:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_CHANGE_DISPLAY_ORIENTATION integerValue:theOrientation]; @@ -299,7 +299,7 @@ static std::unordered_map _screenMap; // - (NSInteger) displayOrientation { OSSpinLockLock(&spinlockDisplayOrientation); - const NSInteger theOrientation = _displayOrientation; + const NSInteger theOrientation = _localViewProps.layout; OSSpinLockUnlock(&spinlockDisplayOrientation); return theOrientation; @@ -308,7 +308,7 @@ static std::unordered_map _screenMap; // - (void) setDisplayOrder:(NSInteger)theOrder { OSSpinLockLock(&spinlockDisplayOrder); - _displayOrder = theOrder; + _localViewProps.order = (ClientDisplayOrder)theOrder; OSSpinLockUnlock(&spinlockDisplayOrder); [CocoaDSUtil messageSendOneWayWithInteger:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_CHANGE_DISPLAY_ORDER integerValue:theOrder]; @@ -317,7 +317,7 @@ static std::unordered_map _screenMap; // - (NSInteger) displayOrder { OSSpinLockLock(&spinlockDisplayOrder); - const NSInteger theOrder = _displayOrder; + const NSInteger theOrder = _localViewProps.order; OSSpinLockUnlock(&spinlockDisplayOrder); return theOrder; @@ -326,14 +326,15 @@ static std::unordered_map _screenMap; // - (void) setDisplayGap:(double)gapScalar { OSSpinLockLock(&spinlockDisplayGap); - _displayGap = gapScalar; + _localViewProps.gapScale = gapScalar; OSSpinLockUnlock(&spinlockDisplayGap); + ClientDisplayView::CalculateNormalSize((ClientDisplayMode)[self displayMode], (ClientDisplayLayout)[self displayOrientation], [self displayGap], _localViewProps.normalWidth, _localViewProps.normalHeight); + [self setIsMinSizeNormal:[self isMinSizeNormal]]; + if ([self displayMode] == ClientDisplayMode_Dual) { - const NSSize newNormalSize = [DisplayView calculateNormalSizeUsingMode:[self displayMode] layout:[self displayOrientation] gapScalar:[self displayGap]]; - [self setIsMinSizeNormal:[self isMinSizeNormal]]; - [self resizeWithTransform:newNormalSize scalar:[self displayScale] rotation:[self displayRotation]]; + [self resizeWithTransform]; } [CocoaDSUtil messageSendOneWayWithFloat:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_CHANGE_DISPLAY_GAP floatValue:(float)gapScalar]; @@ -342,7 +343,7 @@ static std::unordered_map _screenMap; // - (double) displayGap { OSSpinLockLock(&spinlockDisplayGap); - const double gapScalar = _displayGap; + const double gapScalar = _localViewProps.gapScale; OSSpinLockUnlock(&spinlockDisplayGap); return gapScalar; @@ -395,18 +396,20 @@ static std::unordered_map _screenMap; // - (void) setIsMinSizeNormal:(BOOL)theState { _isMinSizeNormal = theState; - _minDisplayViewSize = [DisplayView calculateNormalSizeUsingMode:[self displayMode] layout:[self displayOrientation] gapScalar:[self displayGap]]; + _minDisplayViewSize.width = _localViewProps.normalWidth; + _minDisplayViewSize.height = _localViewProps.normalHeight; if (!_isMinSizeNormal) { - _minDisplayViewSize.width /= 4; - _minDisplayViewSize.height /= 4; + _minDisplayViewSize.width /= 4.0; + _minDisplayViewSize.height /= 4.0; } // Set the minimum content size, keeping the display rotation in mind. - CGSize transformedMinSize = GetTransformedBounds(_minDisplayViewSize.width, _minDisplayViewSize.height, 1.0, CLOCKWISE_DEGREES([self displayRotation])); - transformedMinSize.height += _statusBarHeight; - [[self window] setContentMinSize:NSMakeSize(transformedMinSize.width, transformedMinSize.height)]; + double transformedMinWidth = _minDisplayViewSize.width; + double transformedMinHeight = _minDisplayViewSize.height; + ClientDisplayView::ConvertNormalToTransformedBounds(1.0, CLOCKWISE_DEGREES([self displayRotation]), transformedMinWidth, transformedMinHeight); + [[self window] setContentMinSize:NSMakeSize(transformedMinWidth, transformedMinHeight + _statusBarHeight)]; } - (BOOL) isMinSizeNormal @@ -485,11 +488,6 @@ static std::unordered_map _screenMap; // //[[self view] setIsHUDInputVisible:[[NSUserDefaults standardUserDefaults] boolForKey:@"HUD_ShowInput"]]; } -- (NSSize) normalSize -{ - return [[self view] normalSize]; -} - - (BOOL) masterStatusBarState { return (([self assignedScreen] == nil) || !_useMavericksFullScreen) ? [self isShowingStatusBar] : _masterStatusBarState; @@ -505,39 +503,43 @@ static std::unordered_map _screenMap; // return (([self assignedScreen] == nil) || !_useMavericksFullScreen) ? [self displayScale] : _masterWindowScale; } -- (double) resizeWithTransform:(NSSize)normalBounds scalar:(double)scalar rotation:(double)angleDegrees +- (void) resizeWithTransform { if ([self assignedScreen] != nil) { - return scalar; + return; } // Convert angle to clockwise-direction degrees. - angleDegrees = CLOCKWISE_DEGREES(angleDegrees); + const double angleDegrees = CLOCKWISE_DEGREES(_localViewProps.rotation); // Get the maximum scalar size within drawBounds. Constrain scalar to maxScalar if necessary. - const CGSize checkSize = GetTransformedBounds(normalBounds.width, normalBounds.height, 1.0, angleDegrees); - const double maxScalar = [self maxScalarForContentBoundsWidth:checkSize.width height:checkSize.height]; - if (scalar > maxScalar) + double checkWidth = _localViewProps.normalWidth; + double checkHeight = _localViewProps.normalHeight; + ClientDisplayView::ConvertNormalToTransformedBounds(1.0, angleDegrees, checkWidth, checkHeight); + + const double constrainedScale = [self maxScalarForContentBoundsWidth:checkWidth height:checkHeight]; + if (_localViewProps.viewScale > constrainedScale) { - scalar = maxScalar; + _isUpdatingDisplayScaleValueOnly = YES; + [self setDisplayScale:constrainedScale]; + _isUpdatingDisplayScaleValueOnly = NO; } // Get the new bounds for the window's content view based on the transformed draw bounds. - const CGSize transformedBounds = GetTransformedBounds(normalBounds.width, normalBounds.height, scalar, angleDegrees); + double transformedWidth = _localViewProps.normalWidth; + double transformedHeight = _localViewProps.normalHeight; + ClientDisplayView::ConvertNormalToTransformedBounds(_localViewProps.viewScale, angleDegrees, transformedWidth, transformedHeight); // Get the center of the content view in screen coordinates. const NSRect windowContentRect = [[masterWindow contentView] bounds]; - const double translationX = (windowContentRect.size.width - transformedBounds.width) / 2.0; - const double translationY = ((windowContentRect.size.height - _statusBarHeight) - transformedBounds.height) / 2.0; + const double translationX = (windowContentRect.size.width - transformedWidth) / 2.0; + const double translationY = ((windowContentRect.size.height - _statusBarHeight) - transformedHeight) / 2.0; // Resize the window. const NSRect windowFrame = [masterWindow frame]; - const NSRect newFrame = [masterWindow frameRectForContentRect:NSMakeRect(windowFrame.origin.x + translationX, windowFrame.origin.y + translationY, transformedBounds.width, transformedBounds.height + _statusBarHeight)]; + const NSRect newFrame = [masterWindow frameRectForContentRect:NSMakeRect(windowFrame.origin.x + translationX, windowFrame.origin.y + translationY, transformedWidth, transformedHeight + _statusBarHeight)]; [masterWindow setFrame:newFrame display:YES animate:NO]; - - // Return the actual scale used for the view (may be constrained). - return scalar; } - (double) maxScalarForContentBoundsWidth:(double)contentBoundsWidth height:(double)contentBoundsHeight @@ -548,7 +550,7 @@ static std::unordered_map _screenMap; // const NSRect windowFrame = [[self window] frameRectForContentRect:NSMakeRect(0.0, 0.0, contentBoundsWidth, contentBoundsHeight + _statusBarHeight)]; const NSSize visibleScreenBounds = { (screenFrame.size.width - (windowFrame.size.width - contentBoundsWidth)), (screenFrame.size.height - (windowFrame.size.height - contentBoundsHeight)) }; - return GetMaxScalarInBounds(contentBoundsWidth, contentBoundsHeight, visibleScreenBounds.width, visibleScreenBounds.height); + return ClientDisplayView::GetMaxScalarWithinBounds(contentBoundsWidth, contentBoundsHeight, visibleScreenBounds.width, visibleScreenBounds.height); } - (void) saveScreenshotAsFinish:(NSNotification *)aNotification @@ -633,7 +635,7 @@ static std::unordered_map _screenMap; // } [self setWindow:masterWindow]; - [self resizeWithTransform:[self normalSize] scalar:[self displayScale] rotation:[self displayRotation]]; + [self resizeWithTransform]; NSRect viewFrame = [[masterWindow contentView] frame]; viewFrame.size.height -= _statusBarHeight; @@ -755,16 +757,18 @@ static std::unordered_map _screenMap; // [self setIsMinSizeNormal:YES]; // Set the minimum content size, keeping the display rotation in mind. - CGSize transformedMinSize = GetTransformedBounds(_minDisplayViewSize.width, _minDisplayViewSize.height, 1.0, CLOCKWISE_DEGREES([self displayRotation])); - transformedMinSize.height += _statusBarHeight; + double transformedMinWidth = _minDisplayViewSize.width; + double transformedMinHeight = _minDisplayViewSize.height; + ClientDisplayView::ConvertNormalToTransformedBounds(1.0, CLOCKWISE_DEGREES([self displayRotation]), transformedMinWidth, transformedMinHeight); + transformedMinHeight += _statusBarHeight; // Resize the window if it's smaller than the minimum content size. NSRect windowContentRect = [masterWindow contentRectForFrameRect:[masterWindow frame]]; - if (windowContentRect.size.width < transformedMinSize.width || windowContentRect.size.height < transformedMinSize.height) + if (windowContentRect.size.width < transformedMinWidth || windowContentRect.size.height < transformedMinHeight) { // Prepare to resize. NSRect oldFrameRect = [masterWindow frame]; - windowContentRect.size = NSMakeSize(transformedMinSize.width, transformedMinSize.height); + windowContentRect.size = NSMakeSize(transformedMinWidth, transformedMinHeight); NSRect newFrameRect = [masterWindow frameRectForContentRect:windowContentRect]; // Keep the window centered when expanding the size. @@ -1269,13 +1273,14 @@ static std::unordered_map _screenMap; // // Find the maximum scalar we can use for the display view, bounded by the // content Rect. - const NSSize normalBounds = [self normalSize]; - const CGSize checkSize = GetTransformedBounds(normalBounds.width, normalBounds.height, 1.0, [self displayRotation]); + double checkWidth = _localViewProps.normalWidth; + double checkHeight = _localViewProps.normalHeight; + ClientDisplayView::ConvertNormalToTransformedBounds(1.0, [self displayRotation], checkWidth, checkHeight); const NSSize contentBounds = NSMakeSize(contentRect.size.width, contentRect.size.height - _statusBarHeight); - const double maxS = GetMaxScalarInBounds(checkSize.width, checkSize.height, contentBounds.width, contentBounds.height); + const double constrainedScale = ClientDisplayView::GetMaxScalarWithinBounds(checkWidth, checkHeight, contentBounds.width, contentBounds.height); // Make a new content Rect with our max scalar, and convert it back to a frame Rect. - const NSRect finalContentRect = NSMakeRect(0.0f, 0.0f, checkSize.width * maxS, (checkSize.height * maxS) + _statusBarHeight); + const NSRect finalContentRect = NSMakeRect(0.0f, 0.0f, checkWidth * constrainedScale, (checkHeight * constrainedScale) + _statusBarHeight); const NSRect finalFrameRect = [sender frameRectForContentRect:finalContentRect]; // Set the final size based on our new frame Rect. @@ -1290,15 +1295,17 @@ static std::unordered_map _screenMap; // } // Get the max scalar within the window's current content bounds. - const NSSize normalBounds = [self normalSize]; - const CGSize checkSize = GetTransformedBounds(normalBounds.width, normalBounds.height, 1.0, [self displayRotation]); + double checkWidth = _localViewProps.normalWidth; + double checkHeight = _localViewProps.normalHeight; + ClientDisplayView::ConvertNormalToTransformedBounds(1.0, [self displayRotation], checkWidth, checkHeight); + NSSize contentBounds = [[[self window] contentView] bounds].size; contentBounds.height -= _statusBarHeight; - const double maxS = GetMaxScalarInBounds(checkSize.width, checkSize.height, contentBounds.width, contentBounds.height); + const double constrainedScale = ClientDisplayView::GetMaxScalarWithinBounds(checkWidth, checkHeight, contentBounds.width, contentBounds.height); // Since we are already resizing, only update the displayScale property here. _isUpdatingDisplayScaleValueOnly = YES; - [self setDisplayScale:maxS]; + [self setDisplayScale:constrainedScale]; _isUpdatingDisplayScaleValueOnly = NO; // Resize the view. @@ -1337,13 +1344,14 @@ static std::unordered_map _screenMap; // // Find the maximum scalar we can use for the display view, bounded by the // content Rect. - const NSSize normalBounds = [self normalSize]; - const CGSize checkSize = GetTransformedBounds(normalBounds.width, normalBounds.height, 1.0, [self displayRotation]); + double checkWidth = _localViewProps.normalWidth; + double checkHeight = _localViewProps.normalHeight; + ClientDisplayView::ConvertNormalToTransformedBounds(1.0, [self displayRotation], checkWidth, checkHeight); const NSSize contentBounds = NSMakeSize(contentRect.size.width, contentRect.size.height - _statusBarHeight); - const double maxS = GetMaxScalarInBounds(checkSize.width, checkSize.height, contentBounds.width, contentBounds.height); + const double maxS = ClientDisplayView::GetMaxScalarWithinBounds(checkWidth, checkHeight, contentBounds.width, contentBounds.height); // Make a new content Rect with our max scalar, and convert it back to a frame Rect. - const NSRect finalContentRect = NSMakeRect(0.0f, 0.0f, checkSize.width * maxS, (checkSize.height * maxS) + _statusBarHeight); + const NSRect finalContentRect = NSMakeRect(0.0f, 0.0f, checkWidth * maxS, (checkHeight * maxS) + _statusBarHeight); NSRect finalFrameRect = [window frameRectForContentRect:finalContentRect]; if (isZooming) @@ -1565,7 +1573,7 @@ static std::unordered_map _screenMap; // #endif inputManager = nil; - _initialTouchInMajorDisplay = new InitialTouchPressMap; + _cdv = new ClientDisplayView(); // Initialize the OpenGL context NSOpenGLPixelFormatAttribute attributes[] = { @@ -1639,7 +1647,7 @@ static std::unordered_map _screenMap; // delete oglv; CGLSetCurrentContext(prevContext); - delete _initialTouchInMajorDisplay; + delete _cdv; [self setInputManager:nil]; [context clearDrawable]; [context release]; @@ -1649,16 +1657,6 @@ static std::unordered_map _screenMap; // #pragma mark Dynamic Property Methods -- (NSSize) normalSize -{ - double w; - double h; - - oglv->GetDisplayLayer()->GetNormalSize(w, h); - - return NSMakeSize(w, h); -} - - (void) setIsHUDVisible:(BOOL)theState { OSSpinLockLock(&spinlockIsHUDVisible); @@ -1944,103 +1942,11 @@ static std::unordered_map _screenMap; // // and finally to DS touchscreen coordinates. NSPoint touchLoc = [theEvent locationInWindow]; touchLoc = [self convertPoint:touchLoc fromView:nil]; - touchLoc = [self convertPointToDS:touchLoc inputID:inputID initialTouchPress:isInitialMouseDown]; - return touchLoc; -} - -- (NSPoint) convertPointToDS:(NSPoint)clickLoc inputID:(const NSInteger)inputID initialTouchPress:(BOOL)isInitialTouchPress -{ - DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate]; + u8 x, y; + _cdv->GetNDSPoint((int)inputID, (isInitialMouseDown) ? true : false, touchLoc.x, touchLoc.y, x, y); - double viewAngle = [windowController displayRotation]; - if (viewAngle != 0.0) - { - viewAngle = CLOCKWISE_DEGREES(viewAngle); - } - - const NSSize normalBounds = [windowController normalSize]; - const NSSize viewSize = [self bounds].size; - const CGSize transformBounds = GetTransformedBounds(normalBounds.width, normalBounds.height, 1.0, oglv->GetDisplayLayer()->GetRotation()); - const double s = GetMaxScalarInBounds(transformBounds.width, transformBounds.height, viewSize.width, viewSize.height); - - CGPoint touchLoc = GetNormalPointFromTransformedPoint(clickLoc.x, clickLoc.y, - normalBounds.width, normalBounds.height, - viewSize.width, viewSize.height, - s, - viewAngle); - - // Normalize the touch location to the DS. - if ([windowController displayMode] == ClientDisplayMode_Dual) - { - const ClientDisplayLayout theOrientation = (ClientDisplayLayout)[windowController displayOrientation]; - const ClientDisplayOrder theOrder = (ClientDisplayOrder)[windowController displayOrder]; - - switch (theOrientation) - { - case ClientDisplayLayout_Horizontal: - { - if (theOrder == ClientDisplayOrder_MainFirst) - { - touchLoc.x -= GPU_DISPLAY_WIDTH; - } - break; - } - - case ClientDisplayLayout_Hybrid_3_2: - case ClientDisplayLayout_Hybrid_16_9: - case ClientDisplayLayout_Hybrid_16_10: - { - if (isInitialTouchPress) - { - const bool isClickWithinMajorDisplay = (theOrder == ClientDisplayOrder_TouchFirst) && (touchLoc.x >= 0.0) && (touchLoc.x < 256.0); - (*_initialTouchInMajorDisplay)[(int)inputID] = isClickWithinMajorDisplay; - } - - const bool handleClickInMajorDisplay = (*_initialTouchInMajorDisplay)[(int)inputID]; - if (!handleClickInMajorDisplay) - { - const double minorDisplayScale = (normalBounds.width - (GLfloat)GPU_DISPLAY_WIDTH) / (GLfloat)GPU_DISPLAY_WIDTH; - touchLoc.x = (touchLoc.x - GPU_DISPLAY_WIDTH) / minorDisplayScale; - touchLoc.y = touchLoc.y / minorDisplayScale; - } - break; - } - - default: // Default to vertical orientation. - { - if (theOrder == ClientDisplayOrder_TouchFirst) - { - const double gap = DS_DISPLAY_UNSCALED_GAP * [windowController displayGap]; - touchLoc.y -= (GPU_DISPLAY_HEIGHT+gap); - } - break; - } - } - } - - touchLoc.y = GPU_DISPLAY_HEIGHT - touchLoc.y; - - // Constrain the touch point to the DS dimensions. - if (touchLoc.x < 0) - { - touchLoc.x = 0; - } - else if (touchLoc.x > (GPU_DISPLAY_WIDTH - 1)) - { - touchLoc.x = (GPU_DISPLAY_WIDTH - 1); - } - - if (touchLoc.y < 0) - { - touchLoc.y = 0; - } - else if (touchLoc.y > (GPU_DISPLAY_HEIGHT - 1)) - { - touchLoc.y = (GPU_DISPLAY_HEIGHT - 1); - } - - return NSMakePoint(touchLoc.x, touchLoc.y); + return NSMakePoint(x, y); } #pragma mark InputHIDManagerTarget Protocol @@ -2366,8 +2272,9 @@ static std::unordered_map _screenMap; // const GLsizei w = (GLsizei)rect.size.width; const GLsizei h = (GLsizei)rect.size.height; - DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate]; - double hudObjectScale = [windowController displayScale]; + _cdv->SetClientSize(rect.size.width, rect.size.height); + + double hudObjectScale = _cdv->GetViewScale(); if (hudObjectScale > 2.0) { // If the view scale is <= 2.0, we scale the HUD objects linearly. Otherwise, we scale @@ -2385,7 +2292,9 @@ static std::unordered_map _screenMap; // } - (void)doTransformView:(const DisplayOutputTransformData *)transformData -{ +{ + _cdv->SetRotation(transformData->rotation); + OGLDisplayLayer *display = oglv->GetDisplayLayer(); display->SetRotation((GLfloat)transformData->rotation); [self doRedraw]; @@ -2401,6 +2310,8 @@ static std::unordered_map _screenMap; // - (void)doDisplayModeChanged:(NSInteger)displayModeID { + _cdv->SetMode((ClientDisplayMode)displayModeID); + OGLDisplayLayer *display = oglv->GetDisplayLayer(); display->SetMode((ClientDisplayMode)displayModeID); [self doRedraw]; @@ -2408,6 +2319,8 @@ static std::unordered_map _screenMap; // - (void)doDisplayOrientationChanged:(NSInteger)displayOrientationID { + _cdv->SetLayout((ClientDisplayLayout)displayOrientationID); + OGLDisplayLayer *display = oglv->GetDisplayLayer(); display->SetOrientation((ClientDisplayLayout)displayOrientationID); @@ -2419,6 +2332,8 @@ static std::unordered_map _screenMap; // - (void)doDisplayOrderChanged:(NSInteger)displayOrderID { + _cdv->SetOrder((ClientDisplayOrder)displayOrderID); + OGLDisplayLayer *display = oglv->GetDisplayLayer(); display->SetOrder((ClientDisplayOrder)displayOrderID); @@ -2430,6 +2345,8 @@ static std::unordered_map _screenMap; // - (void)doDisplayGapChanged:(float)displayGapScalar { + _cdv->SetGapWithScalar(displayGapScalar); + OGLDisplayLayer *display = oglv->GetDisplayLayer(); display->SetGapScalar((GLfloat)displayGapScalar); @@ -2439,16 +2356,6 @@ static std::unordered_map _screenMap; // } } -+ (NSSize) calculateNormalSizeUsingMode:(const NSInteger)mode layout:(const NSInteger)layout gapScalar:(const double)gapScalar -{ - double w; - double h; - - OGLDisplayLayer::CalculateNormalSize((ClientDisplayMode)mode, (ClientDisplayLayout)layout, gapScalar, w, h); - - return NSMakeSize(w, h); -} - @end #pragma mark - diff --git a/desmume/src/frontend/cocoa/userinterface/appDelegate.mm b/desmume/src/frontend/cocoa/userinterface/appDelegate.mm index aa267e54f..4d4b25d6d 100644 --- a/desmume/src/frontend/cocoa/userinterface/appDelegate.mm +++ b/desmume/src/frontend/cocoa/userinterface/appDelegate.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 @@ -647,24 +647,24 @@ int frameX = 0; int frameY = 0; - int frameWidth = GPU_DISPLAY_WIDTH; - int frameHeight = GPU_DISPLAY_HEIGHT; + int frameWidth = 256; + int frameHeight = 192; const char *frameCStr = [windowFrameStr cStringUsingEncoding:NSUTF8StringEncoding]; sscanf(frameCStr, "%i %i %i %i", &frameX, &frameY, &frameWidth, &frameHeight); - [windowController setIsMinSizeNormal:isMinSizeNormal]; [windowController setIsShowingStatusBar:isShowingStatusBar]; [windowController setVideoFiltersPreferGPU:videoFiltersPreferGPU]; [windowController setVideoSourceDeposterize:videoSourceDeposterize]; [windowController setVideoPixelScaler:videoPixelScaler]; [windowController setVideoOutputFilter:videoOutputFilter]; [windowController setDisplayMode:displayMode]; - [windowController setDisplayRotation:displayRotation]; [windowController setDisplayOrientation:displayOrientation]; [windowController setDisplayOrder:displayOrder]; [windowController setDisplayGap:displayGap]; - [windowController setScreenshotFileFormat:screenshotFileFormat]; + [windowController setIsMinSizeNormal:isMinSizeNormal]; + [windowController setDisplayRotation:displayRotation]; [windowController setDisplayScale:displayScale]; + [windowController setScreenshotFileFormat:screenshotFileFormat]; [[windowController view] setUseVerticalSync:useVerticalSync]; [[windowController view] setIsHUDVisible:hudEnable]; [[windowController view] setIsHUDVideoFPSVisible:hudShowVideoFPS]; diff --git a/desmume/src/frontend/cocoa/utilities.c b/desmume/src/frontend/cocoa/utilities.c index d7a539dd2..823b76dfc 100644 --- a/desmume/src/frontend/cocoa/utilities.c +++ b/desmume/src/frontend/cocoa/utilities.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 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 @@ -332,266 +332,6 @@ void RGBA8888ForceOpaqueBuffer(const uint32_t *__restrict__ srcBuffer, uint32_t } } -/******************************************************************************************** - GetTransformedBounds() - - Returns the bounds of a normalized 2D surface using affine transformations. - - Takes: - normalBoundsWidth - The width of the normal 2D surface. - - normalBoundsHeight - The height of the normal 2D surface. - - scalar - The scalar used to transform the 2D surface. - - angleDegrees - The rotation angle, in degrees, to transform the 2D surface. - - Returns: - The bounds of a normalized 2D surface using affine transformations. - - Details: - The returned bounds is always a normal rectangle. Ignoring the scaling, the - returned bounds will always be at its smallest when the angle is at 0, 90, 180, - or 270 degrees, and largest when the angle is at 45, 135, 225, or 315 degrees. - ********************************************************************************************/ -CGSize GetTransformedBounds(const double normalBoundsWidth, const double normalBoundsHeight, - const double scalar, - const double angleDegrees) -{ - const double angleRadians = angleDegrees * (M_PI/180.0); - - // The points are as follows: - // - // (x[3], y[3]) (x[2], y[2]) - // - // - // - // (x[0], y[0]) (x[1], y[1]) - - // Do our scale and rotate transformations. -#ifdef __ACCELERATE__ - - // Note that although we only need to calculate 3 points, we include 4 points - // here because Accelerate prefers 16-byte alignment. - double x[] = {0.0, normalBoundsWidth, normalBoundsWidth, 0.0}; - double y[] = {0.0, 0.0, normalBoundsHeight, normalBoundsHeight}; - - cblas_drot(4, x, 1, y, 1, scalar * cos(angleRadians), scalar * sin(angleRadians)); - -#else // Keep a C-version of this transformation for reference purposes. - - const double w = scalar * normalBoundsWidth; - const double h = scalar * normalBoundsHeight; - const double d = hypot(w, h); - const double dAngle = atan2(h, w); - - const double px = w * cos(angleRadians); - const double py = w * sin(angleRadians); - const double qx = d * cos(dAngle + angleRadians); - const double qy = d * sin(dAngle + angleRadians); - const double rx = h * cos((M_PI/2.0) + angleRadians); - const double ry = h * sin((M_PI/2.0) + angleRadians); - - const double x[] = {0.0, px, qx, rx}; - const double y[] = {0.0, py, qy, ry}; - -#endif - - // Determine the transformed width, which is dependent on the location of - // the x-coordinate of point (x[2], y[2]). - CGSize transformBounds = {0.0, 0.0}; - - if (x[2] > 0.0) - { - if (x[2] < x[3]) - { - transformBounds.width = x[3] - x[1]; - } - else if (x[2] < x[1]) - { - transformBounds.width = x[1] - x[3]; - } - else - { - transformBounds.width = x[2]; - } - } - else if (x[2] < 0.0) - { - if (x[2] > x[3]) - { - transformBounds.width = -(x[3] - x[1]); - } - else if (x[2] > x[1]) - { - transformBounds.width = -(x[1] - x[3]); - } - else - { - transformBounds.width = -x[2]; - } - } - else - { - transformBounds.width = fabs(x[1] - x[3]); - } - - // Determine the transformed height, which is dependent on the location of - // the y-coordinate of point (x[2], y[2]). - if (y[2] > 0.0) - { - if (y[2] < y[3]) - { - transformBounds.height = y[3] - y[1]; - } - else if (y[2] < y[1]) - { - transformBounds.height = y[1] - y[3]; - } - else - { - transformBounds.height = y[2]; - } - } - else if (y[2] < 0.0) - { - if (y[2] > y[3]) - { - transformBounds.height = -(y[3] - y[1]); - } - else if (y[2] > y[1]) - { - transformBounds.height = -(y[1] - y[3]); - } - else - { - transformBounds.height = -y[2]; - } - } - else - { - transformBounds.height = fabs(y[3] - y[1]); - } - - return transformBounds; -} - -/******************************************************************************************** - GetMaxScalarInBounds() - - Returns the maximum scalar that a rectangle can grow, while maintaining its aspect - ratio, within a boundary. - - Takes: - normalBoundsWidth - The width of the normal 2D surface. - - normalBoundsHeight - The height of the normal 2D surface. - - keepInBoundsWidth - The width of the keep-in 2D surface. - - keepInBoundsHeight - The height of the keep-in 2D surface. - - Returns: - The maximum scalar that a rectangle can grow, while maintaining its aspect ratio, - within a boundary. - - Details: - If keepInBoundsWidth or keepInBoundsHeight are less than or equal to zero, the - returned scalar will be zero. - ********************************************************************************************/ -double GetMaxScalarInBounds(const double normalBoundsWidth, const double normalBoundsHeight, - const double keepInBoundsWidth, const double keepInBoundsHeight) -{ - const double maxX = (normalBoundsWidth <= 0.0) ? 0.0 : keepInBoundsWidth / normalBoundsWidth; - const double maxY = (normalBoundsHeight <= 0.0) ? 0.0 : keepInBoundsHeight / normalBoundsHeight; - - return (maxX <= maxY) ? maxX : maxY; -} - -/******************************************************************************************** - GetNormalPointFromTransformedPoint() - - Returns a normalized point from a point from a 2D transformed surface. - - Takes: - transformedPointX - The X coordinate of a 2D point as it exists on a 2D - transformed surface. - - transformedPointY - The Y coordinate of a 2D point as it exists on a 2D - transformed surface. - - normalBoundsWidth - The width of the normal 2D surface. - - normalBoundsHeight - The height of the normal 2D surface. - - transformBoundsWidth - The width of the transformed 2D surface. - - transformBoundsHeight - The height of the transformed 2D surface. - - scalar - The scalar used on the transformed 2D surface. - - angleDegrees - The rotation angle, in degrees, of the transformed 2D surface. - - Returns: - A normalized point from a point from a 2D transformed surface. - - Details: - It may help to call GetTransformedBounds() for the transformBounds parameter. - ********************************************************************************************/ -CGPoint GetNormalPointFromTransformedPoint(const double transformedPointX, const double transformedPointY, - const double normalBoundsWidth, const double normalBoundsHeight, - const double transformBoundsWidth, const double transformBoundsHeight, - const double scalar, - const double angleDegrees) -{ - // Get the coordinates of the transformed point and translate the coordinate - // system so that the origin becomes the center. - const double transformedX = transformedPointX - (transformBoundsWidth / 2.0); - const double transformedY = transformedPointY - (transformBoundsHeight / 2.0); - - // Perform rect-polar conversion. - - // Get the radius r with respect to the origin. - const double r = hypot(transformedX, transformedY) / scalar; - - // Get the angle theta with respect to the origin. - double theta = 0.0; - - if (transformedX == 0.0) - { - if (transformedY > 0.0) - { - theta = M_PI / 2.0; - } - else if (transformedY < 0.0) - { - theta = M_PI * 1.5; - } - } - else if (transformedX < 0.0) - { - theta = M_PI - atan2(transformedY, -transformedX); - } - else if (transformedY < 0.0) - { - theta = atan2(transformedY, transformedX) + (M_PI * 2.0); - } - else - { - theta = atan2(transformedY, transformedX); - } - - // Get the normalized angle and use it to rotate about the origin. - // Then do polar-rect conversion and translate back to transformed coordinates - // with a 0 degree rotation. - const double angleRadians = angleDegrees * (M_PI/180.0); - const double normalizedAngle = theta - angleRadians; - const double normalizedX = (r * cos(normalizedAngle)) + (normalBoundsWidth / 2.0); - const double normalizedY = (r * sin(normalizedAngle)) + (normalBoundsHeight / 2.0); - - return CGPointMake(normalizedX, normalizedY); -} - /******************************************************************************************** GetNearestPositivePOT() diff --git a/desmume/src/frontend/cocoa/utilities.h b/desmume/src/frontend/cocoa/utilities.h index 758add3c2..6498059ba 100644 --- a/desmume/src/frontend/cocoa/utilities.h +++ b/desmume/src/frontend/cocoa/utilities.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 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 @@ -37,19 +37,6 @@ void RGB555ToRGBA8888Buffer(const uint16_t *__restrict__ srcBuffer, uint32_t *__ void RGB555ToBGRA8888Buffer(const uint16_t *__restrict__ srcBuffer, uint32_t *__restrict__ destBuffer, size_t pixelCount); void RGB888ToBGRA8888Buffer(const uint32_t *__restrict__ srcBuffer, uint32_t *__restrict__ destBuffer, size_t pixelCount); void RGBA8888ForceOpaqueBuffer(const uint32_t *__restrict__ srcBuffer, uint32_t *__restrict__ destBuffer, size_t pixelCount); - -CGSize GetTransformedBounds(const double normalBoundsWidth, const double normalBoundsHeight, - const double scalar, - const double angleDegrees); - -double GetMaxScalarInBounds(const double normalBoundsWidth, const double normalBoundsHeight, - const double keepInBoundsWidth, const double keepInBoundsHeight); - -CGPoint GetNormalPointFromTransformedPoint(const double transformedPointX, const double transformedPointY, - const double normalBoundsWidth, const double normalBoundsHeight, - const double transformBoundsWidth, const double transformBoundsHeight, - const double scalar, - const double angleDegrees); uint32_t GetNearestPositivePOT(uint32_t value);