protected void ApplyLoop(ISurface src, ISurface dst, Rectangle roi, CancellationToken token, IRenderProgress progress) { src.BeginUpdate(); dst.BeginUpdate(); var completed_lines = new bool[roi.Height]; var last_completed_index = 0; if (Settings.SingleThreaded || roi.Height <= 1) { for (var y = roi.Y; y <= roi.Bottom; ++y) { if (token.IsCancellationRequested) { return; } var dstPtr = dst.GetPointAddress(roi.X, y); var srcPtr = src.GetPointAddress(roi.X, y); Apply(srcPtr, dstPtr, roi.Width); completed_lines[y - roi.Top] = true; if (progress != null) { var last_y = FindLastCompletedLine(completed_lines, last_completed_index); last_completed_index = last_y; progress.CompletedRoi = new Rectangle(roi.X, roi.Y, roi.Width, last_y); progress.PercentComplete = (float)last_y / (float)roi.Height; } } } else { ParallelExtensions.OrderedFor(roi.Y, roi.Bottom + 1, token, (y) => { var dstPtr = dst.GetPointAddress(roi.X, y); var srcPtr = src.GetPointAddress(roi.X, y); Apply(srcPtr, dstPtr, roi.Width); completed_lines[y - roi.Top] = true; if (progress != null) { var last_y = FindLastCompletedLine(completed_lines, last_completed_index); last_completed_index = last_y; progress.CompletedRoi = new Rectangle(roi.X, roi.Y, roi.Width, last_y); progress.PercentComplete = (float)last_y / (float)roi.Height; } }); } src.EndUpdate(); dst.EndUpdate(); }
protected unsafe virtual void RenderLoop(ISurface surface, Rectangle roi, CancellationToken token, IRenderProgress progress) { var dst = new ColorBgra[surface.Height * surface.Width]; fixed(ColorBgra *dst_ptr = dst) { var dst_wrap = new ColorBgraArrayWrapper(dst_ptr, surface.Width, surface.Height); surface.BeginUpdate(); dst_wrap.BeginUpdate(); OnBeginRender(surface, dst_wrap, roi); var completed_lines = new bool[roi.Height]; var last_completed_index = 0; if (Settings.SingleThreaded || roi.Height <= 1) { for (var y = roi.Y; y <= roi.Bottom; ++y) { if (token.IsCancellationRequested) { return; } RenderLine(surface, dst_wrap, new Rectangle(roi.X, y, roi.Width, 1)); completed_lines[y - roi.Top] = true; if (progress != null) { var last_y = FindLastCompletedLine(completed_lines, last_completed_index); last_completed_index = last_y; progress.CompletedRoi = new Rectangle(roi.X, roi.Y, roi.Width, last_y); progress.PercentComplete = (float)last_y / (float)roi.Height; } } } else { ParallelExtensions.OrderedFor(roi.Y, roi.Bottom + 1, token, (y) => { RenderLine(surface, dst_wrap, new Rectangle(roi.X, y, roi.Width, 1)); completed_lines[y - roi.Top] = true; if (progress != null) { var last_y = FindLastCompletedLine(completed_lines, last_completed_index); last_completed_index = last_y; progress.CompletedRoi = new Rectangle(roi.X, roi.Y, roi.Width, last_y); progress.PercentComplete = (float)last_y / (float)roi.Height; } }); } // Copy the result from our temp destination back into the source var op = new IdentityOp(); op.ApplyAsync(dst_wrap, surface, token).Wait(); surface.EndUpdate(); dst_wrap.EndUpdate(); } }