demotool/ui-odbg.cc
2017-11-23 23:31:24 +01:00

230 lines
5.8 KiB
C++

#include "externals.hh"
#include "ui.hh"
#include "ui-odbg.hh"
namespace {
char const NormalOutput_[] = "(DISABLED)";
}
/*= T_OutputDebugger =========================================================*/
T_OutputDebugger::T_OutputDebugger( )
: selectorItems_( nullptr )
{
using namespace ebcl;
registerSubmode( E_ODbgMode::LDR , "Colors" , "copy" );
registerSubmode( E_ODbgMode::LDR_ALPHA , "Colors" , "copy" );
registerSubmode( E_ODbgMode::LDR_ALPHA , "Alpha channel" , "alpha-channel" );
registerSubmode( E_ODbgMode::HDR , "Colors (raw)" , "copy" );
registerSubmode( E_ODbgMode::HDR , "Colors (Reinhart)" , "reinhart" );
registerSubmode( E_ODbgMode::DEPTH , "Depth (linear / 10)" , "depth-linear" ,
[]( uint32_t id ) { glProgramUniform1f( id , 3 , .1 ); } );
registerSubmode( E_ODbgMode::DEPTH , "Depth (linear / 100)" , "depth-linear" ,
[]( uint32_t id ) { glProgramUniform1f( id , 3 , .01 ); } );
registerSubmode( E_ODbgMode::DEPTH , "Depth (Reinhart)" , "depth-reinhart" );
initSubmodeCombo( );
}
T_OutputDebugger::~T_OutputDebugger( )
{
clearSelectorItems( );
for ( auto ptr : smCombo_ ) {
delete[] ptr;
}
}
void T_OutputDebugger::makeUI( )
{
if ( !enabled_ ) {
return;
}
using namespace ImGui;
auto const& dspSize( GetIO( ).DisplaySize );
SetNextWindowSize( ImVec2( dspSize.x * .25f , dspSize.y * .66f - 20 ) , ImGuiSetCond_Appearing );
SetNextWindowPos( ImVec2( 0 , 20 ) , ImGuiSetCond_Appearing );
Begin( "Output debugger" , &enabled_ , ImGuiWindowFlags_NoCollapse );
// Main selector
if ( selectorItems_ == nullptr ) {
makeSelectorItems( );
}
int csi = -1;
for ( auto i = 0u ; i < selectorMapping_.size( ) ; i ++ ) {
if ( selectorMapping_[ i ] == selected_ ) {
csi = i;
break;
}
}
assert( csi != -1 );
if ( Combo( "Output" , &csi , selectorItems_ ) ) {
selected_ = selectorMapping_[ csi ];
}
if ( selected_ == -1 ) {
End( );
return;
}
// LOD selector
auto& t( outputs_[ selected_ ] );
if ( t.levels > 1 ) {
char lodCombo[ t.levels * 4 + 1 ];
char* ptr = lodCombo;
for ( auto i = 0u ; i < t.levels ; i ++ ) {
ptr += 1 + snprintf( ptr , sizeof( lodCombo ) - ( ptr - lodCombo ) , "%d" , i );
}
*ptr = 0;
Combo( "Level" , &t.lod , lodCombo );
}
// Submode selector
Combo( "Display" , &t.submode , smCombo_[ int( t.mode ) ] );
End( );
}
void T_OutputDebugger::registerTexture(
T_Texture& texture ,
const E_ODbgMode mode ,
T_String const& name )
{
texture.debugIndex_ = registerTexture(
texture.id_ , texture.levels_ , mode , name );
}
void T_OutputDebugger::debugOutput( )
{
assert( selected_ != -1 );
glClearColor( 0 , 0 , 0 , 1 );
glClear( GL_COLOR_BUFFER_BIT );
auto const& info( outputs_[ selected_ ] );
auto const& sm( submodes_[ int( info.mode ) ][ info.submode ] );
if ( !sm.pipeline.valid( ) ) {
return;
}
auto& tm( UI::Textures( ) );
glBindTextureUnit( 0 , info.id );
glBindSampler( 0 , tm.sampler( "nearest-border" )->id( ) );
auto const& dspSize( ImGui::GetIO( ).DisplaySize );
auto pid( sm.pipeline.program( E_ShaderType::FRAGMENT ) );
sm.pipeline.enable( );
glProgramUniform1i( pid , 0 , 0 );
glProgramUniform1i( pid , 1 , info.lod );
glProgramUniform2f( pid , 2 , dspSize.x , dspSize.y );
if ( sm.setup ) {
sm.setup( pid );
}
glDrawArrays( GL_TRIANGLE_STRIP , 0 , 4 );
}
/*----------------------------------------------------------------------------*/
void T_OutputDebugger::registerSubmode(
const E_ODbgMode mode ,
T_String const& name ,
T_String const& shader ,
F_SubmodeSetup setup )
{
assert( mode != E_ODbgMode::__COUNT__ );
ebcl::T_StringBuilder sb( "debug/" );
sb << shader << ".glsl" << '\0';
submodes_[ int( mode ) ].add( T_Submode_{
name ,
UI::Shaders( ).pipeline({
"fullscreen.v.glsl" , sb.data( ) }) ,
setup
} );
}
void T_OutputDebugger::initSubmodeCombo( )
{
for ( auto sm = 0u ; sm < int( E_ODbgMode::__COUNT__ ) ; sm ++ ) {
imguiStrings.clear( );
for ( auto const& m : submodes_[ sm ] ) {
imguiStrings << m.name << '\0';
}
imguiStrings << '\0';
smCombo_[ sm ] = new char[ imguiStrings.size( ) ];
memcpy( smCombo_[ sm ] , imguiStrings.data( ) , imguiStrings.size( ) );
}
}
/*----------------------------------------------------------------------------*/
int32_t T_OutputDebugger::registerTexture(
const GLuint id ,
const uint32_t levels ,
const E_ODbgMode mode ,
T_String const& name )
{
assert( mode != E_ODbgMode::__COUNT__ );
assert( id != 0 );
assert( name.length( ) );
nRegistered_ ++;
const auto n( outputs_.size( ) );
for ( auto i = 0u ; i < n ; i ++ ) {
if ( outputs_[ i ].id == 0 ) {
outputs_[ i ] = T_Texture_{ id , levels , mode , name , 0 , 0 };
return i;
}
}
outputs_.add( T_Texture_{ id , levels , mode , name , 0 , 0 } );
return n;
}
void T_OutputDebugger::unregisterTexture(
const uint32_t index )
{
assert( index < outputs_.size( ) );
assert( outputs_[ index ].id != 0 );
assert( nRegistered_ > 0 );
outputs_[ index ].id = 0;
if ( selected_ >= 0 && index == uint32_t( selected_ ) ) {
selected_ = -1;
}
}
/*----------------------------------------------------------------------------*/
void T_OutputDebugger::clearSelectorItems( )
{
if ( selectorItems_ != nullptr ) {
delete[] selectorItems_;
selectorItems_ = nullptr;
selectorMapping_.clear( );
}
}
void T_OutputDebugger::makeSelectorItems( )
{
imguiStrings.clear( );
imguiStrings << NormalOutput_ << '\0';
uint32_t nrLeft = nRegistered_, i = 0;
selectorMapping_.add( -1 );
while ( nrLeft ) {
assert( i < outputs_.size( ) );
if ( outputs_[ i ].id != 0 ) {
imguiStrings << outputs_[ i ].name << '\0';
selectorMapping_.add( i );
nrLeft --;
}
i ++;
}
imguiStrings << '\0';
assert( selectorMapping_.size( ) == 1 + nRegistered_ );
selectorItems_ = new char[ imguiStrings.size( ) ];
memcpy( selectorItems_ , imguiStrings.data( ) , imguiStrings.size( ) );
}