From deadbdf6cbbd6e465fe4f959a239d329ddb4dfdc Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Wed, 27 May 2009 18:40:29 +0000 Subject: [PATCH] Merged TextPrinter optimization changes from gw-next2 branch. --- Source/OpenTK/Graphics/GraphicsContext.cs | 2 +- .../OpenTK/Platform/Windows/WinGLContext.cs | 8 ++- Source/Utilities/Graphics/ITextPrinter.cs | 4 +- .../Graphics/Text/GL1TextOutputProvider.cs | 54 ++++++++++--------- .../Graphics/Text/GdiPlusGlyphRasterizer.cs | 25 +++++---- .../Graphics/Text/IGlyphRasterizer.cs | 4 +- Source/Utilities/Graphics/TextPrinter.cs | 5 +- 7 files changed, 57 insertions(+), 45 deletions(-) diff --git a/Source/OpenTK/Graphics/GraphicsContext.cs b/Source/OpenTK/Graphics/GraphicsContext.cs index 5797db2a..1235dc24 100644 --- a/Source/OpenTK/Graphics/GraphicsContext.cs +++ b/Source/OpenTK/Graphics/GraphicsContext.cs @@ -494,7 +494,7 @@ namespace OpenTK.Graphics { if (!disposed) { - Debug.WriteLine("Disposing context {0}.", (this as IGraphicsContextInternal).Context.ToString()); + Debug.Print("Disposing context {0}.", (this as IGraphicsContextInternal).Context.ToString()); lock (context_lock) { available_contexts.Remove((this as IGraphicsContextInternal).Context); diff --git a/Source/OpenTK/Platform/Windows/WinGLContext.cs b/Source/OpenTK/Platform/Windows/WinGLContext.cs index 7889df53..47e70a95 100644 --- a/Source/OpenTK/Platform/Windows/WinGLContext.cs +++ b/Source/OpenTK/Platform/Windows/WinGLContext.cs @@ -92,7 +92,7 @@ namespace OpenTK.Platform.Windows { try { - Debug.WriteLine("Using WGL_ARB_create_context..."); + Debug.Write("Using WGL_ARB_create_context... "); List attributes = new List(); attributes.Add((int)ArbCreateContext.MajorVersion); @@ -111,6 +111,10 @@ namespace OpenTK.Platform.Windows currentWindow.DeviceContext, sharedContext != null ? (sharedContext as IGraphicsContextInternal).Context.Handle : IntPtr.Zero, attributes.ToArray())); + if (renderContext == ContextHandle.Zero) + Debug.Print("failed. (Error: {0})", Marshal.GetLastWin32Error()); + else + Debug.Print("success!"); } catch (EntryPointNotFoundException e) { Debug.Print(e.ToString()); } catch (NullReferenceException e) { Debug.Print(e.ToString()); } @@ -119,7 +123,7 @@ namespace OpenTK.Platform.Windows if (renderContext == ContextHandle.Zero) { // Failed to create GL3-level context, fall back to GL2. - Debug.Write("failed. Falling back to GL2... "); + Debug.Write("Falling back to GL2... "); renderContext = new ContextHandle(Wgl.Imports.CreateContext(currentWindow.DeviceContext)); if (renderContext == ContextHandle.Zero) renderContext = new ContextHandle(Wgl.Imports.CreateContext(currentWindow.DeviceContext)); diff --git a/Source/Utilities/Graphics/ITextPrinter.cs b/Source/Utilities/Graphics/ITextPrinter.cs index fb85def2..abdcfb56 100644 --- a/Source/Utilities/Graphics/ITextPrinter.cs +++ b/Source/Utilities/Graphics/ITextPrinter.cs @@ -134,11 +134,11 @@ namespace OpenTK.Graphics #endregion + #region End + /// /// Restores the projection and modelview matrices to their previous state. /// - #region End - void End(); #endregion diff --git a/Source/Utilities/Graphics/Text/GL1TextOutputProvider.cs b/Source/Utilities/Graphics/Text/GL1TextOutputProvider.cs index 827c2170..e36c5f0a 100644 --- a/Source/Utilities/Graphics/Text/GL1TextOutputProvider.cs +++ b/Source/Utilities/Graphics/Text/GL1TextOutputProvider.cs @@ -81,7 +81,9 @@ namespace OpenTK.Graphics.Text GL.Disable(EnableCap.DepthTest); - using (TextExtents extents = rasterizer.MeasureText(block)) + RectangleF position; + + using (TextExtents extents = rasterizer.MeasureText(ref block)) { // Build layout int current = 0; @@ -96,31 +98,41 @@ namespace OpenTK.Graphics.Text Cache.Add(glyph, rasterizer, TextQuality); CachedGlyphInfo info = Cache[glyph]; - RectangleF position = extents[current++]; + position = extents[current++]; // Use the real glyph width instead of the measured one (we want to achieve pixel perfect output). position.Size = info.Rectangle.Size; if (!active_lists.ContainsKey(info.Texture)) + { if (inactive_lists.Count > 0) - active_lists.Add(info.Texture, inactive_lists.Dequeue()); + { + List list = inactive_lists.Dequeue(); + list.Clear(); + active_lists.Add(info.Texture, list); + } else + { active_lists.Add(info.Texture, new List()); + } + } + { // Interleaved array: Vertex, TexCoord, Vertex, ... - active_lists[info.Texture].Add(new Vector2(info.RectangleNormalized.Left, info.RectangleNormalized.Top)); - active_lists[info.Texture].Add(new Vector2(position.Left, position.Top)); - active_lists[info.Texture].Add(new Vector2(info.RectangleNormalized.Left, info.RectangleNormalized.Bottom)); - active_lists[info.Texture].Add(new Vector2(position.Left, position.Bottom)); - active_lists[info.Texture].Add(new Vector2(info.RectangleNormalized.Right, info.RectangleNormalized.Bottom)); - active_lists[info.Texture].Add(new Vector2(position.Right, position.Bottom)); + List current_list = active_lists[info.Texture]; + current_list.Add(new Vector2(info.RectangleNormalized.Left, info.RectangleNormalized.Top)); + current_list.Add(new Vector2(position.Left, position.Top)); + current_list.Add(new Vector2(info.RectangleNormalized.Left, info.RectangleNormalized.Bottom)); + current_list.Add(new Vector2(position.Left, position.Bottom)); + current_list.Add(new Vector2(info.RectangleNormalized.Right, info.RectangleNormalized.Bottom)); + current_list.Add(new Vector2(position.Right, position.Bottom)); - active_lists[info.Texture].Add(new Vector2(info.RectangleNormalized.Right, info.RectangleNormalized.Bottom)); - active_lists[info.Texture].Add(new Vector2(position.Right, position.Bottom)); - active_lists[info.Texture].Add(new Vector2(info.RectangleNormalized.Right, info.RectangleNormalized.Top)); - active_lists[info.Texture].Add(new Vector2(position.Right, position.Top)); - active_lists[info.Texture].Add(new Vector2(info.RectangleNormalized.Left, info.RectangleNormalized.Top)); - active_lists[info.Texture].Add(new Vector2(position.Left, position.Top)); + current_list.Add(new Vector2(info.RectangleNormalized.Right, info.RectangleNormalized.Bottom)); + current_list.Add(new Vector2(position.Right, position.Bottom)); + current_list.Add(new Vector2(info.RectangleNormalized.Right, info.RectangleNormalized.Top)); + current_list.Add(new Vector2(position.Right, position.Top)); + current_list.Add(new Vector2(info.RectangleNormalized.Left, info.RectangleNormalized.Top)); + current_list.Add(new Vector2(position.Left, position.Top)); } } } @@ -132,13 +144,6 @@ namespace OpenTK.Graphics.Text key.Bind(); - //if (!legacy_mode) - //{ - // GL.PushMatrix(); - // GL.GetFloat(GetPName.Viewport, viewport); - // GL.Scale(2.0 / (viewport[2] - viewport[0]), -2.0 / (viewport[3] - viewport[1]), 1); - //} - SetColor(color); GL.Begin(BeginMode.Triangles); @@ -150,15 +155,12 @@ namespace OpenTK.Graphics.Text } GL.End(); - - //if (!legacy_mode) - // GL.PopMatrix(); } // Clean layout foreach (List list in active_lists.Values) { - list.Clear(); + //list.Clear(); inactive_lists.Enqueue(list); } diff --git a/Source/Utilities/Graphics/Text/GdiPlusGlyphRasterizer.cs b/Source/Utilities/Graphics/Text/GdiPlusGlyphRasterizer.cs index 8c1fd0da..1f0ab25b 100644 --- a/Source/Utilities/Graphics/Text/GdiPlusGlyphRasterizer.cs +++ b/Source/Utilities/Graphics/Text/GdiPlusGlyphRasterizer.cs @@ -39,7 +39,8 @@ namespace OpenTK.Graphics.Text { #region Fields - Dictionary block_cache = new Dictionary(); + // Note: as an optimization, we store the TextBlock hashcode instead of the TextBlock itself. + Dictionary block_cache = new Dictionary(); System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(new Bitmap(1, 1)); IntPtr[] regions = new IntPtr[GdiPlus.MaxMeasurableCharacterRanges]; @@ -130,23 +131,24 @@ namespace OpenTK.Graphics.Text #region MeasureText - public TextExtents MeasureText(TextBlock block) + public TextExtents MeasureText(ref TextBlock block) { - return MeasureText(block, TextQuality.Default); + return MeasureText(ref block, TextQuality.Default); } - public TextExtents MeasureText(TextBlock block, TextQuality quality) + public TextExtents MeasureText(ref TextBlock block, TextQuality quality) { // First, check if we have cached this text block. Do not use block_cache.TryGetValue, to avoid thrashing // the user's TextBlockExtents struct. - if (block_cache.ContainsKey(block)) - return block_cache[block]; + int hashcode = block.GetHashCode(); + if (block_cache.ContainsKey(hashcode)) + return block_cache[hashcode]; // If this block is not cached, we have to measure it and (potentially) place it in the cache. - TextExtents extents = MeasureTextExtents(block, quality); + TextExtents extents = MeasureTextExtents(ref block, quality); if ((block.Options & TextPrinterOptions.NoCache) == 0) - block_cache.Add(block, extents); + block_cache.Add(hashcode, extents); return extents; } @@ -219,7 +221,7 @@ namespace OpenTK.Graphics.Text #region MeasureTextExtents - TextExtents MeasureTextExtents(TextBlock block, TextQuality quality) + TextExtents MeasureTextExtents(ref TextBlock block, TextQuality quality) { // Todo: Parse layout options: StringFormat format = block.Font.Italic ? measure_string_format : measure_string_format_tight; @@ -288,7 +290,10 @@ namespace OpenTK.Graphics.Text } } - extents.BoundingBox = new RectangleF(extents[0].X, extents[0].Y, max_width, max_height); + if (extents.Count > 0) + extents.BoundingBox = new RectangleF(extents[0].X, extents[0].Y, max_width, max_height); + else + extents.BoundingBox = RectangleF.Empty; return extents; } diff --git a/Source/Utilities/Graphics/Text/IGlyphRasterizer.cs b/Source/Utilities/Graphics/Text/IGlyphRasterizer.cs index 7b51aecc..b3316a2c 100644 --- a/Source/Utilities/Graphics/Text/IGlyphRasterizer.cs +++ b/Source/Utilities/Graphics/Text/IGlyphRasterizer.cs @@ -38,8 +38,8 @@ namespace OpenTK.Graphics.Text { Bitmap Rasterize(Glyph glyph); Bitmap Rasterize(Glyph glyph, TextQuality quality); - TextExtents MeasureText(TextBlock block); - TextExtents MeasureText(TextBlock block, TextQuality quality); + TextExtents MeasureText(ref TextBlock block); + TextExtents MeasureText(ref TextBlock block, TextQuality quality); void Clear(); } } diff --git a/Source/Utilities/Graphics/TextPrinter.cs b/Source/Utilities/Graphics/TextPrinter.cs index 9d9f5a2f..3ed3b8ae 100644 --- a/Source/Utilities/Graphics/TextPrinter.cs +++ b/Source/Utilities/Graphics/TextPrinter.cs @@ -209,7 +209,8 @@ namespace OpenTK.Graphics if (!ValidateParameters(text, font, rect)) return TextExtents.Empty; - return Rasterizer.MeasureText(new TextBlock(text, font, rect, options, alignment, direction)); + TextBlock block = new TextBlock(text, font, rect, options, alignment, direction); + return Rasterizer.MeasureText(ref block); } #endregion @@ -311,7 +312,7 @@ namespace OpenTK.Graphics if (font == null) throw new ArgumentNullException("font"); if (rect.Width < 0 || rect.Height < 0) - throw new ArgumentOutOfRangeException("size"); + throw new ArgumentOutOfRangeException("rect"); return true; }