Cocoa Port: Begin refactoring display view code to reduce the dependence on port-specific code.

This commit is contained in:
rogerman 2017-01-02 22:39:25 -08:00
parent 207a3b2e9e
commit ce494a2eaa
14 changed files with 859 additions and 649 deletions

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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;
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef _CLIENT_DISPLAY_VIEW_H_
#define _CLIENT_DISPLAY_VIEW_H_
#include <map>
#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<int, bool> 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_

View File

@ -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 = "<group>"; };
ABAB454E187CDB70007BE20C /* Image_GuitarGrip.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Image_GuitarGrip.png; path = images/Image_GuitarGrip.png; sourceTree = "<group>"; };
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 = "<group>"; };
ABAD07DB1E19CAA6007867CA /* ClientDisplayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientDisplayView.h; sourceTree = "<group>"; };
ABAD3E5913AF1D6D00502E1E /* AAFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AAFilter.h; sourceTree = "<group>"; };
ABAD3E5A13AF1D6D00502E1E /* BPMDetect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BPMDetect.h; sourceTree = "<group>"; };
ABAD3E5B13AF1D6D00502E1E /* cpu_detect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu_detect.h; sourceTree = "<group>"; };
@ -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 */,

View File

@ -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 = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
AB0F13911E1B7C320075684F /* ClientDisplayView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClientDisplayView.cpp; sourceTree = "<group>"; };
AB0F28FE14BE6E68009ABC6F /* Icon_Execute_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Execute_420x420.png; path = images/Icon_Execute_420x420.png; sourceTree = "<group>"; };
AB0F28FF14BE6E68009ABC6F /* Icon_Pause_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Pause_420x420.png; path = images/Icon_Pause_420x420.png; sourceTree = "<group>"; };
AB0F290014BE6E68009ABC6F /* Icon_Speed1x_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Speed1x_420x420.png; path = images/Icon_Speed1x_420x420.png; sourceTree = "<group>"; };
@ -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;
};

View File

@ -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;
}
}

View File

@ -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 <string>
#include "../../filter/videofilter.h"
#include "ClientDisplayView.h"
#include <ft2build.h>
#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

View File

@ -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

View File

@ -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.

View File

@ -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);

View File

@ -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<int, bool> 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<int, bool> InitialTouchPressMap; // Key = An ID number of the
@interface DisplayView : NSView <CocoaDSDisplayVideoDelegate, InputHIDManagerTarget>
{
InputManager *inputManager;
InitialTouchPressMap *_initialTouchInMajorDisplay;
ClientDisplayView *_cdv;
OGLVideoOutput *oglv;
BOOL canUseShaderBasedFilters;
@ -56,7 +57,6 @@ typedef std::map<int, bool> 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<int, bool> 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<int, bool> 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<int, bool> 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<int, bool> 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<int, bool> 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;

View File

@ -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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _screenMap; //
#endif
inputManager = nil;
_initialTouchInMajorDisplay = new InitialTouchPressMap;
_cdv = new ClientDisplayView();
// Initialize the OpenGL context
NSOpenGLPixelFormatAttribute attributes[] = {
@ -1639,7 +1647,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
delete oglv;
CGLSetCurrentContext(prevContext);
delete _initialTouchInMajorDisplay;
delete _cdv;
[self setInputManager:nil];
[context clearDrawable];
[context release];
@ -1649,16 +1657,6 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _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<NSScreen *, DisplayWindowController *> _screenMap; //
- (void)doDisplayGapChanged:(float)displayGapScalar
{
_cdv->SetGapWithScalar(displayGapScalar);
OGLDisplayLayer *display = oglv->GetDisplayLayer();
display->SetGapScalar((GLfloat)displayGapScalar);
@ -2439,16 +2356,6 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _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 -

View File

@ -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];

View File

@ -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()

View File

@ -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);