@@ -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,58 @@ 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+ } else if (CLEAR_CURSOR ) {
285+ SDL_DestroyTexture (display -> cursor_texture );
286+ }
287+
288+ /* Render primary and cursor planes */
289+ SDL_RenderClear (display -> renderer );
290+
291+ if (display -> primary_texture )
292+ SDL_RenderCopy (display -> renderer , display -> primary_texture , NULL ,
293+ NULL );
294+
295+ if (display -> cursor_texture )
296+ SDL_RenderCopy (display -> renderer , display -> cursor_texture , NULL ,
297+ & display -> cursor_rect );
298+
250299 SDL_RenderPresent (display -> renderer );
251- SDL_DestroyTexture (display -> texture );
252300
301+ /* Mutex unlock */
253302 SDL_UnlockMutex (display -> img_mtx );
254303 }
255304}
@@ -314,15 +363,87 @@ static bool virtio_gpu_to_sdl_format(uint32_t virtio_gpu_format,
314363 }
315364}
316365
366+ void cursor_clear (int scanout_id )
367+ {
368+ /* Reset cursor information */
369+ struct display_info * display = & displays [scanout_id ];
370+ memset (& display -> cursor_rect , 0 , sizeof (SDL_Rect ));
371+ display -> cursor_sdl_format = 0 ;
372+
373+ /* Reset cursor resource */
374+ memset (& display -> cursor , 0 , sizeof (struct gpu_resource ));
375+ free (display -> cursor_img );
376+ display -> cursor_img = NULL ;
377+ display -> cursor .image = NULL ;
378+
379+ /* Trigger plane rendering */
380+ display -> render_type = UPDATE_CURSOR_IMAGE ;
381+ SDL_CondSignal (display -> img_cond );
382+ }
383+
384+ void cursor_update (struct gpu_resource * resource , int scanout_id , int x , int y )
385+ {
386+ /* Convert virtio-gpu resource format to SDL format */
387+ uint32_t sdl_format ;
388+ bool legal_format = virtio_gpu_to_sdl_format (resource -> format , & sdl_format );
389+
390+ if (!legal_format ) {
391+ fprintf (stderr , "Invalid resource format.\n" );
392+ return ;
393+ }
394+
395+ /* Update cursor information */
396+ struct display_info * display = & displays [scanout_id ];
397+ display -> cursor_rect .x = x ;
398+ display -> cursor_rect .y = y ;
399+ display -> cursor_rect .w = resource -> width ;
400+ display -> cursor_rect .h = resource -> height ;
401+ display -> cursor_sdl_format = sdl_format ;
402+
403+ /* Cursor resource update */
404+ memcpy (& display -> cursor , resource , sizeof (struct gpu_resource ));
405+ size_t pixels_size = sizeof (uint32_t ) * resource -> width * resource -> height ;
406+ free (display -> cursor_img ); /* FIXME */
407+ display -> cursor_img = malloc (pixels_size );
408+ display -> cursor .image = display -> cursor_img ;
409+ memcpy (display -> cursor_img , resource -> image , pixels_size );
410+
411+ /* Trigger cursor rendering */
412+ display -> render_type = CLEAR_CURSOR ;
413+ SDL_CondSignal (display -> img_cond );
414+ }
415+
416+ void cursor_move (int scanout_id , int x , int y )
417+ {
418+ /* Update cursor position */
419+ struct display_info * display = & displays [scanout_id ];
420+ display -> cursor_rect .x = x ;
421+ display -> cursor_rect .y = y ;
422+
423+ /* Trigger cursor rendering */
424+ display -> render_type = MOVE_CURSOR ;
425+ SDL_CondSignal (display -> img_cond );
426+ }
427+
317428void window_render (struct gpu_resource * resource )
318429{
319430 int id = resource -> scanout_id ;
431+ struct display_info * display = & displays [id ];
432+
433+ /* Convert virtio-gpu resource format to SDL format */
434+ uint32_t sdl_format ;
435+ bool legal_format = virtio_gpu_to_sdl_format (resource -> format , & sdl_format );
436+
437+ if (!legal_format ) {
438+ fprintf (stderr , "Invalid resource format.\n" );
439+ return ;
440+ }
320441
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 );
442+ /* Update primary plane resource */
443+ display -> primary_sdl_format = sdl_format ;
444+ memcpy (& display -> resource , resource , sizeof (struct gpu_resource ));
325445
326- if (legal_format )
327- SDL_CondSignal (displays [id ].img_cond );
446+ /* Trigger primary plane rendering */
447+ displays [id ].render_type = RENDER_PRIMARY_PLANE ;
448+ SDL_CondSignal (display -> img_cond );
328449}
0 commit comments