1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-11-11 GuEe-GUI the first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13
14 #include <virtio_gpu.h>
15 #include <virtio_input.h>
16
17 #define GRAPHIC_THREAD_PRIORITY 25
18 #define GRAPHIC_THREAD_STACK_SIZE 4096
19 #define GRAPHIC_THREAD_TIMESLICE 5
20
21 static rt_uint32_t cur_min[2];
22 static rt_uint32_t cur_max[2];
23 static rt_uint32_t cur_range[2];
24 static rt_uint32_t cur_points[2];
25 static rt_uint32_t cur_last_points[2];
26 static rt_bool_t cur_event_sync;
27 static rt_uint32_t color[2] = { 0xff0000, 0x0000ff };
28 static rt_uint8_t cursor[VIRTIO_GPU_CURSOR_IMG_SIZE] rt_align(VIRTIO_PAGE_SIZE);
29
tablet_event_handler(struct virtio_input_event event)30 void tablet_event_handler(struct virtio_input_event event)
31 {
32 static rt_bool_t cur_btn_down = RT_FALSE;
33
34 if (event.type == EV_ABS)
35 {
36 if (event.code == 0)
37 {
38 cur_points[0] = (cur_max[0] * (event.value - cur_min[0]) + cur_range[0] / 2) / cur_range[0];
39 }
40 else if (event.code == 1)
41 {
42 cur_points[1] = (cur_max[1] * (event.value - cur_min[1]) + cur_range[1] / 2) / cur_range[1];
43 }
44 }
45 else if (event.type == EV_KEY)
46 {
47 if (event.code == BTN_LEFT)
48 {
49 if (cur_btn_down && event.value == 0)
50 {
51 color[0] ^= color[1];
52 color[1] ^= color[0];
53 color[0] ^= color[1];
54 cur_btn_down = RT_FALSE;
55 cur_event_sync = RT_TRUE;
56 }
57 else
58 {
59 cur_btn_down = RT_TRUE;
60 }
61 }
62 }
63 else if (event.type == EV_SYN)
64 {
65 cur_event_sync = RT_TRUE;
66 }
67 }
68
graphic_thread(void * param)69 void graphic_thread(void *param)
70 {
71 int i;
72 char dev_name[RT_NAME_MAX];
73 rt_device_t device = RT_NULL;
74
75 rt_device_t tablet_dev = RT_NULL;
76 struct virtio_input_config tablet_config;
77
78 rt_uint32_t white = 0xffffff;
79 rt_device_t gpu_dev = RT_NULL;
80 struct rt_device_rect_info rect_info;
81 struct rt_device_graphic_info graphic_info;
82 struct rt_device_graphic_ops *virtio_gpu_graphic_ops;
83
84 /* GPU */
85 device = rt_device_find("virtio-gpu0");
86
87 if (device != RT_NULL && rt_device_open(device, 0) == RT_EOK)
88 {
89 virtio_gpu_graphic_ops = rt_graphix_ops(device);
90
91 rt_memset(&rect_info, 0, sizeof(rect_info));
92 rt_memset(&graphic_info, 0, sizeof(graphic_info));
93
94 rt_device_control(device, VIRTIO_DEVICE_CTRL_GPU_SET_PRIMARY, RT_NULL);
95 rt_device_control(device, VIRTIO_DEVICE_CTRL_GPU_CREATE_2D, (void *)RTGRAPHIC_PIXEL_FORMAT_RGB888);
96 rt_device_control(device, RTGRAPHIC_CTRL_GET_INFO, &graphic_info);
97
98 rect_info.x = 0;
99 rect_info.y = 0;
100 rect_info.width = graphic_info.width;
101 rect_info.height = graphic_info.height;
102
103 if (graphic_info.framebuffer != RT_NULL)
104 {
105 int i = 0;
106
107 rt_memset(graphic_info.framebuffer, 0xff, graphic_info.pitch * graphic_info.height);
108
109 cur_last_points[0] = graphic_info.width / 2;
110 cur_last_points[1] = graphic_info.height / 2;
111
112 virtio_gpu_graphic_ops->draw_hline((char *)&color[0], 0, graphic_info.width, cur_last_points[1]);
113 virtio_gpu_graphic_ops->draw_vline((char *)&color[1], cur_last_points[0], 0, graphic_info.height);
114
115 rt_device_control(device, RTGRAPHIC_CTRL_RECT_UPDATE, &rect_info);
116
117 while (i < sizeof(cursor) / 4)
118 {
119 /* R: 0x4c G: 0xaf B: 0x50 A: 0.8 */
120 ((rt_uint32_t *)cursor)[i] = 0xcc4caf50;
121 ++i;
122 }
123
124 rt_device_control(device, VIRTIO_DEVICE_CTRL_CURSOR_SETUP, cursor);
125 rt_device_control(device, VIRTIO_DEVICE_CTRL_CURSOR_MOVE, (rt_uint32_t[]){0, 0});
126
127 gpu_dev = device;
128 }
129 }
130
131 /* Keyboard, Mouse, Tablet */
132 for (i = 0; i < 3; ++i)
133 {
134 rt_snprintf(dev_name, RT_NAME_MAX, "virtio-input%d", i);
135
136 device = rt_device_find(dev_name);
137
138 if (device != RT_NULL && rt_device_open(device, 0) == RT_EOK)
139 {
140 enum virtio_input_type type;
141 rt_device_control(device, VIRTIO_DEVICE_CTRL_INPUT_GET_TYPE, &type);
142
143 if (type == VIRTIO_INPUT_TYPE_TABLET)
144 {
145 tablet_dev = device;
146 }
147 else
148 {
149 rt_device_close(device);
150 }
151 }
152 }
153
154 if (tablet_dev == RT_NULL || gpu_dev == RT_NULL)
155 {
156 goto _graphic_fail;
157 }
158
159 cur_max[0] = graphic_info.width;
160 cur_max[1] = graphic_info.height;
161
162 rt_device_control(tablet_dev, VIRTIO_DEVICE_CTRL_INPUT_GET_ABS_X_INFO, &tablet_config);
163
164 cur_min[0] = tablet_config.abs.min;
165 cur_range[0] = tablet_config.abs.max - cur_min[0];
166
167 rt_device_control(tablet_dev, VIRTIO_DEVICE_CTRL_INPUT_GET_ABS_Y_INFO, &tablet_config);
168
169 cur_min[1] = tablet_config.abs.min;
170 cur_range[1] = tablet_config.abs.max - cur_min[1];
171
172 cur_event_sync = RT_FALSE;
173
174 rt_device_control(tablet_dev, VIRTIO_DEVICE_CTRL_INPUT_BIND_BSCT_HANDLER, tablet_event_handler);
175
176 for (;;)
177 {
178 while (cur_event_sync)
179 {
180 virtio_gpu_graphic_ops->draw_hline((char *)&white, 0, graphic_info.width, cur_last_points[1]);
181 virtio_gpu_graphic_ops->draw_vline((char *)&white, cur_last_points[0], 0, graphic_info.height);
182
183 cur_last_points[0] = cur_points[0];
184 cur_last_points[1] = cur_points[1];
185
186 virtio_gpu_graphic_ops->draw_hline((char *)&color[0], 0, graphic_info.width, cur_last_points[1]);
187 virtio_gpu_graphic_ops->draw_vline((char *)&color[1], cur_last_points[0], 0, graphic_info.height);
188
189 rt_device_control(gpu_dev, RTGRAPHIC_CTRL_RECT_UPDATE, &rect_info);
190
191 cur_event_sync = RT_FALSE;
192
193 rt_thread_mdelay(1);
194 }
195 }
196
197 _graphic_fail:
198
199 if (gpu_dev != RT_NULL)
200 {
201 rt_device_close(gpu_dev);
202 }
203
204 if (tablet_dev != RT_NULL)
205 {
206 rt_device_close(tablet_dev);
207 }
208 }
209
graphic_test(void)210 int graphic_test(void)
211 {
212 rt_thread_t graphic_tid = rt_thread_create("graphic work", graphic_thread, RT_NULL,
213 GRAPHIC_THREAD_STACK_SIZE, GRAPHIC_THREAD_PRIORITY, GRAPHIC_THREAD_TIMESLICE);
214
215 if (graphic_tid != RT_NULL)
216 {
217 rt_thread_startup(graphic_tid);
218
219 return RT_EOK;
220 }
221
222 return -RT_ERROR;
223 }
224 MSH_CMD_EXPORT(graphic_test, Graphic test);
225