2 #include "vg/vg_engine.h"
3 #include "vg/vg_platform.h"
5 struct framebuffer framebuffers
[] =
9 * The primary draw target
12 .link
= &gpipeline
.fb_main
,
17 "colour", k_framebuffer_attachment_type_texture
,
19 .internalformat
= GL_RGB
,
21 .type
= GL_UNSIGNED_BYTE
,
22 .attachment
= GL_COLOR_ATTACHMENT0
25 "motion", k_framebuffer_attachment_type_texture
,
27 .quality
= k_framebuffer_quality_high_only
,
28 .internalformat
= GL_RG16F
,
31 .attachment
= GL_COLOR_ATTACHMENT1
35 "depth_stencil", k_framebuffer_attachment_type_renderbuffer
,
37 .internalformat
= GL_DEPTH24_STENCIL8
,
39 "depth_stencil", k_framebuffer_attachment_type_texture_depth
,
40 .internalformat
= GL_DEPTH24_STENCIL8
,
41 .format
= GL_DEPTH_STENCIL
,
42 .type
= GL_UNSIGNED_INT_24_8
,
44 .attachment
= GL_DEPTH_STENCIL_ATTACHMENT
50 * Second rendered view from the perspective of the water reflection
53 .link
= &gpipeline
.fb_water_reflection
,
58 "colour", k_framebuffer_attachment_type_texture
,
59 .internalformat
= GL_RGB
,
61 .type
= GL_UNSIGNED_BYTE
,
62 .attachment
= GL_COLOR_ATTACHMENT0
65 "depth_stencil", k_framebuffer_attachment_type_renderbuffer
,
67 .internalformat
= GL_DEPTH24_STENCIL8
,
68 .attachment
= GL_DEPTH_STENCIL_ATTACHMENT
74 * Thid rendered view from the perspective of the camera, but just
75 * captures stuff thats under the water
78 .link
= &gpipeline
.fb_water_beneath
,
83 "colour", k_framebuffer_attachment_type_texture
,
84 .internalformat
= GL_RED
,
86 .type
= GL_UNSIGNED_BYTE
,
87 .attachment
= GL_COLOR_ATTACHMENT0
90 "depth_stencil", k_framebuffer_attachment_type_renderbuffer
,
92 .internalformat
= GL_DEPTH24_STENCIL8
,
93 .attachment
= GL_DEPTH_STENCIL_ATTACHMENT
99 .link
= &gpipeline
.fb_workshop_preview
,
101 .fixed_w
= WORKSHOP_PREVIEW_WIDTH
, .fixed_h
= WORKSHOP_PREVIEW_HEIGHT
,
105 "colour", k_framebuffer_attachment_type_texture
,
106 .internalformat
= GL_RGB
,
108 .type
= GL_UNSIGNED_BYTE
,
109 .attachment
= GL_COLOR_ATTACHMENT0
112 "depth_stencil", k_framebuffer_attachment_type_renderbuffer
,
113 .internalformat
= GL_DEPTH24_STENCIL8
,
114 .attachment
= GL_DEPTH_STENCIL_ATTACHMENT
120 .link
= &gpipeline
.fb_network_status
,
122 .fixed_w
= 128, .fixed_h
= 48,
126 "colour", k_framebuffer_attachment_type_texture
,
127 .internalformat
= GL_RGB
,
129 .type
= GL_UNSIGNED_BYTE
,
130 .attachment
= GL_COLOR_ATTACHMENT0
137 * Get the current (automatically scaled or fixed) resolution of framebuffer
139 void render_fb_get_current_res( struct framebuffer
*fb
, int *x
, int *y
)
141 if( fb
->resolution_div
){
142 *x
= vg
.window_x
/ fb
->resolution_div
;
143 *y
= vg
.window_y
/ fb
->resolution_div
;
151 void render_fb_inverse_ratio( framebuffer
*fb
, v2f inverse
)
155 render_fb_get_current_res( fb
, &x
, &y
);
157 v2f render
= { fb
->render_w
, fb
->render_h
},
160 v2_div( render
, original
, inverse
);
163 v2_div( (v2f
){1.0f
,1.0f
}, (v2f
){ vg
.window_x
, vg
.window_y
}, inverse
);
168 * Bind framebuffer for drawing to
170 void render_fb_bind( framebuffer
*fb
, int use_scaling
)
173 render_fb_get_current_res( fb
, &x
, &y
);
176 x
= k_render_scale
*(float)x
;
177 y
= k_render_scale
*(float)y
;
186 glBindFramebuffer( GL_FRAMEBUFFER
, fb
->fb
);
187 glViewport( 0, 0, x
, y
);
191 * Bind framebuffer attachment's texture
193 void render_fb_bind_texture( framebuffer
*fb
, int attachment
, int slot
)
195 struct framebuffer_attachment
*at
= &fb
->attachments
[attachment
];
197 if( (at
->purpose
!= k_framebuffer_attachment_type_texture
) &&
198 (at
->purpose
!= k_framebuffer_attachment_type_texture_depth
) )
200 vg_fatal_error( "illegal operation: bind non-texture framebuffer"
201 " attachment to texture slot" );
204 glActiveTexture( GL_TEXTURE0
+ slot
);
205 glBindTexture( GL_TEXTURE_2D
, fb
->attachments
[attachment
].id
);
213 #define FB_FORMAT_STR( E ) { E, #E },
216 * Convert OpenGL attachment ID enum to string
218 static const char *render_fb_attachment_str( GLenum e
)
220 struct { GLenum e
; const char *str
; }
223 FB_FORMAT_STR(GL_COLOR_ATTACHMENT0
)
224 FB_FORMAT_STR(GL_COLOR_ATTACHMENT1
)
225 FB_FORMAT_STR(GL_COLOR_ATTACHMENT2
)
226 FB_FORMAT_STR(GL_COLOR_ATTACHMENT3
)
227 FB_FORMAT_STR(GL_COLOR_ATTACHMENT4
)
228 FB_FORMAT_STR(GL_DEPTH_STENCIL_ATTACHMENT
)
231 for( int i
=0; i
<vg_list_size(formats
); i
++ )
232 if( formats
[i
].e
== e
)
233 return formats
[i
].str
;
239 * Convert OpenGL texture format enums from TexImage2D table 1,2 &
240 * RenderBufferStorage Table 1, into strings
242 static const char *render_fb_format_str( GLenum format
)
244 struct { GLenum e
; const char *str
; }
248 FB_FORMAT_STR(GL_DEPTH_COMPONENT
)
249 FB_FORMAT_STR(GL_DEPTH_STENCIL
)
250 FB_FORMAT_STR(GL_RED
)
252 FB_FORMAT_STR(GL_RGB
)
253 FB_FORMAT_STR(GL_RGBA
)
255 /* Render buffer formats */
256 FB_FORMAT_STR(GL_DEPTH_COMPONENT16
)
257 FB_FORMAT_STR(GL_DEPTH_COMPONENT24
)
258 FB_FORMAT_STR(GL_DEPTH_COMPONENT32F
)
259 FB_FORMAT_STR(GL_DEPTH24_STENCIL8
)
260 FB_FORMAT_STR(GL_DEPTH32F_STENCIL8
)
261 FB_FORMAT_STR(GL_STENCIL_INDEX8
)
265 FB_FORMAT_STR(GL_R8_SNORM
)
266 FB_FORMAT_STR(GL_R16
)
267 FB_FORMAT_STR(GL_R16_SNORM
)
268 FB_FORMAT_STR(GL_RG8
)
269 FB_FORMAT_STR(GL_RG8_SNORM
)
270 FB_FORMAT_STR(GL_RG16
)
271 FB_FORMAT_STR(GL_RG16_SNORM
)
272 FB_FORMAT_STR(GL_R3_G3_B2
)
273 FB_FORMAT_STR(GL_RGB4
)
274 FB_FORMAT_STR(GL_RGB5
)
275 FB_FORMAT_STR(GL_RGB8
)
276 FB_FORMAT_STR(GL_RGB8_SNORM
)
277 FB_FORMAT_STR(GL_RGB10
)
278 FB_FORMAT_STR(GL_RGB12
)
279 FB_FORMAT_STR(GL_RGB16_SNORM
)
280 FB_FORMAT_STR(GL_RGBA2
)
281 FB_FORMAT_STR(GL_RGBA4
)
282 FB_FORMAT_STR(GL_RGB5_A1
)
283 FB_FORMAT_STR(GL_RGBA8
)
284 FB_FORMAT_STR(GL_RGBA8_SNORM
)
285 FB_FORMAT_STR(GL_RGB10_A2
)
286 FB_FORMAT_STR(GL_RGB10_A2UI
)
287 FB_FORMAT_STR(GL_RGBA12
)
288 FB_FORMAT_STR(GL_RGBA16
)
289 FB_FORMAT_STR(GL_SRGB8
)
290 FB_FORMAT_STR(GL_SRGB8_ALPHA8
)
291 FB_FORMAT_STR(GL_R16F
)
292 FB_FORMAT_STR(GL_RG16F
)
293 FB_FORMAT_STR(GL_RGB16F
)
294 FB_FORMAT_STR(GL_RGBA16F
)
295 FB_FORMAT_STR(GL_R32F
)
296 FB_FORMAT_STR(GL_RG32F
)
297 FB_FORMAT_STR(GL_RGB32F
)
298 FB_FORMAT_STR(GL_RGBA32F
)
299 FB_FORMAT_STR(GL_R11F_G11F_B10F
)
300 FB_FORMAT_STR(GL_RGB9_E5
)
301 FB_FORMAT_STR(GL_R8I
)
302 FB_FORMAT_STR(GL_R8UI
)
303 FB_FORMAT_STR(GL_R16I
)
304 FB_FORMAT_STR(GL_R16UI
)
305 FB_FORMAT_STR(GL_R32I
)
306 FB_FORMAT_STR(GL_R32UI
)
307 FB_FORMAT_STR(GL_RG8I
)
308 FB_FORMAT_STR(GL_RG8UI
)
309 FB_FORMAT_STR(GL_RG16I
)
310 FB_FORMAT_STR(GL_RG16UI
)
311 FB_FORMAT_STR(GL_RG32I
)
312 FB_FORMAT_STR(GL_RG32UI
)
313 FB_FORMAT_STR(GL_RGB8I
)
314 FB_FORMAT_STR(GL_RGB8UI
)
315 FB_FORMAT_STR(GL_RGB16I
)
316 FB_FORMAT_STR(GL_RGB16UI
)
317 FB_FORMAT_STR(GL_RGB32I
)
318 FB_FORMAT_STR(GL_RGB32UI
)
319 FB_FORMAT_STR(GL_RGBA8I
)
320 FB_FORMAT_STR(GL_RGBA8UI
)
321 FB_FORMAT_STR(GL_RGBA16I
)
322 FB_FORMAT_STR(GL_RGBA16UI
)
323 FB_FORMAT_STR(GL_RGBA32I
)
324 FB_FORMAT_STR(GL_RGBA32UI
)
327 for( int i
=0; i
<vg_list_size(formats
); i
++ )
328 if( formats
[i
].e
== format
)
329 return formats
[i
].str
;
335 * Bind and allocate texture for framebuffer attachment
337 static void render_fb_allocate_texture( struct framebuffer
*fb
,
338 struct framebuffer_attachment
*a
)
341 render_fb_get_current_res( fb
, &rx
, &ry
);
343 if( a
->purpose
== k_framebuffer_attachment_type_renderbuffer
){
344 glBindRenderbuffer( GL_RENDERBUFFER
, a
->id
);
345 glRenderbufferStorage( GL_RENDERBUFFER
, a
->internalformat
, rx
, ry
);
347 else if( a
->purpose
== k_framebuffer_attachment_type_texture
||
348 a
->purpose
== k_framebuffer_attachment_type_texture_depth
)
350 glBindTexture( GL_TEXTURE_2D
, a
->id
);
351 glTexImage2D( GL_TEXTURE_2D
, 0, a
->internalformat
, rx
, ry
,
352 0, a
->format
, a
->type
, NULL
);
357 * Full allocation of a framebuffer
359 void render_fb_allocate( struct framebuffer
*fb
)
361 glGenFramebuffers( 1, &fb
->fb
);
362 glBindFramebuffer( GL_FRAMEBUFFER
, fb
->fb
);
365 render_fb_get_current_res( fb
, &rx
, &ry
);
367 vg_info( "allocate_framebuffer( %s, %dx%d )\n", fb
->display_name
, rx
, ry
);
370 GLenum colour_attachments
[4];
371 u32 colour_count
= 0;
373 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ ){
374 struct framebuffer_attachment
*attachment
= &fb
->attachments
[j
];
376 if( attachment
->purpose
== k_framebuffer_attachment_type_none
)
379 vg_info( " %s: %s\n",
380 render_fb_attachment_str( attachment
->attachment
),
381 render_fb_format_str( attachment
->internalformat
) );
383 if( attachment
->purpose
== k_framebuffer_attachment_type_renderbuffer
){
384 glGenRenderbuffers( 1, &attachment
->id
);
385 render_fb_allocate_texture( fb
, attachment
);
386 glFramebufferRenderbuffer( GL_FRAMEBUFFER
,
387 GL_DEPTH_STENCIL_ATTACHMENT
,
388 GL_RENDERBUFFER
, attachment
->id
);
390 else if( attachment
->purpose
== k_framebuffer_attachment_type_texture
||
391 attachment
->purpose
== k_framebuffer_attachment_type_texture_depth
)
393 glGenTextures( 1, &attachment
->id
);
394 render_fb_allocate_texture( fb
, attachment
);
395 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
396 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
397 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
398 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
400 glFramebufferTexture2D( GL_FRAMEBUFFER
, attachment
->attachment
,
401 GL_TEXTURE_2D
, attachment
->id
, 0 );
403 if( attachment
->purpose
== k_framebuffer_attachment_type_texture
)
404 colour_attachments
[ colour_count
++ ] = attachment
->attachment
;
408 glDrawBuffers( colour_count
, colour_attachments
);
413 GLenum result
= glCheckFramebufferStatus( GL_FRAMEBUFFER
);
415 if( result
== GL_FRAMEBUFFER_COMPLETE
){
417 * Attatch to gpipeline
422 vg_success( " status: complete\n" );
426 if( result
== GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
)
427 vg_error( " status: Incomplete attachment" );
428 else if( result
== GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
)
429 vg_error( " status: Missing attachment" );
430 else if( result
== GL_FRAMEBUFFER_UNSUPPORTED
)
431 vg_error( " status: Unsupported framebuffer format" );
433 vg_error( " status: Generic Error" );
436 vg_fatal_error( "Incomplete framebuffer (see logs)" );
441 * Resize/Update all framebuffers(we know about)
443 void render_fb_resize(void)
445 if( !gpipeline
.ready
) return;
447 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ ){
448 struct framebuffer
*fb
= &framebuffers
[i
];
449 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ ){
450 struct framebuffer_attachment
*attachment
= &fb
->attachments
[j
];
451 render_fb_allocate_texture( fb
, attachment
);
456 static int render_framebuffer_control( int argc
, char const *argv
[] );
457 static void render_framebuffer_poll( int argc
, char const *argv
[] );
459 static void async_render_init( void *payload
, u32 size
)
462 * Complete Framebuffers
464 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ ){
465 struct framebuffer
*fb
= &framebuffers
[i
];
466 render_fb_allocate( fb
);
469 f32 rh
= 0x1p
-4f
, ih
= 0.3f
;
472 0.00f
,0.00f
, 1.00f
,1.00f
, 0.00f
,1.00f
, /* fsquad */
473 0.00f
,0.00f
, 1.00f
,0.00f
, 1.00f
,1.00f
,
475 0.00f
,0.00f
, 1.00f
,rh
, 0.00f
,rh
, /* fsquad1 */
476 0.00f
,0.00f
, 1.00f
,0.00f
, 1.00f
,rh
,
477 0.00f
,1.00f
, 0.00f
,1.0f
-rh
,1.00f
,1.0f
-rh
,
478 0.00f
,1.00f
, 1.00f
,1.0f
-rh
,1.00f
,1.0f
,
482 0.00f
,0.00f
, 0.30f
,0.30f
, 0.00f
,0.30f
,
483 0.00f
,0.00f
, 0.30f
,0.00f
, 0.30f
,0.30f
,
484 0.30f
,0.00f
, 0.60f
,0.30f
, 0.30f
,0.30f
,
485 0.30f
,0.00f
, 0.60f
,0.00f
, 0.60f
,0.30f
,
486 0.60f
,0.00f
, 0.90f
,0.30f
, 0.60f
,0.30f
,
487 0.60f
,0.00f
, 0.90f
,0.00f
, 0.90f
,0.30f
,
489 0.00f
,0.30f
, 0.30f
,0.60f
, 0.00f
,0.60f
,
490 0.00f
,0.30f
, 0.30f
,0.30f
, 0.30f
,0.60f
,
491 0.30f
,0.30f
, 0.60f
,0.60f
, 0.30f
,0.60f
,
492 0.30f
,0.30f
, 0.60f
,0.30f
, 0.60f
,0.60f
,
493 0.60f
,0.30f
, 0.90f
,0.60f
, 0.60f
,0.60f
,
494 0.60f
,0.30f
, 0.90f
,0.30f
, 0.90f
,0.60f
,
496 0.00f
,0.60f
, 0.30f
,0.90f
, 0.00f
,0.90f
,
497 0.00f
,0.60f
, 0.30f
,0.60f
, 0.30f
,0.90f
,
498 0.30f
,0.60f
, 0.60f
,0.90f
, 0.30f
,0.90f
,
499 0.30f
,0.60f
, 0.60f
,0.60f
, 0.60f
,0.90f
,
500 0.60f
,0.60f
, 0.90f
,0.90f
, 0.60f
,0.90f
,
501 0.60f
,0.60f
, 0.90f
,0.60f
, 0.90f
,0.90f
,
503 0.00f
,ih
, 1.00f
,ih
+rh
, 0.00f
,ih
+rh
, /* fsquad2 */
504 0.00f
,ih
, 1.00f
,ih
, 1.00f
,ih
+rh
,
507 glGenVertexArrays( 1, &gpipeline
.fsquad
.vao
);
508 glGenBuffers( 1, &gpipeline
.fsquad
.vbo
);
509 glBindVertexArray( gpipeline
.fsquad
.vao
);
510 glBindBuffer( GL_ARRAY_BUFFER
, gpipeline
.fsquad
.vbo
);
511 glBufferData( GL_ARRAY_BUFFER
, sizeof(quad
), quad
, GL_STATIC_DRAW
);
512 glBindVertexArray( gpipeline
.fsquad
.vao
);
513 glVertexAttribPointer( 0, 2, GL_FLOAT
, GL_FALSE
,
514 sizeof(float)*2, (void*)0 );
515 glEnableVertexAttribArray( 0 );
519 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
523 void render_init(void)
525 vg_console_reg_var( "blur_strength", &k_blur_strength
, k_var_dtype_f32
, 0 );
526 vg_console_reg_var( "render_scale", &k_render_scale
,
527 k_var_dtype_f32
, VG_VAR_PERSISTENT
);
528 vg_console_reg_var( "fov", &k_fov
, k_var_dtype_f32
, VG_VAR_PERSISTENT
);
529 vg_console_reg_var( "cam_height", &k_cam_height
,
530 k_var_dtype_f32
, VG_VAR_PERSISTENT
);
531 vg_console_reg_var( "blur_effect", &k_blur_effect
,
532 k_var_dtype_i32
, VG_VAR_PERSISTENT
);
534 vg_console_reg_cmd( "fb", render_framebuffer_control
,
535 render_framebuffer_poll
);
537 vg_async_call( async_render_init
, NULL
, 0 );
543 void render_fsquad(void)
545 glBindVertexArray( gpipeline
.fsquad
.vao
);
546 glDrawArrays( GL_TRIANGLES
, 0, 6 );
549 void render_fsquad1(void)
551 glBindVertexArray( gpipeline
.fsquad
.vao
);
552 glDrawArrays( GL_TRIANGLES
, 6, 6+6 );
555 void render_fsquad2(void)
557 glBindVertexArray( gpipeline
.fsquad
.vao
);
558 glDrawArrays( GL_TRIANGLES
, 66+6,6 );
562 * Call this inside the UI function
564 void render_view_framebuffer_ui( ui_context
*ctx
)
568 int viewing_count
= 0;
570 glBindVertexArray( gpipeline
.fsquad
.vao
);
572 shader_blit_uTexMain( 0 );
574 v2f identity
= { 1.0f
, 1.0f
};
575 shader_blit_uInverseRatio( identity
);
577 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ ){
578 struct framebuffer
*fb
= &framebuffers
[i
];
580 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ ){
581 struct framebuffer_attachment
*at
= &fb
->attachments
[j
];
583 if( !at
->debug_view
)
587 window
= { vg
.window_x
, vg
.window_y
};
589 corner
[0] = viewing_count
% 3;
590 corner
[1] = 1 + (viewing_count
/ 3);
591 v2_mul( corner
, window
, corner
);
592 v2_muls( corner
, 0.3f
, corner
);
593 corner
[1] = vg
.window_y
- corner
[1];
595 ui_text( (ui_rect
){ corner
[0], corner
[1], 0.0f
, 0.0f
},
596 fb
->display_name
, 2, k_text_align_left
);
597 ui_text( (ui_rect
){ corner
[0], corner
[1] + 32, 0.0f
, 0.0f
, },
598 at
->display_name
, 1, k_text_align_left
);
600 if( at
->purpose
== k_framebuffer_attachment_type_renderbuffer
){
602 v2_muladds( corner
, window
, 0.15f
, center
);
604 ui_text( (ui_rect
){ center
[0], center
[1], 0.0f
, 0.0f
},
605 "<hardware texture>", 1, k_text_align_center
);
608 render_fb_bind_texture( fb
, j
, 0 );
610 int start
= (viewing_count
+2) * 6,
612 glDrawArrays( GL_TRIANGLES
, start
, count
);
621 static void render_framebuffer_show( struct framebuffer
*fb
,
622 struct framebuffer_attachment
*at
,
625 at
->debug_view
= operation
;
626 vg_info( "%s %s:%s\n", (operation
?"shown": "hidden"),
627 fb
->display_name
, at
->display_name
);
631 * arg0: command "show"/"hide"
632 * arg1: framebuffer name <name>/"all"
633 * arg2: subname <name>/none
635 static int render_framebuffer_control( int argc
, char const *argv
[] )
638 vg_error( "Usage: fb \"show/hide\" <name>/\"all\" <name>/none\n" );
645 if( !strcmp( argv
[0], "show" ) )
647 else if( !strcmp( argv
[0], "hide" ) )
650 vg_error( "Unknown framebuffer operation: '%s'\n", argv
[0] );
654 if( !strcmp( argv
[1], "all" ) )
657 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ ){
658 struct framebuffer
*fb
= &framebuffers
[i
];
660 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ ){
661 struct framebuffer_attachment
*at
= &fb
->attachments
[j
];
663 if( at
->purpose
== k_framebuffer_attachment_type_none
)
667 render_framebuffer_show( fb
, at
, operation
);
670 if( !strcmp( fb
->display_name
, argv
[1] ) ){
672 render_framebuffer_show( fb
, at
, operation
);
673 else if( !strcmp( at
->display_name
, argv
[2] ) )
674 render_framebuffer_show( fb
, at
, operation
);
683 static void render_framebuffer_poll( int argc
, char const *argv
[] )
685 const char *term
= argv
[argc
-1];
688 console_suggest_score_text( "show", term
, 0 );
689 console_suggest_score_text( "hide", term
, 0 );
691 else if( argc
== 2 ){
692 console_suggest_score_text( "all", term
, 0 );
694 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ ){
695 struct framebuffer
*fb
= &framebuffers
[i
];
696 console_suggest_score_text( fb
->display_name
, term
, 0 );
699 else if( argc
== 3 ){
702 if( !strcmp( argv
[1], "all" ) )
705 for( int i
=0; i
<vg_list_size(framebuffers
); i
++ ){
706 struct framebuffer
*fb
= &framebuffers
[i
];
708 for( int j
=0; j
<vg_list_size(fb
->attachments
); j
++ ){
709 struct framebuffer_attachment
*at
= &fb
->attachments
[j
];
711 if( at
->purpose
== k_framebuffer_attachment_type_none
)
715 console_suggest_score_text( at
->display_name
, term
, 0 );
717 else if( !strcmp( fb
->display_name
, argv
[1] ) ){
718 console_suggest_score_text( at
->display_name
, term
, 0 );