private unsafe void RenderTileWorkItem(PointInt32 tileOffset) { IBitmap <ColorPbgra32> bitmap; bool isCancelled = false; bool flag = false; Exception error = null; isCancelled |= this.IsTileRenderingCancelled(tileOffset); if (isCancelled) { bitmap = null; } else { RectInt32 tileSourceRect = this.tileMathHelper.GetTileSourceRect(tileOffset); SizeInt32 tileBufferSize = this.GetTileBufferSize(tileOffset); bitmap = RetryManager.Eval <IBitmap <ColorPbgra32> >(3, () => BitmapAllocator.Pbgra32.Allocate(tileBufferSize, AllocationOptions.Default), delegate(Exception _) { CleanupManager.RequestCleanup(); Thread.Sleep(200); CleanupManager.WaitForPendingCleanup(); }, delegate(AggregateException ex) { throw new AggregateException($"could not allocate a bitmap of size {tileBufferSize.Width} x {tileBufferSize.Height}", ex).Flatten(); }); if (this.source != null) { try { isCancelled |= this.IsTileRenderingCancelled(tileOffset); if (!isCancelled) { using (IBitmapLock <ColorPbgra32> @lock = bitmap.Lock <ColorPbgra32>(BitmapLockOptions.ReadWrite)) { if (this.mipLevel == 0) { this.source.CopyPixels(new RectInt32?(tileSourceRect), @lock); RenderingKernels.ConvertBgra32ToPbgra32((uint *)@lock.Scan0, tileBufferSize.Width, tileBufferSize.Height, @lock.Stride); flag = true; } else { BitmapInterpolationMode linear; if (!this.isHighQuality) { linear = BitmapInterpolationMode.Linear; } else if (this.mipLevel == 1) { linear = BitmapInterpolationMode.Linear; } else { linear = BitmapInterpolationMode.Fant; } IImagingFactory instance = ImagingFactory.Instance; ICancellationToken cancelToken = CancellationTokenUtil.Create((Func <bool>)(() => (isCancelled | this.IsTileRenderingCancelled(tileOffset)))); int copyHeightLog2 = Math.Max(3, 7 - this.mipLevel); using (ClippedBitmapSource <ColorBgra32> source2 = new ClippedBitmapSource <ColorBgra32>(this.source, tileSourceRect)) { using (CancellableBitmapSource <ColorBgra32> source3 = new CancellableBitmapSource <ColorBgra32>(source2, r => this.tileMathHelper.EnumerateTilesClippedToSourceRect(r), null, cancelToken)) { using (IBitmapSource <ColorPbgra32> source4 = CreateBufferedTileScaler(instance, source3, tileBufferSize.Width, tileBufferSize.Height, linear)) { using (CancellableBitmapSource <ColorPbgra32> source5 = new CancellableBitmapSource <ColorPbgra32>(source4, r => TileRectSplitter(r, ((int)1) << copyHeightLog2), null, cancelToken)) { try { source5.CopyPixels <ColorPbgra32>(@lock); flag = true; } catch (OperationCanceledException exception2) { error = exception2; isCancelled = true; } catch (Exception exception3) { error = exception3; throw; } } } } } } isCancelled |= this.IsTileRenderingCancelled(tileOffset); if (isCancelled) { flag = false; } } if (!flag) { DisposableUtil.Free <IBitmap <ColorPbgra32> >(ref bitmap); } } } catch (OperationCanceledException exception4) { error = exception4; isCancelled = true; } catch (Exception exception5) { error = exception5; isCancelled |= this.IsTileRenderingCancelled(tileOffset); if (!isCancelled) { using (IDrawingContext context = DrawingContext.FromBitmap(bitmap, FactorySource.PerThread)) { context.Clear(new ColorRgba128Float?((ColorRgba128Float)Colors.White)); string text = exception5.ToString(); using (ISystemFonts fonts = new SystemFonts(true)) { TextLayout textLayout = UIText.CreateLayout(context, text, fonts.Caption, null, HotkeyRenderMode.Ignore, (double)bitmap.Size.Width, 65535.0); textLayout.FontSize *= 0.6; textLayout.WordWrapping = WordWrapping.Wrap; context.DrawTextLayout(PointDouble.Zero, textLayout, SolidColorBrushCache.Get((ColorRgba128Float)Colors.Black), DrawTextOptions.None); } } flag = true; } } } } isCancelled |= this.IsTileRenderingCancelled(tileOffset); if (isCancelled) { DisposableUtil.Free <IBitmap <ColorPbgra32> >(ref bitmap); } RenderedTileInfo info = new RenderedTileInfo(bitmap, !isCancelled && (bitmap > null), error); if (!this.tilesRenderedQueue.TryEnqueue(tileOffset, info)) { ExceptionUtil.ThrowInternalErrorException("Could not enqueue to this.tilesRenderedQueue"); } if (Interlocked.Exchange(ref this.isProcessTileRenderedQueueQueued, 1) == 0) { this.syncContext.Post(this.processTileRenderedQueueCallback); } }
public bool ProcessTileRenderedQueue() { base.VerifyAccess(); using (this.processTileRenderedQueueRegion.UseEnterScope()) { if (this.IsDisposed) { bool flag = false; do { KeyValuePair <PointInt32, RenderedTileInfo> pair; while (this.tilesRenderedQueue.TryDequeue(out pair)) { DisposableUtil.Free <IBitmap <ColorPbgra32> >(ref pair.Value.Buffer); flag = true; } }while (Interlocked.Exchange(ref this.isProcessTileRenderedQueueQueued, 0) == 1); return(flag); } if (Interlocked.Exchange(ref this.isProcessTileRenderedQueueQueued, 0) == 0) { return(false); } List <PointInt32> collection = new List <PointInt32>(); List <PointInt32> cancelledTileOffsets = null; bool flag3 = false; int count = this.tilesRenderedQueue.Count; for (int i = 0; i < count; i++) { KeyValuePair <PointInt32, RenderedTileInfo> pair2; if (this.tilesRenderedQueue.TryDequeue(out pair2)) { PointInt32 key = pair2.Key; RenderedTileInfo info2 = pair2.Value; IBitmap <ColorPbgra32> buffer = info2.Buffer; if (this.tilesRenderingCancelledSet.Remove(key) || !info2.Completed) { DisposableUtil.Free <IBitmap <ColorPbgra32> >(ref buffer); if (this.tilesRenderQueue.Contains(key)) { flag3 = true; } else if (info2.Error is OperationCanceledException) { if (cancelledTileOffsets == null) { cancelledTileOffsets = new List <PointInt32>(); } cancelledTileOffsets.Add(key); } } else { if ((buffer.IsNullReference <IBitmap <ColorPbgra32> >() || buffer.IsDisposed) || !pair2.Value.Completed) { throw new PaintDotNet.InternalErrorException(); } IBitmap <ColorPbgra32> disposeMe = this.tileBuffers[key.Y][key.X]; DisposableUtil.Free <IBitmap <ColorPbgra32> >(ref disposeMe); this.tileBuffers[key.Y][key.X] = buffer; this.tileIsValid[key.Y][key.X] = true; collection.Add(key); } if (!this.tilesRenderingSet.Remove(key)) { throw new PaintDotNet.InternalErrorException(); } } } if (collection.Any <PointInt32>()) { this.owner.NotifyTileCacheFinishedRendering <List <PointInt32> >(this, collection); } if (flag3) { this.ProcessTileRenderQueue(); } if (!this.tilesRenderingSet.Any <PointInt32>()) { this.owner.NotifyTileCacheIsIdle(this); } if (cancelledTileOffsets != null) { this.syncContext.Post(delegate(object _) { this.InvalidateCancelledTiles(cancelledTileOffsets); }); } return(collection.Any <PointInt32>()); } }