Unify as much of D3D and OpenGL as possible
This commit is contained in:
1 parent
46acaf092a
commit
76ededf9f3
7 files changed
+710
-866
No files matched your search
+64
-417
@@ -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
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user