## Summary of the Pull Request Renderer: Add support for backoff and auto-disable on failed retry This commit introduces a backoff (150ms * number of tries) to the renderer's retry logic (introduced in #2830). It also changes the FAIL_FAST to a less globally-harmful render thread disable, so that we stop blowing up any application hosting a terminal when the graphics driver goes away. In addition, it adds a callback that a Renderer consumer can use to determine when the renderer _has_ failed, and a public method to kick it back into life. Fixes #5340. This PR also wires up TermControl so that it shows some UI when the renderer tastes clay. ![image](https://user-images.githubusercontent.com/14316954/79266118-f073f680-7e4b-11ea-8b96-5588a13aff3b.png) ![image](https://user-images.githubusercontent.com/14316954/79266125-f36ee700-7e4b-11ea-9314-4280e9149461.png) ## PR Checklist * [x] Closes #5340 * [x] cla * [ ] Tests added/passed * [ ] Requires documentation to be updated * [x] I've discussed this with core contributors already. ## Validation Steps Performed I tested this by dropping the number of retries to 1 and forcing a TDR while doing `wsl cmatrix -u0`. It picked up exactly where it left off. As a bonus, you can actually still type into the terminal when it's graphically suspended (and `exit` still works.). The block is _entirely graphical_.
141 lines
5.4 KiB
C++
141 lines
5.4 KiB
C++
/*++
|
|
Copyright (c) Microsoft Corporation
|
|
Licensed under the MIT license.
|
|
|
|
Module Name:
|
|
- Renderer.hpp
|
|
|
|
Abstract:
|
|
- This is the definition of our renderer.
|
|
- It provides interfaces for the console application to notify when various portions of the console state have changed and need to be redrawn.
|
|
- It requires a data interface to fetch relevant console structures required for drawing and a drawing engine target for output.
|
|
|
|
Author(s):
|
|
- Michael Niksa (MiNiksa) 17-Nov-2015
|
|
--*/
|
|
|
|
#pragma once
|
|
|
|
#include "../inc/IRenderer.hpp"
|
|
#include "../inc/IRenderEngine.hpp"
|
|
#include "../inc/IRenderData.hpp"
|
|
|
|
#include "thread.hpp"
|
|
|
|
#include "../../buffer/out/textBuffer.hpp"
|
|
#include "../../buffer/out/CharRow.hpp"
|
|
|
|
namespace Microsoft::Console::Render
|
|
{
|
|
class Renderer sealed : public IRenderer
|
|
{
|
|
public:
|
|
Renderer(IRenderData* pData,
|
|
_In_reads_(cEngines) IRenderEngine** const pEngine,
|
|
const size_t cEngines,
|
|
std::unique_ptr<IRenderThread> thread);
|
|
|
|
[[nodiscard]] static HRESULT s_CreateInstance(IRenderData* pData,
|
|
_In_reads_(cEngines) IRenderEngine** const rgpEngines,
|
|
const size_t cEngines,
|
|
_Outptr_result_nullonfailure_ Renderer** const ppRenderer);
|
|
|
|
[[nodiscard]] static HRESULT s_CreateInstance(IRenderData* pData,
|
|
_Outptr_result_nullonfailure_ Renderer** const ppRenderer);
|
|
|
|
virtual ~Renderer() override;
|
|
|
|
[[nodiscard]] HRESULT PaintFrame();
|
|
|
|
void TriggerSystemRedraw(const RECT* const prcDirtyClient) override;
|
|
void TriggerRedraw(const Microsoft::Console::Types::Viewport& region) override;
|
|
void TriggerRedraw(const COORD* const pcoord) override;
|
|
void TriggerRedrawCursor(const COORD* const pcoord) override;
|
|
void TriggerRedrawAll() override;
|
|
void TriggerTeardown() override;
|
|
|
|
void TriggerSelection() override;
|
|
void TriggerScroll() override;
|
|
void TriggerScroll(const COORD* const pcoordDelta) override;
|
|
|
|
void TriggerCircling() override;
|
|
void TriggerTitleChange() override;
|
|
|
|
void TriggerFontChange(const int iDpi,
|
|
const FontInfoDesired& FontInfoDesired,
|
|
_Out_ FontInfo& FontInfo) override;
|
|
|
|
[[nodiscard]] HRESULT GetProposedFont(const int iDpi,
|
|
const FontInfoDesired& FontInfoDesired,
|
|
_Out_ FontInfo& FontInfo) override;
|
|
|
|
bool IsGlyphWideByFont(const std::wstring_view glyph) override;
|
|
|
|
void EnablePainting() override;
|
|
void WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs) override;
|
|
|
|
void AddRenderEngine(_In_ IRenderEngine* const pEngine) override;
|
|
|
|
void SetRendererEnteredErrorStateCallback(std::function<void()> pfn);
|
|
void ResetErrorStateAndResume();
|
|
|
|
private:
|
|
std::deque<IRenderEngine*> _rgpEngines;
|
|
|
|
IRenderData* _pData; // Non-ownership pointer
|
|
|
|
std::unique_ptr<IRenderThread> _pThread;
|
|
bool _destructing = false;
|
|
|
|
void _NotifyPaintFrame();
|
|
|
|
[[nodiscard]] HRESULT _PaintFrameForEngine(_In_ IRenderEngine* const pEngine) noexcept;
|
|
|
|
bool _CheckViewportAndScroll();
|
|
|
|
[[nodiscard]] HRESULT _PaintBackground(_In_ IRenderEngine* const pEngine);
|
|
|
|
void _PaintBufferOutput(_In_ IRenderEngine* const pEngine);
|
|
|
|
void _PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine,
|
|
TextBufferCellIterator it,
|
|
const COORD target,
|
|
const bool lineWrapped);
|
|
|
|
static IRenderEngine::GridLines s_GetGridlines(const TextAttribute& textAttribute) noexcept;
|
|
|
|
void _PaintBufferOutputGridLineHelper(_In_ IRenderEngine* const pEngine,
|
|
const TextAttribute textAttribute,
|
|
const size_t cchLine,
|
|
const COORD coordTarget);
|
|
|
|
void _PaintSelection(_In_ IRenderEngine* const pEngine);
|
|
void _PaintCursor(_In_ IRenderEngine* const pEngine);
|
|
|
|
void _PaintOverlays(_In_ IRenderEngine* const pEngine);
|
|
void _PaintOverlay(IRenderEngine& engine, const RenderOverlay& overlay);
|
|
|
|
[[nodiscard]] HRESULT _UpdateDrawingBrushes(_In_ IRenderEngine* const pEngine, const TextAttribute attr, const bool isSettingDefaultBrushes);
|
|
|
|
[[nodiscard]] HRESULT _PerformScrolling(_In_ IRenderEngine* const pEngine);
|
|
|
|
SMALL_RECT _srViewportPrevious;
|
|
|
|
std::vector<SMALL_RECT> _GetSelectionRects() const;
|
|
void _ScrollPreviousSelection(const til::point delta);
|
|
std::vector<SMALL_RECT> _previousSelection;
|
|
|
|
[[nodiscard]] HRESULT _PaintTitle(IRenderEngine* const pEngine);
|
|
|
|
// Helper functions to diagnose issues with painting and layout.
|
|
// These are only actually effective/on in Debug builds when the flag is set using an attached debugger.
|
|
bool _fDebug = false;
|
|
|
|
std::function<void()> _pfnRendererEnteredErrorState;
|
|
|
|
#ifdef UNIT_TESTING
|
|
friend class ConptyOutputTests;
|
|
#endif
|
|
};
|
|
}
|