WIP: Put padding in the atlas engine

TODO:
- [ ] the background texture gets rendered in the wrong place
- [ ] clean up the weird "updatedpi" thing
- [ ] handle Leonard's request to move the add after the M to get FMA
- [ ] actually use it in TermControl lel
This commit is contained in:
Dustin L. Howett
2023-08-11 10:32:34 -05:00
parent a5d916f5d3
commit eec8dbd6d7
9 changed files with 48 additions and 10 deletions

View File

@@ -194,6 +194,10 @@ void AtlasEngine::_invalidateSpans(std::span<const til::point_span> spans, const
if (_api.s->font->dpi != newDPI)
{
_api.s.write()->font.write()->dpi = newDPI;
_api.s.write()->misc.write()->topLeftOffset = {
.x = _api.topLeftOffsetInDip.x * (_api.s->font->dpi / USER_DEFAULT_SCREEN_DPI),
.y = _api.topLeftOffsetInDip.y * (_api.s->font->dpi / USER_DEFAULT_SCREEN_DPI),
};
}
return S_OK;
@@ -900,3 +904,15 @@ void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, Fo
_api.s.write()->font.write()->fontCollection = std::move(collection);
return true;
}
void AtlasEngine::SetPadding(float x, float y) noexcept
{
if (_api.topLeftOffsetInDip.x != x || _api.topLeftOffsetInDip.y != y)
{
_api.topLeftOffsetInDip = { x, y };
_api.s.write()->misc.write()->topLeftOffset = {
.x = _api.topLeftOffsetInDip.x * (_api.s->font->dpi / USER_DEFAULT_SCREEN_DPI),
.y = _api.topLeftOffsetInDip.y * (_api.s->font->dpi / USER_DEFAULT_SCREEN_DPI),
};
}
}

View File

@@ -57,6 +57,7 @@ namespace Microsoft::Console::Render::Atlas
[[nodiscard]] HRESULT IsGlyphWideByFont(std::wstring_view glyph, _Out_ bool* pResult) noexcept override;
[[nodiscard]] HRESULT UpdateTitle(std::wstring_view newTitle) noexcept override;
void UpdateHyperlinkHoveredId(uint16_t hoveredId) noexcept override;
void SetPadding(float x, float y) noexcept override;
// getter
[[nodiscard]] std::wstring_view GetPixelShaderPath() noexcept;
@@ -181,6 +182,9 @@ namespace Microsoft::Console::Render::Atlas
// The position of the viewport inside the text buffer (in cells).
u16x2 viewportOffset{ 0, 0 };
// SetPadding()
f32x2 topLeftOffsetInDip{ 0.f, 0.f };
} _api;
};
}

View File

@@ -40,6 +40,8 @@ void BackendD2D::Render(RenderingPayload& p)
_handleSettingsUpdate(p);
}
const D2D1_MATRIX_3X2_F worldTransform{ _getDefaultTransform(p) };
_renderTarget->BeginDraw();
try
{
@@ -48,6 +50,7 @@ void BackendD2D::Render(RenderingPayload& p)
_renderTarget->Clear();
#endif
_drawBackground(p);
_renderTarget->SetTransform(&worldTransform);
_drawCursorPart1(p);
_drawText(p);
_drawCursorPart2(p);
@@ -318,7 +321,7 @@ void BackendD2D::_drawText(RenderingPayload& p)
if (row->lineRendition != LineRendition::SingleWidth)
{
_drawTextResetLineRendition(row);
_drawTextResetLineRendition(p, row);
}
if (row->bitmap.revision != 0)
@@ -505,17 +508,15 @@ void BackendD2D::_flushBuiltinGlyphs()
f32 BackendD2D::_drawTextPrepareLineRendition(const RenderingPayload& p, const ShapedRow* row, f32 baselineY) const noexcept
{
const auto lineRendition = row->lineRendition;
D2D1_MATRIX_3X2_F transform{
.m11 = 2.0f,
.m22 = 1.0f,
};
D2D1_MATRIX_3X2_F transform{ _getDefaultTransform(p) };
transform.m11 = 2.0f; // scale horizontally by 2.0
if (lineRendition >= LineRendition::DoubleHeightTop)
{
D2D1_RECT_F clipRect{ 0, 0, static_cast<f32>(p.s->targetSize.x), static_cast<f32>(p.s->targetSize.y) };
transform.m22 = 2.0f;
transform.dy = -1.0f * (baselineY + p.s->font->descender);
transform.dy += -1.0f * (baselineY + p.s->font->descender);
// If you print the top half of a double height row (DECDHL), the expectation is that only
// the top half is visible, which requires us to keep the clip rect at the bottom of the row.
@@ -539,9 +540,9 @@ f32 BackendD2D::_drawTextPrepareLineRendition(const RenderingPayload& p, const S
return baselineY;
}
void BackendD2D::_drawTextResetLineRendition(const ShapedRow* row) const noexcept
void BackendD2D::_drawTextResetLineRendition(const RenderingPayload& p, const ShapedRow* row) const noexcept
{
static constexpr D2D1_MATRIX_3X2_F identity{ .m11 = 1, .m22 = 1 };
const auto identity{ _getDefaultTransform(p) };
_renderTarget->SetTransform(&identity);
if (row->lineRendition >= LineRendition::DoubleHeightTop)
@@ -1005,4 +1006,14 @@ void BackendD2D::_fillRectangle(const D2D1_RECT_F& rect, u32 color)
_renderTarget->FillRectangle(&rect, brush);
}
D2D_MATRIX_3X2_F BackendD2D::_getDefaultTransform(const RenderingPayload& p) const noexcept
{
return {
.m11 = 1.f,
.m22 = 1.f,
.dx = p.s->misc->topLeftOffset.x,
.dy = p.s->misc->topLeftOffset.y,
};
}
TIL_FAST_MATH_END

View File

@@ -25,7 +25,7 @@ namespace Microsoft::Console::Render::Atlas
D2D1_RECT_U _prepareBuiltinGlyph(const RenderingPayload& p, char32_t ch, u32 off);
void _flushBuiltinGlyphs();
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 RenderingPayload& p, const ShapedRow* row) const noexcept;
ATLAS_ATTR_COLD f32r _getGlyphRunDesignBounds(const DWRITE_GLYPH_RUN& glyphRun, f32 baselineX, f32 baselineY);
ATLAS_ATTR_COLD void _drawGridlineRow(const RenderingPayload& p, const ShapedRow* row, u16 y);
ATLAS_ATTR_COLD void _drawBitmap(const RenderingPayload& p, const ShapedRow* row, u16 y) const;
@@ -40,6 +40,8 @@ namespace Microsoft::Console::Render::Atlas
ATLAS_ATTR_COLD ID2D1SolidColorBrush* _brushWithColorUpdate(u32 color);
void _fillRectangle(const D2D1_RECT_F& rect, u32 color);
D2D_MATRIX_3X2_F _getDefaultTransform(const RenderingPayload& p) const noexcept;
wil::com_ptr<ID2D1DeviceContext> _renderTarget;
wil::com_ptr<ID2D1DeviceContext4> _renderTarget4; // Optional. Supported since Windows 10 14393.
wil::com_ptr<ID2D1StrokeStyle> _dottedStrokeStyle;

View File

@@ -576,6 +576,7 @@ void BackendD3D::_recreateConstBuffer(const RenderingPayload& p) const
{
VSConstBuffer data{};
data.positionScale = { 2.0f / p.s->targetSize.x, -2.0f / p.s->targetSize.y };
data.padding = { p.s->misc->topLeftOffset.x, p.s->misc->topLeftOffset.y, 0.f, 0.f };
p.deviceContext->UpdateSubresource(_vsConstantBuffer.get(), 0, nullptr, &data, 0, 0);
}
{

View File

@@ -29,6 +29,7 @@ namespace Microsoft::Console::Render::Atlas
// padding so that it is {u32; u32; u32; <4 byte padding>; u32x2}.
// * bool will probably not work the way you want it to,
// because HLSL uses 32-bit bools and C++ doesn't.
alignas(sizeof(f32x4)) f32x4 padding;
alignas(sizeof(f32x2)) f32x2 positionScale;
#pragma warning(suppress : 4324) // 'VSConstBuffer': structure was padded due to alignment specifier
};

View File

@@ -399,6 +399,7 @@ namespace Microsoft::Console::Render::Atlas
std::wstring customPixelShaderPath;
std::wstring customPixelShaderImagePath;
bool useRetroTerminalEffect = false;
f32x2 topLeftOffset{ 0.f, 0.f };
};
struct Settings

View File

@@ -5,6 +5,7 @@
cbuffer ConstBuffer : register(b0)
{
float4 padding;
float2 positionScale;
}
@@ -18,7 +19,7 @@ PSData main(VSData data)
output.renditionScale = data.renditionScale;
// positionScale is expected to be float2(2.0f / sizeInPixel.x, -2.0f / sizeInPixel.y). Together with the
// addition below this will transform our "position" from pixel into normalized device coordinate (NDC) space.
output.position.xy = (data.position + data.vertex.xy * data.size) * positionScale + float2(-1.0f, 1.0f);
output.position.xy = (padding.xy + data.position + data.vertex.xy * data.size) * positionScale + float2(-1.0f, 1.0f);
output.position.zw = float2(0, 1);
output.texcoord = data.texcoord + data.vertex.xy * data.size;
return output;

View File

@@ -94,6 +94,7 @@ namespace Microsoft::Console::Render
[[nodiscard]] virtual HRESULT IsGlyphWideByFont(std::wstring_view glyph, _Out_ bool* pResult) noexcept = 0;
[[nodiscard]] virtual HRESULT UpdateTitle(std::wstring_view newTitle) noexcept = 0;
virtual void UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept = 0;
virtual void SetPadding(float x, float y) noexcept = 0;
};
}
#pragma warning(pop)