# sample_vot 使用说明

功能描述： sample_vot 示例程序，基于 DRM 框架，实现如下功能：
1. `sample_vot`: 读取图片或创建帧缓存并填充颜色后，送入 HDMI 显示
2. `sample_rotation_square`: 实现对正方形进行旋转的案例（目前不支持长方形的旋转 90 度和 270 度）
3. `sample_blend`: 实现 3 个图层的融合

开发板上连接 `HDMI` 的方法请查阅 [HDMI 接口 ](../quick_start/x5_evb_v2p0_user_guide.html#hdmi) 章节。

注意：必须先手动加载 HDMI 的驱动程序 : `./insmode_driver.sh`

## sample_vot
### 功能概述
功能描述：`sample_vot` 通过输入不同的参数 , 可以演示如下功能：
1. 列出 HDMI 显示器支持的分辨率
2. 读取图片，送入 HDMI 显示
3. 创建帧缓存并填充颜色后，送入 HDMI 显示

#### 软件架构说明
![display_sample_framework](./_static/_images/sample_vot/display_sample_framework.png)

#### 代码位置及目录结构

- 代码位置 `app/samples/platform_samples/sample_vot`
- 目录结构
```
sample_vot/
├── Makefile
├── sample_vot
├── sample_vot.c
└── sample_vot.o
```

#### API 流程说明
根据输入参数的不同，编码流程分为 2 种情况：

| 情况描述            | 特点                      | 不同点，在图中文字的背景颜色 |
|--------------------|-------------------------------------------------| ------------|
| 直接显示内存中的数据 | 从 DRM 框架中申请内存 | 黄色 |
| 读取文件并显示       | 从外部申请内存，传递给 DRM 框架 | 绿色 |

##### sample

![sample_vot_data_flow](./_static/_images/sample_vot/sample_vot_data_flow.png)

图中带背景的函数是对 DRM 接口的封装，下面详细说明每个函数的功能和流程：
1. `__create_and_mmap_drm_frame_buffer`( 黄色背景 ): 调用 DRM 接口从 DRM 框架中申请内存
2. `__wraper_dma_buffer_to_drm_frame_buffer`( 绿色背景 )： 从外部申请内存，传递给 DRM 框架
3. `display_setup`: 调用 DRM 接口获取合适的 `connector` 并根据需要设置对应的 `crtc` 和 `connector`
4. `__add_property`: 调用 DRM 接口设置属性， 完成图层的显示

下面展示上面提到的 4 个函数的流程图


##### __create_and_mmap_drm_frame_buffer

![sample_display_create_buffer](./_static/_images/sample_vot/sample_display_create_buffer.png)

##### __wraper_dma_buffer_to_drm_frame_buffer

![sample_display_wraper_buffer](./_static/_images/sample_vot/sample_display_wraper_buffer.png)

##### display_setup

![sample_vot_display_setup](./_static/_images/sample_vot/sample_vot_display_setup.png)


##### __add_property

![sample_vot_add_property](./_static/_images/sample_vot/sample_vot_add_property.png)



### 编译部署
#### 编译
- 进入 sample_vot 目录，执行 `make` 编译
- 输出成果物是 sample_vot 源码目录下的 `sample_vot`
- 详细程序编译方式请查阅 [ 编译方法 ](overview.html#span-id-sample-build) 章节

#### 程序部署

1. 把目录 `sample_vot` 和 `resource` 上传到开发板 `/userdata` 目录下
2. 进入 `sample_vot` 运行 `chmod +x sample_vot` 命令给程序赋予可执行权限

### 运行
#### 程序运行方法
执行程序：`./sample_vot`
#### 程序参数选项说明
- `./sample_vot -l`　查看接入的 HDMI 显示器支持的分辨率列表
- `./sample_vot -f`　读取 `../resource/nv12_1920x1080.yuv` 并送入到显示器中显示
- `./sample_vot`     创建帧缓存并填充 RGB 的数据后，送入到显示器中显示


#### 运行效果

##### 列出显示器支持的分辨率

执行命令：

```sh
./sample_vot -l
```

日志输出：

```

Print param Config:
        Function : print connector support resolution.
Print [hdmi] connector support resolution:
  [0] 1920x1080 60.00fps
  [1] 1920x1080 59.94fps
  [2] 1920x1080i 60.00fps
  [3] 1920x1080i 59.94fps
  [4] 1920x1080 50.00fps
  [5] 1920x1080i 50.00fps
  [6] 1920x1080 24.00fps
  [7] 1920x1080 23.98fps
```

##### 显示器循环显示 RGB 背景
执行命令：
```sh
./sample_vot
```

运行日志：
```

Print param Config:
        Function : display.
        Input    : default data (R, G, B).
        Output   :
                 Resolution: select connector's first config from EDID
                 Connector: hdmi
display select resolution :1920*1080 .
```

效果说明：
显示器会间隔 2 秒，循环切换颜色：红、绿、蓝

##### 显示器显示文件

执行命令：
```sh
./sample_vot -f
```

运行日志：
```

Print param Config:
        Function : display.
        Input    : file(../resource/nv12_1920x1080.yuv).
        Output   :
                 Resolution: 1920*1080
                 Connector: hdmi
display select resolution :1920*1080 .
```

效果说明：
显示器会把图片 `../resource/nv12_1920x1080.yuv` 显示到屏幕上

## sample_rotation_square
### 功能概述
功能描述：`sample_rotation_square` 实现显示画面间隔 2s 循环旋转 0 度、 90 度、 180 度、 270 度。

#### 软件架构说明
![sample_rotation_framework](./_static/_images/sample_vot/sample_rotation_framework.png)

#### 代码位置及目录结构

- 代码位置 `app/samples/platform_samples/sample_rotation_square`
- 目录结构
```
sample_rotation_square/
├── Makefile
├── sample_rotation_square
├── sample_rotation_square.c
└── sample_rotation_square.o
```

#### API 流程说明

##### sample

![sample_rototaion_data_flow](./_static/_images/sample_vot/sample_rototaion_data_flow.png)

图中带背景的函数是对 DRM 接口的封装，下面详细说明每个函数的功能和流程：
1. `display_setup`( 红色背景 ): 调用 DRM 接口获取合适的 `connector` 并根据需要设置对应的 `crtc` 和 `connector`
2. `find_overlay_plane_id`( 红色背景 )：遍历所有的 plane 找到支持旋转的 plane
3. `__create_and_mmap_drm_frame_buffer`( 黄色背景 ): 调用 DRM 接口从 DRM 框
4. `__destroy_and_unmmap_drm_frame_buffer`( 黄色背景 ): 调用 DRM 接口释放从 DRM 框架中申请的内存
5. `__add_property`( 红色背景 ): 调用 DRM 接口设置属性，完成图层的旋转和显示

##### display_setup

![sample_vot_display_setup](./_static/_images/sample_vot/sample_vot_display_setup.png)

##### find_overlay_plane_id

![sample_display_flow_find_ovrlay_plane_id](./_static/_images/sample_vot/sample_display_flow_find_ovrlay_plane_id.png)

##### __add_property

![sample_vot_add_property](./_static/_images/sample_vot/sample_vot_add_property.png)

##### __create_and_mmap_drm_frame_buffer

![sample_display_create_buffer](./_static/_images/sample_vot/sample_display_create_buffer.png)

##### __destroy_and_unmmap_drm_frame_buffer

![sample_display_destroy_and_unmmap](./_static/_images/sample_vot/sample_display_destroy_and_unmmap.png)


### 编译部署
#### 编译
- 进入 sample_rotation_square 目录，执行 `make` 编译
- 输出成果物是 sample_rotation_square 源码目录下的 `sample_rotation_square`
- 详细程序编译方式请查阅 [ 编译方法 ](overview.html#span-id-sample-build) 章节
#### 程序部署
1. 把目录 `sample_rotation_square` 和 `resource` 上传到开发板 `/userdata` 目录下
2. 进入 `sample_rotation_square` 运行 `chmod +x sample_rotation_square` 命令给程序赋予可执行权限

### 运行
#### 程序运行方法

执行程序：`./sample_rotation_square`

#### 程序参数选项说明
无

#### 运行效果

执行命令：
```sh
./sample_rotation_square
```
日志输出：
```sh
Print param Config:
        Output   :
                 Resolution: select connector's first config from EDID
                 Connector: hdmi
display select resolution :1920*1080 .
```

效果说明 :
1. 显示器会显示 一个白色的正方形，四个角分别是：红色、绿色、蓝色、黄色
2. 间隔 2s 按照如下角度 旋转： 0 度、 90 度、 180 度、 270 度


## sample_blend
### 功能概述
功能描述：`sample_blend` 实现 3 个图层进行 alpha 融合后显示的示例

#### 软件架构说明
![sample_rotation_framework](./_static/_images/sample_vot/sample_rotation_framework.png)

#### 代码位置及目录结构

- 代码位置 `app/samples/platform_samples/sample_blend`
- 目录结构
```
sample_blend/
├── Makefile
├── sample_blend
├── sample_blend.c
└── sample_blend.o
```

#### API 流程说明

##### sample

![sample_blend_data_flow](./_static/_images/sample_vot/sample_blend_data_flow.png)


图中带背景的函数是对 DRM 接口的封装，下面详细说明每个函数的功能和流程：
1. `display_setup`( 红色背景 ): 调用 DRM 接口获取合适的 `connector` 并根据需要设置对应的 `crtc` 和 `connector`
2. `find_plane_ids`( 红色背景 ): 遍历所有的 plane 找到支持融合的 plane
3. `__create_and_mmap_drm_frame_buffer`( 黄色背景 ): 调用 DRM 接口从 DRM 框架中申请内存
4. `__destroy_and_unmmap_drm_frame_buffer`( 黄色背景 ): 调用 DRM 接口释放从 DRM 框架中申请的内存
5. `__add_property`( 红色背景 ): 调用 DRM 接口设置属性，完成多个图层的融合和显示

##### display_setup

![sample_vot_display_setup](./_static/_images/sample_vot/sample_vot_display_setup.png)

##### find_plane_ids

![sample_display_find_plane_ids](./_static/_images/sample_vot/sample_display_find_plane_ids.png)

##### __add_property

![sample_vot_add_property](./_static/_images/sample_vot/sample_vot_add_property.png)

##### __create_and_mmap_drm_frame_buffer

![sample_display_create_buffer](./_static/_images/sample_vot/sample_display_create_buffer.png)


### 编译部署
#### 编译
- 进入 sample_blend 目录，执行 `make` 编译
- 输出成果物是 sample_blend 源码目录下的 `sample_blend`
- 详细程序编译方式请查阅 [ 编译方法 ](overview.html#span-id-sample-build) 章节

#### 程序部署
1. 把目录 `sample_blend` 上传到开发板 `/userdata` 目录下
2. 进入 `sample_blend` 运行 `chmod +x sample_blend` 命令给程序赋予可执行权限


### 运行
#### 程序运行方法
执行程序：`./sample_blend`

#### 程序参数选项说明

- `./sample_blend -m 0 -v 30000`　m 指定融合的模式， v 指定融合数值，参数详细描述如下：
1. 融合数值： 有效范围是 0 - 65535, 默认是 32767
2. 融合模式： 0:Pre-multiplied 1:Coverage  2: None， 默认是 None

	Pre-multiplied 模式 :  `out.rgb = plane_alpha * fg.rgb + (1 - (plane_alpha * fg.alpha)) * bg.rgb`

	Coverage 模式：`out.rgb = plane_alpha * fg.alpha * fg.rgb + (1 - (plane_alpha * fg.alpha)) * bg.rgb`

	None 模式： `out.rgb = plane_alpha * fg.rgb + (1 - plane_alpha) * bg.rgb`

公式中相关参数解释如下：

1. `plane_alpha`： 融合数值（-v 指定的数值 /65535 ）

2. `fg.alpha`： 背景图片的融合数值

3. `fg.rgb`： 当前像素的透明度值

4. `bg.rgb`： 背景图片的透明度值

#### 运行效果

执行命令：
```sh
./sample_blend -m 0 -v 30000
```

日志输出：

```

Print param Config:
        AplhaBlend Param   :
                Mode    : Coverage
                Formula : out.rgb = plane_alpha * fg.alpha * fg.rgb + (1 - (plane_alpha * fg.alpha)) * bg.rgb
                Value   : 32767
display select resolution :1920*1080 .
```
效果说明：

1. 显示器会显示 一个白色为底部，中间分别显示 红色、绿色、蓝色 3 个相交的矩形
2. 未相交的部分和背景色融合
3. 相交的部分：先和背景色融合，两个矩形框的颜色再融合


### 常见问题
1. 问题 1:
   - 描述： Linux DRM 驱动变化时，图层的 ID 号可能会变化
   - 解决办法：程序中最好不要指定图层 ID，推荐使用 plane 的名字去匹配，比如函数 `find_plane_ids`
2. 问题 2 ：
   - 描述：使用 DRM 框架时，不知道有那些图层，以及各个图层的功能
   - 解决办法：使用 命令 ` modetest -M vs-drm -a` 进行查看，详细信息见：[DRM 调试信息与硬件的对应关系 ](../multimedia_development/9-Display_zh_CN.html#id5)
3. 问题 3 ：
   - 描述：编写 demo 程序运行后，发现没有生效，想知道如何快速排除是否是硬件的问题
   - 解决办法：使用命令 `modetest -M vs-drm -a -s 75@31:1920x1080 -P 33@31:1920x1080@NV12`, 详细信息见：[DRM 快速体验 ](../multimedia_development/9-Display_zh_CN.html#id7)
