Add X3 fast LUT option
This commit is contained in:
@@ -230,6 +230,11 @@ class GfxRenderer {
|
||||
void writeGrayscalePlaneStrip(bool lsbPlane, const uint8_t* scratch, int yStart, int numRows) const;
|
||||
bool supportsStripGrayscale() const;
|
||||
|
||||
// X3-only: trade AA visual fidelity for ~2.2 s faster page-flip wall clock.
|
||||
// No effect on X4 (its single grayscale LUT already runs at ~500 ms).
|
||||
void setFastGrayscaleLut(bool fast) const { display.setFastGrayscaleLut(fast); }
|
||||
bool getFastGrayscaleLut() const { return display.getFastGrayscaleLut(); }
|
||||
|
||||
// Tiled grayscale strip target. While active, drawPixel(), clearScreen(),
|
||||
// fillPhysicalHSpanByte() and renderGlyphFast2Bit() operate on `scratch`
|
||||
// (panelWidthBytes * stripRows bytes, holding physical rows
|
||||
|
||||
@@ -97,6 +97,7 @@ STR_SLEEP_COVER_MODE: "Sleep Screen Cover Mode"
|
||||
STR_HIDE_BATTERY: "Hide Battery %"
|
||||
STR_EXTRA_SPACING: "Extra Paragraph Spacing"
|
||||
STR_TEXT_AA: "Text Anti-Aliasing"
|
||||
STR_FAST_AA: "Fast AA (X3 only)"
|
||||
STR_TEXT_DARKNESS: "Text Darkness"
|
||||
STR_EXTRA_DARK: "Extra Dark"
|
||||
STR_MAX_DARK: "Maximum"
|
||||
|
||||
@@ -104,6 +104,10 @@ void HalDisplay::writeGrayscalePlaneStrip(bool lsbPlane, const uint8_t* rows, ui
|
||||
|
||||
bool HalDisplay::supportsStripGrayscale() const { return einkDisplay.supportsStripGrayscale(); }
|
||||
|
||||
void HalDisplay::setFastGrayscaleLut(bool fast) { einkDisplay.setFastGrayscaleLut(fast); }
|
||||
|
||||
bool HalDisplay::getFastGrayscaleLut() const { return einkDisplay.getFastGrayscaleLut(); }
|
||||
|
||||
uint16_t HalDisplay::getDisplayWidth() const { return einkDisplay.getDisplayWidth(); }
|
||||
|
||||
uint16_t HalDisplay::getDisplayHeight() const { return einkDisplay.getDisplayHeight(); }
|
||||
|
||||
@@ -61,6 +61,12 @@ class HalDisplay {
|
||||
void writeGrayscalePlaneStrip(bool lsbPlane, const uint8_t* rows, uint16_t yStart, uint16_t numRows);
|
||||
bool supportsStripGrayscale() const;
|
||||
|
||||
// X3-only knob: pick between the OEM 53-frame grayscale LUT (default, slow
|
||||
// and accurate) and the 7-frame community LUT (fast, slightly darker
|
||||
// mid-tones). No effect on X4. See EInkDisplay::setFastGrayscaleLut.
|
||||
void setFastGrayscaleLut(bool fast);
|
||||
bool getFastGrayscaleLut() const;
|
||||
|
||||
// Runtime geometry passthrough
|
||||
uint16_t getDisplayWidth() const;
|
||||
uint16_t getDisplayHeight() const;
|
||||
|
||||
+1
-1
Submodule open-x4-sdk updated: 15050cb2a8...5f4a46ea3a
@@ -223,6 +223,11 @@ class CrossPointSettings {
|
||||
// Text rendering settings
|
||||
uint8_t extraParagraphSpacing = 1;
|
||||
uint8_t textAntiAliasing = 1;
|
||||
// X3-only: when on, the AA refresh uses the 7-frame community grayscale LUT
|
||||
// (~130 ms panel time) instead of the OEM 53-frame LUT (~2.4 s). Mid-tones
|
||||
// run slightly darker than X4. Matches what papyrix-reader has shipped since
|
||||
// 2025-11. Default off preserves OEM-fidelity grays. No effect on X4.
|
||||
uint8_t fastAntiAliasing = 0;
|
||||
// Text darkness (0 = normal, 1 = dark, 2 = extra dark). Default 1 preserves
|
||||
// historical AA rendering (both grayscale shades drawn in the MSB pass).
|
||||
uint8_t textDarkness = DARKNESS_DARK;
|
||||
|
||||
@@ -111,6 +111,14 @@ inline const std::vector<SettingInfo> list = {
|
||||
SettingInfo::Toggle(StrId::STR_TEXT_AA, &CrossPointSettings::textAntiAliasing, "textAntiAliasing",
|
||||
StrId::STR_CAT_READER)
|
||||
.withSubmenu(StrId::STR_MENU_READER_FONT),
|
||||
// X3-only fast AA LUT toggle. Swaps the 53-frame OEM grayscale waveform
|
||||
// (~2.4 s panel time, X4-accurate grays) for the 7-frame community LUT
|
||||
// (~130 ms, mid-tones slightly darker). See open-x4-sdk
|
||||
// EInkDisplay::setFastGrayscaleLut for trade-offs.
|
||||
SettingInfo::Toggle(StrId::STR_FAST_AA, &CrossPointSettings::fastAntiAliasing, "fastAntiAliasing",
|
||||
StrId::STR_CAT_READER)
|
||||
.withSubmenu(StrId::STR_MENU_READER_FONT)
|
||||
.withDeviceTarget(SettingDeviceTarget::X3),
|
||||
SettingInfo::Enum(StrId::STR_TEXT_DARKNESS, &CrossPointSettings::textDarkness,
|
||||
{StrId::STR_NORMAL, StrId::STR_DARK, StrId::STR_EXTRA_DARK, StrId::STR_MAX_DARK}, "textDarkness",
|
||||
StrId::STR_CAT_READER)
|
||||
|
||||
@@ -174,9 +174,15 @@ bool computePageDynamicYBand(const Page& page, const GfxRenderer& renderer, cons
|
||||
// renderCharImpl culls out-of-band glyphs before bitmap decode so the cost
|
||||
// stays close to one render. Only renderTextOnly() is called here, matching the
|
||||
// legacy AA pass — images and HRs do not participate in grayscale.
|
||||
bool runTiledGrayscalePass(GfxRenderer& renderer, Page& page, int fontId, int marginLeft, int contentTop) {
|
||||
bool runTiledGrayscalePass(GfxRenderer& renderer, Page& page, int fontId, int marginLeft, int contentTop, bool fastAA) {
|
||||
if (!renderer.supportsStripGrayscale()) return false;
|
||||
|
||||
// Push the SETTINGS toggle into the SDK before the AA refresh. No-op on X4;
|
||||
// on X3 picks between OEM _gc (slow/accurate) and community _grayscale
|
||||
// (fast/darker mid-tones). Re-applied per render so a settings change takes
|
||||
// effect on the next page flip without rebooting.
|
||||
renderer.setFastGrayscaleLut(fastAA);
|
||||
|
||||
// Strip height trades scratch size for the number of re-renders. Each render
|
||||
// pays layout + glyph-cull overhead even when bitmap decode is skipped, so
|
||||
// fewer/bigger bands win as long as the scratch fits. 240 rows × ~100 bytes
|
||||
@@ -2157,7 +2163,8 @@ void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int or
|
||||
if (aaEnabledForThisRender) {
|
||||
logReaderMemSnapshot("tiled_gray_begin");
|
||||
const auto tTiledBegin = millis();
|
||||
grayscaleDone = runTiledGrayscalePass(renderer, *page, getEffectiveReaderFontId(), orientedMarginLeft, contentTop);
|
||||
grayscaleDone = runTiledGrayscalePass(renderer, *page, getEffectiveReaderFontId(), orientedMarginLeft, contentTop,
|
||||
SETTINGS.fastAntiAliasing);
|
||||
if (grayscaleDone) {
|
||||
tiledGrayMs = millis() - tTiledBegin;
|
||||
fcm->logStats("tiled_gray");
|
||||
@@ -2219,6 +2226,9 @@ void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int or
|
||||
// grayscale rendering
|
||||
// TODO: Only do this if font supports it
|
||||
if (aaEnabledForThisRender && bwBufferStored) {
|
||||
// Push fast-AA toggle into the SDK before the AA refresh (X3 only; no-op
|
||||
// on X4). Mirrors what runTiledGrayscalePass() does.
|
||||
renderer.setFastGrayscaleLut(SETTINGS.fastAntiAliasing);
|
||||
logReaderMemSnapshot("gray_lsb_begin");
|
||||
renderer.clearScreen(0x00);
|
||||
renderer.setRenderMode(GfxRenderer::GRAYSCALE_LSB);
|
||||
@@ -2341,7 +2351,8 @@ void EpubReaderActivity::displayPreRenderedPage(const Page& page, const int orie
|
||||
const bool aaConfigured = SETTINGS.textAntiAliasing && !antiAliasingSuspendedLowMemory;
|
||||
if (aaConfigured) {
|
||||
Page& pageRef = const_cast<Page&>(page);
|
||||
if (runTiledGrayscalePass(renderer, pageRef, getEffectiveReaderFontId(), orientedMarginLeft, contentTop)) {
|
||||
if (runTiledGrayscalePass(renderer, pageRef, getEffectiveReaderFontId(), orientedMarginLeft, contentTop,
|
||||
SETTINGS.fastAntiAliasing)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2360,6 +2371,7 @@ void EpubReaderActivity::displayPreRenderedPage(const Page& page, const int orie
|
||||
const int snapshotTop = contentTop + bandTop;
|
||||
const int snapshotHeight = std::max(0, bandBottom - bandTop);
|
||||
if (renderer.storeBwBufferRect(contentLeft, snapshotTop, contentRight - contentLeft, snapshotHeight)) {
|
||||
renderer.setFastGrayscaleLut(SETTINGS.fastAntiAliasing);
|
||||
renderer.clearScreen(0x00);
|
||||
renderer.setRenderMode(GfxRenderer::GRAYSCALE_LSB);
|
||||
page.renderTextOnly(renderer, getEffectiveReaderFontId(), orientedMarginLeft, contentTop);
|
||||
|
||||
Reference in New Issue
Block a user