Skip to content

Commit 7c68357

Browse files
committed
Unit test cursor blink control
1 parent 7086366 commit 7c68357

File tree

5 files changed

+63
-35
lines changed

5 files changed

+63
-35
lines changed

src/CDI/Video/Renderer.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,7 @@ bool Renderer::isValidDisplayFormat(const DisplayFormat display) noexcept
3030
void Renderer::IncrementCursorTime(const double ns) noexcept
3131
{
3232
if(!m_cursorEnabled || m_cursorBlinkOff == 0)
33-
{
34-
m_cursorIsOn = true; // Reset to true if blink is disabled during the off/complement pattern.
3533
return; // OFF == 0 means ON indefinitely.
36-
}
3734

3835
double delta = m_60FPS ? DELTA_60FPS : DELTA_50FPS;
3936
if(m_cursorIsOn)

src/CDI/Video/Renderer.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,24 @@ class Renderer
224224
LoadImageContributionFactorB = 0xDC,
225225
};
226226

227-
protected:
228227
static constexpr double DELTA_50FPS = 240'000'000.; /**< GB VII.2.3.4.2 GC_Blnk. */
229228
static constexpr double DELTA_60FPS = 200'000'000.; /**< GB VII.2.3.4.2 GC_Blnk. */
230229

230+
protected:
231231
double m_cursorTime{0.0}; /**< Keeps track of the emulated time for cursor blink. */
232232
bool m_cursorIsOn{true}; /**< Keeps the state of the cursor (ON or OFF/complement). true when ON. */
233+
constexpr Pixel GetCursorColor() const noexcept
234+
{
235+
Pixel color = backdropCursorColorToPixel(m_cursorColor);
236+
if(m_cursorBlinkOff != 0 && !m_cursorIsOn)
237+
{
238+
if(m_cursorBlinkType) // Complement.
239+
color = color.Complement();
240+
else
241+
color = BLACK_PIXEL;
242+
}
243+
return color;
244+
}
233245

234246
uint16_t m_lineNumber{}; /**< Current line being drawn, starts at 0. Handled by the caller. */
235247
DisplayFormat m_displayFormat{DisplayFormat::PAL}; /**< Used to select 360/384 width and 240/280 height. */

src/CDI/Video/RendererSIMD.cpp

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ std::pair<uint16_t, uint16_t> RendererSIMD::DrawLine(const uint8_t* lineA, const
3535
m_lineNumber = lineNumber;
3636
if(m_lineNumber == 0)
3737
{
38-
uint16_t width = getDisplayWidth(m_displayFormat);
39-
uint16_t height = GetDisplayHeight();
38+
const uint16_t width = getDisplayWidth(m_displayFormat);
39+
const uint16_t height = GetDisplayHeight();
4040

4141
m_screen.m_width = m_plane[A].m_width = m_plane[B].m_width = width * 2;
4242
m_screen.m_height = m_plane[A].m_height = m_plane[B].m_height = m_backdropPlane.m_height = height;
@@ -131,17 +131,8 @@ uint16_t RendererSIMD::DrawLinePlane(const uint8_t* lineMain, const uint8_t* lin
131131
void RendererSIMD::DrawCursor() noexcept
132132
{
133133
// Technically speaking the cursor is drawn when the drawing line number is the cursor's one (because video
134-
// is outputted continuously line by line).
135-
// But for here maybe we don't care.
136-
137-
Pixel color = backdropCursorColorToPixel(m_cursorColor);
138-
if(!m_cursorIsOn)
139-
{
140-
if(m_cursorBlinkType) // Complement.
141-
color = color.Complement();
142-
else
143-
color = BLACK_PIXEL;
144-
}
134+
// is outputted continuously line by line). But for here maybe we don't care.
135+
const Pixel color = GetCursorColor();
145136

146137
using SIMDCursorLine = stdx::fixed_size_simd<uint32_t, 16>;
147138
using SIMDCursorLineMask = SIMDCursorLine::mask_type;
@@ -505,8 +496,7 @@ void RendererSIMD::HandleOverlayMixSIMD() noexcept
505496
}
506497

507498
// Both planes always have the same width.
508-
constexpr int simdSize = static_cast<int>(SIMD_SIZE);
509-
for(int width = static_cast<int>(m_plane[A].m_width); width >= simdSize; width -= simdSize,
499+
for(size_t width = m_plane[A].m_width; width >= SIMD_SIZE; width -= SIMD_SIZE,
510500
planeFront += SIMD_SIZE, planeBack += SIMD_SIZE, icfFront += SIMD_SIZE, icfBack += SIMD_SIZE, screen += SIMD_SIZE)
511501
{
512502
if constexpr(MIX) // Mixing.

src/CDI/Video/RendererSoftware.cpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ std::pair<uint16_t, uint16_t> RendererSoftware::DrawLine(const uint8_t* lineA, c
2424
m_lineNumber = lineNumber;
2525
if(m_lineNumber == 0)
2626
{
27-
uint16_t width = getDisplayWidth(m_displayFormat);
28-
uint16_t height = GetDisplayHeight();
27+
const uint16_t width = getDisplayWidth(m_displayFormat);
28+
const uint16_t height = GetDisplayHeight();
2929

3030
m_screen.m_width = m_plane[A].m_width = m_plane[B].m_width = width * 2;
3131
m_screen.m_height = m_plane[A].m_height = m_plane[B].m_height = m_backdropPlane.m_height = height;
@@ -120,16 +120,8 @@ uint16_t RendererSoftware::DrawLinePlane(const uint8_t* lineMain, const uint8_t*
120120
void RendererSoftware::DrawCursor() noexcept
121121
{
122122
// Technically speaking the cursor is drawn when the drawing line number is the cursor's one (because video
123-
// is outputted continuously line by line).
124-
// But for here maybe we don't care.
125-
Pixel color = backdropCursorColorToPixel(m_cursorColor);
126-
if(!m_cursorIsOn)
127-
{
128-
if(m_cursorBlinkType) // Complement.
129-
color = color.Complement();
130-
else
131-
color = BLACK_PIXEL;
132-
}
123+
// is outputted continuously line by line). But for here maybe we don't care.
124+
const Pixel color = GetCursorColor();
133125

134126
Plane::iterator it = m_cursorPlane.begin();
135127
for(size_t y = 0; y < m_cursorPlane.m_height; ++y)

tests/testRenderer.cpp

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,43 @@ TEST_CASE("Cursor blink", "[Video]")
2222
Video::RendererSoftware rendererSoft;
2323
IF_SIMD(Video::RendererSIMD rendererSIMD)
2424

25+
SECTION("Control")
26+
{
27+
constexpr CursorLine EXPECTED_ON{
28+
CYAN, BLACK, CYAN, BLACK, CYAN, BLACK, CYAN, BLACK,
29+
BLACK, CYAN, BLACK, CYAN, BLACK, CYAN, BLACK, CYAN,
30+
};
31+
constexpr CursorLine EXPECTED_OFF{
32+
BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK,
33+
BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK, BLACK,
34+
};
35+
36+
// No need to test SIMD, as the control code is in Renderer.
37+
rendererSoft.SetCursorEnabled(true);
38+
rendererSoft.SetCursorBlink(false, 1, 1);
39+
rendererSoft.SetCursorPattern(0, 0xAA55);
40+
rendererSoft.SetCursorColor(0b1011); // Cyan
41+
rendererSoft.SetDisplayFormat(Video::Renderer::DisplayFormat::PAL, false, false); // 50 FPS.
42+
43+
rendererSoft.RenderFrame();
44+
REQUIRE(std::equal(rendererSoft.m_cursorPlane.begin(), rendererSoft.m_cursorPlane.begin() + 16, EXPECTED_ON.data()));
45+
46+
// Advance time to just before the off period.
47+
rendererSoft.IncrementCursorTime(Video::Renderer::DELTA_50FPS - 1.);
48+
rendererSoft.RenderFrame();
49+
REQUIRE(std::equal(rendererSoft.m_cursorPlane.begin(), rendererSoft.m_cursorPlane.begin() + 16, EXPECTED_ON.data()));
50+
51+
// Advance time to exactly the delta time.
52+
rendererSoft.IncrementCursorTime(1.);
53+
rendererSoft.RenderFrame();
54+
REQUIRE(std::equal(rendererSoft.m_cursorPlane.begin(), rendererSoft.m_cursorPlane.begin() + 16, EXPECTED_OFF.data()));
55+
56+
// Make sure the cursor is on when blink is deactivated on an off/complement period.
57+
rendererSoft.SetCursorBlink(false, 1, 0); // Disable blink.
58+
rendererSoft.RenderFrame();
59+
REQUIRE(std::equal(rendererSoft.m_cursorPlane.begin(), rendererSoft.m_cursorPlane.begin() + 16, EXPECTED_ON.data()));
60+
}
61+
2562
SECTION("ON/OFF")
2663
{
2764
rendererSoft.SetCursorEnabled(true);
@@ -45,9 +82,9 @@ TEST_CASE("Cursor blink", "[Video]")
4582
REQUIRE(std::equal(rendererSoft.m_cursorPlane.begin(), rendererSoft.m_cursorPlane.begin() + 16, EXPECTED_ON.data()));
4683
IF_SIMD(REQUIRE(std::equal(rendererSIMD.m_cursorPlane.begin(), rendererSIMD.m_cursorPlane.begin() + 16, EXPECTED_ON.data())))
4784

48-
rendererSoft.IncrementCursorTime(240'000'000.);
85+
rendererSoft.IncrementCursorTime(Video::Renderer::DELTA_50FPS);
4986
rendererSoft.RenderFrame();
50-
IF_SIMD(rendererSIMD.IncrementCursorTime(240'000'000.))
87+
IF_SIMD(rendererSIMD.IncrementCursorTime(Video::Renderer::DELTA_50FPS))
5188
IF_SIMD(rendererSIMD.RenderFrame())
5289

5390
constexpr CursorLine EXPECTED_OFF{
@@ -81,9 +118,9 @@ TEST_CASE("Cursor blink", "[Video]")
81118
REQUIRE(std::equal(rendererSoft.m_cursorPlane.begin(), rendererSoft.m_cursorPlane.begin() + 16, EXPECTED_ON.data()));
82119
IF_SIMD(REQUIRE(std::equal(rendererSIMD.m_cursorPlane.begin(), rendererSIMD.m_cursorPlane.begin() + 16, EXPECTED_ON.data())))
83120

84-
rendererSoft.IncrementCursorTime(240'000'000.);
121+
rendererSoft.IncrementCursorTime(Video::Renderer::DELTA_50FPS);
85122
rendererSoft.RenderFrame();
86-
IF_SIMD(rendererSIMD.IncrementCursorTime(240'000'000.))
123+
IF_SIMD(rendererSIMD.IncrementCursorTime(Video::Renderer::DELTA_50FPS))
87124
IF_SIMD(rendererSIMD.RenderFrame())
88125

89126
constexpr CursorLine EXPECTED_COMPLEMENT{

0 commit comments

Comments
 (0)