client sizing / AR revisions
This commit is contained in:
parent
20fb404d2e
commit
6f919c64a7
|
@ -291,18 +291,101 @@ namespace BizHawk.Client.EmuHawk
|
|||
/// </summary>
|
||||
public Size CalculateClientSize(IVideoProvider videoProvider, int zoom)
|
||||
{
|
||||
var fvp = new FakeVideoProvider ();
|
||||
fvp.BufferWidth = videoProvider.BufferWidth;
|
||||
fvp.BufferHeight = videoProvider.BufferHeight;
|
||||
fvp.VirtualWidth = videoProvider.VirtualWidth;
|
||||
fvp.VirtualHeight = videoProvider.VirtualHeight;
|
||||
int bufferWidth = videoProvider.BufferWidth;
|
||||
int bufferHeight = videoProvider.BufferHeight;
|
||||
int virtualWidth = videoProvider.VirtualWidth;
|
||||
int virtualHeight = videoProvider.VirtualHeight;
|
||||
|
||||
//test
|
||||
//Console.WriteLine("DISPZOOM " + zoom);
|
||||
|
||||
//old stuff
|
||||
var fvp = new FakeVideoProvider();
|
||||
fvp.BufferWidth = bufferWidth;
|
||||
fvp.BufferHeight = bufferHeight;
|
||||
fvp.VirtualWidth = virtualWidth;
|
||||
fvp.VirtualHeight = virtualHeight;
|
||||
|
||||
Size chain_outsize = new Size(fvp.BufferWidth * zoom, fvp.BufferHeight * zoom);
|
||||
|
||||
//zero 27-may-2014 - this code is now slightly suspicious.. but no proof we need to get rid of it
|
||||
//zero 02-jun-2014 - now, I suspect it is more important
|
||||
if (Global.Config.DispObeyAR && Global.Config.DispFixAspectRatio)
|
||||
chain_outsize = new Size(fvp.VirtualWidth * zoom, fvp.VirtualHeight * zoom);
|
||||
bool ar_active = Global.Config.DispFixAspectRatio;
|
||||
bool ar_system = Global.Config.DispObeyAR;
|
||||
bool ar_unity = !ar_system;
|
||||
bool ar_integer = Global.Config.DispFixScaleInteger;
|
||||
|
||||
if (ar_active)
|
||||
{
|
||||
if (ar_system)
|
||||
{
|
||||
if (ar_integer)
|
||||
{
|
||||
Vector2 VS = new Vector2(virtualWidth, virtualHeight);
|
||||
Vector2 BS = new Vector2(bufferWidth, bufferHeight);
|
||||
Vector2 AR = Vector2.Divide(VS, BS);
|
||||
float target_par = (AR.X / AR.Y);
|
||||
Vector2 PS = new Vector2(1, 1); //this would malfunction for AR <= 0.5 or AR >= 2.0
|
||||
|
||||
//here's how we define zooming, in this case:
|
||||
//make sure each step is an increment of zoom for at least one of the dimensions (or maybe both of them)
|
||||
//look for the increment which helps the AR the best
|
||||
//TODO - this cant possibly support scale factors like 1.5x
|
||||
//TODO - also, this might be messing up zooms and stuff, we might need to run this on the output size of the filter chain
|
||||
for (int i = 1; i < zoom;i++)
|
||||
{
|
||||
//would not be good to run this per frame, but it seems to only run when the resolution changes, etc.
|
||||
Vector2[] trials = new [] {
|
||||
PS + new Vector2(1, 0),
|
||||
PS + new Vector2(0, 1),
|
||||
PS + new Vector2(1, 1)
|
||||
};
|
||||
int bestIndex = -1;
|
||||
float bestValue = 1000.0f;
|
||||
for (int t = 0; t < trials.Length; t++)
|
||||
{
|
||||
//I.
|
||||
float test_ar = trials[t].X / trials[t].Y;
|
||||
|
||||
//II.
|
||||
//Vector2 calc = Vector2.Multiply(trials[t], VS);
|
||||
//float test_ar = calc.X / calc.Y;
|
||||
|
||||
//not clear which approach is superior
|
||||
float deviation_linear = Math.Abs(test_ar - target_par);
|
||||
float deviation_geom = test_ar / target_par;
|
||||
if (deviation_geom < 1) deviation_geom = 1.0f / deviation_geom;
|
||||
|
||||
float value = deviation_linear;
|
||||
if (value < bestValue)
|
||||
{
|
||||
bestIndex = t;
|
||||
bestValue = value;
|
||||
}
|
||||
}
|
||||
//is it possible to get here without selecting one? doubtful.
|
||||
PS = trials[bestIndex];
|
||||
}
|
||||
|
||||
chain_outsize = new Size((int)(bufferWidth * PS.X), (int)(bufferHeight * PS.Y));
|
||||
}
|
||||
else
|
||||
{
|
||||
//obey the AR, but allow free scaling: just zoom the virtual size
|
||||
chain_outsize = new Size(virtualWidth * zoom, virtualHeight * zoom);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//ar_unity:
|
||||
//just choose to zoom the buffer (make no effort to incorporate AR)
|
||||
chain_outsize = new Size(bufferWidth * zoom, bufferHeight * zoom);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//!ar_active:
|
||||
//just choose to zoom the buffer (make no effort to incorporate AR)
|
||||
chain_outsize = new Size(bufferWidth * zoom, bufferHeight * zoom);
|
||||
}
|
||||
|
||||
var job = new JobInfo
|
||||
{
|
||||
|
@ -313,20 +396,8 @@ namespace BizHawk.Client.EmuHawk
|
|||
var filterProgram = UpdateSourceInternal(job);
|
||||
|
||||
var size = filterProgram.Filters[filterProgram.Filters.Count - 1].FindOutput().SurfaceFormat.Size;
|
||||
|
||||
//zero 22-may-2014 - added this to combat problem where nes would default to having sidebars
|
||||
//this would use the actual chain output size. this is undesireable, in the following scenario:
|
||||
//load a nes game at 2x with system-preferred and integer AR enabled, and there will be sidebars.
|
||||
//the sidebars were created by this, so we can peek into it and remove the sidebars.
|
||||
//Only do this if integer fixing is enabled, since only in that case do we have discardable sidebars.
|
||||
//Otherwise discarding the 'sidebars' would result in cropping image.
|
||||
//This is getting complicated..
|
||||
if (Global.Config.DispFixScaleInteger)
|
||||
{
|
||||
var fp = filterProgram["presentation"] as Filters.FinalPresentation;
|
||||
size = fp.GetContentSize();
|
||||
}
|
||||
|
||||
Console.WriteLine("Selecting size " + size.ToString());
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,14 +52,11 @@ namespace BizHawk.Client.EmuHawk.Filters
|
|||
|
||||
float widthScale = (float)targetWidth / sourceWidth;
|
||||
float heightScale = (float)targetHeight / sourceHeight;
|
||||
//zero 22-may-2014 - added this to combat problem where nes would default to having sidebars
|
||||
if (Global.Config.DispFixScaleInteger)
|
||||
{
|
||||
widthScale = (float)targetWidth / textureSize.Width;
|
||||
heightScale = (float)targetHeight / textureSize.Height;
|
||||
}
|
||||
|
||||
if (maintainAspect)
|
||||
|
||||
if (maintainAspect
|
||||
//zero 20-jul-2014 - hacks upon hacks, this function needs rewriting
|
||||
&& !maintainInteger
|
||||
)
|
||||
{
|
||||
if (widthScale > heightScale) widthScale = heightScale;
|
||||
if (heightScale > widthScale) heightScale = widthScale;
|
||||
|
@ -67,73 +64,72 @@ namespace BizHawk.Client.EmuHawk.Filters
|
|||
|
||||
if (maintainInteger)
|
||||
{
|
||||
//don't distort the original texture
|
||||
float apparentWidth = sourceWidth * widthScale;
|
||||
float apparentHeight = sourceHeight * heightScale;
|
||||
widthScale = (apparentWidth / textureWidth);
|
||||
heightScale = (apparentHeight / textureHeight);
|
||||
//just totally different code
|
||||
//apply the zooming algorithm (pasted and reworked, for now)
|
||||
|
||||
//zero 27-may-2014 - no longer relevant, but this is sneaky, so leaving it as a reminder for now
|
||||
//prevent dysfunctional reduction to 0x
|
||||
//if (widthScale == 0) widthScale = 1;
|
||||
//if (heightScale == 0) heightScale = 1;
|
||||
|
||||
REDO:
|
||||
Vector2 VS = new Vector2(virtualWidth, virtualHeight);
|
||||
Vector2 BS = new Vector2(textureWidth, textureHeight);
|
||||
Vector2 AR = Vector2.Divide(VS, BS);
|
||||
float target_par = (AR.X / AR.Y);
|
||||
Vector2 PS = new Vector2(1, 1); //this would malfunction for AR <= 0.5 or AR >= 2.0
|
||||
|
||||
apparentWidth = textureWidth * widthScale;
|
||||
apparentHeight = textureHeight * heightScale;
|
||||
|
||||
//in case we've exaggerated the aspect ratio too far beyond the goal by our blunt integerizing, heres a chance to fix it by reducing one of the dimensions
|
||||
float goalAr = ((float)virtualWidth)/virtualHeight;
|
||||
float haveAr = apparentWidth / apparentHeight;
|
||||
if (widthScale>1)
|
||||
for(;;)
|
||||
{
|
||||
//try truncating this scale, or reducing it by 1 if it's already truncated
|
||||
float floored = (float)Math.Floor(widthScale);
|
||||
float next;
|
||||
if (widthScale == floored)
|
||||
next = widthScale - 1;
|
||||
else next = floored;
|
||||
|
||||
float tryAnotherAR = (next*textureWidth)/(heightScale*textureHeight);
|
||||
if(Math.Abs(tryAnotherAR-goalAr) < Math.Abs(haveAr-goalAr))
|
||||
//TODO - would be good not to run this per frame....
|
||||
Vector2[] trials = new[] {
|
||||
PS + new Vector2(1, 0),
|
||||
PS + new Vector2(0, 1),
|
||||
PS + new Vector2(1, 1)
|
||||
};
|
||||
bool[] trials_limited = new bool[3] { false,false,false};
|
||||
int bestIndex = -1;
|
||||
float bestValue = 1000.0f;
|
||||
for (int t = 0; t < trials.Length; t++)
|
||||
{
|
||||
widthScale = next;
|
||||
goto REDO;
|
||||
Vector2 vTrial = trials[t];
|
||||
trials_limited[t] = false;
|
||||
|
||||
//check whether this is going to exceed our allotted area
|
||||
int test_vw = (int)(vTrial.X * textureWidth);
|
||||
int test_vh = (int)(vTrial.Y * textureHeight);
|
||||
if (test_vw > targetWidth) trials_limited[t] = true;
|
||||
if (test_vh > targetHeight) trials_limited[t] = true;
|
||||
|
||||
//I.
|
||||
float test_ar = vTrial.X / vTrial.Y;
|
||||
|
||||
//II.
|
||||
//Vector2 calc = Vector2.Multiply(trials[t], VS);
|
||||
//float test_ar = calc.X / calc.Y;
|
||||
|
||||
//not clear which approach is superior
|
||||
float deviation_linear = Math.Abs(test_ar - target_par);
|
||||
float deviation_geom = test_ar / target_par;
|
||||
if (deviation_geom < 1) deviation_geom = 1.0f / deviation_geom;
|
||||
|
||||
float value = deviation_linear;
|
||||
if (value < bestValue)
|
||||
{
|
||||
bestIndex = t;
|
||||
bestValue = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (heightScale > 1)
|
||||
{
|
||||
//try truncating this scale, or reducing it by 1 if it's already truncated
|
||||
float floored = (float)Math.Floor(heightScale);
|
||||
float next;
|
||||
if (heightScale == floored)
|
||||
next = heightScale - 1;
|
||||
else next = floored;
|
||||
|
||||
float tryAnotherAR = (widthScale*textureWidth) / (next*textureHeight);
|
||||
if (Math.Abs(tryAnotherAR - goalAr) < Math.Abs(haveAr - goalAr))
|
||||
{
|
||||
heightScale = next;
|
||||
goto REDO;
|
||||
}
|
||||
//last result was best, so bail out
|
||||
if (bestIndex == -1)
|
||||
break;
|
||||
|
||||
//if the winner ran off the edge, bail out
|
||||
if (trials_limited[bestIndex])
|
||||
break;
|
||||
|
||||
PS = trials[bestIndex];
|
||||
}
|
||||
|
||||
//we're not allowed to get out of here with non-integer scales, so if that's happened, back in for another loop we go
|
||||
if (Math.Floor(heightScale) != heightScale && heightScale >= 1)
|
||||
{
|
||||
heightScale = (float)Math.Floor(heightScale);
|
||||
goto REDO;
|
||||
}
|
||||
if (Math.Floor(widthScale) != widthScale && widthScale >= 1)
|
||||
{
|
||||
widthScale = (float)Math.Floor(widthScale);
|
||||
goto REDO;
|
||||
}
|
||||
|
||||
|
||||
vw = (int)(widthScale * textureWidth);
|
||||
vh = (int)(heightScale * textureHeight);
|
||||
vw = (int)(PS.X * textureWidth);
|
||||
vh = (int)(PS.Y * textureHeight);
|
||||
widthScale = PS.X;
|
||||
heightScale = PS.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -141,7 +137,7 @@ namespace BizHawk.Client.EmuHawk.Filters
|
|||
vh = (int)(heightScale * sourceHeight);
|
||||
}
|
||||
|
||||
|
||||
//determine letterboxing parameters
|
||||
vx = (targetWidth - vw) / 2;
|
||||
vy = (targetHeight - vh) / 2;
|
||||
WidthScale = widthScale;
|
||||
|
|
|
@ -255,10 +255,10 @@
|
|||
this.rbUseSystem.AutoSize = true;
|
||||
this.rbUseSystem.Location = new System.Drawing.Point(6, 42);
|
||||
this.rbUseSystem.Name = "rbUseSystem";
|
||||
this.rbUseSystem.Size = new System.Drawing.Size(167, 17);
|
||||
this.rbUseSystem.Size = new System.Drawing.Size(320, 17);
|
||||
this.rbUseSystem.TabIndex = 12;
|
||||
this.rbUseSystem.TabStop = true;
|
||||
this.rbUseSystem.Text = "Use system\'s recommendation";
|
||||
this.rbUseSystem.Text = "Use system\'s recommendation (e.g. 2x1 pixels, for better AR fit)";
|
||||
this.rbUseSystem.UseVisualStyleBackColor = true;
|
||||
this.rbUseSystem.CheckedChanged += new System.EventHandler(this.rbUseSystem_CheckedChanged);
|
||||
//
|
||||
|
@ -268,7 +268,7 @@
|
|||
this.grpARSelection.Controls.Add(this.rbUseSystem);
|
||||
this.grpARSelection.Location = new System.Drawing.Point(21, 177);
|
||||
this.grpARSelection.Name = "grpARSelection";
|
||||
this.grpARSelection.Size = new System.Drawing.Size(264, 71);
|
||||
this.grpARSelection.Size = new System.Drawing.Size(342, 71);
|
||||
this.grpARSelection.TabIndex = 13;
|
||||
this.grpARSelection.TabStop = false;
|
||||
this.grpARSelection.Text = "Aspect Ratio Selection";
|
||||
|
|
Loading…
Reference in New Issue