Advertisement
jimgreeno

Untitled

Jul 8th, 2018
406
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.27 KB | None | 0 0
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Diagnostics;
  4. using System.Drawing;
  5. using System.Drawing.Imaging;
  6. using System.Linq;
  7. using System.Runtime.InteropServices;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using System.Windows.Forms;
  11. using Timer=System.Windows.Forms.Timer;
  12.  
  13. /// <summary>
  14. /// Based on the idea of http://www.jscreenfix.com
  15. /// </summary>
  16. public sealed partial class StuckPixelFixForm : Form
  17. {
  18. [DllImport("user32.dll")]
  19. static extern bool LockWindowUpdate(IntPtr hWndLock);
  20.  
  21. static readonly BlockingCollection<Bitmap> drawQ = new BlockingCollection<Bitmap>(2);
  22. static readonly ThreadLocal<RndPixelFiller> filler = new ThreadLocal<RndPixelFiller>(() => new RndPixelFiller());
  23.  
  24. static readonly Timer timer = new Timer { Interval = 10 };
  25. static TimeStats stats = new TimeStats();
  26. static ulong framesDisplayed = 0;
  27.  
  28. protected override void OnLoad(EventArgs e)
  29. {
  30. base.OnLoad(e);
  31.  
  32. //base.TopMost = true;
  33. base.DoubleBuffered = true;
  34. base.FormBorderStyle = FormBorderStyle.None;
  35. base.WindowState = FormWindowState.Maximized;
  36.  
  37. new Thread(RunFramesRenderer) { IsBackground = true }.Start();
  38. //Task.Factory.StartNew(RunFramesRenderer, TaskCreationOptions.LongRunning);
  39.  
  40. timer.Tick += OnTimerTick;
  41. timer.Start();
  42. }
  43.  
  44. protected override void OnActivated(EventArgs e)
  45. {
  46. Cursor.Hide();
  47. timer.Start();
  48. }
  49.  
  50. protected override void OnDeactivate(EventArgs e)
  51. {
  52. Cursor.Show();
  53. timer.Stop();
  54. }
  55.  
  56. protected override void OnClosed(EventArgs e)
  57. {
  58. base.OnClosed(e);
  59.  
  60. const string f1 = @"ss\.fffff";
  61. MessageBox.Show(this,
  62. string.Join(Environment.NewLine,
  63. "Frame rendering times:",
  64. "Avg (s) = " + stats.Avg.ToString(f1),
  65. "Min (s) = " + stats.Min.ToString(f1),
  66. "Max (s) = " + stats.Max.ToString(f1),
  67. string.Empty,
  68. "Frames Per Second (FPS):",
  69. "Avg = " + (1.0d / stats.Avg.TotalSeconds).ToString("F3"),
  70. "Min = " + (1.0d / stats.Max.TotalSeconds).ToString("F3"),
  71. "Max = " + (1.0d / stats.Min.TotalSeconds).ToString("F3"),
  72. string.Empty,
  73. "Summary:",
  74. "App run time = " + (DateTime.UtcNow - Process.GetCurrentProcess().StartTime.ToUniversalTime()),
  75. "Total frames rendered = " + stats.SamplesCount,
  76. "Total frames displayed = " + framesDisplayed
  77. ), Application.ProductName);
  78. }
  79.  
  80. protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
  81. {
  82. if (keyData == (Keys.Escape))
  83. {
  84. Close();
  85. return true;
  86. }
  87. return base.ProcessCmdKey(ref msg, keyData);
  88. }
  89.  
  90. protected override void OnPaintBackground(PaintEventArgs e)
  91. {
  92. if (drawQ.TryTake(out Bitmap frame))
  93. {
  94. e.Graphics.DrawImageUnscaled(frame, e.ClipRectangle);
  95. ++framesDisplayed;
  96. }
  97. }
  98.  
  99. void OnTimerTick(object sender, EventArgs e)
  100. {
  101. LockWindowUpdate(Handle);
  102. this.Refresh();
  103. LockWindowUpdate(IntPtr.Zero);
  104. }
  105.  
  106. void RunFramesRenderer()
  107. {
  108. var poolLength = drawQ.BoundedCapacity + 2;
  109. var framesPool = Enumerable.Range(0, poolLength)
  110. .Select(_ => new Bitmap(Width, Height)).ToArray();
  111. var frameIndex = 0;
  112. while (true)
  113. {
  114. drawQ.Add(RenderFrame(framesPool[frameIndex]));
  115. frameIndex = (frameIndex + 1) % poolLength;
  116. }
  117. }
  118.  
  119. static Bitmap RenderFrame(Bitmap img)
  120. {
  121. var data = img.LockBits(new Rectangle(0, 0, img.Width, img.Height),
  122. ImageLockMode.WriteOnly,
  123. PixelFormat.Format32bppArgb);
  124. try
  125. {
  126. stats.BeginSample();
  127. #if true // MT
  128. FillNoiseMT(data);
  129. #else
  130. FillNoiseST(data);
  131. #endif
  132. stats.EndSample();
  133. }
  134. finally
  135. {
  136. img.UnlockBits(data);
  137. }
  138. return img;
  139. }
  140.  
  141. static void FillNoiseST(BitmapData data)
  142. {
  143. filler.Value.FillBuffer(data.Scan0, data.Scan0 + data.Stride * data.Height);
  144. }
  145.  
  146. static void FillNoiseMT(BitmapData data)
  147. {
  148. var partitioner = Partitioner.Create(0, data.Height);
  149. Parallel.ForEach(partitioner, (range, state) =>
  150. filler.Value.FillBuffer(data.Scan0 + data.Stride * range.Item1, data.Scan0 + data.Stride * range.Item2)
  151. );
  152. }
  153. }
  154.  
  155. // Adapted version of fast XorShift
  156. // https://bitbucket.org/rstarkov/demoxorshift/src/tip/Xorshift.cs?fileviewer=file-view-default
  157. sealed class RndPixelFiller
  158. {
  159. static readonly uint[] pixels = Enumerable
  160. .Range(0, 8 /* (2 ^ 3) RGB combinations */)
  161. .Select(MaskToArgb).ToArray();
  162.  
  163. static uint MaskToArgb(int mask)
  164. {
  165. return ((mask & 4) == 4 ? 0xffff0000 : 0xff000000) |
  166. ((mask & 2) == 2 ? 0xff00ff00 : 0xff000000) |
  167. ((mask & 1) == 1 ? 0xff0000ff : 0xff000000);
  168. }
  169.  
  170. uint _x = 123456789;
  171. uint _y = 362436069;
  172. uint _z = 521288629;
  173. uint _w = 88675123;
  174.  
  175. public unsafe void FillBuffer(IntPtr start, IntPtr end)
  176. {
  177. uint* pbuf = (uint*)start;
  178. uint* pend = (uint*)end;
  179.  
  180. uint* pendQuads = (pend - (pend - pbuf) % 4);
  181. while (pbuf < pendQuads)
  182. {
  183. uint tx = _x ^ (_x << 11);
  184. uint ty = _y ^ (_y << 11);
  185. uint tz = _z ^ (_z << 11);
  186. uint tw = _w ^ (_w << 11);
  187. *(pbuf++) = pixels[(_x = _w ^ (_w >> 19) ^ (tx ^ (tx >> 8))) % 8];
  188. *(pbuf++) = pixels[(_y = _x ^ (_x >> 19) ^ (ty ^ (ty >> 8))) % 8];
  189. *(pbuf++) = pixels[(_z = _y ^ (_y >> 19) ^ (tz ^ (tz >> 8))) % 8];
  190. *(pbuf++) = pixels[(_w = _z ^ (_z >> 19) ^ (tw ^ (tw >> 8))) % 8];
  191. }
  192.  
  193. if (pbuf < pend)
  194. {
  195. uint t = _x ^ (_x << 11);
  196. _x = _y; _y = _z; _z = _w;
  197. t = _w = _w ^ (_w >> 19) ^ (t ^ (t >> 8));
  198.  
  199. while (true)
  200. {
  201. *(pbuf++) = pixels[(t & 0xFF) % 8];
  202. if (pbuf == pend) break;
  203. t >>= 8;
  204. }
  205. }
  206. }
  207.  
  208. /*public static unsafe void TestFill()
  209. {
  210. var b = new uint[7];
  211. fixed (uint* pb = b)
  212. {
  213. var p = new IntPtr(pb);
  214. new RndPixelFiller()
  215. .FillBuffer(p, IntPtr.Add(p, b.Length * sizeof(uint)));
  216. }
  217. }*/
  218. }
  219.  
  220. [DebuggerDisplay("Avg = {Avg}, Max = {Max}, Min = {Min}, Cnt = {SamplesCount}")]
  221. public sealed class TimeStats
  222. {
  223. private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
  224.  
  225. public TimeSpan Max { get; private set; }
  226. public TimeSpan Min { get; private set; }
  227. public TimeSpan Avg { get; private set; }
  228. public long SamplesCount { get; private set; }
  229.  
  230. public void BeginSample()
  231. {
  232. _stopwatch.Restart();
  233. }
  234.  
  235. public TimeSpan EndSample()
  236. {
  237. var sample = _stopwatch.Elapsed;
  238. AddSample(sample);
  239. return sample;
  240. }
  241.  
  242. public void Combine(TimeStats that)
  243. {
  244. if (that.SamplesCount == 0)
  245. {
  246. return;
  247. }
  248. if (this.SamplesCount == 0)
  249. {
  250. this.Max = that.Max;
  251. this.Min = that.Min;
  252. this.Avg = that.Avg;
  253. this.SamplesCount = that.SamplesCount;
  254. }
  255. else
  256. {
  257. var totalSamplesCount = this.SamplesCount + that.SamplesCount;
  258. this.Max = TimeSpan.FromTicks(Math.Max(this.Max.Ticks, that.Max.Ticks));
  259. this.Min = TimeSpan.FromTicks(Math.Min(this.Min.Ticks, that.Min.Ticks));
  260. this.Avg = TimeSpan.FromTicks((long)
  261. (this.Avg.Ticks * ((double)this.SamplesCount / totalSamplesCount)
  262. + that.Avg.Ticks * ((double)that.SamplesCount / totalSamplesCount))
  263. );
  264. this.SamplesCount = totalSamplesCount;
  265. }
  266. }
  267.  
  268. public static TimeStats operator +(TimeStats stats1, TimeStats stats2)
  269. {
  270. var combinedStats = new TimeStats();
  271. combinedStats.Combine(stats1);
  272. combinedStats.Combine(stats2);
  273. return combinedStats;
  274. }
  275.  
  276. public void AddSample(TimeSpan sample)
  277. {
  278. var samplesCount = ++SamplesCount;
  279. if (samplesCount == 1)
  280. {
  281. Max = sample;
  282. Min = sample;
  283. Avg = sample;
  284. }
  285. else
  286. {
  287. Max = TimeSpan.FromTicks(Math.Max(Max.Ticks, sample.Ticks));
  288. Min = TimeSpan.FromTicks(Math.Min(Min.Ticks, sample.Ticks));
  289. Avg = TimeSpan.FromTicks((Avg.Ticks * (samplesCount - 1) + sample.Ticks) / samplesCount);
  290. }
  291. }
  292. }
  293.  
  294. static class Program
  295. {
  296. /// <summary>
  297. /// The main entry point for the application.
  298. /// </summary>
  299. [STAThread]
  300. static void Main()
  301. {
  302. Application.EnableVisualStyles();
  303. Application.SetCompatibleTextRenderingDefault(false);
  304. Application.Run(new StuckPixelFixForm());
  305. }
  306. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement