diff --git a/src/lgfx/v1/Bus.hpp b/src/lgfx/v1/Bus.hpp index a5f3462a..1d024a2b 100644 --- a/src/lgfx/v1/Bus.hpp +++ b/src/lgfx/v1/Bus.hpp @@ -81,6 +81,8 @@ namespace lgfx virtual void initDMA(void) = 0; /// DMA転送キューを追加する。; + /// Permits retaining data until the destination's waitDMA() completes. + /// The bus must copy or use CPU output if DMA cannot read the source directly. virtual void addDMAQueue(const uint8_t* data, uint32_t length) = 0; // { writeBytes(data, length, true); } /// 蓄積したDMA転送キューの送信を実行する。; @@ -111,6 +113,9 @@ namespace lgfx virtual void writePixels(pixelcopy_t* pc, uint32_t length) = 0; /// 引数のバイト列を送信する。; + /// use_dma permits reading data after return; keep it unchanged until the destination's waitDMA() completes. + /// false consumes data before return. Internal copies may use DMA in either case. + /// The bus selects direct DMA, an internal copy, or CPU output based on the source. virtual void writeBytes(const uint8_t* data, uint32_t length, bool dc, bool use_dma) = 0; virtual void beginRead(uint_fast8_t dummy_bits) { beginRead(); if (dummy_bits) { readData(dummy_bits); } } diff --git a/src/lgfx/v1/LGFXBase.hpp b/src/lgfx/v1/LGFXBase.hpp index 2548a206..655eb777 100644 --- a/src/lgfx/v1/LGFXBase.hpp +++ b/src/lgfx/v1/LGFXBase.hpp @@ -446,6 +446,9 @@ namespace lgfx pushImage(x, y, w, h, &pc, true); } + /// use_dma permits reading param->src_data after return; keep it unchanged until this destination's waitDMA() completes. + /// false consumes the source before return. Internal copies may use DMA in either case. + /// The bus selects direct DMA, an internal copy, or CPU output based on the source. void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, pixelcopy_t *param, bool use_dma = false); //---------------------------------------------------------------------------- diff --git a/src/lgfx/v1/LGFX_Sprite.hpp b/src/lgfx/v1/LGFX_Sprite.hpp index 5daa25af..2b3ffc12 100644 --- a/src/lgfx/v1/LGFX_Sprite.hpp +++ b/src/lgfx/v1/LGFX_Sprite.hpp @@ -421,10 +421,10 @@ namespace lgfx void push_sprite(LovyanGFX* dst, int32_t x, int32_t y, uint32_t transp = pixelcopy_t::NON_TRANSP) { pixelcopy_t p(_img, dst->getColorDepth(), getColorDepth(), dst->hasPalette(), _palette, transp); - // use_dma はバッファが DMA の転送元になれるかで決まる (外部 RAM も対応チップでは真)。 - // DMA 中にこのスプライトのバッファを書き換えないこと。dst の startWrite() 保持中に再描画するなら - // 先に dst->waitDMA() を呼ぶ (待つのは転送先。スプライト自身の waitDMA() は何もしない) - dst->pushImage(x, y, _panel_sprite._panel_width, _panel_sprite._panel_height, &p, _panel_sprite.getSpriteBuffer()->use_dma()); + // Permit the destination bus to retain the source; it decides whether direct DMA is possible. + // If dst->startWrite() is kept open, call dst->waitDMA() before modifying or freeing this buffer. + // Waiting on the source sprite does not wait for the destination's transfer. + dst->pushImage(x, y, _panel_sprite._panel_width, _panel_sprite._panel_height, &p, true); } void push_rotate_zoom(LovyanGFX* dst, float x, float y, float angle, float zoom_x, float zoom_y, uint32_t transp = pixelcopy_t::NON_TRANSP) diff --git a/src/lgfx/v1/Panel.hpp b/src/lgfx/v1/Panel.hpp index 15074974..59993e72 100644 --- a/src/lgfx/v1/Panel.hpp +++ b/src/lgfx/v1/Panel.hpp @@ -128,8 +128,13 @@ namespace lgfx virtual void setWindow(uint_fast16_t xs, uint_fast16_t ys, uint_fast16_t xe, uint_fast16_t ye) = 0; virtual void drawPixelPreclipped(uint_fast16_t x, uint_fast16_t y, uint32_t rawcolor) = 0; virtual void writeFillRectPreclipped(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, uint32_t rawcolor) = 0; + /// use_dma permits retaining param->src_data until this destination's waitDMA() completes. + /// false consumes the source before return; internal copies may still use DMA. + /// The bus copies or uses CPU output if DMA cannot read the source directly. virtual void writeImage(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, pixelcopy_t* param, bool use_dma) = 0; virtual void writeImageARGB(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, pixelcopy_t* param) = 0; + /// use_dma permits retaining param->src_data until this destination's waitDMA() completes. + /// false consumes the source before return; the bus may DMA an internal copy. virtual void writePixels(pixelcopy_t* param, uint32_t len, bool use_dma) = 0; virtual uint32_t readCommand(uint_fast16_t cmd, uint_fast8_t index = 0, uint_fast8_t length = 4) = 0; diff --git a/src/lgfx/v1/misc/SpriteBuffer.hpp b/src/lgfx/v1/misc/SpriteBuffer.hpp index ed18b574..51a28c18 100644 --- a/src/lgfx/v1/misc/SpriteBuffer.hpp +++ b/src/lgfx/v1/misc/SpriteBuffer.hpp @@ -75,6 +75,7 @@ namespace lgfx void release(void); + [[deprecated("DMA source eligibility is determined by the destination bus")]] bool use_dma(void) const; bool use_memcpy(void) const { return _source != AllocationSource::Psram; } }; diff --git a/src/lgfx/v1/panel/Panel_AMOLED.inl b/src/lgfx/v1/panel/Panel_AMOLED.inl index 6685a270..6fa85e79 100644 --- a/src/lgfx/v1/panel/Panel_AMOLED.inl +++ b/src/lgfx/v1/panel/Panel_AMOLED.inl @@ -528,6 +528,8 @@ namespace lgfx else { auto add = param->src_bitwidth * bytes; + // Keep every row in one RAMWR frame; restarting it rewinds the window. + start_qspi(); if (use_dma) { if (_cfg.dlen_16bit && ((wb * h) & 1)) @@ -545,7 +547,7 @@ namespace lgfx { do { - write_bytes(src, wb, false); + _bus->writeBytes(src, wb, true, false); src += add; } while (--h); }