From c9c907e3f0e9a7a6c166d57585902880bcbca4f8 Mon Sep 17 00:00:00 2001 From: Flamefire Date: Mon, 22 Sep 2014 15:08:45 +0200 Subject: [PATCH] Add more queue and update functions Add CopyTexture function Document CDraw --- Vocaluxe/Base/CDraw.cs | 360 ++++++++++---- Vocaluxe/Base/CGraphics.cs | 2 +- Vocaluxe/Base/CMain.cs | 4 +- Vocaluxe/Lib/Draw/CDirect3D.cs | 22 +- Vocaluxe/Lib/Draw/CDrawBase.cs | 445 ++++++++++-------- Vocaluxe/Lib/Draw/CDrawWinForm.cs | 38 +- Vocaluxe/Lib/Draw/COpenGL.cs | 73 +-- Vocaluxe/Lib/Draw/IDraw.cs | 13 +- Vocaluxe/Screens/CPopupScreenPlayerControl.cs | 2 +- Vocaluxe/Screens/CScreenCredits.cs | 2 +- VocaluxeLib/CHelper.cs | 22 +- VocaluxeLib/Draw/CTextureRef.cs | 30 +- 12 files changed, 652 insertions(+), 361 deletions(-) diff --git a/Vocaluxe/Base/CDraw.cs b/Vocaluxe/Base/CDraw.cs index 5c5b97cc..9152a043 100644 --- a/Vocaluxe/Base/CDraw.cs +++ b/Vocaluxe/Base/CDraw.cs @@ -20,7 +20,6 @@ using System.Drawing; using Vocaluxe.Lib.Draw; using VocaluxeLib; using VocaluxeLib.Draw; -using VocaluxeLib.Menu; namespace Vocaluxe.Base { @@ -28,6 +27,10 @@ namespace Vocaluxe.Base { private static IDraw _Draw; + /// + /// Initializes the Driver selected in the config + /// + /// public static bool Init() { if (_Draw != null) @@ -74,12 +77,20 @@ namespace Vocaluxe.Base return _Draw.Init(); } + /// + /// Has to be called to start rendering
+ /// Will only return if program is closed
+ /// Also inits the first screen + ///
public static void MainLoop() { CGraphics.InitFirstScreen(); _Draw.MainLoop(); } + /// + /// Unloads the current driver, e.g. to switch to another one + /// public static void Unload() { if (_Draw != null) @@ -89,87 +100,158 @@ namespace Vocaluxe.Base } } + /// + /// Gets the width of the rendering area + /// + /// public static int GetScreenWidth() { return _Draw.GetScreenWidth(); } + /// + /// Gets the height of the rendering area + /// + /// public static int GetScreenHeight() { return _Draw.GetScreenHeight(); } - public static void DrawLine(int a, int r, int g, int b, int w, int x1, int y1, int x2, int y2) - { - _Draw.DrawLine(a, r, g, b, w, x1, y1, x2, y2); - } - - public static void DrawRect(SColorF color, SRectF rect, float thickness) - { - if (thickness <= 0f) - return; - - _Draw.DrawColor(color, new SRectF(rect.X - thickness / 2, rect.Y - thickness / 2, rect.W + thickness, thickness, rect.Z)); - _Draw.DrawColor(color, new SRectF(rect.X - thickness / 2, rect.Y + rect.H - thickness / 2, rect.W + thickness, thickness, rect.Z)); - _Draw.DrawColor(color, new SRectF(rect.X - thickness / 2, rect.Y - thickness / 2, thickness, rect.H + thickness, rect.Z)); - _Draw.DrawColor(color, new SRectF(rect.X + rect.W - thickness / 2, rect.Y - thickness / 2, thickness, rect.H + thickness, rect.Z)); - } - - public static void DrawColor(SColorF color, SRectF rect) - { - _Draw.DrawColor(color, rect); - } - - public static void DrawColorReflection(SColorF color, SRectF rect, float space, float height) - { - _Draw.DrawColorReflection(color, rect, space, height); - } - - public static void ClearScreen() - { - _Draw.ClearScreen(); - } - - public static CTextureRef CopyScreen() - { - return _Draw.CopyScreen(); - } - - public static void CopyScreen(ref CTextureRef texture) - { - _Draw.CopyScreen(ref texture); - } - + /// + /// Takes a screenshot and saves it to the Screenshot folder + /// public static void MakeScreenShot() { _Draw.MakeScreenShot(); } + /// + /// Gets the current screen content as a texture + /// + /// + public static CTextureRef CopyScreen() + { + return _Draw.CopyScreen(); + } + + /// + /// Gets the current screen content updating the given texture + /// + /// + public static void CopyScreen(ref CTextureRef texture) + { + _Draw.CopyScreen(ref texture); + } + + /// + /// Adds a texture from a Bitmap and returns a reference to it
+ /// Must be called from main thread! + ///
+ /// + /// Reference to texture public static CTextureRef AddTexture(Bitmap bitmap) { return _Draw.AddTexture(bitmap); } + /// + /// Adds a texture from an image file given by its file path
+ /// Must be called from main thread! + ///
+ /// + /// Reference to texture or null on error public static CTextureRef AddTexture(string texturePath) { return _Draw.AddTexture(texturePath); } + /// + /// Adds a texture from a byte array
+ /// Must be called from main thread! + ///
+ /// Width of the image + /// Height of the image + /// Array of 4 byte values for each pixel + /// Reference to texture public static CTextureRef AddTexture(int w, int h, byte[] data) { return _Draw.AddTexture(w, h, data); } + /// + /// Requests aadding a texture from a byte array
+ /// Use this if you add textures from another thread or don't need it immediatelly + ///
+ /// Width of the image + /// Height of the image + /// Array of 4 byte values for each pixel + /// Reference to texture public static CTextureRef EnqueueTexture(int w, int h, byte[] data) { return _Draw.EnqueueTexture(w, h, data); } - public static void UpdateTexture(CTextureRef texture, int w, int h, byte[] data) + /// + /// Requests adding a texture from a bitmap
+ /// Use this if you add textures from another thread or don't need it immediatelly + ///
+ /// + /// Reference to texture + public static CTextureRef EnqueueTexture(Bitmap bmp) { - _Draw.UpdateTexture(texture, w, h, data); + return _Draw.EnqueueTexture(bmp); } + /// + /// Requests updating a texture from a bitmap
+ /// Use this if you add textures from another thread or don't need it immediatelly + ///
+ /// Reference to the texture to update + /// + public static void EnqueueTextureUpdate(CTextureRef textureRef, Bitmap bmp) + { + _Draw.EnqueueTextureUpdate(textureRef, bmp); + } + + /// + /// Creates a copy of the texture
+ /// Updates to the copy do not affect the original texture + ///
+ /// Original texture reference + /// New texture reference of the copy + public static CTextureRef CopyTexture(CTextureRef textureRef) + { + return _Draw.CopyTexture(textureRef); + } + + /// + /// Updates a texture, filling it with the new data + /// + /// + /// Width of the image + /// Height of the image + /// Array of 4 byte values for each pixel + public static void UpdateTexture(CTextureRef textureRef, int w, int h, byte[] data) + { + _Draw.UpdateTexture(textureRef, w, h, data); + } + + /// + /// Updates a texture, filling it with the new data from the bitmap + /// + /// + /// + public static void UpdateTexture(CTextureRef textureRef, Bitmap bmp) + { + _Draw.UpdateTexture(textureRef, bmp); + } + + /// + /// Removes a texture from the VRAM and sets it to null to avoid accidential usage
+ /// Note: You can also use its Dispose method to do the same as this gets automaticly called from the Dispose method and destructor of a texture reference + ///
+ /// public static void RemoveTexture(ref CTextureRef texture) { // Disposed textures call this, possibly at program end! @@ -177,52 +259,156 @@ namespace Vocaluxe.Base _Draw.RemoveTexture(ref texture); } - public static void DrawTexture(CTextureRef texture) - { - _Draw.DrawTexture(texture); - } - - public static void DrawTexture(CTextureRef texture, SRectF rect) - { - _Draw.DrawTexture(texture, rect); - } - - public static void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, bool mirrored = false) - { - _Draw.DrawTexture(texture, rect, color, mirrored); - } - - public static void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false) - { - _Draw.DrawTexture(texture, rect, color, bounds, mirrored); - } - - public static void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, float begin, float end) - { - _Draw.DrawTexture(texture, rect, color, begin, end); - } - - public static void DrawTexture(CStatic staticBounds, CTextureRef texture, EAspect aspect) - { - if (texture == null) - return; - - var bounds = new RectangleF(staticBounds.Rect.X, staticBounds.Rect.Y, staticBounds.Rect.W, staticBounds.Rect.H); - RectangleF rect; - - CHelper.SetRect(bounds, out rect, texture.OrigAspect, aspect); - DrawTexture(texture, new SRectF(rect.X, rect.Y, rect.Width, rect.Height, staticBounds.Rect.Z), - texture.Color, new SRectF(bounds.X, bounds.Y, bounds.Width, bounds.Height, 0f)); - } - - public static void DrawTextureReflection(CTextureRef texture, SRectF rect, SColorF color, SRectF bounds, float space, float height) - { - _Draw.DrawTextureReflection(texture, rect, color, bounds, space, height); - } - + /// + /// Returns the number of textures in the VRAM (textures might get reused so this might not be the actual number of textures in use) + /// + /// public static int TextureCount() { return _Draw.GetTextureCount(); } + + /// + /// Draws a simple line + /// + /// + /// Width of the line + /// + /// + /// + /// + public static void DrawLine(SColorF color, float w, int x1, int y1, int x2, int y2) + { + _Draw.DrawLine(color, w, x1, y1, x2, y2); + } + + /// + /// Draws the outline of a rectangle + /// + /// + /// + /// Width of the lines + public static void DrawRectOutline(SColorF color, SRectF rect, float thickness) + { + if (thickness <= 0f) + return; + int x1 = (int)rect.X; + int x2 = (int)(rect.X + rect.W); + int y1 = (int)rect.Y; + int y2 = (int)(rect.Y + rect.H); + _Draw.DrawLine(color, thickness, x1, y1, x2, y1); + _Draw.DrawLine(color, thickness, x2, y1, x2, y2); + _Draw.DrawLine(color, thickness, x2, y2, x1, y2); + _Draw.DrawLine(color, thickness, x1, y2, x1, y1); + } + + /// + /// Draws a simple (filled) rectangle with the given color + /// + /// + /// + public static void DrawRect(SColorF color, SRectF rect) + { + _Draw.DrawRect(color, rect); + } + + /// + /// Draws the reflection of a filled rectangle with the given color + /// + /// + /// (Original) rectangle to draw the reflection for + /// Spacing between the rect and the reflection + /// Height of the reflection + public static void DrawRectReflection(SColorF color, SRectF rect, float space, float height) + { + _Draw.DrawRectReflection(color, rect, space, height); + } + + /// + /// Draws a texture at its position and with its color + /// + /// The texture to be drawn + public static void DrawTexture(CTextureRef texture) + { + DrawTexture(texture, texture.Rect); + } + + /// + /// Draws a texture with its color at the given position + /// + /// The texture to be drawn + /// A rectangle with the destination coordinates + public static void DrawTexture(CTextureRef textureRef, SRectF rect) + { + DrawTexture(textureRef, rect, textureRef.Color); + } + + /// + /// Draws a texture at the given position with the given color + /// + /// + /// + /// + /// True to mirror the texture on the y axis + public static void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, bool mirrored = false) + { + _Draw.DrawTexture(textureRef, rect, color, mirrored); + } + + /// + /// Draws a texture at the given position with the given color + /// + /// + /// + /// + /// Bounds to draw the texture in (rest gets cropped off) + /// True to mirror the texture on the y axis + public static void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false) + { + _Draw.DrawTexture(textureRef, rect, color, bounds, mirrored); + } + + /// + /// Draws a part of a texture at the given position with the given color + /// + /// + /// + /// + /// Normalized start x-coordinate (0..1) + /// Normalized end x-coordinate (0..1) + public static void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, float begin, float end) + { + _Draw.DrawTexture(textureRef, rect, color, begin, end); + } + + /// + /// Draws a texture fitting it within the given bounds with the method specified by aspect + /// + /// + /// Where to draw the texture + /// How to fit a texture in the bounds if the size differs + public static void DrawTexture(CTextureRef textureRef, SRectF bounds, EAspect aspect) + { + if (textureRef == null) + return; + + SRectF rect; + CHelper.SetRect(bounds, out rect, textureRef.OrigAspect, aspect); + DrawTexture(textureRef, rect); + } + + /// + /// Draws the reflection of a texture at the given position and with the given color + /// + /// + /// (Original) rectangle to draw the reflection for + /// + /// + /// Spacing between the rect and the reflection + /// Height of the reflection + public static void DrawTextureReflection(CTextureRef textureRef, SRectF rect, SColorF color, SRectF bounds, float space, float height) + { + _Draw.DrawTextureReflection(textureRef, rect, color, bounds, space, height); + } } } \ No newline at end of file diff --git a/Vocaluxe/Base/CGraphics.cs b/Vocaluxe/Base/CGraphics.cs index cc4e3f92..0cff2b23 100644 --- a/Vocaluxe/Base/CGraphics.cs +++ b/Vocaluxe/Base/CGraphics.cs @@ -660,7 +660,7 @@ namespace Vocaluxe.Base foreach (string txt in debugOutput) { RectangleF rect = new RectangleF(CSettings.RenderW - CFonts.GetTextWidth(txt), y, CFonts.GetTextWidth(txt), CFonts.GetTextHeight(txt)); - CDraw.DrawColor(gray, new SRectF(rect.X, rect.Top, rect.Width, rect.Height, CSettings.ZNear)); + CDraw.DrawRect(gray, new SRectF(rect.X, rect.Top, rect.Width, rect.Height, CSettings.ZNear)); CFonts.DrawText(txt, rect.X, rect.Y, CSettings.ZNear); y += rect.Height; } diff --git a/Vocaluxe/Base/CMain.cs b/Vocaluxe/Base/CMain.cs index 96ed43d0..e68ecf53 100644 --- a/Vocaluxe/Base/CMain.cs +++ b/Vocaluxe/Base/CMain.cs @@ -440,12 +440,12 @@ namespace Vocaluxe.Base public void DrawColor(SColorF color, SRectF rect) { - CDraw.DrawColor(color, rect); + CDraw.DrawRect(color, rect); } public void DrawColorReflection(SColorF color, SRectF rect, float space, float height) { - CDraw.DrawColorReflection(color, rect, space, height); + CDraw.DrawRectReflection(color, rect, space, height); } } diff --git a/Vocaluxe/Lib/Draw/CDirect3D.cs b/Vocaluxe/Lib/Draw/CDirect3D.cs index 55823166..06918b96 100644 --- a/Vocaluxe/Lib/Draw/CDirect3D.cs +++ b/Vocaluxe/Lib/Draw/CDirect3D.cs @@ -530,23 +530,21 @@ namespace Vocaluxe.Lib.Draw /// /// Draws a line /// - /// The alpha value from 0-255 - /// The red value from 0-255 - /// The red value from 0-255 - /// The red value from 0-255 + /// /// The width of the line /// The start x-value /// The start y-value /// The end x-value /// The end y-value - public void DrawLine(int a, int r, int g, int b, int w, int x1, int y1, int x2, int y2) + public void DrawLine(SColorF color, float w, int x1, int y1, int x2, int y2) { var lineVector = new Vector2[] {new Vector2(x1, y1), new Vector2(x2, y2)}; using (var line = new Line(_Device)) { line.Antialias = true; + line.Width = w; line.Begin(); - line.Draw(lineVector, new Color4((float)a / 255, (float)r / 255, (float)g / 255, (float)b / 255)); + line.Draw(lineVector, new Color4(color.AsColor())); line.End(); } } @@ -556,7 +554,7 @@ namespace Vocaluxe.Lib.Draw /// /// The color in which the rectangle will be drawn in /// The coordinates in a SRectF struct - public void DrawColor(SColorF color, SRectF rect) + public void DrawRect(SColorF color, SRectF rect) { DrawTexture(_BlankTexture, rect, color); } @@ -568,7 +566,7 @@ namespace Vocaluxe.Lib.Draw /// The coordinates in a SRectF struct /// The space between the texture and the reflection /// The height of the reflection - public void DrawColorReflection(SColorF color, SRectF rect, float space, float height) + public void DrawRectReflection(SColorF color, SRectF rect, float space, float height) { DrawTextureReflection(_BlankTexture, rect, color, rect, space, height); } @@ -609,7 +607,7 @@ namespace Vocaluxe.Lib.Draw /// A SRectF struct containing the destination coordinates /// A SColorF struct containing a color which the texture will be colored in /// True if the texture should be mirrored - public override void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, bool mirrored = false) + public void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, bool mirrored = false) { if (rect.W < 1 || rect.H < 1) return; @@ -619,9 +617,9 @@ namespace Vocaluxe.Lib.Draw return; //Calculate the position - float x1 = 0; + const float x1 = 0; float x2 = texture.WidthRatio; - float y1 = 0; + const float y1 = 0; float y2 = texture.HeightRatio; //Calculate the size @@ -636,7 +634,7 @@ namespace Vocaluxe.Lib.Draw if (mirrored) { - y1 = -y1; + //y1 = -y1; y2 = -y2; } var vert = new STexturedColoredVertex[4]; diff --git a/Vocaluxe/Lib/Draw/CDrawBase.cs b/Vocaluxe/Lib/Draw/CDrawBase.cs index 28b7f44c..8dc9bbdb 100644 --- a/Vocaluxe/Lib/Draw/CDrawBase.cs +++ b/Vocaluxe/Lib/Draw/CDrawBase.cs @@ -15,17 +15,38 @@ namespace Vocaluxe.Lib.Draw { abstract class CDrawBase where TTextureType : CTextureBase, IDisposable { + private enum EQueueAction + { + Add, + Update + } + private struct STextureQueue { - public readonly int TextureID; + public readonly WeakReference TextureRef; public readonly Size DataSize; + //Use either Data or DataBmp! public readonly byte[] Data; + //This is disposed after use + public readonly Bitmap DataBmp; + public readonly EQueueAction Action; - public STextureQueue(int textureID, Size dataSize, byte[] data) + public STextureQueue(CTextureRef textureRef, EQueueAction action, Size dataSize, byte[] data) { - TextureID = textureID; + TextureRef = new WeakReference(textureRef); + Action = action; DataSize = dataSize; Data = data; + DataBmp = null; + } + + public STextureQueue(CTextureRef textureRef, EQueueAction action, Bitmap bmp) + { + TextureRef = new WeakReference(textureRef); + Action = action; + DataSize = new Size(bmp.Width, bmp.Height); + Data = null; + DataBmp = bmp; } } @@ -151,6 +172,8 @@ namespace Vocaluxe.Lib.Draw } #region Textures + + #region private/protected protected abstract void _WriteDataToTexture(TTextureType texture, byte[] data); protected virtual void _WriteDataToTexture(TTextureType texture, IntPtr data) @@ -181,17 +204,75 @@ namespace Vocaluxe.Lib.Draw } /// - /// 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) + /// Writes the specified bitmap to the texture, creating it if null
+ /// Also does the resizing if required ///
- /// - /// - /// - private TTextureType _CreateAndFillTexture(Size dataSize, IntPtr data) + /// + /// + private void _WriteBitmapToTexture(ref TTextureType texture, Bitmap bmp) { - TTextureType texture = _CreateTexture(dataSize); - _WriteDataToTexture(texture, data); - return texture; + 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; + } + + // Make sure maxSize is a power of 2 if required + maxSize = _CheckForNextPowerOf2(maxSize); + + Bitmap bmp2 = null; + try + { + // Do not stretch the texture, only make it smaller + int w = Math.Min(bmp.Width, maxSize); + int h = Math.Min(bmp.Height, maxSize); + 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; + } + + //Fill the new Bitmap with the texture data + BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); + Size size = new Size(w, h); + if (texture == null) + texture = _CreateTexture(size); + else + texture.DataSize = size; + _WriteDataToTexture(texture, bmpData.Scan0); + bmp.UnlockBits(bmpData); + } + finally + { + if (bmp2 != null) + bmp2.Dispose(); + } } private void _AddToCache(TTextureType texture, Size origSize, string texturePath) @@ -223,6 +304,122 @@ namespace Vocaluxe.Lib.Draw return null; } + /// + /// Method used to add a texture to the texture list and return a TextureRef to it
+ /// Important: This should be the only function to ever write to _Textures + ///
+ /// + /// + /// + protected CTextureRef _GetTextureReference(Size origSize, TTextureType texture) + { + Debug.Assert(origSize.Width > 0 && origSize.Height > 0); + int id; + lock (_MutexID) + { + id = _NextID++; + } + CTextureRef textureRef = new CTextureRef(id, origSize); + if (texture != null) + texture.RefCount++; + if (texture == null || texture.RefCount == 1) + _TextureCount++; + lock (_Textures) + { + _Textures.Add(id, texture); + } + return textureRef; + } + + /// + /// Method used to add a texture to the texture list and return a TextureRef to it
+ /// Convenience method + ///
+ /// + /// + /// + /// + protected CTextureRef _GetTextureReference(int origWidth, int origHeight, TTextureType texture) + { + return _GetTextureReference(new Size(origWidth, origHeight), texture); + } + + private static bool _IsTextureUsable(TTextureType texture, int dataWidth, int dataHeight) + { + if (texture == null) + return false; + if (texture.DataSize.Width != dataWidth || texture.DataSize.Height != dataHeight) + { + if (texture.W2 > dataWidth || texture.H2 > dataHeight) + return false; // Texture memory to small + if (texture.W2 * 0.9 < dataWidth || texture.H2 * 0.9 < dataHeight) + return false; // Texture memory to big + } + return true; + } + + protected bool _GetTexture(CTextureRef textureRef, out TTextureType texture) + { + if (textureRef == null) + { + texture = null; + return false; + } + lock (_Textures) + { + return _Textures.TryGetValue(textureRef.ID, out texture) && texture != null; + } + } + + /// + /// Decreases the RefCount of a texture and disposes it if necessary + /// + /// + private void _DisposeTexture(TTextureType texture) + { + if (texture != null && --texture.RefCount <= 0) + { + if (texture.TexturePath != null) + _TextureCache.Remove(texture.TexturePath); + texture.Dispose(); + _TextureCount--; + } + } + + private void _CheckQueue() + { + lock (_Textures) + { + while (_TexturesToLoad.Count > 0) + { + STextureQueue q = _TexturesToLoad.Dequeue(); + Debug.Assert(q.Data != null ^ q.DataBmp != null); + CTextureRef textureRef = q.TextureRef.Target as CTextureRef; + if (!q.TextureRef.IsAlive || textureRef == null || !_Textures.ContainsKey(textureRef.ID)) + continue; + + if (q.Action == EQueueAction.Add) + { + TTextureType texture = null; + if (q.Data == null) + _WriteBitmapToTexture(ref texture, q.DataBmp); + else + texture = _CreateAndFillTexture(q.DataSize, q.Data); + texture.RefCount = 1; //Just created, so only 1 reference + _Textures[textureRef.ID] = texture; + } + else + { + if (q.Data == null) + UpdateTexture(textureRef, q.DataBmp); + else + UpdateTexture(textureRef, q.DataSize.Width, q.DataSize.Height, q.Data); + } + } + } + } + #endregion private/protected + /// /// Adds a texture and stores it in the VRam /// @@ -275,65 +472,11 @@ namespace Vocaluxe.Lib.Draw { 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; - } Size origSize = new Size(bmp.Width, bmp.Height); - Bitmap bmp2 = null; - TTextureType texture; - try - { - // Make sure maxSize is a power of 2 if required - maxSize = _CheckForNextPowerOf2(maxSize); - // Do not stretch the texture, only make it smaller - int w = Math.Min(bmp.Width, maxSize); - int h = Math.Min(bmp.Height, maxSize); - 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; - } - - //Fill the new Bitmap with the texture data - BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); - texture = _CreateAndFillTexture(new Size(w, h), bmpData.Scan0); - bmp.UnlockBits(bmpData); - } - finally - { - if (bmp2 != null) - bmp2.Dispose(); - } + TTextureType texture = null; + _WriteBitmapToTexture(ref texture, bmp); _AddToCache(texture, origSize, texturePath); return _GetTextureReference(origSize, texture); @@ -345,56 +488,34 @@ namespace Vocaluxe.Lib.Draw return _GetTextureReference(w, h, texture); } - /// - /// Method used to add a texture to the texture list and return a TextureRef to it
- /// Important: This should be the only function to ever write to _Textures - ///
- /// - /// - /// - protected CTextureRef _GetTextureReference(Size origSize, TTextureType texture) - { - Debug.Assert(origSize.Width > 0 && origSize.Height > 0); - int id; - lock (_MutexID) - { - id = _NextID++; - } - CTextureRef textureRef = new CTextureRef(id, origSize); - if (texture != null) - texture.RefCount++; - if (texture == null || texture.RefCount == 1) - _TextureCount++; - lock (_Textures) - { - _Textures.Add(id, texture); - } - return textureRef; - } - - /// - /// Method used to add a texture to the texture list and return a TextureRef to it
- /// Convenience method - ///
- /// - /// - /// - /// - protected CTextureRef _GetTextureReference(int origWidth, int origHeight, TTextureType texture) - { - return _GetTextureReference(new Size(origWidth, origHeight), texture); - } - public CTextureRef EnqueueTexture(int w, int h, byte[] data) { lock (_Textures) { CTextureRef textureRef = _GetTextureReference(w, h, null); - _TexturesToLoad.Enqueue(new STextureQueue(textureRef.ID, new Size(w, h), data)); + _TexturesToLoad.Enqueue(new STextureQueue(textureRef, EQueueAction.Add, new Size(w, h), data)); return textureRef; } } + public CTextureRef EnqueueTexture(Bitmap bmp) + { + lock (_Textures) + { + CTextureRef textureRef = _GetTextureReference(bmp.Width, bmp.Height, null); + _TexturesToLoad.Enqueue(new STextureQueue(textureRef, EQueueAction.Add, bmp)); + return textureRef; + } + } + + public void EnqueueTextureUpdate(CTextureRef textureRef, Bitmap bmp) + { + lock (_Textures) + { + _TexturesToLoad.Enqueue(new STextureQueue(textureRef, EQueueAction.Update, bmp)); + } + } + /// /// Updates the data of a texture /// @@ -406,57 +527,53 @@ namespace Vocaluxe.Lib.Draw public void UpdateTexture(CTextureRef textureRef, int w, int h, byte[] data) { TTextureType texture; - if (_GetTexture(textureRef, out texture)) + if (!_GetTexture(textureRef, out texture)) return; - bool reuseTexture = true; - if (texture.DataSize.Width != w || texture.DataSize.Height != h) + bool reuseTexture = _IsTextureUsable(texture, w, h); + if (reuseTexture) { - if (texture.W2 > w || texture.H2 > h) - reuseTexture = false; // Texture memory to small - else if (texture.W2 * 0.9 < w || texture.H2 * 0.9 < h) - reuseTexture = false; // Texture memory to big - else - texture.DataSize = new Size(w, h); + texture.DataSize = new Size(w, h); + _WriteDataToTexture(texture, data); } - if (!reuseTexture) + else { _DisposeTexture(texture); texture = _CreateAndFillTexture(new Size(w, h), data); + texture.RefCount = 1; lock (_Textures) { _Textures[textureRef.ID] = texture; } } + } + + public void UpdateTexture(CTextureRef textureRef, Bitmap bmp) + { + TTextureType texture; + if (!_GetTexture(textureRef, out texture)) + return; + bool reuseTexture = _IsTextureUsable(texture, bmp.Width, bmp.Height); + if (reuseTexture) + _WriteBitmapToTexture(ref texture, bmp); else - _WriteDataToTexture(texture, data); - } - - protected bool _GetTexture(CTextureRef textureRef, out TTextureType texture) - { - if (textureRef == null) { + _DisposeTexture(texture); texture = null; - return false; - } - lock (_Textures) - { - return _Textures.TryGetValue(textureRef.ID, out texture) && texture != null; + _WriteBitmapToTexture(ref texture, bmp); + texture.RefCount = 1; + lock (_Textures) + { + _Textures[textureRef.ID] = texture; + } } } - /// - /// Decreases the RefCount of a texture and disposes it if necessary - /// - /// - private void _DisposeTexture(TTextureType texture) + public CTextureRef CopyTexture(CTextureRef textureRef) { - if (texture != null && --texture.RefCount <= 0) - { - if (texture.TexturePath != null) - _TextureCache.Remove(texture.TexturePath); - texture.Dispose(); - _TextureCount--; - } + TTextureType texture; + if (!_GetTexture(textureRef, out texture)) + return null; + return _GetTextureReference(textureRef.OrigSize, texture); } /// @@ -475,57 +592,15 @@ namespace Vocaluxe.Lib.Draw _DisposeTexture(t); _Textures.Remove(textureRef.ID); } - textureRef.ID = -1; + textureRef.SetRemoved(); } textureRef = null; } - private void _CheckQueue() - { - lock (_Textures) - { - while (_TexturesToLoad.Count > 0) - { - STextureQueue q = _TexturesToLoad.Dequeue(); - if (!_Textures.ContainsKey(q.TextureID)) - continue; - - TTextureType texture = _CreateAndFillTexture(q.DataSize, q.Data); - texture.RefCount = 1; //Currently no more than 1 reference to queued textures is possible - _Textures[q.TextureID] = texture; - } - } - } - public int GetTextureCount() { return _TextureCount; } - - /// - /// Draws a texture - /// - /// The texture to be drawn - public void DrawTexture(CTextureRef texture) - { - if (texture == null) - return; - DrawTexture(texture, texture.Rect, texture.Color); - } - - /// - /// Draws a texture - /// - /// The texture to be drawn - /// A SRectF struct containing the destination coordinates - public void DrawTexture(CTextureRef texture, SRectF rect) - { - if (texture == null) - return; - DrawTexture(texture, rect, texture.Color); - } - - public abstract void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, bool mirrored = false); #endregion /// diff --git a/Vocaluxe/Lib/Draw/CDrawWinForm.cs b/Vocaluxe/Lib/Draw/CDrawWinForm.cs index 7e9260a2..81825158 100644 --- a/Vocaluxe/Lib/Draw/CDrawWinForm.cs +++ b/Vocaluxe/Lib/Draw/CDrawWinForm.cs @@ -307,14 +307,14 @@ namespace Vocaluxe.Lib.Draw _Backbuffer.Save(file, ImageFormat.Png); } - public void DrawLine(int a, int r, int g, int b, int w, int x1, int y1, int x2, int y2) + public void DrawLine(SColorF color, float w, int x1, int y1, int x2, int y2) { - _G.DrawLine(new Pen(Color.FromArgb(a, r, g, b), w), new Point(x1, y1), new Point(x2, y2)); + _G.DrawLine(new Pen(color.AsColor(), w), new Point(x1, y1), new Point(x2, y2)); } - public void DrawColor(SColorF color, SRectF rect) {} + public void DrawRect(SColorF color, SRectF rect) {} - public void DrawColorReflection(SColorF color, SRectF rect, float space, float height) {} + public void DrawRectReflection(SColorF color, SRectF rect, float space, float height) {} public CTextureRef AddTexture(Bitmap bmp) { @@ -356,12 +356,20 @@ namespace Vocaluxe.Lib.Draw return texture != null && _Textures.ContainsKey(texture.ID); } + public CTextureRef CopyTexture(CTextureRef textureRef) + { + if (_TextureExists(textureRef)) + return AddTexture(_Bitmaps[textureRef.ID]); + return null; + } + public void RemoveTexture(ref CTextureRef texture) { if (_TextureExists(texture)) { _Bitmaps[texture.ID].Dispose(); _Textures.Remove(texture.ID); + texture.SetRemoved(); } texture = null; } @@ -371,6 +379,16 @@ namespace Vocaluxe.Lib.Draw return AddTexture(w, h, data); } + public CTextureRef EnqueueTexture(Bitmap bmp) + { + return AddTexture(bmp); + } + + public void EnqueueTextureUpdate(CTextureRef textureRef, Bitmap bmp) + { + UpdateTexture(textureRef, bmp); + } + public CTextureRef AddTexture(int w, int h, byte[] data) { using (var bmp = new Bitmap(w, h)) @@ -393,16 +411,10 @@ namespace Vocaluxe.Lib.Draw } } - public void DrawTexture(CTextureRef texture) + public void UpdateTexture(CTextureRef textureRef, Bitmap bmp) { - if (texture != null) - DrawTexture(texture, texture.Rect, texture.Color); - } - - public void DrawTexture(CTextureRef texture, SRectF rect) - { - if (texture != null) - DrawTexture(texture, rect, texture.Color); + if (_TextureExists(textureRef)) + _Bitmaps[textureRef.ID] = bmp; } public void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, bool mirrored = false) diff --git a/Vocaluxe/Lib/Draw/COpenGL.cs b/Vocaluxe/Lib/Draw/COpenGL.cs index c89ce657..a6c2ff4e 100644 --- a/Vocaluxe/Lib/Draw/COpenGL.cs +++ b/Vocaluxe/Lib/Draw/COpenGL.cs @@ -253,9 +253,7 @@ namespace Vocaluxe.Lib.Draw { return _Control.Height; } - #endregion main stuff - #region Basic Draw Methods public override void ClearScreen() { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); @@ -268,6 +266,27 @@ namespace Vocaluxe.Lib.Draw GL.Ortho(-CConfig.BorderLeft, CConfig.BorderRight + CSettings.RenderW, CConfig.BorderBottom + CSettings.RenderH, -CConfig.BorderTop, CSettings.ZNear, CSettings.ZFar); } + public void MakeScreenShot() + { + string file = CHelper.GetUniqueFileName(Path.Combine(CSettings.DataFolder, CSettings.FolderNameScreenshots), "Screenshot.bmp"); + + int width = GetScreenWidth(); + int height = GetScreenHeight(); + + using (var screen = new Bitmap(width, height)) + { + BitmapData bmpData = screen.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + + GL.ReadPixels(0, 0, width, height, PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0); + screen.UnlockBits(bmpData); + + screen.RotateFlip(RotateFlipType.RotateNoneFlipY); + screen.Save(file, ImageFormat.Bmp); + } + } + #endregion main stuff + + #region Basic Draw Methods public CTextureRef CopyScreen() { //TODO: Check if _W,_H needs to be used or not @@ -298,30 +317,11 @@ namespace Vocaluxe.Lib.Draw } } - public void MakeScreenShot() - { - string file = CHelper.GetUniqueFileName(Path.Combine(CSettings.DataFolder, CSettings.FolderNameScreenshots), "Screenshot.bmp"); - - int width = GetScreenWidth(); - int height = GetScreenHeight(); - - using (var screen = new Bitmap(width, height)) - { - BitmapData bmpData = screen.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - - GL.ReadPixels(0, 0, width, height, PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0); - screen.UnlockBits(bmpData); - - screen.RotateFlip(RotateFlipType.RotateNoneFlipY); - screen.Save(file, ImageFormat.Bmp); - } - } - - public void DrawLine(int a, int r, int g, int b, int w, int x1, int y1, int x2, int y2) + public void DrawLine(SColorF color, float w, int x1, int y1, int x2, int y2) { GL.Enable(EnableCap.Blend); - GL.Color4(r, g, b, a * CGraphics.GlobalAlpha); - + GL.Color4(color.R, color.G, color.B, color.A * CGraphics.GlobalAlpha); + GL.LineWidth(w); GL.Begin(BeginMode.Lines); GL.Vertex3(x1, y1, CGraphics.ZOffset); GL.Vertex3(x2, y2, CGraphics.ZOffset); @@ -330,22 +330,30 @@ namespace Vocaluxe.Lib.Draw GL.Disable(EnableCap.Blend); } - public void DrawColor(SColorF color, SRectF rect) + public void DrawRect(SColorF color, SRectF rect) { GL.Enable(EnableCap.Blend); GL.Color4(color.R, color.G, color.B, color.A * CGraphics.GlobalAlpha); GL.Begin(BeginMode.Quads); + GL.MatrixMode(MatrixMode.Texture); + GL.PushMatrix(); + if (Math.Abs(rect.Rotation) > 0.001) + { + GL.Translate(0.5f, 0.5f, 0); + GL.Rotate(-rect.Rotation, 0f, 0f, 1f); + GL.Translate(-0.5f, -0.5f, 0); + } GL.Vertex3(rect.X, rect.Y, rect.Z + CGraphics.ZOffset); GL.Vertex3(rect.X, rect.Y + rect.H, rect.Z + CGraphics.ZOffset); GL.Vertex3(rect.X + rect.W, rect.Y + rect.H, rect.Z + CGraphics.ZOffset); GL.Vertex3(rect.X + rect.W, rect.Y, rect.Z + CGraphics.ZOffset); GL.End(); - + GL.PopMatrix(); GL.Disable(EnableCap.Blend); } - public void DrawColorReflection(SColorF color, SRectF rect, float space, float height) + public void DrawRectReflection(SColorF color, SRectF rect, float space, float height) { if (rect.H < height) height = rect.H; @@ -369,7 +377,8 @@ namespace Vocaluxe.Lib.Draw GL.Enable(EnableCap.Blend); - + GL.MatrixMode(MatrixMode.Texture); + GL.PushMatrix(); if (Math.Abs(rect.Rotation) > 0.001) { GL.Translate(0.5f, 0.5f, 0); @@ -392,7 +401,7 @@ namespace Vocaluxe.Lib.Draw GL.Vertex3(rx1, ry1, rect.Z + CGraphics.ZOffset); GL.End(); - + GL.PopMatrix(); GL.Disable(EnableCap.Blend); } #endregion Basic Draw Methods @@ -435,7 +444,7 @@ namespace Vocaluxe.Lib.Draw } #region drawing - public override void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, bool mirrored = false) + public void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, bool mirrored = false) { COGLTexture texture; if (!_GetTexture(textureRef, out texture)) @@ -446,9 +455,9 @@ namespace Vocaluxe.Lib.Draw GL.BindTexture(TextureTarget.Texture2D, texture.Name); - float x1 = 0; + const float x1 = 0; float x2 = texture.WidthRatio; - float y1 = 0; + const float y1 = 0; float y2 = texture.HeightRatio; float rx1 = rect.X; diff --git a/Vocaluxe/Lib/Draw/IDraw.cs b/Vocaluxe/Lib/Draw/IDraw.cs index 09a0aa0e..a20f873e 100644 --- a/Vocaluxe/Lib/Draw/IDraw.cs +++ b/Vocaluxe/Lib/Draw/IDraw.cs @@ -32,7 +32,6 @@ namespace Vocaluxe.Lib.Draw int GetTextureCount(); - void ClearScreen(); CTextureRef CopyScreen(); void CopyScreen(ref CTextureRef texture); void MakeScreenShot(); @@ -41,16 +40,18 @@ namespace Vocaluxe.Lib.Draw CTextureRef AddTexture(Bitmap bitmap); CTextureRef AddTexture(int w, int h, byte[] data); CTextureRef EnqueueTexture(int w, int h, byte[] data); + CTextureRef EnqueueTexture(Bitmap bmp); + void EnqueueTextureUpdate(CTextureRef textureRef, Bitmap bmp); void UpdateTexture(CTextureRef texture, int w, int h, byte[] data); + void UpdateTexture(CTextureRef texture, Bitmap bmp); + CTextureRef CopyTexture(CTextureRef textureRef); void RemoveTexture(ref CTextureRef texture); // Basic Draw Methods - void DrawLine(int a, int r, int g, int b, int w, int x1, int y1, int x2, int y2); - void DrawColor(SColorF color, SRectF rect); - void DrawColorReflection(SColorF color, SRectF rect, float space, float height); + void DrawLine(SColorF color, float w, int x1, int y1, int x2, int y2); + void DrawRect(SColorF color, SRectF rect); + void DrawRectReflection(SColorF color, SRectF rect, float space, float height); - void DrawTexture(CTextureRef texture); - void DrawTexture(CTextureRef texture, SRectF rect); void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, bool mirrored = false); void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false); void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, float begin, float end); diff --git a/Vocaluxe/Screens/CPopupScreenPlayerControl.cs b/Vocaluxe/Screens/CPopupScreenPlayerControl.cs index e0c1cdf2..4475e1da 100644 --- a/Vocaluxe/Screens/CPopupScreenPlayerControl.cs +++ b/Vocaluxe/Screens/CPopupScreenPlayerControl.cs @@ -195,7 +195,7 @@ namespace Vocaluxe.Screens return false; _Statics[_StaticCover].Texture = CBackgroundMusic.Cover; if (CBackgroundMusic.VideoEnabled && _VideoPreview && CBackgroundMusic.SongHasVideo) - CDraw.DrawTexture(_Statics[_StaticCover], CBackgroundMusic.GetVideoTexture(), EAspect.Crop); + CDraw.DrawTexture(CBackgroundMusic.GetVideoTexture(), _Statics[_StaticCover].Rect, EAspect.Crop); _Buttons[_ButtonPause].Visible = CBackgroundMusic.IsPlaying; _Buttons[_ButtonPlay].Visible = !CBackgroundMusic.IsPlaying; _Texts[_TextCurrentSong].Text = CBackgroundMusic.ArtistAndTitle; diff --git a/Vocaluxe/Screens/CScreenCredits.cs b/Vocaluxe/Screens/CScreenCredits.cs index 0674d9d2..bfc9735b 100644 --- a/Vocaluxe/Screens/CScreenCredits.cs +++ b/Vocaluxe/Screens/CScreenCredits.cs @@ -360,7 +360,7 @@ namespace Vocaluxe.Screens base.Draw(); //Draw background - CDraw.DrawColor(new SColorF(0, 0.18f, 0.474f, 1), new SRectF(0, 0, CSettings.RenderW, CSettings.RenderH, 0)); + CDraw.DrawRect(new SColorF(0, 0.18f, 0.474f, 1), new SRectF(0, 0, CSettings.RenderW, CSettings.RenderH, 0)); //Draw stars _StarsBlue.Draw(); diff --git a/VocaluxeLib/CHelper.cs b/VocaluxeLib/CHelper.cs index 411d39ec..b3392fe4 100644 --- a/VocaluxeLib/CHelper.cs +++ b/VocaluxeLib/CHelper.cs @@ -120,20 +120,20 @@ namespace VocaluxeLib return result; } - public static void SetRect(SRectF bounds, out SRectF rect, float rectAspect, EAspect aspect) + public static void SetRect(SRectF bounds, out SRectF rect, float aspectRatio, EAspect aspect) { var bounds2 = new RectangleF(bounds.X, bounds.Y, bounds.W, bounds.H); RectangleF rect2; - SetRect(bounds2, out rect2, rectAspect, aspect); + SetRect(bounds2, out rect2, aspectRatio, aspect); rect = new SRectF(rect2.X, rect2.Y, rect2.Width, rect2.Height, bounds.Z); } - public static void SetRect(RectangleF bounds, out RectangleF rect, float rectAspect, EAspect aspect) + public static void SetRect(RectangleF bounds, out RectangleF rect, float aspectRatio, EAspect aspect) { float boundsW = bounds.Width; float boundsH = bounds.Height; - float boundsAspect = boundsW / boundsH; + float boundsAspectRatio = boundsW / boundsH; float scaledWidth; float scaledHeight; @@ -141,27 +141,27 @@ namespace VocaluxeLib switch (aspect) { case EAspect.Crop: - if (boundsAspect >= rectAspect) + if (boundsAspectRatio >= aspectRatio) { scaledWidth = boundsW; - scaledHeight = boundsW / rectAspect; + scaledHeight = boundsW / aspectRatio; } else { scaledHeight = boundsH; - scaledWidth = boundsH * rectAspect; + scaledWidth = boundsH * aspectRatio; } break; case EAspect.LetterBox: - if (boundsAspect <= rectAspect) + if (boundsAspectRatio <= aspectRatio) { scaledWidth = boundsW; - scaledHeight = boundsW / rectAspect; + scaledHeight = boundsW / aspectRatio; } else { scaledHeight = boundsH; - scaledWidth = boundsH * rectAspect; + scaledWidth = boundsH * aspectRatio; } break; default: @@ -179,7 +179,7 @@ namespace VocaluxeLib /// /// Returns a list with all files in the given path that match a given pattern /// - /// Path to search for + /// Path to search /// Pattern to match (e.g. "*.jpg") /// Search directories recursively /// False for just file names, True for full path diff --git a/VocaluxeLib/Draw/CTextureRef.cs b/VocaluxeLib/Draw/CTextureRef.cs index 886da3a9..d593cb12 100644 --- a/VocaluxeLib/Draw/CTextureRef.cs +++ b/VocaluxeLib/Draw/CTextureRef.cs @@ -15,6 +15,7 @@ // along with Vocaluxe. If not, see . #endregion +using System; using System.Drawing; namespace VocaluxeLib.Draw @@ -22,10 +23,9 @@ namespace VocaluxeLib.Draw /// /// Reference to a texture in the drawing driver /// - public class CTextureRef + public class CTextureRef : IDisposable { - public int ID; - + public int ID { get; private set; } /// /// Size of original image (e.g. of bmp) /// @@ -56,22 +56,32 @@ namespace VocaluxeLib.Draw Rect = new SRectF(0f, 0f, origSize.Width, origSize.Height, 0f); } - public void CopyFieldsFrom(CTextureRef other) + ~CTextureRef() { - ID = other.ID; - OrigSize = other.OrigSize; - Rect = other.Rect; - Color = other.Color; + Dispose(); } - ~CTextureRef() + public void Dispose() { if (ID >= 0) { - //Free textures that are no longer reference + //Free textures that are no longer referenced CTextureRef tmp = this; CBase.Drawing.RemoveTexture(ref tmp); } + SetRemoved(); + } + + /// + /// Call this from the graphics driver to denote that this reference is remove and no longer valid
+ /// This avoids the finalizer + ///
+ public void SetRemoved() + { + if (ID < 0) + throw new ObjectDisposedException(GetType().Name); + ID = -1; + GC.SuppressFinalize(this); } } } \ No newline at end of file