mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-02-24 04:16:50 +00:00
[Examples] Improved timing display
GameWindowStates will now display the average fps and draw three moving boxes based on different timing methods. If the timing implementation in OpenTK is working correctly, all three boxes should be moving at the same speed.
This commit is contained in:
parent
97e49b76b2
commit
7b98255626
|
@ -25,9 +25,23 @@ namespace Examples.Tests
|
||||||
int texture;
|
int texture;
|
||||||
bool mouse_in_window = false;
|
bool mouse_in_window = false;
|
||||||
bool viewport_changed = true;
|
bool viewport_changed = true;
|
||||||
|
|
||||||
|
// time drift
|
||||||
Stopwatch watch = new Stopwatch();
|
Stopwatch watch = new Stopwatch();
|
||||||
double update_time, render_time;
|
double update_time, render_time;
|
||||||
|
|
||||||
|
// timing information
|
||||||
|
double timestamp;
|
||||||
|
int update_count;
|
||||||
|
int update_fps;
|
||||||
|
int render_count;
|
||||||
|
int render_fps;
|
||||||
|
|
||||||
|
// position of moving objects on screen
|
||||||
|
double variable_update_timestep_pos = -1;
|
||||||
|
double variable_refresh_timestep_pos = -1;
|
||||||
|
double fixed_update_timestep_pos = -1;
|
||||||
|
|
||||||
public GameWindowStates()
|
public GameWindowStates()
|
||||||
: base(800, 600, GraphicsMode.Default)
|
: base(800, 600, GraphicsMode.Default)
|
||||||
{
|
{
|
||||||
|
@ -35,10 +49,10 @@ namespace Examples.Tests
|
||||||
Keyboard.KeyRepeat = true;
|
Keyboard.KeyRepeat = true;
|
||||||
KeyDown += KeyDownHandler;
|
KeyDown += KeyDownHandler;
|
||||||
KeyPress += KeyPressHandler;
|
KeyPress += KeyPressHandler;
|
||||||
|
|
||||||
MouseEnter += delegate { mouse_in_window = true; };
|
MouseEnter += delegate { mouse_in_window = true; };
|
||||||
MouseLeave += delegate { mouse_in_window = false; };
|
MouseLeave += delegate { mouse_in_window = false; };
|
||||||
|
|
||||||
Mouse.Move += MouseMoveHandler;
|
Mouse.Move += MouseMoveHandler;
|
||||||
Mouse.ButtonDown += MouseButtonHandler;
|
Mouse.ButtonDown += MouseButtonHandler;
|
||||||
Mouse.ButtonUp += MouseButtonHandler;
|
Mouse.ButtonUp += MouseButtonHandler;
|
||||||
|
@ -110,7 +124,7 @@ namespace Examples.Tests
|
||||||
{
|
{
|
||||||
return val > max ? max : val < min ? min : val;
|
return val > max ? max : val < min ? min : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static float DrawString(Graphics gfx, string str, int line)
|
static float DrawString(Graphics gfx, string str, int line)
|
||||||
{
|
{
|
||||||
return DrawString(gfx, str, line, 0);
|
return DrawString(gfx, str, line, 0);
|
||||||
|
@ -217,6 +231,8 @@ namespace Examples.Tests
|
||||||
{
|
{
|
||||||
double clock_time = watch.Elapsed.TotalSeconds;
|
double clock_time = watch.Elapsed.TotalSeconds;
|
||||||
update_time += e.Time;
|
update_time += e.Time;
|
||||||
|
timestamp += e.Time;
|
||||||
|
update_count++;
|
||||||
|
|
||||||
using (Graphics gfx = Graphics.FromImage(TextBitmap))
|
using (Graphics gfx = Graphics.FromImage(TextBitmap))
|
||||||
{
|
{
|
||||||
|
@ -247,22 +263,47 @@ namespace Examples.Tests
|
||||||
// Timing information
|
// Timing information
|
||||||
line++;
|
line++;
|
||||||
DrawString(gfx, "Timing:", line++);
|
DrawString(gfx, "Timing:", line++);
|
||||||
DrawString(gfx, String.Format("Frequency: update ({0:f2}/{1:f2}); render ({2:f2}/{3:f2})",
|
DrawString(gfx,
|
||||||
UpdateFrequency, TargetUpdateFrequency, RenderFrequency, TargetRenderFrequency), line++);
|
String.Format("Frequency: update {4} ({0:f2}/{1:f2}); render {5} ({2:f2}/{3:f2})",
|
||||||
DrawString(gfx, String.Format("Period: update ({0:f4}/{1:f4}); render ({2:f4}/{3:f4})",
|
UpdateFrequency, TargetUpdateFrequency,
|
||||||
UpdatePeriod, TargetUpdatePeriod, RenderPeriod, TargetRenderPeriod), line++);
|
RenderFrequency, TargetRenderFrequency,
|
||||||
|
update_fps, render_fps),
|
||||||
|
line++);
|
||||||
|
DrawString(gfx,
|
||||||
|
String.Format("Period: update {4:N4} ({0:f4}/{1:f4}); render {5:N4} ({2:f4}/{3:f4})",
|
||||||
|
UpdatePeriod, TargetUpdatePeriod,
|
||||||
|
RenderPeriod, TargetRenderPeriod,
|
||||||
|
1.0 / update_fps, 1.0 / render_fps),
|
||||||
|
line++);
|
||||||
DrawString(gfx, String.Format("Time: update {0:f4}; render {1:f4}",
|
DrawString(gfx, String.Format("Time: update {0:f4}; render {1:f4}",
|
||||||
UpdateTime, RenderTime), line++);
|
UpdateTime, RenderTime), line++);
|
||||||
DrawString(gfx, String.Format("Drift: clock {0:f4}; update {1:f4}; render {2:f4}",
|
DrawString(gfx, String.Format("Drift: clock {0:f4}; update {1:f4}; render {2:f4}",
|
||||||
clock_time, clock_time - update_time, clock_time - render_time), line++);
|
clock_time, clock_time - update_time, clock_time - render_time), line++);
|
||||||
DrawString(gfx, String.Format("Text: {0}", TypedText.ToString()), line++);
|
DrawString(gfx, String.Format("Text: {0}", TypedText.ToString()), line++);
|
||||||
|
|
||||||
|
if (timestamp >= 1)
|
||||||
|
{
|
||||||
|
timestamp -= 1;
|
||||||
|
update_fps = update_count;
|
||||||
|
render_fps = render_count;
|
||||||
|
update_count = 0;
|
||||||
|
render_count = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Input information
|
// Input information
|
||||||
line = DrawKeyboards(gfx, line);
|
line = DrawKeyboards(gfx, line);
|
||||||
line = DrawMice(gfx, line);
|
line = DrawMice(gfx, line);
|
||||||
line = DrawJoysticks(gfx, line);
|
line = DrawJoysticks(gfx, line);
|
||||||
line = DrawLegacyJoysticks(gfx, Joysticks, line);
|
line = DrawLegacyJoysticks(gfx, Joysticks, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fixed_update_timestep_pos += TargetUpdatePeriod;
|
||||||
|
variable_update_timestep_pos += e.Time;
|
||||||
|
if (fixed_update_timestep_pos >= 1)
|
||||||
|
fixed_update_timestep_pos -= 2;
|
||||||
|
if (variable_update_timestep_pos >= 1)
|
||||||
|
variable_update_timestep_pos -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DrawJoysticks(Graphics gfx, int line)
|
int DrawJoysticks(Graphics gfx, int line)
|
||||||
|
@ -323,7 +364,31 @@ namespace Examples.Tests
|
||||||
protected override void OnRenderFrame(FrameEventArgs e)
|
protected override void OnRenderFrame(FrameEventArgs e)
|
||||||
{
|
{
|
||||||
render_time += e.Time;
|
render_time += e.Time;
|
||||||
|
render_count++;
|
||||||
|
|
||||||
|
GL.Clear(ClearBufferMask.ColorBufferBit);
|
||||||
|
|
||||||
|
if (viewport_changed)
|
||||||
|
{
|
||||||
|
viewport_changed = false;
|
||||||
|
GL.Viewport(0, 0, Width, Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawText();
|
||||||
|
|
||||||
|
DrawMovingObjects();
|
||||||
|
|
||||||
|
variable_refresh_timestep_pos += e.Time;
|
||||||
|
if (variable_refresh_timestep_pos >= 1)
|
||||||
|
variable_refresh_timestep_pos -= 2;
|
||||||
|
|
||||||
|
SwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uploads our text Bitmap to an OpenGL texture
|
||||||
|
// and displays is to screen.
|
||||||
|
private void DrawText()
|
||||||
|
{
|
||||||
System.Drawing.Imaging.BitmapData data = TextBitmap.LockBits(
|
System.Drawing.Imaging.BitmapData data = TextBitmap.LockBits(
|
||||||
new System.Drawing.Rectangle(0, 0, TextBitmap.Width, TextBitmap.Height),
|
new System.Drawing.Rectangle(0, 0, TextBitmap.Width, TextBitmap.Height),
|
||||||
System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||||
|
@ -331,29 +396,63 @@ namespace Examples.Tests
|
||||||
PixelType.UnsignedByte, data.Scan0);
|
PixelType.UnsignedByte, data.Scan0);
|
||||||
TextBitmap.UnlockBits(data);
|
TextBitmap.UnlockBits(data);
|
||||||
|
|
||||||
if (viewport_changed)
|
Matrix4 text_projection = Matrix4.CreateOrthographicOffCenter(0, Width, Height, 0, -1, 1);
|
||||||
{
|
GL.MatrixMode(MatrixMode.Projection);
|
||||||
viewport_changed = false;
|
GL.LoadMatrix(ref text_projection);
|
||||||
|
GL.MatrixMode(MatrixMode.Modelview);
|
||||||
GL.Viewport(0, 0, Width, Height);
|
GL.LoadIdentity();
|
||||||
|
|
||||||
Matrix4 ortho_projection = Matrix4.CreateOrthographicOffCenter(0, Width, Height, 0, -1, 1);
|
|
||||||
GL.MatrixMode(MatrixMode.Projection);
|
|
||||||
GL.LoadMatrix(ref ortho_projection);
|
|
||||||
}
|
|
||||||
|
|
||||||
GL.Clear(ClearBufferMask.ColorBufferBit);
|
|
||||||
|
|
||||||
|
GL.Color4(Color4.White);
|
||||||
|
GL.Enable(EnableCap.Texture2D);
|
||||||
GL.Begin(PrimitiveType.Quads);
|
GL.Begin(PrimitiveType.Quads);
|
||||||
|
|
||||||
GL.TexCoord2(0, 0); GL.Vertex2(0, 0);
|
GL.TexCoord2(0, 0); GL.Vertex2(0, 0);
|
||||||
GL.TexCoord2(1, 0); GL.Vertex2(TextBitmap.Width, 0);
|
GL.TexCoord2(1, 0); GL.Vertex2(TextBitmap.Width, 0);
|
||||||
GL.TexCoord2(1, 1); GL.Vertex2(TextBitmap.Width, TextBitmap.Height);
|
GL.TexCoord2(1, 1); GL.Vertex2(TextBitmap.Width, TextBitmap.Height);
|
||||||
GL.TexCoord2(0, 1); GL.Vertex2(0, TextBitmap.Height);
|
GL.TexCoord2(0, 1); GL.Vertex2(0, TextBitmap.Height);
|
||||||
|
|
||||||
GL.End();
|
GL.End();
|
||||||
|
GL.Disable(EnableCap.Texture2D);
|
||||||
|
}
|
||||||
|
|
||||||
SwapBuffers();
|
// Draws three moving objects, using three different timing methods:
|
||||||
|
// 1. fixed framerate based on TargetUpdatePeriod
|
||||||
|
// 2. variable framerate based on UpdateFrame e.Time
|
||||||
|
// 3. variable framerate based on RenderFrame e.Time
|
||||||
|
// If the timing implementation is correct, all three objects
|
||||||
|
// should be moving at the same speed, regardless of the current
|
||||||
|
// UpdatePeriod and RenderPeriod.
|
||||||
|
void DrawMovingObjects()
|
||||||
|
{
|
||||||
|
Matrix4 thing_projection = Matrix4.CreateOrthographic(2, 2, -1, 1);
|
||||||
|
GL.MatrixMode(MatrixMode.Projection);
|
||||||
|
GL.LoadMatrix(ref thing_projection);
|
||||||
|
|
||||||
|
GL.MatrixMode(MatrixMode.Modelview);
|
||||||
|
GL.LoadIdentity();
|
||||||
|
GL.Translate(fixed_update_timestep_pos, -0.2, 0);
|
||||||
|
GL.Color4(Color4.Red);
|
||||||
|
DrawRectangle();
|
||||||
|
|
||||||
|
GL.MatrixMode(MatrixMode.Modelview);
|
||||||
|
GL.LoadIdentity();
|
||||||
|
GL.Translate(variable_update_timestep_pos, -0.4, 0);
|
||||||
|
GL.Color4(Color4.DarkGoldenrod);
|
||||||
|
DrawRectangle();
|
||||||
|
|
||||||
|
GL.MatrixMode(MatrixMode.Modelview);
|
||||||
|
GL.LoadIdentity();
|
||||||
|
GL.Translate(variable_refresh_timestep_pos, -0.8, 0);
|
||||||
|
GL.Color4(Color4.DarkGreen);
|
||||||
|
DrawRectangle();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawRectangle()
|
||||||
|
{
|
||||||
|
GL.Begin(PrimitiveType.Quads);
|
||||||
|
GL.Vertex2(-0.05, -0.05);
|
||||||
|
GL.Vertex2(+0.05, -0.05);
|
||||||
|
GL.Vertex2(+0.05, +0.05);
|
||||||
|
GL.Vertex2(-0.05, +0.05);
|
||||||
|
GL.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Main()
|
public static void Main()
|
||||||
|
|
Loading…
Reference in a new issue