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)
{
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);

View file

@ -92,7 +92,7 @@ namespace OpenTK.Platform.Windows
{
try
{
Debug.WriteLine("Using WGL_ARB_create_context...");
Debug.Write("Using WGL_ARB_create_context... ");
List<int> attributes = new List<int>();
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));

View file

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

View file

@ -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<Vector2> list = inactive_lists.Dequeue();
list.Clear();
active_lists.Add(info.Texture, list);
}
else
{
active_lists.Add(info.Texture, new List<Vector2>());
}
}
{
// 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<Vector2> 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<Vector2> list in active_lists.Values)
{
list.Clear();
//list.Clear();
inactive_lists.Enqueue(list);
}

View file

@ -39,7 +39,8 @@ namespace OpenTK.Graphics.Text
{
#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));
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;
}

View file

@ -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();
}
}

View file

@ -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;
}