2007-08-08 04:50:02 +02:00
/*
2024-03-27 16:23:53 +01:00
PROC - NODE . hpp - Key abstraction of the Render Engine : a Processing Node
2010-12-17 23:28:49 +01:00
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
Copyright ( C )
2008 , Hermann Vosseler < Ichthyostega @ web . de >
2010-12-17 23:28:49 +01:00
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
* * Lumiera * * 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 . See the file COPYING for further details .
2010-12-17 23:28:49 +01:00
2007-08-08 04:50:02 +02:00
*/
2024-03-27 16:23:53 +01:00
/** @file proc-node.hpp
2008-06-24 05:19:11 +02:00
* * Interface to the processing nodes and the render nodes network .
* *
* * Actually , there are three different interfaces to consider
2024-05-06 23:51:48 +02:00
* * - the ProcNode # pull is the invocation interface . It is function - call style
* * - the builder interface , comprised by the NodeFactory and the WiringFactory .
* * - the actual processing function is supposed to be a C function and will be
* * hooked up within a thin wrapper .
2008-06-24 05:19:11 +02:00
* *
* * By using the builder interface , concrete node and wiring descriptor classes are created ,
* * based on some templates . These concrete classes form the " glue " to tie the node network
2009-08-29 16:13:42 +02:00
* * together and contain much of the operation behaviour in a hard wired fashion .
2024-06-21 16:14:24 +02:00
* *
* * @ todo WIP - WIP - WIP 2024 Node - Invocation is reworked from ground up for the » Playback Vertical Slice «
* *
2008-06-24 05:19:11 +02:00
* * @ see nodefactory . hpp
* * @ see operationpoint . hpp
*/
2007-08-08 04:50:02 +02:00
2024-06-21 16:14:24 +02:00
# ifndef STEAM_ENGINE_PROC_NODE_H
# define STEAM_ENGINE_PROC_NODE_H
2007-08-08 04:50:02 +02:00
2011-12-01 23:32:34 +01:00
# include "lib/error.hpp"
2024-10-14 18:29:29 +02:00
# include "lib/nocopy.hpp"
2024-11-01 23:57:14 +01:00
# include "lib/hash-value.h"
2024-12-13 03:28:28 +01:00
//#include "steam/asset/proc.hpp"
//#include "steam/mobject/parameter.hpp"
# include "steam/engine/buffhandle.hpp"
2024-06-23 19:40:39 +02:00
# include "steam/engine/turnout-system.hpp"
2024-06-29 04:23:55 +02:00
# include "lib/ref-array.hpp" /////////////////////OOO phase out
2024-10-25 18:13:55 +02:00
# include "lib/format-string.hpp"
2024-06-29 04:23:55 +02:00
# include "lib/several.hpp"
2007-08-08 04:50:02 +02:00
2024-11-01 23:57:14 +01:00
# include <string>
2008-06-24 05:19:11 +02:00
# include <vector>
2024-07-31 19:20:44 +02:00
# include <optional>
2007-08-08 04:50:02 +02:00
2018-11-15 23:55:13 +01:00
namespace steam {
2008-05-27 07:22:27 +02:00
namespace engine {
2024-10-25 18:13:55 +02:00
namespace err = lumiera : : error ;
2007-08-08 04:50:02 +02:00
2024-07-06 21:31:03 +02:00
using std : : move ;
2024-11-01 23:57:14 +01:00
using std : : string ;
using lib : : HashVal ;
2024-10-25 18:13:55 +02:00
using util : : _Fmt ;
2008-05-27 07:22:27 +02:00
2024-11-02 23:54:41 +01:00
class ProcID ;
2008-05-27 07:22:27 +02:00
class ProcNode ;
2024-10-26 23:44:42 +02:00
class ProcNodeDiagnostic ;
2024-07-06 21:31:03 +02:00
using ProcNodeRef = std : : reference_wrapper < ProcNode > ;
2024-07-31 19:20:44 +02:00
using OptionalBuff = std : : optional < BuffHandle > ;
2024-12-13 03:28:28 +01:00
2008-06-14 04:19:58 +02:00
2024-06-23 19:40:39 +02:00
class Port
2024-10-22 05:59:00 +02:00
// : util::MoveOnly //////////////////////////////////////////////////OOO not clear if necessary here, and requires us to declare the ctors!!! See Turnout
: util : : NonCopyable //////////////////////////////////////////////////OOO this would be the perfect solution, if we manage to handle this within the builder
2024-06-23 19:40:39 +02:00
{
public :
virtual ~ Port ( ) ; ///< this is an interface
2024-11-02 23:54:41 +01:00
Port ( ProcID & id ) : procID { id } { }
2024-10-14 18:29:29 +02:00
2024-07-31 19:20:44 +02:00
virtual BuffHandle weave ( TurnoutSystem & , OptionalBuff = std : : nullopt ) = 0 ;
2024-10-14 18:29:29 +02:00
2024-10-22 05:59:00 +02:00
// // compiler does not generate a move-ctor automatically due to explicit dtor
// Port() = default;
// Port(Port&&) = default;
2024-11-02 23:54:41 +01:00
ProcID & procID ;
2024-06-23 19:40:39 +02:00
} ;
2008-06-14 04:19:58 +02:00
2024-07-10 02:35:29 +02:00
using PortRef = std : : reference_wrapper < Port > ;
2008-06-14 04:19:58 +02:00
/**
2008-06-29 15:32:19 +02:00
* Interface : Description of the input and output ports ,
* processing function and predecessor nodes for a given ProcNode .
2012-02-04 22:20:21 +01:00
*
* @ todo the design of this part is messy in several respects .
* Basically , its left - over from a first prototypical implementation from 2008
* As of 1 / 2012 , we ' re re - shaping that engine interface and invocation with a top - down approach ,
* starting from the player . Anyhow , you can expect the basic setup to remain as - is : there will
2024-05-06 23:51:48 +02:00
* be a ProcNode and a Connectivity descriptor , telling how it ' s connected to its predecessors ,
* and defining how the Node is supposed to operate
2024-06-21 16:14:24 +02:00
*
* @ todo WIP - WIP - WIP 2024 Node - Invocation is reworked from ground up for the » Playback Vertical Slice «
2008-06-14 04:19:58 +02:00
*/
2024-05-06 23:51:48 +02:00
class Connectivity
2008-06-14 04:19:58 +02:00
{
2012-02-04 22:20:21 +01:00
public : /* === public information record describing the node graph === */
2024-06-21 16:14:24 +02:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
2024-07-06 21:31:03 +02:00
using Ports = lib : : Several < Port > ;
using Leads = lib : : Several < ProcNodeRef > ;
2008-07-16 05:09:04 +02:00
2024-07-06 21:31:03 +02:00
Ports ports ;
Leads leads ;
2008-07-20 20:08:08 +02:00
2024-06-21 16:14:24 +02:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
2008-10-17 04:29:15 +02:00
2024-07-06 21:31:03 +02:00
// protected:
2024-06-21 16:14:24 +02:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
2024-12-13 03:28:28 +01:00
Connectivity ( Ports & & pr , Leads & & lr )
2024-07-06 21:31:03 +02:00
: ports ( move ( pr ) )
, leads ( move ( lr ) )
{ }
2024-06-21 16:14:24 +02:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
2008-07-21 03:25:06 +02:00
2012-02-04 22:20:21 +01:00
2024-06-21 16:14:24 +02:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
2012-02-04 22:20:21 +01:00
/* ==== strategy API for configuring the node operation ==== */
2024-10-23 16:27:09 +02:00
friend class ProcNode ; /////////////////////////////////OOO who needs friendship?
2012-02-04 22:20:21 +01:00
2008-06-29 15:32:19 +02:00
/** the wiring-dependent part of the node operation.
* Includes the creation of a one - way state object on the stack
2008-10-09 05:23:24 +02:00
* holding the actual buffer pointers and issuing the recursive pull ( ) calls
2008-06-29 15:32:19 +02:00
* @ see NodeWiring # callDown default implementation
*/
2024-06-24 23:49:55 +02:00
# if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation
2009-09-05 04:10:51 +02:00
virtual BuffHandle
2024-06-21 16:14:24 +02:00
callDown ( StateClosure_OBSOLETE & currentProcess , uint requiredOutputNr ) const = 0 ;
2024-06-24 23:49:55 +02:00
# endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation
2024-06-21 16:14:24 +02:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
2008-06-14 04:19:58 +02:00
} ;
2008-06-24 05:19:11 +02:00
2007-08-09 18:51:47 +02:00
/**
* Key abstraction of the Render Engine : A Data processing Node
2009-09-05 18:15:58 +02:00
*
* @ todo it ' s not clear as of 9 / 09 if ProcNode shall be an ABC / Interface
* It might be used as ABC ( as was the original intention ) when implementing
* several query / information functions . In that case , the ctor will become protected .
* The alternative would be to push down these information - retrieval part into a
2024-05-06 23:51:48 +02:00
* configurable element within Connectivity , in which case we even might drop
2012-02-04 22:20:21 +01:00
* ProcNode as a frontend entirely .
2024-06-21 16:14:24 +02:00
* @ todo WIP - WIP - WIP 2024 Node - Invocation is reworked from ground up for the » Playback Vertical Slice «
2007-08-09 18:51:47 +02:00
*/
class ProcNode
2018-03-24 05:35:13 +01:00
: util : : NonCopyable
2007-08-09 18:51:47 +02:00
{
2008-06-24 05:19:11 +02:00
2024-07-06 21:31:03 +02:00
Connectivity wiring_ ;
2008-06-24 05:19:11 +02:00
2009-09-05 18:15:58 +02:00
public :
2024-06-21 16:14:24 +02:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
2024-07-06 21:31:03 +02:00
ProcNode ( Connectivity & & con )
: wiring_ ( move ( con ) )
2008-06-24 05:19:11 +02:00
{ }
2008-05-27 07:22:27 +02:00
2024-06-21 16:14:24 +02:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
2008-05-27 07:22:27 +02:00
2008-06-14 04:19:58 +02:00
2008-05-27 07:22:27 +02:00
public :
2024-06-21 16:14:24 +02:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
2009-09-04 01:59:44 +02:00
2024-10-23 16:27:09 +02:00
Port &
getPort ( uint portIdx )
{
2024-10-25 18:13:55 +02:00
if ( portIdx > = wiring_ . ports . size ( ) )
throw err : : Logic { _Fmt { " Accessing node-port #%d, while only %d ports are defined. " }
% portIdx % wiring_ . ports . size ( )
, LERR_ ( INDEX_BOUNDS )
} ;
2024-10-23 16:27:09 +02:00
return wiring_ . ports [ portIdx ] ;
}
2009-09-05 04:10:51 +02:00
2008-06-14 04:19:58 +02:00
/** Engine Core operation: render and pull output from this node.
2009-08-29 16:13:42 +02:00
* On return , currentProcess will hold onto output buffer ( s )
2008-08-04 05:42:55 +02:00
* containing the calculated result frames . In case this node
2009-08-29 16:13:42 +02:00
* calculates a multichannel output , only one channel can be
2008-08-04 05:42:55 +02:00
* retrieved by such a \ c pull ( ) call , but you can expect data
* of the other channels to be processed and fed to cache .
2024-05-06 23:51:48 +02:00
* @ param currentProcess the current processing state for
2008-06-24 05:19:11 +02:00
* managing buffers and accessing current parameter values
2008-10-13 04:33:10 +02:00
* @ param requestedOutputNr the output channel requested
* ( in case this node delivers more than one output channel )
2009-08-29 16:13:42 +02:00
* @ return handle to the buffer containing the calculated result .
2008-05-27 07:22:27 +02:00
*/
2024-06-24 23:49:55 +02:00
# if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation
2008-07-11 19:40:11 +02:00
BuffHandle
2024-06-21 16:14:24 +02:00
pull ( StateClosure_OBSOLETE & currentProcess , uint requestedOutputNr = 0 ) const
2008-06-14 04:19:58 +02:00
{
2008-10-13 04:33:10 +02:00
return this - > wiringConfig_ . callDown ( currentProcess , requestedOutputNr ) ;
2008-06-14 04:19:58 +02:00
}
2024-06-24 23:49:55 +02:00
# endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1367 : Rebuild the Node Invocation
2024-06-21 16:14:24 +02:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
2008-06-24 05:19:11 +02:00
2024-10-26 23:44:42 +02:00
/// „backdoor“ to watch internals from tests
friend class ProcNodeDiagnostic ;
2007-08-09 18:51:47 +02:00
} ;
2008-06-24 05:19:11 +02:00
2009-09-05 04:10:51 +02:00
2024-06-21 16:14:24 +02:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Rebuild the Node Invocation
2024-10-26 23:44:42 +02:00
class ProcNodeDiagnostic
: util : : MoveOnly
{
ProcNode & n_ ;
public :
ProcNodeDiagnostic ( ProcNode & theNode )
: n_ { theNode }
{ }
auto & leads ( ) { return n_ . wiring_ . leads ; }
auto & ports ( ) { return n_ . wiring_ . ports ; }
2024-11-04 23:56:16 +01:00
bool isSrc ( ) { return n_ . wiring_ . leads . empty ( ) ; }
2024-10-26 23:44:42 +02:00
bool
isValid ( )
{
return 0 < ports ( ) . size ( ) ;
///////////////////////////////////////////////////TODO 10/2024 more to verify here
}
2024-11-01 23:57:14 +01:00
2024-11-02 23:54:41 +01:00
string getNodeSpec ( ) ; ///< generate a descriptive Spec of this ProcNode for diagnostics
HashVal getNodeHash ( ) ; ///< calculate an unique hash-key to designate this node
2024-11-01 23:57:14 +01:00
2024-11-02 23:54:41 +01:00
string getPortSpec ( uint portIdx ) ; ///< generate a descriptive diagnostic Spec for the designated Turnout
HashVal getPortHash ( uint portIdx ) ; ///< calculate an unique, stable and reproducible hash-key to identify the Turnout
2024-10-26 23:44:42 +02:00
} ;
inline ProcNodeDiagnostic
watch ( ProcNode & theNode )
{
return ProcNodeDiagnostic { theNode } ;
}
2009-09-05 04:10:51 +02:00
2018-11-15 23:55:13 +01:00
} } // namespace steam::engine
2024-06-21 16:14:24 +02:00
# endif /*STEAM_ENGINE_PROC_NODE_H*/