DRM驅動(五)之drm_atomic_state

上節講到《DRM驅動(四)之ADD_FB》調用drmModeAddFB創建drm_framebuffer。然后通過

drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);

vaddr = mmap(0, create.size, PROT_READ | PROT_WRITE,MAP_SHARED, fd, map.offset);

將物理地址map到用戶空間后,就可以在這塊內存上繪一張自己喜歡的圖。接下來就需要把這塊內存配置到硬件上面,進行刷圖。

刷圖有很多中方式,比如:

int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, uint32_t x, uint32_t y, uint32_t *connectors, int count, drmModeModeInfoPtr mode)

fd:文件描述符

crtcId:crtc_id

bufferId:即上節創建的fb id

x,y:在屏幕上的顯示坐標

connectors:connector id

count:connector 數量

mode:包括刷新率,分辨率等timing的信息

也可以使用下面接口:

drmModeAtomicAlloc();

drmModeAtomicAddProperty(..., property_id, property_value);

drmModeAtomicCommit(...);

本節以drmModeSetCrtc為例

int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
?? ??? ? ? uint32_t x, uint32_t y, uint32_t *connectors, int count,
?? ??? ? ? drmModeModeInfoPtr mode)
{
?? ?struct drm_mode_crtc crtc;
?
?? ?memclear(crtc);
?? ?crtc.x ? ? ? ? ? ? = x;
?? ?crtc.y ? ? ? ? ? ? = y;
?? ?crtc.crtc_id ? ? ? = crtcId;
?? ?crtc.fb_id ? ? ? ? = bufferId;
?? ?crtc.set_connectors_ptr = VOID2U64(connectors);
?? ?crtc.count_connectors = count;
?? ?if (mode) {
?? ? ?memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));
?? ? ?crtc.mode_valid = 1;
?? ?}
?
?? ?return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
}
主要用于填充如下數據結構,傳給內核,drm會根據傳入的信息配置display硬件。比如crtc_id來指定顯示到哪個crtc,fb_id指定哪塊使用dumb顯存等等。

struct drm_mode_crtc {
__u64 set_connectors_ptr;
__u32 count_connectors;
__u32 crtc_id; /**< Id */
__u32 fb_id; /**< Id of framebuffer */
?
__u32 x; /**< x Position on the framebuffer */
__u32 y; /**< y Position on the framebuffer */
?
__u32 gamma_size;
__u32 mode_valid;
struct drm_mode_modeinfo mode;
}
按照之前的經驗,在內核drm_ioctl.c中找到對應函數調用

DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)

DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)

drm_mode_setcrtc和drm_mode_atomic_ioctl從函數調用來看都會調用drm_atomic_commit(state) 也就是說應用傳入的參數最終會轉換成struct drm_atomic_state;

看下struct drm_atomic_state數據結構

struct drm_atomic_state {
?? ?struct kref ref;
?
?? ?struct drm_device *dev;
?? ?bool allow_modeset : 1;
?? ?bool legacy_cursor_update : 1;
?? ?bool async_update : 1;
?? ?struct __drm_planes_state *planes;
?? ?struct __drm_crtcs_state *crtcs;
?? ?int num_connector;
?? ?struct __drm_connnectors_state *connectors;
?? ?int num_private_objs;
?? ?struct __drm_private_objs_state *private_objs;
?
?? ?struct drm_modeset_acquire_ctx *acquire_ctx;
?
? ? struct work_struct commit_work;
};
drm_atomic_state和其他組件state的繼承關系如下圖:

數據結構之間的轉換過程:

int drm_mode_setcrtc(struct drm_device *dev, void *data,
?? ??? ? ? ? struct drm_file *file_priv)
{
?? ?crtc = drm_crtc_find(dev, file_priv, crtc_req->crtc_id);
?
?? ?if (crtc_req->mode_valid) {
?
?? ??? ?fb = drm_framebuffer_lookup(dev, file_priv, crtc_req->fb_id);
?? ??? ?mode = drm_mode_create(dev);
?? ??? ?ret = drm_mode_convert_umode(mode, &crtc_req->mode);
?? ?}
?? ?if (crtc_req->count_connectors > 0) {
?? ??? ?connector_set = kmalloc_array(crtc_req->count_connectors,
?? ??? ??? ??? ??? ? ? ? ?sizeof(struct drm_connector *),
?? ??? ??? ??? ??? ? ? ? ?GFP_KERNEL);
?
?? ??? ?for (i = 0; i < crtc_req->count_connectors; i++) {
?? ??? ??? ?connector_set[i] = NULL;
?? ??? ??? ?set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
?? ??? ??? ?connector = drm_connector_lookup(dev, file_priv, out_id);
?? ??? ??? ?connector_set[i] = connector;
?? ??? ?}
?? ?}
?
?? ?set.crtc = crtc;
?? ?set.x = crtc_req->x;
?? ?set.y = crtc_req->y;
?? ?set.mode = mode;
?? ?set.connectors = connector_set;
?? ?set.num_connectors = crtc_req->count_connectors;
?? ?set.fb = fb;
?? ?ret = __drm_mode_set_config_internal(&set, &ctx);
?
out:
?? ?if (fb)
?? ??? ?drm_framebuffer_put(fb);
?
?? ?if (connector_set) {
?? ??? ?for (i = 0; i < crtc_req->count_connectors; i++) {
?? ??? ??? ?if (connector_set[i])
?? ??? ??? ??? ?drm_connector_put(connector_set[i]);
?? ??? ?}
?? ?}
?? ?kfree(connector_set);
?? ?drm_mode_destroy(dev, mode);
?
?? ?return ret;
}
drm_mode_setcrtc的主要作用:

根據應用傳入的crtc_id找到crtc
根據應用傳入的fb_id,找到對應的drm_framebuffer
根據應用傳入的mode,創建一個drm_display_mode
根據傳入的set_connectors_ptr,找到驅動對應的connector
將以上信息轉為struct drm_mode_set并調用__drm_mode_set_config_internal
static int __drm_mode_set_config_internal(struct drm_mode_set *set,
?? ??? ??? ??? ??? ? ?struct drm_modeset_acquire_ctx *ctx)
{
?? ?struct drm_crtc *crtc = set->crtc;
?? ?struct drm_framebuffer *fb;
?? ?struct drm_crtc *tmp;
?? ?drm_for_each_crtc(tmp, crtc->dev)
?? ??? ?tmp->primary->old_fb = tmp->primary->fb;
?
?? ?fb = set->fb;
?? ?
?? ?ret = drm_atomic_helper_set_config(set, ctx);
?? ?if (ret == 0) {
?? ??? ?crtc->primary->crtc = crtc;
?? ??? ?crtc->primary->fb = fb;
?? ?}
?
?? ?return ret;
}
__drm_mode_set_config_internal的內容比較少,主要調用drm_atomic_helper_set_config

int drm_atomic_helper_set_config(struct drm_mode_set *set,
?? ??? ??? ??? ? struct drm_modeset_acquire_ctx *ctx)
{
?? ?struct drm_atomic_state *state;
?? ?struct drm_crtc *crtc = set->crtc;
?? ?int ret = 0;
?? ?state = drm_atomic_state_alloc(crtc->dev);
?
?? ?ret = __drm_atomic_helper_set_config(set, state);
?
?? ?ret = drm_atomic_commit(state);
fail:
?? ?drm_atomic_state_put(state);
?? ?return ret;
}
drm_atomic_helper_set_config的主要作用:

創建struct drm_atomic_state
將struct drm_mode_set轉換成為struct drm_atomic_state
調用drm_atomic_commit 將修改commit到硬件
int __drm_atomic_helper_set_config(struct drm_mode_set *set,
?? ??? ?struct drm_atomic_state *state)
{
?? ?struct drm_crtc_state *crtc_state;
?? ?struct drm_plane_state *primary_state;
?? ?struct drm_crtc *crtc = set->crtc;
?? ?int hdisplay, vdisplay;
?? ?int ret;
?
?? ?crtc_state = drm_atomic_get_crtc_state(state, crtc);
?
?? ?primary_state = drm_atomic_get_plane_state(state, crtc->primary);
?
?? ?ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode);
?
?? ?crtc_state->active = true;
?
?? ?ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
?
?? ?drm_mode_get_hv_timing(set->mode, &hdisplay, &vdisplay);
?
?? ?drm_atomic_set_fb_for_plane(primary_state, set->fb);
?? ?primary_state->crtc_x = 0;
?? ?primary_state->crtc_y = 0;
?? ?primary_state->crtc_w = hdisplay;
?? ?primary_state->crtc_h = vdisplay;
?? ?primary_state->src_x = set->x << 16;
?? ?primary_state->src_y = set->y << 16;
?? ?if (drm_rotation_90_or_270(primary_state->rotation)) {
?? ??? ?primary_state->src_w = vdisplay << 16;
?? ??? ?primary_state->src_h = hdisplay << 16;
?? ?} else {
?? ??? ?primary_state->src_w = hdisplay << 16;
?? ??? ?primary_state->src_h = vdisplay << 16;
?? ?}
?
?? ?ret = update_output_state(state, set);
?
?? ?return 0;
}
這塊比較代碼有點復雜,這里簡單的用一個表格說明幾個比較重要的結構體數據之間的對應關系,不再贅述代碼里的內容。

本節介紹了應用調用drmModeSetCrtc時傳入參數轉換為struct drm_atomic_state的過程,下節將介紹drm利用drm_atomic_state中內容更新圖像的過程。

注:文中代碼僅作說明,刪除了一些錯誤處理等內容,介意可以看下drm驅動的源碼。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/15716.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/15716.shtml
英文地址,請注明出處:http://en.pswp.cn/web/15716.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python中list遍歷的幾種方式之沒有好與不好,只有合適不合適

Python中list遍歷的幾種方式 引言 Python是一種動態、解釋型的高級編程語言&#xff0c;以其簡潔、易讀的語法而廣受歡迎。在Python中&#xff0c;list是一種非常重要的數據結構&#xff0c;它允許存儲一系列的元素&#xff0c;這些元素可以是任何類型。遍歷list是處理數據的…

nginx的Connection refused

問題描述 nginx的錯誤日志中突然出現大量的的Connection refused問題&#xff0c;日志如下&#xff1a; 2020/03/19 09:52:53 [error] 20117#20117: *7403411764 connect() failed (111: Connection refused) while connecting to upstream, client: xxx.xxx.xxx.xxx, server:…

解決CLion調試時無法顯示變量值的問題

1 問題描述 使用CLion的時候&#xff0c;調試時無法顯示變量的值&#xff0c;例如&#xff1a; 圖來自StackOverflow。 2 解決辦法 可以嘗試切換調試器解決&#xff0c;在Linux下&#xff0c;CLion支持GDB和LLDB&#xff0c;如果GDB不行&#xff0c;可以切換到LLDB。 切換方…

醫院信息化IT監控一體化運維實踐

作者: 曉風 在醫療信息化日益發展的今天&#xff0c;醫院數據中心的運維工作顯得尤為重要。為了確保醫療系統的穩定運行&#xff0c;保障患者數據的安全與完整&#xff0c;我院在信息化IT監控一體化運維方面進行了深入的探索和實踐。 一、背景與挑戰 我院的機房設備規模已有50…

主動歸檔存儲的策略研討

在媒體與娛樂&#xff08;M&E&#xff09;行業中&#xff0c;主動存檔策略對于應對內容的持續需求增長、控制存儲成本膨脹以及實現檔案內容的貨幣化至關重要。以下是對此策略的深入分析&#xff1a; ### 持續的內容需求帶來的挑戰 M&E企業面臨著巨大的挑戰&#xff1…

【Spring】SSM整合_入門代碼實現

1. Maven依賴 在pom.xml中添加SSM框架的依賴 <!-- Spring Core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.x</version> </dependency>…

軟件杯 題目: 基于深度學習的疲勞駕駛檢測 深度學習

文章目錄 0 前言1 課題背景2 實現目標3 當前市面上疲勞駕駛檢測的方法4 相關數據集5 基于頭部姿態的駕駛疲勞檢測5.1 如何確定疲勞狀態5.2 算法步驟5.3 打瞌睡判斷 6 基于CNN與SVM的疲勞檢測方法6.1 網絡結構6.2 疲勞圖像分類訓練6.3 訓練結果 7 最后 0 前言 &#x1f525; 優…

為什么單片機不能直接驅動繼電器和電磁閥

文章是瑞生網轉載&#xff0c;PDF格式文章下載&#xff1a; 為什么單片機不能直接驅動繼電器和電磁閥.pdf: https://url83.ctfile.com/f/45573183-1247189072-10b6d1?p7526 (訪問密碼: 7526)

java-數組內存分配

在 Java 中&#xff0c;數組是一種基本數據結構&#xff0c;用于存儲一系列相同類型的數據。在內存中&#xff0c;數組分配是一塊連續的內存空間&#xff0c;用于存儲數組中的所有元素。本篇文章將詳細解釋 Java 中數組的內存分配&#xff0c;包括數組的聲明、創建、內存模型以…

memcpy的使?和模擬實現

目錄 一&#xff1a;memcpy的使? memcpy的使?的代碼 二&#xff1a;memcpy函數的模擬實現: memcpy和strcpy的區別 用途&#xff1a; 安全性&#xff1a; 數據類型&#xff1a; 性能&#xff1a; 在字符串中的用法示例&#xff1a; memcpy: strcpy 一&#xff1a;…

Ajax面試題精選及參考答案(3萬字長文)

目錄 什么是Ajax,它的核心原理是什么? Ajax應用程序的優勢有哪些? Ajax最大的特點是什么?

Science 基于尖峰時序編碼的模擬神經觸覺系統,可實現動態對象分類

快速處理和有效利用手與物體交互過程中產生的動態觸覺信號&#xff08;例如觸摸和抓握&#xff09;對于觸覺探索和靈巧的物體操作至關重要。將電子皮膚&#xff08;e-skins&#xff09;推進到模仿自然觸覺的水平&#xff0c;是恢復截肢者和癱瘓患者喪失的功能的可行解決方案&am…

實現地圖上展示坐標時,不要全部展示、只展示幾個距離相對較大marker點位,隨著地圖放大再全部展示出來。

比例尺級別地面分辨率 &#xff08;米/像素&#xff09;比例尺0156543.031&#xff1a;591658700.82178271.5151&#xff1a;295829350.4239135.75751&#xff1a;147914675.2319567.878751&#xff1a;73957337.649783.9393751&#xff1a;36978668.854891.9696881&#xff1a…

電機控制系列模塊解析(22)—— 零矢量剎車

一、零矢量剎車 基本概念 逆變器通常采用三相橋式結構&#xff0c;包含六個功率開關元件&#xff08;如IGBT或MOSFET&#xff09;&#xff0c;分為上橋臂和下橋臂。每個橋臂由兩個反并聯的開關元件組成&#xff0c;上橋臂和下橋臂對應于電機三相繞組的正負端。正常工作時&…

mongodb在游戲開發領域的優勢

1、分布式id 游戲服務器里的大部分數據都是要求全局唯一的&#xff0c;例如玩家id&#xff0c;道具id。之所以有這種要求&#xff0c;是因為運營業務上需要進行合服操作&#xff0c;保證不同服的數據在進行合服之后&#xff0c;也能保證id不沖突。如果采用關系型數據庫&#x…

【C++題解】1699 - 輸出是2的倍數,但非3的倍數的數

問題&#xff1a;1699 - 輸出是2的倍數&#xff0c;但非3的倍數的數 類型&#xff1a;循環 題目描述&#xff1a; 請從鍵盤讀入一個整數 n&#xff0c;輸出 1~n 中所有是 2 的倍數&#xff0c;但非 3 的倍數的數&#xff0c;每行 1個。 比如&#xff0c;讀入一個整數10 &…

Spring AI實戰之二:Chat API基礎知識大串講(重要)

歡迎訪問我的GitHub 這里分類和匯總了欣宸的全部原創(含配套源碼)&#xff1a;https://github.com/zq2599/blog_demos Spring AI實戰全系列鏈接 Spring AI實戰之一&#xff1a;快速體驗(OpenAI)Spring AI實戰之二&#xff1a;Chat API基礎知識大串講(重要)SpringAIOllama三部曲…

Linux:進程地址空間、進程控制(一.進程創建、進程終止、進程等待)

上次介紹了環境變量&#xff1a;Linux&#xff1a;進程概念&#xff08;四.main函數的參數、環境變量及其相關操作&#xff09; 文章目錄 1.程序地址空間知識點總結上述空間排布結構是在內存嗎&#xff1f;&#xff08;進程地址空間引入&#xff09; 2.進程地址空間明確幾個點進…

NDIS小端口驅動開發(三)

微型端口驅動程序處理來自過度驅動程序的發送請求&#xff0c;并發出接收指示。 在單個函數調用中&#xff0c;NDIS 微型端口驅動程序可以指示具有多個接收 NET_BUFFER_LIST 結構的鏈接列表。 微型端口驅動程序可以處理對每個NET_BUFFER_LIST結構上具有多個 NET_BUFFER 結構的多…

JAVA -- > 初識JAVA

初始JAVA 第一個JAVA程序詳解 public class Main {public static void main(String[] args) {System.out.println("Hello world");} }1.public class Main: 類型,作為被public修飾的類,必須與文件名一致 2.public static 是JAVA中main函數準寫法,記住該格式即可 …