Unify as much of D3D and OpenGL as possible

This commit is contained in:
Flamefire committed 2014-09-11 21:58:30 +02:00
1 parent 46acaf092a
commit 76ededf9f3
7 files changed
+710 -866

No files matched your search

+64 -417
View File
@@ -15,13 +15,10 @@
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
#endregion
using System.Drawing.Drawing2D;
using System.Threading;
using SlimDX;
using SlimDX.Direct3D9;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
@@ -34,33 +31,26 @@ using VocaluxeLib.Draw;
namespace Vocaluxe.Lib.Draw
{
class CRenderFormHook : RenderForm, CDrawBaseWindows.IFormHook
class CRenderFormHook : RenderForm, IFormHook
{
public CDrawBaseWindows.MessageEventHandler OnMessage { private get; set; }
public MessageEventHandler OnMessage { private get; set; }
protected override void WndProc(ref Message m)
{
if (OnMessage(ref m))
if (OnMessage == null || OnMessage(ref m))
base.WndProc(ref m);
}
}
class CDirect3D : CDrawBaseWindows, IDraw
class CDirect3D : CDrawBaseWindows<Texture>, IDraw
{
#region private vars
private readonly CKeys _Keys;
private readonly CMouse _Mouse;
private bool _Run;
private readonly Direct3D _D3D;
private readonly Device _Device;
private readonly PresentParameters _PresentParameters;
private Size _SizeBeforeMinimize;
private readonly Dictionary<int, Texture> _D3DTextures = new Dictionary<int, Texture>();
private readonly Queue<STextureQueue> _TexturesToLoad = new Queue<STextureQueue>();
private VertexBuffer _VertexBuffer;
private IndexBuffer _IndexBuffer;
@@ -69,16 +59,11 @@ namespace Vocaluxe.Lib.Draw
private int _Y;
private int _X;
private int _BorderLeft;
private int _BorderRight;
private int _BorderTop;
private int _BorderBottom;
private CTexture _BlankTexture;
private readonly Queue<STexturedColoredVertex> _Vertices = new Queue<STexturedColoredVertex>();
private readonly Queue<Texture> _VerticesTextures = new Queue<Texture>();
private readonly Queue<SlimDX.Matrix> _VerticesRotationMatrices = new Queue<SlimDX.Matrix>();
private readonly Queue<Matrix> _VerticesRotationMatrices = new Queue<Matrix>();
#endregion private vars
/// <summary>
@@ -87,7 +72,6 @@ namespace Vocaluxe.Lib.Draw
public CDirect3D()
{
_Form = new CRenderFormHook();
_Keys = new CKeys();
try
{
_D3D = new Direct3D();
@@ -97,17 +81,11 @@ namespace Vocaluxe.Lib.Draw
CLog.LogError("No DirectX runtimes were found, please download and install them from http://www.microsoft.com/download/en/details.aspx?id=8109", true, true, e);
}
_Form.Closing += _OnClosingEvent;
_Form.Resize += _OnResize;
_Form.Load += _OnLoad;
_Form.KeyDown += _OnKeyDown;
_Form.PreviewKeyDown += _OnPreviewKeyDown;
_Form.KeyPress += _OnKeyPress;
_Form.KeyUp += _OnKeyUp;
_Mouse = new CMouse();
_Form.MouseMove += _OnMouseMove;
_Form.MouseWheel += _OnMouseWheel;
_Form.MouseDown += _OnMouseDown;
@@ -184,6 +162,10 @@ namespace Vocaluxe.Lib.Draw
{
_Device = new Device(_D3D, _D3D.Adapters.DefaultAdapter.Adapter, DeviceType.Hardware, _Form.Handle, flags, _PresentParameters);
}
catch (Exception e)
{
CLog.LogError("Error during D3D device creation.", false, false, e);
}
finally
{
if (_Device == null || _Device.Disposed)
@@ -198,20 +180,6 @@ namespace Vocaluxe.Lib.Draw
}
#region form events
private void _OnClosingEvent(object sender, CancelEventArgs e)
{
_Run = false;
}
private void _OnLoad(object sender, EventArgs e)
{
_Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);
}
private void _OnResize(object sender, EventArgs e)
{
_DoResize();
}
#endregion form events
#region resize
@@ -273,62 +241,6 @@ namespace Vocaluxe.Lib.Draw
// ReSharper restore RedundantOverridenMember
#endregion resize
#region mouse event handlers
private void _OnMouseMove(object sender, MouseEventArgs e)
{
_Mouse.MouseMove(e);
}
private void _OnMouseWheel(object sender, MouseEventArgs e)
{
_Mouse.MouseWheel(e);
}
private void _OnMouseDown(object sender, MouseEventArgs e)
{
_Mouse.MouseDown(e);
}
private void _OnMouseUp(object sender, MouseEventArgs e)
{
_Mouse.MouseUp(e);
}
private void _OnMouseLeave(object sender, EventArgs e)
{
_Mouse.Visible = false;
Cursor.Show();
}
private void _OnMouseEnter(object sender, EventArgs e)
{
Cursor.Hide();
_Mouse.Visible = true;
}
#endregion
#region keyboard event handlers
private void _OnPreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
_OnKeyDown(sender, new KeyEventArgs(e.KeyData));
}
private void _OnKeyDown(object sender, KeyEventArgs e)
{
_Keys.KeyDown(e);
}
private void _OnKeyPress(object sender, KeyPressEventArgs e)
{
_Keys.KeyPress(e);
}
private void _OnKeyUp(object sender, KeyEventArgs e)
{
_Keys.KeyUp(e);
}
#endregion keyboard event handlers
#region implementation
#region main stuff
@@ -359,9 +271,9 @@ namespace Vocaluxe.Lib.Draw
CLog.LogError("Failed to enable alpha blending");
if (_Device.SetRenderState(RenderState.Lighting, false).IsFailure)
CLog.LogError("Failed to disable lighting");
if (_Device.SetRenderState(RenderState.DestinationBlend, SlimDX.Direct3D9.Blend.InverseSourceAlpha).IsFailure)
if (_Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha).IsFailure)
CLog.LogError("Failed to set destination blend");
if (_Device.SetRenderState(RenderState.SourceBlend, SlimDX.Direct3D9.Blend.SourceAlpha).IsFailure)
if (_Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha).IsFailure)
CLog.LogError("Failed to set source blend");
if (_PresentParameters.Multisample != MultisampleType.None)
{
@@ -412,84 +324,35 @@ namespace Vocaluxe.Lib.Draw
return true;
}
/// <summary>
/// Starts the rendering
/// </summary>
public void MainLoop()
protected override void _OnBeforeDraw()
{
_Run = true;
int delay = 0;
_Form.Show();
if (_Device.BeginScene().IsFailure)
CLog.LogError("Failed to begin scene");
}
if (CConfig.FullScreen == EOffOn.TR_CONFIG_ON)
_EnterFullScreen();
//Resize window if aspect ratio is incorrect
if (Math.Abs(_W / (float)_H - CSettings.GetRenderAspect()) > 0.01)
_DoResize();
while (_Run)
protected override void _OnAfterDraw()
{
_RenderVertexBuffer();
if (_Device.EndScene().IsFailure)
CLog.LogError("Failed to end scene");
try
{
Application.DoEvents();
//Clear the previous Frame
ClearScreen();
//We want to begin drawing
if (_Device.BeginScene().IsFailure)
CLog.LogError("Failed to begin scene");
_CheckQueue();
if (!CGraphics.Draw())
_Run = false;
_RenderVertexBuffer();
//We finished drawing the frame
if (_Device.EndScene().IsFailure)
CLog.LogError("Failed to end scene");
if (!CGraphics.UpdateGameLogic(_Keys, _Mouse))
_Run = false;
try
{
//Now push the frame to the Viewport
_Device.Present();
}
catch (Direct3D9Exception)
{
//In Direct3D devices can get lost.
//This happens for example when opening the Task Manager in Vista/Windows 7 or if a UAC message is opening
//We need to reset the device to get it to workable state again
//After a reset Init() needs to be called because all data in the Direct3D default pool are lost and need to be recreated
if (_Device.TestCooperativeLevel() == ResultCode.DeviceNotReset)
{
_Reset();
Init();
}
}
//Apply fullscreen mode
if ((CConfig.FullScreen == EOffOn.TR_CONFIG_ON) != _Fullscreen)
_ToggleFullScreen();
//Apply border changes
if (_BorderLeft != CConfig.BorderLeft || _BorderRight != CConfig.BorderRight || _BorderTop != CConfig.BorderTop || _BorderBottom != CConfig.BorderBottom)
{
_BorderLeft = CConfig.BorderLeft;
_BorderRight = CConfig.BorderRight;
_BorderTop = CConfig.BorderTop;
_BorderBottom = CConfig.BorderBottom;
_AdjustNewBorders();
}
if (CConfig.VSync == EOffOn.TR_CONFIG_ON)
{
if (CTime.IsRunning())
delay = (int)Math.Floor(CConfig.CalcCycleTime() - CTime.GetMilliseconds());
if (delay >= 1 && delay < 500)
Thread.Sleep(delay);
}
//Calculate the FPS Rate and restart the timer after a frame
CTime.CalculateFPS();
CTime.Restart();
//Now push the frame to the Viewport
_Device.Present();
}
_Form.Close();
catch (Direct3D9Exception)
{
//In Direct3D devices can get lost.
//This happens for example when opening the Task Manager in Vista/Windows 7 or if a UAC message is opening
//We need to reset the device to get it to workable state again
//After a reset Init() needs to be called because all data in the Direct3D default pool are lost and need to be recreated
if (_Device.TestCooperativeLevel() == ResultCode.DeviceNotReset)
{
_Reset();
Init();
}
}
Application.DoEvents();
}
/// <summary>
@@ -505,10 +368,10 @@ namespace Vocaluxe.Lib.Draw
CLog.LogError("Failed to reset the device");
}
private void _AdjustNewBorders()
protected override void _AdjustNewBorders()
{
SlimDX.Matrix translate = SlimDX.Matrix.Translation(new Vector3(-(float)CSettings.RenderW / 2, (float)CSettings.RenderH / 2, 0));
SlimDX.Matrix projection = SlimDX.Matrix.OrthoOffCenterLH(
Matrix translate = Matrix.Translation(new Vector3(-(float)CSettings.RenderW / 2, (float)CSettings.RenderH / 2, 0));
Matrix projection = Matrix.OrthoOffCenterLH(
-(float)CSettings.RenderW / 2 - _BorderLeft, (float)CSettings.RenderW / 2 + _BorderRight,
-(float)CSettings.RenderH / 2 - _BorderBottom, (float)CSettings.RenderH / 2 + _BorderTop,
CSettings.ZNear, CSettings.ZFar);
@@ -523,20 +386,9 @@ namespace Vocaluxe.Lib.Draw
/// Unloads all Textures and other objects used by Direct3D for rendering
/// </summary>
/// <returns></returns>
public void Unload()
public override void Unload()
{
try
{
_Form.Close();
}
catch {}
//Dispose all textures
foreach (Texture texture in _D3DTextures.Values)
{
if (texture != null)
texture.Dispose();
}
base.Unload();
STexturedColoredVertex.GetDeclaration(_Device).Dispose();
_VertexBuffer.Dispose();
_IndexBuffer.Dispose();
@@ -568,7 +420,7 @@ namespace Vocaluxe.Lib.Draw
/// <param name="vertices">A TexturedColoredVertex array containg 4 vertices</param>
/// <param name="tex">The texture the vertex should be textured with</param>
/// <param name="rotation">The vertices' rotation</param>
private void _AddToVertexBuffer(STexturedColoredVertex[] vertices, Texture tex, SlimDX.Matrix rotation)
private void _AddToVertexBuffer(STexturedColoredVertex[] vertices, Texture tex, Matrix rotation)
{
//The vertexbuffer is full, so we need to flush it before we can continue
if (_Vertices.Count >= CSettings.VertexBufferElements)
@@ -617,7 +469,7 @@ namespace Vocaluxe.Lib.Draw
/// <summary>
/// Removes all textures from the screen
/// </summary>
public void ClearScreen()
public override void ClearScreen()
{
if (_Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0).IsFailure)
CLog.LogError("Failed to clear the backbuffer");
@@ -629,16 +481,16 @@ namespace Vocaluxe.Lib.Draw
/// </summary>
public CTexture CopyScreen()
{
CTexture texture = GetNewTexture(_W, _H);
CTexture texture = _GetNewTextureRef(_W, _H);
Surface backbufferSurface = _Device.GetBackBuffer(0, 0);
var tex = new Texture(_Device, texture.W2, texture.H2, 0, Usage.AutoGenerateMipMap, Format.A8R8G8B8, Pool.Managed);
Surface textureSurface = tex.GetSurfaceLevel(0);
Surface.FromSurface(textureSurface, backbufferSurface, Filter.Default, 0, new Rectangle(0, 0, _W, _H), new Rectangle(0, 0, _W, _H));
backbufferSurface.Dispose();
lock (_D3DTextures)
lock (_Textures)
{
_D3DTextures.Add(texture.ID, tex);
_Textures.Add(texture.ID, tex);
}
return texture;
@@ -658,7 +510,7 @@ namespace Vocaluxe.Lib.Draw
else
{
Surface backbufferSurface = _Device.GetBackBuffer(0, 0);
Surface textureSurface = _D3DTextures[texture.ID].GetSurfaceLevel(0);
Surface textureSurface = _Textures[texture.ID].GetSurfaceLevel(0);
Surface.FromSurface(textureSurface, backbufferSurface, Filter.Default, 0);
}
}
@@ -729,132 +581,7 @@ namespace Vocaluxe.Lib.Draw
#region Textures
#region adding
/// <summary>
/// Adds a texture and stores it in the VRam
/// </summary>
/// <param name="texturePath">The texture's filepath</param>
/// <returns>A STexture object containing the added texture</returns>
public CTexture AddTexture(string texturePath)
{
if (!File.Exists(texturePath))
{
CLog.LogError("Can't find File: " + texturePath);
return null;
}
Bitmap bmp;
try
{
bmp = new Bitmap(texturePath);
}
catch (Exception)
{
CLog.LogError("Error loading Texture: " + texturePath);
return null;
}
CTexture s;
try
{
s = AddTexture(bmp);
}
finally
{
bmp.Dispose();
}
return s;
}
/// <summary>
/// Adds a texture and stores it in the Vram
/// </summary>
/// <param name="bmp">The Bitmap of which the texure will be created from</param>
/// <returns>A STexture object containing the added texture</returns>
public CTexture AddTexture(Bitmap bmp)
{
if (bmp.Height == 0 || bmp.Width == 0)
return null;
int maxSize;
//Apply the right max size
switch (CConfig.TextureQuality)
{
case ETextureQuality.TR_CONFIG_TEXTURE_LOWEST:
maxSize = 128;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_LOW:
maxSize = 256;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_MEDIUM:
maxSize = 512;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_HIGH:
maxSize = 1024;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_HIGHEST:
maxSize = 2048;
break;
default:
maxSize = 512;
break;
}
int w = Math.Min(bmp.Width, maxSize);
int h = Math.Min(bmp.Height, maxSize);
CTexture texture = GetNewTexture(bmp.Width, bmp.Height, w, h);
Bitmap bmp2 = null;
byte[] data;
try
{
w = texture.W2;
h = texture.H2;
if (bmp.Width != w || bmp.Height != h)
{
//Create a new Bitmap with the new sizes
bmp2 = new Bitmap(w, h);
//Scale the texture
using (Graphics g = Graphics.FromImage(bmp2))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawImage(bmp, new Rectangle(0, 0, bmp2.Width, bmp2.Height));
}
bmp = bmp2;
texture.DataSize = new Size(w, h);
}
//Fill the new Bitmap with the texture data
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
data = new byte[4 * w * h];
Marshal.Copy(bmpData.Scan0, data, 0, data.Length);
bmp.UnlockBits(bmpData);
}
finally
{
if (bmp2 != null)
bmp2.Dispose();
}
return _AddTexture(texture, data);
}
public CTexture AddTexture(int w, int h, byte[] data)
{
CTexture texture = GetNewTexture(w, h);
return _AddTexture(texture, data);
}
private CTexture _AddTexture(CTexture texture, byte[] data)
{
Texture t = _CreateTexture(texture, data);
lock (_D3DTextures)
{
_D3DTextures.Add(texture.ID, t);
}
return texture;
}
private Texture _CreateTexture(CTexture texture, byte[] data)
protected override Texture _CreateTexture(CTexture texture, byte[] data)
{
//Create a new texture in the managed pool, which does not need to be recreated on a lost device
//because a copy of the texture is hold in the Ram
@@ -881,18 +608,6 @@ namespace Vocaluxe.Lib.Draw
}
t.UnlockRectangle(0);
}
public CTexture EnqueueTexture(int w, int h, byte[] data)
{
CTexture texture = GetNewTexture(w, h);
lock (_D3DTextures)
{
_D3DTextures.Add(texture.ID, null);
_TexturesToLoad.Enqueue(new STextureQueue(texture, data));
}
return texture;
}
#endregion adding
#region updating
@@ -904,7 +619,7 @@ namespace Vocaluxe.Lib.Draw
/// <param name="h"></param>
/// <param name="data">A byte array containing the new texture's data</param>
/// <returns>True if succeeded</returns>
public bool UpdateTexture(CTexture texture, int w, int h, byte[] data)
public override bool UpdateTexture(CTexture texture, int w, int h, byte[] data)
{
if (!_TextureExists(texture))
return false;
@@ -916,58 +631,14 @@ namespace Vocaluxe.Lib.Draw
return false; // Texture memory to big
texture.DataSize = new Size(w, h);
}
lock (_D3DTextures)
lock (_Textures)
{
_WriteDataToTexture(_D3DTextures[texture.ID], w, data);
}
return true;
}
public bool UpdateOrAddTexture(ref CTexture texture, int w, int h, byte[] data)
{
if (!UpdateTexture(texture, w, h, data))
{
RemoveTexture(ref texture);
texture = AddTexture(w, h, data);
_WriteDataToTexture(_Textures[texture.ID], w, data);
}
return true;
}
#endregion updating
/// <summary>
/// Checks if a texture exists
/// </summary>
/// <param name="texture">The texture to check</param>
/// <returns>True if the texture exists</returns>
private bool _TextureExists(CTexture texture)
{
lock (_D3DTextures)
{
return texture != null && _D3DTextures.ContainsKey(texture.ID);
}
}
/// <summary>
/// Removes a texture from the Vram
/// </summary>
/// <param name="texture">The texture to be removed</param>
public void RemoveTexture(ref CTexture texture)
{
if (texture == null)
return;
lock (_D3DTextures)
{
Texture t;
if (_D3DTextures.TryGetValue(texture.ID, out t))
{
if (t != null)
t.Dispose();
_D3DTextures.Remove(texture.ID);
}
}
texture = null;
}
#region drawing
/// <summary>
/// Draws a texture
@@ -1016,7 +687,7 @@ namespace Vocaluxe.Lib.Draw
{
if (!_TextureExists(texture))
return;
if (_D3DTextures[texture.ID] == null)
if (_Textures[texture.ID] == null)
return;
//Calculate the position
@@ -1081,7 +752,7 @@ namespace Vocaluxe.Lib.Draw
vert[1] = new STexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, y2), c.ToArgb());
vert[2] = new STexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, y2), c.ToArgb());
vert[3] = new STexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, y1), c.ToArgb());
_AddToVertexBuffer(vert, _D3DTextures[texture.ID], _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
_AddToVertexBuffer(vert, _Textures[texture.ID], _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
}
else
{
@@ -1090,7 +761,7 @@ namespace Vocaluxe.Lib.Draw
vert[1] = new STexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, -y2), c.ToArgb());
vert[2] = new STexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, -y2), c.ToArgb());
vert[3] = new STexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, -y1), c.ToArgb());
_AddToVertexBuffer(vert, _D3DTextures[texture.ID], _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
_AddToVertexBuffer(vert, _Textures[texture.ID], _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
}
}
@@ -1106,7 +777,7 @@ namespace Vocaluxe.Lib.Draw
{
if (!_TextureExists(texture))
return;
if (_D3DTextures[texture.ID] == null)
if (_Textures[texture.ID] == null)
return;
float x1 = 0f + begin * texture.WidthRatio;
@@ -1134,7 +805,7 @@ namespace Vocaluxe.Lib.Draw
vert[1] = new STexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, y2), c.ToArgb());
vert[2] = new STexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, y2), c.ToArgb());
vert[3] = new STexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, y1), c.ToArgb());
_AddToVertexBuffer(vert, _D3DTextures[texture.ID], _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
_AddToVertexBuffer(vert, _Textures[texture.ID], _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
}
/// <summary>
@@ -1150,7 +821,7 @@ namespace Vocaluxe.Lib.Draw
{
if (!_TextureExists(texture))
return;
if (_D3DTextures[texture.ID] == null)
if (_Textures[texture.ID] == null)
return;
if (Math.Abs(rect.W) < float.Epsilon || Math.Abs(rect.H) < float.Epsilon || Math.Abs(bounds.H) < float.Epsilon || Math.Abs(bounds.W) < float.Epsilon ||
@@ -1217,57 +888,33 @@ namespace Vocaluxe.Lib.Draw
vert[1] = new STexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), transparent.ToArgb());
vert[2] = new STexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, y1), transparent.ToArgb());
vert[3] = new STexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, y2), c.ToArgb());
_AddToVertexBuffer(vert, _D3DTextures[texture.ID], _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
_AddToVertexBuffer(vert, _Textures[texture.ID], _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
}
#endregion drawing
private void _CheckQueue()
{
lock (_D3DTextures)
{
while (_TexturesToLoad.Count > 0)
{
STextureQueue q = _TexturesToLoad.Dequeue();
if (!_D3DTextures.ContainsKey(q.Texture.ID))
continue;
Texture t = _CreateTexture(q.Texture, q.Data);
_D3DTextures[q.Texture.ID] = t;
}
}
}
/// <summary>
/// Gets the count of current textures
/// </summary>
/// <returns>The amount of textures</returns>
public int GetTextureCount()
{
return _D3DTextures.Count;
}
#endregion Textures
#endregion implementation
#region utility
private SlimDX.Matrix _CalculateRotationMatrix(float rot, float rx1, float rx2, float ry1, float ry2)
private static Matrix _CalculateRotationMatrix(float rot, float rx1, float rx2, float ry1, float ry2)
{
SlimDX.Matrix originTranslation = SlimDX.Matrix.Translation(new Vector3(-(float)CSettings.RenderW / 2, (float)CSettings.RenderH / 2, 0));
Matrix originTranslation = Matrix.Translation(new Vector3(-(float)CSettings.RenderW / 2, (float)CSettings.RenderH / 2, 0));
if (Math.Abs(rot) > float.Epsilon)
{
float rotation = rot * (float)Math.PI / 180;
float centerX = (rx1 + rx2) / 2f;
float centerY = -(ry1 + ry2) / 2f;
SlimDX.Matrix translationA = SlimDX.Matrix.Translation(-centerX, -centerY, 0);
SlimDX.Matrix rotationMat = SlimDX.Matrix.RotationZ(-rotation);
SlimDX.Matrix translationB = SlimDX.Matrix.Translation(centerX, centerY, 0);
Matrix translationA = Matrix.Translation(-centerX, -centerY, 0);
Matrix rotationMat = Matrix.RotationZ(-rotation);
Matrix translationB = Matrix.Translation(centerX, centerY, 0);
//Multiplicate the matrices to get the real world matrix,
//First shift the texture into the center
//Rotate it and shift it back to the origin position
//Apply the originTranslation after
SlimDX.Matrix result = translationA * rotationMat * translationB * originTranslation;
Matrix result = translationA * rotationMat * translationB * originTranslation;
return result;
}
return originTranslation;
+366 -100
View File
@@ -1,20 +1,18 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using Vocaluxe.Base;
using VocaluxeLib;
using VocaluxeLib.Draw;
namespace Vocaluxe.Lib.Draw
{
struct SClientRect
{
public Point Location;
public int Width;
public int Height;
};
struct STextureQueue
{
public readonly CTexture Texture;
@@ -27,104 +25,53 @@ namespace Vocaluxe.Lib.Draw
}
}
abstract class CDrawBaseWindows : CDrawBase
{
public delegate bool MessageEventHandler(ref Message m);
public interface IFormHook
{
MessageEventHandler OnMessage { set; }
}
protected Form _Form;
private SClientRect _Restore;
protected void _CenterToScreen()
{
Screen screen = Screen.FromControl(_Form);
_Form.Location = new Point((screen.WorkingArea.Width - _Form.Width) / 2,
(screen.WorkingArea.Height - _Form.Height) / 2);
}
private bool _OnMessageAvoidScreenOff(ref Message m)
{
switch (m.Msg)
{
case 0x112: // WM_SYSCOMMAND
switch ((int)m.WParam & 0xFFF0)
{
case 0xF100: // SC_KEYMENU
m.Result = IntPtr.Zero;
return false;
case 0xF140: // SC_SCREENSAVER
case 0xF170: // SC_MONITORPOWER
return false;
}
break;
}
return true;
}
protected void _ToggleFullScreen()
{
if (!_Fullscreen)
_EnterFullScreen();
else
_LeaveFullScreen();
}
protected virtual void _EnterFullScreen()
{
Debug.Assert(!_Fullscreen);
_Fullscreen = true;
_Restore.Location = _Form.Location;
_Restore.Width = _Form.Width;
_Restore.Height = _Form.Height;
_Form.FormBorderStyle = FormBorderStyle.None;
Screen screen = Screen.FromControl(_Form);
_Form.DesktopBounds = new Rectangle(screen.Bounds.Location, new Size(screen.Bounds.Width, screen.Bounds.Height));
if (_Form.WindowState == FormWindowState.Maximized)
{
_Form.WindowState = FormWindowState.Normal;
_DoResize();
_Form.WindowState = FormWindowState.Maximized;
}
else
_DoResize();
}
protected abstract void _DoResize();
protected void _LeaveFullScreen()
{
Debug.Assert(_Fullscreen);
_Fullscreen = false;
_Form.FormBorderStyle = FormBorderStyle.Sizable;
_Form.DesktopBounds = new Rectangle(_Restore.Location, new Size(_Restore.Width, _Restore.Height));
}
public virtual bool Init()
{
_Form.Icon = new Icon(Path.Combine(CSettings.ProgramFolder, CSettings.FileNameIcon));
_Form.Text = CSettings.GetFullVersionText();
((IFormHook)_Form).OnMessage = _OnMessageAvoidScreenOff;
return true;
}
}
abstract class CDrawBase
abstract class CDrawBase<TTextureType> where TTextureType : class, IDisposable
{
protected bool _NonPowerOf2TextureSupported;
protected bool _Fullscreen;
protected bool _Run;
protected readonly CKeys _Keys = new CKeys();
protected readonly CMouse _Mouse = new CMouse();
private readonly Object _MutexID = new object();
private int _NextID;
protected readonly Dictionary<int, TTextureType> _Textures = new Dictionary<int, TTextureType>();
private readonly Queue<STextureQueue> _TexturesToLoad = new Queue<STextureQueue>();
protected int _BorderLeft;
protected int _BorderRight;
protected int _BorderTop;
protected int _BorderBottom;
public abstract void ClearScreen();
protected abstract void _AdjustNewBorders();
protected abstract void _LeaveFullScreen();
protected abstract void _OnAfterDraw();
protected abstract void _OnBeforeDraw();
protected abstract void _DoResize();
protected abstract void _EnterFullScreen();
public virtual void Unload()
{
lock (_Textures)
{
//Dispose all textures
foreach (TTextureType texture in _Textures.Values)
{
if (texture != null)
texture.Dispose();
}
_Textures.Clear();
}
}
/// <summary>
/// Calculates the next power of two if the device has the POW2 flag set
/// </summary>
@@ -139,7 +86,30 @@ namespace Vocaluxe.Lib.Draw
return (int)Math.Pow(2, Math.Ceiling(Math.Log(n, 2)));
}
public CTexture GetNewTexture(int origWidth, int origHeight, int dataWidth = 0, int dataHeight = 0)
#region Textures
/// <summary>
/// Creates the texture specified by the reference and fills it with the given data
/// </summary>
/// <param name="texture"></param>
/// <param name="data"></param>
/// <returns></returns>
protected abstract TTextureType _CreateTexture(CTexture texture, byte[] data);
/// <summary>
/// Creates the texture specified by the reference and fills it with the given data<br />
/// Data has to be a pointer to an array of size W*H with 4 Byte values for each pixel (e.g. bmpData.Scan0)
/// </summary>
/// <param name="texture"></param>
/// <param name="data"></param>
/// <returns></returns>
protected virtual TTextureType _CreateTexture(CTexture texture, IntPtr data)
{
byte[] dataArray = new byte[4 * texture.DataSize.Width * texture.DataSize.Height];
Marshal.Copy(data, dataArray, 0, dataArray.Length);
return _CreateTexture(texture, dataArray);
}
protected CTexture _GetNewTextureRef(int origWidth, int origHeight, int dataWidth = 0, int dataHeight = 0)
{
Debug.Assert(origWidth > 0 && origHeight > 0);
Debug.Assert(dataWidth > 0 || dataHeight <= 0);
@@ -152,5 +122,301 @@ namespace Vocaluxe.Lib.Draw
Size dataSize = (dataHeight > 0) ? new Size(dataWidth, dataHeight) : origSize;
return new CTexture(id, origSize, dataSize, _CheckForNextPowerOf2(dataSize.Width), _CheckForNextPowerOf2(dataSize.Height));
}
/// <summary>
/// Adds a texture and stores it in the VRam
/// </summary>
/// <param name="texturePath">The texture's filepath</param>
/// <returns>A STexture object containing the added texture</returns>
public CTexture AddTexture(string texturePath)
{
if (!File.Exists(texturePath))
{
CLog.LogError("Can't find File: " + texturePath);
return null;
}
Bitmap bmp;
try
{
bmp = new Bitmap(texturePath);
}
catch (Exception)
{
CLog.LogError("Error loading Texture: " + texturePath);
return null;
}
CTexture s;
try
{
s = AddTexture(bmp);
}
finally
{
bmp.Dispose();
}
return s;
}
/// <summary>
/// Adds a texture and stores it in the Vram
/// </summary>
/// <param name="bmp">The Bitmap of which the texure will be created from</param>
/// <returns>A STexture object containing the added texture</returns>
public CTexture AddTexture(Bitmap bmp)
{
if (bmp.Height == 0 || bmp.Width == 0)
return null;
int maxSize;
//Apply the right max size
switch (CConfig.TextureQuality)
{
case ETextureQuality.TR_CONFIG_TEXTURE_LOWEST:
maxSize = 128;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_LOW:
maxSize = 256;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_MEDIUM:
maxSize = 512;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_HIGH:
maxSize = 1024;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_HIGHEST:
maxSize = 2048;
break;
default:
maxSize = 512;
break;
}
int w = Math.Min(bmp.Width, maxSize);
int h = Math.Min(bmp.Height, maxSize);
CTexture texture = _GetNewTextureRef(bmp.Width, bmp.Height, w, h);
Bitmap bmp2 = null;
try
{
// Do not stretch the texture, only make it smaller
w = Math.Min(bmp.Width, texture.W2);
h = Math.Min(bmp.Height, texture.H2);
if (bmp.Width != w || bmp.Height != h)
{
//Create a new Bitmap with the new sizes
bmp2 = new Bitmap(w, h);
//Scale the texture
using (Graphics g = Graphics.FromImage(bmp2))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawImage(bmp, new Rectangle(0, 0, bmp2.Width, bmp2.Height));
}
bmp = bmp2;
texture.DataSize = new Size(w, h);
}
//Fill the new Bitmap with the texture data
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
_AddTexture(texture, bmpData.Scan0);
bmp.UnlockBits(bmpData);
}
finally
{
if (bmp2 != null)
bmp2.Dispose();
}
return texture;
}
public CTexture AddTexture(int w, int h, byte[] data)
{
CTexture texture = _GetNewTextureRef(w, h);
_AddTexture(texture, data);
return texture;
}
private void _AddTexture(CTexture texture, byte[] data)
{
TTextureType t = _CreateTexture(texture, data);
lock (_Textures)
{
_Textures.Add(texture.ID, t);
}
}
private void _AddTexture(CTexture texture, IntPtr data)
{
TTextureType t = _CreateTexture(texture, data);
lock (_Textures)
{
_Textures.Add(texture.ID, t);
}
}
public CTexture EnqueueTexture(int w, int h, byte[] data)
{
CTexture texture = _GetNewTextureRef(w, h);
lock (_Textures)
{
_Textures.Add(texture.ID, null);
_TexturesToLoad.Enqueue(new STextureQueue(texture, data));
}
return texture;
}
/// <summary>
/// Updates the data of a texture
/// </summary>
/// <param name="texture">The texture to update</param>
/// <param name="w"></param>
/// <param name="h"></param>
/// <param name="data">A byte array containing the new texture's data</param>
/// <returns>True if succeeded</returns>
public abstract bool UpdateTexture(CTexture texture, int w, int h, byte[] data);
public bool UpdateOrAddTexture(ref CTexture texture, int w, int h, byte[] data)
{
if (!UpdateTexture(texture, w, h, data))
{
RemoveTexture(ref texture);
texture = AddTexture(w, h, data);
}
return true;
}
/// <summary>
/// Checks if a texture exists
/// </summary>
/// <param name="texture">The texture to check</param>
/// <returns>True if the texture exists</returns>
protected bool _TextureExists(CTexture texture)
{
lock (_Textures)
{
TTextureType t;
return texture != null && _Textures.TryGetValue(texture.ID, out t) && t != null;
}
}
protected TTextureType _GetTexture(CTexture textureRef)
{
TTextureType texture;
_Textures.TryGetValue(textureRef.ID, out texture);
return texture;
}
/// <summary>
/// Removes a texture from the Vram
/// </summary>
/// <param name="texture">The texture to be removed</param>
public void RemoveTexture(ref CTexture texture)
{
if (texture == null)
return;
lock (_Textures)
{
TTextureType t;
if (_Textures.TryGetValue(texture.ID, out t))
{
if (t != null)
t.Dispose();
_Textures.Remove(texture.ID);
}
}
texture = null;
}
protected void _CheckQueue()
{
lock (_Textures)
{
while (_TexturesToLoad.Count > 0)
{
STextureQueue q = _TexturesToLoad.Dequeue();
if (!_Textures.ContainsKey(q.Texture.ID))
continue;
TTextureType t = _CreateTexture(q.Texture, q.Data);
_Textures[q.Texture.ID] = t;
}
}
}
public int GetTextureCount()
{
return _Textures.Count;
}
#endregion
/// <summary>
/// Starts the rendering
/// </summary>
public virtual void MainLoop()
{
_Run = true;
_Fullscreen = false;
if (CConfig.FullScreen == EOffOn.TR_CONFIG_ON)
_EnterFullScreen();
else
_DoResize(); //Resize window if aspect ratio is incorrect
while (_Run)
{
_CheckQueue();
//We want to begin drawing
_OnBeforeDraw();
//Clear the previous Frame
ClearScreen();
if (!CGraphics.Draw())
_Run = false;
_OnAfterDraw();
if (!CGraphics.UpdateGameLogic(_Keys, _Mouse))
_Run = false;
//Apply fullscreen mode
if ((CConfig.FullScreen == EOffOn.TR_CONFIG_ON) != _Fullscreen)
_ToggleFullScreen();
//Apply border changes
if (_BorderLeft != CConfig.BorderLeft || _BorderRight != CConfig.BorderRight || _BorderTop != CConfig.BorderTop || _BorderBottom != CConfig.BorderBottom)
{
_BorderLeft = CConfig.BorderLeft;
_BorderRight = CConfig.BorderRight;
_BorderTop = CConfig.BorderTop;
_BorderBottom = CConfig.BorderBottom;
_AdjustNewBorders();
}
if (CConfig.VSync == EOffOn.TR_CONFIG_OFF)
{
if (CTime.IsRunning())
{
int delay = (int)Math.Floor(CConfig.CalcCycleTime() - CTime.GetMilliseconds());
if (delay >= 1 && delay < 500)
Thread.Sleep(delay);
}
}
//Calculate the FPS Rate and restart the timer after a frame
CTime.CalculateFPS();
CTime.Restart();
}
}
protected void _ToggleFullScreen()
{
if (!_Fullscreen)
_EnterFullScreen();
else
_LeaveFullScreen();
}
}
}
+192
View File
@@ -0,0 +1,192 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Vocaluxe.Base;
namespace Vocaluxe.Lib.Draw
{
public delegate bool MessageEventHandler(ref Message m);
public interface IFormHook
{
MessageEventHandler OnMessage { set; }
}
abstract class CDrawBaseWindows<TTextureType> : CDrawBase<TTextureType> where TTextureType : class, IDisposable
{
private struct SClientRect
{
public Point Location;
public int Width;
public int Height;
}
protected Form _Form;
private SClientRect _Restore;
public override void Unload()
{
base.Unload();
try
{
_Form.Close();
}
catch {}
}
protected void _CenterToScreen()
{
Screen screen = Screen.FromControl(_Form);
_Form.Location = new Point((screen.WorkingArea.Width - _Form.Width) / 2,
(screen.WorkingArea.Height - _Form.Height) / 2);
}
private static bool _OnMessageAvoidScreenOff(ref Message m)
{
switch (m.Msg)
{
case 0x112: // WM_SYSCOMMAND
switch ((int)m.WParam & 0xFFF0)
{
case 0xF100: // SC_KEYMENU
m.Result = IntPtr.Zero;
return false;
case 0xF140: // SC_SCREENSAVER
case 0xF170: // SC_MONITORPOWER
return false;
}
break;
}
return true;
}
protected override void _EnterFullScreen()
{
Debug.Assert(!_Fullscreen);
_Fullscreen = true;
_Restore.Location = _Form.Location;
_Restore.Width = _Form.Width;
_Restore.Height = _Form.Height;
_Form.FormBorderStyle = FormBorderStyle.None;
Screen screen = Screen.FromControl(_Form);
_Form.DesktopBounds = new Rectangle(screen.Bounds.Location, new Size(screen.Bounds.Width, screen.Bounds.Height));
if (_Form.WindowState == FormWindowState.Maximized)
{
_Form.WindowState = FormWindowState.Normal;
_DoResize();
_Form.WindowState = FormWindowState.Maximized;
}
else
_DoResize();
}
protected override void _LeaveFullScreen()
{
Debug.Assert(_Fullscreen);
_Fullscreen = false;
_Form.FormBorderStyle = FormBorderStyle.Sizable;
_Form.DesktopBounds = new Rectangle(_Restore.Location, new Size(_Restore.Width, _Restore.Height));
}
#region form event handlers
private void _OnClose(object sender, CancelEventArgs e)
{
_Run = false;
}
private void _OnLoad(object sender, EventArgs e)
{
ClearScreen();
}
protected virtual void _OnResize(object sender, EventArgs e)
{
_DoResize();
}
#region mouse event handlers
protected void _OnMouseMove(object sender, MouseEventArgs e)
{
_Mouse.MouseMove(e);
}
protected void _OnMouseWheel(object sender, MouseEventArgs e)
{
_Mouse.MouseWheel(e);
}
protected void _OnMouseDown(object sender, MouseEventArgs e)
{
_Mouse.MouseDown(e);
}
protected void _OnMouseUp(object sender, MouseEventArgs e)
{
_Mouse.MouseUp(e);
}
protected void _OnMouseLeave(object sender, EventArgs e)
{
_Mouse.Visible = false;
Cursor.Show();
}
protected void _OnMouseEnter(object sender, EventArgs e)
{
Cursor.Hide();
_Mouse.Visible = true;
}
#endregion
#region keyboard event handlers
protected void _OnPreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
_OnKeyDown(sender, new KeyEventArgs(e.KeyData));
}
protected void _OnKeyDown(object sender, KeyEventArgs e)
{
_Keys.KeyDown(e);
}
protected void _OnKeyPress(object sender, KeyPressEventArgs e)
{
_Keys.KeyPress(e);
}
protected void _OnKeyUp(object sender, KeyEventArgs e)
{
_Keys.KeyUp(e);
}
#endregion keyboard event handlers
#endregion
public virtual bool Init()
{
_Form.Icon = new Icon(Path.Combine(CSettings.ProgramFolder, CSettings.FileNameIcon));
_Form.Text = CSettings.GetFullVersionText();
((IFormHook)_Form).OnMessage = _OnMessageAvoidScreenOff;
_Form.Closing += _OnClose;
_Form.Resize += _OnResize;
_Form.Load += _OnLoad;
return true;
}
public override void MainLoop()
{
_Form.Show();
base.MainLoop();
_Form.Hide();
}
}
}
+82 -342
View File
@@ -15,14 +15,10 @@
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
#endregion
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Threading;
using OpenTK;
using OpenTK.Graphics;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
@@ -41,7 +37,6 @@ using DepthFunction = OpenTK.Graphics.OpenGL.DepthFunction;
using EnableCap = OpenTK.Graphics.OpenGL.EnableCap;
using GL = OpenTK.Graphics.OpenGL.GL;
using GenerateMipmapTarget = OpenTK.Graphics.OpenGL.GenerateMipmapTarget;
using KeyPressEventArgs = System.Windows.Forms.KeyPressEventArgs;
using MatrixMode = OpenTK.Graphics.OpenGL.MatrixMode;
using PixelFormat = OpenTK.Graphics.OpenGL.PixelFormat;
using PixelInternalFormat = OpenTK.Graphics.OpenGL.PixelInternalFormat;
@@ -54,29 +49,46 @@ using TextureTarget = OpenTK.Graphics.OpenGL.TextureTarget;
namespace Vocaluxe.Lib.Draw
{
class CFormHook : Form, CDrawBaseWindows.IFormHook
class CFormHook : Form, IFormHook
{
public CDrawBaseWindows.MessageEventHandler OnMessage { private get; set; }
public MessageEventHandler OnMessage { private get; set; }
protected override void WndProc(ref Message m)
{
if (OnMessage(ref m))
if (OnMessage == null || OnMessage(ref m))
base.WndProc(ref m);
}
}
class COpenGL : CDrawBaseWindows, IDraw
class CGLTexture : IDisposable
{
public int PBO;
//The texture "name" according to the specs
public readonly int Name;
public CGLTexture(int name)
{
Name = name;
}
private bool _IsDisposed;
public void Dispose()
{
if (_IsDisposed)
throw new ObjectDisposedException(GetType().Name);
_IsDisposed = true;
GL.DeleteTexture(Name);
if (PBO > 0)
GL.DeleteBuffers(1, ref PBO);
}
}
class COpenGL : CDrawBaseWindows<CGLTexture>, IDraw
{
#region private vars
private readonly CKeys _Keys;
private readonly CMouse _Mouse;
private bool _Run;
private readonly GLControl _Control;
private readonly Dictionary<int, CTexture> _Textures = new Dictionary<int, CTexture>();
private readonly Queue<STextureQueue> _TexturesToLoad = new Queue<STextureQueue>();
private int _H = 1;
private int _W = 1;
private int _Y;
@@ -112,18 +124,11 @@ namespace Vocaluxe.Lib.Draw
_Form.Controls.Add(_Control);
_Control.KeyDown += _OnKeyDown;
_Control.PreviewKeyDown += _OnPreviewKeyDown;
_Control.KeyPress += _OnKeyPress;
_Control.KeyUp += _OnKeyUp;
_Keys = new CKeys();
_Form.Closing += _OnClosingEvent;
_Form.Load += _OnLoad;
_Form.Resize += _OnResize;
_Control.KeyDown += _OnKeyDownEvent;
_Control.PreviewKeyDown += _OnPreviewKeyDownEvent;
_Control.KeyPress += _OnKeyPressEvent;
_Control.KeyUp += _OnKeyUpEvent;
_Mouse = new CMouse();
_Control.MouseMove += _OnMouseMove;
_Control.MouseWheel += _OnMouseWheel;
_Control.MouseDown += _OnMouseDown;
@@ -139,7 +144,7 @@ namespace Vocaluxe.Lib.Draw
}
#region Helpers
private int _CheckAntiAliasingMode(int setValue)
private static int _CheckAntiAliasingMode(int setValue)
{
int samples = 0;
@@ -201,79 +206,13 @@ namespace Vocaluxe.Lib.Draw
#endregion Helpers
#region form events
private void _OnClosingEvent(object sender, CancelEventArgs e)
{
_Run = false;
}
private static void _OnLoad(object sender, EventArgs e)
{
GL.ClearColor(Color.Black);
}
private void _OnResize(object sender, EventArgs e)
protected override void _OnResize(object sender, EventArgs e)
{
_Control.ClientSize = _Form.ClientSize;
_DoResize();
base._OnResize(sender, e);
}
#endregion form events
#region mouse event handlers
private void _OnMouseMove(object sender, MouseEventArgs e)
{
_Mouse.MouseMove(e);
}
private void _OnMouseWheel(object sender, MouseEventArgs e)
{
_Mouse.MouseWheel(e);
}
private void _OnMouseDown(object sender, MouseEventArgs e)
{
_Mouse.MouseDown(e);
}
private void _OnMouseUp(object sender, MouseEventArgs e)
{
_Mouse.MouseUp(e);
}
private void _OnMouseLeave(object sender, EventArgs e)
{
_Mouse.Visible = false;
Cursor.Show();
}
private void _OnMouseEnter(object sender, EventArgs e)
{
Cursor.Hide();
_Mouse.Visible = true;
}
#endregion
#region keyboard event handlers
private void _OnPreviewKeyDownEvent(object sender, PreviewKeyDownEventArgs e)
{
_OnKeyDownEvent(sender, new KeyEventArgs(e.KeyData));
}
private void _OnKeyDownEvent(object sender, KeyEventArgs e)
{
_Keys.KeyDown(e);
}
private void _OnKeyPressEvent(object sender, KeyPressEventArgs e)
{
_Keys.KeyPress(e);
}
private void _OnKeyUpEvent(object sender, KeyEventArgs e)
{
_Keys.KeyUp(e);
}
#endregion keyboard event handlers
protected override void _DoResize()
{
_H = _Control.Height;
@@ -316,59 +255,19 @@ namespace Vocaluxe.Lib.Draw
GL.DepthRange(CSettings.ZFar, CSettings.ZNear);
GL.DepthFunc(DepthFunction.Lequal);
GL.Enable(EnableCap.DepthTest);
GL.ClearColor(Color.Black);
return true;
}
public void MainLoop()
protected override void _OnBeforeDraw()
{
_Run = true;
int delay = 0;
_Form.Show();
if (CConfig.FullScreen == EOffOn.TR_CONFIG_ON)
_EnterFullScreen();
while (_Run)
{
ClearScreen();
if (!CGraphics.Draw())
_Run = false;
if (!CGraphics.UpdateGameLogic(_Keys, _Mouse))
_Run = false;
_Control.SwapBuffers();
if ((CConfig.FullScreen == EOffOn.TR_CONFIG_ON) != _Fullscreen)
_ToggleFullScreen();
_CheckQueue();
if (CTime.IsRunning())
delay = (int)Math.Floor(CConfig.CalcCycleTime() - CTime.GetMilliseconds());
if (delay >= 1 && CConfig.VSync == EOffOn.TR_CONFIG_OFF)
Thread.Sleep(delay);
CTime.CalculateFPS();
CTime.Restart();
Application.DoEvents();
}
_Form.Close();
//Nothing to do
}
public void Unload()
protected override void _OnAfterDraw()
{
try
{
_Form.Close();
}
catch {}
var textures = new CTexture[_Textures.Count];
_Textures.Values.CopyTo(textures, 0);
for (int i = 0; i < _Textures.Count; i++)
RemoveTexture(ref textures[i]);
_Control.SwapBuffers();
}
public int GetScreenWidth()
@@ -383,17 +282,22 @@ namespace Vocaluxe.Lib.Draw
#endregion main stuff
#region Basic Draw Methods
public void ClearScreen()
public override void ClearScreen()
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
}
protected override void _AdjustNewBorders()
{
//TODO: Implement!!!
}
public CTexture CopyScreen()
{
CTexture texture = GetNewTexture(_W, _H);
CTexture texture = _GetNewTextureRef(_W, _H);
texture.Name = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
CGLTexture t = new CGLTexture(GL.GenTexture());
GL.BindTexture(TextureTarget.Texture2D, t.Name);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, texture.W2, texture.H2, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
GL.CopyTexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, _X, _Y, _W, _H);
@@ -406,7 +310,7 @@ namespace Vocaluxe.Lib.Draw
// Add to Texture List
lock (_Textures)
{
_Textures[texture.ID] = texture;
_Textures[texture.ID] = t;
}
return texture;
@@ -422,7 +326,7 @@ namespace Vocaluxe.Lib.Draw
}
else
{
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
GL.BindTexture(TextureTarget.Texture2D, _Textures[texture.ID].Name);
GL.CopyTexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, 0, 0, GetScreenWidth(), GetScreenHeight());
@@ -532,149 +436,46 @@ namespace Vocaluxe.Lib.Draw
#region Textures
#region adding
public CTexture AddTexture(string texturePath)
protected override CGLTexture _CreateTexture(CTexture texture, IntPtr data)
{
if (!File.Exists(texturePath))
{
CLog.LogError("Can't find File: " + texturePath);
return null;
}
Bitmap bmp;
try
{
bmp = new Bitmap(texturePath);
}
catch (Exception)
{
CLog.LogError("Error loading Texture: " + texturePath);
return null;
}
try
{
return AddTexture(bmp);
}
finally
{
bmp.Dispose();
}
}
CGLTexture t = new CGLTexture(GL.GenTexture());
public CTexture AddTexture(Bitmap bmp)
{
if (bmp.Height == 0 || bmp.Width == 0)
return null;
GL.BindTexture(TextureTarget.Texture2D, t.Name);
int maxSize;
switch (CConfig.TextureQuality)
{
case ETextureQuality.TR_CONFIG_TEXTURE_LOWEST:
maxSize = 128;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_LOW:
maxSize = 256;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_MEDIUM:
maxSize = 512;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_HIGH:
maxSize = 1024;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_HIGHEST:
maxSize = 2048;
break;
default:
maxSize = 512;
break;
}
int w = Math.Min(bmp.Width, maxSize);
int h = Math.Min(bmp.Height, maxSize);
CTexture texture = GetNewTexture(w, h);
texture.Name = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
Bitmap bmp2 = null;
try
{
if (bmp.Width != w || bmp.Height != h)
{
//Create a new Bitmap with the new sizes
bmp2 = new Bitmap(w, h);
//Scale the texture
using (Graphics g = Graphics.FromImage(bmp2))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawImage(bmp, new Rectangle(0, 0, bmp2.Width, bmp2.Height));
}
bmp = bmp2;
}
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, texture.W2, texture.H2, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, bmpData.Width, bmpData.Height, PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0);
bmp.UnlockBits(bmpData);
}
finally
{
if (bmp2 != null)
bmp2.Dispose();
}
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, texture.W2, texture.H2, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, texture.DataSize.Width, texture.DataSize.Height, PixelFormat.Bgra, PixelType.UnsignedByte, data);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, 0);
// Add to Texture List
texture.TexturePath = String.Empty;
lock (_Textures)
{
_Textures[texture.ID] = texture;
}
return texture;
return t;
}
public CTexture AddTexture(int w, int h, byte[] data)
protected override CGLTexture _CreateTexture(CTexture texture, byte[] data)
{
CTexture texture = GetNewTexture(w, h);
CGLTexture t = new CGLTexture(GL.GenTexture());
_CreateTexture(texture, data);
lock (_Textures)
{
_Textures[texture.ID] = texture;
}
return texture;
}
private void _CreateTexture(CTexture texture, byte[] data)
{
if (_UsePBO)
{
try
{
GL.GenBuffers(1, out texture.PBO);
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, texture.PBO);
GL.GenBuffers(1, out t.PBO);
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, t.PBO);
GL.BufferData(BufferTarget.PixelUnpackBuffer, (IntPtr)data.Length, IntPtr.Zero, BufferUsageHint.StreamDraw);
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
}
catch (Exception)
catch (Exception e)
{
//throw;
CLog.LogError("PBO creation failed. Using fallback solution.", false, false, e);
_UsePBO = false;
}
}
texture.Name = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
GL.BindTexture(TextureTarget.Texture2D, t.Name);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, texture.W2, texture.H2, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, texture.OrigSize.Width, texture.OrigSize.Height, PixelFormat.Bgra, PixelType.UnsignedByte, data);
@@ -686,27 +487,15 @@ namespace Vocaluxe.Lib.Draw
GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, 0);
}
public CTexture EnqueueTexture(int w, int h, byte[] data)
{
CTexture texture = GetNewTexture(w, h);
lock (_Textures)
{
var queue = new STextureQueue(texture, data);
_TexturesToLoad.Enqueue(queue);
_Textures[texture.ID] = texture;
}
return texture;
return t;
}
#endregion adding
#region updating
public bool UpdateTexture(CTexture texture, int w, int h, byte[] data)
public override bool UpdateTexture(CTexture texture, int w, int h, byte[] data)
{
if (!_TextureExists(texture))
CGLTexture t = _GetTexture(texture);
if (t == null)
return false;
if (texture.DataSize.Width != w || texture.DataSize.Height != h)
{
@@ -716,16 +505,17 @@ namespace Vocaluxe.Lib.Draw
return false; // Texture memory to big
texture.DataSize = new Size(w, h);
}
if (_UsePBO)
{
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, texture.PBO);
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, t.PBO);
IntPtr buffer = GL.MapBuffer(BufferTarget.PixelUnpackBuffer, BufferAccess.WriteOnly);
Marshal.Copy(data, 0, buffer, data.Length);
GL.UnmapBuffer(BufferTarget.PixelUnpackBuffer);
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
GL.BindTexture(TextureTarget.Texture2D, t.Name);
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, w, h, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
@@ -737,7 +527,7 @@ namespace Vocaluxe.Lib.Draw
return true;
}
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
GL.BindTexture(TextureTarget.Texture2D, t.Name);
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, w, h, PixelFormat.Bgra, PixelType.UnsignedByte, data);
@@ -747,43 +537,8 @@ namespace Vocaluxe.Lib.Draw
return true;
}
public bool UpdateOrAddTexture(ref CTexture texture, int w, int h, byte[] data)
{
if (!UpdateTexture(texture, w, h, data))
{
RemoveTexture(ref texture);
texture = AddTexture(w, h, data);
}
return true;
}
#endregion updating
public void RemoveTexture(ref CTexture texture)
{
lock (_Textures)
{
if (_TextureExists(texture))
{
GL.DeleteTexture(texture.Name);
if (texture.PBO > 0)
GL.DeleteBuffers(1, ref texture.PBO);
}
_Textures.Remove(texture.ID);
}
texture = null;
}
private bool _TextureExists(CTexture texture)
{
lock (_Textures)
{
if (texture != null && _Textures.ContainsKey(texture.ID) && texture.Name > 0)
return true;
}
return false;
}
#region drawing
public void DrawTexture(CTexture texture)
{
@@ -806,7 +561,8 @@ namespace Vocaluxe.Lib.Draw
public void DrawTexture(CTexture texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false)
{
if (!_TextureExists(texture))
CGLTexture t = _GetTexture(texture);
if (t == null)
return;
if (Math.Abs(rect.W) < float.Epsilon || Math.Abs(rect.H) < float.Epsilon || Math.Abs(bounds.H) < float.Epsilon || Math.Abs(bounds.W) < float.Epsilon ||
@@ -819,7 +575,7 @@ namespace Vocaluxe.Lib.Draw
if (bounds.Y > rect.Y + rect.H || bounds.Y + bounds.H < rect.Y)
return;
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
GL.BindTexture(TextureTarget.Texture2D, t.Name);
float x1 = (bounds.X - rect.X) / rect.W * texture.WidthRatio;
float x2 = (bounds.X + bounds.W - rect.X) / rect.W * texture.WidthRatio;
@@ -914,9 +670,11 @@ namespace Vocaluxe.Lib.Draw
public void DrawTexture(CTexture texture, SRectF rect, SColorF color, float begin, float end)
{
if (!_TextureExists(texture))
CGLTexture t = _GetTexture(texture);
if (t == null)
return;
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
GL.BindTexture(TextureTarget.Texture2D, t.Name);
GL.Enable(EnableCap.Blend);
GL.Color4(color.R, color.G, color.B, color.A * CGraphics.GlobalAlpha);
@@ -945,7 +703,8 @@ namespace Vocaluxe.Lib.Draw
public void DrawTextureReflection(CTexture texture, SRectF rect, SColorF color, SRectF bounds, float space, float height)
{
if (!_TextureExists(texture))
CGLTexture t = _GetTexture(texture);
if (t == null)
return;
if (Math.Abs(rect.W) < float.Epsilon || Math.Abs(rect.H) < float.Epsilon || Math.Abs(bounds.H) < float.Epsilon || Math.Abs(bounds.W) < float.Epsilon ||
@@ -961,7 +720,7 @@ namespace Vocaluxe.Lib.Draw
if (height > bounds.H)
height = bounds.H;
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
GL.BindTexture(TextureTarget.Texture2D, t.Name);
float x1 = (bounds.X - rect.X) / rect.W * texture.WidthRatio;
float x2 = (bounds.X + bounds.W - rect.X) / rect.W * texture.WidthRatio;
@@ -1039,25 +798,6 @@ namespace Vocaluxe.Lib.Draw
}
#endregion drawing
public int GetTextureCount()
{
return _Textures.Count;
}
private void _CheckQueue()
{
lock (_Textures)
{
while (_TexturesToLoad.Count > 0)
{
STextureQueue q = _TexturesToLoad.Dequeue();
if (!_Textures.ContainsKey(q.Texture.ID))
continue;
_CreateTexture(q.Texture, q.Data);
}
}
}
#endregion Textures
#endregion implementation
+1
View File
@@ -225,6 +225,7 @@
<Compile Include="Lib\Database\CHighscoreDB.cs" />
<Compile Include="Lib\Database\CResourceDB.cs" />
<Compile Include="Lib\Draw\CDrawBase.cs" />
<Compile Include="Lib\Draw\CDrawBaseWindows.cs" />
<Compile Include="Lib\Sound\Playback\CAudioStreamBase.cs" />
<Compile Include="Lib\Sound\Playback\CPlaybackBase.cs" />
<Compile Include="Lib\Sound\Playback\CRingBuffer.cs" />
+5 -5
View File
@@ -19,12 +19,12 @@ using System.Drawing;
namespace VocaluxeLib.Draw
{
/// <summary>
/// Reference to a texture in the drawing driver
/// </summary>
public class CTexture
{
public readonly int ID;
public int PBO;
//Only used by OpenGL (the texture "name" according to the specs)
public int Name = -1;
public string TexturePath = "";
@@ -117,8 +117,8 @@ namespace VocaluxeLib.Draw
private void _CalcRatios()
{
WidthRatio = (float)_DataSize.Width / _W2;
HeightRatio = (float)_DataSize.Height / _H2;
WidthRatio = (float)_DataSize.Width / _W2;
HeightRatio = (float)_DataSize.Height / _H2;
}
}
}
-2
View File
@@ -136,7 +136,6 @@ namespace VocaluxeLib
void LoadPreview(CSong song, float start = 0f);
void PlayPreview(float start = -1f);
void StopPreview();
}
public interface IDrawing
@@ -338,6 +337,5 @@ namespace VocaluxeLib
CTexture GetVideoTexture();
bool IsPlaying();
float GetLength();
}
}