1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
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 Negative Fragment Pipe API tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es31fNegativeFragmentApiTests.hpp"
25
26#include "gluCallLogWrapper.hpp"
27
28#include "glwDefs.hpp"
29#include "glwEnums.hpp"
30
31namespace deqp
32{
33namespace gles31
34{
35namespace Functional
36{
37namespace NegativeTestShared
38{
39
40using tcu::TestLog;
41using glu::CallLogWrapper;
42using namespace glw;
43
44using tcu::TestLog;
45
46void scissor (NegativeTestContext& ctx)
47{
48	ctx.beginSection("GL_INVALID_VALUE is generated if either width or height is negative.");
49	ctx.glScissor(0, 0, -1, 0);
50	ctx.expectError(GL_INVALID_VALUE);
51	ctx.glScissor(0, 0, 0, -1);
52	ctx.expectError(GL_INVALID_VALUE);
53	ctx.glScissor(0, 0, -1, -1);
54	ctx.expectError(GL_INVALID_VALUE);
55	ctx.endSection();
56}
57
58void depth_func (NegativeTestContext& ctx)
59{
60	ctx.beginSection("GL_INVALID_ENUM is generated if func is not an accepted value.");
61	ctx.glDepthFunc(-1);
62	ctx.expectError(GL_INVALID_ENUM);
63	ctx.endSection();
64}
65
66void viewport (NegativeTestContext& ctx)
67{
68	ctx.beginSection("GL_INVALID_VALUE is generated if either width or height is negative.");
69	ctx.glViewport(0, 0, -1, 1);
70	ctx.expectError(GL_INVALID_VALUE);
71	ctx.glViewport(0, 0, 1, -1);
72	ctx.expectError(GL_INVALID_VALUE);
73	ctx.glViewport(0, 0, -1, -1);
74	ctx.expectError(GL_INVALID_VALUE);
75	ctx.endSection();
76}
77
78// Stencil functions
79void stencil_func (NegativeTestContext& ctx)
80{
81	ctx.beginSection("GL_INVALID_ENUM is generated if func is not one of the eight accepted values.");
82	ctx.glStencilFunc(-1, 0, 1);
83	ctx.expectError(GL_INVALID_ENUM);
84	ctx.endSection();
85}
86
87void stencil_func_separate (NegativeTestContext& ctx)
88{
89	ctx.beginSection("GL_INVALID_ENUM is generated if face is not GL_FRONT, GL_BACK, or GL_FRONT_AND_BACK.");
90	ctx.glStencilFuncSeparate(-1, GL_NEVER, 0, 1);
91	ctx.expectError(GL_INVALID_ENUM);
92	ctx.endSection();
93
94	ctx.beginSection("GL_INVALID_ENUM is generated if func is not one of the eight accepted values.");
95	ctx.glStencilFuncSeparate(GL_FRONT, -1, 0, 1);
96	ctx.expectError(GL_INVALID_ENUM);
97	ctx.endSection();
98}
99
100void stencil_op (NegativeTestContext& ctx)
101{
102	ctx.beginSection("GL_INVALID_ENUM is generated if sfail, dpfail, or dppass is any value other than the defined symbolic constant values.");
103	ctx.glStencilOp(-1, GL_ZERO, GL_REPLACE);
104	ctx.expectError(GL_INVALID_ENUM);
105	ctx.glStencilOp(GL_KEEP, -1, GL_REPLACE);
106	ctx.expectError(GL_INVALID_ENUM);
107	ctx.glStencilOp(GL_KEEP, GL_ZERO, -1);
108	ctx.expectError(GL_INVALID_ENUM);
109	ctx.endSection();
110}
111
112void stencil_op_separate (NegativeTestContext& ctx)
113{
114	ctx.beginSection("GL_INVALID_ENUM is generated if face is any value other than GL_FRONT, GL_BACK, or GL_FRONT_AND_BACK.");
115	ctx.glStencilOpSeparate(-1, GL_KEEP, GL_ZERO, GL_REPLACE);
116	ctx.expectError(GL_INVALID_ENUM);
117	ctx.endSection();
118
119	ctx.beginSection("GL_INVALID_ENUM is generated if sfail, dpfail, or dppass is any value other than the eight defined symbolic constant values.");
120	ctx.glStencilOpSeparate(GL_FRONT, -1, GL_ZERO, GL_REPLACE);
121	ctx.expectError(GL_INVALID_ENUM);
122	ctx.glStencilOpSeparate(GL_FRONT, GL_KEEP, -1, GL_REPLACE);
123	ctx.expectError(GL_INVALID_ENUM);
124	ctx.glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_ZERO, -1);
125	ctx.expectError(GL_INVALID_ENUM);
126	ctx.endSection();
127}
128
129void stencil_mask_separate (NegativeTestContext& ctx)
130{
131	ctx.beginSection("GL_INVALID_ENUM is generated if face is not GL_FRONT, GL_BACK, or GL_FRONT_AND_BACK.");
132	ctx.glStencilMaskSeparate(-1, 0);
133	ctx.expectError(GL_INVALID_ENUM);
134	ctx.endSection();
135}
136
137// Blend functions
138void blend_equation (NegativeTestContext& ctx)
139{
140	ctx.beginSection("GL_INVALID_ENUM is generated if mode is not GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT, GL_MAX or GL_MIN.");
141	ctx.glBlendEquation(-1);
142	ctx.expectError(GL_INVALID_ENUM);
143	ctx.endSection();
144}
145
146void blend_equation_separate (NegativeTestContext& ctx)
147{
148	ctx.beginSection("GL_INVALID_ENUM is generated if modeRGB is not GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT, GL_MAX or GL_MIN.");
149	ctx.glBlendEquationSeparate(-1, GL_FUNC_ADD);
150	ctx.expectError(GL_INVALID_ENUM);
151	ctx.endSection();
152	ctx.beginSection("GL_INVALID_ENUM is generated if modeAlpha is not GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT, GL_MAX or GL_MIN.");
153	ctx.glBlendEquationSeparate(GL_FUNC_ADD, -1);
154	ctx.expectError(GL_INVALID_ENUM);
155	ctx.endSection();
156}
157
158void blend_func (NegativeTestContext& ctx)
159{
160	ctx.beginSection("GL_INVALID_ENUM is generated if either sfactor or dfactor is not an accepted value.");
161	ctx.glBlendFunc(-1, GL_ONE);
162	ctx.expectError(GL_INVALID_ENUM);
163	ctx.glBlendFunc(GL_ONE, -1);
164	ctx.expectError(GL_INVALID_ENUM);
165	ctx.endSection();
166}
167
168void blend_func_separate (NegativeTestContext& ctx)
169{
170	ctx.beginSection("GL_INVALID_ENUM is generated if srcRGB, dstRGB, srcAlpha, or dstAlpha is not an accepted value.");
171	ctx.glBlendFuncSeparate(-1, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);
172	ctx.expectError(GL_INVALID_ENUM);
173	ctx.glBlendFuncSeparate(GL_ZERO, -1, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);
174	ctx.expectError(GL_INVALID_ENUM);
175	ctx.glBlendFuncSeparate(GL_ZERO, GL_ONE, -1, GL_ONE_MINUS_SRC_COLOR);
176	ctx.expectError(GL_INVALID_ENUM);
177	ctx.glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_SRC_COLOR, -1);
178	ctx.expectError(GL_INVALID_ENUM);
179	ctx.endSection();
180}
181
182// Rasterization API functions
183void cull_face (NegativeTestContext& ctx)
184{
185	ctx.beginSection("GL_INVALID_ENUM is generated if mode is not an accepted value.");
186	ctx.glCullFace(-1);
187	ctx.expectError(GL_INVALID_ENUM);
188	ctx.endSection();
189}
190
191void front_face (NegativeTestContext& ctx)
192{
193	ctx.beginSection("GL_INVALID_ENUM is generated if mode is not an accepted value.");
194	ctx.glFrontFace(-1);
195	ctx.expectError(GL_INVALID_ENUM);
196	ctx.endSection();
197}
198
199void line_width (NegativeTestContext& ctx)
200{
201	ctx.beginSection("GL_INVALID_VALUE is generated if width is less than or equal to 0.");
202	ctx.glLineWidth(0);
203	ctx.expectError(GL_INVALID_VALUE);
204	ctx.glLineWidth(-1);
205	ctx.expectError(GL_INVALID_VALUE);
206	ctx.endSection();
207}
208
209// Asynchronous queries
210void gen_queries (NegativeTestContext& ctx)
211{
212	ctx.beginSection("GL_INVALID_VALUE is generated if n is negative.");
213	GLuint ids = 0;
214	ctx.glGenQueries	(-1, &ids);
215	ctx.expectError		(GL_INVALID_VALUE);
216	ctx.endSection();
217}
218
219void begin_query (NegativeTestContext& ctx)
220{
221	GLuint ids[3];
222	ctx.glGenQueries	(3, ids);
223
224	ctx.beginSection("GL_INVALID_ENUM is generated if target is not one of the accepted tokens.");
225	ctx.glBeginQuery	(-1, ids[0]);
226	ctx.expectError		(GL_INVALID_ENUM);
227	ctx.endSection();
228
229	ctx.beginSection("GL_INVALID_OPERATION is generated if ctx.glBeginQuery is executed while a query object of the same target is already active.");
230	ctx.glBeginQuery	(GL_ANY_SAMPLES_PASSED, ids[0]);
231	ctx.expectError		(GL_NO_ERROR);
232	ctx.glBeginQuery	(GL_ANY_SAMPLES_PASSED, ids[1]);
233	ctx.expectError		(GL_INVALID_OPERATION);
234	// \note GL_ANY_SAMPLES_PASSED and GL_ANY_SAMPLES_PASSED_CONSERVATIVE alias to the same target for the purposes of this error.
235	ctx.glBeginQuery	(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, ids[1]);
236	ctx.expectError		(GL_INVALID_OPERATION);
237	ctx.glBeginQuery	(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, ids[1]);
238	ctx.expectError		(GL_NO_ERROR);
239	ctx.glBeginQuery	(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, ids[2]);
240	ctx.expectError		(GL_INVALID_OPERATION);
241	ctx.glEndQuery		(GL_ANY_SAMPLES_PASSED);
242	ctx.glEndQuery		(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
243	ctx.expectError		(GL_NO_ERROR);
244	ctx.endSection();
245
246	ctx.beginSection("GL_INVALID_OPERATION is generated if id is 0.");
247	ctx.glBeginQuery	(GL_ANY_SAMPLES_PASSED, 0);
248	ctx.expectError		(GL_INVALID_OPERATION);
249	ctx.endSection();
250
251	ctx.beginSection("GL_INVALID_OPERATION is generated if id not a name returned from a previous call to ctx.glGenQueries, or if such a name has since been deleted with ctx.glDeleteQueries.");
252	ctx.glBeginQuery	(GL_ANY_SAMPLES_PASSED, -1);
253	ctx.expectError		(GL_INVALID_OPERATION);
254	ctx.glDeleteQueries	(1, &ids[2]);
255	ctx.expectError		(GL_NO_ERROR);
256	ctx.glBeginQuery	(GL_ANY_SAMPLES_PASSED, ids[2]);
257	ctx.expectError		(GL_INVALID_OPERATION);
258	ctx.endSection();
259
260	ctx.beginSection("GL_INVALID_OPERATION is generated if id is the name of an already active query object.");
261	ctx.glBeginQuery	(GL_ANY_SAMPLES_PASSED, ids[0]);
262	ctx.expectError		(GL_NO_ERROR);
263	ctx.glBeginQuery	(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, ids[0]);
264	ctx.expectError		(GL_INVALID_OPERATION);
265	ctx.endSection();
266
267	ctx.beginSection("GL_INVALID_OPERATION is generated if id refers to an existing query object whose type does not does not match target.");
268	ctx.glEndQuery		(GL_ANY_SAMPLES_PASSED);
269	ctx.expectError		(GL_NO_ERROR);
270	ctx.glBeginQuery	(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, ids[0]);
271	ctx.expectError		(GL_INVALID_OPERATION);
272	ctx.endSection();
273
274	ctx.glDeleteQueries	(2, &ids[0]);
275	ctx.expectError		(GL_NO_ERROR);
276}
277
278void end_query (NegativeTestContext& ctx)
279{
280	GLuint id = 0;
281	ctx.glGenQueries	(1, &id);
282
283	ctx.beginSection("GL_INVALID_ENUM is generated if target is not one of the accepted tokens.");
284	ctx.glEndQuery		(-1);
285	ctx.expectError		(GL_INVALID_ENUM);
286	ctx.endSection();
287
288	ctx.beginSection("GL_INVALID_OPERATION is generated if ctx.glEndQuery is executed when a query object of the same target is not active.");
289	ctx.glEndQuery		(GL_ANY_SAMPLES_PASSED);
290	ctx.expectError		(GL_INVALID_OPERATION);
291	ctx.glBeginQuery	(GL_ANY_SAMPLES_PASSED, id);
292	ctx.expectError		(GL_NO_ERROR);
293	ctx.glEndQuery		(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
294	ctx.expectError		(GL_INVALID_OPERATION);
295	ctx.glEndQuery		(GL_ANY_SAMPLES_PASSED);
296	ctx.expectError		(GL_NO_ERROR);
297	ctx.endSection();
298
299	ctx.glDeleteQueries	(1, &id);
300	ctx.expectError		(GL_NO_ERROR);
301}
302
303void delete_queries (NegativeTestContext& ctx)
304{
305	GLuint id = 0;
306	ctx.glGenQueries	(1, &id);
307
308	ctx.beginSection("GL_INVALID_VALUE is generated if n is negative.");
309	ctx.glDeleteQueries	(-1, &id);
310	ctx.expectError		(GL_INVALID_VALUE);
311	ctx.endSection();
312
313	ctx.glDeleteQueries	(1, &id);
314}
315
316// Sync objects
317void fence_sync (NegativeTestContext& ctx)
318{
319	ctx.beginSection("GL_INVALID_ENUM is generated if condition is not GL_SYNC_GPU_COMMANDS_COMPLETE.");
320	ctx.glFenceSync(-1, 0);
321	ctx.expectError(GL_INVALID_ENUM);
322	ctx.endSection();
323
324	ctx.beginSection("GL_INVALID_VALUE is generated if flags is not zero.");
325	ctx.glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0x0010);
326	ctx.expectError(GL_INVALID_VALUE);
327	ctx.endSection();
328}
329
330void wait_sync (NegativeTestContext& ctx)
331{
332	GLsync sync = ctx.glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
333
334	ctx.beginSection("GL_INVALID_VALUE is generated if sync is not the name of a sync object.");
335	ctx.glWaitSync(0, 0, GL_TIMEOUT_IGNORED);
336	ctx.expectError(GL_INVALID_VALUE);
337	ctx.endSection();
338
339	ctx.beginSection("GL_INVALID_VALUE is generated if flags is not zero.");
340	ctx.glWaitSync(sync, 0x0010, GL_TIMEOUT_IGNORED);
341	ctx.expectError(GL_INVALID_VALUE);
342	ctx.endSection();
343
344	ctx.beginSection("GL_INVALID_VALUE is generated if timeout is not GL_TIMEOUT_IGNORED.");
345	ctx.glWaitSync(sync, 0, 0);
346	ctx.expectError(GL_INVALID_VALUE);
347	ctx.endSection();
348
349	ctx.glDeleteSync(sync);
350}
351
352void client_wait_sync (NegativeTestContext& ctx)
353{
354	GLsync sync = ctx.glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
355
356	ctx.beginSection("GL_INVALID_VALUE is generated if sync is not the name of an existing sync object.");
357	ctx.glClientWaitSync (0, 0, 10000);
358	ctx.expectError(GL_INVALID_VALUE);
359	ctx.endSection();
360
361	ctx.beginSection("GL_INVALID_VALUE is generated if flags contains any unsupported flag.");
362	ctx.glClientWaitSync(sync, 0x00000004, 10000);
363	ctx.expectError(GL_INVALID_VALUE);
364	ctx.endSection();
365
366	ctx.glDeleteSync(sync);
367}
368
369void delete_sync (NegativeTestContext& ctx)
370{
371	ctx.beginSection("GL_INVALID_VALUE is generated if sync is neither zero or the name of a sync object.");
372	ctx.glDeleteSync((GLsync)1);
373	ctx.expectError(GL_INVALID_VALUE);
374	ctx.glDeleteSync(0);
375	ctx.expectError(GL_NO_ERROR);
376	ctx.endSection();
377}
378
379std::vector<FunctionContainer> getNegativeFragmentApiTestFunctions ()
380{
381	FunctionContainer funcs[] =
382	{
383		{scissor,					"scissor",					"Invalid glScissor() usage"				 },
384		{depth_func,				"depth_func",				"Invalid glDepthFunc() usage"			 },
385		{viewport,					"viewport",					"Invalid glViewport() usage"			 },
386		{stencil_func,				"stencil_func",				"Invalid glStencilFunc() usage"			 },
387		{stencil_func_separate,		"stencil_func_separate",	"Invalid glStencilFuncSeparate() usage"	 },
388		{stencil_op,				"stencil_op",				"Invalid glStencilOp() usage"			 },
389		{stencil_op_separate,		"stencil_op_separate",		"Invalid glStencilOpSeparate() usage"	 },
390		{stencil_mask_separate,		"stencil_mask_separate",	"Invalid glStencilMaskSeparate() usage"	 },
391		{blend_equation,			"blend_equation",			"Invalid glBlendEquation() usage"		 },
392		{blend_equation_separate,	"blend_equation_separate",	"Invalid glBlendEquationSeparate() usage"},
393		{blend_func,				"blend_func",				"Invalid glBlendFunc() usage"			 },
394		{blend_func_separate,		"blend_func_separate",		"Invalid glBlendFuncSeparate() usage"	 },
395		{cull_face,					"cull_face",				"Invalid glCullFace() usage"			 },
396		{front_face,				"front_face",				"Invalid glFrontFace() usage"			 },
397		{line_width,				"line_width",				"Invalid glLineWidth() usage"			 },
398		{gen_queries,				"gen_queries",				"Invalid glGenQueries() usage"			 },
399		{begin_query,				"begin_query",				"Invalid glBeginQuery() usage"			 },
400		{end_query,					"end_query",				"Invalid glEndQuery() usage"			 },
401		{delete_queries,			"delete_queries",			"Invalid glDeleteQueries() usage"		 },
402		{fence_sync,				"fence_sync",				"Invalid glFenceSync() usage"			 },
403		{wait_sync,					"wait_sync",				"Invalid glWaitSync() usage"			 },
404		{client_wait_sync,			"client_wait_sync",			"Invalid glClientWaitSync() usage"		 },
405		{delete_sync,				"delete_sync",				"Invalid glDeleteSync() usage"			 },
406	};
407
408	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
409}
410
411} // NegativeTestShared
412} // Functional
413} // gles31
414} // deqp
415