Merged TextPrinter optimization changes from gw-next2 branch.

This commit is contained in:
the_fiddler 2009-05-27 18:40:29 +00:00
parent b5f08288c6
commit 14eefe7e5c
7 changed files with 57 additions and 45 deletions

View file

@ -494,7 +494,7 @@ namespace OpenTK.Graphics
{ {
if (!disposed) 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) lock (context_lock)
{ {
available_contexts.Remove((this as IGraphicsContextInternal).Context); available_contexts.Remove((this as IGraphicsContextInternal).Context);

View file

@ -92,7 +92,7 @@ namespace OpenTK.Platform.Windows
{ {
try try
{ {
Debug.WriteLine("Using WGL_ARB_create_context..."); Debug.Write("Using WGL_ARB_create_context... ");
List<int> attributes = new List<int>(); List<int> attributes = new List<int>();
attributes.Add((int)ArbCreateContext.MajorVersion); attributes.Add((int)ArbCreateContext.MajorVersion);
@ -111,6 +111,10 @@ namespace OpenTK.Platform.Windows
currentWindow.DeviceContext, currentWindow.DeviceContext,
sharedContext != null ? (sharedContext as IGraphicsContextInternal).Context.Handle : IntPtr.Zero, sharedContext != null ? (sharedContext as IGraphicsContextInternal).Context.Handle : IntPtr.Zero,
attributes.ToArray())); 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 (EntryPointNotFoundException e) { Debug.Print(e.ToString()); }
catch (NullReferenceException e) { Debug.Print(e.ToString()); } catch (NullReferenceException e) { Debug.Print(e.ToString()); }
@ -119,7 +123,7 @@ namespace OpenTK.Platform.Windows
if (renderContext == ContextHandle.Zero) if (renderContext == ContextHandle.Zero)
{ {
// Failed to create GL3-level context, fall back to GL2. // 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)); renderContext = new ContextHandle(Wgl.Imports.CreateContext(currentWindow.DeviceContext));
if (renderContext == ContextHandle.Zero) if (renderContext == ContextHandle.Zero)
renderContext = new ContextHandle(Wgl.Imports.CreateContext(currentWindow.DeviceContext)); renderContext = new ContextHandle(Wgl.Imports.CreateContext(currentWindow.DeviceContext));

View file

@ -134,11 +134,11 @@ namespace OpenTK.Graphics
#endregion #endregion
#region End
/// <summary> /// <summary>
/// Restores the projection and modelview matrices to their previous state. /// Restores the projection and modelview matrices to their previous state.
/// </summary> /// </summary>
#region End
void End(); void End();
#endregion #endregion

View file

@ -81,7 +81,9 @@ namespace OpenTK.Graphics.Text
GL.Disable(EnableCap.DepthTest); GL.Disable(EnableCap.DepthTest);
using (TextExtents extents = rasterizer.MeasureText(block)) RectangleF position;
using (TextExtents extents = rasterizer.MeasureText(ref block))
{ {
// Build layout // Build layout
int current = 0; int current = 0;
@ -96,31 +98,41 @@ namespace OpenTK.Graphics.Text
Cache.Add(glyph, rasterizer, TextQuality); Cache.Add(glyph, rasterizer, TextQuality);
CachedGlyphInfo info = Cache[glyph]; 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). // Use the real glyph width instead of the measured one (we want to achieve pixel perfect output).
position.Size = info.Rectangle.Size; position.Size = info.Rectangle.Size;
if (!active_lists.ContainsKey(info.Texture)) if (!active_lists.ContainsKey(info.Texture))
{
if (inactive_lists.Count > 0) if (inactive_lists.Count > 0)
active_lists.Add(info.Texture, inactive_lists.Dequeue()); {
List<Vector2> list = inactive_lists.Dequeue();
list.Clear();
active_lists.Add(info.Texture, list);
}
else else
{
active_lists.Add(info.Texture, new List<Vector2>()); active_lists.Add(info.Texture, new List<Vector2>());
}
}
{ {
// Interleaved array: Vertex, TexCoord, Vertex, ... // Interleaved array: Vertex, TexCoord, Vertex, ...
active_lists[info.Texture].Add(new Vector2(info.RectangleNormalized.Left, info.RectangleNormalized.Top)); List<Vector2> current_list = active_lists[info.Texture];
active_lists[info.Texture].Add(new Vector2(position.Left, position.Top)); current_list.Add(new Vector2(info.RectangleNormalized.Left, info.RectangleNormalized.Top));
active_lists[info.Texture].Add(new Vector2(info.RectangleNormalized.Left, info.RectangleNormalized.Bottom)); current_list.Add(new Vector2(position.Left, position.Top));
active_lists[info.Texture].Add(new Vector2(position.Left, position.Bottom)); current_list.Add(new Vector2(info.RectangleNormalized.Left, info.RectangleNormalized.Bottom));
active_lists[info.Texture].Add(new Vector2(info.RectangleNormalized.Right, info.RectangleNormalized.Bottom)); current_list.Add(new Vector2(position.Left, position.Bottom));
active_lists[info.Texture].Add(new Vector2(position.Right, 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)); current_list.Add(new Vector2(info.RectangleNormalized.Right, info.RectangleNormalized.Bottom));
active_lists[info.Texture].Add(new Vector2(position.Right, position.Bottom)); current_list.Add(new Vector2(position.Right, position.Bottom));
active_lists[info.Texture].Add(new Vector2(info.RectangleNormalized.Right, info.RectangleNormalized.Top)); current_list.Add(new Vector2(info.RectangleNormalized.Right, info.RectangleNormalized.Top));
active_lists[info.Texture].Add(new Vector2(position.Right, position.Top)); current_list.Add(new Vector2(position.Right, position.Top));
active_lists[info.Texture].Add(new Vector2(info.RectangleNormalized.Left, info.RectangleNormalized.Top)); current_list.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(position.Left, position.Top));
} }
} }
} }
@ -132,13 +144,6 @@ namespace OpenTK.Graphics.Text
key.Bind(); 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); SetColor(color);
GL.Begin(BeginMode.Triangles); GL.Begin(BeginMode.Triangles);
@ -150,15 +155,12 @@ namespace OpenTK.Graphics.Text
} }
GL.End(); GL.End();
//if (!legacy_mode)
// GL.PopMatrix();
} }
// Clean layout // Clean layout
foreach (List<Vector2> list in active_lists.Values) foreach (List<Vector2> list in active_lists.Values)
{ {
list.Clear(); //list.Clear();
inactive_lists.Enqueue(list); inactive_lists.Enqueue(list);
} }

View file

@ -39,7 +39,8 @@ namespace OpenTK.Graphics.Text
{ {
#region Fields #region Fields
Dictionary<TextBlock, TextExtents> block_cache = new Dictionary<TextBlock, TextExtents>(); // Note: as an optimization, we store the TextBlock hashcode instead of the TextBlock itself.
Dictionary<int, TextExtents> block_cache = new Dictionary<int, TextExtents>();
System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(new Bitmap(1, 1)); System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(new Bitmap(1, 1));
IntPtr[] regions = new IntPtr[GdiPlus.MaxMeasurableCharacterRanges]; IntPtr[] regions = new IntPtr[GdiPlus.MaxMeasurableCharacterRanges];
@ -130,23 +131,24 @@ namespace OpenTK.Graphics.Text
#region MeasureText #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 // First, check if we have cached this text block. Do not use block_cache.TryGetValue, to avoid thrashing
// the user's TextBlockExtents struct. // the user's TextBlockExtents struct.
if (block_cache.ContainsKey(block)) int hashcode = block.GetHashCode();
return block_cache[block]; 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. // 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) if ((block.Options & TextPrinterOptions.NoCache) == 0)
block_cache.Add(block, extents); block_cache.Add(hashcode, extents);
return extents; return extents;
} }
@ -219,7 +221,7 @@ namespace OpenTK.Graphics.Text
#region MeasureTextExtents #region MeasureTextExtents
TextExtents MeasureTextExtents(TextBlock block, TextQuality quality) TextExtents MeasureTextExtents(ref TextBlock block, TextQuality quality)
{ {
// Todo: Parse layout options: // Todo: Parse layout options:
StringFormat format = block.Font.Italic ? measure_string_format : measure_string_format_tight; StringFormat format = block.Font.Italic ? measure_string_format : measure_string_format_tight;
@ -288,7 +290,10 @@ namespace OpenTK.Graphics.Text
} }
} }
if (extents.Count > 0)
extents.BoundingBox = new RectangleF(extents[0].X, extents[0].Y, max_width, max_height); extents.BoundingBox = new RectangleF(extents[0].X, extents[0].Y, max_width, max_height);
else
extents.BoundingBox = RectangleF.Empty;
return extents; return extents;
} }

View file

@ -38,8 +38,8 @@ namespace OpenTK.Graphics.Text
{ {
Bitmap Rasterize(Glyph glyph); Bitmap Rasterize(Glyph glyph);
Bitmap Rasterize(Glyph glyph, TextQuality quality); Bitmap Rasterize(Glyph glyph, TextQuality quality);
TextExtents MeasureText(TextBlock block); TextExtents MeasureText(ref TextBlock block);
TextExtents MeasureText(TextBlock block, TextQuality quality); TextExtents MeasureText(ref TextBlock block, TextQuality quality);
void Clear(); void Clear();
} }
} }

View file

@ -209,7 +209,8 @@ namespace OpenTK.Graphics
if (!ValidateParameters(text, font, rect)) if (!ValidateParameters(text, font, rect))
return TextExtents.Empty; 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 #endregion
@ -311,7 +312,7 @@ namespace OpenTK.Graphics
if (font == null) if (font == null)
throw new ArgumentNullException("font"); throw new ArgumentNullException("font");
if (rect.Width < 0 || rect.Height < 0) if (rect.Width < 0 || rect.Height < 0)
throw new ArgumentOutOfRangeException("size"); throw new ArgumentOutOfRangeException("rect");
return true; return true;
} }