From 76ededf9f329494c807fed29031fce67534e6f44 Mon Sep 17 00:00:00 2001 From: Flamefire Date: Thu, 11 Sep 2014 21:58:30 +0200 Subject: [PATCH] Unify as much of D3D and OpenGL as possible --- Vocaluxe/Lib/Draw/CDirect3D.cs | 481 ++++---------------------- Vocaluxe/Lib/Draw/CDrawBase.cs | 466 +++++++++++++++++++------ Vocaluxe/Lib/Draw/CDrawBaseWindows.cs | 192 ++++++++++ Vocaluxe/Lib/Draw/COpenGL.cs | 424 +++++------------------ Vocaluxe/Vocaluxe.csproj | 1 + VocaluxeLib/Draw/CTexture.cs | 10 +- VocaluxeLib/IBasic.cs | 2 - 7 files changed, 710 insertions(+), 866 deletions(-) create mode 100644 Vocaluxe/Lib/Draw/CDrawBaseWindows.cs diff --git a/Vocaluxe/Lib/Draw/CDirect3D.cs b/Vocaluxe/Lib/Draw/CDirect3D.cs index ca6c771a..aa337fe0 100644 --- a/Vocaluxe/Lib/Draw/CDirect3D.cs +++ b/Vocaluxe/Lib/Draw/CDirect3D.cs @@ -15,13 +15,10 @@ // along with Vocaluxe. If not, see . #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, 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 _D3DTextures = new Dictionary(); - private readonly Queue _TexturesToLoad = new Queue(); - 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 _Vertices = new Queue(); private readonly Queue _VerticesTextures = new Queue(); - private readonly Queue _VerticesRotationMatrices = new Queue(); + private readonly Queue _VerticesRotationMatrices = new Queue(); #endregion private vars /// @@ -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; } - /// - /// Starts the rendering - /// - 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(); } /// @@ -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 /// /// - 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 /// A TexturedColoredVertex array containg 4 vertices /// The texture the vertex should be textured with /// The vertices' rotation - 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 /// /// Removes all textures from the screen /// - 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 /// 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 - /// - /// Adds a texture and stores it in the VRam - /// - /// The texture's filepath - /// A STexture object containing the added texture - 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; - } - - /// - /// Adds a texture and stores it in the Vram - /// - /// The Bitmap of which the texure will be created from - /// A STexture object containing the added texture - 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 /// /// A byte array containing the new texture's data /// True if succeeded - 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 - /// - /// Checks if a texture exists - /// - /// The texture to check - /// True if the texture exists - private bool _TextureExists(CTexture texture) - { - lock (_D3DTextures) - { - return texture != null && _D3DTextures.ContainsKey(texture.ID); - } - } - - /// - /// Removes a texture from the Vram - /// - /// The texture to be removed - 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 /// /// 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)); } /// @@ -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; - } - } - } - - /// - /// Gets the count of current textures - /// - /// The amount of textures - 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; diff --git a/Vocaluxe/Lib/Draw/CDrawBase.cs b/Vocaluxe/Lib/Draw/CDrawBase.cs index 7da7073f..c1b7505a 100644 --- a/Vocaluxe/Lib/Draw/CDrawBase.cs +++ b/Vocaluxe/Lib/Draw/CDrawBase.cs @@ -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 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 _Textures = new Dictionary(); + private readonly Queue _TexturesToLoad = new Queue(); + + 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(); + } + } + /// /// Calculates the next power of two if the device has the POW2 flag set /// @@ -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 + /// + /// Creates the texture specified by the reference and fills it with the given data + /// + /// + /// + /// + protected abstract TTextureType _CreateTexture(CTexture texture, byte[] data); + + /// + /// Creates the texture specified by the reference and fills it with the given data
+ /// Data has to be a pointer to an array of size W*H with 4 Byte values for each pixel (e.g. bmpData.Scan0) + ///
+ /// + /// + /// + 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)); } + + /// + /// Adds a texture and stores it in the VRam + /// + /// The texture's filepath + /// A STexture object containing the added texture + 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; + } + + /// + /// Adds a texture and stores it in the Vram + /// + /// The Bitmap of which the texure will be created from + /// A STexture object containing the added texture + 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; + } + + /// + /// Updates the data of a texture + /// + /// The texture to update + /// + /// + /// A byte array containing the new texture's data + /// True if succeeded + 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; + } + + /// + /// Checks if a texture exists + /// + /// The texture to check + /// True if the texture exists + 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; + } + + /// + /// Removes a texture from the Vram + /// + /// The texture to be removed + 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 + + /// + /// Starts the rendering + /// + 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(); + } } } \ No newline at end of file diff --git a/Vocaluxe/Lib/Draw/CDrawBaseWindows.cs b/Vocaluxe/Lib/Draw/CDrawBaseWindows.cs new file mode 100644 index 00000000..7f2c31a5 --- /dev/null +++ b/Vocaluxe/Lib/Draw/CDrawBaseWindows.cs @@ -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 : CDrawBase 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(); + } + } +} \ No newline at end of file diff --git a/Vocaluxe/Lib/Draw/COpenGL.cs b/Vocaluxe/Lib/Draw/COpenGL.cs index 09db4bf7..fa22be66 100644 --- a/Vocaluxe/Lib/Draw/COpenGL.cs +++ b/Vocaluxe/Lib/Draw/COpenGL.cs @@ -15,14 +15,10 @@ // along with Vocaluxe. If not, see . #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, IDraw { #region private vars - private readonly CKeys _Keys; - private readonly CMouse _Mouse; - private bool _Run; - private readonly GLControl _Control; - private readonly Dictionary _Textures = new Dictionary(); - private readonly Queue _TexturesToLoad = new Queue(); - 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 diff --git a/Vocaluxe/Vocaluxe.csproj b/Vocaluxe/Vocaluxe.csproj index 5585782e..aed2508e 100644 --- a/Vocaluxe/Vocaluxe.csproj +++ b/Vocaluxe/Vocaluxe.csproj @@ -225,6 +225,7 @@ + diff --git a/VocaluxeLib/Draw/CTexture.cs b/VocaluxeLib/Draw/CTexture.cs index e228a4a3..dda82f9c 100644 --- a/VocaluxeLib/Draw/CTexture.cs +++ b/VocaluxeLib/Draw/CTexture.cs @@ -19,12 +19,12 @@ using System.Drawing; namespace VocaluxeLib.Draw { + /// + /// Reference to a texture in the drawing driver + /// 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; } } } \ No newline at end of file diff --git a/VocaluxeLib/IBasic.cs b/VocaluxeLib/IBasic.cs index 0583e189..ade82b4c 100644 --- a/VocaluxeLib/IBasic.cs +++ b/VocaluxeLib/IBasic.cs @@ -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(); - } } \ No newline at end of file