From 3d3e97a4f86c5efd7292142f74dbd2f1168b61d0 Mon Sep 17 00:00:00 2001 From: jpbruyere Date: Tue, 3 Jan 2017 13:20:21 +0100 Subject: [PATCH] * Grid.cs, TabView.cs, Wrapper.cs, GenericStack.cs, GraphicObject.cs: IsDirty instead of deleting bmp, resolve blinking bug * Interface.cs: DrawingQueue locked inside the foreach loop, once per item * OpenTKGameWindow.cs: non blocking mutex inside render frame loop --- Tests/OpenTKGameWindow.cs | 3 ++- src/GraphicObjects/GenericStack.cs | 8 +++---- src/GraphicObjects/GraphicObject.cs | 34 ++++++++++++++++------------- src/GraphicObjects/Grid.cs | 2 +- src/GraphicObjects/TabView.cs | 2 +- src/GraphicObjects/Wrapper.cs | 4 ++-- src/Interface.cs | 27 ++++++++--------------- 7 files changed, 38 insertions(+), 42 deletions(-) diff --git a/Tests/OpenTKGameWindow.cs b/Tests/OpenTKGameWindow.cs index 359948c7..f5e69671 100644 --- a/Tests/OpenTKGameWindow.cs +++ b/Tests/OpenTKGameWindow.cs @@ -184,7 +184,7 @@ namespace Crow shader.SetMVP (projection); GL.ActiveTexture (TextureUnit.Texture0); GL.BindTexture (TextureTarget.Texture2D, texID); - lock (CrowInterface.RenderMutex) { + if (Monitor.TryEnter(CrowInterface.RenderMutex)) { if (CrowInterface.IsDirty) { GL.TexSubImage2D (TextureTarget.Texture2D, 0, CrowInterface.DirtyRect.Left, CrowInterface.DirtyRect.Top, @@ -192,6 +192,7 @@ namespace Crow OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.dirtyBmp); CrowInterface.IsDirty = false; } + Monitor.Exit (CrowInterface.RenderMutex); } quad.Render (BeginMode.TriangleStrip); GL.BindTexture(TextureTarget.Texture2D, 0); diff --git a/src/GraphicObjects/GenericStack.cs b/src/GraphicObjects/GenericStack.cs index 840e883f..a2d78d88 100644 --- a/src/GraphicObjects/GenericStack.cs +++ b/src/GraphicObjects/GenericStack.cs @@ -84,7 +84,7 @@ namespace Crow d += c.Slot.Height + Spacing; } } - bmp = null; + IsDirty = true; } GraphicObject stretchedGO = null; public override bool UpdateLayout (LayoutingType layoutType) @@ -99,7 +99,7 @@ namespace Crow ComputeChildrenPositions (); //if no layouting remains in queue for item, registre for redraw - if (RegisteredLayoutings == LayoutingType.None && bmp == null) + if (RegisteredLayoutings == LayoutingType.None && IsDirty) CurrentInterface.EnqueueForRepaint (this); return true; @@ -134,7 +134,7 @@ namespace Crow newW = Math.Min (newW, stretchedGO.MaximumSize.Width); if (newW != stretchedGO.Slot.Width) { stretchedGO.Slot.Width = newW; - stretchedGO.bmp = null; + stretchedGO.IsDirty = true; #if DEBUG_LAYOUTING Debug.WriteLine ("\tAdjusting Width of " + stretchedGO.ToString()); #endif @@ -173,7 +173,7 @@ namespace Crow newH = Math.Min (newH, stretchedGO.MaximumSize.Height); if (newH != stretchedGO.Slot.Height) { stretchedGO.Slot.Height = newH; - stretchedGO.bmp = null; + stretchedGO.IsDirty = true; #if DEBUG_LAYOUTING Debug.WriteLine ("\tAdjusting Height of " + stretchedGO.ToString()); #endif diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index e5313ea2..4a61386d 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -107,6 +107,7 @@ namespace Crow public object Tag; /// drawing Cache, if null, a redraw is done, cached or not public byte[] bmp; + public bool IsDirty = true; /// /// This size is computed on each child' layout changes. /// In stacking widget, it is used to compute the remaining space for the stretched @@ -416,17 +417,23 @@ namespace Crow NotifyValueChanged ("MouseRepeat", mouseRepeat); } } + bool clearBackground = false; [XmlAttributeAttribute()][DefaultValue("Transparent")] public virtual Fill Background { get { return background; } set { if (background == value) return; + clearBackground = false; if (value == null) return; background = value; NotifyValueChanged ("Background", background); RegisterForRedraw (); + if (background is SolidColor) { + if ((Background as SolidColor).Equals (Color.Clear)) + clearBackground = true; + } } } [XmlAttributeAttribute()][DefaultValue("White")] @@ -781,7 +788,7 @@ namespace Crow #region Queuing public virtual void RegisterClip(Rectangle clip){ - if (CacheEnabled && bmp != null) + if (CacheEnabled && !IsDirty) Clipping.AddRectangle (clip + ClientRectangle.Position); if (Parent != null) Parent.RegisterClip (clip + Slot.Position + ClientRectangle.Position); @@ -790,7 +797,7 @@ namespace Crow [MethodImpl(MethodImplOptions.AggressiveInlining)] public void RegisterForGraphicUpdate () { - bmp = null; + IsDirty = true; if (Width.IsFit || Height.IsFit) RegisterForLayouting (LayoutingType.Sizing); else if (RegisteredLayoutings == LayoutingType.None) @@ -800,7 +807,7 @@ namespace Crow [MethodImpl(MethodImplOptions.AggressiveInlining)] public void RegisterForRedraw () { - bmp = null; + IsDirty = true; if (RegisteredLayoutings == LayoutingType.None) CurrentInterface.EnqueueForRepaint (this); } @@ -913,7 +920,7 @@ namespace Crow if (LastSlots.X == Slot.X) break; - bmp = null; + IsDirty = true; OnLayoutChanges (layoutType); @@ -943,7 +950,7 @@ namespace Crow if (LastSlots.Y == Slot.Y) break; - bmp = null; + IsDirty = true; OnLayoutChanges (layoutType); @@ -979,7 +986,7 @@ namespace Crow if (LastSlots.Width == Slot.Width) break; - bmp = null; + IsDirty = true; OnLayoutChanges (layoutType); @@ -1015,7 +1022,7 @@ namespace Crow if (LastSlots.Height == Slot.Height) break; - bmp = null; + IsDirty = true; OnLayoutChanges (layoutType); @@ -1024,7 +1031,7 @@ namespace Crow } //if no layouting remains in queue for item, registre for redraw - if (this.registeredLayoutings == LayoutingType.None && bmp == null) + if (this.registeredLayoutings == LayoutingType.None && IsDirty) CurrentInterface.EnqueueForRepaint (this); return true; @@ -1051,7 +1058,7 @@ namespace Crow int bmpSize = Math.Abs (stride) * Slot.Height; bmp = new byte[bmpSize]; - + IsDirty = false; using (ImageSurface draw = new ImageSurface(bmp, Format.Argb32, Slot.Width, Slot.Height, stride)) { using (Context gr = new Context (draw)) { @@ -1063,16 +1070,13 @@ namespace Crow } protected virtual void UpdateCache(Context ctx){ Rectangle rb = Slot + Parent.ClientRectangle.Position; - using (ImageSurface cache = new ImageSurface (bmp, Format.Argb32, Slot.Width, Slot.Height, 4 * Slot.Width)) { - //TODO:improve equality test for basic color and Fill - if (this.Background is SolidColor) { - if ((this.Background as SolidColor).Equals (Color.Clear)) { + using (ImageSurface cache = new ImageSurface (bmp, Format.Argb32, Slot.Width, Slot.Height, 4 * Slot.Width)) { + if (clearBackground) { ctx.Save (); ctx.Operator = Operator.Clear; ctx.Rectangle (rb); ctx.Fill (); ctx.Restore (); - } } ctx.SetSourceSurface (cache, rb.X, rb.Y); ctx.Paint (); @@ -1096,7 +1100,7 @@ namespace Crow } if (cacheEnabled) { - if (bmp == null) + if (IsDirty) RecreateCache (); UpdateCache (ctx); diff --git a/src/GraphicObjects/Grid.cs b/src/GraphicObjects/Grid.cs index a0f0cb69..57ceda5e 100644 --- a/src/GraphicObjects/Grid.cs +++ b/src/GraphicObjects/Grid.cs @@ -134,7 +134,7 @@ namespace Crow ComputeChildrenPositions (); //if no layouting remains in queue for item, registre for redraw - if (RegisteredLayoutings == LayoutingType.None && bmp == null) + if (RegisteredLayoutings == LayoutingType.None && IsDirty) CurrentInterface.EnqueueForRepaint (this); return true; diff --git a/src/GraphicObjects/TabView.cs b/src/GraphicObjects/TabView.cs index 42bb39c0..e5466554 100644 --- a/src/GraphicObjects/TabView.cs +++ b/src/GraphicObjects/TabView.cs @@ -143,7 +143,7 @@ namespace Crow } //if no layouting remains in queue for item, registre for redraw - if (RegisteredLayoutings == LayoutingType.None && bmp == null) + if (RegisteredLayoutings == LayoutingType.None && IsDirty) CurrentInterface.EnqueueForRepaint (this); return true; diff --git a/src/GraphicObjects/Wrapper.cs b/src/GraphicObjects/Wrapper.cs index 1bfcd92a..fcf88583 100644 --- a/src/GraphicObjects/Wrapper.cs +++ b/src/GraphicObjects/Wrapper.cs @@ -76,7 +76,7 @@ namespace Crow dy += c.Slot.Height + Spacing; } } - bmp = null; + IsDirty = true; } public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) { @@ -180,7 +180,7 @@ namespace Crow ComputeChildrenPositions (); //if no layouting remains in queue for item, registre for redraw - if (RegisteredLayoutings == LayoutingType.None && bmp == null) + if (RegisteredLayoutings == LayoutingType.None && IsDirty) CurrentInterface.EnqueueForRepaint (this); return true; diff --git a/src/Interface.cs b/src/Interface.cs index 0cff9b87..d63b75de 100644 --- a/src/Interface.cs +++ b/src/Interface.cs @@ -98,14 +98,6 @@ namespace Crow public string Clipboard;//TODO:use object instead for complex copy paste public void EnqueueForRepaint(GraphicObject g) { -// if (g.RegisteredLayoutings != LayoutingType.None) -// return; - ILayoutable l = g; -// while (l.Parent != null) -// l = l.Parent; -// if (!(l is Interface)) -// return; - lock (DrawingQueue) { if (g.IsQueueForRedraw) return; @@ -408,15 +400,16 @@ namespace Crow #if MEASURE_TIME clippingTime.Restart (); #endif - lock (DrawingQueue) { - while (DrawingQueue.Count > 0) { - GraphicObject g = DrawingQueue.Dequeue (); - g.IsQueueForRedraw = false; - g.Parent.RegisterClip (g.LastPaintedSlot); - if (g.getSlot () != g.LastPaintedSlot) - g.Parent.RegisterClip (g.getSlot ()); - } + GraphicObject g = null; + while (DrawingQueue.Count > 0) { + lock (DrawingQueue) + g = DrawingQueue.Dequeue (); + g.IsQueueForRedraw = false; + g.Parent.RegisterClip (g.LastPaintedSlot); + if (g.getSlot () != g.LastPaintedSlot) + g.Parent.RegisterClip (g.getSlot ()); } + #if MEASURE_TIME clippingTime.Stop (); #endif @@ -427,8 +420,6 @@ namespace Crow #endif using (surf = new ImageSurface (bmp, Format.Argb32, ClientRectangle.Width, ClientRectangle.Height, ClientRectangle.Width * 4)) { using (ctx = new Context (surf)){ - - if (clipping.count > 0) { //Link.draw (ctx); clipping.clearAndClip(ctx); -- 2.47.3