mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-20 10:29:30 -05:00
AtlasEngine: Fix several error handling bugs (#17193)
This fixes:
* `HRESULT`s not being shown as unsigned hex
* `D2DERR_RECREATE_TARGET` not being handled
* 4 calls not checking their `HRESULT` return
Out of the 4 only `CreateCompatibleRenderTarget` will throw in
practice, however it throws `D2DERR_RECREATE_TARGET` which is common.
Without this error handling, AtlasEngine may crash.
* Set Graphics API to Direct2D
* Use `DXGIAdapterRemovalSupportTest.exe` to trigger
`D2DERR_RECREATE_TARGET`
* No error message is shown ✅
* If the `D2DERR_RECREATE_TARGET` handling is removed, the application
never crashes due to `cursorRenderTarget` being `nullptr` ✅
(cherry picked from commit b31059e53e)
Service-Card-Id: 92500372
Service-Version: 1.20
This commit is contained in:
committed by
Dustin L. Howett
parent
345d266350
commit
ed2923ba8c
@@ -995,7 +995,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||||||
winrt::fire_and_forget TermControl::_RendererWarning(IInspectable /*sender*/,
|
winrt::fire_and_forget TermControl::_RendererWarning(IInspectable /*sender*/,
|
||||||
Control::RendererWarningArgs args)
|
Control::RendererWarningArgs args)
|
||||||
{
|
{
|
||||||
const auto hr = static_cast<HRESULT>(args.Result());
|
// HRESULT is a signed 32-bit integer which would result in a hex output like "-0x7766FFF4",
|
||||||
|
// but canonically HRESULTs are displayed unsigned as "0x8899000C". See GH#11556.
|
||||||
|
const auto hr = std::bit_cast<uint32_t>(args.Result());
|
||||||
|
|
||||||
auto weakThis{ get_weak() };
|
auto weakThis{ get_weak() };
|
||||||
co_await wil::resume_foreground(Dispatcher());
|
co_await wil::resume_foreground(Dispatcher());
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ catch (const wil::ResultException& exception)
|
|||||||
{
|
{
|
||||||
const auto hr = exception.GetErrorCode();
|
const auto hr = exception.GetErrorCode();
|
||||||
|
|
||||||
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
|
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET || hr == D2DERR_RECREATE_TARGET)
|
||||||
{
|
{
|
||||||
_p.dxgi = {};
|
_p.dxgi = {};
|
||||||
return E_PENDING;
|
return E_PENDING;
|
||||||
|
|||||||
@@ -148,11 +148,11 @@ void BackendD2D::_handleSettingsUpdate(const RenderingPayload& p)
|
|||||||
_viewportCellCount = p.s->viewportCellCount;
|
_viewportCellCount = p.s->viewportCellCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackendD2D::_drawBackground(const RenderingPayload& p) noexcept
|
void BackendD2D::_drawBackground(const RenderingPayload& p)
|
||||||
{
|
{
|
||||||
if (_backgroundBitmapGeneration != p.colorBitmapGenerations[0])
|
if (_backgroundBitmapGeneration != p.colorBitmapGenerations[0])
|
||||||
{
|
{
|
||||||
_backgroundBitmap->CopyFromMemory(nullptr, p.backgroundBitmap.data(), gsl::narrow_cast<UINT32>(p.colorBitmapRowStride * sizeof(u32)));
|
THROW_IF_FAILED(_backgroundBitmap->CopyFromMemory(nullptr, p.backgroundBitmap.data(), gsl::narrow_cast<UINT32>(p.colorBitmapRowStride * sizeof(u32))));
|
||||||
_backgroundBitmapGeneration = p.colorBitmapGenerations[0];
|
_backgroundBitmapGeneration = p.colorBitmapGenerations[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,7 +350,7 @@ f32r BackendD2D::_getGlyphRunDesignBounds(const DWRITE_GLYPH_RUN& glyphRun, f32
|
|||||||
_glyphMetrics = Buffer<DWRITE_GLYPH_METRICS>{ size };
|
_glyphMetrics = Buffer<DWRITE_GLYPH_METRICS>{ size };
|
||||||
}
|
}
|
||||||
|
|
||||||
glyphRun.fontFace->GetDesignGlyphMetrics(glyphRun.glyphIndices, glyphRun.glyphCount, _glyphMetrics.data(), false);
|
THROW_IF_FAILED(glyphRun.fontFace->GetDesignGlyphMetrics(glyphRun.glyphIndices, glyphRun.glyphCount, _glyphMetrics.data(), false));
|
||||||
|
|
||||||
const f32 fontScale = glyphRun.fontEmSize / fontMetrics.designUnitsPerEm;
|
const f32 fontScale = glyphRun.fontEmSize / fontMetrics.designUnitsPerEm;
|
||||||
f32r accumulatedBounds{
|
f32r accumulatedBounds{
|
||||||
@@ -535,7 +535,8 @@ void BackendD2D::_resizeCursorBitmap(const RenderingPayload& p, const til::size
|
|||||||
const D2D1_SIZE_F sizeF{ static_cast<f32>(newSizeInPx.width), static_cast<f32>(newSizeInPx.height) };
|
const D2D1_SIZE_F sizeF{ static_cast<f32>(newSizeInPx.width), static_cast<f32>(newSizeInPx.height) };
|
||||||
const D2D1_SIZE_U sizeU{ gsl::narrow_cast<UINT32>(newSizeInPx.width), gsl::narrow_cast<UINT32>(newSizeInPx.height) };
|
const D2D1_SIZE_U sizeU{ gsl::narrow_cast<UINT32>(newSizeInPx.width), gsl::narrow_cast<UINT32>(newSizeInPx.height) };
|
||||||
wil::com_ptr<ID2D1BitmapRenderTarget> cursorRenderTarget;
|
wil::com_ptr<ID2D1BitmapRenderTarget> cursorRenderTarget;
|
||||||
_renderTarget->CreateCompatibleRenderTarget(&sizeF, &sizeU, nullptr, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, cursorRenderTarget.addressof());
|
THROW_IF_FAILED(_renderTarget->CreateCompatibleRenderTarget(&sizeF, &sizeU, nullptr, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, cursorRenderTarget.addressof()));
|
||||||
|
|
||||||
cursorRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
|
cursorRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
|
||||||
|
|
||||||
cursorRenderTarget->BeginDraw();
|
cursorRenderTarget->BeginDraw();
|
||||||
@@ -547,7 +548,7 @@ void BackendD2D::_resizeCursorBitmap(const RenderingPayload& p, const til::size
|
|||||||
}
|
}
|
||||||
THROW_IF_FAILED(cursorRenderTarget->EndDraw());
|
THROW_IF_FAILED(cursorRenderTarget->EndDraw());
|
||||||
|
|
||||||
cursorRenderTarget->GetBitmap(_cursorBitmap.put());
|
THROW_IF_FAILED(cursorRenderTarget->GetBitmap(_cursorBitmap.put()));
|
||||||
_cursorBitmapSize = newSize;
|
_cursorBitmapSize = newSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace Microsoft::Console::Render::Atlas
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
ATLAS_ATTR_COLD void _handleSettingsUpdate(const RenderingPayload& p);
|
ATLAS_ATTR_COLD void _handleSettingsUpdate(const RenderingPayload& p);
|
||||||
void _drawBackground(const RenderingPayload& p) noexcept;
|
void _drawBackground(const RenderingPayload& p);
|
||||||
void _drawText(RenderingPayload& p);
|
void _drawText(RenderingPayload& p);
|
||||||
ATLAS_ATTR_COLD f32 _drawTextPrepareLineRendition(const RenderingPayload& p, const ShapedRow* row, f32 baselineY) const noexcept;
|
ATLAS_ATTR_COLD f32 _drawTextPrepareLineRendition(const RenderingPayload& p, const ShapedRow* row, f32 baselineY) const noexcept;
|
||||||
ATLAS_ATTR_COLD void _drawTextResetLineRendition(const ShapedRow* row) const noexcept;
|
ATLAS_ATTR_COLD void _drawTextResetLineRendition(const ShapedRow* row) const noexcept;
|
||||||
|
|||||||
Reference in New Issue
Block a user