diff --git a/esphome/components/mipi_dsi/mipi_dsi.cpp b/esphome/components/mipi_dsi/mipi_dsi.cpp index 9fddc62a2e7..192772d7699 100644 --- a/esphome/components/mipi_dsi/mipi_dsi.cpp +++ b/esphome/components/mipi_dsi/mipi_dsi.cpp @@ -183,7 +183,6 @@ void MipiDsi::update() { if (this->auto_clear_enabled_) { this->clear(); } - // Blocks drawn by the writer stay in the buffer until the one flush below this->updating_ = true; if (this->show_test_card_) { this->test_card(); @@ -198,14 +197,9 @@ void MipiDsi::update() { this->flush_dirty_(); } -// Outside update() nothing else would flush, inside it the end of update() does. -void MipiDsi::flush_now_() { - if (!this->updating_) - this->flush_dirty_(); -} - void MipiDsi::flush_dirty_() { - if (this->buffer_ == nullptr || this->x_low_ > this->x_high_ || this->y_low_ > this->y_high_) + // Inside update() the one flush at its end sends everything + if (this->updating_ || this->buffer_ == nullptr || this->x_low_ > this->x_high_ || this->y_low_ > this->y_high_) return; ESP_LOGV(TAG, "x_low %d, y_low %d, x_high %d, y_high %d", this->x_low_, this->y_low_, this->x_high_, this->y_high_); int w = this->x_high_ - this->x_low_ + 1; @@ -223,9 +217,7 @@ void MipiDsi::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8 display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) { if (w <= 0 || h <= 0) return; - // Copy as is only when the bytes are laid out the way draw_pixel_at() writes them; an RGB - // ordered little endian 888 block is b,g,r in memory. Anything else, or a block drawn under a clipping - // region, goes per pixel. + // An RGB ordered little endian 888 block is b,g,r in memory, as the BGR colour mode writes it const bool same_layout = bitness == display::COLOR_BITNESS_565 ? big_endian == this->big_endian_ : big_endian == (this->color_mode_ == display::COLOR_ORDER_RGB); @@ -234,12 +226,11 @@ void MipiDsi::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8 display::Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, x_pad); this->mark_dirty_(x_start, y_start, w, h); - this->flush_now_(); + this->flush_dirty_(); return; } if (this->buffer_ != nullptr) { // With a buffer the block goes through it, or a flush of the old contents would paint over it - // Only the part on the panel const int first_col = std::max(0, -x_start), end_col = std::min(w, static_cast(this->width_) - x_start); const int first_row = std::max(0, -y_start), end_row = std::min(h, static_cast(this->height_) - y_start); if (first_col >= end_col || first_row >= end_row) @@ -251,8 +242,12 @@ void MipiDsi::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8 ptr + ((y_offset + y) * stride + x_offset + first_col) * bytes_per_pixel, (end_col - first_col) * bytes_per_pixel); } - this->mark_dirty_(x_start + first_col, y_start + first_row, end_col - first_col, end_row - first_row); - this->flush_now_(); + if (this->updating_) { + this->mark_dirty_(x_start + first_col, y_start + first_row, end_col - first_col, end_row - first_row); + } else { + this->write_to_display_(x_start + first_col, y_start + first_row, end_col - first_col, end_row - first_row, ptr, + x_offset + first_col, y_offset + first_row, x_pad + w - end_col); + } return; } this->write_to_display_(x_start, y_start, w, h, ptr, x_offset, y_offset, x_pad); @@ -300,26 +295,6 @@ bool MipiDsi::check_buffer_() { return true; } -// Maps drawn coordinates to the buffer the way draw_pixel_at() stores them. -void MipiDsi::rotate_(int &x, int &y) const { - switch (this->rotation_) { - case display::DISPLAY_ROTATION_0_DEGREES: - break; - case display::DISPLAY_ROTATION_90_DEGREES: - std::swap(x, y); - x = this->width_ - x - 1; - break; - case display::DISPLAY_ROTATION_180_DEGREES: - x = this->width_ - x - 1; - y = this->height_ - y - 1; - break; - case display::DISPLAY_ROTATION_270_DEGREES: - std::swap(x, y); - y = this->height_ - y - 1; - break; - } -} - // Widen the dirty box to the drawn rectangle, even where the buffer already held the same values. void MipiDsi::mark_dirty_(int x_start, int y_start, int w, int h) { int x1 = x_start, y1 = y_start; diff --git a/esphome/components/mipi_dsi/mipi_dsi.h b/esphome/components/mipi_dsi/mipi_dsi.h index 948c013a979..20acf02966b 100644 --- a/esphome/components/mipi_dsi/mipi_dsi.h +++ b/esphome/components/mipi_dsi/mipi_dsi.h @@ -7,6 +7,8 @@ #ifdef USE_ESP32_VARIANT_ESP32P4 #include "esphome/core/component.h" #include "esphome/core/helpers.h" + +#include #include "esphome/core/application.h" #include "esphome/core/log.h" #include "esphome/core/gpio.h" @@ -88,8 +90,25 @@ class MipiDsi final : public display::Display { bool check_buffer_(); /// Send the region touched since the last flush to the panel. void flush_dirty_(); - void flush_now_(); - void rotate_(int &x, int &y) const; + // Maps drawn coordinates to the buffer the way draw_pixel_at() stores them + void rotate_(int &x, int &y) const { + switch (this->rotation_) { + case display::DISPLAY_ROTATION_0_DEGREES: + break; + case display::DISPLAY_ROTATION_90_DEGREES: + std::swap(x, y); + x = this->width_ - x - 1; + break; + case display::DISPLAY_ROTATION_180_DEGREES: + x = this->width_ - x - 1; + y = this->height_ - y - 1; + break; + case display::DISPLAY_ROTATION_270_DEGREES: + std::swap(x, y); + y = this->height_ - y - 1; + break; + } + } void mark_dirty_(int x_start, int y_start, int w, int h); /// Pack a colour as the 565 value the panel's byte order expects in memory. uint16_t to_panel_565_(Color color) const { @@ -118,6 +137,7 @@ class MipiDsi final : public display::Display { display::ColorOrder color_mode_{display::COLOR_ORDER_BGR}; display::ColorBitness color_depth_; bool big_endian_{false}; + bool updating_{false}; uint8_t pixel_mode_{}; esp_lcd_panel_handle_t handle_{}; @@ -125,7 +145,6 @@ class MipiDsi final : public display::Display { esp_lcd_panel_io_handle_t io_handle_{}; SemaphoreHandle_t io_lock_{}; uint8_t *buffer_{nullptr}; - bool updating_{false}; uint16_t x_low_{1}; uint16_t y_low_{1}; uint16_t x_high_{0}; diff --git a/esphome/components/mipi_rgb/mipi_rgb.cpp b/esphome/components/mipi_rgb/mipi_rgb.cpp index 8b0a938932b..2bc300e5b82 100644 --- a/esphome/components/mipi_rgb/mipi_rgb.cpp +++ b/esphome/components/mipi_rgb/mipi_rgb.cpp @@ -188,7 +188,6 @@ void MipiRgb::update() { if (this->auto_clear_enabled_) { this->clear(); } - // Blocks drawn by the writer stay in the buffer until the one flush below this->updating_ = true; if (this->show_test_card_) { this->test_card(); @@ -203,14 +202,9 @@ void MipiRgb::update() { this->flush_dirty_(); } -// Outside update() nothing else would flush, inside it the end of update() does. -void MipiRgb::flush_now_() { - if (!this->updating_) - this->flush_dirty_(); -} - void MipiRgb::flush_dirty_() { - if (this->buffer_ == nullptr || this->x_low_ > this->x_high_ || this->y_low_ > this->y_high_) + // Inside update() the one flush at its end sends everything + if (this->updating_ || this->buffer_ == nullptr || this->x_low_ > this->x_high_ || this->y_low_ > this->y_high_) return; ESP_LOGV(TAG, "x_low %d, y_low %d, x_high %d, y_high %d", this->x_low_, this->y_low_, this->x_high_, this->y_high_); int w = this->x_high_ - this->x_low_ + 1; @@ -228,16 +222,13 @@ void MipiRgb::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8 display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) { if (w <= 0 || h <= 0 || this->is_failed()) return; - // RGB565 in the configured byte order at rotation 0 copies as is; anything else, or a block drawn under a - // clipping region, goes per pixel if (bitness != display::COLOR_BITNESS_565 || order != display::COLOR_ORDER_RGB || big_endian != this->big_endian_ || this->rotation_ != display::DISPLAY_ROTATION_0_DEGREES || this->is_clipping()) { Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, x_pad); this->mark_dirty_(x_start, y_start, w, h); - this->flush_now_(); + this->flush_dirty_(); } else if (this->buffer_ != nullptr) { // With a buffer the block goes through it, or a flush of the old contents would paint over it - // Only the part on the panel const int first_col = std::max(0, -x_start), end_col = std::min(w, static_cast(this->width_) - x_start); const int first_row = std::max(0, -y_start), end_row = std::min(h, static_cast(this->height_) - y_start); if (first_col >= end_col || first_row >= end_row) @@ -247,8 +238,12 @@ void MipiRgb::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8 memcpy(this->buffer_ + (y_start + y) * this->width_ + x_start + first_col, ptr + ((y_offset + y) * stride + x_offset + first_col) * 2, (end_col - first_col) * 2); } - this->mark_dirty_(x_start + first_col, y_start + first_row, end_col - first_col, end_row - first_row); - this->flush_now_(); + if (this->updating_) { + this->mark_dirty_(x_start + first_col, y_start + first_row, end_col - first_col, end_row - first_row); + } else { + this->write_to_display_(x_start + first_col, y_start + first_row, end_col - first_col, end_row - first_row, ptr, + x_offset + first_col, y_offset + first_row, x_pad + w - end_col); + } } else { this->write_to_display_(x_start, y_start, w, h, ptr, x_offset, y_offset, x_pad); } @@ -291,26 +286,6 @@ bool MipiRgb::check_buffer_() { return true; } -// Maps drawn coordinates to the buffer the way draw_pixel_at() stores them. -void MipiRgb::rotate_(int &x, int &y) const { - switch (this->rotation_) { - case display::DISPLAY_ROTATION_0_DEGREES: - break; - case display::DISPLAY_ROTATION_90_DEGREES: - std::swap(x, y); - x = this->width_ - x - 1; - break; - case display::DISPLAY_ROTATION_180_DEGREES: - x = this->width_ - x - 1; - y = this->height_ - y - 1; - break; - case display::DISPLAY_ROTATION_270_DEGREES: - std::swap(x, y); - y = this->height_ - y - 1; - break; - } -} - // Widen the dirty box to the drawn rectangle, even where the buffer already held the same values. void MipiRgb::mark_dirty_(int x_start, int y_start, int w, int h) { int x1 = x_start, y1 = y_start; diff --git a/esphome/components/mipi_rgb/mipi_rgb.h b/esphome/components/mipi_rgb/mipi_rgb.h index 5c6d310b986..b2d9e06c007 100644 --- a/esphome/components/mipi_rgb/mipi_rgb.h +++ b/esphome/components/mipi_rgb/mipi_rgb.h @@ -80,8 +80,25 @@ class MipiRgb : public display::Display { } /// Send the region touched since the last flush to the panel. void flush_dirty_(); - void flush_now_(); - void rotate_(int &x, int &y) const; + // Maps drawn coordinates to the buffer the way draw_pixel_at() stores them + void rotate_(int &x, int &y) const { + switch (this->rotation_) { + case display::DISPLAY_ROTATION_0_DEGREES: + break; + case display::DISPLAY_ROTATION_90_DEGREES: + std::swap(x, y); + x = this->width_ - x - 1; + break; + case display::DISPLAY_ROTATION_180_DEGREES: + x = this->width_ - x - 1; + y = this->height_ - y - 1; + break; + case display::DISPLAY_ROTATION_270_DEGREES: + std::swap(x, y); + y = this->height_ - y - 1; + break; + } + } void mark_dirty_(int x_start, int y_start, int w, int h); void dump_pins_(uint8_t start, uint8_t end, const char *name, uint8_t offset); void setup_enables_(); @@ -104,11 +121,11 @@ class MipiRgb : public display::Display { bool invert_colors_{}; display::ColorOrder color_mode_{display::COLOR_ORDER_BGR}; bool big_endian_{true}; + bool updating_{false}; size_t width_; size_t height_; uint16_t *buffer_{nullptr}; std::vector enable_pins_{}; - bool updating_{false}; uint16_t x_low_{1}; uint16_t y_low_{1}; uint16_t x_high_{0}; diff --git a/esphome/components/mipi_spi/mipi_spi.h b/esphome/components/mipi_spi/mipi_spi.h index 3122cffb2f0..ece4b2c6ff0 100644 --- a/esphome/components/mipi_spi/mipi_spi.h +++ b/esphome/components/mipi_spi/mipi_spi.h @@ -671,15 +671,12 @@ class MipiSpiBuffer } protected: - // Convert per pixel into the buffer void draw_pixels_slow(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order, display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) override { display::Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, x_pad); } - // Rotate the coordinates to match the display orientation. - // Convert a color to the buffer pixel format. static BUFFERTYPE convert_color(const Color &color) { if constexpr (BUFFERPIXEL == PIXEL_MODE_8) { diff --git a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp index c38d54516be..9f92a850f55 100644 --- a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +++ b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp @@ -51,8 +51,6 @@ void RpiDpiRgb::draw_pixels_at(int x_start, int y_start, int w, int h, const uin display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) { if (w <= 0 || h <= 0) return; - // Big endian RGB565 at rotation 0 copies as is; anything else, or a block drawn under a clipping region, goes - // per pixel if (bitness != display::COLOR_BITNESS_565 || order != display::COLOR_ORDER_RGB || !big_endian || this->rotation_ != display::DISPLAY_ROTATION_0_DEGREES || this->is_clipping()) { display::Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, diff --git a/esphome/components/st7701s/st7701s.cpp b/esphome/components/st7701s/st7701s.cpp index 1009f36940e..756473dae71 100644 --- a/esphome/components/st7701s/st7701s.cpp +++ b/esphome/components/st7701s/st7701s.cpp @@ -54,8 +54,6 @@ void ST7701S::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8 display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) { if (w <= 0 || h <= 0) return; - // Big endian RGB565 at rotation 0 copies as is; anything else, or a block drawn under a clipping region, goes - // per pixel if (bitness != display::COLOR_BITNESS_565 || order != display::COLOR_ORDER_RGB || !big_endian || this->rotation_ != display::DISPLAY_ROTATION_0_DEGREES || this->is_clipping()) { display::Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset,