@@ -127,16 +127,27 @@ struct key_map_entry key_map[] = {
127127};
128128
129129struct display_info {
130+ /* Request type: primary or cursor */
131+ int render_type ;
132+
133+ /* Primary plane */
130134 struct gpu_resource resource ;
131- uint32_t sdl_format ;
135+ uint32_t primary_sdl_format ;
136+ SDL_Texture * primary_texture ;
137+
138+ /* Cursor plane */
139+ struct gpu_resource cursor ;
140+ uint32_t cursor_sdl_format ;
141+ uint32_t * cursor_img ;
142+ SDL_Rect cursor_rect ; /* Cursor size and position */
143+ SDL_Texture * cursor_texture ;
144+
132145 SDL_mutex * img_mtx ;
133146 SDL_cond * img_cond ;
134147 SDL_Thread * win_thread ;
135148 SDL_Thread * ev_thread ;
136149 SDL_Window * window ;
137150 SDL_Renderer * renderer ;
138- SDL_Surface * surface ;
139- SDL_Texture * texture ;
140151};
141152
142153static struct display_info displays [VIRTIO_GPU_MAX_SCANOUTS ];
@@ -203,6 +214,7 @@ static int window_thread(void *data)
203214{
204215 struct display_info * display = (struct display_info * ) data ;
205216 struct gpu_resource * resource = & display -> resource ;
217+ struct gpu_resource * cursor = & display -> cursor ;
206218
207219 /* Create SDL window */
208220 display -> window = SDL_CreateWindow ("semu" , SDL_WINDOWPOS_UNDEFINED ,
@@ -232,24 +244,57 @@ static int window_thread(void *data)
232244 ((struct display_info * ) data )-> ev_thread =
233245 SDL_CreateThread (event_thread , NULL , data );
234246
247+ SDL_Surface * surface ;
248+
235249 while (1 ) {
250+ /* Mutex lock */
236251 SDL_LockMutex (display -> img_mtx );
237252
238253 /* Wait until the image is arrived */
239254 while (SDL_CondWaitTimeout (display -> img_cond , display -> img_mtx ,
240255 SDL_COND_TIMEOUT ))
241256 ;
242257
243- /* Render image */
244- display -> surface = SDL_CreateRGBSurfaceWithFormatFrom (
245- resource -> image , resource -> width , resource -> height ,
246- resource -> bits_per_pixel , resource -> stride , display -> sdl_format );
247- display -> texture =
248- SDL_CreateTextureFromSurface (display -> renderer , display -> surface );
249- SDL_RenderCopy (display -> renderer , display -> texture , NULL , NULL );
258+ if (display -> render_type == RENDER_PRIMARY_PLANE ) {
259+ /* Generate primary plane texture */
260+ surface = SDL_CreateRGBSurfaceWithFormatFrom (
261+ resource -> image , resource -> width , resource -> height ,
262+ resource -> bits_per_pixel , resource -> stride ,
263+ display -> primary_sdl_format );
264+
265+ SDL_DestroyTexture (display -> primary_texture );
266+ display -> primary_texture =
267+ SDL_CreateTextureFromSurface (display -> renderer , surface );
268+ SDL_FreeSurface (surface );
269+ } else if (display -> render_type == UPDATE_CURSOR_RESOURCE ) {
270+ /* Generate cursor plane texture */
271+ surface = SDL_CreateRGBSurfaceWithFormatFrom (
272+ cursor -> image , cursor -> width , cursor -> height , CURSOR_BPP ,
273+ CURSOR_STRIDE , SDL_PIXELFORMAT_ARGB8888 );
274+
275+ SDL_DestroyTexture (display -> cursor_texture );
276+ display -> cursor_texture =
277+ SDL_CreateTextureFromSurface (display -> renderer , surface );
278+ SDL_FreeSurface (surface );
279+ } else if (display -> render_type == CLEAR_CURSOR_RESOURCE ) {
280+ SDL_DestroyTexture (display -> cursor_texture );
281+ display -> cursor_texture = NULL ;
282+ }
283+
284+ /* Render primary and cursor planes */
285+ SDL_RenderClear (display -> renderer );
286+
287+ if (display -> primary_texture )
288+ SDL_RenderCopy (display -> renderer , display -> primary_texture , NULL ,
289+ NULL );
290+
291+ if (display -> cursor_texture )
292+ SDL_RenderCopy (display -> renderer , display -> cursor_texture , NULL ,
293+ & display -> cursor_rect );
294+
250295 SDL_RenderPresent (display -> renderer );
251- SDL_DestroyTexture (display -> texture );
252296
297+ /* Mutex unlock */
253298 SDL_UnlockMutex (display -> img_mtx );
254299 }
255300}
@@ -314,15 +359,87 @@ static bool virtio_gpu_to_sdl_format(uint32_t virtio_gpu_format,
314359 }
315360}
316361
362+ void cursor_clear (int scanout_id )
363+ {
364+ /* Reset cursor information */
365+ struct display_info * display = & displays [scanout_id ];
366+ memset (& display -> cursor_rect , 0 , sizeof (SDL_Rect ));
367+ display -> cursor_sdl_format = 0 ;
368+
369+ /* Reset cursor resource */
370+ memset (& display -> cursor , 0 , sizeof (struct gpu_resource ));
371+ free (display -> cursor_img );
372+ display -> cursor_img = NULL ;
373+ display -> cursor .image = NULL ;
374+
375+ /* Trigger plane rendering */
376+ display -> render_type = CLEAR_CURSOR_RESOURCE ;
377+ SDL_CondSignal (display -> img_cond );
378+ }
379+
380+ void cursor_update (struct gpu_resource * resource , int scanout_id , int x , int y )
381+ {
382+ /* Convert virtio-gpu resource format to SDL format */
383+ uint32_t sdl_format ;
384+ bool legal_format = virtio_gpu_to_sdl_format (resource -> format , & sdl_format );
385+
386+ if (!legal_format ) {
387+ fprintf (stderr , "Invalid resource format.\n" );
388+ return ;
389+ }
390+
391+ /* Update cursor information */
392+ struct display_info * display = & displays [scanout_id ];
393+ display -> cursor_rect .x = x ;
394+ display -> cursor_rect .y = y ;
395+ display -> cursor_rect .w = resource -> width ;
396+ display -> cursor_rect .h = resource -> height ;
397+ display -> cursor_sdl_format = sdl_format ;
398+
399+ /* Cursor resource update */
400+ memcpy (& display -> cursor , resource , sizeof (struct gpu_resource ));
401+ size_t pixels_size = sizeof (uint32_t ) * resource -> width * resource -> height ;
402+ free (display -> cursor_img );
403+ display -> cursor_img = malloc (pixels_size );
404+ display -> cursor .image = display -> cursor_img ;
405+ memcpy (display -> cursor_img , resource -> image , pixels_size );
406+
407+ /* Trigger cursor rendering */
408+ display -> render_type = UPDATE_CURSOR_RESOURCE ;
409+ SDL_CondSignal (display -> img_cond );
410+ }
411+
412+ void cursor_move (int scanout_id , int x , int y )
413+ {
414+ /* Update cursor position */
415+ struct display_info * display = & displays [scanout_id ];
416+ display -> cursor_rect .x = x ;
417+ display -> cursor_rect .y = y ;
418+
419+ /* Trigger cursor rendering */
420+ display -> render_type = MOVE_CURSOR_POSITION ;
421+ SDL_CondSignal (display -> img_cond );
422+ }
423+
317424void window_render (struct gpu_resource * resource )
318425{
319426 int id = resource -> scanout_id ;
427+ struct display_info * display = & displays [id ];
428+
429+ /* Convert virtio-gpu resource format to SDL format */
430+ uint32_t sdl_format ;
431+ bool legal_format = virtio_gpu_to_sdl_format (resource -> format , & sdl_format );
432+
433+ if (!legal_format ) {
434+ fprintf (stderr , "Invalid resource format.\n" );
435+ return ;
436+ }
320437
321- /* Resource update */
322- memcpy (& displays [id ].resource , resource , sizeof (struct gpu_resource ));
323- bool legal_format =
324- virtio_gpu_to_sdl_format (resource -> format , & displays [id ].sdl_format );
438+ /* Update primary plane resource */
439+ display -> primary_sdl_format = sdl_format ;
440+ memcpy (& display -> resource , resource , sizeof (struct gpu_resource ));
325441
326- if (legal_format )
327- SDL_CondSignal (displays [id ].img_cond );
442+ /* Trigger primary plane rendering */
443+ displays [id ].render_type = RENDER_PRIMARY_PLANE ;
444+ SDL_CondSignal (display -> img_cond );
328445}
0 commit comments