@@ -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,59 @@ 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_RESOURCE ) {
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_RESOURCE ) {
285+ SDL_DestroyTexture (display -> cursor_texture );
286+ display -> cursor_texture = NULL ;
287+ }
288+
289+ /* Render primary and cursor planes */
290+ SDL_RenderClear (display -> renderer );
291+
292+ if (display -> primary_texture )
293+ SDL_RenderCopy (display -> renderer , display -> primary_texture , NULL ,
294+ NULL );
295+
296+ if (display -> cursor_texture )
297+ SDL_RenderCopy (display -> renderer , display -> cursor_texture , NULL ,
298+ & display -> cursor_rect );
299+
250300 SDL_RenderPresent (display -> renderer );
251- SDL_DestroyTexture (display -> texture );
252301
302+ /* Mutex unlock */
253303 SDL_UnlockMutex (display -> img_mtx );
254304 }
255305}
@@ -314,15 +364,87 @@ static bool virtio_gpu_to_sdl_format(uint32_t virtio_gpu_format,
314364 }
315365}
316366
367+ void cursor_clear (int scanout_id )
368+ {
369+ /* Reset cursor information */
370+ struct display_info * display = & displays [scanout_id ];
371+ memset (& display -> cursor_rect , 0 , sizeof (SDL_Rect ));
372+ display -> cursor_sdl_format = 0 ;
373+
374+ /* Reset cursor resource */
375+ memset (& display -> cursor , 0 , sizeof (struct gpu_resource ));
376+ free (display -> cursor_img );
377+ display -> cursor_img = NULL ;
378+ display -> cursor .image = NULL ;
379+
380+ /* Trigger plane rendering */
381+ display -> render_type = CLEAR_CURSOR_RESOURCE ;
382+ SDL_CondSignal (display -> img_cond );
383+ }
384+
385+ void cursor_update (struct gpu_resource * resource , int scanout_id , int x , int y )
386+ {
387+ /* Convert virtio-gpu resource format to SDL format */
388+ uint32_t sdl_format ;
389+ bool legal_format = virtio_gpu_to_sdl_format (resource -> format , & sdl_format );
390+
391+ if (!legal_format ) {
392+ fprintf (stderr , "Invalid resource format.\n" );
393+ return ;
394+ }
395+
396+ /* Update cursor information */
397+ struct display_info * display = & displays [scanout_id ];
398+ display -> cursor_rect .x = x ;
399+ display -> cursor_rect .y = y ;
400+ display -> cursor_rect .w = resource -> width ;
401+ display -> cursor_rect .h = resource -> height ;
402+ display -> cursor_sdl_format = sdl_format ;
403+
404+ /* Cursor resource update */
405+ memcpy (& display -> cursor , resource , sizeof (struct gpu_resource ));
406+ size_t pixels_size = sizeof (uint32_t ) * resource -> width * resource -> height ;
407+ free (display -> cursor_img );
408+ display -> cursor_img = malloc (pixels_size );
409+ display -> cursor .image = display -> cursor_img ;
410+ memcpy (display -> cursor_img , resource -> image , pixels_size );
411+
412+ /* Trigger cursor rendering */
413+ display -> render_type = UPDATE_CURSOR_RESOURCE ;
414+ SDL_CondSignal (display -> img_cond );
415+ }
416+
417+ void cursor_move (int scanout_id , int x , int y )
418+ {
419+ /* Update cursor position */
420+ struct display_info * display = & displays [scanout_id ];
421+ display -> cursor_rect .x = x ;
422+ display -> cursor_rect .y = y ;
423+
424+ /* Trigger cursor rendering */
425+ display -> render_type = MOVE_CURSOR_POSITION ;
426+ SDL_CondSignal (display -> img_cond );
427+ }
428+
317429void window_render (struct gpu_resource * resource )
318430{
319431 int id = resource -> scanout_id ;
432+ struct display_info * display = & displays [id ];
433+
434+ /* Convert virtio-gpu resource format to SDL format */
435+ uint32_t sdl_format ;
436+ bool legal_format = virtio_gpu_to_sdl_format (resource -> format , & sdl_format );
437+
438+ if (!legal_format ) {
439+ fprintf (stderr , "Invalid resource format.\n" );
440+ return ;
441+ }
320442
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 );
443+ /* Update primary plane resource */
444+ display -> primary_sdl_format = sdl_format ;
445+ memcpy (& display -> resource , resource , sizeof (struct gpu_resource ));
325446
326- if (legal_format )
327- SDL_CondSignal (displays [id ].img_cond );
447+ /* Trigger primary plane rendering */
448+ displays [id ].render_type = RENDER_PRIMARY_PLANE ;
449+ SDL_CondSignal (display -> img_cond );
328450}
0 commit comments