2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
10 #include "shaders/blit.h"
11 #include "shaders/blitblur.h"
12 #include "shaders/blitcolour.h"
13 #include "shaders/blit_transition.h"
15 #define WORKSHOP_PREVIEW_WIDTH 504
16 #define WORKSHOP_PREVIEW_HEIGHT 336
20 static f32 k_render_scale
= 1.0f
;
21 static i32 k_blur_effect
= 1;
22 static f32 k_blur_strength
= 0.3f
;
23 static f32 k_fov
= 0.86f
;
24 static f32 k_cam_height
= 0.8f
;
26 typedef struct framebuffer framebuffer
;
29 * All standard buffers used in rendering
31 static struct pipeline
{
44 const char *display_name
;
45 int resolution_div
, /* definition */
49 render_w
, /* runtime */
52 struct framebuffer_attachment
{
53 const char *display_name
;
55 enum framebuffer_attachment_type
{
56 k_framebuffer_attachment_type_none
,
57 k_framebuffer_attachment_type_texture
,
58 k_framebuffer_attachment_type_renderbuffer
,
59 k_framebuffer_attachment_type_texture_depth
63 enum framebuffer_quality_profile
{
64 k_framebuffer_quality_all
,
65 k_framebuffer_quality_high_only
69 GLenum internalformat
,
87 * The primary draw target
90 .link
= &gpipeline
.fb_main
,
95 "colour", k_framebuffer_attachment_type_texture
,
97 .internalformat
= GL_RGB
,
99 .type
= GL_UNSIGNED_BYTE
,
100 .attachment
= GL_COLOR_ATTACHMENT0
103 "motion", k_framebuffer_attachment_type_texture
,
105 .quality
= k_framebuffer_quality_high_only
,
106 .internalformat
= GL_RG16F
,
109 .attachment
= GL_COLOR_ATTACHMENT1
113 "depth_stencil", k_framebuffer_attachment_type_renderbuffer
,
115 .internalformat
= GL_DEPTH24_STENCIL8
,
117 "depth_stencil", k_framebuffer_attachment_type_texture_depth
,
118 .internalformat
= GL_DEPTH24_STENCIL8
,
119 .format
= GL_DEPTH_STENCIL
,
120 .type
= GL_UNSIGNED_INT_24_8
,
122 .attachment
= GL_DEPTH_STENCIL_ATTACHMENT
128 * Second rendered view from the perspective of the water reflection
131 .link
= &gpipeline
.fb_water_reflection
,
136 "colour", k_framebuffer_attachment_type_texture
,
137 .internalformat
= GL_RGB
,
139 .type
= GL_UNSIGNED_BYTE
,
140 .attachment
= GL_COLOR_ATTACHMENT0
143 "depth_stencil", k_framebuffer_attachment_type_renderbuffer
,
145 .internalformat
= GL_DEPTH24_STENCIL8
,
146 .attachment
= GL_DEPTH_STENCIL_ATTACHMENT
152 * Thid rendered view from the perspective of the camera, but just
153 * captures stuff thats under the water
156 .link
= &gpipeline
.fb_water_beneath
,
161 "colour", k_framebuffer_attachment_type_texture
,
162 .internalformat
= GL_RED
,
164 .type
= GL_UNSIGNED_BYTE
,
165 .attachment
= GL_COLOR_ATTACHMENT0
168 "depth_stencil", k_framebuffer_attachment_type_renderbuffer
,
170 .internalformat
= GL_DEPTH24_STENCIL8
,
171 .attachment
= GL_DEPTH_STENCIL_ATTACHMENT
177 .link
= &gpipeline
.fb_workshop_preview
,
179 .fixed_w
= WORKSHOP_PREVIEW_WIDTH
, .fixed_h
= WORKSHOP_PREVIEW_HEIGHT
,
183 "colour", k_framebuffer_attachment_type_texture
,
184 .internalformat
= GL_RGB
,
186 .type
= GL_UNSIGNED_BYTE
,
187 .attachment
= GL_COLOR_ATTACHMENT0
190 "depth_stencil", k_framebuffer_attachment_type_renderbuffer
,
191 .internalformat
= GL_DEPTH24_STENCIL8
,
192 .attachment
= GL_DEPTH_STENCIL_ATTACHMENT
198 .link
= &gpipeline
.fb_network_status
,
200 .fixed_w
= 128, .fixed_h
= 48,
204 "colour", k_framebuffer_attachment_type_texture
,
205 .internalformat
= GL_RGB
,
207 .type
= GL_UNSIGNED_BYTE
,
208 .attachment
= GL_COLOR_ATTACHMENT0
215 * Get the current (automatically scaled or fixed) resolution of framebuffer
217 static void render_fb_get_current_res( struct framebuffer
*fb
,
220 if( fb
->resolution_div
){
221 *x
= vg
.window_x
/ fb
->resolution_div
;
222 *y
= vg
.window_y
/ fb
->resolution_div
;
230 static void render_fb_inverse_ratio( framebuffer
*fb
, v2f inverse
)
234 render_fb_get_current_res( fb
, &x
, &y
);
236 v2f render
= { fb
->render_w
, fb
->render_h
},
239 v2_div( render
, original
, inverse
);
242 v2_div( (v2f
){1.0f
,1.0f
}, (v2f
){ vg
.window_x
, vg
.window_y
}, inverse
);
247 * Bind framebuffer for drawing to
249 static void render_fb_bind( framebuffer
*fb
, int use_scaling
)
252 render_fb_get_current_res( fb
, &x
, &y
);
255 x
= k_render_scale
*(float)x
;
256 y
= k_render_scale
*(float)y
;
265 glBindFramebuffer( GL_FRAMEBUFFER
, fb
->fb
);
266 glViewport( 0, 0, x
, y
);
270 * Bind framebuffer attachment's texture
272 static void render_fb_bind_texture( framebuffer
*fb
,
273 int attachment
, int slot
)
275 struct framebuffer_attachment
*at
= &fb
->attachments
[attachment
];
277 if( (at
->purpose
!= k_framebuffer_attachment_type_texture
) &&
278 (at
->purpose
!= k_framebuffer_attachment_type_texture_depth
) )
280 vg_fatal_error( "illegal operation: bind non-texture framebuffer"
281 " attachment to texture slot" );
284 glActiveTexture( GL_TEXTURE0
+ slot
);
285 glBindTexture( GL_TEXTURE_2D
, fb
->attachments
[attachment
].id
);
293 #define FB_FORMAT_STR( E ) { E, #E },
296 * Convert OpenGL attachment ID enum to string
298 static const char *render_fb_attachment_str( GLenum e
)
300 struct { GLenum e
; const char *str
; }
303 FB_FORMAT_STR(GL_COLOR_ATTACHMENT0
)
304 FB_FORMAT_STR(GL_COLOR_ATTACHMENT1
)
305 FB_FORMAT_STR(GL_COLOR_ATTACHMENT2
)
306 FB_FORMAT_STR(GL_COLOR_ATTACHMENT3
)
307 FB_FORMAT_STR(GL_COLOR_ATTACHMENT4
)
308 FB_FORMAT_STR(GL_DEPTH_STENCIL_ATTACHMENT
)
311 for( int i
=0; i
<vg_list_size(formats
); i
++ )
312 if( formats
[i
].e
== e
)
313 return formats
[i
].str
;
319 * Convert OpenGL texture format enums from TexImage2D table 1,2 &
320 * RenderBufferStorage Table 1, into strings
322 static const char *render_fb_format_str( GLenum format
)
324 struct { GLenum e
; const char *str
; }
328 FB_FORMAT_STR(GL_DEPTH_COMPONENT
)
329 FB_FORMAT_STR(GL_DEPTH_STENCIL
)
330 FB_FORMAT_STR(GL_RED
)
332 FB_FORMAT_STR(GL_RGB
)
333 FB_FORMAT_STR(GL_RGBA
)
335 /* Render buffer formats */
336 FB_FORMAT_STR(GL_DEPTH_COMPONENT16
)
337 FB_FORMAT_STR(GL_DEPTH_COMPONENT24
)
338 FB_FORMAT_STR(GL_DEPTH_COMPONENT32F
)
339 FB_FORMAT_STR(GL_DEPTH24_STENCIL8
)
340 FB_FORMAT_STR(GL_DEPTH32F_STENCIL8
)
341 FB_FORMAT_STR(GL_STENCIL_INDEX8
)
345 FB_FORMAT_STR(GL_R8_SNORM
)
346 FB_FORMAT_STR(GL_R16
)
347 FB_FORMAT_STR(GL_R16_SNORM
)
348 FB_FORMAT_STR(GL_RG8
)
349 FB_FORMAT_STR(GL_RG8_SNORM
)
350 FB_FORMAT_STR(GL_RG16
)
351 FB_FORMAT_STR(GL_RG16_SNORM
)
352 FB_FORMAT_STR(GL_R3_G3_B2
)
353 FB_FORMAT_STR(GL_RGB4
)
354 FB_FORMAT_STR(GL_RGB5
)
355 FB_FORMAT_STR(GL_RGB8
)
356 FB_FORMAT_STR(GL_RGB8_SNORM
)
357 FB_FORMAT_STR(GL_RGB10
)
358 FB_FORMAT_STR(GL_RGB12
)
359 FB_FORMAT_STR(GL_RGB16_SNORM
)
360 FB_FORMAT_STR(GL_RGBA2
)
361 FB_FORMAT_STR(GL_RGBA4
)
362 FB_FORMAT_STR(GL_RGB5_A1
)
363 FB_FORMAT_STR(GL_RGBA8
)
364 FB_FORMAT_STR(GL_RGBA8_SNORM
)
365 FB_FORMAT_STR(GL_RGB10_A2
)
366 FB_FORMAT_STR(GL_RGB10_A2UI
)
367 FB_FORMAT_STR(GL_RGBA12
)
368 FB_FORMAT_STR(GL_RGBA16
)
369 FB_FORMAT_STR(GL_SRGB8
)
370 FB_FORMAT_STR(GL_SRGB8_ALPHA8
)
371 FB_FORMAT_STR(GL_R16F
)
372 FB_FORMAT_STR(GL_RG16F
)
373 FB_FORMAT_STR(GL_RGB16F
)
374 FB_FORMAT_STR(GL_RGBA16F
)
375 FB_FORMAT_STR(GL_R32F
)
376 FB_FORMAT_STR(GL_RG32F
)
377 FB_FORMAT_STR(GL_RGB32F
)
378 FB_FORMAT_STR(GL_RGBA32F
)
379 FB_FORMAT_STR(GL_R11F_G11F_B10F
)
380 FB_FORMAT_STR(GL_RGB9_E5
)
381 FB_FORMAT_STR(GL_R8I
)
382 FB_FORMAT_STR(GL_R8UI
)
383 FB_FORMAT_STR(GL_R16I
)
384 FB_FORMAT_STR(GL_R16UI
)
385 FB_FORMAT_STR(GL_R32I
)
386 FB_FORMAT_STR(GL_R32UI
)
387 FB_FORMAT_STR(GL_RG8I
)
388 FB_FORMAT_STR(GL_RG8UI
)
389 FB_FORMAT_STR(GL_RG16I
)
390 FB_FORMAT_STR(GL_RG16UI
)
391 FB_FORMAT_STR(GL_RG32I
)
392 FB_FORMAT_STR(GL_RG32UI
)
393 FB_FORMAT_STR(GL_RGB8I
)
394 FB_FORMAT_STR(GL_RGB8UI
)
395 FB_FORMAT_STR(GL_RGB16I
)
396 FB_FORMAT_STR(GL_RGB16UI
)
397 FB_FORMAT_STR(GL_RGB32I
)
398 FB_FORMAT_STR(GL_RGB32UI
)
399 FB_FORMAT_STR(GL_RGBA8I
)
400 FB_FORMAT_STR(GL_RGBA8UI
)
401 FB_FORMAT_STR(GL_RGBA16I
)
402 FB_FORMAT_STR(GL_RGBA16UI
)
403 FB_FORMAT_STR(GL_RGBA32I
)
404 FB_FORMAT_STR(GL_RGBA32UI
)
407 for( int i
=0; i
<vg_list_size(formats
); i
++ )
408 if( formats
[i
].e
== format
)
409 return formats
[i
].str
;
415 * Bind and allocate texture for framebuffer attachment
417 static void render_fb_allocate_texture( struct framebuffer
*fb
,
418 struct framebuffer_attachment
*a
)
421 render_fb_get_current_res( fb
, &rx
, &ry
);
423 if( a
->purpose
== k_framebuffer_attachment_type_renderbuffer
){
424 glBindRenderbuffer( GL_RENDERBUFFER
, a
->id
);
425 glRenderbufferStorage( GL_RENDERBUFFER
, a
->internalformat
, rx
, ry
);
427 else if( a
->purpose
== k_framebuffer_attachment_type_texture
||
428 a
->purpose
== k_framebuffer_attachment_type_texture_depth
)
430 glBindTexture( GL_TEXTURE_2D
, a
->id
);
431 glTexImage2D( GL_TEXTURE_2D
, 0, a
->internalformat
, rx
, ry
,
432 0, a
->format
, a
->type
, NULL
);
437 * Full allocation of a framebuffer
439 static void render_fb_allocate( struct framebuffer
*fb
)
441 glGenFramebuffers( 1, &fb
->fb
);
442 glBindFramebuffer( GL_FRAMEBUFFER
, fb
->fb
);
445 render_fb_get_current_res( fb
, &rx
, &ry
);
447 vg_info( "allocate_framebuffer( %s, %dx%d )\n", fb
->display_name
, rx
, ry
);
450 GLenum colour_attachments
[4];
451 u32 colour_count
= 0;
453 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ ){
454 struct framebuffer_attachment
*attachment
= &fb
->attachments
[j
];
456 if( attachment
->purpose
== k_framebuffer_attachment_type_none
)
459 vg_info( " %s: %s\n",
460 render_fb_attachment_str( attachment
->attachment
),
461 render_fb_format_str( attachment
->internalformat
) );
463 if( attachment
->purpose
== k_framebuffer_attachment_type_renderbuffer
){
464 glGenRenderbuffers( 1, &attachment
->id
);
465 render_fb_allocate_texture( fb
, attachment
);
466 glFramebufferRenderbuffer( GL_FRAMEBUFFER
,
467 GL_DEPTH_STENCIL_ATTACHMENT
,
468 GL_RENDERBUFFER
, attachment
->id
);
470 else if( attachment
->purpose
== k_framebuffer_attachment_type_texture
||
471 attachment
->purpose
== k_framebuffer_attachment_type_texture_depth
)
473 glGenTextures( 1, &attachment
->id
);
474 render_fb_allocate_texture( fb
, attachment
);
475 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
476 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
477 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
478 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
480 glFramebufferTexture2D( GL_FRAMEBUFFER
, attachment
->attachment
,
481 GL_TEXTURE_2D
, attachment
->id
, 0 );
483 if( attachment
->purpose
== k_framebuffer_attachment_type_texture
)
484 colour_attachments
[ colour_count
++ ] = attachment
->attachment
;
488 glDrawBuffers( colour_count
, colour_attachments
);
493 GLenum result
= glCheckFramebufferStatus( GL_FRAMEBUFFER
);
495 if( result
== GL_FRAMEBUFFER_COMPLETE
){
497 * Attatch to gpipeline
502 vg_success( " status: complete\n" );
506 if( result
== GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
)
507 vg_error( " status: Incomplete attachment" );
508 else if( result
== GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
)
509 vg_error( " status: Missing attachment" );
510 else if( result
== GL_FRAMEBUFFER_UNSUPPORTED
)
511 vg_error( " status: Unsupported framebuffer format" );
513 vg_error( " status: Generic Error" );
516 vg_fatal_error( "Incomplete framebuffer (see logs)" );
521 * Resize/Update all framebuffers(we know about)
523 static void render_fb_resize(void)
525 if( !gpipeline
.ready
) return;
527 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ ){
528 struct framebuffer
*fb
= &framebuffers
[i
];
529 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ ){
530 struct framebuffer_attachment
*attachment
= &fb
->attachments
[j
];
531 render_fb_allocate_texture( fb
, attachment
);
536 static int render_framebuffer_control( int argc
, char const *argv
[] );
537 static void render_framebuffer_poll( int argc
, char const *argv
[] );
539 static void async_render_init( void *payload
, u32 size
)
542 * Complete Framebuffers
544 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ ){
545 struct framebuffer
*fb
= &framebuffers
[i
];
546 render_fb_allocate( fb
);
549 f32 rh
= 0x1p
-4f
, ih
= 0.3f
;
552 0.00f
,0.00f
, 1.00f
,1.00f
, 0.00f
,1.00f
, /* fsquad */
553 0.00f
,0.00f
, 1.00f
,0.00f
, 1.00f
,1.00f
,
555 0.00f
,0.00f
, 1.00f
,rh
, 0.00f
,rh
, /* fsquad1 */
556 0.00f
,0.00f
, 1.00f
,0.00f
, 1.00f
,rh
,
560 0.00f
,0.00f
, 0.30f
,0.30f
, 0.00f
,0.30f
,
561 0.00f
,0.00f
, 0.30f
,0.00f
, 0.30f
,0.30f
,
562 0.30f
,0.00f
, 0.60f
,0.30f
, 0.30f
,0.30f
,
563 0.30f
,0.00f
, 0.60f
,0.00f
, 0.60f
,0.30f
,
564 0.60f
,0.00f
, 0.90f
,0.30f
, 0.60f
,0.30f
,
565 0.60f
,0.00f
, 0.90f
,0.00f
, 0.90f
,0.30f
,
567 0.00f
,0.30f
, 0.30f
,0.60f
, 0.00f
,0.60f
,
568 0.00f
,0.30f
, 0.30f
,0.30f
, 0.30f
,0.60f
,
569 0.30f
,0.30f
, 0.60f
,0.60f
, 0.30f
,0.60f
,
570 0.30f
,0.30f
, 0.60f
,0.30f
, 0.60f
,0.60f
,
571 0.60f
,0.30f
, 0.90f
,0.60f
, 0.60f
,0.60f
,
572 0.60f
,0.30f
, 0.90f
,0.30f
, 0.90f
,0.60f
,
574 0.00f
,0.60f
, 0.30f
,0.90f
, 0.00f
,0.90f
,
575 0.00f
,0.60f
, 0.30f
,0.60f
, 0.30f
,0.90f
,
576 0.30f
,0.60f
, 0.60f
,0.90f
, 0.30f
,0.90f
,
577 0.30f
,0.60f
, 0.60f
,0.60f
, 0.60f
,0.90f
,
578 0.60f
,0.60f
, 0.90f
,0.90f
, 0.60f
,0.90f
,
579 0.60f
,0.60f
, 0.90f
,0.60f
, 0.90f
,0.90f
,
581 0.00f
,ih
, 1.00f
,ih
+rh
, 0.00f
,ih
+rh
, /* fsquad2 */
582 0.00f
,ih
, 1.00f
,ih
, 1.00f
,ih
+rh
,
585 vg_console_reg_cmd( "fb", render_framebuffer_control
,
586 render_framebuffer_poll
);
587 glGenVertexArrays( 1, &gpipeline
.fsquad
.vao
);
588 glGenBuffers( 1, &gpipeline
.fsquad
.vbo
);
589 glBindVertexArray( gpipeline
.fsquad
.vao
);
590 glBindBuffer( GL_ARRAY_BUFFER
, gpipeline
.fsquad
.vbo
);
591 glBufferData( GL_ARRAY_BUFFER
, sizeof(quad
), quad
, GL_STATIC_DRAW
);
592 glBindVertexArray( gpipeline
.fsquad
.vao
);
593 glVertexAttribPointer( 0, 2, GL_FLOAT
, GL_FALSE
,
594 sizeof(float)*2, (void*)0 );
595 glEnableVertexAttribArray( 0 );
599 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
603 static void render_init(void)
605 vg_console_reg_var( "blur_strength", &k_blur_strength
, k_var_dtype_f32
, 0 );
606 vg_console_reg_var( "render_scale", &k_render_scale
,
607 k_var_dtype_f32
, VG_VAR_PERSISTENT
);
608 vg_console_reg_var( "fov", &k_fov
, k_var_dtype_f32
, VG_VAR_PERSISTENT
);
609 vg_console_reg_var( "cam_height", &k_cam_height
,
610 k_var_dtype_f32
, VG_VAR_PERSISTENT
);
611 vg_console_reg_var( "blur_effect", &k_blur_effect
,
612 k_var_dtype_i32
, VG_VAR_PERSISTENT
);
615 shader_blit_register();
616 shader_blitblur_register();
617 shader_blitcolour_register();
618 shader_blit_transition_register();
620 vg_async_call( async_render_init
, NULL
, 0 );
626 static void render_fsquad(void)
628 glBindVertexArray( gpipeline
.fsquad
.vao
);
629 glDrawArrays( GL_TRIANGLES
, 0, 6 );
632 static void render_fsquad1(void)
634 glBindVertexArray( gpipeline
.fsquad
.vao
);
635 glDrawArrays( GL_TRIANGLES
, 6, 6 );
638 static void render_fsquad2(void)
640 glBindVertexArray( gpipeline
.fsquad
.vao
);
641 glDrawArrays( GL_TRIANGLES
, 66,6 );
645 * Call this inside the UI function
647 static void render_view_framebuffer_ui(void)
650 int viewing_count
= 0;
652 glBindVertexArray( gpipeline
.fsquad
.vao
);
654 shader_blit_uTexMain( 0 );
656 v2f identity
= { 1.0f
, 1.0f
};
657 shader_blit_uInverseRatio( identity
);
659 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ ){
660 struct framebuffer
*fb
= &framebuffers
[i
];
662 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ ){
663 struct framebuffer_attachment
*at
= &fb
->attachments
[j
];
665 if( !at
->debug_view
)
669 window
= { vg
.window_x
, vg
.window_y
};
671 corner
[0] = viewing_count
% 3;
672 corner
[1] = 1 + (viewing_count
/ 3);
673 v2_mul( corner
, window
, corner
);
674 v2_muls( corner
, 0.3f
, corner
);
675 corner
[1] = vg
.window_y
- corner
[1];
677 ui_text( (ui_rect
){ corner
[0], corner
[1], 0.0f
, 0.0f
},
678 fb
->display_name
, 2, k_text_align_left
);
679 ui_text( (ui_rect
){ corner
[0], corner
[1] + 32, 0.0f
, 0.0f
, },
680 at
->display_name
, 1, k_text_align_left
);
682 if( at
->purpose
== k_framebuffer_attachment_type_renderbuffer
){
684 v2_muladds( corner
, window
, 0.15f
, center
);
686 ui_text( (ui_rect
){ center
[0], center
[1], 0.0f
, 0.0f
},
687 "<hardware texture>", 1, k_text_align_center
);
690 render_fb_bind_texture( fb
, j
, 0 );
692 int start
= (viewing_count
+2) * 6,
694 glDrawArrays( GL_TRIANGLES
, start
, count
);
703 static void render_framebuffer_show( struct framebuffer
*fb
,
704 struct framebuffer_attachment
*at
,
707 at
->debug_view
= operation
;
708 vg_info( "%s %s:%s\n", (operation
?"shown": "hidden"),
709 fb
->display_name
, at
->display_name
);
713 * arg0: command "show"/"hide"
714 * arg1: framebuffer name <name>/"all"
715 * arg2: subname <name>/none
717 static int render_framebuffer_control( int argc
, char const *argv
[] )
720 vg_error( "Usage: fb \"show/hide\" <name>/\"all\" <name>/none\n" );
727 if( !strcmp( argv
[0], "show" ) )
729 else if( !strcmp( argv
[0], "hide" ) )
732 vg_error( "Unknown framebuffer operation: '%s'\n", argv
[0] );
736 if( !strcmp( argv
[1], "all" ) )
739 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ ){
740 struct framebuffer
*fb
= &framebuffers
[i
];
742 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ ){
743 struct framebuffer_attachment
*at
= &fb
->attachments
[j
];
745 if( at
->purpose
== k_framebuffer_attachment_type_none
)
749 render_framebuffer_show( fb
, at
, operation
);
752 if( !strcmp( fb
->display_name
, argv
[1] ) ){
754 render_framebuffer_show( fb
, at
, operation
);
755 else if( !strcmp( at
->display_name
, argv
[2] ) )
756 render_framebuffer_show( fb
, at
, operation
);
765 static void render_framebuffer_poll( int argc
, char const *argv
[] )
767 const char *term
= argv
[argc
-1];
770 console_suggest_score_text( "show", term
, 0 );
771 console_suggest_score_text( "hide", term
, 0 );
773 else if( argc
== 2 ){
774 console_suggest_score_text( "all", term
, 0 );
776 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ ){
777 struct framebuffer
*fb
= &framebuffers
[i
];
778 console_suggest_score_text( fb
->display_name
, term
, 0 );
781 else if( argc
== 3 ){
784 if( !strcmp( argv
[1], "all" ) )
787 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ ){
788 struct framebuffer
*fb
= &framebuffers
[i
];
790 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ ){
791 struct framebuffer_attachment
*at
= &fb
->attachments
[j
];
793 if( at
->purpose
== k_framebuffer_attachment_type_none
)
797 console_suggest_score_text( at
->display_name
, term
, 0 );
799 else if( !strcmp( fb
->display_name
, argv
[1] ) ){
800 console_suggest_score_text( at
->display_name
, term
, 0 );
807 #endif /* RENDER_H */