From 9fce9fe9625b6c8453d3caf8b5cbdc48a8c4bd9d Mon Sep 17 00:00:00 2001 From: Flamefire Date: Sat, 13 Sep 2014 15:16:01 +0200 Subject: [PATCH] Faster rendering (most draw calls are without bounds) Fix for D3D --- Vocaluxe/Lib/Draw/CDirect3D.cs | 171 ++++++++++++++++---------- Vocaluxe/Lib/Draw/CDrawBase.cs | 11 +- Vocaluxe/Lib/Draw/CDrawBaseWindows.cs | 1 - Vocaluxe/Lib/Draw/COpenGL.cs | 120 ++++++++++++------ 4 files changed, 198 insertions(+), 105 deletions(-) diff --git a/Vocaluxe/Lib/Draw/CDirect3D.cs b/Vocaluxe/Lib/Draw/CDirect3D.cs index 47d67190..84680772 100644 --- a/Vocaluxe/Lib/Draw/CDirect3D.cs +++ b/Vocaluxe/Lib/Draw/CDirect3D.cs @@ -69,7 +69,8 @@ namespace Vocaluxe.Lib.Draw /// public CDirect3D() { - _Form = new CRenderFormHook(); + _Form = new CRenderFormHook {ClientSize = new Size(CConfig.ScreenW, CConfig.ScreenH)}; + try { _D3D = new Direct3D(); @@ -184,37 +185,45 @@ namespace Vocaluxe.Lib.Draw // The window was minimized, so restore it to the last known size if (_Form.ClientSize.Width == 0 || _Form.ClientSize.Height == 0) _Form.ClientSize = _SizeBeforeMinimize; - if (!_Run) - return; - _H = _Form.ClientSize.Height; - _W = _Form.ClientSize.Width; + + int newH = _Form.ClientSize.Height; + int newW = _Form.ClientSize.Width; _Y = 0; _X = 0; - if (_W / (float)_H > CSettings.GetRenderAspect()) + if (newW / (float)newH > CSettings.GetRenderAspect()) { //The windows width is too big - _W = (int)Math.Round(_H * CSettings.GetRenderAspect()); - _X = (_Form.ClientSize.Width - _W) / 2; + newW = (int)Math.Round(newH * CSettings.GetRenderAspect()); + _X = (_Form.ClientSize.Width - newW) / 2; } else { //The windows height is too big - _H = (int)Math.Round(_W / CSettings.GetRenderAspect()); - _Y = (_Form.ClientSize.Height - _H) / 2; + newH = (int)Math.Round(newW / CSettings.GetRenderAspect()); + _Y = (_Form.ClientSize.Height - newH) / 2; } + if (_H == newH && _W == newW) + return; + _H = newH; + _W = newW; + + //Apply the new sizes to the PresentParameters _PresentParameters.BackBufferWidth = _Form.ClientSize.Width; _PresentParameters.BackBufferHeight = _Form.ClientSize.Height; - ClearScreen(); - //To set new PresentParameters the device has to be resetted - _Reset(); - //All configurations got flushed due to Reset(), so apply them again - Init(); + if (_Run) + { + ClearScreen(); + //To set new PresentParameters the device has to be resetted + _Reset(); + //All configurations got flushed due to Reset(), so apply them again + _InitDevice(); + //Set the new Viewport + _Device.Viewport = new Viewport(_X, _Y, _W, _H); + } - //Set the new Viewport - _Device.Viewport = new Viewport(_X, _Y, _W, _H); //Store size so it can get restored after the window gets minimized _SizeBeforeMinimize = _Form.ClientSize; } @@ -249,6 +258,21 @@ namespace Vocaluxe.Lib.Draw if (_Device.Disposed) return false; + _InitDevice(); + + //This creates a new white texture and adds it to the texture pool + //This texture is used for the DrawRect method + using (var blankMap = new Bitmap(1, 1)) + using (Graphics g = Graphics.FromImage(blankMap)) + { + g.Clear(Color.White); + _BlankTexture = AddTexture(blankMap); + } + return true; + } + + private void _InitDevice() + { _AdjustNewBorders(); _VertexBuffer = new VertexBuffer(_Device, CSettings.VertexBufferElements * (4 * Marshal.SizeOf(typeof(STexturedColoredVertex))), Usage.WriteOnly | Usage.Dynamic, @@ -304,17 +328,6 @@ namespace Vocaluxe.Lib.Draw stream.WriteRange(indices); _IndexBuffer.Unlock(); _Device.Indices = _IndexBuffer; - - //This creates a new white texture and adds it to the texture pool - //This texture is used for the DrawRect method - using (var blankMap = new Bitmap(1, 1)) - { - Graphics g = Graphics.FromImage(blankMap); - g.Clear(Color.White); - g.Dispose(); - _BlankTexture = AddTexture(blankMap); - } - return true; } protected override void _OnBeforeDraw() @@ -342,7 +355,7 @@ namespace Vocaluxe.Lib.Draw if (_Device.TestCooperativeLevel() == ResultCode.DeviceNotReset) { _Reset(); - Init(); + _InitDevice(); } } Application.DoEvents(); @@ -382,7 +395,7 @@ namespace Vocaluxe.Lib.Draw public override void Unload() { base.Unload(); - STexturedColoredVertex.GetDeclaration(_Device).Dispose(); + STexturedColoredVertex.DisposeDeclaration(); _VertexBuffer.Dispose(); _IndexBuffer.Dispose(); _Device.Dispose(); @@ -572,7 +585,6 @@ namespace Vocaluxe.Lib.Draw #endregion Basic Draw Methods #region Textures - 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 @@ -661,7 +673,40 @@ namespace Vocaluxe.Lib.Draw /// True if the texture should be mirrored public void DrawTexture(CTexture texture, SRectF rect, SColorF color, bool mirrored = false) { - DrawTexture(texture, rect, color, new SRectF(0, 0, CSettings.RenderW, CSettings.RenderH, rect.Z), mirrored); + if (rect.W < 1 || rect.H < 1) + return; + + Texture t = _GetTexture(texture); + if (t == null) + return; + + //Calculate the position + float x1 = 0; + float x2 = texture.WidthRatio; + float y1 = 0; + float y2 = texture.HeightRatio; + + //Calculate the size + float rx1 = rect.X; + float rx2 = rect.X + rect.W; + float ry1 = rect.Y; + float ry2 = rect.Y + rect.H; + + color.A *= CGraphics.GlobalAlpha; + + Color c = color.AsColor(); + + if (mirrored) + { + y1 = -y1; + y2 = -y2; + } + var vert = new STexturedColoredVertex[4]; + vert[0] = new STexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), c.ToArgb()); + 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, t, _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2)); } /// @@ -674,9 +719,18 @@ namespace Vocaluxe.Lib.Draw /// True if the texture should be mirrored public void DrawTexture(CTexture texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false) { - if (!_TextureExists(texture)) + if (Math.Abs(rect.W) < 1 || Math.Abs(rect.H) < 1 || Math.Abs(bounds.H) < 1 || Math.Abs(bounds.W) < 1 || + Math.Abs(color.A) < 0.01) return; - if (_Textures[texture.ID] == null) + + if (bounds.X > rect.X + rect.W || bounds.X + bounds.W < rect.X) + return; + + if (bounds.Y > rect.Y + rect.H || bounds.Y + bounds.H < rect.Y) + return; + + Texture t = _GetTexture(texture); + if (t == null) return; //Calculate the position @@ -715,43 +769,21 @@ namespace Vocaluxe.Lib.Draw if (ry2 > bounds.Y + bounds.H) ry2 = bounds.Y + bounds.H; - //Align the pixels because Direct3D expects the pixels to be the left top corner - rx1 -= 0.5f; - ry1 -= 0.5f; - rx2 -= 0.5f; - ry2 -= 0.5f; - color.A *= CGraphics.GlobalAlpha; - if (color.A > 1) - color.A = 1; - if (color.R > 1) - color.R = 1; - if (color.G > 1) - color.G = 1; - if (color.B > 1) - color.B = 1; - Color c = color.AsColor(); - if (!mirrored) + if (mirrored) { - var vert = new STexturedColoredVertex[4]; - vert[0] = new STexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), c.ToArgb()); - 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, _Textures[texture.ID], _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2)); - } - else - { - var vert = new STexturedColoredVertex[4]; - vert[0] = new STexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, -y1), c.ToArgb()); - 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, _Textures[texture.ID], _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2)); + y1 = -y1; + y2 = -y2; } + var vert = new STexturedColoredVertex[4]; + vert[0] = new STexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), c.ToArgb()); + 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, t, _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2)); } /// @@ -941,6 +973,15 @@ namespace Vocaluxe.Lib.Draw return _Declaration; } + + public static void DisposeDeclaration() + { + if (_Declaration != null && !_Declaration.Disposed) + { + _Declaration.Dispose(); + _Declaration = null; + } + } } } } \ No newline at end of file diff --git a/Vocaluxe/Lib/Draw/CDrawBase.cs b/Vocaluxe/Lib/Draw/CDrawBase.cs index 4ecc9dae..19512ce3 100644 --- a/Vocaluxe/Lib/Draw/CDrawBase.cs +++ b/Vocaluxe/Lib/Draw/CDrawBase.cs @@ -148,7 +148,7 @@ namespace Vocaluxe.Lib.Draw CTexture s; try { - s = AddTexture(bmp); + s = AddTexture(bmp, texturePath); } finally { @@ -157,12 +157,18 @@ namespace Vocaluxe.Lib.Draw return s; } + public CTexture AddTexture(Bitmap bmp) + { + return AddTexture(bmp, ""); + } + /// /// Adds a texture and stores it in the Vram /// /// The Bitmap of which the texure will be created from + /// /// A STexture object containing the added texture - public CTexture AddTexture(Bitmap bmp) + public CTexture AddTexture(Bitmap bmp, string texturePath) { if (bmp.Height == 0 || bmp.Width == 0) return null; @@ -194,6 +200,7 @@ namespace Vocaluxe.Lib.Draw int h = Math.Min(bmp.Height, maxSize); CTexture texture = _GetNewTextureRef(bmp.Width, bmp.Height, w, h); + texture.TexturePath = texturePath; Bitmap bmp2 = null; try diff --git a/Vocaluxe/Lib/Draw/CDrawBaseWindows.cs b/Vocaluxe/Lib/Draw/CDrawBaseWindows.cs index dc8d8256..77c3ac9c 100644 --- a/Vocaluxe/Lib/Draw/CDrawBaseWindows.cs +++ b/Vocaluxe/Lib/Draw/CDrawBaseWindows.cs @@ -180,7 +180,6 @@ namespace Vocaluxe.Lib.Draw _Form.Resize += _OnResize; _Form.Load += _OnLoad; - _Form.ClientSize = new Size(CConfig.ScreenW, CConfig.ScreenH); _SizeBeforeMinimize = _Form.ClientSize; _CenterToScreen(); diff --git a/Vocaluxe/Lib/Draw/COpenGL.cs b/Vocaluxe/Lib/Draw/COpenGL.cs index 5c0ed946..ecbf7194 100644 --- a/Vocaluxe/Lib/Draw/COpenGL.cs +++ b/Vocaluxe/Lib/Draw/COpenGL.cs @@ -99,7 +99,8 @@ namespace Vocaluxe.Lib.Draw public COpenGL() { - _Form = new CFormHook(); + _Form = new CFormHook {ClientSize = new Size(CConfig.ScreenW, CConfig.ScreenH)}; + //Check AA Mode CConfig.AAMode = (EAntiAliasingModes)_CheckAntiAliasingMode((int)CConfig.AAMode); @@ -440,11 +441,12 @@ namespace Vocaluxe.Lib.Draw GL.BindTexture(TextureTarget.Texture2D, t.Name); + GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); 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.TextureWrapS, (int)TextureWrapMode.ClampToEdge); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear); GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D); @@ -478,8 +480,8 @@ namespace Vocaluxe.Lib.Draw 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); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear); GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D); @@ -554,7 +556,65 @@ namespace Vocaluxe.Lib.Draw public void DrawTexture(CTexture texture, SRectF rect, SColorF color, bool mirrored = false) { - DrawTexture(texture, rect, color, new SRectF(0, 0, CSettings.RenderW, CSettings.RenderH, rect.Z), mirrored); + CGLTexture t = _GetTexture(texture); + if (t == null) + return; + + if (Math.Abs(rect.W) < 1 || Math.Abs(rect.H) < 1 || Math.Abs(color.A) < 0.01) + return; + + GL.BindTexture(TextureTarget.Texture2D, t.Name); + + float x1 = 0; + float x2 = texture.WidthRatio; + float y1 = 0; + float y2 = texture.HeightRatio; + + float rx1 = rect.X; + float rx2 = rect.X + rect.W; + float ry1 = rect.Y; + float ry2 = rect.Y + rect.H; + + GL.Enable(EnableCap.Blend); + GL.Color4(color.R, color.G, color.B, color.A * CGraphics.GlobalAlpha); + + GL.MatrixMode(MatrixMode.Texture); + GL.PushMatrix(); + + if (Math.Abs(rect.Rotation) > float.Epsilon) + { + GL.Translate(0.5f, 0.5f, 0); + GL.Rotate(-rect.Rotation, 0f, 0f, 1f); + GL.Translate(-0.5f, -0.5f, 0); + } + + if (mirrored) + { + float tmp = ry2; + ry2 = ry1; + ry1 = tmp; + } + + GL.Begin(BeginMode.Quads); + + GL.TexCoord2(x1, y1); + GL.Vertex3(rx1, ry1, rect.Z + CGraphics.ZOffset); + + GL.TexCoord2(x1, y2); + GL.Vertex3(rx1, ry2, rect.Z + CGraphics.ZOffset); + + GL.TexCoord2(x2, y2); + GL.Vertex3(rx2, ry2, rect.Z + CGraphics.ZOffset); + + GL.TexCoord2(x2, y1); + GL.Vertex3(rx2, ry1, rect.Z + CGraphics.ZOffset); + + GL.End(); + + GL.PopMatrix(); + + GL.Disable(EnableCap.Blend); + GL.BindTexture(TextureTarget.Texture2D, 0); } public void DrawTexture(CTexture texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false) @@ -563,8 +623,8 @@ namespace Vocaluxe.Lib.Draw 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 || - Math.Abs(color.A) < float.Epsilon) + if (Math.Abs(rect.W) < 1 || Math.Abs(rect.H) < 1 || Math.Abs(bounds.H) < 1 || Math.Abs(bounds.W) < 1 || + Math.Abs(color.A) < 0.01) return; if (bounds.X > rect.X + rect.W || bounds.X + bounds.W < rect.X) @@ -623,42 +683,28 @@ namespace Vocaluxe.Lib.Draw GL.Translate(-0.5f, -0.5f, 0); } - if (!mirrored) + if (mirrored) { - GL.Begin(BeginMode.Quads); - - GL.TexCoord2(x1, y1); - GL.Vertex3(rx1, ry1, rect.Z + CGraphics.ZOffset); - - GL.TexCoord2(x1, y2); - GL.Vertex3(rx1, ry2, rect.Z + CGraphics.ZOffset); - - GL.TexCoord2(x2, y2); - GL.Vertex3(rx2, ry2, rect.Z + CGraphics.ZOffset); - - GL.TexCoord2(x2, y1); - GL.Vertex3(rx2, ry1, rect.Z + CGraphics.ZOffset); - - GL.End(); + float tmp = ry2; + ry2 = ry1; + ry1 = tmp; } - else - { - GL.Begin(BeginMode.Quads); - GL.TexCoord2(x2, y2); - GL.Vertex3(rx2, ry1, rect.Z + CGraphics.ZOffset); + GL.Begin(BeginMode.Quads); - GL.TexCoord2(x2, y1); - GL.Vertex3(rx2, ry2, rect.Z + CGraphics.ZOffset); + GL.TexCoord2(x1, y1); + GL.Vertex3(rx1, ry1, rect.Z + CGraphics.ZOffset); - GL.TexCoord2(x1, y1); - GL.Vertex3(rx1, ry2, rect.Z + CGraphics.ZOffset); + GL.TexCoord2(x1, y2); + GL.Vertex3(rx1, ry2, rect.Z + CGraphics.ZOffset); - GL.TexCoord2(x1, y2); - GL.Vertex3(rx1, ry1, rect.Z + CGraphics.ZOffset); + GL.TexCoord2(x2, y2); + GL.Vertex3(rx2, ry2, rect.Z + CGraphics.ZOffset); - GL.End(); - } + GL.TexCoord2(x2, y1); + GL.Vertex3(rx2, ry1, rect.Z + CGraphics.ZOffset); + + GL.End(); GL.PopMatrix();