@@ -20,21 +20,27 @@ typedef struct {
2020 bool disable_speaker_icon ;
2121 gfx_border_t border ;
2222 struct {
23- sg_image img ; // framebuffer texture, RGBA8 or R8 if paletted
24- sg_image pal_img ; // optional color palette texture
23+ struct { // framebuffer texture, RGBA8 or R8 if paletted
24+ sg_image img ;
25+ sg_view tex_view ;
26+ } vidmem ;
27+ struct { // optional color palette texture
28+ sg_image img ;
29+ sg_view tex_view ;
30+ } pal ;
2531 sg_sampler smp ;
2632 chips_dim_t dim ;
2733 bool paletted ;
2834 } fb ;
2935 struct {
30- chips_rect_t view ;
36+ chips_rect_t viewport ;
3137 chips_dim_t pixel_aspect ;
3238 sg_image img ;
39+ sg_view tex_view ;
3340 sg_sampler smp ;
3441 sg_buffer vbuf ;
3542 sg_pipeline pip ;
36- sg_attachments attachments ;
37- sg_pass_action pass_action ;
43+ sg_pass pass ;
3844 } offscreen ;
3945 struct {
4046 sg_buffer vbuf ;
@@ -43,7 +49,7 @@ typedef struct {
4349 bool portrait ;
4450 } display ;
4551 struct {
46- sg_image img ;
52+ sg_view tex_view ;
4753 sg_sampler smp ;
4854 sgl_pipeline pip ;
4955 chips_dim_t dim ;
@@ -172,7 +178,7 @@ chips_dim_t gfx_pixel_aspect(void) {
172178 return state .offscreen .pixel_aspect ;
173179}
174180
175- sg_image gfx_create_icon_texture (const uint8_t * packed_pixels , int width , int height , int stride ) {
181+ sg_view gfx_create_icon_texview (const uint8_t * packed_pixels , int width , int height , int stride , const char * label ) {
176182 const size_t pixel_data_size = width * height * sizeof (uint32_t );
177183 uint32_t * pixels = malloc (pixel_data_size );
178184 assert (pixels );
@@ -201,54 +207,71 @@ sg_image gfx_create_icon_texture(const uint8_t* packed_pixels, int width, int he
201207 .pixel_format = SG_PIXELFORMAT_RGBA8 ,
202208 .width = width ,
203209 .height = height ,
204- .data .subimage [0 ][0 ] = { .ptr = pixels , .size = pixel_data_size }
210+ .data .mip_levels [0 ] = { .ptr = pixels , .size = pixel_data_size },
211+ .label = label ,
205212 });
206213 free (pixels );
207- return img ;
214+ sg_view view = sg_make_view (& (sg_view_desc ){ .texture .image = img , .label = label });
215+ return view ;
208216}
209217
210218// this function will be called at init time and when the emulator framebuffer size changes
211219static void gfx_init_images_and_pass (void ) {
212220 // destroy previous resources (if exist)
213- sg_destroy_image (state .fb .img );
221+ sg_destroy_image (state .fb .vidmem .img );
222+ sg_destroy_view (state .fb .vidmem .tex_view );
214223 sg_destroy_sampler (state .fb .smp );
215224 sg_destroy_image (state .offscreen .img );
225+ sg_destroy_view (state .offscreen .tex_view );
226+ sg_destroy_view (state .offscreen .pass .attachments .colors [0 ]);
216227 sg_destroy_sampler (state .offscreen .smp );
217- sg_destroy_attachments (state .offscreen .attachments );
218228
219- // a texture with the emulator's raw pixel data
229+ // an image and texture-view with the emulator's raw pixel data
220230 assert ((state .fb .dim .width > 0 ) && (state .fb .dim .height > 0 ));
221- state .fb .img = sg_make_image (& (sg_image_desc ){
231+ state .fb .vidmem . img = sg_make_image (& (sg_image_desc ){
222232 .usage .stream_update = true,
223233 .width = state .fb .dim .width ,
224234 .height = state .fb .dim .height ,
225235 .pixel_format = state .fb .paletted ? SG_PIXELFORMAT_R8 : SG_PIXELFORMAT_RGBA8 ,
236+ .label = "vidmem-image" ,
237+ });
238+ state .fb .vidmem .tex_view = sg_make_view (& (sg_view_desc ){
239+ .texture .image = state .fb .vidmem .img ,
240+ .label = "vidmem-tex-view" ,
226241 });
227242
228243 // a sampler for sampling the emulators raw pixel data
229244 state .fb .smp = sg_make_sampler (& (sg_sampler_desc ){
230245 .min_filter = SG_FILTER_NEAREST ,
231246 .mag_filter = SG_FILTER_NEAREST ,
232247 .wrap_u = SG_WRAP_CLAMP_TO_EDGE ,
233- .wrap_v = SG_WRAP_CLAMP_TO_EDGE
248+ .wrap_v = SG_WRAP_CLAMP_TO_EDGE ,
249+ .label = "vidmem-sampler" ,
234250 });
235251
236- // 2x-upscaling render target texture, sampler and pass
237- assert ((state .offscreen .view .width > 0 ) && (state .offscreen .view .height > 0 ));
252+ // 2x-upscaling render target image, views and sampler
253+ assert ((state .offscreen .viewport .width > 0 ) && (state .offscreen .viewport .height > 0 ));
238254 state .offscreen .img = sg_make_image (& (sg_image_desc ){
239- .usage .render_attachment = true,
240- .width = 2 * state .offscreen .view .width ,
241- .height = 2 * state .offscreen .view .height ,
255+ .usage .color_attachment = true,
256+ .width = 2 * state .offscreen .viewport .width ,
257+ .height = 2 * state .offscreen .viewport .height ,
242258 .sample_count = 1 ,
259+ .label = "upscale-image"
260+ });
261+ state .offscreen .tex_view = sg_make_view (& (sg_view_desc ){
262+ .texture .image = state .offscreen .img ,
263+ .label = "upscale-texview" ,
264+ });
265+ state .offscreen .pass .attachments .colors [0 ] = sg_make_view (& (sg_view_desc ){
266+ .color_attachment .image = state .offscreen .img ,
267+ .label = "upscale-attachment-view" ,
243268 });
244269 state .offscreen .smp = sg_make_sampler (& (sg_sampler_desc ){
245270 .min_filter = SG_FILTER_LINEAR ,
246271 .mag_filter = SG_FILTER_LINEAR ,
247272 .wrap_u = SG_WRAP_CLAMP_TO_EDGE ,
248273 .wrap_v = SG_WRAP_CLAMP_TO_EDGE ,
249- });
250- state .offscreen .attachments = sg_make_attachments (& (sg_attachments_desc ){
251- .colors [0 ].image = state .offscreen .img
274+ .label = "upscale-sampler" ,
252275 });
253276}
254277
@@ -258,10 +281,13 @@ void gfx_init(const gfx_desc_t* desc) {
258281 .image_pool_size = 128 ,
259282 .shader_pool_size = 16 ,
260283 .pipeline_pool_size = 16 ,
261- .attachments_pool_size = 2 ,
284+ .view_pool_size = 256 ,
262285 .environment = sglue_environment (),
263286 .logger .func = slog_func ,
264287 });
288+ if (desc -> init_extra_cb ) {
289+ desc -> init_extra_cb ();
290+ }
265291 sgl_setup (& (sgl_desc_t ){
266292 .max_vertices = 16 ,
267293 .max_commands = 16 ,
@@ -285,37 +311,42 @@ void gfx_init(const gfx_desc_t* desc) {
285311 state .fb .paletted = 0 != desc -> display_info .palette .ptr ;
286312 state .offscreen .pixel_aspect .width = GFX_DEF (desc -> pixel_aspect .width , 1 );
287313 state .offscreen .pixel_aspect .height = GFX_DEF (desc -> pixel_aspect .height , 1 );
288- state .offscreen .view = desc -> display_info .screen ;
314+ state .offscreen .viewport = desc -> display_info .screen ;
289315
290316 if (state .fb .paletted ) {
291317 static uint32_t palette_buf [256 ];
292318 assert ((desc -> display_info .palette .size > 0 ) && (desc -> display_info .palette .size <= sizeof (palette_buf )));
293319 memcpy (palette_buf , desc -> display_info .palette .ptr , desc -> display_info .palette .size );
294- state .fb .pal_img = sg_make_image (& (sg_image_desc ){
320+ state .fb .pal . img = sg_make_image (& (sg_image_desc ){
295321 .width = 256 ,
296322 .height = 1 ,
297323 .pixel_format = SG_PIXELFORMAT_RGBA8 ,
298324 .data = {
299- .subimage [ 0 ] [0 ] = {
325+ .mip_levels [0 ] = {
300326 .ptr = palette_buf ,
301327 .size = sizeof (palette_buf )
302328 }
303- }
329+ },
330+ .label = "palette-image" ,
331+ });
332+ state .fb .pal .tex_view = sg_make_view (& (sg_view_desc ){
333+ .texture .image = state .fb .pal .img ,
334+ .label = "palette-texview" ,
304335 });
305336 }
306337
307- state .offscreen .pass_action = (sg_pass_action ) {
338+ state .offscreen .pass . action = (sg_pass_action ) {
308339 .colors [0 ] = { .load_action = SG_LOADACTION_DONTCARE }
309340 };
310341 state .offscreen .vbuf = sg_make_buffer (& (sg_buffer_desc ){
311- .data = SG_RANGE (gfx_verts )
342+ .data = SG_RANGE (gfx_verts ),
343+ .label = "offscreen-vbuf" ,
312344 });
313345
314346 sg_shader shd = {0 };
315347 if (state .fb .paletted ) {
316348 shd = sg_make_shader (offscreen_pal_shader_desc (sg_query_backend ()));
317- }
318- else {
349+ } else {
319350 shd = sg_make_shader (offscreen_shader_desc (sg_query_backend ()));
320351 }
321352 state .offscreen .pip = sg_make_pipeline (& (sg_pipeline_desc ){
@@ -335,6 +366,7 @@ void gfx_init(const gfx_desc_t* desc) {
335366 };
336367 state .display .vbuf = sg_make_buffer (& (sg_buffer_desc ){
337368 .data = gfx_select_vertices (),
369+ .label = "display-vbuf" ,
338370 });
339371
340372 state .display .pip = sg_make_pipeline (& (sg_pipeline_desc ){
@@ -353,16 +385,19 @@ void gfx_init(const gfx_desc_t* desc) {
353385 // textures must be 2^n for WebGL
354386 state .icon .dim .width = speaker_icon .width ;
355387 state .icon .dim .height = speaker_icon .height ;
356- state .icon .img = gfx_create_icon_texture (
388+ state .icon .tex_view = gfx_create_icon_texview (
357389 speaker_icon .pixels ,
358390 speaker_icon .width ,
359391 speaker_icon .height ,
360- speaker_icon .stride );
392+ speaker_icon .stride ,
393+ "speaker-icon"
394+ );
361395 state .icon .smp = sg_make_sampler (& (sg_sampler_desc ){
362396 .min_filter = SG_FILTER_LINEAR ,
363397 .mag_filter = SG_FILTER_LINEAR ,
364398 .wrap_u = SG_WRAP_CLAMP_TO_EDGE ,
365399 .wrap_v = SG_WRAP_CLAMP_TO_EDGE ,
400+ .label = "speaker-icon" ,
366401 });
367402
368403 // sokol-gl pipeline for alpha-blended rendering
@@ -421,7 +456,7 @@ void gfx_draw(chips_display_info_t display_info) {
421456 assert ((display_info .screen .width > 0 ) && (display_info .screen .height > 0 ));
422457 const chips_dim_t display = { .width = sapp_width (), .height = sapp_height () };
423458
424- state .offscreen .view = display_info .screen ;
459+ state .offscreen .viewport = display_info .screen ;
425460
426461 // check if emulator framebuffer size has changed, need to create new backing texture
427462 if ((display_info .frame .dim .width != state .fb .dim .width ) || (display_info .frame .dim .height != state .fb .dim .height )) {
@@ -438,7 +473,7 @@ void gfx_draw(chips_display_info_t display_info) {
438473 const float alpha = (sapp_frame_count () & 0x20 ) ? 0.0f : 1.0f ;
439474 sgl_defaults ();
440475 sgl_enable_texture ();
441- sgl_texture (state .icon .img , state .icon .smp );
476+ sgl_texture (state .icon .tex_view , state .icon .smp );
442477 sgl_matrix_mode_projection ();
443478 sgl_ortho (0.0f , (float )display .width , (float )display .height , 0.0f , -1.0f , +1.0f );
444479 sgl_c4f (1.0f , 1.0f , 1.0f , alpha );
@@ -452,35 +487,32 @@ void gfx_draw(chips_display_info_t display_info) {
452487 }
453488
454489 // copy emulator pixel data into emulator framebuffer texture
455- sg_update_image (state .fb .img , & (sg_image_data ){
456- .subimage [ 0 ] [0 ] = {
490+ sg_update_image (state .fb .vidmem . img , & (sg_image_data ){
491+ .mip_levels [0 ] = {
457492 .ptr = display_info .frame .buffer .ptr ,
458493 .size = display_info .frame .buffer .size ,
459494 }
460495 });
461496
462497 // upscale the original framebuffer 2x with nearest filtering
463- sg_begin_pass (& (sg_pass ){
464- .action = state .offscreen .pass_action ,
465- .attachments = state .offscreen .attachments
466- });
498+ sg_begin_pass (& state .offscreen .pass );
467499 sg_apply_pipeline (state .offscreen .pip );
468500 sg_apply_bindings (& (sg_bindings ){
469501 .vertex_buffers [0 ] = state .offscreen .vbuf ,
470- .images = {
471- [IMG_fb_tex ] = state .fb .img ,
472- [IMG_pal_tex ] = state .fb .pal_img ,
502+ .views = {
503+ [VIEW_fb_tex ] = state .fb .vidmem . tex_view ,
504+ [VIEW_pal_tex ] = state .fb .pal . tex_view ,
473505 },
474506 .samplers [SMP_smp ] = state .fb .smp ,
475507 });
476508 const offscreen_vs_params_t vs_params = {
477509 .uv_offset = {
478- (float )state .offscreen .view .x / (float )state .fb .dim .width ,
479- (float )state .offscreen .view .y / (float )state .fb .dim .height ,
510+ (float )state .offscreen .viewport .x / (float )state .fb .dim .width ,
511+ (float )state .offscreen .viewport .y / (float )state .fb .dim .height ,
480512 },
481513 .uv_scale = {
482- (float )state .offscreen .view .width / (float )state .fb .dim .width ,
483- (float )state .offscreen .view .height / (float )state .fb .dim .height
514+ (float )state .offscreen .viewport .width / (float )state .fb .dim .width ,
515+ (float )state .offscreen .viewport .height / (float )state .fb .dim .height
484516 }
485517 };
486518 sg_apply_uniforms (UB_offscreen_vs_params , & SG_RANGE (vs_params ));
@@ -510,7 +542,7 @@ void gfx_draw(chips_display_info_t display_info) {
510542 sg_apply_pipeline (state .display .pip );
511543 sg_apply_bindings (& (sg_bindings ){
512544 .vertex_buffers [0 ] = state .display .vbuf ,
513- .images [ IMG_tex ] = state .offscreen .img ,
545+ .views [ VIEW_tex ] = state .offscreen .tex_view ,
514546 .samplers [SMP_smp ] = state .offscreen .smp ,
515547 });
516548 sg_draw (0 , 4 , 1 );
@@ -519,14 +551,13 @@ void gfx_draw(chips_display_info_t display_info) {
519551 sgl_draw ();
520552 if (state .draw_extra_cb ) {
521553 state .draw_extra_cb (& (gfx_draw_info_t ){
522- .display_image = state .offscreen .img ,
554+ .display_texview = state .offscreen .tex_view ,
523555 .display_sampler = state .offscreen .smp ,
524556 .display_info = display_info ,
525557 });
526558 }
527559 sg_end_pass ();
528560 sg_commit ();
529-
530561}
531562
532563void gfx_shutdown () {
0 commit comments