mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-11 13:56:33 -06:00
atlas,d2d: overdraw background bitmap by one cell on all sides (#17674)
BackendD2D will now draw one extra cell on all sides when rendering the background, filled with the expected background color, starting at (-1, -1) to ensure that cell backgrounds do not bleed over the edges of the viewport where the is swapchain but no content. Fixes #17672
This commit is contained in:
parent
07c7167535
commit
9007fc2894
@ -80,6 +80,7 @@ void BackendD2D::_handleSettingsUpdate(const RenderingPayload& p)
|
|||||||
const auto renderTargetChanged = !_renderTarget;
|
const auto renderTargetChanged = !_renderTarget;
|
||||||
const auto fontChanged = _fontGeneration != p.s->font.generation();
|
const auto fontChanged = _fontGeneration != p.s->font.generation();
|
||||||
const auto cursorChanged = _cursorGeneration != p.s->cursor.generation();
|
const auto cursorChanged = _cursorGeneration != p.s->cursor.generation();
|
||||||
|
const auto backgroundColorChanged = _miscGeneration != p.s->misc.generation();
|
||||||
const auto cellCountChanged = _viewportCellCount != p.s->viewportCellCount;
|
const auto cellCountChanged = _viewportCellCount != p.s->viewportCellCount;
|
||||||
|
|
||||||
if (renderTargetChanged)
|
if (renderTargetChanged)
|
||||||
@ -125,7 +126,7 @@ void BackendD2D::_handleSettingsUpdate(const RenderingPayload& p)
|
|||||||
_builtinGlyphsRenderTargetActive = false;
|
_builtinGlyphsRenderTargetActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderTargetChanged || fontChanged || cellCountChanged)
|
if (renderTargetChanged || fontChanged || cellCountChanged || backgroundColorChanged)
|
||||||
{
|
{
|
||||||
const D2D1_BITMAP_PROPERTIES props{
|
const D2D1_BITMAP_PROPERTIES props{
|
||||||
.pixelFormat = { DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED },
|
.pixelFormat = { DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED },
|
||||||
@ -133,18 +134,40 @@ void BackendD2D::_handleSettingsUpdate(const RenderingPayload& p)
|
|||||||
.dpiY = static_cast<f32>(p.s->font->dpi),
|
.dpiY = static_cast<f32>(p.s->font->dpi),
|
||||||
};
|
};
|
||||||
const D2D1_SIZE_U size{
|
const D2D1_SIZE_U size{
|
||||||
p.s->viewportCellCount.x,
|
p.s->viewportCellCount.x + 2u,
|
||||||
p.s->viewportCellCount.y,
|
p.s->viewportCellCount.y + 2u,
|
||||||
};
|
};
|
||||||
const D2D1_MATRIX_3X2_F transform{
|
const D2D1_MATRIX_3X2_F transform{
|
||||||
.m11 = static_cast<f32>(p.s->font->cellSize.x),
|
.m11 = static_cast<f32>(p.s->font->cellSize.x),
|
||||||
.m22 = static_cast<f32>(p.s->font->cellSize.y),
|
.m22 = static_cast<f32>(p.s->font->cellSize.y),
|
||||||
|
/* Brushes are transformed relative to the render target, not the rect into which they are painted. */
|
||||||
|
.dx = -static_cast<f32>(p.s->font->cellSize.x),
|
||||||
|
.dy = -static_cast<f32>(p.s->font->cellSize.y),
|
||||||
};
|
};
|
||||||
THROW_IF_FAILED(_renderTarget->CreateBitmap(size, nullptr, 0, &props, _backgroundBitmap.put()));
|
|
||||||
|
/*
|
||||||
|
We're allocating a bitmap that is one pixel wider on every side than the viewport so that we can fill in the gutter
|
||||||
|
with the background color. D2D doesn't have an equivalent to D3D11_TEXTURE_ADDRESS_BORDER, which we use in the D3D
|
||||||
|
backend to ensure the colors don't bleed off the edges.
|
||||||
|
|
||||||
|
XXXXXXXXXXXXXXXX <- background color
|
||||||
|
X+------------+X
|
||||||
|
X| viewport |X
|
||||||
|
X| |X
|
||||||
|
X| |X
|
||||||
|
X+------------+X
|
||||||
|
XXXXXXXXXXXXXXXX
|
||||||
|
|
||||||
|
The translation in `transform` ensures that we render it off the top left of the render target.
|
||||||
|
*/
|
||||||
|
auto backgroundFill = std::make_unique_for_overwrite<u32[]>(static_cast<size_t>(size.width) * size.height);
|
||||||
|
std::fill_n(backgroundFill.get(), size.width * size.height, u32ColorPremultiply(p.s->misc->backgroundColor));
|
||||||
|
|
||||||
|
THROW_IF_FAILED(_renderTarget->CreateBitmap(size, backgroundFill.get(), size.width * sizeof(u32), &props, _backgroundBitmap.put()));
|
||||||
THROW_IF_FAILED(_renderTarget->CreateBitmapBrush(_backgroundBitmap.get(), _backgroundBrush.put()));
|
THROW_IF_FAILED(_renderTarget->CreateBitmapBrush(_backgroundBitmap.get(), _backgroundBrush.put()));
|
||||||
_backgroundBrush->SetInterpolationMode(D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
|
_backgroundBrush->SetInterpolationMode(D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
|
||||||
_backgroundBrush->SetExtendModeX(D2D1_EXTEND_MODE_MIRROR);
|
_backgroundBrush->SetExtendModeX(D2D1_EXTEND_MODE_CLAMP);
|
||||||
_backgroundBrush->SetExtendModeY(D2D1_EXTEND_MODE_MIRROR);
|
_backgroundBrush->SetExtendModeY(D2D1_EXTEND_MODE_CLAMP);
|
||||||
_backgroundBrush->SetTransform(&transform);
|
_backgroundBrush->SetTransform(&transform);
|
||||||
_backgroundBitmapGeneration = {};
|
_backgroundBitmapGeneration = {};
|
||||||
}
|
}
|
||||||
@ -158,6 +181,7 @@ void BackendD2D::_handleSettingsUpdate(const RenderingPayload& p)
|
|||||||
_generation = p.s.generation();
|
_generation = p.s.generation();
|
||||||
_fontGeneration = p.s->font.generation();
|
_fontGeneration = p.s->font.generation();
|
||||||
_cursorGeneration = p.s->cursor.generation();
|
_cursorGeneration = p.s->cursor.generation();
|
||||||
|
_miscGeneration = p.s->misc.generation();
|
||||||
_viewportCellCount = p.s->viewportCellCount;
|
_viewportCellCount = p.s->viewportCellCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +189,13 @@ void BackendD2D::_drawBackground(const RenderingPayload& p)
|
|||||||
{
|
{
|
||||||
if (_backgroundBitmapGeneration != p.colorBitmapGenerations[0])
|
if (_backgroundBitmapGeneration != p.colorBitmapGenerations[0])
|
||||||
{
|
{
|
||||||
THROW_IF_FAILED(_backgroundBitmap->CopyFromMemory(nullptr, p.backgroundBitmap.data(), gsl::narrow_cast<UINT32>(p.colorBitmapRowStride * sizeof(u32))));
|
const D2D1_RECT_U rect{
|
||||||
|
1u,
|
||||||
|
1u,
|
||||||
|
1u + p.s->viewportCellCount.x,
|
||||||
|
1u + p.s->viewportCellCount.y,
|
||||||
|
};
|
||||||
|
THROW_IF_FAILED(_backgroundBitmap->CopyFromMemory(&rect, p.backgroundBitmap.data(), gsl::narrow_cast<UINT32>(p.colorBitmapRowStride * sizeof(u32))));
|
||||||
_backgroundBitmapGeneration = p.colorBitmapGenerations[0];
|
_backgroundBitmapGeneration = p.colorBitmapGenerations[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -67,6 +67,7 @@ namespace Microsoft::Console::Render::Atlas
|
|||||||
til::generation_t _generation;
|
til::generation_t _generation;
|
||||||
til::generation_t _fontGeneration;
|
til::generation_t _fontGeneration;
|
||||||
til::generation_t _cursorGeneration;
|
til::generation_t _cursorGeneration;
|
||||||
|
til::generation_t _miscGeneration;
|
||||||
u16x2 _viewportCellCount{};
|
u16x2 _viewportCellCount{};
|
||||||
|
|
||||||
#if ATLAS_DEBUG_SHOW_DIRTY
|
#if ATLAS_DEBUG_SHOW_DIRTY
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user