2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
9 #include "shaders/blit.h"
10 #include "shaders/blitblur.h"
11 #include "shaders/blitcolour.h"
14 #include "shaders/standard.h"
15 #include "shaders/vblend.h"
18 VG_STATIC
void render_water_texture( camera
*cam
);
19 VG_STATIC
void render_water_surface( camera
*cam
);
20 VG_STATIC
void render_world( camera
*cam
);
21 VG_STATIC
void shader_link_standard_ub( GLuint shader
, int texture_id
);
22 VG_STATIC
void render_world_depth( camera
*cam
);
27 typedef struct framebuffer framebuffer
;
31 * All standard buffers used in rendering
33 VG_STATIC
struct pipeline
43 struct ub_world_lighting
46 v4f g_light_colours
[3],
47 g_light_directions
[3],
58 v4f g_point_light_positions
[32];
59 v4f g_point_light_colours
[32];
71 float shadow_spread
, shadow_length
;
72 GLuint ubo_world_lighting
,
83 .colour
= { 1.36f
, 1.35f
, 1.01f
},
84 .dir
= { 0.63f
, -0.08f
}
88 .colour
= { 0.33f
, 0.56f
, 0.64f
},
89 .dir
= { -2.60f
, -0.13f
}
93 .colour
= { 0.05f
, 0.05f
, 0.23f
},
94 .dir
= { 2.60f
, -0.84f
}
97 .shadow_spread
= 0.65f
,
98 .shadow_length
= 9.50f
,
102 .g_ambient_colour
= { 0.09f
, 0.03f
, 0.07f
}
108 const char *display_name
;
113 struct framebuffer_attachment
115 const char *display_name
;
117 enum framebuffer_attachment_type
119 k_framebuffer_attachment_type_none
,
120 k_framebuffer_attachment_type_colour
,
121 k_framebuffer_attachment_type_renderbuffer
125 enum framebuffer_quality_profile
127 k_framebuffer_quality_all
,
128 k_framebuffer_quality_high_only
132 GLenum internalformat
,
150 * The primary draw target
153 .link
= &gpipeline
.fb_main
,
158 "colour", k_framebuffer_attachment_type_colour
,
160 .internalformat
= GL_RGB
,
162 .type
= GL_UNSIGNED_BYTE
,
163 .attachment
= GL_COLOR_ATTACHMENT0
166 "motion", k_framebuffer_attachment_type_colour
,
168 .quality
= k_framebuffer_quality_high_only
,
169 .internalformat
= GL_RG16F
,
172 .attachment
= GL_COLOR_ATTACHMENT1
175 "depth_stencil", k_framebuffer_attachment_type_renderbuffer
,
177 .internalformat
= GL_DEPTH24_STENCIL8
,
178 .attachment
= GL_DEPTH_STENCIL_ATTACHMENT
184 * A ortho projection of the world, used for shadows and ocean colouring.
185 * Note: it does not have a render buffer attachement because it's
186 * intended to be drawn to in a MAX blending mode
189 .link
= &gpipeline
.fb_heightmap
,
196 "depth", k_framebuffer_attachment_type_colour
,
198 .internalformat
= GL_R32F
,
201 .attachment
= GL_COLOR_ATTACHMENT0
207 * Second rendered view from the perspective of the water reflection
210 .link
= &gpipeline
.fb_water_reflection
,
215 "colour", k_framebuffer_attachment_type_colour
,
216 .internalformat
= GL_RGB
,
218 .type
= GL_UNSIGNED_BYTE
,
219 .attachment
= GL_COLOR_ATTACHMENT0
222 "depth_stencil", k_framebuffer_attachment_type_renderbuffer
,
224 .internalformat
= GL_DEPTH24_STENCIL8
,
225 .attachment
= GL_DEPTH_STENCIL_ATTACHMENT
231 * Thid rendered view from the perspective of the camera, but just
232 * captures stuff thats under the water
235 .link
= &gpipeline
.fb_water_beneath
,
240 "colour", k_framebuffer_attachment_type_colour
,
241 .internalformat
= GL_RGBA
,
243 .type
= GL_UNSIGNED_BYTE
,
244 .attachment
= GL_COLOR_ATTACHMENT0
247 "depth_stencil", k_framebuffer_attachment_type_renderbuffer
,
249 .internalformat
= GL_DEPTH24_STENCIL8
,
250 .attachment
= GL_DEPTH_STENCIL_ATTACHMENT
257 * Get the current (automatically scaled or fixed) resolution of framebuffer
259 VG_STATIC
void render_fb_get_current_res( struct framebuffer
*fb
,
262 if( fb
->resolution_div
)
264 *x
= vg
.window_x
/ fb
->resolution_div
;
265 *y
= vg
.window_y
/ fb
->resolution_div
;
275 * Bind framebuffer for drawing to
277 VG_STATIC
void render_fb_bind( framebuffer
*fb
)
280 render_fb_get_current_res( fb
, &x
, &y
);
281 glBindFramebuffer( GL_FRAMEBUFFER
, fb
->fb
);
282 glViewport( 0, 0, x
, y
);
286 * Bind framebuffer attachment's texture
288 VG_STATIC
void render_fb_bind_texture( framebuffer
*fb
,
289 int attachment
, int slot
)
291 struct framebuffer_attachment
*at
= &fb
->attachments
[attachment
];
293 if( at
->purpose
!= k_framebuffer_attachment_type_colour
)
295 vg_fatal_exit_loop( "illegal operation: bind non-colour framebuffer"
296 " attachment to texture slot" );
299 glActiveTexture( GL_TEXTURE0
+ slot
);
300 glBindTexture( GL_TEXTURE_2D
, fb
->attachments
[attachment
].id
);
307 VG_STATIC
void shader_link_standard_ub( GLuint shader
, int texture_id
)
309 GLuint idx
= glGetUniformBlockIndex( shader
, "ub_world_lighting" );
310 glUniformBlockBinding( shader
, idx
, 0 );
312 render_fb_bind_texture( gpipeline
.fb_heightmap
, 0, texture_id
);
313 glUniform1i( glGetUniformLocation( shader
, "g_world_depth" ), texture_id
);
316 VG_STATIC
void render_update_lighting_ub(void)
318 struct ub_world_lighting
*winf
= &gpipeline
.ub_world_lighting
;
321 for( int i
=0; i
<3; i
++ )
323 struct light_widget
*lw
= &gpipeline
.widgets
[i
];
327 float pitch
= lw
->dir
[0],
331 v3_copy( (v3f
){ xz
*cosf(yaw
), sinf(pitch
), xz
*sinf(yaw
) },
332 winf
->g_light_directions
[c
] );
333 v3_copy( lw
->colour
, winf
->g_light_colours
[c
] );
339 winf
->g_light_count
= c
;
340 winf
->g_light_directions
[0][3] = gpipeline
.shadow_length
;
341 winf
->g_light_colours
[0][3] = gpipeline
.shadow_spread
;
343 if( vg
.quality_profile
== k_quality_profile_low
)
344 winf
->g_shadow_samples
= 0;
346 winf
->g_shadow_samples
= 8;
348 glBindBuffer( GL_UNIFORM_BUFFER
, gpipeline
.ubo_world_lighting
);
349 glBufferSubData( GL_UNIFORM_BUFFER
, 0, sizeof(struct ub_world_lighting
),
350 &gpipeline
.ub_world_lighting
);
353 #define FB_FORMAT_STR( E ) { E, #E },
356 * Convert OpenGL attachment ID enum to string
358 VG_STATIC
const char *render_fb_attachment_str( GLenum e
)
360 struct { GLenum e
; const char *str
; }
363 FB_FORMAT_STR(GL_COLOR_ATTACHMENT0
)
364 FB_FORMAT_STR(GL_COLOR_ATTACHMENT1
)
365 FB_FORMAT_STR(GL_COLOR_ATTACHMENT2
)
366 FB_FORMAT_STR(GL_COLOR_ATTACHMENT3
)
367 FB_FORMAT_STR(GL_COLOR_ATTACHMENT4
)
368 FB_FORMAT_STR(GL_DEPTH_STENCIL_ATTACHMENT
)
371 for( int i
=0; i
<vg_list_size(formats
); i
++ )
372 if( formats
[i
].e
== e
)
373 return formats
[i
].str
;
379 * Convert OpenGL texture format enums from TexImage2D table 1,2 &
380 * RenderBufferStorage Table 1, into strings
382 VG_STATIC
const char *render_fb_format_str( GLenum format
)
384 struct { GLenum e
; const char *str
; }
388 FB_FORMAT_STR(GL_DEPTH_COMPONENT
)
389 FB_FORMAT_STR(GL_DEPTH_STENCIL
)
390 FB_FORMAT_STR(GL_RED
)
392 FB_FORMAT_STR(GL_RGB
)
393 FB_FORMAT_STR(GL_RGBA
)
395 /* Render buffer formats */
396 FB_FORMAT_STR(GL_DEPTH_COMPONENT16
)
397 FB_FORMAT_STR(GL_DEPTH_COMPONENT24
)
398 FB_FORMAT_STR(GL_DEPTH_COMPONENT32F
)
399 FB_FORMAT_STR(GL_DEPTH24_STENCIL8
)
400 FB_FORMAT_STR(GL_DEPTH32F_STENCIL8
)
401 FB_FORMAT_STR(GL_STENCIL_INDEX8
)
405 FB_FORMAT_STR(GL_R8_SNORM
)
406 FB_FORMAT_STR(GL_R16
)
407 FB_FORMAT_STR(GL_R16_SNORM
)
408 FB_FORMAT_STR(GL_RG8
)
409 FB_FORMAT_STR(GL_RG8_SNORM
)
410 FB_FORMAT_STR(GL_RG16
)
411 FB_FORMAT_STR(GL_RG16_SNORM
)
412 FB_FORMAT_STR(GL_R3_G3_B2
)
413 FB_FORMAT_STR(GL_RGB4
)
414 FB_FORMAT_STR(GL_RGB5
)
415 FB_FORMAT_STR(GL_RGB8
)
416 FB_FORMAT_STR(GL_RGB8_SNORM
)
417 FB_FORMAT_STR(GL_RGB10
)
418 FB_FORMAT_STR(GL_RGB12
)
419 FB_FORMAT_STR(GL_RGB16_SNORM
)
420 FB_FORMAT_STR(GL_RGBA2
)
421 FB_FORMAT_STR(GL_RGBA4
)
422 FB_FORMAT_STR(GL_RGB5_A1
)
423 FB_FORMAT_STR(GL_RGBA8
)
424 FB_FORMAT_STR(GL_RGBA8_SNORM
)
425 FB_FORMAT_STR(GL_RGB10_A2
)
426 FB_FORMAT_STR(GL_RGB10_A2UI
)
427 FB_FORMAT_STR(GL_RGBA12
)
428 FB_FORMAT_STR(GL_RGBA16
)
429 FB_FORMAT_STR(GL_SRGB8
)
430 FB_FORMAT_STR(GL_SRGB8_ALPHA8
)
431 FB_FORMAT_STR(GL_R16F
)
432 FB_FORMAT_STR(GL_RG16F
)
433 FB_FORMAT_STR(GL_RGB16F
)
434 FB_FORMAT_STR(GL_RGBA16F
)
435 FB_FORMAT_STR(GL_R32F
)
436 FB_FORMAT_STR(GL_RG32F
)
437 FB_FORMAT_STR(GL_RGB32F
)
438 FB_FORMAT_STR(GL_RGBA32F
)
439 FB_FORMAT_STR(GL_R11F_G11F_B10F
)
440 FB_FORMAT_STR(GL_RGB9_E5
)
441 FB_FORMAT_STR(GL_R8I
)
442 FB_FORMAT_STR(GL_R8UI
)
443 FB_FORMAT_STR(GL_R16I
)
444 FB_FORMAT_STR(GL_R16UI
)
445 FB_FORMAT_STR(GL_R32I
)
446 FB_FORMAT_STR(GL_R32UI
)
447 FB_FORMAT_STR(GL_RG8I
)
448 FB_FORMAT_STR(GL_RG8UI
)
449 FB_FORMAT_STR(GL_RG16I
)
450 FB_FORMAT_STR(GL_RG16UI
)
451 FB_FORMAT_STR(GL_RG32I
)
452 FB_FORMAT_STR(GL_RG32UI
)
453 FB_FORMAT_STR(GL_RGB8I
)
454 FB_FORMAT_STR(GL_RGB8UI
)
455 FB_FORMAT_STR(GL_RGB16I
)
456 FB_FORMAT_STR(GL_RGB16UI
)
457 FB_FORMAT_STR(GL_RGB32I
)
458 FB_FORMAT_STR(GL_RGB32UI
)
459 FB_FORMAT_STR(GL_RGBA8I
)
460 FB_FORMAT_STR(GL_RGBA8UI
)
461 FB_FORMAT_STR(GL_RGBA16I
)
462 FB_FORMAT_STR(GL_RGBA16UI
)
463 FB_FORMAT_STR(GL_RGBA32I
)
464 FB_FORMAT_STR(GL_RGBA32UI
)
467 for( int i
=0; i
<vg_list_size(formats
); i
++ )
468 if( formats
[i
].e
== format
)
469 return formats
[i
].str
;
475 * Bind and allocate texture for framebuffer attachment
477 VG_STATIC
void render_fb_allocate_texture( struct framebuffer
*fb
,
478 struct framebuffer_attachment
*a
)
481 render_fb_get_current_res( fb
, &rx
, &ry
);
483 if( a
->purpose
== k_framebuffer_attachment_type_renderbuffer
)
485 glBindRenderbuffer( GL_RENDERBUFFER
, a
->id
);
486 glRenderbufferStorage( GL_RENDERBUFFER
, GL_DEPTH24_STENCIL8
, rx
, ry
);
488 else if( a
->purpose
== k_framebuffer_attachment_type_colour
)
490 glBindTexture( GL_TEXTURE_2D
, a
->id
);
491 glTexImage2D( GL_TEXTURE_2D
, 0, a
->internalformat
, rx
, ry
,
492 0, a
->format
, a
->type
, NULL
);
497 * Full allocation of a framebuffer
499 VG_STATIC
void render_fb_allocate( struct framebuffer
*fb
)
501 glGenFramebuffers( 1, &fb
->fb
);
502 glBindFramebuffer( GL_FRAMEBUFFER
, fb
->fb
);
505 render_fb_get_current_res( fb
, &rx
, &ry
);
507 vg_info( "allocate_framebuffer( %s, %dx%d )\n", fb
->display_name
, rx
, ry
);
510 GLenum colour_attachments
[4];
511 u32 colour_count
= 0;
513 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ )
515 struct framebuffer_attachment
*attachment
= &fb
->attachments
[j
];
517 if( attachment
->purpose
== k_framebuffer_attachment_type_none
)
520 vg_info( " %s: %s\n",
521 render_fb_attachment_str( attachment
->attachment
),
522 render_fb_format_str( attachment
->internalformat
) );
524 if( attachment
->purpose
== k_framebuffer_attachment_type_renderbuffer
)
526 glGenRenderbuffers( 1, &attachment
->id
);
527 render_fb_allocate_texture( fb
, attachment
);
528 glFramebufferRenderbuffer( GL_FRAMEBUFFER
,
529 GL_DEPTH_STENCIL_ATTACHMENT
,
530 GL_RENDERBUFFER
, attachment
->id
);
532 else if( attachment
->purpose
== k_framebuffer_attachment_type_colour
)
534 glGenTextures( 1, &attachment
->id
);
535 render_fb_allocate_texture( fb
, attachment
);
536 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
537 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
538 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
539 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
541 glFramebufferTexture2D( GL_FRAMEBUFFER
, attachment
->attachment
,
542 GL_TEXTURE_2D
, attachment
->id
, 0 );
544 colour_attachments
[ colour_count
++ ] = attachment
->attachment
;
548 glDrawBuffers( colour_count
, colour_attachments
);
553 GLenum result
= glCheckFramebufferStatus( GL_FRAMEBUFFER
);
555 if( result
== GL_FRAMEBUFFER_COMPLETE
)
558 * Attatch to gpipeline
563 vg_success( " status: complete\n" );
568 if( result
== GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
)
569 vg_error( " status: Incomplete attachment" );
570 else if( result
== GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
)
571 vg_error( " status: Missing attachment" );
572 else if( result
== GL_FRAMEBUFFER_UNSUPPORTED
)
573 vg_error( " status: Unsupported framebuffer format" );
575 vg_error( " status: Generic Error" );
578 vg_fatal_exit_loop( "Incomplete framebuffer (see logs)" );
583 * Resize/Update all framebuffers(we know about)
585 VG_STATIC
void render_fb_resize(void)
587 if( !gpipeline
.ready
)
590 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ )
592 struct framebuffer
*fb
= &framebuffers
[i
];
593 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ )
595 struct framebuffer_attachment
*attachment
= &fb
->attachments
[j
];
596 render_fb_allocate_texture( fb
, attachment
);
601 VG_STATIC
int render_framebuffer_control( int argc
, char const *argv
[] );
602 VG_STATIC
void render_framebuffer_poll( int argc
, char const *argv
[] );
603 VG_STATIC
void render_init_fs_quad(void)
605 vg_info( "[render] Allocate quad\n" );
609 0.00f
,0.00f
, 1.00f
,1.00f
, 0.00f
,1.00f
,
610 0.00f
,0.00f
, 1.00f
,0.00f
, 1.00f
,1.00f
,
612 0.20f
,0.00f
, 0.80f
,1.00f
, 0.20f
,1.00f
,
613 0.20f
,0.00f
, 0.80f
,0.00f
, 0.80f
,1.00f
,
617 0.00f
,0.00f
, 0.30f
,0.30f
, 0.00f
,0.30f
,
618 0.00f
,0.00f
, 0.30f
,0.00f
, 0.30f
,0.30f
,
619 0.30f
,0.00f
, 0.60f
,0.30f
, 0.30f
,0.30f
,
620 0.30f
,0.00f
, 0.60f
,0.00f
, 0.60f
,0.30f
,
621 0.60f
,0.00f
, 0.90f
,0.30f
, 0.60f
,0.30f
,
622 0.60f
,0.00f
, 0.90f
,0.00f
, 0.90f
,0.30f
,
624 0.00f
,0.30f
, 0.30f
,0.60f
, 0.00f
,0.60f
,
625 0.00f
,0.30f
, 0.30f
,0.30f
, 0.30f
,0.60f
,
626 0.30f
,0.30f
, 0.60f
,0.60f
, 0.30f
,0.60f
,
627 0.30f
,0.30f
, 0.60f
,0.30f
, 0.60f
,0.60f
,
628 0.60f
,0.30f
, 0.90f
,0.60f
, 0.60f
,0.60f
,
629 0.60f
,0.30f
, 0.90f
,0.30f
, 0.90f
,0.60f
,
631 0.00f
,0.60f
, 0.30f
,0.90f
, 0.00f
,0.90f
,
632 0.00f
,0.60f
, 0.30f
,0.60f
, 0.30f
,0.90f
,
633 0.30f
,0.60f
, 0.60f
,0.90f
, 0.30f
,0.90f
,
634 0.30f
,0.60f
, 0.60f
,0.60f
, 0.60f
,0.90f
,
635 0.60f
,0.60f
, 0.90f
,0.90f
, 0.60f
,0.90f
,
636 0.60f
,0.60f
, 0.90f
,0.60f
, 0.90f
,0.90f
,
639 vg_function_push( (struct vg_cmd
)
642 .function
= render_framebuffer_control
,
643 .poll_suggest
= render_framebuffer_poll
646 glGenVertexArrays( 1, &gpipeline
.fsquad
.vao
);
647 glGenBuffers( 1, &gpipeline
.fsquad
.vbo
);
648 glBindVertexArray( gpipeline
.fsquad
.vao
);
649 glBindBuffer( GL_ARRAY_BUFFER
, gpipeline
.fsquad
.vbo
);
650 glBufferData( GL_ARRAY_BUFFER
, sizeof(quad
), quad
, GL_STATIC_DRAW
);
651 glBindVertexArray( gpipeline
.fsquad
.vao
);
652 glVertexAttribPointer( 0, 2, GL_FLOAT
, GL_FALSE
,
653 sizeof(float)*2, (void*)0 );
654 glEnableVertexAttribArray( 0 );
659 VG_STATIC
void render_init_uniform_buffers(void)
661 vg_info( "[render] Allocate uniform buffer\n" );
663 glGenBuffers( 1, &gpipeline
.ubo_world_lighting
);
664 glBindBuffer( GL_UNIFORM_BUFFER
, gpipeline
.ubo_world_lighting
);
665 glBufferData( GL_UNIFORM_BUFFER
, sizeof(struct ub_world_lighting
),
666 NULL
, GL_DYNAMIC_DRAW
);
668 render_update_lighting_ub();
669 glBindBufferBase( GL_UNIFORM_BUFFER
, 0, gpipeline
.ubo_world_lighting
);
674 VG_STATIC
void render_init(void)
676 shader_blit_register();
677 shader_blitblur_register();
678 shader_blitcolour_register();
680 vg_acquire_thread_sync();
683 * Complete Framebuffers
685 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ )
687 struct framebuffer
*fb
= &framebuffers
[i
];
688 render_fb_allocate( fb
);
691 render_init_fs_quad();
692 render_init_uniform_buffers();
694 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
698 vg_release_thread_sync();
704 VG_STATIC
void render_fsquad(void)
706 glBindVertexArray( gpipeline
.fsquad
.vao
);
707 glDrawArrays( GL_TRIANGLES
, 0, 6 );
710 VG_STATIC
void render_fsquad1(void)
712 glBindVertexArray( gpipeline
.fsquad
.vao
);
713 glDrawArrays( GL_TRIANGLES
, 6, 6 );
717 * Call this inside the UI function
719 VG_STATIC
void render_view_framebuffer_ui(void)
721 int viewing_count
= 0;
723 glBindVertexArray( gpipeline
.fsquad
.vao
);
725 shader_blit_uTexMain( 0 );
727 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ )
729 struct framebuffer
*fb
= &framebuffers
[i
];
731 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ )
733 struct framebuffer_attachment
*at
= &fb
->attachments
[j
];
735 if( !at
->debug_view
)
739 window
= { vg
.window_x
, vg
.window_y
};
741 corner
[0] = viewing_count
% 3;
742 corner
[1] = 1 + (viewing_count
/ 3);
743 v2_mul( corner
, window
, corner
);
744 v2_muls( corner
, 0.3f
, corner
);
745 corner
[1] = vg
.window_y
- corner
[1];
747 ui_text( (ui_rect
){ corner
[0], corner
[1], 0.0f
, 0.0f
},
748 fb
->display_name
, 2, k_text_align_left
);
749 ui_text( (ui_rect
){ corner
[0], corner
[1] + 32, 0.0f
, 0.0f
, },
750 at
->display_name
, 1, k_text_align_left
);
752 if( at
->purpose
== k_framebuffer_attachment_type_renderbuffer
)
755 v2_muladds( corner
, window
, 0.15f
, center
);
757 ui_text( (ui_rect
){ center
[0], center
[1], 0.0f
, 0.0f
},
758 "<hardware texture>", 1, k_text_align_center
);
762 render_fb_bind_texture( fb
, j
, 0 );
764 int start
= (viewing_count
+2) * 6,
766 glDrawArrays( GL_TRIANGLES
, start
, count
);
774 VG_STATIC
void render_framebuffer_show( struct framebuffer
*fb
,
775 struct framebuffer_attachment
*at
,
778 at
->debug_view
= operation
;
779 vg_info( "%s %s:%s\n", (operation
?"shown": "hidden"),
780 fb
->display_name
, at
->display_name
);
784 * arg0: command "show"/"hide"
785 * arg1: framebuffer name <name>/"all"
786 * arg2: subname <name>/none
788 VG_STATIC
int render_framebuffer_control( int argc
, char const *argv
[] )
792 vg_error( "Usage: fb \"show/hide\" <name>/\"all\" <name>/none\n" );
799 if( !strcmp( argv
[0], "show" ) )
801 else if( !strcmp( argv
[0], "hide" ) )
805 vg_error( "Unknown framebuffer operation: '%s'\n", argv
[0] );
809 if( !strcmp( argv
[1], "all" ) )
812 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ )
814 struct framebuffer
*fb
= &framebuffers
[i
];
816 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ )
818 struct framebuffer_attachment
*at
= &fb
->attachments
[j
];
820 if( at
->purpose
== k_framebuffer_attachment_type_none
)
825 render_framebuffer_show( fb
, at
, operation
);
829 if( !strcmp( fb
->display_name
, argv
[1] ) )
832 render_framebuffer_show( fb
, at
, operation
);
833 else if( !strcmp( at
->display_name
, argv
[2] ) )
834 render_framebuffer_show( fb
, at
, operation
);
843 VG_STATIC
void render_framebuffer_poll( int argc
, char const *argv
[] )
845 const char *term
= argv
[argc
-1];
849 console_suggest_score_text( "show", term
, 0 );
850 console_suggest_score_text( "hide", term
, 0 );
854 console_suggest_score_text( "all", term
, 0 );
856 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ )
858 struct framebuffer
*fb
= &framebuffers
[i
];
859 console_suggest_score_text( fb
->display_name
, term
, 0 );
866 if( !strcmp( argv
[1], "all" ) )
869 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ )
871 struct framebuffer
*fb
= &framebuffers
[i
];
873 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ )
875 struct framebuffer_attachment
*at
= &fb
->attachments
[j
];
877 if( at
->purpose
== k_framebuffer_attachment_type_none
)
882 console_suggest_score_text( at
->display_name
, term
, 0 );
884 else if( !strcmp( fb
->display_name
, argv
[1] ) )
886 console_suggest_score_text( at
->display_name
, term
, 0 );
893 #endif /* RENDER_H */