changeset 82:0d389692be32

FBGUI: Separated locking in renderer so Invalidate does not block while Painting in timer callback
author Ivo Smits <Ivo@UCIS.nl>
date Mon, 17 Feb 2014 22:35:52 +0100
parents 4714531734b3
children 4ca44dd25a6a
files FBGUI/FBGUI.cs
diffstat 1 files changed, 16 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/FBGUI/FBGUI.cs	Sun Feb 16 15:05:31 2014 +0100
+++ b/FBGUI/FBGUI.cs	Mon Feb 17 22:35:52 2014 +0100
@@ -630,6 +630,7 @@
 		public IFramebuffer Framebuffer { get; private set; }
 		private Bitmap Frontbuffer = null;
 		protected Object RenderLock = new object();
+		private Object StatusLock = new object();
 		public event EventHandler<InvalidateEventArgs> Painted;
 		protected Size size = Size.Empty;
 		private ThreadingTimer PaintTimer = null;
@@ -638,29 +639,28 @@
 		public Boolean SuspendDrawing {
 			get { return suspenddrawing; }
 			set {
+				lock (StatusLock) suspenddrawing = value;
+				if (value) return;
 				lock (RenderLock) {
-					suspenddrawing = value;
-					if (!value) {
-						Refresh(DirtyRectangle);
-						DirtyRectangle = Rectangle.Empty;
-					}
+					Refresh(DirtyRectangle);
+					DirtyRectangle = Rectangle.Empty;
 				}
 			}
 		}
 		public int RedrawDelay {
 			get { return PaintDelay; }
 			set {
-				lock (RenderLock) {
+				lock (StatusLock) {
 					if (value < 0) throw new ArgumentOutOfRangeException("value");
 					PaintDelay = value;
 					if (PaintDelay == 0) {
 						if (PaintTimer != null) PaintTimer.Dispose();
 						PaintTimer = null;
-						if (PaintScheduled) PaintTimerCallback(null);
 					} else {
 						PaintTimer = new ThreadingTimer(PaintTimerCallback);
 					}
 				}
+				if (PaintScheduled) PaintTimerCallback(null);
 			}
 		}
 		private Boolean suspenddrawing = false;
@@ -709,7 +709,8 @@
 		}
 		public override void Invalidate(Rectangle rect) {
 			if (rect.Width == 0 || rect.Height == 0) return;
-			lock (RenderLock) {
+			Boolean drawDirect = false;
+			lock (StatusLock) {
 				if (SuspendDrawing || PaintTimer != null) {
 					DirtyRectangle = DirtyRectangle.IsEmpty ? rect : Rectangle.Union(DirtyRectangle, rect);
 					if (!SuspendDrawing && !PaintScheduled) {
@@ -717,17 +718,20 @@
 						PaintTimer.Change(PaintDelay, Timeout.Infinite);
 					}
 				} else {
-					Refresh(rect);
+					drawDirect = true;
 				}
 			}
+			if (drawDirect) Refresh(rect);
 		}
 		private void PaintTimerCallback(Object state) {
 			try {
-				lock (RenderLock) {
+				Rectangle rect;
+				lock (StatusLock) {
 					PaintScheduled = false;
-					Refresh(DirtyRectangle);
+					rect = DirtyRectangle;
 					DirtyRectangle = Rectangle.Empty;
 				}
+				Refresh(rect);
 			} catch (Exception ex) {
 				Debug.WriteLine(ex);
 				Console.Error.WriteLine(ex);
@@ -776,7 +780,7 @@
 			return true;
 		}
 		public virtual void Dispose() {
-			lock (RenderLock) {
+			lock (StatusLock) {
 				if (PaintTimer != null) PaintTimer.Dispose();
 				PaintTimer = null;
 			}