@@ -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 ,
@@ -223,6 +235,9 @@ static int window_thread(void *data)
223235 exit (2 );
224236 }
225237
238+ /* FIXME */
239+ SDL_SetRenderDrawBlendMode (display -> renderer , SDL_BLENDMODE_BLEND );
240+
226241 /* Render the whole screen with black color */
227242 SDL_SetRenderDrawColor (display -> renderer , 0 , 0 , 0 , 255 );
228243 SDL_RenderClear (display -> renderer );
@@ -232,24 +247,56 @@ static int window_thread(void *data)
232247 ((struct display_info * ) data )-> ev_thread =
233248 SDL_CreateThread (event_thread , NULL , data );
234249
250+ SDL_Surface * surface ;
251+
235252 while (1 ) {
253+ /* Mutex lock */
236254 SDL_LockMutex (display -> img_mtx );
237255
238256 /* Wait until the image is arrived */
239257 while (SDL_CondWaitTimeout (display -> img_cond , display -> img_mtx ,
240258 SDL_COND_TIMEOUT ))
241259 ;
242260
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 );
261+ if (display -> render_type == RENDER_PRIMARY_PLANE ) {
262+ /* Generate primary plane texture */
263+ surface = SDL_CreateRGBSurfaceWithFormatFrom (
264+ resource -> image , resource -> width , resource -> height ,
265+ resource -> bits_per_pixel , resource -> stride ,
266+ display -> primary_sdl_format );
267+
268+ SDL_DestroyTexture (display -> primary_texture );
269+ display -> primary_texture =
270+ SDL_CreateTextureFromSurface (display -> renderer , surface );
271+ SDL_FreeSurface (surface );
272+ } else if (display -> render_type == UPDATE_CURSOR_IMAGE ) {
273+ /* Generate cursor plane texture */
274+ surface = SDL_CreateRGBSurfaceWithFormatFrom (
275+ cursor -> image , cursor -> width , cursor -> height ,
276+ cursor -> bits_per_pixel , cursor -> stride ,
277+ /*display->cursor_sdl_format*/
278+ SDL_PIXELFORMAT_RGBA32 /* FIXME */ );
279+
280+ SDL_DestroyTexture (display -> cursor_texture );
281+ display -> cursor_texture =
282+ SDL_CreateTextureFromSurface (display -> renderer , surface );
283+ SDL_FreeSurface (surface );
284+ }
285+
286+ /* Render primary and cursor planes */
287+ SDL_RenderClear (display -> renderer );
288+
289+ if (display -> primary_texture )
290+ SDL_RenderCopy (display -> renderer , display -> primary_texture , NULL ,
291+ NULL );
292+
293+ if (display -> cursor_texture )
294+ SDL_RenderCopy (display -> renderer , display -> cursor_texture , NULL ,
295+ & display -> cursor_rect );
296+
250297 SDL_RenderPresent (display -> renderer );
251- SDL_DestroyTexture (display -> texture );
252298
299+ /* Mutex unlock */
253300 SDL_UnlockMutex (display -> img_mtx );
254301 }
255302}
@@ -314,15 +361,69 @@ static bool virtio_gpu_to_sdl_format(uint32_t virtio_gpu_format,
314361 }
315362}
316363
364+ void cursor_update (struct gpu_resource * resource , int scanout_id , int x , int y )
365+ {
366+ /* Convert virtio-gpu resource format to SDL format */
367+ uint32_t sdl_format ;
368+ bool legal_format = virtio_gpu_to_sdl_format (resource -> format , & sdl_format );
369+
370+ if (!legal_format ) {
371+ fprintf (stderr , "Invalid resource format.\n" );
372+ return ;
373+ }
374+
375+ /* Update cursor information */
376+ struct display_info * display = & displays [scanout_id ];
377+ display -> cursor_rect .x = x ;
378+ display -> cursor_rect .y = y ;
379+ display -> cursor_rect .w = resource -> width ;
380+ display -> cursor_rect .h = resource -> height ;
381+ display -> cursor_sdl_format = sdl_format ;
382+
383+ /* Cursor resource update */
384+ memcpy (& display -> cursor , resource , sizeof (struct gpu_resource ));
385+ size_t pixels_size = sizeof (uint32_t ) * resource -> width * resource -> height ;
386+ free (display -> cursor_img ); /* FIXME */
387+ display -> cursor_img = malloc (pixels_size );
388+ display -> cursor .image = display -> cursor_img ;
389+ memcpy (display -> cursor_img , resource -> image , pixels_size );
390+
391+ /* Trigger cursor rendering */
392+ display -> render_type = UPDATE_CURSOR_IMAGE ;
393+ SDL_CondSignal (display -> img_cond );
394+ }
395+
396+ void cursor_move (int scanout_id , int x , int y )
397+ {
398+ /* Update cursor position */
399+ struct display_info * display = & displays [scanout_id ];
400+ display -> cursor_rect .x = x ;
401+ display -> cursor_rect .y = y ;
402+
403+ /* Trigger cursor rendering */
404+ display -> render_type = MOVE_CURSOR ;
405+ SDL_CondSignal (display -> img_cond );
406+ }
407+
317408void window_render (struct gpu_resource * resource )
318409{
319410 int id = resource -> scanout_id ;
411+ struct display_info * display = & displays [id ];
412+
413+ /* Convert virtio-gpu resource format to SDL format */
414+ uint32_t sdl_format ;
415+ bool legal_format = virtio_gpu_to_sdl_format (resource -> format , & sdl_format );
416+
417+ if (!legal_format ) {
418+ fprintf (stderr , "Invalid resource format.\n" );
419+ return ;
420+ }
320421
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 );
422+ /* Update main plane resource */
423+ display -> primary_sdl_format = sdl_format ;
424+ memcpy (& display -> resource , resource , sizeof (struct gpu_resource ));
325425
326- if (legal_format )
327- SDL_CondSignal (displays [id ].img_cond );
426+ /* Trigger main plane rendering */
427+ displays [id ].render_type = RENDER_PRIMARY_PLANE ;
428+ SDL_CondSignal (display -> img_cond );
328429}
0 commit comments