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