ESP Display Present

[English]

esp_display_present 用于连接渲染器生成的像素表面与 esp_lcd 面板,不依赖 场景、控件或输入语义。送屏路径从 GUI 中抽出,LVGL、GSP 或其他自绘 GUI 可以共用 同一套 Presenter。

它不是 esp_lvgl_adapter。LVGL 9 请使用 ESP LV Present。

渲染器负责逻辑脏区和像素生成;Presenter 负责物理缓冲区一致性和面板提交。

功能

  • 校验显示目标并选择合适的呈现策略

  • 租用渲染表面或有界绘制缓冲区

  • 提交整帧或脏区更新

  • 处理帧缓冲区所有权、TE 同步、旋转、字节序、缓存同步和可选硬件拷贝

  • 按顺序跟踪完成状态,并在关闭时避免提前释放传输中的缓冲区

添加到工程

idf.py add-dependency "espressif/esp_display_present"

或在 idf_component.yml 中:

dependencies:
  espressif/esp_display_present: "*"

公共 API

包含 esp_display_present.h 即可使用公共 API。配置和共享类型分别定义在 esp_display_present_config.h 和 esp_display_present_types.h 中。

主要对象为 esp_display_presenter_t。

面板初始化前,使用 esp_display_present_get_required_frame_buffer_count(), 按明确的面板类型、模式、旋转和 TE 配置查询驱动的 num_fbs。 查询与创建共用静态策略,不访问面板句柄。IO/GRAM 返回 0,绘制缓冲和 TE compose 缓冲另行管理。创建面板后填入句柄,用同一目标配置创建 Presenter。 使用驱动自有缓冲时,保持 target.fb.frame_buffer_count = 0。

渲染器随后按以下顺序工作:

  1. 使用 esp_display_present_target_config_t 创建 Presenter

  2. 获取帧契约

  3. 渲染请求的完整表面或分区

  4. 提交逻辑覆盖范围,或取消当前帧

  5. 等待生产端工作排空后停止并删除 Presenter

绘制契约:

契约

渲染器职责

PARTITION

将请求区域渲染到 Presenter 持有的绘制缓冲区

DIRECT

将脏区渲染到完整逻辑表面

FULL

重绘完整逻辑表面

呈现模式通常应保持 ESP_DISPLAY_PRESENT_MODE_AUTO。在目标配置中提供准确的 面板类型、Framebuffer、TE、旋转和字节序信息,组件即可选择正确路径。

内部 RAM 充足时,PARTIAL 和 TE 模式会使用第二个绘制缓冲区,使条带拷贝与渲染 重叠。内存紧张的应用可设置 drawbuf.buffers = 1 保持单个绘制缓冲区。

关屏或拆除面板前,先停止帧生产并调用 esp_display_presenter_quiesce()。 在 quiesce 成功之前必须保持面板 IO 和完成中断有效,然后再关屏并删除 Presenter。

更多说明

参见组件 README:

LVGL benchmark example 位于 examples/display/gui/lvgl_present_benchmark。 GSP/LVGL 所有权切换 example 位于 examples/display/gui/gsp_lvgl_present_handoff。 Unity test app 位于 components/display/tools/esp_display_present/test_apps。

API 参考

Header File

Functions

esp_err_t esp_display_present_get_required_frame_buffer_count(const esp_display_present_target_config_t *config, uint8_t *out_count)

Query the minimum number of panel framebuffers before creating the panel.

Set an explicit RGB, MIPI-DSI or IO panel type. Only panel type, mode, rotation and TE configuration are read; handles, supplied framebuffers, pixel format and draw-buffer settings are ignored. This query performs static policy validation without accessing hardware or allocating memory.

IO/GRAM returns 0: draw buffers and TE compose buffers are separate. Presenter creation still validates the actual handles and buffer storage. out_count is set to 0 on error when non-NULL.

返回

ESP_OK on success, ESP_ERR_INVALID_ARG for invalid arguments, ESP_ERR_NOT_SUPPORTED for an unresolved panel type or unsupported mode, rotation or TE combination.

esp_err_t esp_display_presenter_create(const esp_display_presenter_config_t *config, esp_display_presenter_t **out_presenter)

Create a renderer endpoint and bind all required target callbacks.

Renderer calls are single-task and serialize acquire, submit and cancel. A control task may request stop, but delete has one exclusive owner and must not race another API call. Hardware callbacks run in ISR context; the component keeps their state alive until stop has drained them.

esp_err_t esp_display_presenter_stop(esp_display_presenter_t *presenter)

Enter CLOSING and stop after all asynchronous work has retired. New acquire calls fail with ESP_ERR_INVALID_STATE. An active lease must be cancelled by its renderer. Retry ESP_ERR_INVALID_STATE while renderer calls or hardware work are in flight. A terminal hardware fault never reopens the presenter.

esp_err_t esp_display_presenter_delete(esp_display_presenter_t *presenter)

Stop, detach callbacks and release the target and endpoint.

On ESP_ERR_INVALID_STATE the object remains owned by the caller and must be retained for a later retry. Do not call delete concurrently from two tasks.

esp_err_t esp_display_presenter_set_rotation(esp_display_presenter_t *presenter, esp_display_present_rotation_t rotation)

Reconfigure logical-to-physical rotation without changing panel scan mode.

The producer must first stop submitting and quiesce the presenter. The presenter object remains valid and keeps the same address; its target and endpoint are rebuilt so all rotation-dependent storage and transforms are updated consistently. On failure, the previous configuration is restored.

esp_err_t esp_display_presenter_get_caps(const esp_display_presenter_t *presenter, esp_display_presenter_caps_t *out_caps)
esp_err_t esp_display_presenter_get_drawbuf(const esp_display_presenter_t *presenter, esp_display_presenter_drawbuf_t *out_drawbuf)
esp_err_t esp_display_presenter_get_buffer_alignment(const esp_display_presenter_t *presenter, size_t *out_alignment)

Read the minimum base-address alignment of all buffers that this presenter can lease to its renderer. The result is a power of two, in bytes. Query again after changing rotation, which rebuilds the renderer storage.

esp_err_t esp_display_presenter_rebind_producer(esp_display_presenter_t *presenter)

Rebind the serial render-task owner after a platform session handoff. Valid only between frames; it retains pending hardware completion fences.

esp_err_t esp_display_presenter_get_state(const esp_display_presenter_t *presenter, esp_display_presenter_state_t *out_state)

Read the monotonic lifecycle state; FAULTED never reopens in place.

esp_err_t esp_display_presenter_get_fault_reason(const esp_display_presenter_t *presenter, esp_display_present_fault_reason_t *out_reason)

Read why the presenter faulted. ESP_DISPLAY_PRESENT_FAULT_NONE means no fault was recorded. A transfer timeout is recoverable by deleting and recreating the presenter only when the endpoint can prove that hardware no longer owns its buffers (for example the framebuffer endpoint’s fault-stop path). GRAM/TE endpoints must retain storage until their transfer callback arrives. A producer protocol fault is a producer bug.

esp_err_t esp_display_presenter_map_point(const esp_display_presenter_t *presenter, int32_t *x, int32_t *y)

Map physical input coordinates into the logical render orientation.

esp_err_t esp_display_presenter_begin_next_frame(esp_display_presenter_t *presenter, const esp_display_present_surface_request_t *request, esp_display_present_area_t *out_render_areas, size_t render_area_capacity, size_t *out_render_area_count, bool *out_full_coverage)

Begin a frame on the presenter-owned timeline and return the logical areas requiring rasterization. The asynchronous completion ticket is private to the presenter.

esp_err_t esp_display_presenter_acquire_buffer(esp_display_presenter_t *presenter, esp_display_presenter_buffer_t *out_buffer)

Lease producer storage without choosing a logical damage area.

esp_err_t esp_display_presenter_submit_buffer(esp_display_presenter_t *presenter, const esp_display_presenter_buffer_t *buffer, const esp_display_present_area_t *area, size_t stride_bytes)

Submit the rendered portion of a buffer lease.

Pixels start at buffer.surface.pixels and use stride_bytes. The inclusive logical area supplies the destination position and rendered dimensions.

esp_err_t esp_display_presenter_commit_frame(esp_display_presenter_t *presenter, const esp_display_presenter_submit_t *submit)

Commit the active frame with explicit logical coverage.

void esp_display_presenter_cancel_frame(esp_display_presenter_t *presenter)

Cancel the active pre-commit frame and any held region from its bound producer task.

esp_err_t esp_display_presenter_quiesce(esp_display_presenter_t *presenter, uint32_t timeout_ms)

Wait until all work accepted before this call has completed transfer and presentation. The producer must already be stopped between frames.

Structures

struct esp_display_presenter_surface_t

Pixel surface description.

Public Members

void *pixels

Address of the first pixel.

size_t stride_bytes

Distance between adjacent rows in bytes.

uint16_t width

Surface width in pixels.

uint16_t height

Surface height in pixels.

esp_display_present_pixel_format_t pixel_format

Pixel storage format.

struct esp_display_presenter_config_t

Presenter creation parameters.

Public Members

uint16_t width

Logical display width in pixels.

uint16_t height

Logical display height in pixels.

esp_display_present_pixel_format_t pixel_format

Renderer output format; must match target.hw.input_pixel_format.

size_t max_damage_areas

Maximum dirty areas accepted per frame.

uint32_t transfer_timeout_ms

Per-push panel transfer completion budget in milliseconds; 0 selects ESP_DISPLAY_PRESENT_DEFAULT_TRANSFER_TIMEOUT_MS. A timeout faults the presenter with ESP_DISPLAY_PRESENT_FAULT_TRANSFER_TIMEOUT, so raise this for slow panels instead of accepting a terminal fault.

uint32_t pipeline_acquire_timeout_ms

FB pipeline free-buffer acquire budget in milliseconds; 0 selects ESP_DISPLAY_PRESENT_DEFAULT_PIPELINE_ACQUIRE_TIMEOUT_MS.

esp_display_present_target_config_t target

Panel hardware, present mode and endpoint memory configuration.

struct esp_display_presenter_caps_t

Renderer-visible capabilities of a presenter.

Public Members

esp_display_present_contract_t contract

Public draw contract seen by GSP.

bool supports_coverage_areas

DIRECT/FULL only; true when submit may use COVERAGE_AREAS.

bool surface_retains_content

DIRECT/FULL only: pixels remain valid across frames for dirty rendering.

bool previous_surface_readable

DIRECT/FULL only: previous displayed surface can be read for scroll blits.

uint16_t width

Logical display width in pixels.

uint16_t height

Logical display height in pixels.

size_t stride_bytes

Preferred full-surface row stride in bytes.

esp_display_present_pixel_format_t pixel_format

Renderer output format.

size_t drawbuf_bytes

PARTITION only: bytes available in one acquired draw region.

size_t max_damage_areas

Maximum dirty areas accepted per frame.

struct esp_display_presenter_submit_t

Coverage supplied when submitting a DIRECT or FULL surface.

Public Members

esp_display_present_coverage_t coverage

Explicit coverage for a submitted surface. No-op updates are handled before acquire/submit. FULL ignores areas. AREAS requires non-empty areas.

const esp_display_present_area_t *areas

Covered logical areas for AREAS coverage.

size_t area_count

Number of entries in areas.

struct esp_display_presenter_region_t

Drawable logical region leased for the current frame.

Public Members

esp_display_presenter_surface_t surface

Region pixel storage.

uint16_t origin_x

Logical X origin of the region.

uint16_t origin_y

Logical Y origin of the region.

struct esp_display_presenter_buffer_t

Producer-owned drawable-buffer lease.

Public Members

esp_display_presenter_surface_t surface

Preferred drawable surface layout.

size_t capacity_bytes

Authoritative writable storage capacity.

uint32_t lease_id

Identifier required by resolve, submit, or cancel.

esp_display_presenter_resolve_rows_cb_t resolve_rows

Resolve a legal row count after the producer chooses its stride.

void *resolve_rows_ctx

Opaque context for resolve_rows.

struct esp_display_presenter_drawbuf_t

PARTITION only: borrow the presenter’s drawbuf pool pointers.

The pointers remain owned by the presenter for its lifetime. Producers such as LVGL may register them with lv_display_set_buffers() and render directly into them so flush can submit without an extra memcpy hop.

Public Members

void *buffers[2]

Borrowed draw-buffer addresses.

uint8_t count

Number of valid draw-buffer addresses.

uint16_t lines

Preferred draw-buffer height in rows.

size_t bytes

Capacity of each draw buffer in bytes.

Macros

ESP_DISPLAY_PRESENT_DEFAULT_TRANSFER_TIMEOUT_MS

Default per-push panel transfer completion budget.

ESP_DISPLAY_PRESENT_DEFAULT_PIPELINE_ACQUIRE_TIMEOUT_MS

Default FB pipeline free-buffer acquire budget.

Type Definitions

typedef esp_err_t (*esp_display_presenter_resolve_rows_cb_t)(void *user_ctx, uint32_t lease_id, size_t stride_bytes, size_t requested_rows, size_t *out_rows)

Producer-neutral drawable buffer lease.

PARTITION/TE leases expose reusable scratch storage; FULL leases expose the complete logical surface. The producer chooses the logical area and the packed stride when submitting. capacity_bytes is the authoritative storage limit; surface dimensions describe the presenter’s preferred full-width layout.

typedef struct esp_display_presenter esp_display_presenter_t

Enumerations

enum esp_display_present_contract_t

How GSP should talk to this presenter.

This is the public draw contract, not the transport implementation. Transport and framebuffer policy stay inside the presenter.

Values:

enumerator ESP_DISPLAY_PRESENT_CONTRACT_PARTITION

Submit partitioned areas through a shared draw buffer.

enumerator ESP_DISPLAY_PRESENT_CONTRACT_DIRECT

Submit dirty regions into a coherent draw surface.

enumerator ESP_DISPLAY_PRESENT_CONTRACT_FULL

Submit a full frame.

enum esp_display_present_coverage_t

Explicit coverage of a DIRECT/FULL surface submission.

Values:

enumerator ESP_DISPLAY_PRESENT_COVERAGE_FULL

The complete logical screen has been produced.

enumerator ESP_DISPLAY_PRESENT_COVERAGE_AREAS

Only listed logical areas have been produced.

enum esp_display_presenter_state_t

Values:

enumerator ESP_DISPLAY_PRESENTER_STATE_OPEN
enumerator ESP_DISPLAY_PRESENTER_STATE_CLOSING
enumerator ESP_DISPLAY_PRESENTER_STATE_STOPPED
enumerator ESP_DISPLAY_PRESENTER_STATE_FAULTED

Header File

Structures

struct esp_display_present_te_sync_config_t

Optional panel TE sync. A zeroed config is disabled; gpio 0 is valid, so set te_enabled when a TE line is wired.

Frame/blanking/transfer timing is measured at runtime. bus_freq_hz and data_lines only seed the first-frame transfer estimate before a real transfer duration has been observed.

Public Members

int gpio_num

TE input GPIO number, or -1 when disabled.

uint32_t bus_freq_hz

Initial panel-bus frequency estimate in hertz.

uint8_t data_lines

Number of panel-bus data lines.

struct esp_display_present_hw_config_t

Panel / bus hardware fact. Borrowed handles stay valid until presenter deletion.

RGB and MIPI-DPI have no distinct generic handle shape, so set panel_type explicitly for them. Panel-IO/GRAM may use AUTO when io is supplied.

Public Members

esp_lcd_panel_handle_t panel

Borrowed initialized panel handle.

esp_lcd_panel_io_handle_t io

Required for panel-IO/GRAM transfers; otherwise optional.

esp_display_present_panel_t panel_type

Panel transport category.

esp_display_present_pixel_format_t input_pixel_format

Pixel format accepted by the initialized panel data path.

esp_display_present_rotation_t rotation

Logical-to-physical rotation.

bool swap_bytes

Whether RGB565 bytes are swapped on transfer.

bool te_enabled

Whether TE synchronization is enabled.

esp_display_present_te_sync_config_t te_sync

TE synchronization settings.

struct esp_display_present_fb_config_t

Frame-buffer present profile (RGB / MIPI paths).

frame_buffers are borrowed for the presenter’s lifetime; each buffer must hold the resolved physical frame and satisfy the panel driver’s DMA/cache alignment contract. A zero frame_buffer_count asks the component to fetch driver-owned RGB/MIPI framebuffers. Ignored for GRAM partition targets.

Public Members

esp_display_present_mode_t mode

Requested presentation mode.

void *frame_buffers[ESP_DISPLAY_PRESENT_MAX_FRAME_BUFFERS]

Borrowed framebuffer addresses.

uint8_t frame_buffer_count

Number of valid framebuffer addresses.

struct esp_display_present_drawbuf_config_t

Shared producer drawbuf policy for every partition rendering mode.

Public Members

uint16_t lines

Preferred height of each partition draw buffer.

uint8_t buffers

Number of partition draw buffers (1 or 2). 0 selects two for GRAM without TE, and for FB repair and TE only on multi-core targets whose internal DMA heap keeps 128 KiB free after both; two buffers overlap tile copies with rendering at the cost of one more buffer and a 4 KiB worker stack.

bool in_psram

Allocate draw buffers in PSRAM when possible.

uint8_t te_compose_buffers

TE_SYNC full-screen compose buffers. 0/1 keeps the synchronous, single-buffer path; 2 enables a rotating compose pool so composition can overlap an in-flight GRAM transfer.

struct esp_display_present_target_config_t

Target hardware, presentation policy and endpoint memory configuration.

Public Members

esp_display_present_hw_config_t hw

Panel and bus configuration.

esp_display_present_fb_config_t fb

Framebuffer presentation policy.

esp_display_present_drawbuf_config_t drawbuf

Partition draw-buffer policy.

Macros

ESP_DISPLAY_PRESENT_MAX_FRAME_BUFFERS
ESP_DISPLAY_PRESENT_TE_SYNC_DISABLED()

Enumerations

enum esp_display_present_panel_t

Values:

enumerator ESP_DISPLAY_PRESENT_PANEL_AUTO
enumerator ESP_DISPLAY_PRESENT_PANEL_MIPI_DSI
enumerator ESP_DISPLAY_PRESENT_PANEL_RGB
enumerator ESP_DISPLAY_PRESENT_PANEL_IO
enum esp_display_present_mode_t

Values:

enumerator ESP_DISPLAY_PRESENT_MODE_NONE

No tearing avoidance; single buffer or direct transfer.

enumerator ESP_DISPLAY_PRESENT_MODE_DOUBLE_FULL

Double buffering with full frame buffers.

enumerator ESP_DISPLAY_PRESENT_MODE_TRIPLE_FULL

Triple buffering with full frame buffers.

enumerator ESP_DISPLAY_PRESENT_MODE_DOUBLE_DIRECT

Double buffering with direct dirty-area rendering into full buffers.

enumerator ESP_DISPLAY_PRESENT_MODE_TRIPLE_PARTIAL

Triple buffering with partial/partition refresh.

enumerator ESP_DISPLAY_PRESENT_MODE_TE_SYNC

TE GPIO synchronized direct transfer for SPI/I80/QSPI panels.

enumerator ESP_DISPLAY_PRESENT_MODE_DOUBLE_PARTIAL

Double buffering with partial/partition refresh.

enumerator ESP_DISPLAY_PRESENT_MODE_AUTO

Let esp_display_present choose from panel type, TE config and buffers.

Header File

Structures

struct esp_display_present_point_t

Logical pixel coordinate.

Public Members

int32_t x

Horizontal coordinate.

int32_t y

Vertical coordinate.

struct esp_display_present_size_t

Two-dimensional size in pixels.

Public Members

uint16_t width

Width in pixels.

uint16_t height

Height in pixels.

struct esp_display_present_area_t

Inclusive logical pixel area.

Public Members

int x1

Inclusive logical coordinates (closed interval): x2/y2 name the last affected pixel. The GSP-side counterpart gsp_rect_t (gsp_types.h) is open-interval [x1, x2) x [y1, y2). Left coordinate.

int y1

Top coordinate.

int x2

Right coordinate.

int y2

Bottom coordinate.

struct esp_display_present_render_alignment_t

Producer raster-area requirements. Zero fields mean no extra alignment. The presenter expands damage conservatively and clips it to the logical display before returning render areas.

Public Members

uint16_t x_pixels

Required X-origin alignment in pixels.

uint16_t y_pixels

Required Y-origin alignment in pixels.

uint16_t width_pixels

Required area-width alignment in pixels.

uint16_t height_pixels

Required area-height alignment in pixels.

struct esp_display_present_surface_request_t

Logical damage supplied when preparing a surface frame.

The presenter may copy the previous displayed surface into the new draw surface and may conservatively request a full raster when scroll state or buffer history cannot be reused safely.

Public Members

const esp_display_present_area_t *dirty_areas

Logical dirty areas.

size_t dirty_area_count

Number of entries in dirty_areas.

esp_display_present_render_alignment_t render_alignment

Producer raster alignment.

bool has_scroll

Whether this request contains a scroll operation.

esp_display_present_area_t scroll_viewport

Logical viewport affected by scrolling.

int16_t scroll_dx

Horizontal scroll displacement in pixels.

int16_t scroll_dy

Vertical scroll displacement in pixels.

struct esp_display_present_frame_buffers_t

Framebuffer storage returned by a panel driver.

Public Members

void *buffers[3]

Framebuffer addresses.

uint8_t count

Number of valid framebuffer addresses.

size_t size_bytes

Size of each framebuffer in bytes.

Enumerations

enum esp_display_present_panel_interface_t

Values:

enumerator ESP_DISPLAY_PRESENT_PANEL_IF_RGB
enumerator ESP_DISPLAY_PRESENT_PANEL_IF_MIPI_DSI
enumerator ESP_DISPLAY_PRESENT_PANEL_IF_OTHER
enum esp_display_present_rotation_t

Values:

enumerator ESP_DISPLAY_PRESENT_ROTATE_0
enumerator ESP_DISPLAY_PRESENT_ROTATE_90
enumerator ESP_DISPLAY_PRESENT_ROTATE_180
enumerator ESP_DISPLAY_PRESENT_ROTATE_270
enum esp_display_present_pixel_format_t

Values:

enumerator ESP_DISPLAY_PRESENT_PIXEL_FORMAT_RGB565
enumerator ESP_DISPLAY_PRESENT_PIXEL_FORMAT_RGB888
enum esp_display_present_fault_reason_t

Why a presenter latched a fault. A transfer timeout is a hardware-level condition (for example bus jitter or a slow panel) that the application may recover from by deleting and recreating the presenter; a producer protocol fault is a producer-side bug and has no in-place recovery.

Values:

enumerator ESP_DISPLAY_PRESENT_FAULT_NONE
enumerator ESP_DISPLAY_PRESENT_FAULT_PRODUCER_PROTOCOL

Ticket/order violation in the producer build or fence protocol.

enumerator ESP_DISPLAY_PRESENT_FAULT_TRANSFER_TIMEOUT

A panel transfer failed to complete within the configured budget.

Header File

Functions

static inline bool esp_display_present_geometry_area_is_valid(const esp_display_present_area_t *area, uint16_t width, uint16_t height)
esp_err_t esp_display_present_geometry_align_area(esp_display_present_size_t logical_size, const esp_display_present_area_t *area, const esp_display_present_render_alignment_t *alignment, esp_display_present_area_t *out_area)

Conservatively expand an inclusive logical area to producer raster alignment and clip it to logical_size. Zero alignment fields mean 1. Alignments need not be powers of two.

esp_err_t esp_display_present_geometry_map_logical_point_to_physical(esp_display_present_rotation_t rotation, esp_display_present_size_t logical_size, const esp_display_present_point_t *logical_point, esp_display_present_point_t *out_physical_point)
esp_err_t esp_display_present_geometry_map_physical_point_to_logical(esp_display_present_rotation_t rotation, esp_display_present_size_t logical_size, const esp_display_present_point_t *physical_point, esp_display_present_point_t *out_logical_point)
esp_err_t esp_display_present_geometry_map_logical_area_to_physical(esp_display_present_rotation_t rotation, esp_display_present_size_t logical_size, const esp_display_present_area_t *logical, esp_display_present_area_t *out_physical)