diff --git a/Vocaluxe/Lib/Draw/CDirect3D.cs b/Vocaluxe/Lib/Draw/CDirect3D.cs index 9c123131..0aa91787 100644 --- a/Vocaluxe/Lib/Draw/CDirect3D.cs +++ b/Vocaluxe/Lib/Draw/CDirect3D.cs @@ -210,7 +210,7 @@ namespace Vocaluxe.Lib.Draw _PresentParameters.BackBufferHeight = _Form.ClientSize.Height; if (_Run) { - ClearScreen(); + _ClearScreen(); //To set new PresentParameters the device has to be resetted _Reset(); //All configurations got flushed due to Reset(), so apply them again @@ -469,7 +469,7 @@ namespace Vocaluxe.Lib.Draw /// /// Removes all textures from the screen /// - public override void ClearScreen() + protected override void _ClearScreen() { if (_Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0).IsFailure) CLog.LogError("Failed to clear the backbuffer"); diff --git a/Vocaluxe/Lib/Draw/CDrawBase.cs b/Vocaluxe/Lib/Draw/CDrawBase.cs index 78f1598d..1eca5564 100644 --- a/Vocaluxe/Lib/Draw/CDrawBase.cs +++ b/Vocaluxe/Lib/Draw/CDrawBase.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Drawing; -using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; using System.Runtime.InteropServices; @@ -88,7 +87,7 @@ namespace Vocaluxe.Lib.Draw protected int _BorderBottom; protected EGeneralAlignment _CurrentAlignment = EGeneralAlignment.Middle; - public abstract void ClearScreen(); + protected abstract void _ClearScreen(); protected abstract void _AdjustNewBorders(); protected abstract void _LeaveFullScreen(); @@ -174,6 +173,63 @@ namespace Vocaluxe.Lib.Draw #region Textures #region private/protected + /// + /// Returns the maximum area allowed for a texture based on the current quality + /// + /// + private static int _GetMaxTextureArea() + { + switch (CConfig.TextureQuality) + { + case ETextureQuality.TR_CONFIG_TEXTURE_LOWEST: + return 128 * 128; + case ETextureQuality.TR_CONFIG_TEXTURE_LOW: + return 256 * 128; + case ETextureQuality.TR_CONFIG_TEXTURE_MEDIUM: + return 512 * 256; + case ETextureQuality.TR_CONFIG_TEXTURE_HIGH: + return 1024 * 512; + case ETextureQuality.TR_CONFIG_TEXTURE_HIGHEST: + return CSettings.RenderW * CSettings.RenderH; + default: + throw new ArgumentException(); + } + } + + /// + /// Calculates the size for a new texture using the quality and smart values for rescaling + /// + /// New size for the texture + private Size _GetNewTextureSize(Size size) + { + Debug.Assert(size.Width > 0 && size.Height > 0); + int maxArea = _GetMaxTextureArea(); + int curArea = size.Width * size.Height; + if (curArea <= maxArea) + return size; + double factor = Math.Sqrt((double)maxArea / curArea); + Size newSize = new Size((int)(size.Width * factor), (int)(size.Height * factor)); + if (!_NonPowerOf2TextureSupported) + { + if (size.Width < size.Height) + { + newSize.Width = _CheckForNextPowerOf2(newSize.Width); + newSize.Height = _CheckForNextPowerOf2(maxArea / newSize.Width); + if (newSize.Width * newSize.Height > maxArea) + newSize.Height /= 2; + } + else + { + newSize.Height = _CheckForNextPowerOf2(newSize.Height); + newSize.Width = _CheckForNextPowerOf2(maxArea / newSize.Height); + if (newSize.Width * newSize.Height > maxArea) + newSize.Width /= 2; + } + } + Debug.Assert(newSize.Width * newSize.Height <= maxArea); + return newSize; + } + protected abstract void _WriteDataToTexture(TTextureType texture, byte[] data); protected virtual void _WriteDataToTexture(TTextureType texture, IntPtr data) @@ -211,56 +267,18 @@ namespace Vocaluxe.Lib.Draw /// private void _WriteBitmapToTexture(ref TTextureType texture, Bitmap bmp) { - 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) + Size size = _GetNewTextureSize(bmp.GetSize()); + if (!size.Equals(bmp.GetSize())) { - //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)); - } + bmp2 = bmp.Resize(size); 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); + BitmapData bmpData = bmp.LockBits(bmp.GetRect(), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); if (texture == null) texture = _CreateTexture(size); else @@ -624,7 +642,7 @@ namespace Vocaluxe.Lib.Draw _OnBeforeDraw(); //Clear the previous Frame - ClearScreen(); + _ClearScreen(); if (!CGraphics.Draw()) _Run = false; _OnAfterDraw(); diff --git a/Vocaluxe/Lib/Draw/CDrawBaseWindows.cs b/Vocaluxe/Lib/Draw/CDrawBaseWindows.cs index eb3a4b5e..e387281b 100644 --- a/Vocaluxe/Lib/Draw/CDrawBaseWindows.cs +++ b/Vocaluxe/Lib/Draw/CDrawBaseWindows.cs @@ -105,7 +105,7 @@ namespace Vocaluxe.Lib.Draw private void _OnLoad(object sender, EventArgs e) { - ClearScreen(); + _ClearScreen(); } protected virtual void _OnResize(object sender, EventArgs e) diff --git a/Vocaluxe/Lib/Draw/COpenGL.cs b/Vocaluxe/Lib/Draw/COpenGL.cs index 39730246..997bd148 100644 --- a/Vocaluxe/Lib/Draw/COpenGL.cs +++ b/Vocaluxe/Lib/Draw/COpenGL.cs @@ -254,7 +254,7 @@ namespace Vocaluxe.Lib.Draw return _Control.Height; } - public override void ClearScreen() + protected override void _ClearScreen() { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); } diff --git a/VocaluxeLib/Extensions.cs b/VocaluxeLib/Extensions.cs index 80d0ce3e..3716cbb5 100644 --- a/VocaluxeLib/Extensions.cs +++ b/VocaluxeLib/Extensions.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.Drawing.Drawing2D; using System.Globalization; using System.Linq; @@ -143,7 +144,39 @@ namespace VocaluxeLib public static Rectangle GetRect(this Bitmap bmp) { - return new Rectangle(0, 0, bmp.Width, bmp.Height); + return Rectangle.Round(new Rectangle(0, 0, bmp.Width, bmp.Height)); + } + + /// + /// Resizes the bitmap to the given size creating a copy of it + /// + /// + /// + /// Resized bitmap or null on error + public static Bitmap Resize(this Bitmap bmp, Size newSize) + { + Bitmap result = null; + try + { + //Create a new Bitmap with the new sizes + result = new Bitmap(newSize.Width, newSize.Height); + //Scale the texture + using (Graphics g = Graphics.FromImage(result)) + { + g.InterpolationMode = InterpolationMode.HighQualityBicubic; + g.SmoothingMode = SmoothingMode.HighQuality; + g.DrawImage(bmp, result.GetRect()); + } + } + catch (Exception) + { + if (result != null) + { + result.Dispose(); + result = null; + } + } + return result; } } } \ No newline at end of file