00001 /* 00002 * PROPRIETARY INFORMATION. This software is proprietary to 00003 * Side Effects Software Inc., and is not to be reproduced, 00004 * transmitted, or disclosed in any way without written permission. 00005 * 00006 * Produced by: 00007 * Side Effects Software Inc 00008 * 477 Richmond Street West 00009 * Toronto, Ontario 00010 * Canada M5V 3E7 00011 * 416-504-9876 00012 * 00013 * NAME: VEX_VexOp.h ( VEX Library, C++) 00014 * 00015 * COMMENTS: External VEX function definition 00016 * 00017 * The signature of a VEX OP function determines the parameters the function 00018 * expects. The signature is composed as follows: 00019 * name@parms 00020 * where name is the user function name and the parms are the single character 00021 * representations of the parameters expected. The single character mnemonics 00022 * are: 00023 * F = float 00024 * I = integer 00025 * S = string 00026 * V = vector 00027 * P = vector4 (originally "point") 00028 * 3 = matrix3 00029 * 4 = matrix4 00030 * 00031 * Arrays of primitive types use the single character mnemonic for that 00032 * type preceeded by the open square bracket ([) character. The array 00033 * types are then represented as: 00034 * [F = float array 00035 * [I = integer array 00036 * [S = string array 00037 * [V = vector array 00038 * [P = vector4 array 00039 * [3 = matrix3 array 00040 * [4 = matrix4 array 00041 * 00042 * If a parameter is written to by the VexOp function, the parameter mnemonic 00043 * should be preceded by an ampersand (&) or an asterix (*). The ampersand is 00044 * used it the value of the variable is not read by the function, while the 00045 * asterix is used if the variable is read and then modified. The signature 00046 * specification is very important if the compiler is to work correctly. 00047 * 00048 * The compiler is "smart" in that if only one argument is written to (and not 00049 * read from), that argument will be flagged as the return code for the 00050 * function. 00051 * 00052 * Examples: 00053 * Signature: test@&IF 00054 * Decoded: int test(float) 00055 * 00056 * Signature: test@*IF 00057 * Decoded: void test(int &, float) 00058 * Details: The integer parameter must be set since this function 00059 * reads the argument before modifying it. 00060 * 00061 * Signature: test@S&VFF 00062 * Decoded: vector test(string; float, float) 00063 * 00064 * At this time VEXOps do not support variadic functions (i.e. var-args 00065 * functions like printf()). 00066 * 00067 */ 00068 00069 #ifndef __VEX_VexOp__ 00070 #define __VEX_VexOp__ 00071 00072 #include "VEX_API.h" 00073 #include "VEX_VexTypes.h" 00074 00075 /// VEX operator initialization callback. When called, it should allocated 00076 /// and initialize custom state data. 00077 typedef void *(*VEX_VexOpInit)(); 00078 /// VEX operator evaluation callback. When called, the data returned by the 00079 /// VEX_VexOpInit function will be passed as the "data" argument. 00080 typedef void (*VEX_VexOpCallback)(int argc, void *argv[], void *data); 00081 /// VEX operator cleanup callback. When called, it should deallocate the data. 00082 typedef void (*VEX_VexOpCleanup)(void *data); 00083 /// VEX operator completed callback. Called when a shader that evaluated a 00084 /// custom operator completes. 00085 typedef void (*VEX_VexOpCompleted)(void *data); 00086 00087 // 00088 // It's possible to give hints to the compiler as to what optimizations may be 00089 // performed on the function. The different levels of optimizations are: 00090 // 0 = No optimizations may be performed on the custom function. 00091 // 1 = If the result of the function is unused, the function can 00092 // be eliminated. 00093 // 2 = If all parameters to the function are constant, then the result may 00094 // be pre-computed and cached. 00095 // The only time you would want to turn off optimization is to guarantee that 00096 // your custom function is evaluated in all cases (i.e. something like printf). 00097 // Typically, functions used in computation can be optimized by VEX. 00098 // 00099 // Turning off optimization may result in an overall performance hit. 00100 // 00101 00102 /// @def VEX_OPTIMIZE_0 00103 /// Perform no optimization on the VEX function 00104 /// @warning this may impact performance severely. 00105 /// @def VEX_OPTIMIZE_1 00106 /// If the result of the function is unused, the function can be 00107 /// eliminated. 00108 /// @def VEX_OPTIMIZE_2 00109 // If all parameters to the function are constant, then the result may 00110 // be pre-computed and cached. (preferred mode) 00111 #define VEX_OPTIMIZE_0 0 00112 #define VEX_OPTIMIZE_1 1 00113 #define VEX_OPTIMIZE_2 2 00114 00115 // 00116 // When a function modifies only one parameter (without reading from it), the 00117 // compiler will automatically interpret the first argument as a return code 00118 // for the function. However, if the function modifies multiple arguments, the 00119 // compiler assumes that all arguments should be passed by reference. 00120 // Sometimes, it's useful to have the first modified argument treated as a 00121 // return code rather than an actual parameter to the function. This behaviour 00122 // can be forced (if all conditions are met) by passing in a true on the 00123 // "force_return_code" parameter. 00124 // For example, something like the function: 00125 // import@&IS&F 00126 // would decode to 00127 // import(int &success, string, float &result) 00128 // But, with the force_return_code argument set to true, the function would be 00129 // interpreted as: 00130 // int import(string, float &result) 00131 // which is most likely more friendly to the user. 00132 // 00133 00134 /// Use this class to extend VEX by adding custom VEX functions. 00135 class VEX_API VEX_VexOp { 00136 public: 00137 /// Function declaration 00138 /// @param signature @n The function name and parameters expected 00139 /// @param evaluator @n The evaluation callback 00140 /// @param ctx_mask @n Which contexts this function is available in 00141 /// @param init @n Initialization callback (called for every instance) 00142 /// @param cleanup @n Cleanup callback 00143 /// @param optimize_level @n Optimization level 00144 /// @param force_return_code @n 00145 /// For signatures which have multiple write-only variables, this 00146 /// @c bool forces the first write-only variable to be interpreted 00147 /// as a return code. 00148 VEX_VexOp(const char *signature, 00149 VEX_VexOpCallback evaluator, 00150 int ctx_mask=(VEX_ALL_CONTEXT), 00151 VEX_VexOpInit init = 0, 00152 VEX_VexOpCleanup cleanup = 0, 00153 int optimize_level = VEX_OPTIMIZE_2, 00154 bool force_return_code=false); 00155 00156 /// Standard destructor 00157 ~VEX_VexOp(); 00158 00159 /// Set the completed callback, called when all evaluate calls for a 00160 /// given shader invokation are finished. 00161 void setCompleted(VEX_VexOpCompleted cback) 00162 { myCompleted = cback; } 00163 00164 /// Query the signature 00165 const char *getSignature() const { return mySignature; } 00166 /// Query the context mask 00167 int getContextMask() const { return myContextMask; } 00168 /// Query the initialization function 00169 VEX_VexOpInit getInit() const { return myInit; } 00170 /// Query the evaluation function 00171 VEX_VexOpCallback getEvaluator() const { return myEvaluator; } 00172 /// Query the cleanup function 00173 VEX_VexOpCleanup getCleanup() const { return myCleanup; } 00174 /// Query the completed function 00175 VEX_VexOpCompleted getCompleted() const { return myCompleted; } 00176 /// Query the optimization level 00177 int getOptimizer() const { return myOptimizeLevel; } 00178 00179 /// @private: Internal used to query state 00180 unsigned int getFlag(unsigned int f) const { return myFlags&f; } 00181 /// @private: Internal used to store state 00182 void setFlag(unsigned int f) { myFlags |= f; } 00183 /// @private: Internal used to store state 00184 void clearFlag(unsigned int f) { myFlags &= ~f; } 00185 00186 /// When dealing assigning to string arguments, you must "free" the previous 00187 /// string value by calling "stringFree". You must set the resulting string 00188 /// to the return code from "stringAlloc". If you do your own memory 00189 /// management (i.e. calling strdup() or setting strings to constant 00190 /// values), you will most likely crash VEX. 00191 /// For example: 00192 /// @code 00193 /// void 00194 /// vexStrCat(int argc, void *argv[], void *) 00195 /// { 00196 /// // arg[0] = result, arg[1..2] == strings to concat 00197 /// char work_buf[256]; 00198 /// VEX_VexOp::stringFree((char *)argv[0]); 00199 /// strcpy(work_buf, (char *)argv[1]); 00200 /// strcat(work_buf, (char *)argv[2]); 00201 /// argv[0] = VEX_VexOp::stringAlloc(work_buf); 00202 /// } 00203 /// @endcode 00204 static const char *stringAlloc(const char *str); 00205 /// Function to free an allocated string 00206 static void stringFree(const char *str); 00207 00208 /// These functions can be used to query the number of DSO's loaded by VEX 00209 /// and the locations of the shadered objects loaded. 00210 static int getNumVexOps(); 00211 /// Query the Nth function 00212 static const VEX_VexOp *getVexOp(int idx); 00213 /// Get the path to the DSO associated with the VEX plug-in 00214 static const char *getVexOpLocation(int idx); 00215 00216 protected: 00217 // The signature of the function call. This is documented in the header 00218 // above. The constructor will duplicate the string passed in. 00219 char *mySignature; 00220 00221 // Initialization, Evaluation and Cleanup callbacks 00222 VEX_VexOpInit myInit; 00223 VEX_VexOpCallback myEvaluator; 00224 VEX_VexOpCleanup myCleanup; 00225 VEX_VexOpCompleted myCompleted; 00226 00227 // The contexts which this VEXOp is valid for. The mask is a bit-field 00228 // represented by or'ing the context defines above together. 00229 int myContextMask; 00230 int myOptimizeLevel; 00231 unsigned int myFlags; 00232 }; 00233 00234 extern "C" { 00235 /// Function called in DSO to install new functions 00236 SYS_VISIBILITY_EXPORT extern void newVEXOp(void *); 00237 } 00238 00239 #endif 00240
1.5.9