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 */; }; ABACB8DC1710B621003B845D /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABACB8DB1710B621003B845D /* AudioToolbox.framework */; };
ABACB8DD1710B656003B845D /* 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 */; }; 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 */; }; ABAD3E7113AF1D6D00502E1E /* AAFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABAD3E6513AF1D6D00502E1E /* AAFilter.cpp */; };
ABAD3E7413AF1D6D00502E1E /* FIFOSampleBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABAD3E6813AF1D6D00502E1E /* FIFOSampleBuffer.cpp */; }; ABAD3E7413AF1D6D00502E1E /* FIFOSampleBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABAD3E6813AF1D6D00502E1E /* FIFOSampleBuffer.cpp */; };
ABAD3E7513AF1D6D00502E1E /* FIRFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABAD3E6913AF1D6D00502E1E /* FIRFilter.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>"; }; 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>"; }; 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; }; 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>"; }; 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>"; }; 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>"; }; ABAD3E5B13AF1D6D00502E1E /* cpu_detect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu_detect.h; sourceTree = "<group>"; };
@ -1953,6 +1958,7 @@
AB3ACB6514C2361100D7D192 /* userinterface */, AB3ACB6514C2361100D7D192 /* userinterface */,
AB82445A1704AE9A00B8EE20 /* utilities.c */, AB82445A1704AE9A00B8EE20 /* utilities.c */,
ABD10AE51715FCDD00B5729D /* audiosamplegenerator.cpp */, ABD10AE51715FCDD00B5729D /* audiosamplegenerator.cpp */,
ABAD07DA1E19CAA6007867CA /* ClientDisplayView.cpp */,
AB1B9E5F1501A78000464647 /* coreaudiosound.cpp */, AB1B9E5F1501A78000464647 /* coreaudiosound.cpp */,
AB23567216C2F6F400DA782E /* macosx_10_5_compat.cpp */, AB23567216C2F6F400DA782E /* macosx_10_5_compat.cpp */,
ABD10AE61715FCDD00B5729D /* mic_ext.cpp */, ABD10AE61715FCDD00B5729D /* mic_ext.cpp */,
@ -1961,6 +1967,7 @@
AB1B9E601501A78000464647 /* ringbuffer.cpp */, AB1B9E601501A78000464647 /* ringbuffer.cpp */,
ABD104141346652500AF11D1 /* sndOSX.cpp */, ABD104141346652500AF11D1 /* sndOSX.cpp */,
ABD10AE31715FCDD00B5729D /* audiosamplegenerator.h */, ABD10AE31715FCDD00B5729D /* audiosamplegenerator.h */,
ABAD07DB1E19CAA6007867CA /* ClientDisplayView.h */,
ABA6574914511EC90077E5E9 /* cocoa_cheat.h */, ABA6574914511EC90077E5E9 /* cocoa_cheat.h */,
ABD103FE1346652500AF11D1 /* cocoa_core.h */, ABD103FE1346652500AF11D1 /* cocoa_core.h */,
AB58F32B1364F44B0074C376 /* cocoa_file.h */, AB58F32B1364F44B0074C376 /* cocoa_file.h */,
@ -3781,6 +3788,7 @@
AB6FBEF6139B6258007BB045 /* slot1_retail_nand.cpp in Sources */, AB6FBEF6139B6258007BB045 /* slot1_retail_nand.cpp in Sources */,
ABCFA9F5178BDE920030C8BA /* encrypt.cpp in Sources */, ABCFA9F5178BDE920030C8BA /* encrypt.cpp in Sources */,
ABD1FF0E1345AC9C00AF11D1 /* slot2_expMemory.cpp in Sources */, ABD1FF0E1345AC9C00AF11D1 /* slot2_expMemory.cpp in Sources */,
ABAD07DE1E19CAA6007867CA /* ClientDisplayView.cpp in Sources */,
ABD1FF0F1345AC9C00AF11D1 /* slot2_gbagame.cpp in Sources */, ABD1FF0F1345AC9C00AF11D1 /* slot2_gbagame.cpp in Sources */,
ABD1FF101345AC9C00AF11D1 /* slot2_guitarGrip.cpp in Sources */, ABD1FF101345AC9C00AF11D1 /* slot2_guitarGrip.cpp in Sources */,
AB000DD21CCC6B3A00413F02 /* file_path.c in Sources */, AB000DD21CCC6B3A00413F02 /* file_path.c in Sources */,
@ -3938,6 +3946,7 @@
ABFEA8341BB4EC1100B08C25 /* ftmm.c in Sources */, ABFEA8341BB4EC1100B08C25 /* ftmm.c in Sources */,
AB4C81E41B21676C00ACECD5 /* hq3x.cpp in Sources */, AB4C81E41B21676C00ACECD5 /* hq3x.cpp in Sources */,
AB796CF815CDCBA200C59155 /* cp15.cpp in Sources */, AB796CF815CDCBA200C59155 /* cp15.cpp in Sources */,
ABAD07DC1E19CAA6007867CA /* ClientDisplayView.cpp in Sources */,
AB796CF915CDCBA200C59155 /* cpu_detect_x86_gcc.cpp in Sources */, AB796CF915CDCBA200C59155 /* cpu_detect_x86_gcc.cpp in Sources */,
AB796CFA15CDCBA200C59155 /* crc.cpp in Sources */, AB796CFA15CDCBA200C59155 /* crc.cpp in Sources */,
AB301BDF1D9C8BAC00246A93 /* deposterize.cpp in Sources */, AB301BDF1D9C8BAC00246A93 /* deposterize.cpp in Sources */,
@ -4266,6 +4275,7 @@
AB8F3CD11A53AC2600A80BF6 /* slot2_passme.cpp in Sources */, AB8F3CD11A53AC2600A80BF6 /* slot2_passme.cpp in Sources */,
AB8F3CD21A53AC2600A80BF6 /* WavFile.cpp in Sources */, AB8F3CD21A53AC2600A80BF6 /* WavFile.cpp in Sources */,
AB8F3CD31A53AC2600A80BF6 /* wifi.cpp in Sources */, AB8F3CD31A53AC2600A80BF6 /* wifi.cpp in Sources */,
ABAD07DD1E19CAA6007867CA /* ClientDisplayView.cpp in Sources */,
AB8F3CD41A53AC2600A80BF6 /* slot1_retail_mcrom.cpp in Sources */, AB8F3CD41A53AC2600A80BF6 /* slot1_retail_mcrom.cpp in Sources */,
AB8F3CD51A53AC2600A80BF6 /* xstring.cpp in Sources */, AB8F3CD51A53AC2600A80BF6 /* xstring.cpp in Sources */,
AB8F3CD61A53AC2600A80BF6 /* main.m 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 */; }; 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 */; }; 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 */; }; 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 */; }; 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 */; }; 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 */; }; 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>"; }; 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>"; }; 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; }; 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>"; }; 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>"; }; 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>"; }; 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 */, AB3ACB6514C2361100D7D192 /* userinterface */,
AB2F56EF1704C86900E28885 /* utilities.c */, AB2F56EF1704C86900E28885 /* utilities.c */,
AB2145221714DFF4006DDB0F /* audiosamplegenerator.cpp */, AB2145221714DFF4006DDB0F /* audiosamplegenerator.cpp */,
AB0F13911E1B7C320075684F /* ClientDisplayView.cpp */,
ABD0A5341501AA5A0074A094 /* coreaudiosound.cpp */, ABD0A5341501AA5A0074A094 /* coreaudiosound.cpp */,
ABD9A46413DB99B300777194 /* mic_ext.cpp */, ABD9A46413DB99B300777194 /* mic_ext.cpp */,
ABECB51318A460910052D52A /* OGLDisplayOutput.cpp */, ABECB51318A460910052D52A /* OGLDisplayOutput.cpp */,
ABD0A5351501AA5A0074A094 /* ringbuffer.cpp */, ABD0A5351501AA5A0074A094 /* ringbuffer.cpp */,
ABD104141346652500AF11D1 /* sndOSX.cpp */, ABD104141346652500AF11D1 /* sndOSX.cpp */,
AB2145211714DFF4006DDB0F /* audiosamplegenerator.h */, AB2145211714DFF4006DDB0F /* audiosamplegenerator.h */,
AB0F13901E1B7C320075684F /* ClientDisplayView.h */,
ABA6574914511EC90077E5E9 /* cocoa_cheat.h */, ABA6574914511EC90077E5E9 /* cocoa_cheat.h */,
ABD103FE1346652500AF11D1 /* cocoa_core.h */, ABD103FE1346652500AF11D1 /* cocoa_core.h */,
AB58F32B1364F44B0074C376 /* cocoa_file.h */, AB58F32B1364F44B0074C376 /* cocoa_file.h */,
@ -4529,6 +4538,7 @@
ABD21B5C1DE900D3001D2DFA /* Database.cpp in Sources */, ABD21B5C1DE900D3001D2DFA /* Database.cpp in Sources */,
ABD21B631DE9010B001D2DFA /* features_cpu.c in Sources */, ABD21B631DE9010B001D2DFA /* features_cpu.c in Sources */,
AB2C25081DEBFBD400706BFC /* encoding_utf.c in Sources */, AB2C25081DEBFBD400706BFC /* encoding_utf.c in Sources */,
AB0F13931E1B7C320075684F /* ClientDisplayView.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -4710,6 +4720,7 @@
ABD21B5D1DE900D3001D2DFA /* Database.cpp in Sources */, ABD21B5D1DE900D3001D2DFA /* Database.cpp in Sources */,
ABD21B641DE9010B001D2DFA /* features_cpu.c in Sources */, ABD21B641DE9010B001D2DFA /* features_cpu.c in Sources */,
AB2C25091DEBFBD400706BFC /* encoding_utf.c in Sources */, AB2C25091DEBFBD400706BFC /* encoding_utf.c in Sources */,
AB0F13941E1B7C320075684F /* ClientDisplayView.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -4921,6 +4932,7 @@
ABD21B5B1DE900D3001D2DFA /* Database.cpp in Sources */, ABD21B5B1DE900D3001D2DFA /* Database.cpp in Sources */,
ABD21B621DE9010B001D2DFA /* features_cpu.c in Sources */, ABD21B621DE9010B001D2DFA /* features_cpu.c in Sources */,
AB2C25071DEBFBD400706BFC /* encoding_utf.c in Sources */, AB2C25071DEBFBD400706BFC /* encoding_utf.c in Sources */,
AB0F13921E1B7C320075684F /* ClientDisplayView.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -5132,6 +5144,7 @@
ABD21B5F1DE900D3001D2DFA /* Database.cpp in Sources */, ABD21B5F1DE900D3001D2DFA /* Database.cpp in Sources */,
ABD21B661DE9010B001D2DFA /* features_cpu.c in Sources */, ABD21B661DE9010B001D2DFA /* features_cpu.c in Sources */,
AB2C250B1DEBFBD400706BFC /* encoding_utf.c in Sources */, AB2C250B1DEBFBD400706BFC /* encoding_utf.c in Sources */,
AB0F13961E1B7C320075684F /* ClientDisplayView.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -5313,6 +5326,7 @@
ABD21B5E1DE900D3001D2DFA /* Database.cpp in Sources */, ABD21B5E1DE900D3001D2DFA /* Database.cpp in Sources */,
ABD21B651DE9010B001D2DFA /* features_cpu.c in Sources */, ABD21B651DE9010B001D2DFA /* features_cpu.c in Sources */,
AB2C250A1DEBFBD400706BFC /* encoding_utf.c in Sources */, AB2C250A1DEBFBD400706BFC /* encoding_utf.c in Sources */,
AB0F13951E1B7C320075684F /* ClientDisplayView.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; 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 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 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 w = this->_viewportWidth;
const double h = this->_viewportHeight; 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) if (this->_canUseShaderOutput)
{ {
@ -6742,11 +6742,11 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO)
_gapScalar = 0.0f; _gapScalar = 0.0f;
_rotation = 0.0f; _rotation = 0.0f;
_normalWidth = GPU_DISPLAY_WIDTH; _normalWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH;
_normalHeight = GPU_DISPLAY_HEIGHT*2.0 + (DS_DISPLAY_UNSCALED_GAP*_gapScalar); _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[0] = new VideoFilter(GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, VideoFilterTypeID_None, 0);
_vf[1] = new VideoFilter(GPU_DISPLAY_WIDTH, GPU_DISPLAY_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)); _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); _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[0] = true;
_isTexVideoInputDataNative[1] = true; _isTexVideoInputDataNative[1] = true;
_texLoadedWidth[0] = (GLfloat)GPU_DISPLAY_WIDTH; _texLoadedWidth[0] = (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH;
_texLoadedWidth[1] = (GLfloat)GPU_DISPLAY_WIDTH; _texLoadedWidth[1] = (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH;
_texLoadedHeight[0] = (GLfloat)GPU_DISPLAY_HEIGHT; _texLoadedHeight[0] = (GLfloat)GPU_FRAMEBUFFER_NATIVE_HEIGHT;
_texLoadedHeight[1] = (GLfloat)GPU_DISPLAY_HEIGHT; _texLoadedHeight[1] = (GLfloat)GPU_FRAMEBUFFER_NATIVE_HEIGHT;
_videoColorFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV; _videoColorFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV;
_videoSrcBufferHead = NULL; _videoSrcBufferHead = NULL;
@ -6769,10 +6769,10 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO)
_videoSrcNativeBuffer[1] = NULL; _videoSrcNativeBuffer[1] = NULL;
_videoSrcCustomBuffer[0] = NULL; _videoSrcCustomBuffer[0] = NULL;
_videoSrcCustomBuffer[1] = NULL; _videoSrcCustomBuffer[1] = NULL;
_videoSrcCustomBufferWidth[0] = GPU_DISPLAY_WIDTH; _videoSrcCustomBufferWidth[0] = GPU_FRAMEBUFFER_NATIVE_WIDTH;
_videoSrcCustomBufferWidth[1] = GPU_DISPLAY_WIDTH; _videoSrcCustomBufferWidth[1] = GPU_FRAMEBUFFER_NATIVE_WIDTH;
_videoSrcCustomBufferHeight[0] = GPU_DISPLAY_HEIGHT; _videoSrcCustomBufferHeight[0] = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
_videoSrcCustomBufferHeight[1] = GPU_DISPLAY_HEIGHT; _videoSrcCustomBufferHeight[1] = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
// Set up textures // Set up textures
glGenTextures(2, _texCPUFilterDstID); 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_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_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_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]); 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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_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_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_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]); 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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_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_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_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]); 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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_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_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_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); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
@ -7045,7 +7045,7 @@ void OGLDisplayLayer::SetVideoBuffers(const uint32_t colorFormat,
this->_videoColorFormat = glColorFormat; this->_videoColorFormat = glColorFormat;
this->_videoSrcBufferHead = videoBufferHead; 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[0] = nativeBuffer0;
this->_videoSrcNativeBuffer[1] = nativeBuffer1; this->_videoSrcNativeBuffer[1] = nativeBuffer1;
this->_videoSrcCustomBuffer[0] = customBuffer0; this->_videoSrcCustomBuffer[0] = customBuffer0;
@ -7067,11 +7067,11 @@ void OGLDisplayLayer::SetVideoBuffers(const uint32_t colorFormat,
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[0]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[0]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); 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]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[1]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); 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]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataCustomID[0]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); 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) void OGLDisplayLayer::SetMode(const ClientDisplayMode dispMode)
{ {
this->_displayMode = 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; this->_needUpdateVertices = true;
} }
@ -7136,7 +7136,7 @@ ClientDisplayLayout OGLDisplayLayer::GetOrientation() const
void OGLDisplayLayer::SetOrientation(ClientDisplayLayout dispOrientation) void OGLDisplayLayer::SetOrientation(ClientDisplayLayout dispOrientation)
{ {
this->_displayOrientation = 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; this->_needUpdateVertices = true;
} }
@ -7148,7 +7148,7 @@ double OGLDisplayLayer::GetGapScalar() const
void OGLDisplayLayer::SetGapScalar(double theScalar) void OGLDisplayLayer::SetGapScalar(double theScalar)
{ {
this->_gapScalar = 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; this->_needUpdateVertices = true;
} }
@ -7214,20 +7214,20 @@ void OGLDisplayLayer::UpdateVerticesOGL()
case ClientDisplayLayout_Hybrid_3_2: 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[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[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[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[14] = w; vtxBufferPtr[15] = -h; // Minor bottom display, bottom right
vtxBufferPtr[16] = -w; vtxBufferPtr[17] = h; // Major display, top left 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[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) memcpy(vtxBufferPtr + (3 * 8), vtxBufferPtr + (2 * 8), sizeof(GLfloat) * (1 * 8)); // Major display (bottom screen)
break; break;
@ -7235,22 +7235,22 @@ void OGLDisplayLayer::UpdateVerticesOGL()
case ClientDisplayLayout_Hybrid_16_9: 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[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[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[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[14] = w; vtxBufferPtr[15] = -h; // Minor bottom display, bottom right
vtxBufferPtr[16] = -w; vtxBufferPtr[17] = h; // Major display, top left 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[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) memcpy(vtxBufferPtr + (3 * 8), vtxBufferPtr + (2 * 8), sizeof(GLfloat) * (1 * 8)); // Major display (bottom screen)
break; break;
@ -7258,22 +7258,22 @@ void OGLDisplayLayer::UpdateVerticesOGL()
case ClientDisplayLayout_Hybrid_16_10: 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[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[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[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[14] = w; vtxBufferPtr[15] = -h; // Minor bottom display, bottom right
vtxBufferPtr[16] = -w; vtxBufferPtr[17] = h; // Major display, top left 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[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) memcpy(vtxBufferPtr + (3 * 8), vtxBufferPtr + (2 * 8), sizeof(GLfloat) * (1 * 8)); // Major display (bottom screen)
break; break;
@ -7374,8 +7374,11 @@ void OGLDisplayLayer::UploadTransformationOGL()
{ {
const GLdouble w = this->_viewportWidth; const GLdouble w = this->_viewportWidth;
const GLdouble h = this->_viewportHeight; 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()) if (this->_output->GetInfo()->IsShaderSupported())
{ {
@ -7391,7 +7394,7 @@ void OGLDisplayLayer::UploadTransformationOGL()
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); 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); glScalef(s, s, 1.0f);
} }
@ -7802,10 +7805,10 @@ void OGLDisplayLayer::LoadFrameOGL(bool isMainSizeNative, bool isTouchSizeNative
this->_isTexVideoInputDataNative[0] = isMainSizeNative; this->_isTexVideoInputDataNative[0] = isMainSizeNative;
this->_isTexVideoInputDataNative[1] = isTouchSizeNative; this->_isTexVideoInputDataNative[1] = isTouchSizeNative;
this->_texLoadedWidth[0] = (this->_isTexVideoInputDataNative[0]) ? (GLfloat)GPU_DISPLAY_WIDTH : (GLfloat)this->_videoSrcCustomBufferWidth[0]; this->_texLoadedWidth[0] = (this->_isTexVideoInputDataNative[0]) ? (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH : (GLfloat)this->_videoSrcCustomBufferWidth[0];
this->_texLoadedHeight[0] = (this->_isTexVideoInputDataNative[0]) ? (GLfloat)GPU_DISPLAY_HEIGHT : (GLfloat)this->_videoSrcCustomBufferHeight[0]; this->_texLoadedHeight[0] = (this->_isTexVideoInputDataNative[0]) ? (GLfloat)GPU_FRAMEBUFFER_NATIVE_HEIGHT : (GLfloat)this->_videoSrcCustomBufferHeight[0];
this->_texLoadedWidth[1] = (this->_isTexVideoInputDataNative[1]) ? (GLfloat)GPU_DISPLAY_WIDTH : (GLfloat)this->_videoSrcCustomBufferWidth[1]; this->_texLoadedWidth[1] = (this->_isTexVideoInputDataNative[1]) ? (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH : (GLfloat)this->_videoSrcCustomBufferWidth[1];
this->_texLoadedHeight[1] = (this->_isTexVideoInputDataNative[1]) ? (GLfloat)GPU_DISPLAY_HEIGHT : (GLfloat)this->_videoSrcCustomBufferHeight[1]; this->_texLoadedHeight[1] = (this->_isTexVideoInputDataNative[1]) ? (GLfloat)GPU_FRAMEBUFFER_NATIVE_HEIGHT : (GLfloat)this->_videoSrcCustomBufferHeight[1];
if (loadMainScreen) if (loadMainScreen)
{ {
@ -7824,7 +7827,7 @@ void OGLDisplayLayer::LoadFrameOGL(bool isMainSizeNative, bool isTouchSizeNative
if (!isUsingCPUPixelScaler || this->_useDeposterize) if (!isUsingCPUPixelScaler || this->_useDeposterize)
{ {
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[0]); 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); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
glFlush(); glFlush();
} }
@ -7832,11 +7835,11 @@ void OGLDisplayLayer::LoadFrameOGL(bool isMainSizeNative, bool isTouchSizeNative
{ {
if (this->_videoColorFormat == GL_UNSIGNED_SHORT_1_5_5_5_REV) 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 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) if (!isUsingCPUPixelScaler || this->_useDeposterize)
{ {
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[1]); 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); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
glFlush(); glFlush();
} }
@ -7874,11 +7877,11 @@ void OGLDisplayLayer::LoadFrameOGL(bool isMainSizeNative, bool isTouchSizeNative
{ {
if (this->_videoColorFormat == GL_UNSIGNED_SHORT_1_5_5_5_REV) 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 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[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]) ); 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 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 it under the terms of the GNU General Public License as published by
@ -31,6 +31,8 @@
#include <string> #include <string>
#include "../../filter/videofilter.h" #include "../../filter/videofilter.h"
#include "ClientDisplayView.h"
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
@ -43,28 +45,6 @@
class OGLVideoOutput; class OGLVideoOutput;
struct NDSFrameInfo; 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 enum OutputFilterTypeID
{ {
OutputFilterTypeID_NearestNeighbor = 0, OutputFilterTypeID_NearestNeighbor = 0,
@ -504,8 +484,6 @@ public:
virtual void ProcessOGL(); virtual void ProcessOGL();
virtual void RenderOGL(); virtual void RenderOGL();
virtual void FinishOGL(); virtual void FinishOGL();
static void CalculateNormalSize(const ClientDisplayMode mode, const ClientDisplayLayout layout, const double gapScalar, double &outWidth, double &outHeight);
}; };
class OGLVideoOutput 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 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 it under the terms of the GNU General Public License as published by
@ -216,7 +216,7 @@ public:
- (void) setGpuScale:(NSUInteger)theScale - (void) setGpuScale:(NSUInteger)theScale
{ {
_gpuScale = (uint8_t)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 - (NSUInteger) gpuScale

View File

@ -1,6 +1,6 @@
/* /*
Copyright (C) 2011 Roger Manuel 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 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 it under the terms of the GNU General Public License as published by
@ -185,13 +185,6 @@
#define CHEAT_DESCRIPTION_LENGTH 1024 #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 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. #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 // Set up the DS display
displayMode = ClientDisplayMode_Dual; 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); displayAspectRatio = OEIntSizeMake(2, 3);
return self; return self;
@ -154,17 +154,17 @@ volatile bool execute = true;
switch (theMode) switch (theMode)
{ {
case ClientDisplayMode_Main: 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); newDisplayAspectRatio = OEIntSizeMake(4, 3);
break; break;
case ClientDisplayMode_Touch: 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); newDisplayAspectRatio = OEIntSizeMake(4, 3);
break; break;
case ClientDisplayMode_Dual: 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); newDisplayAspectRatio = OEIntSizeMake(2, 3);
break; break;
@ -280,7 +280,7 @@ volatile bool execute = true;
- (OEIntSize)bufferSize - (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 - (const void *)videoBuffer
@ -396,7 +396,7 @@ volatile bool execute = true;
case ClientDisplayMode_Dual: case ClientDisplayMode_Dual:
isTouchPressed = YES; 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; break;
default: default:
@ -409,18 +409,18 @@ volatile bool execute = true;
{ {
aPoint.x = 0; 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) if (aPoint.y < 0)
{ {
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); 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 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 it under the terms of the GNU General Public License as published by
@ -23,12 +23,13 @@
#import "InputManager.h" #import "InputManager.h"
#import "cocoa_output.h" #import "cocoa_output.h"
#include "../ClientDisplayView.h"
#undef BOOL
@class CocoaDSController; @class CocoaDSController;
@class EmuControllerDelegate; @class EmuControllerDelegate;
class OGLVideoOutput; 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. // Subclass NSWindow for full screen windows so that we can override some methods.
@interface DisplayFullScreenWindow : NSWindow @interface DisplayFullScreenWindow : NSWindow
{ } { }
@ -37,7 +38,7 @@ typedef std::map<int, bool> InitialTouchPressMap; // Key = An ID number of the
@interface DisplayView : NSView <CocoaDSDisplayVideoDelegate, InputHIDManagerTarget> @interface DisplayView : NSView <CocoaDSDisplayVideoDelegate, InputHIDManagerTarget>
{ {
InputManager *inputManager; InputManager *inputManager;
InitialTouchPressMap *_initialTouchInMajorDisplay; ClientDisplayView *_cdv;
OGLVideoOutput *oglv; OGLVideoOutput *oglv;
BOOL canUseShaderBasedFilters; BOOL canUseShaderBasedFilters;
@ -56,7 +57,6 @@ typedef std::map<int, bool> InitialTouchPressMap; // Key = An ID number of the
} }
@property (retain) InputManager *inputManager; @property (retain) InputManager *inputManager;
@property (readonly) NSSize normalSize;
@property (readonly) BOOL canUseShaderBasedFilters; @property (readonly) BOOL canUseShaderBasedFilters;
@property (assign) BOOL isHUDVisible; @property (assign) BOOL isHUDVisible;
@property (assign) BOOL isHUDVideoFPSVisible; @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) setScaleFactor:(float)theScaleFactor;
- (void) drawVideoFrame; - (void) drawVideoFrame;
- (NSPoint) dsPointFromEvent:(NSEvent *)theEvent inputID:(const NSInteger)inputID; - (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) handleKeyPress:(NSEvent *)theEvent keyPressed:(BOOL)keyPressed;
- (BOOL) handleMouseButton:(NSEvent *)theEvent buttonPressed:(BOOL)buttonPressed; - (BOOL) handleMouseButton:(NSEvent *)theEvent buttonPressed:(BOOL)buttonPressed;
- (void) requestScreenshot:(NSURL *)fileURL fileType:(NSBitmapImageFileType)fileType; - (void) requestScreenshot:(NSURL *)fileURL fileType:(NSBitmapImageFileType)fileType;
+ (NSSize) calculateNormalSizeUsingMode:(const NSInteger)mode layout:(const NSInteger)layout gapScalar:(const double)gapScalar;
@end @end
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 #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; NSObject *dummyObject;
DisplayView *view; DisplayView *view;
ClientDisplayViewProperties _localViewProps;
NSView *saveScreenshotPanelAccessoryView; NSView *saveScreenshotPanelAccessoryView;
NSView *outputVolumeControlView; NSView *outputVolumeControlView;
NSView *microphoneGainControlView; NSView *microphoneGainControlView;
@ -105,12 +103,6 @@ typedef std::map<int, bool> InitialTouchPressMap; // Key = An ID number of the
NSScreen *assignedScreen; NSScreen *assignedScreen;
NSWindow *masterWindow; NSWindow *masterWindow;
double _displayScale;
double _displayRotation;
NSInteger _displayMode;
NSInteger _displayOrientation;
NSInteger _displayOrder;
double _displayGap;
NSInteger screenshotFileFormat; NSInteger screenshotFileFormat;
NSSize _minDisplayViewSize; NSSize _minDisplayViewSize;
@ -146,7 +138,6 @@ typedef std::map<int, bool> InitialTouchPressMap; // Key = An ID number of the
@property (assign) NSScreen *assignedScreen; @property (assign) NSScreen *assignedScreen;
@property (retain) NSWindow *masterWindow; @property (retain) NSWindow *masterWindow;
@property (readonly) NSSize normalSize;
@property (assign) double displayScale; @property (assign) double displayScale;
@property (assign) double displayRotation; @property (assign) double displayRotation;
@property (assign) BOOL videoFiltersPreferGPU; @property (assign) BOOL videoFiltersPreferGPU;
@ -167,7 +158,7 @@ typedef std::map<int, bool> InitialTouchPressMap; // Key = An ID number of the
- (BOOL) masterStatusBarState; - (BOOL) masterStatusBarState;
- (NSRect) masterWindowFrame; - (NSRect) masterWindowFrame;
- (double) masterWindowScale; - (double) masterWindowScale;
- (double) resizeWithTransform:(NSSize)normalBounds scalar:(double)scalar rotation:(double)angleDegrees; - (void) resizeWithTransform;
- (double) maxScalarForContentBoundsWidth:(double)contentBoundsWidth height:(double)contentBoundsHeight; - (double) maxScalarForContentBoundsWidth:(double)contentBoundsWidth height:(double)contentBoundsHeight;
- (void) enterFullScreen; - (void) enterFullScreen;
- (void) exitFullScreen; - (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 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 it under the terms of the GNU General Public License as published by
@ -59,7 +59,6 @@
@synthesize microphoneGainSlider; @synthesize microphoneGainSlider;
@synthesize microphoneMuteButton; @synthesize microphoneMuteButton;
@dynamic normalSize;
@dynamic displayScale; @dynamic displayScale;
@dynamic displayRotation; @dynamic displayRotation;
@dynamic videoFiltersPreferGPU; @dynamic videoFiltersPreferGPU;
@ -106,17 +105,25 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
screenshotFileFormat = NSTIFFFileType; screenshotFileFormat = NSTIFFFileType;
// These need to be initialized first since there are dependencies on these. // These need to be initialized first since there are dependencies on these.
_displayGap = 0.0; _localViewProps.normalWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH;
_displayMode = ClientDisplayMode_Dual; _localViewProps.normalHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2.0;
_displayOrientation = ClientDisplayLayout_Vertical; _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; _isMinSizeNormal = YES;
_statusBarHeight = WINDOW_STATUS_BAR_HEIGHT; _statusBarHeight = WINDOW_STATUS_BAR_HEIGHT;
_isUpdatingDisplayScaleValueOnly = NO; _isUpdatingDisplayScaleValueOnly = NO;
_useMavericksFullScreen = IsOSXVersionSupported(10, 9, 0); _useMavericksFullScreen = IsOSXVersionSupported(10, 9, 0);
_masterWindowScale = 1.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; _masterStatusBarState = NO;
[[NSNotificationCenter defaultCenter] addObserver:self [[NSNotificationCenter defaultCenter] addObserver:self
@ -147,30 +154,25 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void) setDisplayScale:(double)s - (void) setDisplayScale:(double)s
{ {
// There are two ways that this property is used: // 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 // 2. Resize the window as a result of setting displayScale
// //
// Use the _isUpdatingDisplayScaleValueOnly flag to control this property's behavior. // 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. // 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 - (double) displayScale
{ {
OSSpinLockLock(&spinlockScale); OSSpinLockLock(&spinlockScale);
const double s = _displayScale; const double s = _localViewProps.viewScale;
OSSpinLockUnlock(&spinlockScale); OSSpinLockUnlock(&spinlockScale);
return s; return s;
@ -190,26 +192,23 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
} }
OSSpinLockLock(&spinlockRotation); OSSpinLockLock(&spinlockRotation);
_displayRotation = newAngleDegrees; _localViewProps.rotation = newAngleDegrees;
OSSpinLockUnlock(&spinlockRotation); OSSpinLockUnlock(&spinlockRotation);
NSWindow *theWindow = [self window]; NSWindow *theWindow = [self window];
// Set the minimum content size for the window, since this will change based on rotation. // 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)); double contentMinWidth = _minDisplayViewSize.width;
minContentSize.height += _statusBarHeight; double contentMinHeight = _minDisplayViewSize.height;
[theWindow setContentMinSize:NSMakeSize(minContentSize.width, minContentSize.height)]; ClientDisplayView::ConvertNormalToTransformedBounds(1.0, CLOCKWISE_DEGREES(newAngleDegrees), contentMinWidth, contentMinHeight);
contentMinHeight += _statusBarHeight;
[theWindow setContentMinSize:NSMakeSize(contentMinWidth, contentMinHeight)];
// Resize the window. // Resize the window.
const NSSize oldBounds = [theWindow frame].size; const NSSize oldBounds = [theWindow frame].size;
const NSSize newNormalSize = [DisplayView calculateNormalSizeUsingMode:[self displayMode] layout:[self displayOrientation] gapScalar:[self displayGap]]; [self resizeWithTransform];
const double constrainedScale = [self resizeWithTransform:newNormalSize scalar:[self displayScale] rotation:newAngleDegrees];
const NSSize newBounds = [theWindow frame].size; 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 // 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 // are 180 degrees offset from each other. In this case, we'll need to force the
// display view to update itself. // display view to update itself.
@ -218,8 +217,8 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
[view setNeedsDisplay:YES]; [view setNeedsDisplay:YES];
} }
DisplayOutputTransformData transformData = { constrainedScale, DisplayOutputTransformData transformData = { _localViewProps.viewScale,
angleDegrees, newAngleDegrees,
0.0, 0.0,
0.0, 0.0,
0.0 }; 0.0 };
@ -232,7 +231,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (double) displayRotation - (double) displayRotation
{ {
OSSpinLockLock(&spinlockRotation); OSSpinLockLock(&spinlockRotation);
const double angleDegrees = _displayRotation; const double angleDegrees = _localViewProps.rotation;
OSSpinLockUnlock(&spinlockRotation); OSSpinLockUnlock(&spinlockRotation);
return angleDegrees; return angleDegrees;
@ -261,12 +260,12 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
} }
OSSpinLockLock(&spinlockDisplayMode); OSSpinLockLock(&spinlockDisplayMode);
_displayMode = displayModeID; _localViewProps.mode = (ClientDisplayMode)displayModeID;
OSSpinLockUnlock(&spinlockDisplayMode); 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 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]; [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 - (NSInteger) displayMode
{ {
OSSpinLockLock(&spinlockDisplayMode); OSSpinLockLock(&spinlockDisplayMode);
const NSInteger displayModeID = _displayMode; const NSInteger displayModeID = _localViewProps.mode;
OSSpinLockUnlock(&spinlockDisplayMode); OSSpinLockUnlock(&spinlockDisplayMode);
return displayModeID; return displayModeID;
@ -283,14 +282,15 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void) setDisplayOrientation:(NSInteger)theOrientation - (void) setDisplayOrientation:(NSInteger)theOrientation
{ {
OSSpinLockLock(&spinlockDisplayOrientation); OSSpinLockLock(&spinlockDisplayOrientation);
_displayOrientation = theOrientation; _localViewProps.layout = (ClientDisplayLayout)theOrientation;
OSSpinLockUnlock(&spinlockDisplayOrientation); 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) if ([self displayMode] == ClientDisplayMode_Dual)
{ {
const NSSize newNormalSize = [DisplayView calculateNormalSizeUsingMode:[self displayMode] layout:[self displayOrientation] gapScalar:[self displayGap]]; [self resizeWithTransform];
[self setIsMinSizeNormal:[self isMinSizeNormal]];
[self resizeWithTransform:newNormalSize scalar:[self displayScale] rotation:[self displayRotation]];
} }
[CocoaDSUtil messageSendOneWayWithInteger:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_CHANGE_DISPLAY_ORIENTATION integerValue:theOrientation]; [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 - (NSInteger) displayOrientation
{ {
OSSpinLockLock(&spinlockDisplayOrientation); OSSpinLockLock(&spinlockDisplayOrientation);
const NSInteger theOrientation = _displayOrientation; const NSInteger theOrientation = _localViewProps.layout;
OSSpinLockUnlock(&spinlockDisplayOrientation); OSSpinLockUnlock(&spinlockDisplayOrientation);
return theOrientation; return theOrientation;
@ -308,7 +308,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void) setDisplayOrder:(NSInteger)theOrder - (void) setDisplayOrder:(NSInteger)theOrder
{ {
OSSpinLockLock(&spinlockDisplayOrder); OSSpinLockLock(&spinlockDisplayOrder);
_displayOrder = theOrder; _localViewProps.order = (ClientDisplayOrder)theOrder;
OSSpinLockUnlock(&spinlockDisplayOrder); OSSpinLockUnlock(&spinlockDisplayOrder);
[CocoaDSUtil messageSendOneWayWithInteger:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_CHANGE_DISPLAY_ORDER integerValue:theOrder]; [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 - (NSInteger) displayOrder
{ {
OSSpinLockLock(&spinlockDisplayOrder); OSSpinLockLock(&spinlockDisplayOrder);
const NSInteger theOrder = _displayOrder; const NSInteger theOrder = _localViewProps.order;
OSSpinLockUnlock(&spinlockDisplayOrder); OSSpinLockUnlock(&spinlockDisplayOrder);
return theOrder; return theOrder;
@ -326,14 +326,15 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void) setDisplayGap:(double)gapScalar - (void) setDisplayGap:(double)gapScalar
{ {
OSSpinLockLock(&spinlockDisplayGap); OSSpinLockLock(&spinlockDisplayGap);
_displayGap = gapScalar; _localViewProps.gapScale = gapScalar;
OSSpinLockUnlock(&spinlockDisplayGap); 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) if ([self displayMode] == ClientDisplayMode_Dual)
{ {
const NSSize newNormalSize = [DisplayView calculateNormalSizeUsingMode:[self displayMode] layout:[self displayOrientation] gapScalar:[self displayGap]]; [self resizeWithTransform];
[self setIsMinSizeNormal:[self isMinSizeNormal]];
[self resizeWithTransform:newNormalSize scalar:[self displayScale] rotation:[self displayRotation]];
} }
[CocoaDSUtil messageSendOneWayWithFloat:[[self cdsVideoOutput] receivePort] msgID:MESSAGE_CHANGE_DISPLAY_GAP floatValue:(float)gapScalar]; [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 - (double) displayGap
{ {
OSSpinLockLock(&spinlockDisplayGap); OSSpinLockLock(&spinlockDisplayGap);
const double gapScalar = _displayGap; const double gapScalar = _localViewProps.gapScale;
OSSpinLockUnlock(&spinlockDisplayGap); OSSpinLockUnlock(&spinlockDisplayGap);
return gapScalar; return gapScalar;
@ -395,18 +396,20 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void) setIsMinSizeNormal:(BOOL)theState - (void) setIsMinSizeNormal:(BOOL)theState
{ {
_isMinSizeNormal = theState; _isMinSizeNormal = theState;
_minDisplayViewSize = [DisplayView calculateNormalSizeUsingMode:[self displayMode] layout:[self displayOrientation] gapScalar:[self displayGap]]; _minDisplayViewSize.width = _localViewProps.normalWidth;
_minDisplayViewSize.height = _localViewProps.normalHeight;
if (!_isMinSizeNormal) if (!_isMinSizeNormal)
{ {
_minDisplayViewSize.width /= 4; _minDisplayViewSize.width /= 4.0;
_minDisplayViewSize.height /= 4; _minDisplayViewSize.height /= 4.0;
} }
// Set the minimum content size, keeping the display rotation in mind. // Set the minimum content size, keeping the display rotation in mind.
CGSize transformedMinSize = GetTransformedBounds(_minDisplayViewSize.width, _minDisplayViewSize.height, 1.0, CLOCKWISE_DEGREES([self displayRotation])); double transformedMinWidth = _minDisplayViewSize.width;
transformedMinSize.height += _statusBarHeight; double transformedMinHeight = _minDisplayViewSize.height;
[[self window] setContentMinSize:NSMakeSize(transformedMinSize.width, transformedMinSize.height)]; ClientDisplayView::ConvertNormalToTransformedBounds(1.0, CLOCKWISE_DEGREES([self displayRotation]), transformedMinWidth, transformedMinHeight);
[[self window] setContentMinSize:NSMakeSize(transformedMinWidth, transformedMinHeight + _statusBarHeight)];
} }
- (BOOL) isMinSizeNormal - (BOOL) isMinSizeNormal
@ -485,11 +488,6 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
//[[self view] setIsHUDInputVisible:[[NSUserDefaults standardUserDefaults] boolForKey:@"HUD_ShowInput"]]; //[[self view] setIsHUDInputVisible:[[NSUserDefaults standardUserDefaults] boolForKey:@"HUD_ShowInput"]];
} }
- (NSSize) normalSize
{
return [[self view] normalSize];
}
- (BOOL) masterStatusBarState - (BOOL) masterStatusBarState
{ {
return (([self assignedScreen] == nil) || !_useMavericksFullScreen) ? [self isShowingStatusBar] : _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; return (([self assignedScreen] == nil) || !_useMavericksFullScreen) ? [self displayScale] : _masterWindowScale;
} }
- (double) resizeWithTransform:(NSSize)normalBounds scalar:(double)scalar rotation:(double)angleDegrees - (void) resizeWithTransform
{ {
if ([self assignedScreen] != nil) if ([self assignedScreen] != nil)
{ {
return scalar; return;
} }
// Convert angle to clockwise-direction degrees. // 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. // Get the maximum scalar size within drawBounds. Constrain scalar to maxScalar if necessary.
const CGSize checkSize = GetTransformedBounds(normalBounds.width, normalBounds.height, 1.0, angleDegrees); double checkWidth = _localViewProps.normalWidth;
const double maxScalar = [self maxScalarForContentBoundsWidth:checkSize.width height:checkSize.height]; double checkHeight = _localViewProps.normalHeight;
if (scalar > maxScalar) 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. // 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. // Get the center of the content view in screen coordinates.
const NSRect windowContentRect = [[masterWindow contentView] bounds]; const NSRect windowContentRect = [[masterWindow contentView] bounds];
const double translationX = (windowContentRect.size.width - transformedBounds.width) / 2.0; const double translationX = (windowContentRect.size.width - transformedWidth) / 2.0;
const double translationY = ((windowContentRect.size.height - _statusBarHeight) - transformedBounds.height) / 2.0; const double translationY = ((windowContentRect.size.height - _statusBarHeight) - transformedHeight) / 2.0;
// Resize the window. // Resize the window.
const NSRect windowFrame = [masterWindow frame]; 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]; [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 - (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 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)) }; 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 - (void) saveScreenshotAsFinish:(NSNotification *)aNotification
@ -633,7 +635,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
} }
[self setWindow:masterWindow]; [self setWindow:masterWindow];
[self resizeWithTransform:[self normalSize] scalar:[self displayScale] rotation:[self displayRotation]]; [self resizeWithTransform];
NSRect viewFrame = [[masterWindow contentView] frame]; NSRect viewFrame = [[masterWindow contentView] frame];
viewFrame.size.height -= _statusBarHeight; viewFrame.size.height -= _statusBarHeight;
@ -755,16 +757,18 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
[self setIsMinSizeNormal:YES]; [self setIsMinSizeNormal:YES];
// Set the minimum content size, keeping the display rotation in mind. // Set the minimum content size, keeping the display rotation in mind.
CGSize transformedMinSize = GetTransformedBounds(_minDisplayViewSize.width, _minDisplayViewSize.height, 1.0, CLOCKWISE_DEGREES([self displayRotation])); double transformedMinWidth = _minDisplayViewSize.width;
transformedMinSize.height += _statusBarHeight; 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. // Resize the window if it's smaller than the minimum content size.
NSRect windowContentRect = [masterWindow contentRectForFrameRect:[masterWindow frame]]; 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. // Prepare to resize.
NSRect oldFrameRect = [masterWindow frame]; NSRect oldFrameRect = [masterWindow frame];
windowContentRect.size = NSMakeSize(transformedMinSize.width, transformedMinSize.height); windowContentRect.size = NSMakeSize(transformedMinWidth, transformedMinHeight);
NSRect newFrameRect = [masterWindow frameRectForContentRect:windowContentRect]; NSRect newFrameRect = [masterWindow frameRectForContentRect:windowContentRect];
// Keep the window centered when expanding the size. // 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 // Find the maximum scalar we can use for the display view, bounded by the
// content Rect. // content Rect.
const NSSize normalBounds = [self normalSize]; double checkWidth = _localViewProps.normalWidth;
const CGSize checkSize = GetTransformedBounds(normalBounds.width, normalBounds.height, 1.0, [self displayRotation]); double checkHeight = _localViewProps.normalHeight;
ClientDisplayView::ConvertNormalToTransformedBounds(1.0, [self displayRotation], checkWidth, checkHeight);
const NSSize contentBounds = NSMakeSize(contentRect.size.width, contentRect.size.height - _statusBarHeight); 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. // 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]; const NSRect finalFrameRect = [sender frameRectForContentRect:finalContentRect];
// Set the final size based on our new frame Rect. // 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. // Get the max scalar within the window's current content bounds.
const NSSize normalBounds = [self normalSize]; double checkWidth = _localViewProps.normalWidth;
const CGSize checkSize = GetTransformedBounds(normalBounds.width, normalBounds.height, 1.0, [self displayRotation]); double checkHeight = _localViewProps.normalHeight;
ClientDisplayView::ConvertNormalToTransformedBounds(1.0, [self displayRotation], checkWidth, checkHeight);
NSSize contentBounds = [[[self window] contentView] bounds].size; NSSize contentBounds = [[[self window] contentView] bounds].size;
contentBounds.height -= _statusBarHeight; 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. // Since we are already resizing, only update the displayScale property here.
_isUpdatingDisplayScaleValueOnly = YES; _isUpdatingDisplayScaleValueOnly = YES;
[self setDisplayScale:maxS]; [self setDisplayScale:constrainedScale];
_isUpdatingDisplayScaleValueOnly = NO; _isUpdatingDisplayScaleValueOnly = NO;
// Resize the view. // 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 // Find the maximum scalar we can use for the display view, bounded by the
// content Rect. // content Rect.
const NSSize normalBounds = [self normalSize]; double checkWidth = _localViewProps.normalWidth;
const CGSize checkSize = GetTransformedBounds(normalBounds.width, normalBounds.height, 1.0, [self displayRotation]); double checkHeight = _localViewProps.normalHeight;
ClientDisplayView::ConvertNormalToTransformedBounds(1.0, [self displayRotation], checkWidth, checkHeight);
const NSSize contentBounds = NSMakeSize(contentRect.size.width, contentRect.size.height - _statusBarHeight); 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. // 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]; NSRect finalFrameRect = [window frameRectForContentRect:finalContentRect];
if (isZooming) if (isZooming)
@ -1565,7 +1573,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
#endif #endif
inputManager = nil; inputManager = nil;
_initialTouchInMajorDisplay = new InitialTouchPressMap; _cdv = new ClientDisplayView();
// Initialize the OpenGL context // Initialize the OpenGL context
NSOpenGLPixelFormatAttribute attributes[] = { NSOpenGLPixelFormatAttribute attributes[] = {
@ -1639,7 +1647,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
delete oglv; delete oglv;
CGLSetCurrentContext(prevContext); CGLSetCurrentContext(prevContext);
delete _initialTouchInMajorDisplay; delete _cdv;
[self setInputManager:nil]; [self setInputManager:nil];
[context clearDrawable]; [context clearDrawable];
[context release]; [context release];
@ -1649,16 +1657,6 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
#pragma mark Dynamic Property Methods #pragma mark Dynamic Property Methods
- (NSSize) normalSize
{
double w;
double h;
oglv->GetDisplayLayer()->GetNormalSize(w, h);
return NSMakeSize(w, h);
}
- (void) setIsHUDVisible:(BOOL)theState - (void) setIsHUDVisible:(BOOL)theState
{ {
OSSpinLockLock(&spinlockIsHUDVisible); OSSpinLockLock(&spinlockIsHUDVisible);
@ -1944,103 +1942,11 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
// and finally to DS touchscreen coordinates. // and finally to DS touchscreen coordinates.
NSPoint touchLoc = [theEvent locationInWindow]; NSPoint touchLoc = [theEvent locationInWindow];
touchLoc = [self convertPoint:touchLoc fromView:nil]; touchLoc = [self convertPoint:touchLoc fromView:nil];
touchLoc = [self convertPointToDS:touchLoc inputID:inputID initialTouchPress:isInitialMouseDown];
return touchLoc; u8 x, y;
} _cdv->GetNDSPoint((int)inputID, (isInitialMouseDown) ? true : false, touchLoc.x, touchLoc.y, x, y);
- (NSPoint) convertPointToDS:(NSPoint)clickLoc inputID:(const NSInteger)inputID initialTouchPress:(BOOL)isInitialTouchPress return NSMakePoint(x, y);
{
DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate];
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);
} }
#pragma mark InputHIDManagerTarget Protocol #pragma mark InputHIDManagerTarget Protocol
@ -2366,8 +2272,9 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
const GLsizei w = (GLsizei)rect.size.width; const GLsizei w = (GLsizei)rect.size.width;
const GLsizei h = (GLsizei)rect.size.height; const GLsizei h = (GLsizei)rect.size.height;
DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate]; _cdv->SetClientSize(rect.size.width, rect.size.height);
double hudObjectScale = [windowController displayScale];
double hudObjectScale = _cdv->GetViewScale();
if (hudObjectScale > 2.0) if (hudObjectScale > 2.0)
{ {
// If the view scale is <= 2.0, we scale the HUD objects linearly. Otherwise, we scale // If the view scale is <= 2.0, we scale the HUD objects linearly. Otherwise, we scale
@ -2386,6 +2293,8 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void)doTransformView:(const DisplayOutputTransformData *)transformData - (void)doTransformView:(const DisplayOutputTransformData *)transformData
{ {
_cdv->SetRotation(transformData->rotation);
OGLDisplayLayer *display = oglv->GetDisplayLayer(); OGLDisplayLayer *display = oglv->GetDisplayLayer();
display->SetRotation((GLfloat)transformData->rotation); display->SetRotation((GLfloat)transformData->rotation);
[self doRedraw]; [self doRedraw];
@ -2401,6 +2310,8 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void)doDisplayModeChanged:(NSInteger)displayModeID - (void)doDisplayModeChanged:(NSInteger)displayModeID
{ {
_cdv->SetMode((ClientDisplayMode)displayModeID);
OGLDisplayLayer *display = oglv->GetDisplayLayer(); OGLDisplayLayer *display = oglv->GetDisplayLayer();
display->SetMode((ClientDisplayMode)displayModeID); display->SetMode((ClientDisplayMode)displayModeID);
[self doRedraw]; [self doRedraw];
@ -2408,6 +2319,8 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void)doDisplayOrientationChanged:(NSInteger)displayOrientationID - (void)doDisplayOrientationChanged:(NSInteger)displayOrientationID
{ {
_cdv->SetLayout((ClientDisplayLayout)displayOrientationID);
OGLDisplayLayer *display = oglv->GetDisplayLayer(); OGLDisplayLayer *display = oglv->GetDisplayLayer();
display->SetOrientation((ClientDisplayLayout)displayOrientationID); display->SetOrientation((ClientDisplayLayout)displayOrientationID);
@ -2419,6 +2332,8 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void)doDisplayOrderChanged:(NSInteger)displayOrderID - (void)doDisplayOrderChanged:(NSInteger)displayOrderID
{ {
_cdv->SetOrder((ClientDisplayOrder)displayOrderID);
OGLDisplayLayer *display = oglv->GetDisplayLayer(); OGLDisplayLayer *display = oglv->GetDisplayLayer();
display->SetOrder((ClientDisplayOrder)displayOrderID); display->SetOrder((ClientDisplayOrder)displayOrderID);
@ -2430,6 +2345,8 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void)doDisplayGapChanged:(float)displayGapScalar - (void)doDisplayGapChanged:(float)displayGapScalar
{ {
_cdv->SetGapWithScalar(displayGapScalar);
OGLDisplayLayer *display = oglv->GetDisplayLayer(); OGLDisplayLayer *display = oglv->GetDisplayLayer();
display->SetGapScalar((GLfloat)displayGapScalar); 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 @end
#pragma mark - #pragma mark -

View File

@ -1,6 +1,6 @@
/* /*
Copyright (C) 2011 Roger Manuel 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 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 it under the terms of the GNU General Public License as published by
@ -647,24 +647,24 @@
int frameX = 0; int frameX = 0;
int frameY = 0; int frameY = 0;
int frameWidth = GPU_DISPLAY_WIDTH; int frameWidth = 256;
int frameHeight = GPU_DISPLAY_HEIGHT; int frameHeight = 192;
const char *frameCStr = [windowFrameStr cStringUsingEncoding:NSUTF8StringEncoding]; const char *frameCStr = [windowFrameStr cStringUsingEncoding:NSUTF8StringEncoding];
sscanf(frameCStr, "%i %i %i %i", &frameX, &frameY, &frameWidth, &frameHeight); sscanf(frameCStr, "%i %i %i %i", &frameX, &frameY, &frameWidth, &frameHeight);
[windowController setIsMinSizeNormal:isMinSizeNormal];
[windowController setIsShowingStatusBar:isShowingStatusBar]; [windowController setIsShowingStatusBar:isShowingStatusBar];
[windowController setVideoFiltersPreferGPU:videoFiltersPreferGPU]; [windowController setVideoFiltersPreferGPU:videoFiltersPreferGPU];
[windowController setVideoSourceDeposterize:videoSourceDeposterize]; [windowController setVideoSourceDeposterize:videoSourceDeposterize];
[windowController setVideoPixelScaler:videoPixelScaler]; [windowController setVideoPixelScaler:videoPixelScaler];
[windowController setVideoOutputFilter:videoOutputFilter]; [windowController setVideoOutputFilter:videoOutputFilter];
[windowController setDisplayMode:displayMode]; [windowController setDisplayMode:displayMode];
[windowController setDisplayRotation:displayRotation];
[windowController setDisplayOrientation:displayOrientation]; [windowController setDisplayOrientation:displayOrientation];
[windowController setDisplayOrder:displayOrder]; [windowController setDisplayOrder:displayOrder];
[windowController setDisplayGap:displayGap]; [windowController setDisplayGap:displayGap];
[windowController setScreenshotFileFormat:screenshotFileFormat]; [windowController setIsMinSizeNormal:isMinSizeNormal];
[windowController setDisplayRotation:displayRotation];
[windowController setDisplayScale:displayScale]; [windowController setDisplayScale:displayScale];
[windowController setScreenshotFileFormat:screenshotFileFormat];
[[windowController view] setUseVerticalSync:useVerticalSync]; [[windowController view] setUseVerticalSync:useVerticalSync];
[[windowController view] setIsHUDVisible:hudEnable]; [[windowController view] setIsHUDVisible:hudEnable];
[[windowController view] setIsHUDVideoFPSVisible:hudShowVideoFPS]; [[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 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 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() 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 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 it under the terms of the GNU General Public License as published by
@ -38,19 +38,6 @@ void RGB555ToBGRA8888Buffer(const uint16_t *__restrict__ srcBuffer, uint32_t *__
void RGB888ToBGRA8888Buffer(const uint32_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); 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); uint32_t GetNearestPositivePOT(uint32_t value);
#ifdef __cplusplus #ifdef __cplusplus