当前位置: 首页 > news >正文

驱动开发系列57 - Linux Graphics QXL显卡驱动代码分析(四)显示区域绘制

一:概述

        前面在介绍了显示模式设置(分辨率,刷新率)之后,本文继续分析下,显示区域的绘制,详细看看虚拟机的画面是如何由QXL显卡绘制出来的。 

二:相关数据结构介绍 

struct qxl_monitors_config {uint16_t count;         // 当前启用的显示器数量(head 数量)uint16_t max_allowed;   // 驱动允许的最大显示器数量,如果为 0,表示没有固定限制,由驱动动态决定struct qxl_head heads[]; // 每个显示器的配置数组(实际大小为 count)
};
struct qxl_head {uint32_t id;           // 显示头(显示器)IDuint32_t surface_id;   // 绑定的 QXLSurface IDuint32_t width;        // 显示区域的宽度(像素)uint32_t height;       // 显示区域的高度(像素)uint32_t x;            // 在绑定 surface 上的 X 偏移(起始坐标)uint32_t y;            // 在绑定 surface 上的 Y 偏移uint32_t flags;        // 标志位,用于额外配置(比如是否启用、旋转等)
};
struct qxl_surface_id {uint32_t surface_id; // 表示 QXL 表面(Surface)的唯一标识符。每个表面都会有一个唯一的 ID,用于区分和识别不同的表面。
};
struct qxl_image {struct qxl_image_descriptor descriptor;  // 图像的描述符,包含图像的基本信息(例如图像类型、大小等)union {  /* 可变长度的数据,根据图像类型选择使用 */struct qxl_bitmap bitmap;        // 图像数据,作为位图(bitmap)表示struct qxl_encoder_data quic;    // 图像数据,作为 QUIC 编码数据表示(用于高效传输)struct qxl_surface_id surface_image; // 图像数据,作为表面图像的 ID 表示(指向一个渲染表面)} u;
};
struct qxl_image_descriptor {uint64_t id;           // 图像的唯一标识符,用于标识该图像在系统中的位置uint8_t type;          // 图像类型,用于指示该图像的具体格式或用途(例如位图、编码图像等)uint8_t flags;         // 图像的标志位,通常用于表示图像的特定属性(例如是否是透明图像等)uint32_t width;        // 图像的宽度,以像素为单位uint32_t height;       // 图像的高度,以像素为单位
};
struct qxl_encoder_data {uint32_t data_size;   // 编码数据的大小,单位是字节。uint8_t data[];       // 可变长度的编码数据,存储编码后的图像或图形数据。
};
struct qxl_palette {uint64_t unique;      // 唯一标识符,用于区分不同的调色板。每个调色板都会有一个唯一的 ID。uint16_t num_ents;    // 调色板条目的数量,即调色板中包含的颜色数。uint32_t ents[];      // 可变长度数组,存储调色板中的颜色值。每个条目代表一个颜色,通常是32位颜色值(例如 RGBA)。
};
struct qxl_bitmap {uint8_t format;        // 位图的格式,表示图像数据的颜色深度或编码方式。uint8_t flags;         // 位图的标志字段,指示位图的附加属性或状态。uint32_t x;            // 位图的 X 坐标,表示位图左上角的位置。uint32_t y;            // 位图的 Y 坐标,表示位图左上角的位置。uint32_t stride;       // 位图每行的字节数,即图像数据的跨度。用于访问像素数据时的步长。QXLPHYSICAL palette;   // 调色板的物理地址,用于与调色板相关的数据。通常这是指向 `qxl_palette` 结构体的指针。QXLPHYSICAL data;      // 图像数据的物理地址。指向存储位图像素数据的内存区域。
};
struct qxl_surface {uint32_t format;      // 图形表面的格式(例如 RGBA,BGRA 等)uint32_t width;       // 表面的宽度uint32_t height;      // 表面的高度int32_t stride;       // 行跨度,表示表面每行数据占用的字节数QXLPHYSICAL data;     // 指向表面数据的物理地址
};
struct qxl_surface_cmd {union qxl_release_info release_info;  // 用于释放的额外信息uint32_t surface_id;                  // 表面ID,标识一个具体的图形表面uint8_t type;                         // 命令类型,指示是创建表面还是销毁表面uint32_t flags;                       // 命令标志,可能用于控制命令的行为union {struct qxl_surface surface_create;  // 创建表面时的相关信息} u;
};
struct qxl_clip_rects {uint32_t num_rects;       // 包含的矩形数量struct qxl_data_chunk chunk;  // 包含矩形数据的内容
};
struct qxl_drawable {// 释放信息,用于释放渲染资源时的管理union qxl_release_info release_info;// 该可绘制对象使用的表面IDuint32_t surface_id;// 绘制效果类型,用于标识渲染操作的效果类型(例如:透明、混合等)uint8_t effect;// 绘制对象类型,定义该对象的类型(例如:填充、文本、复制等)uint8_t type;// 标记是否是自带位图数据,如果是,则会直接使用该位图uint8_t self_bitmap;// 如果是自带位图,定义位图的有效区域struct qxl_rect self_bitmap_area;// 可绘制对象的边界框,定义了渲染的边界范围struct qxl_rect bbox;// 裁剪区域,定义了在渲染时应考虑的区域,超出该区域的部分将被裁剪掉struct qxl_clip clip;// 内存管理时间戳,用于标识该对象的渲染时间uint32_t mm_time;// 目标表面数组,最多支持三个目标表面int32_t surfaces_dest[3];// 每个目标表面的渲染区域矩形struct qxl_rect surfaces_rects[3];// 根据绘制类型选择不同的绘制操作,这里使用联合体来支持多种操作union {// 填充操作,例如使用颜色填充区域struct qxl_fill fill;// 不透明操作,可能表示不透明的填充区域struct qxl_opaque opaque;// 复制操作,将源区域复制到目标区域struct qxl_copy copy;// 透明操作,可能表示透明背景或区域struct qxl_transparent transparent;// alpha混合操作,支持透明度的混合效果struct qxl_alpha_blend alpha_blend;// 复制位图操作,支持特定的位图复制struct qxl_copy_bits copy_bits;// 复制操作的另一种形式struct qxl_copy blend;// 3元逻辑操作,用于图像处理中基于位的像素操作struct qxl_rop_3 rop3;// 描边操作,用于绘制路径的边框struct qxl_stroke stroke;// 文本渲染操作,用于绘制文本struct qxl_text text;// 黑色掩码操作,支持黑色掩码效果struct qxl_mask blackness;// 反转掩码操作,用于像素的反色效果struct qxl_mask invers;// 白色掩码操作,支持白色掩码效果struct qxl_mask whiteness;// 合成操作,用于合成多个图像层struct qxl_composite composite;} u;
};
struct qxl_cursor_header {uint64_t unique;          // 唯一标识符,标识一个光标uint16_t type;            // 光标类型(例如:标准光标、自定义光标)uint16_t width;           // 光标的宽度(以像素为单位)uint16_t height;          // 光标的高度(以像素为单位)uint16_t hot_spot_x;      // 热点位置的 X 坐标(相对于光标左上角)uint16_t hot_spot_y;      // 热点位置的 Y 坐标(相对于光标左上角)
};
struct qxl_cursor {struct qxl_cursor_header header;  // 光标的基本信息uint32_t data_size;              // 光标数据的大小struct qxl_data_chunk chunk;     // 包含光标数据的内容(例如:像素数据)
};
struct qxl_cursor_cmd {union qxl_release_info release_info;  // 释放信息,用于同步或更新uint8_t type;                         // 光标操作类型(例如:设置、移动、隐藏)union {struct {  struct qxl_point_1_6 position;   // 光标的新位置uint8_t visible;                 // 光标是否可见QXLPHYSICAL shape;               // 光标形状数据} set;                              // 设置光标操作struct {  uint16_t length;                 // 光标轨迹的长度uint16_t frequency;              // 光标轨迹的频率} trail;                            // 设置光标轨迹操作struct qxl_point_1_6 position;      // 光标的新位置(在移动或其他命令中使用)} u;uint8_t device_data[QXL_CURSOR_DEVICE_DATA_SIZE];  // 设备特定数据,大小为 128 字节
};
struct qxl_ram_header {uint32_t magic;                            // 魔术数字,用于验证数据结构是否正确uint32_t int_pending;                      // 当前挂起的中断uint32_t int_mask;                         // 中断屏蔽uint8_t log_buf[QXL_LOG_BUF_SIZE];         // 日志缓冲区,用于记录日志struct qxl_ring_header cmd_ring_hdr;       // 命令环头,用于管理命令队列struct qxl_command cmd_ring[QXL_COMMAND_RING_SIZE]; // 命令环,用于存储具体的命令struct qxl_ring_header cursor_ring_hdr;    // 光标环头,用于管理光标队列struct qxl_command cursor_ring[QXL_CURSOR_RING_SIZE]; // 光标环,用于存储光标命令struct qxl_ring_header release_ring_hdr;   // 释放环头,用于管理释放命令uint64_t release_ring[QXL_RELEASE_RING_SIZE]; // 释放环,用于存储释放命令struct qxl_rect update_area;               // 更新区域,表示图形更新的区域/* appended for qxl-2 */uint32_t update_surface;                   // 更新的表面 ID,用于指定目标表面struct qxl_mem_slot mem_slot;              // 内存槽,用于分配图形内存struct qxl_surface_create create_surface;  // 表面创建结构,表示新创建的图形表面uint64_t flags;                            // 标志位,用于存储相关的配置信息/* appended for qxl-4 *//* used by QXL_IO_MONITORS_CONFIG_ASYNC */QXLPHYSICAL monitors_config;               // 显示器配置,用于存储显示器相关的配置信息uint8_t guest_capabilities[64];            // 客户端能力,存储与虚拟机环境相关的信息
};
/* qxl-1 compat: append only */
struct qxl_rom {uint32_t magic;                         // 魔术数,用于验证这是一个有效的 QXL ROMuint32_t id;                            // ROM 的唯一标识符uint32_t update_id;                     // 更新标识符,用于标记 ROM 版本或更新次数uint32_t compression_level;             // 压缩级别,可能指示 ROM 数据的压缩程度uint32_t log_level;                     // 日志级别,控制 QXL 驱动的日志输出详细程度uint32_t mode;                          // 驱动的工作模式(qxl-1 特定)uint32_t modes_offset;                  // 显示模式的偏移量,指向模式数据的位置uint32_t num_io_pages;                  // I/O 页的数量,表示 ROM 中的 I/O 页数量uint32_t pages_offset;                  // 页面的偏移量,指向页面数据的位置(qxl-1 特定)uint32_t draw_area_offset;              // 绘制区域的偏移量,表示绘制区域在 ROM 中的位置(qxl-1 特定)uint32_t surface0_area_size;            // 表面0区域的大小,用于描述第一个图形表面的内存大小(qxl-1 特定,名为 draw_area_size)uint32_t ram_header_offset;             // RAM 头部的偏移量,指向 RAM 头部数据的位置uint32_t mm_clock;                      // 内存时钟频率,控制 RAM 访问的时序,影响性能/* qxl-2 特有字段 */uint32_t n_surfaces;                   // 表面数量,表示支持的图形表面数量uint64_t flags;                         // 标志位,存储驱动的配置特性uint8_t slots_start;                    // 起始槽位,内存槽位的起始位置uint8_t slots_end;                      // 结束槽位,内存槽位的结束位置uint8_t slot_gen_bits;                  // 槽生成位数,用于标识槽位的生成位uint8_t slot_id_bits;                   // 槽 ID 位数,表示槽位的唯一标识符的位数uint8_t slot_generation;                // 槽代号,用于表示槽位的代次(内存管理、版本控制)/* qxl-4 特有字段 */uint8_t client_present;                 // 客户端存在标志,指示客户端是否存在uint8_t client_capabilities[58];        // 客户端的能力位图,描述客户端支持的功能或特性uint32_t client_monitors_config_crc;    // 客户端显示配置的 CRC 校验和,用于验证配置的有效性struct {uint16_t count;                     // 显示器配置的数量uint16_t padding;                   // 填充,保持对齐struct qxl_urect heads[64];         // 显示器配置,最多支持 64 个显示器} client_monitors_config;               // 客户端监视器配置,描述显示器的位置和尺寸
};

http://www.xdnf.cn/news/304489.html

相关文章:

  • 使用原生javascript手动实现一个可选链运算符
  • [论文阅读]MCP Guardian: A Security-First Layer for Safeguarding MCP-Based AI System
  • 【Spring Boot 注解】@Configuration与@AutoConfiguration
  • vue2项目中使用pag格式动图
  • GMRES算法处理多个右端项的Block与PseudoBlock变体
  • 【已解决】Neo4j Desktop打不开,不断网解决
  • 一种基于条件生成对抗网络(cGAN)的CT重建算法
  • Hadoop架构再探讨
  • keil+vscode+腾讯ai助手
  • 【prometheus+Grafana篇】基于Prometheus+Grafana实现Linux操作系统的监控与可视化
  • 【程序员AI入门:基础】5.提示工程怎么释放LLM的潜力
  • WT2606B显示驱动TFT语音芯片IC:重塑电子锁交互体验的技术革新
  • 神经网络之训练的艺术:反向传播与常见问题解决之道
  • 数据库实验10 函数存储
  • Dify - Stable Diffusion
  • 《数据分析与可视化》(清华)ch-6 作业 三、绘图题
  • 解决Centos连不上网
  • 数字图像相关法在薄板变形测量中的实践
  • 《Python星球日记》第34天:Web 安全基础
  • Cadence学习笔记之---PCB工程创建、类与子类、颜色管理器介绍
  • 【Python】--实现多进程
  • 2.4线性方程组
  • 使用batch脚本调用另一个batch脚本遇到的问题
  • 【Linux网络编程十一】网络原理之数据链路层
  • 【HTML5】显示-隐藏法 实现网页轮播图效果
  • 【LDM】视觉自回归建模:通过Next-Scale预测生成可扩展图像(NeurIPS2024最佳论文阅读笔记与吃瓜)
  • 第七节:图像基本操作-图像属性获取 (尺寸、通道数、数据类型)
  • C++【STL】(1)string
  • 基于STM32、HAL库的W25X40CLSNIG NOR FLASH存储器驱动应用程序设计
  • 【Linux系统】线程安全