1# -*- coding: utf-8 -*-
2
3#-------------------------------------------------------------------------
4# drawElements Quality Program utilities
5# --------------------------------------
6#
7# Copyright 2015 The Android Open Source Project
8#
9# Licensed under the Apache License, Version 2.0 (the "License");
10# you may not use this file except in compliance with the License.
11# You may obtain a copy of the License at
12#
13#      http://www.apache.org/licenses/LICENSE-2.0
14#
15# Unless required by applicable law or agreed to in writing, software
16# distributed under the License is distributed on an "AS IS" BASIS,
17# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18# See the License for the specific language governing permissions and
19# limitations under the License.
20#
21#-------------------------------------------------------------------------
22
23import sys
24import itertools
25from collections import namedtuple
26from genutil import *
27
28# Templates
29
30declarationTemplate = """
31case ${{NAME}}
32	${{COMPILE_FAIL}}
33	values {}
34
35	vertex ""
36		precision mediump float;
37		attribute highp vec4 dEQP_Position;
38
39		${{VARIABLE_VTX}}
40
41		void main()
42		{
43			x0 = 1.0;
44			gl_Position = dEQP_Position;
45		}
46	""
47
48	fragment ""
49		precision mediump float;
50
51		${{VARIABLE_FRG}}
52
53		void main()
54		{
55			float result = x0 + x1;
56			gl_FragColor = vec4(result, result, result, 1.0);
57		}
58	""
59end
60"""[1:-1]
61
62parameterTemplate = """
63case ${{NAME}}
64	${{COMPILE_FAIL}}
65	values {}
66
67	both ""
68		precision mediump float;
69		${DECLARATIONS}
70
71		float foo0 (${{PARAMETER0}})
72		{
73			return x + 1.0;
74		}
75
76		void foo1 (${{PARAMETER1}})
77		{
78			x = 1.0;
79		}
80
81		float foo2 (${{PARAMETER2}})
82		{
83			return x + 1.0;
84		}
85
86		void main()
87		{
88			${SETUP}
89			float result;
90			foo1(result);
91			float x0 = foo0(1.0);
92			foo2(result);
93			${OUTPUT}
94		}
95	""
96end
97"""[1:-1]
98
99# Classes
100
101class DeclarationCase(ShaderCase):
102	def __init__(self, compileFail, paramList):
103		self.compileFail	= "expect compile_fail" if compileFail else "expect pass"
104		self.name			= ''
105		var0				= ''
106		var1				= ''
107		var2				= ''
108
109		for p in paramList:
110			self.name += p.name
111			if paramList.index(p) != len(paramList)-1:
112				self.name += '_'
113
114			var0 += p.vars[0] + ' '
115			var1 += p.vars[1] + ' '
116			var2 += p.vars[2] + ' '
117
118		var0 += 'float x0;\n'
119		var1 += 'float x1;\n'
120		var2 += 'float x2;'
121
122		self.variableVtx 	= (var0 + var1 + var2).strip()
123		self.variableFrg 	= (var0 + var1).strip()			# Omit 'attribute' in frag shader
124		self.variableVtx 	= self.variableVtx.replace("  ", " ")
125		self.variableFrg 	= self.variableFrg.replace("  ", " ")
126
127	def __str__(self):
128		params = {
129			"NAME"			: self.name,
130			"COMPILE_FAIL"	: self.compileFail,
131			"VARIABLE_VTX"	: self.variableVtx,
132			"VARIABLE_FRG"	: self.variableFrg
133		}
134		return fillTemplate(declarationTemplate, params)
135
136class ParameterCase(ShaderCase):
137	def __init__(self, compileFail, paramList):
138		self.compileFail	= "expect compile_fail" if compileFail else "expect pass"
139		self.name			= ''
140		self.param0			= ''
141		self.param1			= ''
142		self.param2			= ''
143
144		for p in paramList:
145			self.name += p.name
146			if paramList.index(p) != len(paramList)-1:
147				self.name += '_'
148
149			self.param0 += p.vars[0] + ' '
150			self.param1 += p.vars[1] + ' '
151			self.param2 += p.vars[2] + ' '
152
153		self.param0 += 'float x'
154		self.param1 += 'float x'
155		self.param2 += 'float x'
156		self.param0	= self.param0.replace("  ", " ")
157		self.param1	= self.param1.replace("  ", " ")
158		self.param2	= self.param2.replace("  ", " ")
159
160	def __str__(self):
161		params = {
162			"NAME"			: self.name,
163			"COMPILE_FAIL"	: self.compileFail,
164			"PARAMETER0"	: self.param0,
165			"PARAMETER1"	: self.param1,
166			"PARAMETER2"	: self.param2,
167		}
168		return fillTemplate(parameterTemplate, params)
169
170# Declarations
171
172CaseFormat			= namedtuple('CaseFormat', 'name vars')
173
174DECL_INVARIANT		= CaseFormat("invariant",	["invariant", 	"",			""])
175DECL_STORAGE		= CaseFormat("storage", 	["varying", 	"uniform",	"attribute"])
176DECL_PRECISION		= CaseFormat("precision", 	["lowp", 		"mediump",	"mediump"])
177
178PARAM_STORAGE		= CaseFormat("storage",		[ "const", 		"", 				""])
179PARAM_PARAMETER 	= CaseFormat("parameter",	[ "in", 		"out", 				"inout" ])
180PARAM_PRECISION		= CaseFormat("precision",	[ "lowp", 		"mediump",			"mediump" ])
181
182# Order of qualification tests
183
184validDeclarationCases	= []
185invalidDeclarationCases = []
186validParameterCases		= []
187invalidParameterCases	= []
188
189declFormats = [
190	[DECL_INVARIANT, DECL_STORAGE, DECL_PRECISION],
191	[DECL_STORAGE, DECL_PRECISION],
192	[DECL_INVARIANT, DECL_STORAGE]
193]
194
195paramFormats = [
196	[PARAM_STORAGE, PARAM_PARAMETER, PARAM_PRECISION],
197	[PARAM_STORAGE, PARAM_PARAMETER],
198	[PARAM_STORAGE, PARAM_PRECISION],
199	[PARAM_PARAMETER, PARAM_PRECISION]
200]
201
202for f in declFormats:
203	for p in itertools.permutations(f):
204		if list(p) == f:
205			validDeclarationCases.append(DeclarationCase(False, p))		# Correct order
206		else:
207			invalidDeclarationCases.append(DeclarationCase(True, p))	# Incorrect order
208
209for f in paramFormats:
210	for p in itertools.permutations(f):
211		if list(p) == f:
212			validParameterCases.append(ParameterCase(False, p))			# Correct order
213		else:
214			invalidParameterCases.append(ParameterCase(True, p))		# Incorrect order
215
216qualificationOrderCases = [
217	CaseGroup("variables",	"Order of qualification in variable declarations.", children = [
218		CaseGroup("valid", 		"Valid orderings.", 	validDeclarationCases),
219		CaseGroup("invalid",	"Invalid orderings.", 	invalidDeclarationCases)
220	]),
221	CaseGroup("parameters", "Order of qualification in function parameters.", children = [
222		CaseGroup("valid", 		"Valid orderings.", 	validParameterCases),
223		CaseGroup("invalid",	"Invalid orderings.", 	invalidParameterCases)
224	])
225]
226
227# Main program
228
229if __name__ == "__main__":
230	print "Generating shader case files."
231	writeAllCases("qualification_order.test", qualificationOrderCases)
232