Browse Source

Reworked rendering

pull/2117/head
Nikita Tsukanov 8 years ago
parent
commit
36915d6c94
  1. 146
      src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

146
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@ -205,99 +205,105 @@ namespace Avalonia.Rendering
internal void UnitTestUpdateScene() => UpdateScene();
internal void UnitTestRender() => Render(_scene.Item, false, false);
internal void UnitTestRender() => Render(false);
private void Render(bool forceComposite)
{
using (var l = _lock.TryLock())
if (l != null)
{
bool reRun = false;
do
{
IRef<Scene> scene;
lock (_sceneLock)
scene = _scene?.Clone();
using (scene)
reRun = Render(scene?.Item, forceComposite, reRun);
} while (reRun);
}
}
private bool Render(Scene scene, bool forceComposite, bool reUpdating)
{
bool renderOverlay = DrawDirtyRects || DrawFps;
bool composite = false;
if (RenderTarget == null)
{
RenderTarget = ((IRenderRoot)_root).CreateRenderTarget();
}
if (renderOverlay)
{
_dirtyRectsDisplay.Tick();
}
if (l == null)
return;
try
{
if (scene != null && scene.Size != Size.Empty)
IDrawingContextImpl context = null;
try
{
IDrawingContextImpl context = null;
if (scene.Generation != _lastSceneId)
try
{
context = RenderTarget.CreateDrawingContext(this);
Layers.Update(scene, context);
RenderToLayers(scene);
if (DebugFramesPath != null)
IDrawingContextImpl GetContext()
{
SaveDebugFrames(scene.Generation);
}
if (context != null)
return context;
if (RenderTarget == null)
RenderTarget = ((IRenderRoot)_root).CreateRenderTarget();
return context = RenderTarget.CreateDrawingContext(this);
lock (_sceneLock)
_lastSceneId = scene.Generation;
}
// We have consumed the previously available scene, but there might be some dirty
// rects since the last update. *If* we are on UI thread, we can force immediate scene
// rebuild before rendering anything on-screen
// By returning true we indicate that this method should be called again
if (!reUpdating && Dispatcher.UIThread.CheckAccess() && NeedsUpdate)
var (scene, updated) = UpdateRenderLayersAndConsumeSceneIfNeeded(GetContext);
using (scene)
{
UpdateScene();
return true;
var overlay = DrawDirtyRects || DrawFps;
if (DrawDirtyRects)
_dirtyRectsDisplay.Tick();
if (overlay)
RenderOverlay(scene.Item, GetContext());
if (updated || forceComposite || overlay)
RenderComposite(scene.Item, GetContext());
}
composite = true;
}
if (renderOverlay)
finally
{
context = context ?? RenderTarget.CreateDrawingContext(this);
RenderOverlay(scene, context);
RenderComposite(scene, context);
context?.Dispose();
}
else if (composite || forceComposite)
}
catch (RenderTargetCorruptedException ex)
{
Logging.Logger.Information("Renderer", this, "Render target was corrupted. Exception: {0}", ex);
RenderTarget?.Dispose();
RenderTarget = null;
}
}
}
private (IRef<Scene> scene, bool updated) UpdateRenderLayersAndConsumeSceneIfNeeded(Func<IDrawingContextImpl> contextFactory,
bool recursiveCall = false)
{
IRef<Scene> sceneRef;
lock (_sceneLock)
sceneRef = _scene?.Clone();
if (sceneRef == null)
return (null, false);
using (sceneRef)
{
var scene = sceneRef.Item;
if (scene.Generation != _lastSceneId)
{
var context = contextFactory();
Layers.Update(scene, context);
RenderToLayers(scene);
if (DebugFramesPath != null)
{
context = context ?? RenderTarget.CreateDrawingContext(this);
RenderComposite(scene, context);
SaveDebugFrames(scene.Generation);
}
context?.Dispose();
lock (_sceneLock)
_lastSceneId = scene.Generation;
// We have consumed the previously available scene, but there might be some dirty
// rects since the last update. *If* we are on UI thread, we can force immediate scene
// rebuild before rendering anything on-screen
// We are calling the same method recursively here
if (!recursiveCall && Dispatcher.UIThread.CheckAccess() && NeedsUpdate)
{
UpdateScene();
var (rs, _) = UpdateRenderLayersAndConsumeSceneIfNeeded(contextFactory, true);
return (rs, true);
}
// Indicate that we have updated the layers
return (sceneRef.Clone(), true);
}
// Just return scene, layers weren't updated
return (sceneRef.Clone(), false);
}
catch (RenderTargetCorruptedException ex)
{
Logging.Logger.Information("Renderer", this, "Render target was corrupted. Exception: {0}", ex);
RenderTarget?.Dispose();
RenderTarget = null;
}
return false;
}
private void Render(IDrawingContextImpl context, VisualNode node, IVisual layer, Rect clipBounds)
{
if (layer == null || node.LayerRoot == layer)

Loading…
Cancel
Save