NAME

Rivl_NodeClass, Rivl_NodeClassInit - node class structure

SYNOPSIS

#include <rivl.h>
int
Rivl_NodeClassInit(classPtr)
Rivl_DestroyNodeClass(interp,classPtr)

ARGUMENTS

Tcl_Interp *interp (in)
Tcl interpreter.
Rivl_NodeClass *classPtr (in)
Pointer to structure that defines the new node class.

DESCRIPTION

The Rivl_NodeClass structure defines a node class. There is exactly one Rivl_NodeClass structure for each class; each node of that class contains a pointer to the structure.

Typically the structure is declared statically in the function implementing the node command for the class. The first time the command is called, Rivl_NodeClassInit is called to initialize the structure with default values. This is followed by code overriding default values as necessary.

Rivl_DestroyNodeClass destroys the class indicated by classPtr. This is typically used when a node command and its associated class are deleted or redefined dynamically. All existing nodes of the class are invalidated; henceforth any attempt to compute signal data from that node results in an error. The fields of Rivl_NodeClass are described below. At the end of each description the default value of the field is given; this is the value placed in the field by Rivl_NodeClassInit.

NAME

classPtr->name provides a name for the class. Currently the name is used mostly for debugging purposes and special-purpose graph optimizations.

There is no default for name; it must be specified.

COMPUTE_HAVE_REGION_PROC

classPtr->computeHaveRegionProc computes the have region of the node's output signal. computeHaveRegionProc must match the following prototype:

void
ComputeHaveRegionProc(
   Tcl_Interp *interp,
   Rivl_Signal signal,
   Rivl_Region *inHaves,
   Rivl_Region outHave,
   Rivl_Point sampleRate;)
signal is the node's output signal. inHaves is an array with one element for each input. inHaves[i] contains the have region for input signal i; this is equivalent to the result of calling Rivl_SignalHaveRegion on signal->inputs[i] with sampleRate.

computeHaveRegionProc must place the output signal's have region into outHave. On entry, outHave is initialized to an allocated region with a default value depending on the type of node. For leaf nodes, outHave is initialized to the infinite region. For non-leaf nodes, outHave is initialized to a copy of inHaves[0]. sampleRate is the sample rate at which the output have region should be expressed. Any spatial value that contributes to the calculation of outHave should first be multiplied by sampleRate. See the "sample rate" section below for an explanation.

If classPtr->autoPrepareHaveRegionsFlag is FALSE, the input have regions are not precomputed. In this case, inHaves is an array with the same dimensions but undefined contents. This flag is used in rare cases where the input have regions must be computed in a special way; for example, with a different sample rate than the output.

The procedure Rivl_ComputeHaveRegionFromSize may be used as a value for computeHaveRegionProc; it sets outHave to the rectangle from (0,0) to the signal's size. This is appropriate for many leaf nodes.

The default for computeHaveRegionProc sets outHave to the infinite region for leaf nodes, and the union of all inHaves for non-leaf nodes. Note that the latter is different from the default value of outHave passed into computeHaveRegionProc.

COMPUTE_NEED_REGION_PROC

classPtr->computeNeedRegionProc computes the need regions of the node's input signals given a need region for the output signal. That is, given that we are computing a region N of a signal, what regions N1, ..., Ni should we compute of the signal's inputs? computeNeedRegionProc must match the following prototype:

void
ComputeNeedRegionsProc (
   Tcl_Interp *interp;
   Rivl_Signal signal;
   Rivl_Region *inNeeds;
   Rivl_Region outNeed;
   Rivl_Point sampleRate;)
signal is the node's output signal. outNeed is the current need region -- the region of signal being computed. inNeeds is an array with one element for each input. Each inNeeds[i] must be filled with the need region of input i with respect to outNeed. The inNeeds elements are initialized to copies of outNeed.

sampleRate is the sample rate at which outNeed is expressed and at which inNeeds should be expressed. Any spatial value that contributes to the calculation of inNeeds should first be multiplied by sampleRate. See the "sample rate" section below for an explanation.

computeNeedRegionsProc is used to compute the inNeeds parameter that is passed to computeDataProc. Its result also indirectly affects the inBufs parameter if autoComputeInputsFlag is TRUE. computeNeedRegionsProc is ignored for leaf nodes.

The default for computeNeedRegionProc does nothing, leaving a copy of outNeed in each inNeeds[i].

COMPUTE_DATA_PROC

classPtr->computeDataProc computes a region of a signal's data into a buffer, possibly using data from the signal's inputs. computeDataProc must match the following prototype:

int
ComputeDataProc (
   Tcl_Interp *interp;
   Rivl_Signal signal;
   Rivl_Region *inNeeds;
   Rivl_Region outNeed;
   Rivl_Buf *inBufs;
   Rivl_Buf *outBufPtr;
   Rivl_Point sampleRate;)
outNeed contains the region to compute. inNeeds is an array with one element for each input, where inNeeds[i] contains the need region for input signal i with respect to outNeed. inNeeds is obtained by calling classInfo->computeNeedRegions. If cropInputNeedRegionsFlag is TRUE, then each inNeeds[i] is intersected with the have region of input signal i.

inBufs is an array with one element for each input. If autoComputeInputsFlag is TRUE, then each inBufs[i] contains the data for input signal i in the region inNeeds[i]. The data in inBufs[i] outside the region inNeeds[i] is undefined. The area of inBufs[i] is taken from the clip box of inNeeds[i].

If autoComputeInputsFlag is FALSE, then inHaves is an array with the same dimensions but undefined contents. In this case the function must compute any desired input data by calling Rivl_ComputeSignalData manually. autoComputeInputsFlag is ignored for leaf nodes.

computeDataProc must compute the data in outNeed and return it via one of two methods. The first method is to fill the buffer pointed to by outBuf, which is an allocated buffer guaranteed to hold at least the region outNeed. The function should not modify values in outBuf outside the region outNeed. The second method is to point outBuf to a new buffer containing the requested data. The node class indicates which method it will use by setting imCreateFlag to FALSE for the first method and TRUE for the second method (FALSE is the default).

The need regions and buffers are in terms of sampleRate. Any spatial value that contributes to the computation should first be multiplied by sampleRate. See SAMPLE RATE, below, for an explanation.

If computeDataProc completes successfully, it should return TCL_OK. Otherwise, it should place an error message in interp->result and return TCL_ERROR. There is no default for computeDataProc; it must be specified. If you want the node to pass its input data untouched, then set autoComputeInputsFlag to FALSE and call Rivl_ComputeSignalData manually. See the implementation of sig_dup for an example.

FREE_PROC

classPtr->freeProc releases resources associated with a node's instance data. freeProc must match the following prototype:

void
FreeProc (
   Tcl_Interp *interp;
   Rivl_Node node;)
node contains the node that is being freed. freeProc should release resources associated with node->data, including freeing node->data if it points to a malloc'd structure. It should not free the structure pointed to by node; that is handled automatically by Rivl.

The default for freeProc checks to see if node->data is non-NULL; if so, it calls free() on it. Thus you need only define freeProc if there are items within node->data that need to be manually deallocated, or if node->data is set to a value that is not a malloc address.

IM_CREATE_FLAG

If classPtr->imCreateFlag is TRUE, then computeDataProc creates its own output buffer. If it is FALSE, then computeDataProc fills the buffer it receives in the outBuf parameter. See computeDataProc for details.

The default is FALSE.

AUTO_PREPARE_HAVE_REGIONS_FLAG

If classPtr->autoPrepareHaveRegionsFlag is TRUE, then input have regions are automatically computed and passed to computeHaveRegionProc. Otherwise, they are not. See computeHaveRegionProc for details.

The default is TRUE. Set this to FALSE only if you want to compute the input have regions manually for some reason.

CROP_INPUT_NEED_REGIONS_FLAG

classPtr->cropInputNeedRegionsFlag indicates whether the inNeeds and inBufs parameters to computeDataProc should be affected by the corresponding input have regions. If cropInputNeedRegionsFlag is TRUE, then the inNeeds (and thus the area of each of the inBufs) will be intersected with the input have regions. See computeDataProc for details.

The default is FALSE. The advantage of this is that the input buffer sizes will be predictable, making it a little easier to write non-local transforms. The disadvantage is that the buffers may use more storage than necessary.

AUTO_COMPUTE_INPUTS_FLAG

If classPtr->autoComputeInputsFlag is TRUE, then input buffers are automatically allocated, computed, and passed to computeDataProc via the inBufs parameter. Otherwise, input buffers are not allocated or computed. See computeDataProc for details.

The default is TRUE. Set this to FALSE if you want to manually compute the input signal(s) data in computeDataProc. For example, you might want to compute input data directly into the output buffer and operate on it there.

SAMPLE RATE

The sampleRate parameter appears in computeHaveRegionProc, computeNeedRegionProc, and computeDataProc. It deserves a special explanation that I haven't been able to write yet. For now, see RIVL/doc/examples/node.c for an example of how sampleRate is used.