1212#define VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D 0x0105
1313#define VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING 0x0106
1414#define VIRTIO_GPU_CMD_GET_CAPSET_INFO 0x0108
15+ #define VIRTIO_GPU_CMD_UPDATE_CURSOR 0x0300
16+ #define VIRTIO_GPU_CMD_MOVE_CURSOR 0x0301
1517
1618#define VIRTIO_GPU_RESP_OK_NODATA 0x1100
1719#define VIRTIO_GPU_RESP_OK_DISPLAY_INFO 0x1101
2123#define VIRTIO_GPU_RESP_OK_RESOURCE_UUID 0x1105
2224#define VIRTIO_GPU_RESP_OK_MAP_INFO 0x1106
2325
24- #define GPU_RESOURCE_ID 1
25-
2626#define BPP 4
2727
28+ #define CONTROL_QUEUE 0
29+ #define CURSOR_QUEUE 1
30+
2831// TODO: format logs
2932VirtioGPUDriver* VirtioGPUDriver::try_init (gpu_size preferred_screen_size){
3033 VirtioGPUDriver* driver = new VirtioGPUDriver ();
@@ -64,6 +67,8 @@ bool VirtioGPUDriver::init(gpu_size preferred_screen_size){
6467
6568 fb_set_stride (screen_size.width * BPP );
6669
70+ resource_id_counter = 0 ;
71+
6772 kprintf (" Stride %i" ,screen_size.width * BPP );
6873
6974 framebuffer_size = screen_size.width * screen_size.height * BPP ;
@@ -72,10 +77,14 @@ bool VirtioGPUDriver::init(gpu_size preferred_screen_size){
7277 fb_set_bounds (screen_size.width ,screen_size.height );
7378
7479 get_capset ();
80+
81+ fb_resource_id = new_resource_id ();
82+
83+ kprintf (" Resource %i" , fb_resource_id);
7584
76- if (!create_2d_resource (screen_size)) return false ;
85+ if (!create_2d_resource (fb_resource_id, screen_size)) return false ;
7786
78- if (!attach_backing ()) return false ;
87+ if (!attach_backing (fb_resource_id, (sizedptr){framebuffer,framebuffer_size} )) return false ;
7988
8089 if (scanout_found)
8190 set_scanout ();
@@ -87,6 +96,10 @@ bool VirtioGPUDriver::init(gpu_size preferred_screen_size){
8796 return true ;
8897}
8998
99+ uint32_t VirtioGPUDriver::new_resource_id (){
100+ return ++resource_id_counter;
101+ }
102+
90103#define VIRTIO_GPU_MAX_SCANOUTS 16
91104
92105typedef struct virtio_gpu_ctrl_hdr {
@@ -165,7 +178,7 @@ gpu_size VirtioGPUDriver::get_display_info(){
165178 return (gpu_size){0 , 0 };
166179}
167180
168- bool VirtioGPUDriver::create_2d_resource (gpu_size size) {
181+ bool VirtioGPUDriver::create_2d_resource (uint32_t resource_id, gpu_size size) {
169182 virtio_2d_resource* cmd = (virtio_2d_resource*)kalloc (gpu_dev.memory_page , sizeof (virtio_2d_resource), ALIGN_4KB , true , true );
170183
171184 cmd->hdr .type = VIRTIO_GPU_CMD_RESOURCE_CREATE_2D ;
@@ -176,7 +189,7 @@ bool VirtioGPUDriver::create_2d_resource(gpu_size size) {
176189 cmd->hdr .padding [0 ] = 0 ;
177190 cmd->hdr .padding [1 ] = 0 ;
178191 cmd->hdr .padding [2 ] = 0 ;
179- cmd->resource_id = GPU_RESOURCE_ID ;
192+ cmd->resource_id = resource_id ;
180193 cmd->format = 1 ; // VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM
181194 cmd->width = size.width ;
182195 cmd->height = size.height ;
@@ -213,7 +226,7 @@ typedef struct virtio_backing_cmd {
213226 }__attribute__((packed)) entries[1 ];
214227}__attribute__((packed)) virtio_backing_cmd;
215228
216- bool VirtioGPUDriver::attach_backing () {
229+ bool VirtioGPUDriver::attach_backing (uint32_t resource_id, sizedptr ptr ) {
217230 virtio_backing_cmd* cmd = (virtio_backing_cmd*)kalloc (gpu_dev.memory_page , sizeof (virtio_backing_cmd), ALIGN_4KB , true , true );
218231
219232 cmd->hdr .type = VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING ;
@@ -224,11 +237,11 @@ bool VirtioGPUDriver::attach_backing() {
224237 cmd->hdr .padding [0 ] = 0 ;
225238 cmd->hdr .padding [1 ] = 0 ;
226239 cmd->hdr .padding [2 ] = 0 ;
227- cmd->resource_id = GPU_RESOURCE_ID ;
240+ cmd->resource_id = resource_id ;
228241 cmd->nr_entries = 1 ;
229242
230- cmd->entries [0 ].addr = framebuffer ;
231- cmd->entries [0 ].length = framebuffer_size ;
243+ cmd->entries [0 ].addr = ptr. ptr ;
244+ cmd->entries [0 ].length = ptr. size ;
232245 cmd->entries [0 ].padding = 0 ;
233246
234247 virtio_gpu_ctrl_hdr* resp = (virtio_gpu_ctrl_hdr*)kalloc (gpu_dev.memory_page , sizeof (virtio_gpu_ctrl_hdr), ALIGN_4KB , true , true );
@@ -267,7 +280,7 @@ bool VirtioGPUDriver::set_scanout() {
267280 cmd->r .height = screen_size.height ;
268281
269282 cmd->scanout_id = scanout_id;
270- cmd->resource_id = GPU_RESOURCE_ID ;
283+ cmd->resource_id = fb_resource_id ;
271284
272285 cmd->hdr .type = VIRTIO_GPU_CMD_SET_SCANOUT ;
273286 cmd->hdr .flags = 0 ;
@@ -306,7 +319,7 @@ typedef struct virtio_transfer_cmd {
306319 uint32_t padding;
307320}__attribute__((packed)) virtio_transfer_cmd;
308321
309- bool VirtioGPUDriver::transfer_to_host (gpu_rect rect) {
322+ bool VirtioGPUDriver::transfer_to_host (uint32_t resource_id, gpu_rect rect) {
310323 virtio_transfer_cmd* cmd = (virtio_transfer_cmd*)kalloc (gpu_dev.memory_page , sizeof (virtio_transfer_cmd), ALIGN_4KB , true , true );
311324
312325 cmd->hdr .type = VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D ;
@@ -315,7 +328,7 @@ bool VirtioGPUDriver::transfer_to_host(gpu_rect rect) {
315328 cmd->hdr .padding [0 ] = 0 ;
316329 cmd->hdr .padding [1 ] = 0 ;
317330 cmd->hdr .padding [2 ] = 0 ;
318- cmd->resource_id = GPU_RESOURCE_ID ;
331+ cmd->resource_id = resource_id ;
319332 cmd->offset = 0 ;
320333 cmd->padding = 0 ;
321334 cmd->rect .x = rect.point .x ;
@@ -353,11 +366,11 @@ typedef struct virtio_flush_cmd {
353366void VirtioGPUDriver::flush () {
354367
355368 if (full_redraw) {
356- transfer_to_host ((gpu_rect){{0 ,0 },{screen_size.width ,screen_size.height }});
369+ transfer_to_host (fb_resource_id, (gpu_rect){{0 ,0 },{screen_size.width ,screen_size.height }});
357370 } else {
358371 for (uint32_t i = 0 ; i < dirty_count; i++) {
359372 gpu_rect r = dirty_rects[i];
360- transfer_to_host (r);
373+ transfer_to_host (fb_resource_id, r);
361374 }
362375 }
363376
@@ -369,7 +382,7 @@ void VirtioGPUDriver::flush() {
369382 cmd->hdr .padding [0 ] = 0 ;
370383 cmd->hdr .padding [1 ] = 0 ;
371384 cmd->hdr .padding [2 ] = 0 ;
372- cmd->resource_id = GPU_RESOURCE_ID ;
385+ cmd->resource_id = fb_resource_id ;
373386 cmd->padding = 0 ;
374387 cmd->rect .x = 0 ;
375388 cmd->rect .y = 0 ;
@@ -478,4 +491,66 @@ gpu_size VirtioGPUDriver::get_screen_size(){
478491
479492draw_ctx VirtioGPUDriver::get_ctx (){
480493 return (uint32_t *)framebuffer;
481- }
494+ }
495+
496+ void VirtioGPUDriver::setup_cursor ()
497+ {
498+ cursor_resource_id = new_resource_id ();
499+ size_t cursor_size = 64 *64 *BPP ;
500+ create_2d_resource (cursor_resource_id, {64 ,64 });
501+ uint32_t *cursor = (uint32_t *)kalloc (gpu_dev.memory_page , cursor_size, ALIGN_4KB , true , true );
502+ for (uint32_t i = 0 ; i < 64 *64 ; i++) cursor[i] = 0xB4DD13 ;
503+ attach_backing (cursor_resource_id, (sizedptr){(uintptr_t )cursor, cursor_size});
504+ transfer_to_host (cursor_resource_id, {{0 ,0 },{64 ,64 }});
505+ }
506+
507+ struct virtio_gpu_cursor_pos {
508+ uint32_t scanout_id;
509+ uint32_t x;
510+ uint32_t y;
511+ uint32_t padding;
512+ };
513+
514+ struct virtio_gpu_update_cursor {
515+ virtio_gpu_ctrl_hdr hdr;
516+ virtio_gpu_cursor_pos pos;
517+ uint32_t resource_id;
518+ uint32_t hot_x;
519+ uint32_t hot_y;
520+ uint32_t padding;
521+ };
522+ static_assert (sizeof (virtio_gpu_update_cursor) == 56 , " Update cursor command must be 56 bytes" );
523+
524+ void VirtioGPUDriver::update_cursor (uint32_t x, uint32_t y, bool full)
525+ {
526+ select_queue (&gpu_dev, CURSOR_QUEUE );
527+
528+ virtio_gpu_update_cursor* cmd = (virtio_gpu_update_cursor*)kalloc (gpu_dev.memory_page , sizeof (virtio_gpu_update_cursor), ALIGN_4KB , true , true );
529+
530+ cmd->hdr .type = full ? VIRTIO_GPU_CMD_UPDATE_CURSOR : VIRTIO_GPU_CMD_MOVE_CURSOR ;
531+ cmd->pos .scanout_id = scanout_id;
532+ cmd->pos .x = x;
533+ cmd->pos .y = y;
534+ cmd->resource_id = cursor_resource_id;
535+
536+ virtio_gpu_ctrl_hdr* resp = (virtio_gpu_ctrl_hdr*)kalloc (gpu_dev.memory_page , sizeof (virtio_gpu_ctrl_hdr), ALIGN_4KB , true , true );
537+
538+ if (!virtio_send (&gpu_dev, gpu_dev.common_cfg ->queue_desc , gpu_dev.common_cfg ->queue_driver , gpu_dev.common_cfg ->queue_device ,
539+ (uintptr_t )cmd, sizeof (virtio_gpu_update_cursor), (uintptr_t )resp, sizeof (virtio_gpu_ctrl_hdr), VIRTQ_DESC_F_WRITE )){
540+ select_queue (&gpu_dev, CONTROL_QUEUE );
541+ kfree ((void *)cmd, sizeof (virtio_gpu_update_cursor));
542+ kfree ((void *)resp, sizeof (virtio_gpu_ctrl_hdr));
543+ return ;
544+ }
545+
546+ select_queue (&gpu_dev, CONTROL_QUEUE );
547+
548+ if (resp->type != VIRTIO_GPU_RESP_OK_NODATA ) {
549+ kfree ((void *)cmd, sizeof (virtio_gpu_update_cursor));
550+ kfree ((void *)resp, sizeof (virtio_gpu_ctrl_hdr));
551+ return ;
552+ }
553+
554+ kfree ((void *)cmd, sizeof (virtio_gpu_update_cursor));
555+ kfree ((void *)resp, sizeof (virtio_gpu_ctrl_hdr));
556+ }
0 commit comments