LVGL 从什么时候开始知道要进行绘制的?(真正的绘制开始啦)

如何得知对象的状态发生改变,需要重新绘制?

event的开始

在LVGL中,`lv_obj_send_event` 函数是一个用于发送事件到指定对象的函数。这个函数的调用意味着事件传递机制的开始,它是LVGL事件系统的核心部分,用于在不同组件之间传递消息和信号。当一个对象( 比如按钮、滑块、文本框等)发生了某种状态的改变(例如,被点击、值改变等),`lv_obj_send_event` 函数就会被用来发送一个事件。这个事件会被发送到对象本身,以及可能的父对象。

这个函数的调用通常意味着以下几个方面:

1. **状态改变通知**:当用户与界面交互或者界面内部状态发生变化时,`lv_obj_send_event` 函数会发送一个事件,通知其他部分代码这个改变。

2. **事件传递**:事件会按照一定的顺序传递给注册的回调函数。这些回调函数可以是用户自定义的,用于处理特定类型的事件。

3. **响应链**:事件的发送启动了一个响应链,这个链条上的每个环节都有机会处理这个事件。如果当前对象的回调没有处理这个事件,它会被传递到父对象,直到被处理或者到达响应链的顶端。

4. **用户自定义事件处理**:用户可以注册自己的事件回调函数,用于处理特定对象发送的事件。这样,当`lv_obj_send_event` 被调用时,用户的回调函数会被触发,执行相应的逻辑。

5. **界面更新**:事件的发送有时也会导致界面的更新。例如,当一个对象的尺寸发生变化时,发送的事件可能会触发重绘,以反映新的界面状态。

`lv_obj_send_event` 函数的调用是LVGL中事件驱动模型的一个关键环节,它确保了用户交互和内部状态变化能够被正确地传递和响应。通过这个机制,开发者可以创建动态、响应式的图形用户界面。

event的核心

event_send_core 函数是事件系统的核心函数,它的主要作用是处理和分发事件到相应的对象和回调函数。这个函数是LVGL事件处理机制的心脏,确保了事件能够从源头传递到目标对象,并且允许用户定义的处理函数得以执行。

以下是event_send_core函数的主要作用:

  1. 事件创建:当界面中的某个对象(如按钮、列表、图表等)发生状态变化时,event_send_core 会创建一个事件对象,这个对象包含了事件的类型、相关的数据以及发生事件的对象等信息。

  2. 事件分发event_send_core 负责将创建的事件对象分发给正确的目标对象。这通常是通过遍历对象的父级链表来完成的,直到找到合适的处理者或者到达顶级父对象。

  3. 回调执行:当事件被分发到目标对象时,event_send_core 会检查该对象是否有注册的回调函数来处理该类型的事件。如果有,它会调用这些回调函数,允许用户定义的代码来响应事件。

  4. 事件传播:事件可以在对象树中向上传播,直到找到处理事件的回调或者到达根级别。这种机制允许在不同层级上响应事件,提供了灵活的事件处理策略。

  5. 响应抑制:在某些情况下,一个事件可能被一个对象处理后不再需要向上传播。event_send_core 允许在回调函数中标记事件为已处理,这样事件就不会继续传播到更高层级的对象。

  6. 错误处理:如果在事件分发过程中出现错误,如找不到处理函数或者回调函数执行出错,event_send_core 会负责处理这些错误情况,确保系统的稳定性。

  7. 性能优化event_send_core 通过智能的事件分发机制,确保只有相关的对象和回调函数被触发,从而提高事件处理的效率和性能。

从事件通知到渲染完成,整个过程做了哪些工作?

从事件通知到事件处理完成,完成渲染任务的整个函数调用过程如下:

绘制开始啦!!!

1.lv_obj_send_event(lv_obj_t * obj, lv_event_code_t event_code, void * param)
用于向指定的对象发送事件。事件可以是用户定义的自定义事件,由event_send_core处理接下来的事情


2.event_send_core
其函数实现核心是:

lv_event_send(list, e, true)-->lv_obj_event_base--->lv_event_send(list, e, false)
这样一个流程之后,开始对该obj的父对象进行同样的处理,直到没有可以处理的父对象。

3.lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e)
调用event_cb,处理事件,event_cb有两个类型,一个是class类型注册回调,一个是具体obj注册的回调函数(lv_obj_add_event_cb)

4.lv_obj_event就是class 类型的event_cb,在初始化的时候配置。
lv_obj_add_event_cb函数则是后面根据需要注册具体的回调,lv_event_add(&obj->spec_attr->event_list, event_cb, filter, user_data);

5.lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj)
从lv_event_t中拿到需要绘制的obj对象,得到需要重新绘制obj的哪些区域、背景色、source image等信息(lv_obj_init_draw_rect_dsc)

6.lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
针对layer,开始进行绘制。
lv_draw_add_task(lv_layer_t * layer, const lv_area_t * coords)函数就是将要绘制的区域信息和layer的裁剪区域通过new task 联系起来(填充一个绘制task),然后加到队列里面去。

7.lv_draw_finalize_task_creation(lv_layer_t * layer, lv_draw_task_t * t)
创建和配置绘制任务时需要调用。 它将向小部件发送有关新绘制任务的事件并将其分配给绘制单元

8.lv_draw_dispatch:
获取一个显示对象,循环处理该显示对象的layer(lv_draw_dispatch_layer(disp, layer));
尝试获得一个绘制layer的任务,通过lv_draw_dispatch_layer进行分派.

9.lv_draw_dispatch_layer(lv_display_t * disp, lv_layer_t * layer)
内部用于尝试调度具体层的绘制任务,两个入参分别是显示对象和需要绘制的layer。
首先,会移除已经完成的task;
然后,判断该层已准备就绪,启用混合其缓冲区,
当该图层是src,找到一个类型为TYPE_LAYER的绘制任务;(当执行类型为 `LV_DRAW_TASK_TYPE_LAYER` 的绘图任务时,LittlevGL 将指定图层的内容渲染到屏幕上。)找到一个不忙且至少可以完成一项任务的绘图单元.

10.最终调用dispatch_cb进行具体的绘制

11.dispatch_cb由初始化的时候注册实际的处理函数draw_dispatch

12.draw_dispatch函数,layer->draw_buf->data是layer中的target buffer(line205)

13.lv_vg_lite_buffer_from_draw_buf,将layer层的targetbuffer给到draw_uint
lv_vg_lite_buffer_from_draw_buf(&u->target_buffer, layer->draw_buf);

14.然后就可以根据task->type,调用对应的绘制函数。

15.以贴图为例子,lv_draw_vg_lite_img

16.首先,会对绘制需求(task->draw_dsc)进行处理解析,解码出要贴的source image。(lv_vg_lite_buffer_open_image)

17.然后进行底层贴图的驱动调用,进行贴图操作。

备注


第13点中,隐含着如下信息
从u->task_act->draw_dsc解码出src_buf(lv_vg_lite_buffer_open_image);
u->base_unit.target_layer->draw_buf->data就是target buffer.
layer里面包含了target buffer 和 area信息
task 里面可以解析出source image数据、area信息。

在第12点中,通过下面的code将task和layer联系在一起
    u->base_unit.target_layer = layer;
    u->base_unit.clip_area = &t->clip_area;
    u->task_act = t;

is_independent(lv_layer_t * layer, lv_draw_task_t * t_check)
查找排队且独立的任务,根据area判断layer中的task和t_check是否有相交的地方,明确是否是独立的task.

重要的枚举


LV_DRAW_TASK_STATE_WAITING:表示绘图任务正在等待某些操作完成,例如正在等待图层渲染完成。
LV_DRAW_TASK_STATE_QUEUED:表示绘图任务已经被添加到绘图队列中,等待系统调度执行。
LV_DRAW_TASK_STATE_IN_PROGRESS:表示绘图任务正在执行中。
LV_DRAW_TASK_STATE_READY:表示绘图任务已经准备好执行,等待系统调度执行。


这些是LVGL中的绘图任务类型,用于指定要绘制的图形类型。具体含义如下:

- LV_DRAW_TASK_TYPE_FILL:填充矩形或圆形
- LV_DRAW_TASK_TYPE_BORDER:绘制矩形或圆形的边框
- LV_DRAW_TASK_TYPE_BOX_SHADOW:绘制矩形或圆形的阴影
- LV_DRAW_TASK_TYPE_LABEL:绘制文本标签
- LV_DRAW_TASK_TYPE_IMAGE:绘制图像
- LV_DRAW_TASK_TYPE_LAYER:绘制图层
- LV_DRAW_TASK_TYPE_LINE:绘制直线
- LV_DRAW_TASK_TYPE_ARC:绘制弧线
- LV_DRAW_TASK_TYPE_TRIANGLE:绘制三角形
- LV_DRAW_TASK_TYPE_MASK_RECTANGLE:绘制矩形遮罩
- LV_DRAW_TASK_TYPE_MASK_BITMAP:绘制位图遮罩
- LV_DRAW_TASK_TYPE_VECTOR:绘制矢量图形

LVGL使用这些任务类型来绘制各种UI元素,例如按钮、文本框、进度条等。开发人员可以使用LVGL提供的API来创建和定制这些UI元素。
 

相关推荐

  1. PlantUML 是绘制 uml 一个开源项目

    2024-04-05 16:54:04       12 阅读
  2. draw.io: 开启图表绘制无限可能

    2024-04-05 16:54:04       15 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-05 16:54:04       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-05 16:54:04       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-05 16:54:04       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-05 16:54:04       18 阅读

热门阅读

  1. 物联网之传感器如何选型

    2024-04-05 16:54:04       13 阅读
  2. 宝塔 docker 安装 rabbitmq

    2024-04-05 16:54:04       19 阅读
  3. npm常用命令

    2024-04-05 16:54:04       19 阅读
  4. 什么是Android ABI?

    2024-04-05 16:54:04       16 阅读
  5. Python 中的 *args 和 **kwargs

    2024-04-05 16:54:04       18 阅读
  6. 设计模式:桥接模式

    2024-04-05 16:54:04       14 阅读
  7. AcWing 4407.扫雷

    2024-04-05 16:54:04       15 阅读
  8. 基于SpringBoot + Vue 的电影售票及影院管理系统

    2024-04-05 16:54:04       13 阅读