Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / webgl / src / sdk / tests / conformance / resources / glsl-constructor-tests-generator.js
1 /*
2 ** Copyright (c) 2014 The Khronos Group Inc.
3 **
4 ** Permission is hereby granted, free of charge, to any person obtaining a
5 ** copy of this software and/or associated documentation files (the
6 ** "Materials"), to deal in the Materials without restriction, including
7 ** without limitation the rights to use, copy, modify, merge, publish,
8 ** distribute, sublicense, and/or sell copies of the Materials, and to
9 ** permit persons to whom the Materials are furnished to do so, subject to
10 ** the following conditions:
11 **
12 ** The above copyright notice and this permission notice shall be included
13 ** in all copies or substantial portions of the Materials.
14 **
15 ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
22 */
23
24
25 var GLSLConstructorTestsGenerator = (function() {
26   
27 var wtu = WebGLTestUtils;
28
29 // Shader code templates 
30 var constructorVertexTemplate = [
31   "attribute vec4 vPosition;",
32
33   "precision mediump int;",
34   "precision mediump float;",
35
36   // Colors used to signal correctness of component values comparison  
37   "const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);",
38   "const vec4 red   = vec4(1.0, 0.0, 0.0, 1.0);",
39
40   // Error bound used in comparison of floating point values 
41   "$(errorBound)", 
42
43   "varying vec4 vColor;",
44   
45   "void main() {",
46   "  $(argsList)",
47   
48   "  $(type) v = $(type)($(argsConstr));",
49   
50   "  if ($(checkCompVals))",
51   "    vColor = green;",
52   "  else",
53   "    vColor = red;",
54   
55   "  gl_Position = vPosition;",
56   "}"
57 ].join("\n");
58
59
60 var passThroughColorFragmentShader = [
61   "precision mediump float;",
62   
63   "varying vec4 vColor;",
64   
65   "void main() {",
66   "    gl_FragColor = vColor;",
67   "}"
68 ].join('\n');
69
70
71 var constructorFragmentTemplate = [
72   "precision mediump int;",
73   "precision mediump float;",
74
75   // Colors used to signal correctness of component values comparison  
76   "const vec4 green = vec4(0.0, 1.0, 0.0, 1.0); ",
77   "const vec4 red   = vec4(1.0, 0.0, 0.0, 1.0); ",
78   
79   // Error bound used in comparison of floating point values
80   "$(errorBound)", 
81
82   "void main() {",
83   "  $(argsList)",
84     
85   "  $(type) v = $(type)($(argsConstr));",
86   
87   "  if ($(checkCompVals))",
88   "    gl_FragColor = green;",
89   "  else",
90   "    gl_FragColor = red;",
91   "}"
92 ].join("\n");
93
94
95 // Coding of the different argument types  
96 // s  : scalar
97 // v2 : vec2
98 // v3 : vec3
99 // v4 : vec4
100 // m2 : mat2
101 // m3 : mat3 
102 // m4 : mat4
103
104 // Returns the dimensions of the type
105 // Count of columns, count of rows  
106 function getTypeCodeDimensions(typeCode) {
107   switch (typeCode) {
108     case "s":  return [1, 1];
109     case "v2": return [1, 2];
110     case "v3": return [1, 3];
111     case "v4": return [1, 4];
112     case "m2": return [2, 2];
113     case "m3": return [3, 3];
114     case "m4": return [4, 4];
115     
116     default:
117       wtu.error("GLSLConstructorTestsGenerator.getTypeCodeDimensions(), unknown type code");        
118       debugger;
119   }    
120 };
121
122
123 // Returns the component count for the type code
124 function getTypeCodeComponentCount(typeCode) {
125   var dim = getTypeCodeDimensions(typeCode);
126   
127   return dim[0] * dim[1];
128 }
129
130
131 // Returns glsl name of type code
132 function getGLSLBaseTypeName(typeCode) {
133   switch(typeCode) {
134     case "s":  return "";
135     case "v2": return "vec2";
136     case "v3": return "vec3";
137     case "v4": return "vec4";
138     case "m2": return "mat2";
139     case "m3": return "mat3";
140     case "m4": return "mat4";
141
142     default:
143       wtu.error("GLSLConstructorTestsGenerator.getGLSLBaseTypeName(), unknown type code");        
144       debugger;
145   }
146 }
147
148
149 // Returns the scalar glsl type name related to the structured type
150 function getGLSLScalarType(targetType) {
151   switch(targetType[0]) {
152     case 'i': return "int";
153     case 'b': return "bool";
154     
155     case 'v':
156     case 'm':
157       return "float";
158         
159     default:
160       wtu.error("GLSLConstructorTestsGenerator.getGLSLScalarType(), unknown target type");        
161       debugger;
162   }
163 }
164
165
166 // Returns the scalar prefix for the associated scalar type
167 function getGLSLScalarPrefix(targetType) {
168   switch(targetType[0]) {
169     case 'i': 
170     case 'b': 
171       return targetType[0];
172             
173     case 'v':
174     case 'm':
175       return '';
176             
177     default:
178       wtu.error("GLSLConstructorTestsGenerator.getGLSLScalarPrefix(), unknown target type");        
179       debugger;
180   }
181 }
182
183
184 // Returns the type for a specified target type and argument type code
185 function getGLSLArgumentType(typeCode, targetType) {
186   var baseType = getGLSLBaseTypeName(typeCode);
187   if (baseType !== "") {
188     if (typeCode[0] === "v") {
189       // Vectors come in different flavours
190       return getGLSLScalarPrefix(targetType) + baseType;
191     }
192     else
193       return baseType;
194   }
195   else 
196     return getGLSLScalarType(targetType);
197 }
198
199
200 // Returns the glsl type of the argument components  
201 function getGLSLArgumentComponentType(argTypeCode, targetType) {
202   var scalarType;
203
204   if (argTypeCode[0] === "m") {
205     // Matrices are always floats    
206     scalarType = "float";
207   }
208   else 
209     scalarType = getGLSLScalarType(targetType);
210   
211   return scalarType;
212 }
213
214
215 function getGLSLColumnSize(targetType) {
216   colSize = parseInt(targetType.slice(-1));
217
218   if (!isNaN(colSize))
219     return colSize;
220     
221   wtu.error("GLSLConstructorTestsGenerator.getGLSLColumnSize(), invalid target type");        
222     debugger;
223 }
224   
225   
226 // Returns correct string representation of scalar value 
227 function getScalarTypeValStr(val, scalarType) {
228   if (val == null)
229     debugger;
230     
231   switch (scalarType) {
232     case "float": return val.toFixed(1);
233     case "int":   return val;
234     case "bool":  return (val === 0) ? "false" : "true";
235        
236     default:
237       wtu.error("GLSLConstructorTestsGenerator.getScalarTypeValStr(), unknown scalar type");        
238       debugger;
239   }
240 }
241
242
243 // Returns true if the glsl type name is a matrix   
244 function isGLSLTypeMatrix(type) {
245   return (type.indexOf("mat") !== -1);
246 }
247
248
249 // Returns true if the glsl type name is a vector   
250 function isGLSLTypeVector(type) {
251   return (type.indexOf("vec") !== -1);
252 }
253
254  
255 // Returns the count of components 
256 function getGLSLTypeComponentCount(type) {
257   var colSize = getGLSLColumnSize(type);
258       
259   if (isGLSLTypeMatrix(type))
260     return colSize * colSize;
261   else
262     return colSize;    
263 }
264
265
266 // Returns the constructor expression with the components set to a sequence of scalar values
267 // Like vec3(1.0, 2.0, 3.0)
268 function getComponentSequenceConstructorExpression(typeCode, firstCompValue, targetType) {
269   var scalarType = getGLSLArgumentComponentType(typeCode, targetType);
270     
271   if (typeCode === "s") {
272     // Scalar
273     return getScalarTypeValStr(firstCompValue, scalarType) + ";";
274   } 
275   else {
276     // Structured typeargTypeCode[0] === "m"
277     compCount = getTypeCodeComponentCount(typeCode);
278     var constrExpParts = new Array(compCount);
279     for (var aa = 0; aa < compCount; ++aa) 
280         constrExpParts[aa] = getScalarTypeValStr(firstCompValue + aa, scalarType);  
281     
282     return getGLSLArgumentType(typeCode, targetType) + "(" + constrExpParts.join(", ") + ");"; 
283   }
284 }
285
286
287 // Returns the expression to select a component of the structured type
288 function getComponentSelectorExpStr(targetType, compIx) {
289   if (isGLSLTypeMatrix(targetType)) {
290     var colRowIx = getColRowIndexFromLinearIndex(compIx, getGLSLColumnSize(targetType));
291     return "v[" + colRowIx.colIx + "][" + colRowIx.rowIx + "]";
292   }
293   else 
294     return "v[" + compIx + "]";
295 }
296     
297     
298 // Returns expression which validates the components set by the constructor expression
299 function getComponentValidationExpression(refCompVals, targetType) {
300   // Early out for invalid arguments
301   if (refCompVals.length === 0) 
302     return "false";
303     
304   var scalarType = getGLSLScalarType(targetType);
305   var checkComponentValueParts = new Array(refCompVals.length);
306   for (var cc = 0; cc < refCompVals.length; ++cc) {
307     var val_str = getScalarTypeValStr(refCompVals[cc], scalarType);
308     var comp_sel_exp = getComponentSelectorExpStr(targetType, cc);
309     if (scalarType === "float") {
310       // Comparison of floating point values with error bound 
311       checkComponentValueParts[cc] = "abs(" + comp_sel_exp + " - " + val_str + ") <= errorBound";
312     }
313     else {
314       // Simple comparison to expected value
315       checkComponentValueParts[cc] = comp_sel_exp + " == " + val_str;
316     }
317   }       
318   
319   return checkComponentValueParts.join(" && ");
320 }
321
322
323 // Returns substitution parts to turn the shader template into testable shader code 
324 function getTestShaderParts(targetType, argExp, firstCompValue) {
325   // glsl code of declarations of arguments 
326   var argsListParts = new Array(argExp.length);
327
328   // glsl code of constructor expression
329   var argsConstrParts = new Array(argExp.length);
330   
331   // glsl type expression
332   var typeExpParts = new Array(argExp.length);
333   for (var aa = 0; aa < argExp.length; ++aa) {
334     var typeCode     = argExp[aa];
335     var argCompCount = getTypeCodeComponentCount(typeCode);
336     var argName      = "a" + aa; 
337     var argType      = getGLSLArgumentType(typeCode, targetType);
338     var argConstrExp = argType + " " + argName + " = " + getComponentSequenceConstructorExpression(typeCode, firstCompValue, targetType);
339     
340     // Add construction of one argument
341     // Indent if not first argument
342     argsListParts[aa] = ((aa > 0) ? "  " : "") + argConstrExp;
343       
344     // Add argument name to target type argument list
345     argsConstrParts[aa] = argName;
346     
347     // Add type name to type expression  
348     typeExpParts[aa] = argType;
349
350     // Increment argument component value so all argument component arguments have a unique value
351     firstCompValue += argCompCount;
352   }
353   
354   return {
355     argsList:   argsListParts.join("\n") + "\n",
356     argsConstr: argsConstrParts.join(", "),
357     typeExp:    targetType + "(" + typeExpParts.join(", ") + ")"
358   };
359 }
360
361
362 // Utility functions to manipulate the array of reference values
363
364 // Returns array filled with identical values
365 function getArrayWithIdenticalValues(size, val) {
366   var matArray = new Array(size);
367   for (var aa = 0; aa < size; ++aa)
368     matArray[aa] = val;
369   
370   return matArray;
371 }
372
373
374 // Returns array filled with increasing values from a specified start value
375 function getArrayWithIncreasingValues(size, start) {
376   var matArray = new Array(size);
377   for (var aa = 0; aa < size; ++aa)
378     matArray[aa] = start + aa;
379   
380   return matArray;
381 }
382
383
384 // Utility functions to manipulate the array of reference values if the target type is a matrix
385
386 // Returns an array which is the column order layout of a square matrix where the diagonal is set to a specified value 
387 function matCompArraySetDiagonal(matArray, diagVal) {
388   // The entries for the diagonal start at array index 0 and increase 
389   // by column size + 1
390   var colSize = Math.round(Math.sqrt(matArray.length));
391   var dIx = 0;
392   do {
393     matArray[dIx] = diagVal;
394     dIx += (colSize + 1);
395   }
396   while (dIx < colSize * colSize);
397   
398   return matArray;
399 }
400
401
402 // Returns an array which contains the values of an identity matrix read out in column order 
403 function matCompArrayCreateDiagonalMatrix(colSize, diagVal) {
404   var size = colSize * colSize;
405   var matArray = new Array(size);
406   for (var aa = 0; aa < size; ++aa)
407     matArray[aa] = 0;
408   
409   return matCompArraySetDiagonal(matArray, diagVal);  
410 }
411
412
413 // Returns the column and row index from the linear index if the components of the matrix are stored in column order in an array
414 // in a one dimensional array in column order 
415 function getColRowIndexFromLinearIndex(linIx, colSize) {
416   return { 
417     colIx: Math.floor(linIx / colSize),
418     rowIx: linIx % colSize
419   };
420 }     
421   
422   
423 // Returns the linear index for matrix column and row index for a specified matrix size  
424 function getLinearIndexFromColRowIndex(rowColIx, colSize) {
425   return rowColIx.colIx * colSize + rowColIx.rowIx;
426 }
427   
428   
429 // Returns a matrix set from another matrix  
430 function matCompArraySetMatrixFromMatrix(dstColSize, srcMatArray) {
431   // Overwrite components from destination with the source component values at the same col, row coordinates
432   var dstMatArray = matCompArrayCreateDiagonalMatrix(dstColSize, 1);
433   
434   var srcColSize = Math.round(Math.sqrt(srcMatArray.length));
435       
436   for (var c_ix = 0; c_ix < srcMatArray.length; ++c_ix) {
437     var srcMatIx = getColRowIndexFromLinearIndex(c_ix, srcColSize);
438     if (srcMatIx.colIx < dstColSize && srcMatIx.rowIx < dstColSize) { 
439       // Source matrix coordinates are valid destination matrix coordinates
440       dstMatArray[getLinearIndexFromColRowIndex(srcMatIx, dstColSize)] = srcMatArray[c_ix];
441     } 
442   }      
443      
444   return dstMatArray;    
445 }
446
447   
448 // Returns the glsl code to verify if the components are set correctly
449 // and the message to display for the test
450 function getConstructorExpressionInfo(targetType, argExp, firstCompValue) {
451   var argCompCountsSum = 0;
452   var argCompCounts = new Array(argExp.length);
453   for (var aa = 0; aa < argExp.length; ++aa) {
454     argCompCounts[aa] = getTypeCodeComponentCount(argExp[aa]);
455     argCompCountsSum += argCompCounts[aa]; 
456   }
457   
458   var targetCompCount = getGLSLTypeComponentCount(targetType); 
459
460   var refCompVals;
461   var testMsg;
462   var valid;  
463   
464   if (argCompCountsSum === 0) {
465     // A constructor needs at least one argument
466     refCompVals = [];
467     testMsg     = "invalid (no arguments)";
468     valid       = false;
469   }
470   else {
471     if (isGLSLTypeVector(targetType)) {  
472       if (argCompCountsSum === 1) {
473         // One scalar argument
474         // Vector constructor with one scalar argument set all components to the same value
475         refCompVals = getArrayWithIdenticalValues(targetCompCount, firstCompValue);
476         testMsg     = "valid (all components set to the same value)";
477         valid       = true;
478       }
479       else {
480         // Not one scalar argument
481         if (argCompCountsSum < targetCompCount) {
482           // Not all components set
483           refCompVals = [];
484           testMsg     = "invalid (not enough arguments)";
485           valid       = false;
486         }
487         else {
488           // argCompCountsSum >= targetCompCount
489           // All components set
490           var lastArgFirstCompIx = argCompCountsSum - argCompCounts[argCompCounts.length - 1];
491           
492           if (lastArgFirstCompIx < targetCompCount) {
493             // First component of last argument is used
494             refCompVals = getArrayWithIncreasingValues(targetCompCount, firstCompValue);
495             testMsg     = "valid";
496             valid       = true;
497           }
498           else { 
499             // First component of last argument is not used
500             refCompVals = [];
501             testMsg     = "invalid (unused argument)";
502             valid       = false;
503           }      
504         }
505       }
506     }    
507     else {
508       // Matrix target type
509       if (argCompCountsSum === 1) {
510         // One scalar argument
511         // Matrix constructors with one scalar set all components on the diagonal to the same value
512         // All other components are set to zero 
513         refCompVals = matCompArrayCreateDiagonalMatrix(Math.round(Math.sqrt(targetCompCount)), firstCompValue);
514         testMsg     = "valid (diagonal components set to the same value, off-diagonal components set to zero)";
515         valid       = true;    
516       }
517       else {
518         // Not one scalar argument
519         if (argExp.length === 1 && argExp[0][0] === "m") {
520           // One single matrix argument
521           var dstColSize = getGLSLColumnSize(targetType);
522           refCompVals = matCompArraySetMatrixFromMatrix(dstColSize, getArrayWithIncreasingValues(getTypeCodeComponentCount(argExp[0]), firstCompValue)); 
523           testMsg     = "valid, components at corresponding col, row indices are set from argument, other components are set from identity matrix";
524           valid       = true;
525         }
526         else {
527           // More than one argument or one argument not of type matrix
528           // Can be treated in the same manner
529           // Arguments can not be of type matrix
530           var matFound = false;
531           for (var aa = 0; aa < argExp.length; ++aa) 
532             if (argExp[aa][0] === "m")
533               matFound = true;
534           
535           if (matFound) {
536             refCompVals = [];
537             testMsg     = "invalid, argument list greater than one contains matrix type";
538             valid       = false;
539           }
540           else {
541             if (argCompCountsSum < targetCompCount) {
542               refCompVals = [];
543               testMsg     = "invalid (not enough arguments)";
544               valid       = false;
545             }
546             else {
547               // argCompCountsSum >= targetCompCount
548               // All components set
549               var lastArgFirstCompIx = argCompCountsSum - argCompCounts[argCompCounts.length - 1];
550               
551               if (lastArgFirstCompIx < targetCompCount) {
552                 // First component of last argument is used
553                 refCompVals = getArrayWithIncreasingValues(targetCompCount, firstCompValue);
554                 testMsg     = "valid";
555                 valid       = true;
556               }
557               else { 
558                 // First component of last argument is not used
559                 refCompVals = [];
560                 testMsg     = "invalid (unused argument)";
561                 valid       = false;
562               }      
563             }
564           }
565         }
566       }
567     }
568   }
569     
570   // Check if no case is missed 
571   if (testMsg == null || valid == null) {
572     wtu.error("GLSLConstructorTestsGenerator.getConstructorExpressionInfo(), info not set");        
573     debugger;
574   }
575   
576   return {
577     refCompVals: refCompVals,
578     testMsg:     testMsg,
579     valid:       valid
580   };
581 }
582
583
584 // Returns a vertex shader testcase and a fragment shader testcase
585 function getVertexAndFragmentShaderTestCase(targetType, argExp) {
586   var firstCompValue = 0;
587   if (isGLSLTypeMatrix(targetType)) {
588     // Use value different from 0 and 1
589     // 0 and 1 are values used by matrix constructed from a matrix or a single scalar
590     firstCompValue = 2;
591   }
592    
593   var argCode = getTestShaderParts          (targetType, argExp, firstCompValue);
594   var expInfo = getConstructorExpressionInfo(targetType, argExp, firstCompValue);
595     
596   var substitutions = {
597     type:          targetType, 
598     errorBound:    (getGLSLScalarType(targetType) === "float") ? "const float errorBound = 1.0E-5;" : "",
599     argsList:      argCode.argsList,
600     argsConstr:    argCode.argsConstr, 
601     checkCompVals: getComponentValidationExpression(expInfo.refCompVals, targetType)
602   };
603     
604   return [ {
605       // Test constructor argument list in vertex shader
606       vShaderSource:  wtu.replaceParams(constructorVertexTemplate, substitutions),
607       vShaderSuccess: expInfo.valid,
608       fShaderSource:  passThroughColorFragmentShader,
609       fShaderSuccess: true,
610       linkSuccess:    expInfo.valid,
611       passMsg:        "Vertex shader : " + argCode.typeExp + ", " + expInfo.testMsg,
612       render:         expInfo.valid
613     }, {
614       // Test constructor argument list in fragment shader
615       vShaderSource:  GLSLConformanceTester.defaultVertexShader,
616       vShaderSuccess: true,
617       fShaderSource:  wtu.replaceParams(constructorFragmentTemplate, substitutions),
618       fShaderSuccess: expInfo.valid,
619       linkSuccess:    expInfo.valid,
620       passMsg:        "Fragment shader : " + argCode.typeExp + ", " + expInfo.testMsg,
621       render:         expInfo.valid
622     }
623   ];  
624 }
625
626
627 // Incrementing the argument expressions
628 // Utility object which defines the order of incrementing the argument types
629 var typeCodeIncrementer = {
630   s:     { typeCode: "v2", order: 0 },
631   v2:    { typeCode: "v3", order: 1 },
632   v3:    { typeCode: "v4", order: 2 },
633   v4:    { typeCode: "m2", order: 3 },
634   m2:    { typeCode: "m3", order: 4 },
635   m3:    { typeCode: "m4", order: 5 },
636   m4:    { typeCode: "s",  order: 6 },
637   first: "s"
638 }
639
640
641 // Returns the next argument sequence
642 function getNextArgumentSequence(inSeq) {
643   var nextSeq;
644   if (inSeq.length === 0) {
645     // Current argument sequence is empty, add first argument
646     nextSeq = [typeCodeIncrementer.first];
647   }
648   else {
649     nextSeq = new Array(inSeq.length);
650     var overflow = true;
651     for (var aa = 0; aa < inSeq.length; ++aa) {
652       var currArg = inSeq[aa];
653       if (overflow) {
654         // Increment the current argument type
655         var nextArg = typeCodeIncrementer[currArg].typeCode;
656         nextSeq[aa] = nextArg;
657         overflow = (nextArg === typeCodeIncrementer.first);
658       }
659       else {
660         // Copy remainder of sequence
661         nextSeq[aa] = currArg;
662       }
663     }
664         
665     if (overflow) {
666       nextSeq.push(typeCodeIncrementer.first);                        
667     }    
668   }
669      
670   return nextSeq;            
671 }
672  
673
674 // Returns true if two argument expressions are equal
675 function areArgExpEqual(expA, expB) {
676   if (expA.length !== expB.length)
677     return false;
678         
679   for (var aa = 0; aa < expA.length; ++aa) 
680     if (expA[aa] !== expB[aa])
681       return false;
682             
683   return true;
684 }
685
686
687 // Returns true if first argument expression is smaller 
688 // (comes before the second one in iterating order) 
689 // compared to the second argument expression  
690 function isArgExpSmallerOrEqual(argExpA, argExpB) {
691   var aLen = argExpA.length;
692   var bLen = argExpB.length; 
693   if (aLen !== bLen)
694     return (aLen < bLen);
695
696   // Argument type expression lengths are equal
697   for (var aa = aLen - 1; aa >= 0; --aa) {
698     var argA = argExpA[aa];
699     var argB = argExpB[aa];
700        
701     if (argA !== argB) {
702       var aOrder = typeCodeIncrementer[argA].order;
703       var bOrder = typeCodeIncrementer[argB].order;
704       if (aOrder !== bOrder)
705         return (aOrder < bOrder);
706     }
707   }
708   
709   // Argument type expressions are equal          
710   return true;
711 }
712
713
714 // Returns the next argument expression from sequence set 
715 // Returns null if end is reached
716 function getNextArgumentExpression(testExp, testSet) {
717   var testInterval = testSet[testExp.ix];
718     
719   if (areArgExpEqual(testExp.argExp, testInterval[1])) {
720     // End of current interval reached
721     if (testExp.ix === testSet.length - 1) {
722       // End of set reached
723       return null;
724     }
725     else {
726       // Return first argument expression of next interval
727       var nextIx = testExp.ix + 1;
728       return { ix: nextIx, argExp: testSet[nextIx][0] };              
729     }
730   }
731   else {
732     // Return next expression in current interval
733     return { ix: testExp.ix, argExp: getNextArgumentSequence(testExp.argExp) };
734   }
735 }
736
737
738 // Returns an array of the parts in the string separated by commas and with the white space trimmed 
739 function convertCsvToArray(str) {
740   // Checks type codes in input
741   function checkInput(el, ix, arr) {
742     var typeCode = el.trim();
743     if (!(typeCode in typeCodeIncrementer) && typeCode !== "first") {
744       wtu.error("GLSLConstructorTestsGenerator.convertCsvToArray(), unknown type code" + typeCode);        
745       debugger;      
746     }
747
748     arr[ix] = typeCode;    
749   }  
750   
751   var spArr = str.split(",");
752   
753   // Convert empty string to empty array
754   if (spArr.length === 1 && spArr[0].trim() === "")
755     spArr = [];
756     
757   spArr.forEach(checkInput);
758   
759   return spArr;
760 }
761
762
763 // Processes the set of specified test sequences
764 function processInputs(testSequences) {
765   var testSet = new Array(testSequences.length);
766   for (var tt = 0; tt < testSequences.length; ++tt) {
767     var interval = testSequences[tt];
768     var bounds = interval.split("-");
769     var begin = convertCsvToArray(bounds[0]);
770     var end   = convertCsvToArray(bounds[bounds.length - 1]);
771
772     // Check if interval is valid
773     if (!isArgExpSmallerOrEqual(begin, end)) {
774       wtu.error("GLSLConstructorTestsGenerator.processInputs(), interval not valid");        
775       debugger;      
776     }
777     
778     testSet[tt] = [ begin, end ];    
779   }
780   
781   return testSet;
782 }
783
784
785 /**
786  * Returns list of test cases for vector types
787  * All combinations of arguments up to one unused argument of one component are tested
788  * @param {targetType} Name of target type to test the constructor expressions on 
789  * @param {testSet}    Set of intervals of argument sequences to test
790  */
791 function getConstructorTests(targetType, testSequences) {
792   // List of tests to return
793   var testInfos = [];
794
795   // List of argument types  
796   var testSet = processInputs(testSequences);
797   var testExp = { ix: 0, argExp: testSet[0][0] };
798   
799   do {
800     // Add one vertex shader test case and one fragment shader test case 
801     testInfos = testInfos.concat(getVertexAndFragmentShaderTestCase(targetType, testExp.argExp));
802      
803     // Generate next argument expression
804     testExp = getNextArgumentExpression(testExp, testSet);
805   }
806   while (testExp != null);
807
808   return testInfos;
809 }
810   
811
812 // Returns default test argument expression set
813 // For details on input format : see bottom of file
814 function getDefaultTestSet(targetType) {
815   switch(targetType) {
816     case "vec2":
817     case "ivec2":
818     case "bvec2":
819       return [
820         // No arguments and all single argument expressions
821         " - m4", 
822         
823         // All two argument expressions with a scalar as second argument
824         "s, s - m4, s",
825         
826         // All two arguments expressions with a scalar as first argument
827         "s, v2", "s, v3", "s, v4", "s, m2", "s, m3", "s, m4",
828         
829         // Three argument expression
830         "s, s, s"
831       ];
832
833     case "vec3":
834     case "ivec3":
835     case "bvec3":
836       return [
837         // No arguments and all single argument expressions
838         " - m4", 
839         
840         // All two argument expressions with a scalar as second argument
841         "s, s - m4, s",
842         
843         // All two argument expressions with a scalar as first argument
844         "s, v2", "s, v3", "s, v4", "s, m2", "s, m3", "s, m4",
845         
846         // All three argument expressions with two scalars as second and third argument
847         "s, s, s - m4, s, s",
848         
849         // All three argument expressions with two scalars as first and second argument 
850         "s, s, v2", "s, s, v3", "s, s, v4", "s, s, m2", "s, s, m3", "s, s, m4",
851         
852         // Four argument expression
853         "s, s, s, s"
854       ];
855
856     case "vec4":
857     case "ivec4":
858     case "bvec4":
859     case "mat2":
860       return [
861         // No arguments and all single argument expressions
862         " - m4", 
863         
864         // All two argument expressions with a scalar as second argument
865         "s, s - m4, s",
866         
867         // All two argument expressions with a scalar as first argument
868         "s, v2", "s, v3", "s, v4", "s, m2", "s, m3", "s, m4",
869         
870         // All three argument expressions with two scalars as second and third argument
871         "s, s, s - m4, s, s",
872         
873         // All three argument expressions with two scalars as first and second argument 
874         "s, s, v2", "s, s, v3", "s, s, v4", "s, s, m2", "s, s, m3", "s, s, m4",
875
876         // All four argument expressions with three scalars as second, third and fourth argument
877         "s, s, s, s - m4, s, s, s",
878         
879         // All four argument expressions with three scalars as first, second and third argument 
880         "s, s, s, v2", "s, s, s, v3", "s, s, s, v4", "s, s, s, m2", "s, s, s, m3", "s, s, s, m4",
881         
882         // Five argument expression
883         "s, s, s, s, s"
884       ];
885
886     case "mat3":
887     case "mat4":
888       return [
889         // No arguments and all single argument expressions
890         " - m4", 
891         
892         // All two argument expressions with a scalar as second argument
893         "s, s - m4, s",
894         
895         // All two argument expressions with a scalar as first argument
896         "s, v2", "s, v3", "s, v4", "s, m2", "s, m3", "s, m4",
897
898         // Several argument sequences
899         "v4, s, v4", "v4, s, v3, v2", "v4, v4, v3, v2", "v4, v4, v4, v4", "v2, v2, v2, v2, v2", "v2, v2, v2, v2, v2, v2, v2, v2",
900         "v3, v3, v3", "v3, v3, v3, s", "v3, v3, v3, v3, v3, s", "v3, v3, v3, v3, v3, s, s",         
901       ];
902   }
903 }
904
905
906 // Return publics
907 return {
908   getConstructorTests: getConstructorTests,
909   getDefaultTestSet:   getDefaultTestSet
910 };
911
912 }());
913
914
915 // Input is an array of intervals of argument types
916 // The generated test argument sequences are from (including) the lower interval boundary
917 // until (including) the upper boundary
918 // Coding and order of the different argument types : 
919 // s  : scalar
920 // v2 : vec2
921 // v3 : vec3
922 // v4 : vec4
923 // m2 : mat2
924 // m3 : mat3 
925 // m4 : mat4
926
927 // One interval is put in one string
928 // Low and high bound are separated by a dash.
929 // If there is no dash it is regarded as an interval of one expression
930 // The individual argument codes are separated by commas  
931 // The individual arguments are incremented from left to right
932 // The left most argument is the one which is incremented first
933 // Once the left most arguments wraps the second argument is increased 
934 // Examples :
935 // "s - m4"        : All single arguments from scalar up to (including) mat4
936 // "m2, s - m4, s" : All two argument expressions with a matrix argument as first argument and a scalar as second argument 
937 // " - m4, m4"     : The empty argument, all one arguments and all two argument expressions
938 // "m2, s, v3, m4" : One 4 argument expression : mat2, scalar, vec3, mat4