1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
4 ** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the Qt3D module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include "renderstateset_p.h"
42 
43 #include <bitset>
44 
45 #include <Qt3DRender/private/renderstates_p.h>
46 #include <Qt3DRender/private/qrenderstate_p.h>
47 
48 QT_BEGIN_NAMESPACE
49 
50 namespace Qt3DRender {
51 namespace Render {
52 
RenderStateSet()53 RenderStateSet::RenderStateSet()
54     : m_stateMask(0)
55 {
56 }
57 
~RenderStateSet()58 RenderStateSet::~RenderStateSet()
59 {
60 }
61 
62 template<>
addState(const StateVariant & ds)63 void RenderStateSet::addState<StateVariant>(const StateVariant &ds)
64 {
65     m_states.push_back(ds);
66     m_stateMask |= ds.type;
67 }
68 
changeCost(RenderStateSet * previousState)69 int RenderStateSet::changeCost(RenderStateSet *previousState)
70 {
71     if (previousState == this)
72         return 0;
73 
74     int cost = 0;
75 
76     // first, find cost of any resets
77     StateMaskSet invOurState = ~stateMask();
78     StateMaskSet stateToReset = previousState->stateMask() & invOurState;
79 
80     std::bitset<64> bs(stateToReset);
81     cost += int(bs.count());
82 
83     // now, find out how many states we're changing
84     for (const StateVariant &ds : qAsConst(m_states)) {
85         // if the other state contains matching, then doesn't
86         // contribute to cost at all
87         if (previousState->contains(ds))
88             continue;
89 
90         // flat cost for now; could be replaced with a cost() method on
91         // RenderState
92         cost += 2;
93     }
94 
95     return cost;
96 }
97 
stateMask() const98 StateMaskSet RenderStateSet::stateMask() const
99 {
100     return m_stateMask;
101 }
102 
103 // This modifies our state to add states from others
104 // if we don't already contain a state with that type set
merge(const RenderStateSet * other)105 void RenderStateSet::merge(const RenderStateSet *other)
106 {
107     const QVector<StateVariant> otherStates = other->states();
108 
109     // We only add states which are new (different type)
110     for (const StateVariant &otherState : otherStates) {
111         const bool canAdd = canAddStateOfType(otherState.type);
112         if (canAdd)
113             m_states.push_back(otherState);
114     }
115     m_stateMask |= other->stateMask();
116 }
117 
canAddStateOfType(StateMask type) const118 bool RenderStateSet::canAddStateOfType(StateMask type) const
119 {
120     return !hasStateOfType(type) || allowMultipleStatesOfType(type);
121 }
122 
hasStateOfType(StateMask type) const123 bool RenderStateSet::hasStateOfType(StateMask type) const
124 {
125     return (type & stateMask());
126 }
127 
allowMultipleStatesOfType(StateMask type) const128 bool RenderStateSet::allowMultipleStatesOfType(StateMask type) const
129 {
130     return (type == BlendEquationArgumentsMask) ||
131            (type == ClipPlaneMask);
132 }
133 
contains(const StateVariant & ds) const134 bool RenderStateSet::contains(const StateVariant &ds) const
135 {
136     // trivial reject using the state mask bits
137     if (!(ds.type & stateMask()))
138         return false;
139 
140     for (const StateVariant &rs : m_states) {
141         if (rs == ds)
142             return true;
143     }
144     return false;
145 }
146 
147 } // namespace Render
148 } // namespace Qt3DRender
149 
150 QT_END_NAMESPACE
151