1/*-------------------------------------------------------------------------
2 * drawElements Quality Program Random Shader Generator
3 * ----------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Variable Value class.
22 *//*--------------------------------------------------------------------*/
23
24#include "rsgVariableValue.hpp"
25
26namespace rsg
27{
28
29namespace
30{
31
32template <class CompareOp>
33bool compareValueRangesAllTrue (const ConstValueRangeAccess& a, const ConstValueRangeAccess& b)
34{
35	DE_ASSERT(a.getType() == b.getType());
36
37	if (a.getType().isStruct())
38	{
39		int numMembers = (int)a.getType().getMembers().size();
40		for (int ndx = 0; ndx < numMembers; ndx++)
41		{
42			if (!compareValueRangesAllTrue<CompareOp>(a.member(ndx), b.member(ndx)))
43				return false;
44		}
45	}
46	else if (a.getType().isArray())
47	{
48		int numElements = (int)a.getType().getNumElements();
49		for (int ndx = 0; ndx < numElements; ndx++)
50		{
51			if (!compareValueRangesAllTrue<CompareOp>(a.arrayElement(ndx), b.arrayElement(ndx)))
52				return false;
53		}
54	}
55	else
56	{
57		int numElements = (int)a.getType().getNumElements();
58		switch (a.getType().getBaseType())
59		{
60			case VariableType::TYPE_FLOAT:
61				for (int ndx = 0; ndx < numElements; ndx++)
62				{
63					float aMin = a.component(ndx).getMin().asFloat();
64					float aMax = a.component(ndx).getMax().asFloat();
65					float bMin = b.component(ndx).getMin().asFloat();
66					float bMax = b.component(ndx).getMax().asFloat();
67
68					if (!CompareOp()(aMin, aMax, bMin, bMax))
69						return false;
70				}
71				break;
72
73			case VariableType::TYPE_INT:
74			case VariableType::TYPE_SAMPLER_2D:
75			case VariableType::TYPE_SAMPLER_CUBE:
76				for (int ndx = 0; ndx < numElements; ndx++)
77				{
78					int aMin = a.component(ndx).getMin().asInt();
79					int aMax = a.component(ndx).getMax().asInt();
80					int bMin = b.component(ndx).getMin().asInt();
81					int bMax = b.component(ndx).getMax().asInt();
82
83					if (!CompareOp()(aMin, aMax, bMin, bMax))
84						return false;
85				}
86				break;
87
88			case VariableType::TYPE_BOOL:
89				for (int ndx = 0; ndx < numElements; ndx++)
90				{
91					bool aMin = a.component(ndx).getMin().asBool();
92					bool aMax = a.component(ndx).getMax().asBool();
93					bool bMin = b.component(ndx).getMin().asBool();
94					bool bMax = b.component(ndx).getMax().asBool();
95
96					if (!CompareOp()(aMin, aMax, bMin, bMax))
97						return false;
98				}
99				break;
100
101			default:
102				DE_ASSERT(DE_FALSE);
103				return false;
104		}
105	}
106
107	return true;
108}
109
110inline int toInt (bool boolVal) { return boolVal ? 1 : 0; }
111
112struct CompareIntersection
113{
114	inline bool operator() (float aMin, float aMax, float bMin, float bMax) const	{ return (aMin <= bMax && bMin <= aMax);	}
115	inline bool operator() (int aMin, int aMax, int bMin, int bMax) const			{ return (aMin <= bMax && bMin <= aMax);	}
116
117	inline bool operator() (bool aMin, bool aMax, bool bMin, bool bMax) const
118	{
119		return CompareIntersection()(toInt(aMin), toInt(aMax), toInt(bMin), toInt(bMax));
120	}
121};
122
123struct CompareIsSubsetOf
124{
125	inline bool operator() (float aMin, float aMax, float bMin, float bMax) const
126	{
127		return de::inRange(aMin, bMin, bMax) && de::inRange(aMax, bMin, bMax);
128	}
129
130	inline bool operator() (int aMin, int aMax, int bMin, int bMax) const
131	{
132		return de::inRange(aMin, bMin, bMax) && de::inRange(aMax, bMin, bMax);
133	}
134
135	inline bool operator() (bool aMin, bool aMax, bool bMin, bool bMax) const
136	{
137		return CompareIsSubsetOf()(toInt(aMin), toInt(aMax), toInt(bMin), toInt(bMax));
138	}
139};
140
141} // anonymous
142
143bool ConstValueRangeAccess::intersects (const ConstValueRangeAccess& other) const
144{
145	return compareValueRangesAllTrue<CompareIntersection>(*this, other);
146}
147
148bool ConstValueRangeAccess::isSubsetOf (const ConstValueRangeAccess& other) const
149{
150	return compareValueRangesAllTrue<CompareIsSubsetOf>(*this, other);
151}
152
153bool ConstValueRangeAccess::isSupersetOf (const ConstValueRangeAccess& other) const
154{
155	return other.isSubsetOf(*this);
156}
157
158ValueRange::ValueRange (const VariableType& type)
159	: m_type		(type)
160	, m_min			(type.getScalarSize())
161	, m_max			(type.getScalarSize())
162{
163}
164
165ValueRange::ValueRange (const VariableType& type, const ConstValueAccess& minVal, const ConstValueAccess& maxVal)
166	: m_type		(type)
167	, m_min			(type.getScalarSize())
168	, m_max			(type.getScalarSize())
169{
170	getMin() = minVal.value();
171	getMax() = maxVal.value();
172}
173
174ValueRange::ValueRange (const VariableType& type, const Scalar* minVal, const Scalar* maxVal)
175	: m_type		(type)
176	, m_min			(type.getScalarSize())
177	, m_max			(type.getScalarSize())
178{
179	getMin() = ConstValueAccess(type, minVal).value();
180	getMax() = ConstValueAccess(type, maxVal).value();
181}
182
183ValueRange::ValueRange (ConstValueRangeAccess other)
184	: m_type		(other.getType())
185	, m_min			(other.getType().getScalarSize())
186	, m_max			(other.getType().getScalarSize())
187{
188	getMin() = other.getMin().value();
189	getMax() = other.getMax().value();
190}
191
192ValueRange::~ValueRange (void)
193{
194}
195
196void ValueRange::computeIntersection (ValueRange& dst, const ConstValueRangeAccess& a, const ConstValueRangeAccess& b)
197{
198	computeIntersection(dst.asAccess(), a, b);
199}
200
201void ValueRange::computeIntersection (ValueRangeAccess dst, const ConstValueRangeAccess& a, const ConstValueRangeAccess& b)
202{
203	DE_ASSERT(dst.getType() == a.getType() && dst.getType() == b.getType());
204
205	if (a.getType().isStruct())
206	{
207		int numMembers = (int)a.getType().getMembers().size();
208		for (int ndx = 0; ndx < numMembers; ndx++)
209			computeIntersection(dst.member(ndx), a.member(ndx), b.member(ndx));
210	}
211	else if (a.getType().isArray())
212	{
213		int numElements = (int)a.getType().getNumElements();
214		for (int ndx = 0; ndx < numElements; ndx++)
215			computeIntersection(dst.arrayElement(ndx), a.arrayElement(ndx), b.arrayElement(ndx));
216	}
217	else
218	{
219		int numElements = (int)a.getType().getNumElements();
220		switch (a.getType().getBaseType())
221		{
222			case VariableType::TYPE_FLOAT:
223				for (int ndx = 0; ndx < numElements; ndx++)
224				{
225					float aMin = a.component(ndx).getMin().asFloat();
226					float aMax = a.component(ndx).getMax().asFloat();
227					float bMin = b.component(ndx).getMin().asFloat();
228					float bMax = b.component(ndx).getMax().asFloat();
229
230					dst.component(ndx).getMin() = de::max(aMin, bMin);
231					dst.component(ndx).getMax() = de::min(aMax, bMax);
232				}
233				break;
234
235			case VariableType::TYPE_INT:
236			case VariableType::TYPE_SAMPLER_2D:
237			case VariableType::TYPE_SAMPLER_CUBE:
238				for (int ndx = 0; ndx < numElements; ndx++)
239				{
240					int aMin = a.component(ndx).getMin().asInt();
241					int aMax = a.component(ndx).getMax().asInt();
242					int bMin = b.component(ndx).getMin().asInt();
243					int bMax = b.component(ndx).getMax().asInt();
244
245					dst.component(ndx).getMin() = de::max(aMin, bMin);
246					dst.component(ndx).getMax() = de::min(aMax, bMax);
247				}
248				break;
249
250			case VariableType::TYPE_BOOL:
251				for (int ndx = 0; ndx < numElements; ndx++)
252				{
253					bool aMin = a.component(ndx).getMin().asBool();
254					bool aMax = a.component(ndx).getMax().asBool();
255					bool bMin = b.component(ndx).getMin().asBool();
256					bool bMax = b.component(ndx).getMax().asBool();
257
258					dst.component(ndx).getMin() = aMin || bMin;
259					dst.component(ndx).getMax() = aMax && bMax;
260				}
261				break;
262
263			default:
264				DE_ASSERT(DE_FALSE);
265		}
266	}
267}
268
269VariableValue::VariableValue (const VariableValue& other)
270	: m_variable(other.m_variable)
271	, m_storage(other.m_variable->getType())
272{
273	m_storage.getValue(getType()) = other.getValue().value();
274}
275
276VariableValue& VariableValue::operator= (const VariableValue& other)
277{
278	m_variable	= other.m_variable;
279	m_storage.setStorage(getType());
280	m_storage.getValue(getType()) = other.getValue().value();
281	return *this;
282}
283
284} // rsg
285