Improve CTexture and Drawing stuff related to that

(Don't use an ID queue, store DataSizes of texture data)
This commit is contained in:
Flamefire committed 2014-09-10 20:58:35 +02:00
1 parent e9b584d84c
commit ad18bec52c
7 files changed
+178 -201

No files matched your search

+48 -73
View File
@@ -37,7 +37,6 @@ namespace Vocaluxe.Lib.Draw
class CDirect3D : RenderForm, IDraw
{
#region private vars
private const int _MaxID = 100000;
private readonly CKeys _Keys;
private readonly CMouse _Mouse;
@@ -53,9 +52,6 @@ namespace Vocaluxe.Lib.Draw
private readonly Dictionary<int, Texture> _D3DTextures = new Dictionary<int, Texture>();
private readonly Queue<STextureQueue> _TexturesToLoad = new Queue<STextureQueue>();
private readonly Queue<int> _IDs = new Queue<int>(_MaxID);
private readonly Object _MutexTexture = new Object();
private VertexBuffer _VertexBuffer;
private IndexBuffer _IndexBuffer;
@@ -76,7 +72,6 @@ namespace Vocaluxe.Lib.Draw
private readonly Queue<Texture> _VerticesTextures = new Queue<Texture>();
private readonly Queue<SlimDX.Matrix> _VerticesRotationMatrices = new Queue<SlimDX.Matrix>();
private readonly bool _NonPowerOf2TextureSupported;
#endregion private vars
/// <summary>
@@ -86,10 +81,6 @@ namespace Vocaluxe.Lib.Draw
{
Icon = new Icon(Path.Combine(CSettings.ProgramFolder, CSettings.FileNameIcon));
//Fill Queue with 100000 IDs
for (int i = 0; i < _MaxID; i++)
_IDs.Enqueue(i);
_Keys = new CKeys();
try
{
@@ -177,10 +168,10 @@ namespace Vocaluxe.Lib.Draw
CreateFlags flags = (caps.DeviceCaps & DeviceCaps.HWTransformAndLight) != 0 ? CreateFlags.HardwareVertexProcessing : CreateFlags.SoftwareVertexProcessing;
//Check if Pow2 textures are needed
_NonPowerOf2TextureSupported = true;
_NonPowerOf2TextureSupported &= (caps.TextureCaps & TextureCaps.Pow2) == 0;
_NonPowerOf2TextureSupported &= (caps.TextureCaps & TextureCaps.NonPow2Conditional) == 0;
_NonPowerOf2TextureSupported &= (caps.TextureCaps & TextureCaps.SquareOnly) == 0;
CDrawHelper.NonPowerOf2TextureSupported = true;
CDrawHelper.NonPowerOf2TextureSupported &= (caps.TextureCaps & TextureCaps.Pow2) == 0;
CDrawHelper.NonPowerOf2TextureSupported &= (caps.TextureCaps & TextureCaps.NonPow2Conditional) == 0;
CDrawHelper.NonPowerOf2TextureSupported &= (caps.TextureCaps & TextureCaps.SquareOnly) == 0;
try
{
@@ -689,20 +680,19 @@ namespace Vocaluxe.Lib.Draw
/// </summary>
public CTexture CopyScreen()
{
CTexture texture = _GetNewTexture(_W, _H);
CTexture texture = CDrawHelper.GetNewTexture(_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 (_MutexTexture)
lock (_D3DTextures)
{
texture.ID = _IDs.Dequeue();
_D3DTextures.Add(texture.ID, tex);
return texture;
}
return texture;
}
/// <summary>
@@ -711,8 +701,7 @@ namespace Vocaluxe.Lib.Draw
/// <param name="texture">The texture in which the frame is copied to</param>
public void CopyScreen(ref CTexture texture)
{
//Check for actual texture sizes! (W2/H2) as it may be up/downsized compared to OrigSize
if (!_TextureExists(texture) || texture.W2 != GetScreenWidth() || texture.H2 != GetScreenHeight())
if (!_TextureExists(texture) || texture.DataSize.Width != GetScreenWidth() || texture.DataSize.Height != GetScreenHeight())
{
RemoveTexture(ref texture);
texture = CopyScreen();
@@ -860,15 +849,15 @@ namespace Vocaluxe.Lib.Draw
int w = Math.Min(bmp.Width, maxSize);
int h = Math.Min(bmp.Height, maxSize);
w = _CheckForNextPowerOf2(w);
h = _CheckForNextPowerOf2(h);
var texture = new CTexture(bmp.Width, bmp.Height, w, h, true);
CTexture texture = CDrawHelper.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
@@ -881,6 +870,7 @@ namespace Vocaluxe.Lib.Draw
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
@@ -895,33 +885,32 @@ namespace Vocaluxe.Lib.Draw
bmp2.Dispose();
}
return _AddTexture(texture, w, data);
return _AddTexture(texture, data);
}
public CTexture AddTexture(int w, int h, byte[] data)
{
CTexture texture = _GetNewTexture(w, h);
return _AddTexture(texture, w, data);
CTexture texture = CDrawHelper.GetNewTexture(w, h);
return _AddTexture(texture, data);
}
private CTexture _AddTexture(CTexture texture, int w, byte[] data)
private CTexture _AddTexture(CTexture texture, byte[] data)
{
Texture t = _CreateTexture(texture.W2, texture.H2, w, data);
Texture t = _CreateTexture(texture, data);
lock (_MutexTexture)
lock (_D3DTextures)
{
texture.ID = _IDs.Dequeue();
_D3DTextures.Add(texture.ID, t);
}
return texture;
}
private Texture _CreateTexture(int textureW, int textureH, int w, byte[] data)
private 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
var t = new Texture(_Device, textureW, textureH, 0, Usage.AutoGenerateMipMap, Format.A8R8G8B8, Pool.Managed);
_WriteDataToTexture(t, w, data);
var t = new Texture(_Device, texture.W2, texture.H2, 0, Usage.AutoGenerateMipMap, Format.A8R8G8B8, Pool.Managed);
_WriteDataToTexture(t, texture.DataSize.Width, data);
return t;
}
@@ -946,22 +935,15 @@ namespace Vocaluxe.Lib.Draw
public CTexture EnqueueTexture(int w, int h, byte[] data)
{
CTexture texture = _GetNewTexture(w, h);
CTexture texture = CDrawHelper.GetNewTexture(w, h);
lock (_MutexTexture)
lock (_D3DTextures)
{
texture.ID = _IDs.Dequeue();
_D3DTextures.Add(texture.ID, null);
var queue = new STextureQueue(texture.ID, texture.W2, texture.H2, w, h, data);
_TexturesToLoad.Enqueue(queue);
_TexturesToLoad.Enqueue(new STextureQueue(texture, data));
}
return texture;
}
private CTexture _GetNewTexture(int w, int h)
{
return new CTexture(w, h, _CheckForNextPowerOf2(w), _CheckForNextPowerOf2(h));
}
#endregion adding
#region updating
@@ -975,10 +957,17 @@ namespace Vocaluxe.Lib.Draw
/// <returns>True if succeeded</returns>
public bool UpdateTexture(CTexture texture, int w, int h, byte[] data)
{
//Check if texture exists and extend matches
if (!_TextureExists(texture) || texture.UsedWidth != w || texture.UsedHeight != h)
if (!_TextureExists(texture))
return false;
lock (_MutexTexture)
if (texture.DataSize.Width != w || texture.DataSize.Height != h)
{
if (texture.W2 > w || texture.H2 > h)
return false; // Texture memory to small
if (texture.W2 * 0.9 < w || texture.H2 * 0.9 < h)
return false; // Texture memory to big
texture.DataSize = new Size(w, h);
}
lock (_D3DTextures)
{
_WriteDataToTexture(_D3DTextures[texture.ID], w, data);
}
@@ -1003,7 +992,7 @@ namespace Vocaluxe.Lib.Draw
/// <returns>True if the texture exists</returns>
private bool _TextureExists(CTexture texture)
{
lock (_MutexTexture)
lock (_D3DTextures)
{
return texture != null && _D3DTextures.ContainsKey(texture.ID);
}
@@ -1015,15 +1004,16 @@ namespace Vocaluxe.Lib.Draw
/// <param name="texture">The texture to be removed</param>
public void RemoveTexture(ref CTexture texture)
{
if (_TextureExists(texture))
{
lock (_MutexTexture)
if(texture==null) return;
lock (_D3DTextures)
{
_D3DTextures[texture.ID].Dispose();
_D3DTextures.Remove(texture.ID);
_IDs.Enqueue(texture.ID);
Texture t;
if (_D3DTextures.TryGetValue(texture.ID, out t))
{
if(t!=null) t.Dispose();
_D3DTextures.Remove(texture.ID);
}
}
}
texture = null;
}
@@ -1282,17 +1272,16 @@ namespace Vocaluxe.Lib.Draw
private void _CheckQueue()
{
lock (_MutexTexture)
lock (_D3DTextures)
{
while (_TexturesToLoad.Count > 0)
{
STextureQueue q = _TexturesToLoad.Dequeue();
Texture t;
if (_D3DTextures.TryGetValue(q.ID, out t) && t != null)
if (!_D3DTextures.ContainsKey(q.Texture.ID))
continue;
t = _CreateTexture(q.TextureWidth, q.TextureHeight, q.DataWidth, q.Data);
_D3DTextures[q.ID] = t;
Texture t = _CreateTexture(q.Texture, q.Data);
_D3DTextures[q.Texture.ID] = t;
}
}
}
@@ -1310,20 +1299,6 @@ namespace Vocaluxe.Lib.Draw
#endregion implementation
#region utility
/// <summary>
/// Calculates the next power of two if the device has the POW2 flag set
/// </summary>
/// <param name="n">The value of which the next power of two will be calculated</param>
/// <returns>The next power of two</returns>
private int _CheckForNextPowerOf2(int n)
{
if (_NonPowerOf2TextureSupported)
return n;
if (n < 0)
throw new ArgumentOutOfRangeException("n", "Must be positive.");
return (int)Math.Pow(2, Math.Ceiling(Math.Log(n, 2)));
}
private SlimDX.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));
+43
View File
@@ -0,0 +1,43 @@
using System;
using System.Diagnostics;
using System.Drawing;
using VocaluxeLib.Draw;
namespace Vocaluxe.Lib.Draw
{
static class CDrawHelper
{
public static bool NonPowerOf2TextureSupported;
private static readonly Object _MutexID = new object();
private static int _NextID;
/// <summary>
/// Calculates the next power of two if the device has the POW2 flag set
/// </summary>
/// <param name="n">The value of which the next power of two will be calculated</param>
/// <returns>The next power of two</returns>
private static int _CheckForNextPowerOf2(int n)
{
if (NonPowerOf2TextureSupported)
return n;
if (n < 0)
throw new ArgumentOutOfRangeException("n", "Must be positive.");
return (int)Math.Pow(2, Math.Ceiling(Math.Log(n, 2)));
}
public static CTexture GetNewTexture(int origWidth, int origHeight, int dataWidth = 0, int dataHeight = 0)
{
Debug.Assert(origWidth > 0 && origHeight > 0);
Debug.Assert(dataWidth > 0 || dataHeight <= 0);
int id;
lock (_MutexID)
{
id = _NextID++;
}
Size origSize = new Size(origWidth, origHeight);
Size dataSize = (dataHeight > 0) ? new Size(dataWidth, dataHeight) : origSize;
return new CTexture(id, origSize, dataSize, _CheckForNextPowerOf2(dataSize.Width), _CheckForNextPowerOf2(dataSize.Height));
}
}
}
+1 -1
View File
@@ -332,7 +332,7 @@ namespace Vocaluxe.Lib.Draw
private CTexture _GetNewTexture(int w, int h)
{
return new CTexture(w, h) {ID = _Bitmaps.Count - 1};
return new CTexture(_Bitmaps.Count - 1, new Size(w, h), new Size(w, h));
}
public CTexture AddTexture(string texturePath)
+37 -58
View File
@@ -63,20 +63,12 @@ namespace Vocaluxe.Lib.Draw
struct STextureQueue
{
public readonly int ID;
public readonly int TextureWidth;
public readonly int TextureHeight;
public readonly int DataWidth;
public readonly int DataHeight;
public readonly CTexture Texture;
public readonly byte[] Data;
public STextureQueue(int id, int textureWidth, int textureHeight, int dataWidth, int dataHeight, byte[] data)
public STextureQueue(CTexture texture, byte[] data)
{
ID = id;
TextureWidth = textureWidth;
TextureHeight = textureHeight;
DataWidth = dataWidth;
DataHeight = dataHeight;
Texture = texture;
Data = data;
}
}
@@ -84,8 +76,6 @@ namespace Vocaluxe.Lib.Draw
class COpenGL : Form, IDraw
{
#region private vars
private const int _MaxID = 100000;
private readonly CKeys _Keys;
private readonly CMouse _Mouse;
private bool _Run;
@@ -96,11 +86,8 @@ namespace Vocaluxe.Lib.Draw
private bool _Fullscreen;
private readonly Dictionary<int, CTexture> _Textures = new Dictionary<int, CTexture>();
private readonly Queue<int> _IDs = new Queue<int>(_MaxID);
private readonly Queue<STextureQueue> _TexturesToLoad = new Queue<STextureQueue>();
private readonly Object _MutexTexture = new Object();
private int _H = 1;
private int _W = 1;
private int _Y;
@@ -113,9 +100,6 @@ namespace Vocaluxe.Lib.Draw
{
Icon = new Icon(Path.Combine(CSettings.ProgramFolder, CSettings.FileNameIcon));
for (int i = 1; i < _MaxID; i++)
_IDs.Enqueue(i);
//Check AA Mode
CConfig.AAMode = (EAntiAliasingModes)_CheckAntiAliasingMode((int)CConfig.AAMode);
@@ -161,6 +145,8 @@ namespace Vocaluxe.Lib.Draw
ClientSize = new Size(CConfig.ScreenW, CConfig.ScreenH);
CenterToScreen();
CDrawHelper.NonPowerOf2TextureSupported = false;
}
#region Helpers
@@ -490,7 +476,7 @@ namespace Vocaluxe.Lib.Draw
public CTexture CopyScreen()
{
CTexture texture = _GetNewTexture(_W, _H);
CTexture texture = CDrawHelper.GetNewTexture(_W, _H);
texture.Name = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
@@ -504,10 +490,8 @@ namespace Vocaluxe.Lib.Draw
GL.BindTexture(TextureTarget.Texture2D, 0);
// Add to Texture List
lock (_MutexTexture)
lock (_Textures)
{
texture.ID = _IDs.Dequeue();
_Textures[texture.ID] = texture;
}
@@ -517,7 +501,7 @@ namespace Vocaluxe.Lib.Draw
public void CopyScreen(ref CTexture texture)
{
//Check for actual texture sizes as it may be downsized compared to OrigSize
if (!_TextureExists(texture) || texture.UsedWidth != GetScreenWidth() || texture.UsedHeight != GetScreenHeight())
if (!_TextureExists(texture) || texture.DataSize.Width != GetScreenWidth() || texture.DataSize.Height != GetScreenHeight())
{
RemoveTexture(ref texture);
texture = CopyScreen();
@@ -691,10 +675,9 @@ namespace Vocaluxe.Lib.Draw
int w = Math.Min(bmp.Width, maxSize);
int h = Math.Min(bmp.Height, maxSize);
w = MathHelper.NextPowerOfTwo(w);
h = MathHelper.NextPowerOfTwo(h);
var texture = new CTexture(bmp.Width, bmp.Height, w, h, true) {Name = GL.GenTexture()};
CTexture texture = CDrawHelper.GetNewTexture(w, h);
texture.Name = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
Bitmap bmp2 = null;
@@ -736,9 +719,8 @@ namespace Vocaluxe.Lib.Draw
// Add to Texture List
texture.TexturePath = String.Empty;
lock (_MutexTexture)
lock (_Textures)
{
texture.ID = _IDs.Dequeue();
_Textures[texture.ID] = texture;
}
@@ -747,20 +729,19 @@ namespace Vocaluxe.Lib.Draw
public CTexture AddTexture(int w, int h, byte[] data)
{
CTexture texture = _GetNewTexture(w, h);
CTexture texture = CDrawHelper.GetNewTexture(w, h);
_CreateTexture(texture, w, h, data);
_CreateTexture(texture, data);
lock (_MutexTexture)
lock (_Textures)
{
texture.ID = _IDs.Dequeue();
_Textures[texture.ID] = texture;
}
return texture;
}
private void _CreateTexture(CTexture texture, int w, int h, byte[] data)
private void _CreateTexture(CTexture texture, byte[] data)
{
if (_UsePBO)
{
@@ -782,7 +763,7 @@ namespace Vocaluxe.Lib.Draw
GL.BindTexture(TextureTarget.Texture2D, texture.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, w, h, PixelFormat.Bgra, PixelType.UnsignedByte, data);
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, texture.OrigSize.Width, texture.OrigSize.Height, PixelFormat.Bgra, PixelType.UnsignedByte, data);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
@@ -795,31 +776,32 @@ namespace Vocaluxe.Lib.Draw
public CTexture EnqueueTexture(int w, int h, byte[] data)
{
CTexture texture = _GetNewTexture(w, h);
CTexture texture = CDrawHelper.GetNewTexture(w, h);
lock (_MutexTexture)
lock (_Textures)
{
texture.ID = _IDs.Dequeue();
var queue = new STextureQueue(texture.ID, texture.W2, texture.H2, w, h, data);
var queue = new STextureQueue(texture, data);
_TexturesToLoad.Enqueue(queue);
_Textures[texture.ID] = texture;
}
return texture;
}
private static CTexture _GetNewTexture(int w, int h)
{
return new CTexture(w, h, MathHelper.NextPowerOfTwo(w), MathHelper.NextPowerOfTwo(h));
}
#endregion adding
#region updating
public bool UpdateTexture(CTexture texture, int w, int h, byte[] data)
{
//Check if texture exists and extend matches
if (!_TextureExists(texture) || texture.UsedWidth != w || texture.UsedHeight != h)
if (!_TextureExists(texture))
return false;
if (texture.DataSize.Width != w || texture.DataSize.Height != h)
{
if (texture.W2 > w || texture.H2 > h)
return false; // Texture memory to small
if (texture.W2 * 0.9 < w || texture.H2 * 0.9 < h)
return false; // Texture memory to big
texture.DataSize = new Size(w, h);
}
if (_UsePBO)
{
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, texture.PBO);
@@ -865,27 +847,25 @@ namespace Vocaluxe.Lib.Draw
public void RemoveTexture(ref CTexture texture)
{
if (_TextureExists(texture, false))
lock (_Textures)
{
lock (_MutexTexture)
if (_TextureExists(texture))
{
_IDs.Enqueue(texture.ID);
GL.DeleteTexture(texture.Name);
if (texture.PBO > 0)
GL.DeleteBuffers(1, ref texture.PBO);
_Textures.Remove(texture.ID);
}
_Textures.Remove(texture.ID);
}
texture = null;
}
private bool _TextureExists(CTexture texture, bool checkIfLoaded = true)
private bool _TextureExists(CTexture texture)
{
lock (_MutexTexture)
lock (_Textures)
{
if (texture != null && _Textures.ContainsKey(texture.ID))
if (texture != null && _Textures.ContainsKey(texture.ID) && texture.Name>0)
{
if (!checkIfLoaded || _Textures[texture.ID].Name > 0)
return true;
}
}
@@ -1154,16 +1134,15 @@ namespace Vocaluxe.Lib.Draw
private void _CheckQueue()
{
lock (_MutexTexture)
lock (_Textures)
{
while (_TexturesToLoad.Count > 0)
{
STextureQueue q = _TexturesToLoad.Dequeue();
CTexture texture;
if (!_Textures.TryGetValue(q.ID, out texture))
if (!_Textures.ContainsKey(q.Texture.ID))
continue;
_CreateTexture(texture, q.DataWidth, q.DataHeight, q.Data);
_CreateTexture(q.Texture, q.Data);
}
}
}
+1
View File
@@ -224,6 +224,7 @@
<Compile Include="Lib\Database\CDatabaseBase.cs" />
<Compile Include="Lib\Database\CHighscoreDB.cs" />
<Compile Include="Lib\Database\CResourceDB.cs" />
<Compile Include="Lib\Draw\CDrawHelper.cs" />
<Compile Include="Lib\Sound\Playback\CAudioStreamBase.cs" />
<Compile Include="Lib\Sound\Playback\CPlaybackBase.cs" />
<Compile Include="Lib\Sound\Playback\CRingBuffer.cs" />