Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

atlas: draw selection colors as background/foreground instead of alpha overlay #17725

Merged
merged 4 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/cascadia/TerminalControl/HwndTerminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,7 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
renderSettings.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, theme.DefaultForeground);
renderSettings.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, theme.DefaultBackground);

publicTerminal->_renderEngine->SetSelectionBackground(theme.DefaultSelectionBackground, theme.SelectionBackgroundAlpha);
publicTerminal->_renderEngine->SetSelectionBackground(theme.DefaultSelectionBackground);

// Set the font colors
for (size_t tableIndex = 0; tableIndex < 16; tableIndex++)
Expand Down
1 change: 0 additions & 1 deletion src/cascadia/TerminalControl/HwndTerminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ typedef struct _TerminalTheme
COLORREF DefaultBackground;
COLORREF DefaultForeground;
COLORREF DefaultSelectionBackground;
float SelectionBackgroundAlpha;
uint32_t CursorStyle; // This will be converted to DispatchTypes::CursorStyle (size_t), but C# cannot marshal an enum type and have it fit in a size_t.
COLORREF ColorTable[16];
} TerminalTheme, *LPTerminalTheme;
Expand Down
5 changes: 0 additions & 5 deletions src/cascadia/WpfTerminalControl/TerminalTheme.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,6 @@ public struct TerminalTheme
/// </summary>
public uint DefaultSelectionBackground;

/// <summary>
/// The opacity alpha for the selection color of the terminal, must be between 1.0 and 0.0.
/// </summary>
public float SelectionBackgroundAlpha;

/// <summary>
/// The style of cursor to use in the terminal.
/// </summary>
Expand Down
1 change: 0 additions & 1 deletion src/cascadia/WpfTerminalTestNetCore/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ private void Terminal_Loaded(object sender, RoutedEventArgs e)
DefaultBackground = 0x0c0c0c,
DefaultForeground = 0xcccccc,
DefaultSelectionBackground = 0xcccccc,
SelectionBackgroundAlpha = 0.5f,
CursorStyle = CursorStyle.BlinkingBar,
// This is Campbell.
ColorTable = new uint[] { 0x0C0C0C, 0x1F0FC5, 0x0EA113, 0x009CC1, 0xDA3700, 0x981788, 0xDD963A, 0xCCCCCC, 0x767676, 0x5648E7, 0x0CC616, 0xA5F1F9, 0xFF783B, 0x9E00B4, 0xD6D661, 0xF2F2F2 },
Expand Down
10 changes: 7 additions & 3 deletions src/renderer/atlas/AtlasEngine.api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "Backend.h"
#include "../../buffer/out/textBuffer.hpp"
#include "../base/FontCache.h"
#include "../../types/inc/ColorFix.hpp"

// #### NOTE ####
// If you see any code in here that contains "_r." you might be seeing a race condition.
Expand Down Expand Up @@ -424,12 +425,15 @@ void AtlasEngine::SetRetroTerminalEffect(bool enable) noexcept
}
}

void AtlasEngine::SetSelectionBackground(const COLORREF color, const float alpha) noexcept
void AtlasEngine::SetSelectionBackground(const COLORREF color) noexcept
{
const u32 selectionColor = (color & 0xffffff) | gsl::narrow_cast<u32>(lrintf(alpha * 255.0f)) << 24;
const u32 selectionColor = (color & 0xffffff) | 0xff000000;
if (_api.s->misc->selectionColor != selectionColor)
{
_api.s.write()->misc.write()->selectionColor = selectionColor;
auto misc = _api.s.write()->misc.write();
misc->selectionColor = selectionColor;
// Selection Foreground is based on the default foreground; it is also updated in UpdateDrawingBrushes
misc->selectionForeground = 0xff000000 | ColorFix::GetPerceivableColor(misc->foregroundColor, color, 0.5f * 0.5f);
}
}

Expand Down
48 changes: 23 additions & 25 deletions src/renderer/atlas/AtlasEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "DWriteTextAnalysis.h"
#include "../../interactivity/win32/CustomWindowMessages.h"

#include "../types/inc/ColorFix.hpp"

// #### NOTE ####
// This file should only contain methods that are only accessed by the caller of Present() (the "Renderer" class).
// Basically this file poses the "synchronization" point between the concurrently running
Expand Down Expand Up @@ -311,6 +313,8 @@ CATCH_RETURN()
_api.searchHighlightFocused = { info.searchHighlightFocused, 1 };
}
}

_api.selectionSpans = til::point_span_subspan_within_rect(info.selectionSpans, dr);
}

return S_OK;
Expand Down Expand Up @@ -411,9 +415,10 @@ try
const auto end = isFinalRow ? std::min(hiEnd.x + 1, x2) : x2;
_fillColorBitmap(row, x1, end, fgColor, bgColor);

// Return early if we couldn't paint the whole region. We will resume
// from here in the next call.
if (!isFinalRow || end == x2)
// Return early if we couldn't paint the whole region (either this was not the last row, or
// it was the last row but the highlight ends outside of our x range.)
// We will resume from here in the next call.
if (!isFinalRow || hiEnd.x /*inclusive*/ >= x2 /*exclusive*/)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the thing it took hours to fix lol

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, Ahh, hmm. Thanks for fixing this 🥲😃

{
return S_OK;
}
Expand Down Expand Up @@ -497,6 +502,7 @@ try
// Apply the highlighting colors to the highlighted cells
RETURN_IF_FAILED(_drawHighlighted(_api.searchHighlights, y, x, columnEnd, highlightFg, highlightBg));
RETURN_IF_FAILED(_drawHighlighted(_api.searchHighlightFocused, y, x, columnEnd, highlightFocusFg, highlightFocusBg));
RETURN_IF_FAILED(_drawHighlighted(_api.selectionSpans, y, x, columnEnd, _api.s->misc->selectionForeground, _api.s->misc->selectionColor));

_api.lastPaintBufferLineCoord = { x, y };
return S_OK;
Expand Down Expand Up @@ -563,28 +569,9 @@ try
CATCH_RETURN()

[[nodiscard]] HRESULT AtlasEngine::PaintSelection(const til::rect& rect) noexcept
try
{
// Unfortunately there's no step after Renderer::_PaintBufferOutput that
// would inform us that it's done with the last AtlasEngine::PaintBufferLine.
// As such we got to call _flushBufferLine() here just to be sure.
_flushBufferLine();

const auto y = gsl::narrow_cast<u16>(clamp<til::CoordType>(rect.top, 0, _p.s->viewportCellCount.y - 1));
const auto from = gsl::narrow_cast<u16>(clamp<til::CoordType>(rect.left, 0, _p.s->viewportCellCount.x - 1));
const auto to = gsl::narrow_cast<u16>(clamp<til::CoordType>(rect.right, from, _p.s->viewportCellCount.x));

auto& row = *_p.rows[y];
row.selectionFrom = from;
row.selectionTo = to;

_p.dirtyRectInPx.left = std::min(_p.dirtyRectInPx.left, from * _p.s->font->cellSize.x);
_p.dirtyRectInPx.top = std::min(_p.dirtyRectInPx.top, y * _p.s->font->cellSize.y);
_p.dirtyRectInPx.right = std::max(_p.dirtyRectInPx.right, to * _p.s->font->cellSize.x);
_p.dirtyRectInPx.bottom = std::max(_p.dirtyRectInPx.bottom, _p.dirtyRectInPx.top + _p.s->font->cellSize.y);
return S_OK;
}
CATCH_RETURN()

[[nodiscard]] HRESULT AtlasEngine::PaintCursor(const CursorOptions& options) noexcept
try
Expand Down Expand Up @@ -661,10 +648,21 @@ try
_api.currentForeground = gsl::narrow_cast<u32>(fg);
_api.attributes = attributes;
}
else if (textAttributes.BackgroundIsDefault() && bg != _api.s->misc->backgroundColor)
else
{
_api.s.write()->misc.write()->backgroundColor = bg;
_p.s.write()->misc.write()->backgroundColor = bg;
if (textAttributes.BackgroundIsDefault() && bg != _api.s->misc->backgroundColor)
{
_api.s.write()->misc.write()->backgroundColor = bg;
_p.s.write()->misc.write()->backgroundColor = bg;
}

if (textAttributes.GetForeground().IsDefault() && fg != _api.s->misc->foregroundColor)
{
auto misc = _api.s.write()->misc.write();
misc->foregroundColor = fg;
// Selection Foreground is based on the default foreground; it is also updated in SetSelectionColor
misc->selectionForeground = 0xff000000 | ColorFix::GetPerceivableColor(fg, misc->selectionColor, 0.5f * 0.5f);
}
}

return S_OK;
Expand Down
3 changes: 2 additions & 1 deletion src/renderer/atlas/AtlasEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ namespace Microsoft::Console::Render::Atlas
void SetPixelShaderPath(std::wstring_view value) noexcept;
void SetPixelShaderImagePath(std::wstring_view value) noexcept;
void SetRetroTerminalEffect(bool enable) noexcept;
void SetSelectionBackground(COLORREF color, float alpha = 0.5f) noexcept;
void SetSelectionBackground(COLORREF color) noexcept;
void SetSoftwareRendering(bool enable) noexcept;
void SetDisablePartialInvalidation(bool enable) noexcept;
void SetGraphicsAPI(GraphicsAPI graphicsAPI) noexcept;
Expand Down Expand Up @@ -171,6 +171,7 @@ namespace Microsoft::Console::Render::Atlas
// These tracks the highlighted regions on the screen that are yet to be painted.
std::span<const til::point_span> searchHighlights;
std::span<const til::point_span> searchHighlightFocused;
std::span<const til::point_span> selectionSpans;

// dirtyRect is a computed value based on invalidatedRows.
til::rect dirtyRect;
Expand Down
21 changes: 0 additions & 21 deletions src/renderer/atlas/BackendD2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ void BackendD2D::Render(RenderingPayload& p)
_drawCursorPart1(p);
_drawText(p);
_drawCursorPart2(p);
_drawSelection(p);
#if ATLAS_DEBUG_SHOW_DIRTY
_debugShowDirty(p);
#endif
Expand Down Expand Up @@ -938,26 +937,6 @@ void BackendD2D::_drawCursor(const RenderingPayload& p, ID2D1RenderTarget* rende
}
}

void BackendD2D::_drawSelection(const RenderingPayload& p)
{
u16 y = 0;
for (const auto& row : p.rows)
{
if (row->selectionTo > row->selectionFrom)
{
const D2D1_RECT_F rect{
static_cast<f32>(p.s->font->cellSize.x * row->selectionFrom),
static_cast<f32>(p.s->font->cellSize.y * y),
static_cast<f32>(p.s->font->cellSize.x * row->selectionTo),
static_cast<f32>(p.s->font->cellSize.y * (y + 1)),
};
_fillRectangle(rect, p.s->misc->selectionColor);
}

y++;
}
}

#if ATLAS_DEBUG_SHOW_DIRTY
void BackendD2D::_debugShowDirty(const RenderingPayload& p)
{
Expand Down
42 changes: 1 addition & 41 deletions src/renderer/atlas/BackendD3D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,6 @@ void BackendD3D::Render(RenderingPayload& p)
_drawBackground(p);
_drawCursorBackground(p);
_drawText(p);
_drawSelection(p);
_debugShowDirty(p);
_flushQuads(p);

Expand Down Expand Up @@ -2248,45 +2247,6 @@ size_t BackendD3D::_drawCursorForegroundSlowPath(const CursorRect& c, size_t off
return addedInstances;
}

void BackendD3D::_drawSelection(const RenderingPayload& p)
{
u16 y = 0;
u16 lastFrom = 0;
u16 lastTo = 0;

for (const auto& row : p.rows)
{
if (row->selectionTo > row->selectionFrom)
{
// If the current selection line matches the previous one, we can just extend the previous quad downwards.
// The way this is implemented isn't very smart, but we also don't have very many rows to iterate through.
if (row->selectionFrom == lastFrom && row->selectionTo == lastTo)
{
_getLastQuad().size.y += p.s->font->cellSize.y;
}
else
{
_appendQuad() = {
.shadingType = static_cast<u16>(ShadingType::Selection),
.position = {
static_cast<i16>(p.s->font->cellSize.x * row->selectionFrom),
static_cast<i16>(p.s->font->cellSize.y * y),
},
.size = {
static_cast<u16>(p.s->font->cellSize.x * (row->selectionTo - row->selectionFrom)),
static_cast<u16>(p.s->font->cellSize.y),
},
.color = p.s->misc->selectionColor,
};
lastFrom = row->selectionFrom;
lastTo = row->selectionTo;
}
}

y++;
}
}

void BackendD3D::_debugShowDirty(const RenderingPayload& p)
{
#if ATLAS_DEBUG_SHOW_DIRTY
Expand All @@ -2302,7 +2262,7 @@ void BackendD3D::_debugShowDirty(const RenderingPayload& p)
{
const auto& rect = _presentRects[(_presentRectsPos + i) % std::size(_presentRects)];
_appendQuad() = {
.shadingType = static_cast<u16>(ShadingType::Selection),
.shadingType = static_cast<u16>(ShadingType::FilledRect),
.position = {
static_cast<i16>(rect.left),
static_cast<i16>(rect.top),
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/atlas/BackendD3D.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ namespace Microsoft::Console::Render::Atlas
SolidLine,

Cursor,
Selection,
FilledRect,

TextDrawingFirst = TextGrayscale,
TextDrawingLast = SolidLine,
Expand Down
8 changes: 3 additions & 5 deletions src/renderer/atlas/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,9 @@ namespace Microsoft::Console::Render::Atlas
struct MiscellaneousSettings
{
u32 backgroundColor = 0;
u32 selectionColor = 0x7fffffff;
u32 foregroundColor = 0;
u32 selectionColor = 0xffffffff;
u32 selectionForeground = 0xff000000;
std::wstring customPixelShaderPath;
std::wstring customPixelShaderImagePath;
bool useRetroTerminalEffect = false;
Expand Down Expand Up @@ -475,8 +477,6 @@ namespace Microsoft::Console::Render::Atlas
bitmap.active = false;
gridLineRanges.clear();
lineRendition = LineRendition::SingleWidth;
selectionFrom = 0;
selectionTo = 0;
dirtyTop = y * cellHeight;
dirtyBottom = dirtyTop + cellHeight;
}
Expand All @@ -496,8 +496,6 @@ namespace Microsoft::Console::Render::Atlas
Bitmap bitmap;
std::vector<GridLineRange> gridLineRanges;
LineRendition lineRendition = LineRendition::SingleWidth;
u16 selectionFrom = 0;
u16 selectionTo = 0;
til::CoordType dirtyTop = 0;
til::CoordType dirtyBottom = 0;
};
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/atlas/shader_common.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#define SHADING_TYPE_CURLY_LINE 7
#define SHADING_TYPE_SOLID_LINE 8
#define SHADING_TYPE_CURSOR 9
#define SHADING_TYPE_SELECTION 10
#define SHADING_TYPE_FILLED_RECT 10
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better name would be A-OK with me


struct VSData
{
Expand Down
Loading