diff --git a/lib/GfxRenderer/GfxRenderer.cpp b/lib/GfxRenderer/GfxRenderer.cpp index 8199bd6..171bd80 100644 --- a/lib/GfxRenderer/GfxRenderer.cpp +++ b/lib/GfxRenderer/GfxRenderer.cpp @@ -164,7 +164,9 @@ int GfxRenderer::getLineHeight(const int fontId) const { uint8_t* GfxRenderer::getFrameBuffer() const { return einkDisplay.getFrameBuffer(); } -void GfxRenderer::swapBuffers() const { einkDisplay.swapBuffers(); } +size_t GfxRenderer::getBufferSize() { + return EInkDisplay::BUFFER_SIZE; +} void GfxRenderer::grayscaleRevert() const { einkDisplay.grayscaleRevert(); } @@ -174,6 +176,35 @@ void GfxRenderer::copyGrayscaleMsbBuffers() const { einkDisplay.copyGrayscaleMsb void GfxRenderer::displayGrayBuffer() const { einkDisplay.displayGrayBuffer(); } +/** + * This should be called before grayscale buffers are populated. + * A `restoreBwBuffer` call should always follow the grayscale render if this method was called. + */ +void GfxRenderer::storeBwBuffer() { + if (bwBuffer) { + Serial.printf("[%lu] [GFX] !! BW buffer already stored - this is likely a bug, freeing it\n", millis()); + free(bwBuffer); + } + + bwBuffer = static_cast(malloc(EInkDisplay::BUFFER_SIZE)); + memcpy(bwBuffer, einkDisplay.getFrameBuffer(), EInkDisplay::BUFFER_SIZE); +} + +/** + * This can only be called if `storeBwBuffer` was called prior to the grayscale render. + * It should be called to restore the BW buffer state after grayscale rendering is complete. + */ +void GfxRenderer::restoreBwBuffer() { + if (!bwBuffer) { + Serial.printf("[%lu] [GFX] !! BW buffer not stored - this is likely a bug\n", millis()); + return; + } + + einkDisplay.cleanupGrayscaleBuffers(bwBuffer); + free(bwBuffer); + bwBuffer = nullptr; +} + void GfxRenderer::renderChar(const EpdFontFamily& fontFamily, const uint32_t cp, int* x, const int* y, const bool pixelState, const EpdFontStyle style) const { const EpdGlyph* glyph = fontFamily.getGlyph(cp, style); diff --git a/lib/GfxRenderer/GfxRenderer.h b/lib/GfxRenderer/GfxRenderer.h index 720bf70..e5760a2 100644 --- a/lib/GfxRenderer/GfxRenderer.h +++ b/lib/GfxRenderer/GfxRenderer.h @@ -12,6 +12,7 @@ class GfxRenderer { private: EInkDisplay& einkDisplay; RenderMode renderMode; + uint8_t* bwBuffer = nullptr; std::map fontMap; void renderChar(const EpdFontFamily& fontFamily, uint32_t cp, int* x, const int* y, bool pixelState, EpdFontStyle style) const; @@ -49,9 +50,11 @@ class GfxRenderer { void copyGrayscaleLsbBuffers() const; void copyGrayscaleMsbBuffers() const; void displayGrayBuffer() const; + void storeBwBuffer(); + void restoreBwBuffer(); // Low level functions uint8_t* getFrameBuffer() const; - void swapBuffers() const; + static size_t getBufferSize(); void grayscaleRevert() const; }; diff --git a/open-x4-sdk b/open-x4-sdk index 4d0dcd5..af965a0 160000 --- a/open-x4-sdk +++ b/open-x4-sdk @@ -1 +1 @@ -Subproject commit 4d0dcd5ff87fcd86eb2966a123e85b03284a03db +Subproject commit af965a074b99bdbbf0670d2c284bb34d978f73ed diff --git a/platformio.ini b/platformio.ini index 7998dcb..3b19781 100644 --- a/platformio.ini +++ b/platformio.ini @@ -20,6 +20,7 @@ build_flags = -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DMINIZ_NO_ZLIB_COMPATIBLE_NAMES=1 + -DEINK_DISPLAY_SINGLE_BUFFER_MODE=1 # https://libexpat.github.io/doc/api/latest/#XML_GE -DXML_GE=0 -DXML_CONTEXT_BYTES=1024 diff --git a/src/screens/EpubReaderScreen.cpp b/src/screens/EpubReaderScreen.cpp index f2c51d9..fade5da 100644 --- a/src/screens/EpubReaderScreen.cpp +++ b/src/screens/EpubReaderScreen.cpp @@ -217,9 +217,8 @@ void EpubReaderScreen::renderScreen() { const int w = textWidth + margin * 2; const int h = renderer.getLineHeight(READER_FONT_ID) + margin * 2; renderer.grayscaleRevert(); - uint8_t* fb1 = renderer.getFrameBuffer(); - renderer.swapBuffers(); - memcpy(fb1, renderer.getFrameBuffer(), EInkDisplay::BUFFER_SIZE); + + // TODO: This looks like garbage again, need to implement windowed updates renderer.fillRect(x, y, w, h, 0); renderer.drawText(READER_FONT_ID, x + margin, y + margin, "Indexing..."); renderer.drawRect(x + 5, y + 5, w - 10, h - 10); @@ -297,6 +296,9 @@ void EpubReaderScreen::renderContents(std::unique_ptr page) { pagesUntilFullRefresh--; } + // Save bw buffer to reset buffer state after grayscale data sync + renderer.storeBwBuffer(); + // grayscale rendering // TODO: Only do this if font supports it { @@ -315,6 +317,9 @@ void EpubReaderScreen::renderContents(std::unique_ptr page) { renderer.displayGrayBuffer(); renderer.setRenderMode(GfxRenderer::BW); } + + // restore the bw data + renderer.restoreBwBuffer(); } void EpubReaderScreen::renderStatusBar() const {