Home | History | Annotate | Download | only in MachineIndependent
      1 //
      2 //Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
      3 //All rights reserved.
      4 //
      5 //Redistribution and use in source and binary forms, with or without
      6 //modification, are permitted provided that the following conditions
      7 //are met:
      8 //
      9 //    Redistributions of source code must retain the above copyright
     10 //    notice, this list of conditions and the following disclaimer.
     11 //
     12 //    Redistributions in binary form must reproduce the above
     13 //    copyright notice, this list of conditions and the following
     14 //    disclaimer in the documentation and/or other materials provided
     15 //    with the distribution.
     16 //
     17 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
     18 //    contributors may be used to endorse or promote products derived
     19 //    from this software without specific prior written permission.
     20 //
     21 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     22 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     23 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     24 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     25 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     26 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     27 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     28 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     29 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     31 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     32 //POSSIBILITY OF SUCH DAMAGE.
     33 //
     34 
     35 //
     36 // Travarse a tree of constants to create a single folded constant.
     37 // It should only be used when the whole tree is known to be constant.
     38 //
     39 
     40 #include "ParseHelper.h"
     41 
     42 namespace glslang {
     43 
     44 class TConstTraverser : public TIntermTraverser {
     45 public:
     46     TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t)
     47       : unionArray(cUnion), type(t),
     48         constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false),
     49         matrixCols(0), matrixRows(0) {  index = 0; tOp = EOpNull; }
     50 
     51     virtual void visitConstantUnion(TIntermConstantUnion* node);
     52     virtual bool visitAggregate(TVisit, TIntermAggregate* node);
     53 
     54     int index;
     55     TConstUnionArray unionArray;
     56     TOperator tOp;
     57     const TType& type;
     58     TOperator constructorType;
     59     bool singleConstantParam;
     60     bool error;
     61     int size; // size of the constructor ( 4 for vec4)
     62     bool isMatrix;
     63     int matrixCols;
     64     int matrixRows;
     65 
     66 protected:
     67     TConstTraverser(TConstTraverser&);
     68     TConstTraverser& operator=(TConstTraverser&);
     69 };
     70 
     71 bool TConstTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
     72 {
     73     if (! node->isConstructor() && node->getOp() != EOpComma) {
     74         error = true;
     75 
     76         return false;
     77     }
     78 
     79     if (node->getSequence().size() == 0) {
     80         error = true;
     81 
     82         return false;
     83     }
     84 
     85     bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
     86     if (flag) {
     87         singleConstantParam = true;
     88         constructorType = node->getOp();
     89         size = node->getType().computeNumComponents();
     90 
     91         if (node->getType().isMatrix()) {
     92             isMatrix = true;
     93             matrixCols = node->getType().getMatrixCols();
     94             matrixRows = node->getType().getMatrixRows();
     95         }
     96     }
     97 
     98     for (TIntermSequence::iterator p = node->getSequence().begin();
     99                                    p != node->getSequence().end(); p++) {
    100 
    101         if (node->getOp() == EOpComma)
    102             index = 0;
    103 
    104         (*p)->traverse(this);
    105     }
    106     if (flag)
    107     {
    108         singleConstantParam = false;
    109         constructorType = EOpNull;
    110         size = 0;
    111         isMatrix = false;
    112         matrixCols = 0;
    113         matrixRows = 0;
    114     }
    115 
    116     return false;
    117 }
    118 
    119 void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
    120 {
    121     TConstUnionArray leftUnionArray(unionArray);
    122     int instanceSize = type.computeNumComponents();
    123 
    124     if (index >= instanceSize)
    125         return;
    126 
    127     if (! singleConstantParam) {
    128         int rightUnionSize = node->getType().computeNumComponents();
    129 
    130         const TConstUnionArray& rightUnionArray = node->getConstArray();
    131         for (int i = 0; i < rightUnionSize; i++) {
    132             if (index >= instanceSize)
    133                 return;
    134             leftUnionArray[index] = rightUnionArray[i];
    135 
    136             index++;
    137         }
    138     } else {
    139         int endIndex = index + size;
    140         const TConstUnionArray& rightUnionArray = node->getConstArray();
    141         if (! isMatrix) {
    142             int count = 0;
    143             int nodeComps = node->getType().computeNumComponents();
    144             for (int i = index; i < endIndex; i++) {
    145                 if (i >= instanceSize)
    146                     return;
    147 
    148                 leftUnionArray[i] = rightUnionArray[count];
    149 
    150                 (index)++;
    151 
    152                 if (nodeComps > 1)
    153                     count++;
    154             }
    155         } else {
    156             // constructing a matrix, but from what?
    157             if (node->isMatrix()) {
    158                 // Matrix from a matrix; this has the outer matrix, node is the argument matrix.
    159                 // Traverse the outer, potentially bigger matrix, fill in missing pieces with the
    160                 // identity matrix.
    161                 for (int c = 0; c < matrixCols; ++c) {
    162                     for (int r = 0; r < matrixRows; ++r) {
    163                         int targetOffset = index + c * matrixRows + r;
    164                         if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) {
    165                             int srcOffset = c * node->getType().getMatrixRows() + r;
    166                             leftUnionArray[targetOffset] = rightUnionArray[srcOffset];
    167                         } else if (r == c)
    168                             leftUnionArray[targetOffset].setDConst(1.0);
    169                         else
    170                             leftUnionArray[targetOffset].setDConst(0.0);
    171                     }
    172                 }
    173             } else {
    174                 // matrix from vector
    175                 int count = 0;
    176                 const int startIndex = index;
    177                 int nodeComps = node->getType().computeNumComponents();
    178                 for (int i = startIndex; i < endIndex; i++) {
    179                     if (i >= instanceSize)
    180                         return;
    181                     if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
    182                         leftUnionArray[i] = rightUnionArray[count];
    183                     else
    184                         leftUnionArray[i].setDConst(0.0);
    185 
    186                     index++;
    187 
    188                     if (nodeComps > 1)
    189                         count++;
    190                 }
    191             }
    192         }
    193     }
    194 }
    195 
    196 bool TIntermediate::parseConstTree(TIntermNode* root, TConstUnionArray unionArray, TOperator constructorType, const TType& t, bool singleConstantParam)
    197 {
    198     if (root == 0)
    199         return false;
    200 
    201     TConstTraverser it(unionArray, singleConstantParam, constructorType, t);
    202 
    203     root->traverse(&it);
    204     if (it.error)
    205         return true;
    206     else
    207         return false;
    208 }
    209 
    210 } // end namespace glslang
    211