mirror of
https://github.com/DaedalusX64/daedalus.git
synced 2025-04-02 10:21:48 -04:00
619 lines
19 KiB
C++
619 lines
19 KiB
C++
/*
|
|
Copyright (C) 2007 StrmnNrmn
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "CombinerTree.h"
|
|
|
|
#include "CombinerExpression.h"
|
|
#include "RenderSettings.h"
|
|
#include "BlendConstant.h"
|
|
#include "HLEGraphics/RDP.h"
|
|
#include "Utility/Stream.h"
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
namespace
|
|
{
|
|
|
|
const ECombinerInput CombinerInput32[ 32 ] =
|
|
{
|
|
CI_COMBINED, CI_TEXEL0, CI_TEXEL1, CI_PRIMITIVE, CI_SHADE, CI_ENV, CI_1, CI_COMBINED_ALPHA,
|
|
CI_TEXEL0_ALPHA, CI_TEXEL1_ALPHA, CI_PRIMITIVE_ALPHA, CI_SHADE_ALPHA, CI_ENV_ALPHA, CI_LOD_FRACTION, CI_PRIM_LOD_FRACTION, CI_K5,
|
|
|
|
CI_UNKNOWN, CI_UNKNOWN, CI_UNKNOWN, CI_UNKNOWN, CI_UNKNOWN, CI_UNKNOWN, CI_UNKNOWN, CI_UNKNOWN,
|
|
CI_UNKNOWN, CI_UNKNOWN, CI_UNKNOWN, CI_UNKNOWN, CI_UNKNOWN, CI_UNKNOWN, CI_UNKNOWN, CI_0,
|
|
};
|
|
|
|
const ECombinerInput CombinerInput16[ 16 ] =
|
|
{
|
|
CI_COMBINED, CI_TEXEL0, CI_TEXEL1, CI_PRIMITIVE, CI_SHADE, CI_ENV, CI_1, CI_COMBINED_ALPHA,
|
|
CI_TEXEL0_ALPHA, CI_TEXEL1_ALPHA, CI_PRIMITIVE_ALPHA, CI_SHADE_ALPHA, CI_ENV_ALPHA, CI_LOD_FRACTION, CI_PRIM_LOD_FRACTION, CI_0,
|
|
};
|
|
|
|
const ECombinerInput CombinerInput8[ 8 ] =
|
|
{
|
|
CI_COMBINED, CI_TEXEL0, CI_TEXEL1, CI_PRIMITIVE, CI_SHADE, CI_ENV, CI_1, CI_0,
|
|
};
|
|
|
|
const ECombinerInput CombinerInputAlphaC1_8[ 8 ] =
|
|
{
|
|
CI_LOD_FRACTION, CI_TEXEL0, CI_TEXEL1, CI_PRIMITIVE, CI_SHADE, CI_ENV, CI_1, CI_0,
|
|
};
|
|
|
|
const ECombinerInput CombinerInputAlphaC2_8[ 8 ] =
|
|
{
|
|
CI_COMBINED, CI_TEXEL0, CI_TEXEL1, CI_PRIMITIVE, CI_SHADE, CI_ENV, CI_1, CI_0,
|
|
};
|
|
|
|
|
|
enum EBuildConstantExpressionOptions
|
|
{
|
|
BCE_ALLOW_SHADE,
|
|
BCE_DISALLOW_SHADE,
|
|
};
|
|
|
|
static const CBlendConstantExpression * BuildConstantExpression( const CCombinerOperand * operand, EBuildConstantExpressionOptions options )
|
|
{
|
|
if(operand->IsInput())
|
|
{
|
|
const CCombinerInput * input( static_cast< const CCombinerInput * >( operand ) );
|
|
|
|
switch( input->GetInput() )
|
|
{
|
|
case CI_PRIMITIVE: return new CBlendConstantExpressionValue( BC_PRIMITIVE );
|
|
case CI_ENV: return new CBlendConstantExpressionValue( BC_ENVIRONMENT );
|
|
case CI_PRIMITIVE_ALPHA: return new CBlendConstantExpressionValue( BC_PRIMITIVE_ALPHA );
|
|
case CI_ENV_ALPHA: return new CBlendConstantExpressionValue( BC_ENVIRONMENT_ALPHA );
|
|
case CI_1: return new CBlendConstantExpressionValue( BC_1 );
|
|
case CI_0: return new CBlendConstantExpressionValue( BC_0 );
|
|
case CI_SHADE:
|
|
if( options == BCE_ALLOW_SHADE )
|
|
return new CBlendConstantExpressionValue( BC_SHADE );
|
|
else
|
|
return NULL;
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
else if(operand->IsSum())
|
|
{
|
|
const CCombinerSum * sum( static_cast< const CCombinerSum * >( operand ) );
|
|
|
|
const CBlendConstantExpression * sum_expr( NULL );
|
|
|
|
for( u32 i = 0; i < sum->GetNumOperands(); ++i )
|
|
{
|
|
const CCombinerOperand * sum_term( sum->GetOperand( i ) );
|
|
const CBlendConstantExpression * lhs( sum_expr );
|
|
const CBlendConstantExpression * rhs( BuildConstantExpression( sum_term, options ) );
|
|
|
|
if( rhs == NULL )
|
|
{
|
|
delete sum_expr;
|
|
return NULL;
|
|
}
|
|
|
|
if( sum->IsTermNegated( i ) )
|
|
{
|
|
if( lhs == NULL )
|
|
{
|
|
lhs = new CBlendConstantExpressionValue( BC_0 );
|
|
}
|
|
|
|
sum_expr = new CBlendConstantExpressionSub( lhs, rhs );
|
|
}
|
|
else
|
|
{
|
|
if( lhs == NULL )
|
|
{
|
|
sum_expr = rhs;
|
|
}
|
|
else
|
|
{
|
|
sum_expr = new CBlendConstantExpressionAdd( lhs, rhs );
|
|
}
|
|
}
|
|
}
|
|
|
|
return sum_expr;
|
|
}
|
|
else if(operand->IsProduct())
|
|
{
|
|
const CCombinerProduct * product( static_cast< const CCombinerProduct * >( operand ) );
|
|
|
|
const CBlendConstantExpression * product_expr( NULL );
|
|
|
|
for( u32 i = 0; i < product->GetNumOperands(); ++i )
|
|
{
|
|
const CCombinerOperand * product_term( product->GetOperand( i ) );
|
|
const CBlendConstantExpression * lhs( product_expr );
|
|
const CBlendConstantExpression * rhs( BuildConstantExpression( product_term, options ) );
|
|
|
|
if( rhs == NULL )
|
|
{
|
|
delete product_expr;
|
|
return NULL;
|
|
}
|
|
|
|
if( lhs == NULL )
|
|
{
|
|
product_expr = rhs;
|
|
}
|
|
else
|
|
{
|
|
product_expr = new CBlendConstantExpressionMul( lhs, rhs );
|
|
}
|
|
}
|
|
|
|
return product_expr;
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
CCombinerTree::CCombinerTree( u64 mux, bool two_cycles )
|
|
: mMux( mux )
|
|
, mCycle1( NULL )
|
|
, mCycle1A( NULL )
|
|
, mCycle2( NULL )
|
|
, mCycle2A( NULL )
|
|
{
|
|
RDP_Combine m; m.mux = mux;
|
|
//fprintf(fh, "\n\t\tcase 0x%08x%08xLL:\n", mux0, mux1);
|
|
//fprintf(fh, "\t\t//aRGB0: (%s - %s) * %s + %s\n", sc_colcombtypes16[aRGB0], sc_colcombtypes16[bRGB0], sc_colcombtypes32[cRGB0], sc_colcombtypes8[dRGB0]);
|
|
//fprintf(fh, "\t\t//aA0 : (%s - %s) * %s + %s\n", sc_colcombtypes8[aA0], sc_colcombtypes8[bA0], sc_colcombtypes8[cA0], sc_colcombtypes8[dA0]);
|
|
//fprintf(fh, "\t\t//aRGB1: (%s - %s) * %s + %s\n", sc_colcombtypes16[aRGB1], sc_colcombtypes16[bRGB1], sc_colcombtypes32[cRGB1], sc_colcombtypes8[dRGB1]);
|
|
//fprintf(fh, "\t\t//aA1 : (%s - %s) * %s + %s\n", sc_colcombtypes8[aA1], sc_colcombtypes8[bA1], sc_colcombtypes8[cA1], sc_colcombtypes8[dA1]);
|
|
|
|
mCycle1 = BuildCycle1( CombinerInput16[m.aRGB0], CombinerInput16[m.bRGB0], CombinerInput32[m.cRGB0], CombinerInput8[m.dRGB0] );
|
|
mCycle1A = BuildCycle1( CombinerInputAlphaC1_8[m.aA0], CombinerInputAlphaC1_8[m.bA0], CombinerInputAlphaC1_8[m.cA0], CombinerInputAlphaC1_8[m.dA0] );
|
|
|
|
if( two_cycles )
|
|
{
|
|
mCycle2 = BuildCycle2( CombinerInput16[m.aRGB1], CombinerInput16[m.bRGB1], CombinerInput32[m.cRGB1], CombinerInput8[m.dRGB1], mCycle1 );
|
|
mCycle2A = BuildCycle2( CombinerInputAlphaC2_8[m.aA1], CombinerInputAlphaC2_8[m.bA1], CombinerInputAlphaC2_8[m.cA1], CombinerInputAlphaC2_8[m.dA1], mCycle1A );
|
|
mBlendStates = GenerateBlendStates( mCycle2, mCycle2A );
|
|
}
|
|
else
|
|
{
|
|
mBlendStates = GenerateBlendStates( mCycle1, mCycle1A );
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
CCombinerTree::~CCombinerTree()
|
|
{
|
|
delete mCycle1;
|
|
delete mCycle1A;
|
|
delete mCycle2;
|
|
delete mCycle2A;
|
|
}
|
|
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
CCombinerOperand * CCombinerTree::BuildCycle1( ECombinerInput a, ECombinerInput b, ECombinerInput c, ECombinerInput d )
|
|
{
|
|
CCombinerOperand * input_a( new CCombinerInput( a ) );
|
|
CCombinerOperand * input_b( new CCombinerInput( b ) );
|
|
CCombinerOperand * input_c( new CCombinerInput( c ) );
|
|
CCombinerOperand * input_d( new CCombinerInput( d ) );
|
|
|
|
return Build( input_a, input_b, input_c, input_d );
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
CCombinerOperand * CCombinerTree::BuildCycle2( ECombinerInput a, ECombinerInput b, ECombinerInput c, ECombinerInput d, const CCombinerOperand * cycle_1_output )
|
|
{
|
|
CCombinerOperand * input_a( a == CI_COMBINED ? cycle_1_output->Clone() : new CCombinerInput( a ) );
|
|
CCombinerOperand * input_b( b == CI_COMBINED ? cycle_1_output->Clone() : new CCombinerInput( b ) );
|
|
CCombinerOperand * input_c( c == CI_COMBINED ? cycle_1_output->Clone() : new CCombinerInput( c ) );
|
|
CCombinerOperand * input_d( d == CI_COMBINED ? cycle_1_output->Clone() : new CCombinerInput( d ) );
|
|
|
|
return Build( input_a, input_b, input_c, input_d );
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Build an expression of the form output = (A-B)*C + D, and simplify.
|
|
//*****************************************************************************
|
|
CCombinerOperand * CCombinerTree::Build( CCombinerOperand * a, CCombinerOperand * b, CCombinerOperand * c, CCombinerOperand * d )
|
|
{
|
|
CCombinerSum * sum( new CCombinerSum( NULL ) );
|
|
sum->Add( a );
|
|
sum->Sub( b );
|
|
|
|
CCombinerProduct * product( new CCombinerProduct( sum ) );
|
|
product->Mul( c );
|
|
|
|
CCombinerSum * output( new CCombinerSum( product ) );
|
|
output->Add( d );
|
|
|
|
return Simplify( output );
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
COutputStream & CCombinerTree::Stream( COutputStream & stream ) const
|
|
{
|
|
stream << "RGB: "; mCycle2->Stream( stream ); stream << "\n";
|
|
stream << "Alpha: "; mCycle2A->Stream( stream ); stream << "\n";
|
|
return stream;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
CBlendStates * CCombinerTree::GenerateBlendStates( const CCombinerOperand * colour_operand, const CCombinerOperand * alpha_operand ) const
|
|
{
|
|
CBlendStates * states( new CBlendStates );
|
|
|
|
states->SetAlphaSettings( GenerateAlphaRenderSettings( alpha_operand ) );
|
|
|
|
GenerateRenderSettings( states, colour_operand );
|
|
|
|
return states;
|
|
}
|
|
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
namespace
|
|
{
|
|
void ApplyAlphaModulateTerm( CAlphaRenderSettings * settings, const CCombinerOperand * operand )
|
|
{
|
|
if( operand->IsInput() )
|
|
{
|
|
const CCombinerInput * input( static_cast< const CCombinerInput * >( operand ) );
|
|
|
|
switch( input->GetInput() )
|
|
{
|
|
case CI_TEXEL0:
|
|
settings->AddTermTexel0();
|
|
break;
|
|
case CI_TEXEL1:
|
|
settings->AddTermTexel1();
|
|
break;
|
|
case CI_SHADE:
|
|
settings->AddTermConstant( new CBlendConstantExpressionValue( BC_SHADE ) );
|
|
break;
|
|
case CI_PRIMITIVE:
|
|
settings->AddTermConstant( new CBlendConstantExpressionValue( BC_PRIMITIVE ) );
|
|
break;
|
|
case CI_ENV:
|
|
settings->AddTermConstant( new CBlendConstantExpressionValue( BC_ENVIRONMENT ) );
|
|
break;
|
|
case CI_PRIMITIVE_ALPHA:
|
|
settings->AddTermConstant( new CBlendConstantExpressionValue( BC_PRIMITIVE_ALPHA ) );
|
|
break;
|
|
case CI_ENV_ALPHA:
|
|
settings->AddTermConstant( new CBlendConstantExpressionValue( BC_ENVIRONMENT_ALPHA ) );
|
|
break;
|
|
case CI_0:
|
|
settings->AddTermConstant( new CBlendConstantExpressionValue( BC_0 ) );
|
|
break;
|
|
case CI_1:
|
|
settings->AddTermConstant( new CBlendConstantExpressionValue( BC_1 ) );
|
|
break;
|
|
|
|
default:
|
|
#ifdef DAEDALUS_DEBUG_DISPLAYLIST
|
|
printf( "Unhandled Alpha Input: %s\n", GetCombinerInputName( input->GetInput() ) );
|
|
#endif
|
|
settings->SetInexact();
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Try to reduce to a constant term, and add that
|
|
//
|
|
const CBlendConstantExpression * constant_expression( BuildConstantExpression( operand, BCE_ALLOW_SHADE ) );
|
|
if( constant_expression != NULL )
|
|
{
|
|
settings->AddTermConstant( constant_expression );
|
|
}
|
|
else
|
|
{
|
|
#ifdef DAEDALUS_DEBUG_DISPLAYLIST
|
|
COutputStringStream str;
|
|
operand->Stream( str );
|
|
printf( "\n********************************\n" );
|
|
printf( "Unhandled alpha - not a simple term: %s\n", str.c_str() );
|
|
printf( "********************************\n\n" );
|
|
#endif
|
|
settings->SetInexact();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
CAlphaRenderSettings * CCombinerTree::GenerateAlphaRenderSettings( const CCombinerOperand * operand ) const
|
|
{
|
|
COutputStringStream str;
|
|
operand->Stream( str );
|
|
|
|
CAlphaRenderSettings * settings( new CAlphaRenderSettings( str.c_str() ) );
|
|
|
|
if(operand->IsProduct())
|
|
{
|
|
const CCombinerProduct * product( static_cast< const CCombinerProduct * >( operand ) );
|
|
for( u32 i = 0; i < product->GetNumOperands(); ++i )
|
|
{
|
|
ApplyAlphaModulateTerm( settings, product->GetOperand( i ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ApplyAlphaModulateTerm( settings, operand );
|
|
}
|
|
|
|
settings->Finalise();
|
|
|
|
return settings;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
namespace
|
|
{
|
|
void ApplyModulateTerm( CRenderSettingsModulate * settings, const CCombinerOperand * operand )
|
|
{
|
|
if( operand->IsInput() )
|
|
{
|
|
const CCombinerInput * input( static_cast< const CCombinerInput * >( operand ) );
|
|
|
|
switch( input->GetInput() )
|
|
{
|
|
case CI_TEXEL0:
|
|
settings->AddTermTexel0();
|
|
break;
|
|
case CI_TEXEL1:
|
|
settings->AddTermTexel1();
|
|
break;
|
|
case CI_SHADE:
|
|
settings->AddTermConstant( new CBlendConstantExpressionValue( BC_SHADE ) );
|
|
break;
|
|
case CI_PRIMITIVE:
|
|
settings->AddTermConstant( new CBlendConstantExpressionValue( BC_PRIMITIVE ) );
|
|
break;
|
|
case CI_ENV:
|
|
settings->AddTermConstant( new CBlendConstantExpressionValue( BC_ENVIRONMENT ) );
|
|
break;
|
|
case CI_PRIMITIVE_ALPHA:
|
|
settings->AddTermConstant( new CBlendConstantExpressionValue( BC_PRIMITIVE_ALPHA ) );
|
|
break;
|
|
case CI_ENV_ALPHA:
|
|
settings->AddTermConstant( new CBlendConstantExpressionValue( BC_ENVIRONMENT_ALPHA ) );
|
|
break;
|
|
case CI_0:
|
|
settings->AddTermConstant( new CBlendConstantExpressionValue( BC_0 ) );
|
|
break;
|
|
case CI_1:
|
|
settings->AddTermConstant( new CBlendConstantExpressionValue( BC_1 ) );
|
|
break;
|
|
|
|
default:
|
|
#ifdef DAEDALUS_DEBUG_DISPLAYLIST
|
|
printf( "Unhandled Input: %s\n", GetCombinerInputName( input->GetInput() ) );
|
|
#endif
|
|
settings->SetInexact();
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Try to reduce to a constant term, and add that
|
|
//
|
|
const CBlendConstantExpression * constant_expression( BuildConstantExpression( operand, BCE_ALLOW_SHADE ) );
|
|
if( constant_expression != NULL )
|
|
{
|
|
settings->AddTermConstant( constant_expression );
|
|
}
|
|
else
|
|
{
|
|
#ifdef DAEDALUS_DEBUG_DISPLAYLIST
|
|
COutputStringStream str;
|
|
operand->Stream( str );
|
|
printf( "\n********************************\n" );
|
|
printf( "Unhandled rgb - not a simple term: %s\n", str.c_str() );
|
|
printf( "********************************\n\n" );
|
|
#endif
|
|
settings->SetInexact();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
void CCombinerTree::GenerateRenderSettings( CBlendStates * states, const CCombinerOperand * operand ) const
|
|
{
|
|
if(operand->IsInput())
|
|
{
|
|
COutputStringStream str;
|
|
operand->Stream( str );
|
|
|
|
CRenderSettingsModulate * settings( new CRenderSettingsModulate( str.c_str() ) );
|
|
|
|
ApplyModulateTerm( settings, operand );
|
|
|
|
settings->Finalise();
|
|
|
|
states->AddColourSettings( settings );
|
|
}
|
|
else if(operand->IsSum())
|
|
{
|
|
const CCombinerSum * sum( static_cast< const CCombinerSum * >( operand ) );
|
|
|
|
for( u32 i = 0; i < sum->GetNumOperands(); ++i )
|
|
{
|
|
const CCombinerOperand * sum_term( sum->GetOperand( i ) );
|
|
|
|
// Recurse
|
|
if( sum->IsTermNegated( i ) )
|
|
{
|
|
printf( "Negative term!!\n" );
|
|
COutputStringStream str;
|
|
str << "- ";
|
|
sum->Stream( str );
|
|
states->AddColourSettings( new CRenderSettingsInvalid( str.c_str() ) );
|
|
}
|
|
else
|
|
{
|
|
GenerateRenderSettings( states, sum_term );
|
|
}
|
|
}
|
|
}
|
|
else if(operand->IsProduct())
|
|
{
|
|
const CCombinerProduct * product( static_cast< const CCombinerProduct * >( operand ) );
|
|
|
|
COutputStringStream str;
|
|
product->Stream( str );
|
|
|
|
CRenderSettingsModulate * settings( new CRenderSettingsModulate( str.c_str() ) );
|
|
|
|
for( u32 i = 0; i < product->GetNumOperands(); ++i )
|
|
{
|
|
ApplyModulateTerm( settings, product->GetOperand( i ) );
|
|
}
|
|
|
|
settings->Finalise();
|
|
|
|
states->AddColourSettings( settings );
|
|
}
|
|
else if(operand->IsBlend())
|
|
{
|
|
const CCombinerBlend * blend( static_cast< const CCombinerBlend * >( operand ) );
|
|
|
|
const CCombinerOperand * operand_a( blend->GetInputA() ); // Needs to be a constant factor /w shade
|
|
const CCombinerOperand * operand_b( blend->GetInputB() ); // Needs to be a constant factor
|
|
const CCombinerOperand * operand_f( blend->GetInputF() );
|
|
|
|
COutputStringStream str;
|
|
blend->Stream( str );
|
|
bool handled( false );
|
|
|
|
if( operand_f->IsInput( CI_TEXEL0 ) )
|
|
{
|
|
const CBlendConstantExpression * expr_a( BuildConstantExpression( operand_a, BCE_ALLOW_SHADE ) );
|
|
const CBlendConstantExpression * expr_b( BuildConstantExpression( operand_b, BCE_DISALLOW_SHADE ) );
|
|
if( expr_a != NULL && expr_b != NULL )
|
|
{
|
|
states->AddColourSettings( new CRenderSettingsBlend( str.c_str(), expr_a, expr_b ) );
|
|
handled = true;
|
|
}
|
|
else
|
|
{
|
|
delete expr_a;
|
|
delete expr_b;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const CBlendConstantExpression * expr_a( BuildConstantExpression( operand_a, BCE_ALLOW_SHADE ) );
|
|
const CBlendConstantExpression * expr_b( BuildConstantExpression( operand_b, BCE_ALLOW_SHADE ) );
|
|
const CBlendConstantExpression * expr_f( BuildConstantExpression( operand_f, BCE_ALLOW_SHADE ) );
|
|
|
|
if( expr_a != NULL && expr_b != NULL && expr_f != NULL )
|
|
{
|
|
const CBlendConstantExpressionBlend * expr_blend( new CBlendConstantExpressionBlend( expr_a, expr_b, expr_f ) );
|
|
CRenderSettingsModulate * settings( new CRenderSettingsModulate( str.c_str() ) );
|
|
|
|
settings->AddTermConstant( expr_blend );
|
|
settings->Finalise();
|
|
states->AddColourSettings( settings );
|
|
handled = true;
|
|
}
|
|
else
|
|
{
|
|
delete expr_a;
|
|
delete expr_b;
|
|
delete expr_f;
|
|
}
|
|
}
|
|
|
|
if( !handled )
|
|
{
|
|
#ifdef DAEDALUS_DEBUG_DISPLAYLIST
|
|
printf( "CANNOT BLEND!\n" );
|
|
#endif
|
|
states->AddColourSettings( new CRenderSettingsInvalid( str.c_str() ) );
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
COutputStringStream str;
|
|
operand->Stream( str );
|
|
#ifdef DAEDALUS_DEBUG_DISPLAYLIST
|
|
printf( "\n********************************\n" );
|
|
printf( "Unhandled - inner operand is not an input/product/sum: %s\n", str.c_str() );
|
|
printf( "********************************\n\n" );
|
|
#endif
|
|
states->AddColourSettings( new CRenderSettingsInvalid( str.c_str() ) );
|
|
}
|
|
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
CCombinerOperand * CCombinerTree::Simplify( CCombinerOperand * operand )
|
|
{
|
|
bool did_something;
|
|
do
|
|
{
|
|
CCombinerOperand * new_tree( operand->SimplifyAndReduce() );
|
|
|
|
did_something = !new_tree->IsEqual( *operand );
|
|
delete operand;
|
|
operand = new_tree;
|
|
}
|
|
while( did_something );
|
|
|
|
return operand;
|
|
}
|