mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
refactor(lcd): add async dma2d copy wrapper
This commit is contained in:
@@ -36,7 +36,8 @@ if(CONFIG_SOC_DW_GDMA_SUPPORTED)
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_DMA2D_SUPPORTED)
|
||||
list(APPEND srcs "src/dma2d.c" "src/esp_async_color_convert.c" "src/async_color_convert_dma2d.c")
|
||||
list(APPEND srcs "src/dma2d.c" "src/esp_async_color_convert.c" "src/async_color_convert_dma2d.c"
|
||||
"src/async_memcpy_dma2d.c")
|
||||
if(CONFIG_SOC_PAU_SUPPORTED)
|
||||
list(APPEND srcs "${target}/dma2d_retention.c")
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// DO NOT USE THESE APIS IN ANY APPLICATIONS
|
||||
// DMA2D async 2D memcpy is a private helper built on async color convert
|
||||
// for same-format window copy (e.g. LCD frame buffer blit).
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
#include "hal/color_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Opaque handle of DMA2D async 2D memcpy driver instance
|
||||
*
|
||||
* @note Internally this is a thin wrapper over async color convert with
|
||||
* source/destination formats forced to the same value (copy-only path).
|
||||
*/
|
||||
typedef struct async_memcpy_dma2d_t *async_memcpy_dma2d_handle_t;
|
||||
|
||||
/**
|
||||
* @brief DMA2D async 2D memcpy event data
|
||||
*/
|
||||
typedef struct {
|
||||
} async_memcpy_dma2d_event_data_t;
|
||||
|
||||
/**
|
||||
* @brief DMA2D async 2D memcpy ISR callback
|
||||
*
|
||||
* @note This callback runs in ISR context.
|
||||
*
|
||||
* @param[in] mcp Driver handle that produced this event
|
||||
* @param[in] edata Event data for the completed request
|
||||
* @param[in] cb_args User context passed to :cpp:func:`esp_async_memcpy_dma2d`
|
||||
*
|
||||
* @return
|
||||
* - true: a higher-priority task was woken and a yield is requested
|
||||
* - false: no yield request
|
||||
*/
|
||||
typedef bool (*async_memcpy_dma2d_isr_cb_t)(async_memcpy_dma2d_handle_t mcp,
|
||||
async_memcpy_dma2d_event_data_t *edata,
|
||||
void *cb_args);
|
||||
|
||||
/**
|
||||
* @brief DMA2D async 2D memcpy driver configuration
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t backlog; /*!< Number of in-flight/pending requests. 0 means driver default. */
|
||||
size_t dma_burst_size; /*!< DMA burst length in bytes. 0 means driver default. */
|
||||
uint32_t intr_priority; /*!< Interrupt priority. 0 means default low/medium priority. */
|
||||
} async_memcpy_dma2d_config_t;
|
||||
|
||||
/**
|
||||
* @brief DMA2D async 2D memcpy transaction descriptor
|
||||
*
|
||||
* Coordinates and size are in pixels.
|
||||
*
|
||||
* The source and destination windows are:
|
||||
* - source: [src_x, src_x + copy_width) x [src_y, src_y + copy_height)
|
||||
* - destination: [dst_x, dst_x + copy_width) x [dst_y, dst_y + copy_height)
|
||||
*
|
||||
* Both windows must be fully inside their corresponding image bounds.
|
||||
*
|
||||
* This API only performs same-format 2D window copy (no color conversion).
|
||||
*/
|
||||
typedef struct {
|
||||
const void *src_buffer; /*!< Source picture base address */
|
||||
uint32_t src_stride; /*!< Source picture row stride in pixels */
|
||||
uint32_t src_height; /*!< Source picture height in pixels */
|
||||
uint32_t src_x; /*!< Source window x offset in pixels */
|
||||
uint32_t src_y; /*!< Source window y offset in pixels */
|
||||
|
||||
void *dst_buffer; /*!< Destination picture base address */
|
||||
uint32_t dst_stride; /*!< Destination picture row stride in pixels */
|
||||
uint32_t dst_height; /*!< Destination picture height in pixels */
|
||||
uint32_t dst_x; /*!< Destination window x offset in pixels */
|
||||
uint32_t dst_y; /*!< Destination window y offset in pixels */
|
||||
|
||||
uint32_t copy_width; /*!< Copy window width in pixels */
|
||||
uint32_t copy_height; /*!< Copy window height in pixels */
|
||||
|
||||
esp_color_fourcc_t pixel_format; /*!< Pixel format of both source and destination */
|
||||
} async_memcpy_dma2d_trans_desc_t;
|
||||
|
||||
/**
|
||||
* @brief Install DMA2D async 2D memcpy driver
|
||||
*
|
||||
* This is a thin wrapper over :cpp:func:`esp_async_color_convert_install_dma2d`.
|
||||
* 2D window copy is implemented as a same-format color-convert request.
|
||||
*
|
||||
* @param[in] config Driver configuration
|
||||
* @param[out] ret_hdl Returned driver handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Driver installed successfully
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - ESP_ERR_NO_MEM: Out of memory
|
||||
* - ESP_ERR_NOT_FOUND: Required DMA2D resource is unavailable
|
||||
* - others: Error from lower-level driver
|
||||
*/
|
||||
esp_err_t esp_async_memcpy_install_dma2d(const async_memcpy_dma2d_config_t *config,
|
||||
async_memcpy_dma2d_handle_t *ret_hdl);
|
||||
|
||||
/**
|
||||
* @brief Uninstall DMA2D async 2D memcpy driver
|
||||
*
|
||||
* @param[in] mcp Driver handle returned by :cpp:func:`esp_async_memcpy_install_dma2d`
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Driver uninstalled successfully
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: There are pending requests in the queue
|
||||
*/
|
||||
esp_err_t esp_async_memcpy_uninstall_dma2d(async_memcpy_dma2d_handle_t mcp);
|
||||
|
||||
/**
|
||||
* @brief Submit an asynchronous 2D memory copy request via DMA2D
|
||||
*
|
||||
* The request is enqueued and completed later in DMA2D interrupt context.
|
||||
* The callback can be NULL if no completion notification is needed.
|
||||
*
|
||||
* @param[in] mcp Driver handle returned by :cpp:func:`esp_async_memcpy_install_dma2d`
|
||||
* @param[in] trans 2D memcpy transaction descriptor
|
||||
* @param[in] cb_isr ISR callback invoked on copy completion, can be NULL
|
||||
* @param[in] cb_args User context passed to @p cb_isr
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Request accepted
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument or invalid request fields
|
||||
* - ESP_ERR_INVALID_STATE: No free internal transaction slot (queue full)
|
||||
* - others: Error from lower-level driver
|
||||
*/
|
||||
esp_err_t esp_async_memcpy_dma2d(async_memcpy_dma2d_handle_t mcp,
|
||||
const async_memcpy_dma2d_trans_desc_t *trans,
|
||||
async_memcpy_dma2d_isr_cb_t cb_isr,
|
||||
void *cb_args);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
67
components/esp_driver_dma/src/async_memcpy_dma2d.c
Normal file
67
components/esp_driver_dma/src/async_memcpy_dma2d.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_check.h"
|
||||
#include "esp_async_color_convert.h"
|
||||
#include "esp_private/async_memcpy_dma2d.h"
|
||||
|
||||
ESP_LOG_ATTR_TAG(TAG, "async_memcpy_dma2d");
|
||||
|
||||
/*
|
||||
* DMA2D 2D window copy is a simplified same-format color-convert request.
|
||||
* Keep this file as a thin naming/API wrapper so LCD and other drivers can
|
||||
* express "2D memcpy" without calling color-convert APIs directly.
|
||||
*/
|
||||
|
||||
esp_err_t esp_async_memcpy_install_dma2d(const async_memcpy_dma2d_config_t *config,
|
||||
async_memcpy_dma2d_handle_t *ret_hdl)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(config && ret_hdl, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
|
||||
async_color_convert_config_t conv_config = {
|
||||
.backlog = config->backlog,
|
||||
.dma_burst_size = config->dma_burst_size,
|
||||
.intr_priority = config->intr_priority,
|
||||
};
|
||||
return esp_async_color_convert_install_dma2d(&conv_config, (async_color_convert_handle_t *)ret_hdl);
|
||||
}
|
||||
|
||||
esp_err_t esp_async_memcpy_uninstall_dma2d(async_memcpy_dma2d_handle_t mcp)
|
||||
{
|
||||
return esp_async_color_convert_uninstall((async_color_convert_handle_t)mcp);
|
||||
}
|
||||
|
||||
esp_err_t esp_async_memcpy_dma2d(async_memcpy_dma2d_handle_t mcp,
|
||||
const async_memcpy_dma2d_trans_desc_t *trans,
|
||||
async_memcpy_dma2d_isr_cb_t cb_isr,
|
||||
void *cb_args)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(mcp && trans, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
|
||||
async_color_convert_request_t request = {
|
||||
.src_buffer = trans->src_buffer,
|
||||
.dst_buffer = trans->dst_buffer,
|
||||
.src_stride = trans->src_stride,
|
||||
.src_height = trans->src_height,
|
||||
.dst_stride = trans->dst_stride,
|
||||
.dst_height = trans->dst_height,
|
||||
.src_x = trans->src_x,
|
||||
.src_y = trans->src_y,
|
||||
.dst_x = trans->dst_x,
|
||||
.dst_y = trans->dst_y,
|
||||
.copy_width = trans->copy_width,
|
||||
.copy_height = trans->copy_height,
|
||||
// Same source/destination format disables CSC and performs 2D window copy only.
|
||||
.src_color_format = trans->pixel_format,
|
||||
.dst_color_format = trans->pixel_format,
|
||||
};
|
||||
|
||||
// Callback prototypes are ABI-compatible: opaque handle pointer + empty event struct + user args.
|
||||
return esp_async_color_convert((async_color_convert_handle_t)mcp,
|
||||
&request,
|
||||
(async_color_convert_isr_cb_t)cb_isr,
|
||||
cb_args);
|
||||
}
|
||||
@@ -6,12 +6,12 @@
|
||||
#include <sys/param.h>
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_lcd_mipi_dsi.h"
|
||||
#include "esp_async_color_convert.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_clk_tree.h"
|
||||
#include "esp_cache.h"
|
||||
#include "mipi_dsi_priv.h"
|
||||
#include "esp_memory_utils.h"
|
||||
#include "esp_private/async_memcpy_dma2d.h"
|
||||
#include "esp_private/dw_gdma.h"
|
||||
#include "hal/color_hal.h"
|
||||
|
||||
@@ -45,7 +45,7 @@ struct esp_lcd_dpi_panel_t {
|
||||
esp_lcd_panel_draw_bitmap_hook_t draw_bitmap_hook; // Draw bitmap hook function
|
||||
void* hook_ctx; // Hook context
|
||||
bool (*on_hook_end)(esp_lcd_panel_handle_t panel); // Callback to be invoked when the draw bitmap hook completes its operation
|
||||
async_color_convert_handle_t fbcpy_handle; // Async color convert handle used for same-format DMA2D frame buffer copy
|
||||
async_memcpy_dma2d_handle_t fbcpy_handle; // DMA2D async 2D memcpy handle used for same-format frame buffer copy
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
esp_pm_lock_handle_t pm_lock; // Power management lock
|
||||
@@ -65,11 +65,11 @@ static bool dpi_panel_draw_bitmap_hook_end(esp_lcd_panel_t *panel)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool async_fbcpy_done_cb(async_color_convert_handle_t conv_hdl, async_color_convert_event_data_t *event, void *cb_args)
|
||||
static bool async_fbcpy_done_cb(async_memcpy_dma2d_handle_t mcp, async_memcpy_dma2d_event_data_t *event, void *cb_args)
|
||||
{
|
||||
bool need_yield = false;
|
||||
esp_lcd_dpi_panel_t *dpi_panel = (esp_lcd_dpi_panel_t *)cb_args;
|
||||
(void)conv_hdl;
|
||||
(void)mcp;
|
||||
(void)event;
|
||||
|
||||
if (dpi_panel->on_hook_end) {
|
||||
@@ -484,7 +484,9 @@ static esp_err_t dpi_panel_draw_bitmap_dma2d_hook(esp_lcd_panel_t *panel, const
|
||||
esp_lcd_dpi_panel_t *dpi_panel = __containerof(panel, esp_lcd_dpi_panel_t, base);
|
||||
(void)hook_ctx;
|
||||
|
||||
async_color_convert_request_t fbcpy_trans_config = {
|
||||
// Built-in DMA2D draw hook only needs same-format 2D window copy.
|
||||
// Use the private DMA2D async memcpy wrapper (thin layer over color convert).
|
||||
async_memcpy_dma2d_trans_desc_t fbcpy_trans_config = {
|
||||
.src_buffer = hook_data->src_data,
|
||||
.dst_buffer = hook_data->dst_data,
|
||||
.src_stride = hook_data->src_x_size,
|
||||
@@ -497,16 +499,13 @@ static esp_err_t dpi_panel_draw_bitmap_dma2d_hook(esp_lcd_panel_t *panel, const
|
||||
.dst_y = hook_data->dst_y_start,
|
||||
.copy_width = hook_data->src_x_end - hook_data->src_x_start,
|
||||
.copy_height = hook_data->src_y_end - hook_data->src_y_start,
|
||||
// For this DMA2D hook we only do window copy from draw buffer to frame buffer.
|
||||
// Source and destination color formats are intentionally set to the same value to disable CSC.
|
||||
.src_color_format = dpi_panel->in_color_format,
|
||||
.dst_color_format = dpi_panel->in_color_format,
|
||||
.pixel_format = dpi_panel->in_color_format,
|
||||
};
|
||||
// The async color convert backend owns source/destination cache sync for the
|
||||
// DMA2D copy path, so the LCD driver should not perform extra cache sync here.
|
||||
// The DMA2D async 2D memcpy backend owns source/destination cache sync for the
|
||||
// copy path, so the LCD driver should not perform extra cache sync here.
|
||||
// Save the completion callback and invoke it when the async frame buffer copy finishes.
|
||||
dpi_panel->on_hook_end = hook_data->on_hook_end;
|
||||
ESP_RETURN_ON_ERROR(esp_async_color_convert(dpi_panel->fbcpy_handle, &fbcpy_trans_config, async_fbcpy_done_cb, dpi_panel), TAG, "async frame buffer copy failed");
|
||||
ESP_RETURN_ON_ERROR(esp_async_memcpy_dma2d(dpi_panel->fbcpy_handle, &fbcpy_trans_config, async_fbcpy_done_cb, dpi_panel), TAG, "async frame buffer copy failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -531,12 +530,12 @@ esp_err_t esp_lcd_dpi_panel_enable_dma2d(esp_lcd_panel_handle_t panel)
|
||||
// Check if built-in DMA2D draw bitmap hook is registered
|
||||
ESP_RETURN_ON_FALSE(!dpi_panel->fbcpy_handle, ESP_ERR_INVALID_STATE, TAG, "draw bitmap DMA2D hook is already registered");
|
||||
|
||||
// Initialize the async color convert backend used by the built-in DMA2D copy hook.
|
||||
// Initialize the DMA2D async 2D memcpy backend used by the built-in copy hook.
|
||||
// Use its default backlog to queue multiple frame buffer copy requests.
|
||||
async_color_convert_config_t fbcpy_config = {
|
||||
async_memcpy_dma2d_config_t fbcpy_config = {
|
||||
.dma_burst_size = 128, // for better performance
|
||||
};
|
||||
ESP_RETURN_ON_ERROR(esp_async_color_convert_install_dma2d(&fbcpy_config, &dpi_panel->fbcpy_handle), TAG, "install async frame buffer copy backend failed");
|
||||
ESP_RETURN_ON_ERROR(esp_async_memcpy_install_dma2d(&fbcpy_config, &dpi_panel->fbcpy_handle), TAG, "install async frame buffer copy backend failed");
|
||||
|
||||
// Register the DMA2D draw bitmap hook
|
||||
esp_lcd_panel_hooks_t hooks = {
|
||||
@@ -548,7 +547,7 @@ esp_err_t esp_lcd_dpi_panel_enable_dma2d(esp_lcd_panel_handle_t panel)
|
||||
|
||||
err:
|
||||
if (dpi_panel->fbcpy_handle) {
|
||||
esp_async_color_convert_uninstall(dpi_panel->fbcpy_handle);
|
||||
esp_async_memcpy_uninstall_dma2d(dpi_panel->fbcpy_handle);
|
||||
dpi_panel->fbcpy_handle = NULL;
|
||||
}
|
||||
dpi_panel->on_hook_end = NULL;
|
||||
@@ -568,13 +567,7 @@ esp_err_t esp_lcd_dpi_panel_disable_dma2d(esp_lcd_panel_handle_t panel)
|
||||
.draw_bitmap_hook = NULL,
|
||||
};
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_dpi_panel_register_hooks(panel, &hooks, NULL), TAG, "unregister DMA2D draw bitmap hook failed");
|
||||
esp_err_t ret = esp_async_color_convert_uninstall(dpi_panel->fbcpy_handle);
|
||||
if (ret != ESP_OK) {
|
||||
// Restore the hook so draw_bitmap_hook and fbcpy_handle stay consistent on failure
|
||||
hooks.draw_bitmap_hook = dpi_panel_draw_bitmap_dma2d_hook;
|
||||
esp_lcd_dpi_panel_register_hooks(panel, &hooks, NULL);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "uninstall DMA2D failed");
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_async_memcpy_uninstall_dma2d(dpi_panel->fbcpy_handle), TAG, "uninstall DMA2D failed");
|
||||
dpi_panel->fbcpy_handle = NULL;
|
||||
dpi_panel->on_hook_end = NULL;
|
||||
|
||||
@@ -665,7 +658,7 @@ static esp_err_t dpi_panel_draw_bitmap_2d(esp_lcd_panel_t *panel, int x_start, i
|
||||
ESP_LOGV(TAG, "copy draw buffer by draw bitmap hook");
|
||||
// Note, whether the previous draw operation is finished should be ensured by the hook.
|
||||
// For the built-in DMA2D hook, cache maintenance of the source and destination
|
||||
// buffers is handled inside the async color convert driver.
|
||||
// buffers is handled inside the DMA2D async 2D memcpy driver.
|
||||
|
||||
esp_lcd_draw_bitmap_hook_data_t hook_data = {
|
||||
.dst_data = frame_buffer,
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#include "hal/color_hal.h"
|
||||
#include "rgb_lcd_rotation_sw.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "esp_async_color_convert.h"
|
||||
#include "esp_private/async_memcpy_dma2d.h"
|
||||
|
||||
#if SOC_HAS(AXI_GDMA)
|
||||
#include "hal/axi_dma_ll.h"
|
||||
@@ -178,7 +178,7 @@ struct esp_rgb_panel_t {
|
||||
esp_lcd_panel_draw_bitmap_hook_t draw_bitmap_hook; // Draw bitmap hook function
|
||||
void* hook_ctx; // Hook context
|
||||
bool (*on_hook_end)(esp_lcd_panel_handle_t panel); // Callback to be invoked when the draw bitmap hook completes its operation
|
||||
async_color_convert_handle_t fbcpy_handle; // Async color convert handle used for same-format DMA2D frame buffer copy
|
||||
async_memcpy_dma2d_handle_t fbcpy_handle; // DMA2D async 2D memcpy handle used for same-format frame buffer copy
|
||||
};
|
||||
|
||||
static esp_err_t lcd_rgb_panel_alloc_frame_buffers(esp_rgb_panel_t *rgb_panel, const esp_lcd_rgb_panel_config_t *panel_config)
|
||||
@@ -730,11 +730,11 @@ static bool rgb_panel_draw_bitmap_hook_end(esp_lcd_panel_t *panel)
|
||||
}
|
||||
|
||||
#if SOC_HAS(DMA2D)
|
||||
static bool async_fbcpy_done_cb(async_color_convert_handle_t conv_hdl, async_color_convert_event_data_t *event, void *cb_args)
|
||||
static bool async_fbcpy_done_cb(async_memcpy_dma2d_handle_t mcp, async_memcpy_dma2d_event_data_t *event, void *cb_args)
|
||||
{
|
||||
bool need_yield = false;
|
||||
esp_rgb_panel_t *rgb_panel = (esp_rgb_panel_t *)cb_args;
|
||||
(void)conv_hdl;
|
||||
(void)mcp;
|
||||
(void)event;
|
||||
|
||||
if (rgb_panel->on_hook_end) {
|
||||
@@ -822,7 +822,7 @@ static esp_err_t rgb_panel_draw_bitmap_2d(esp_lcd_panel_t *panel, int x_start, i
|
||||
ESP_LOGV(TAG, "copy draw buffer by draw bitmap hook");
|
||||
// Note, whether the previous draw operation is finished should be ensured by the hook.
|
||||
// For the built-in DMA2D hook, cache maintenance of the source and destination
|
||||
// buffers is handled inside the async color convert driver.
|
||||
// buffers is handled inside the DMA2D async 2D memcpy driver.
|
||||
|
||||
esp_lcd_draw_bitmap_hook_data_t hook_data = {
|
||||
.dst_data = frame_buffer,
|
||||
@@ -1531,7 +1531,9 @@ static esp_err_t rgb_panel_draw_bitmap_dma2d_hook(esp_lcd_panel_t *panel, const
|
||||
esp_rgb_panel_t *rgb_panel = __containerof(panel, esp_rgb_panel_t, base);
|
||||
(void)hook_ctx;
|
||||
|
||||
async_color_convert_request_t fbcpy_trans_config = {
|
||||
// Built-in DMA2D draw hook only needs same-format 2D window copy.
|
||||
// Use the private DMA2D async memcpy wrapper (thin layer over color convert).
|
||||
async_memcpy_dma2d_trans_desc_t fbcpy_trans_config = {
|
||||
.src_buffer = hook_data->src_data,
|
||||
.dst_buffer = hook_data->dst_data,
|
||||
.src_stride = hook_data->src_x_size,
|
||||
@@ -1544,16 +1546,13 @@ static esp_err_t rgb_panel_draw_bitmap_dma2d_hook(esp_lcd_panel_t *panel, const
|
||||
.dst_y = hook_data->dst_y_start,
|
||||
.copy_width = hook_data->src_x_end - hook_data->src_x_start,
|
||||
.copy_height = hook_data->src_y_end - hook_data->src_y_start,
|
||||
// For this DMA2D hook we only do window copy from draw buffer to frame buffer.
|
||||
// Source and destination color formats are intentionally set to the same value to disable CSC.
|
||||
.src_color_format = rgb_panel->in_color_format,
|
||||
.dst_color_format = rgb_panel->in_color_format,
|
||||
.pixel_format = rgb_panel->in_color_format,
|
||||
};
|
||||
// The async color convert backend owns source/destination cache sync for the
|
||||
// DMA2D copy path, so the LCD driver should not perform extra cache sync here.
|
||||
// The DMA2D async 2D memcpy backend owns source/destination cache sync for the
|
||||
// copy path, so the LCD driver should not perform extra cache sync here.
|
||||
// Save the completion callback and invoke it when the async frame buffer copy finishes.
|
||||
rgb_panel->on_hook_end = hook_data->on_hook_end;
|
||||
ESP_RETURN_ON_ERROR(esp_async_color_convert(rgb_panel->fbcpy_handle, &fbcpy_trans_config, async_fbcpy_done_cb, rgb_panel), TAG, "async frame buffer copy failed");
|
||||
ESP_RETURN_ON_ERROR(esp_async_memcpy_dma2d(rgb_panel->fbcpy_handle, &fbcpy_trans_config, async_fbcpy_done_cb, rgb_panel), TAG, "async frame buffer copy failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -1566,12 +1565,12 @@ esp_err_t esp_lcd_rgb_panel_enable_dma2d(esp_lcd_panel_handle_t panel)
|
||||
// Check if built-in DMA2D draw bitmap hook is registered
|
||||
ESP_RETURN_ON_FALSE(!rgb_panel->fbcpy_handle, ESP_ERR_INVALID_STATE, TAG, "draw bitmap DMA2D hook is already registered");
|
||||
|
||||
// Initialize the async color convert backend used by the built-in DMA2D copy hook.
|
||||
// Initialize the DMA2D async 2D memcpy backend used by the built-in copy hook.
|
||||
// Use its default backlog to queue multiple frame buffer copy requests.
|
||||
async_color_convert_config_t fbcpy_config = {
|
||||
async_memcpy_dma2d_config_t fbcpy_config = {
|
||||
.dma_burst_size = 128, // for better performance
|
||||
};
|
||||
ESP_RETURN_ON_ERROR(esp_async_color_convert_install_dma2d(&fbcpy_config, &rgb_panel->fbcpy_handle), TAG, "install async frame buffer copy backend failed");
|
||||
ESP_RETURN_ON_ERROR(esp_async_memcpy_install_dma2d(&fbcpy_config, &rgb_panel->fbcpy_handle), TAG, "install async frame buffer copy backend failed");
|
||||
|
||||
// Register the DMA2D draw bitmap hook
|
||||
esp_lcd_panel_hooks_t hooks = {
|
||||
@@ -1583,7 +1582,7 @@ esp_err_t esp_lcd_rgb_panel_enable_dma2d(esp_lcd_panel_handle_t panel)
|
||||
|
||||
err:
|
||||
if (rgb_panel->fbcpy_handle) {
|
||||
esp_async_color_convert_uninstall(rgb_panel->fbcpy_handle);
|
||||
esp_async_memcpy_uninstall_dma2d(rgb_panel->fbcpy_handle);
|
||||
rgb_panel->fbcpy_handle = NULL;
|
||||
}
|
||||
rgb_panel->on_hook_end = NULL;
|
||||
@@ -1603,13 +1602,7 @@ esp_err_t esp_lcd_rgb_panel_disable_dma2d(esp_lcd_panel_handle_t panel)
|
||||
.draw_bitmap_hook = NULL,
|
||||
};
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_rgb_panel_register_hooks(panel, &hooks, NULL), TAG, "unregister DMA2D draw bitmap hook failed");
|
||||
esp_err_t ret = esp_async_color_convert_uninstall(rgb_panel->fbcpy_handle);
|
||||
if (ret != ESP_OK) {
|
||||
// Restore the hook so draw_bitmap_hook and fbcpy_handle stay consistent on failure
|
||||
hooks.draw_bitmap_hook = rgb_panel_draw_bitmap_dma2d_hook;
|
||||
esp_lcd_rgb_panel_register_hooks(panel, &hooks, NULL);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "uninstall DMA2D failed");
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_async_memcpy_uninstall_dma2d(rgb_panel->fbcpy_handle), TAG, "uninstall DMA2D failed");
|
||||
rgb_panel->fbcpy_handle = NULL;
|
||||
rgb_panel->on_hook_end = NULL;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user