1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program EGL 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 Surface query tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "teglQuerySurfaceTests.hpp"
25 
26 #include "teglSimpleConfigCase.hpp"
27 
28 #include "egluNativeDisplay.hpp"
29 #include "egluNativeWindow.hpp"
30 #include "egluNativePixmap.hpp"
31 #include "egluStrUtil.hpp"
32 #include "egluUtil.hpp"
33 #include "egluUnique.hpp"
34 
35 #include "eglwLibrary.hpp"
36 #include "eglwEnums.hpp"
37 
38 #include "tcuTestLog.hpp"
39 #include "tcuTestContext.hpp"
40 #include "tcuCommandLine.hpp"
41 
42 #include "deUniquePtr.hpp"
43 
44 #include <string>
45 #include <vector>
46 
47 namespace deqp
48 {
49 namespace egl
50 {
51 
52 using eglu::ConfigInfo;
53 using tcu::TestLog;
54 using namespace eglw;
55 
logSurfaceAttribute(tcu::TestLog & log,EGLint attribute,EGLint value)56 static void logSurfaceAttribute (tcu::TestLog& log, EGLint attribute, EGLint value)
57 {
58 	const char*								name		= eglu::getSurfaceAttribName(attribute);
59 	const eglu::SurfaceAttribValueFmt		valueFmt	(attribute, value);
60 
61 	log << TestLog::Message << "  " << name << ": " << valueFmt << TestLog::EndMessage;
62 }
63 
logSurfaceAttributes(tcu::TestLog & log,const Library & egl,EGLDisplay display,EGLSurface surface,const EGLint * attributes,int numAttribs)64 static void logSurfaceAttributes (tcu::TestLog& log, const Library& egl, EGLDisplay display, EGLSurface surface, const EGLint* attributes, int numAttribs)
65 {
66 	for (int ndx = 0; ndx < numAttribs; ndx++)
67 		logSurfaceAttribute(log, attributes[ndx], eglu::querySurfaceInt(egl, display, surface, attributes[ndx]));
68 }
69 
logCommonSurfaceAttributes(tcu::TestLog & log,const Library & egl,EGLDisplay display,EGLSurface surface)70 static void logCommonSurfaceAttributes (tcu::TestLog& log, const Library& egl, EGLDisplay display, EGLSurface surface)
71 {
72 	static const EGLint	attributes[] =
73 	{
74 		EGL_CONFIG_ID,
75 		EGL_WIDTH,
76 		EGL_HEIGHT,
77 		EGL_HORIZONTAL_RESOLUTION,
78 		EGL_VERTICAL_RESOLUTION,
79 		EGL_MULTISAMPLE_RESOLVE,
80 		EGL_PIXEL_ASPECT_RATIO,
81 		EGL_RENDER_BUFFER,
82 		EGL_SWAP_BEHAVIOR,
83 		EGL_ALPHA_FORMAT,
84 		EGL_COLORSPACE
85 	};
86 
87 	logSurfaceAttributes(log, egl, display, surface, attributes, DE_LENGTH_OF_ARRAY(attributes));
88 }
89 
logPbufferSurfaceAttributes(tcu::TestLog & log,const Library & egl,EGLDisplay display,EGLSurface surface)90 static void logPbufferSurfaceAttributes (tcu::TestLog& log, const Library& egl, EGLDisplay display, EGLSurface surface)
91 {
92 	static const EGLint	attributes[] =
93 	{
94 		EGL_LARGEST_PBUFFER,
95 		EGL_TEXTURE_FORMAT,
96 		EGL_TEXTURE_TARGET,
97 		EGL_MIPMAP_TEXTURE,
98 		EGL_MIPMAP_LEVEL,
99 	};
100 
101 	logSurfaceAttributes(log, egl, display, surface, attributes, DE_LENGTH_OF_ARRAY(attributes));
102 }
103 
104 class QuerySurfaceCase : public SimpleConfigCase
105 {
106 public:
107 			QuerySurfaceCase			(EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters);
108 
109 	void	checkCommonAttributes		(EGLDisplay display, EGLSurface surface, const ConfigInfo& info);
110 	void	checkNonPbufferAttributes	(EGLDisplay display, EGLSurface surface);
111 };
112 
QuerySurfaceCase(EglTestContext & eglTestCtx,const char * name,const char * description,const eglu::FilterList & filters)113 QuerySurfaceCase::QuerySurfaceCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters)
114 	: SimpleConfigCase(eglTestCtx, name, description, filters)
115 {
116 }
117 
checkCommonAttributes(EGLDisplay display,EGLSurface surface,const ConfigInfo & info)118 void QuerySurfaceCase::checkCommonAttributes (EGLDisplay display, EGLSurface surface, const ConfigInfo& info)
119 {
120 	const Library&	egl		= m_eglTestCtx.getLibrary();
121 	tcu::TestLog&	log		= m_testCtx.getLog();
122 
123 	// Attributes which are common to all surface types
124 
125 	// Config ID
126 	{
127 		const EGLint	id	= eglu::querySurfaceInt(egl, display, surface, EGL_CONFIG_ID);
128 
129 		if (id != info.configId)
130 		{
131 			log << TestLog::Message << "    Fail, config ID " << id << " does not match the one used to create the surface" << TestLog::EndMessage;
132 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Config ID mismatch");
133 		}
134 	}
135 
136 	// Width and height
137 	{
138 		const EGLint	width	= eglu::querySurfaceInt(egl, display, surface, EGL_WIDTH);
139 		const EGLint	height	= eglu::querySurfaceInt(egl, display, surface, EGL_HEIGHT);
140 
141 		if (width <= 0 || height <= 0)
142 		{
143 			log << TestLog::Message << "    Fail, invalid surface size " << width << "x" << height << TestLog::EndMessage;
144 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid surface size");
145 		}
146 	}
147 
148 	// Horizontal and vertical resolution
149 	{
150 		const EGLint	hRes	= eglu::querySurfaceInt(egl, display, surface, EGL_HORIZONTAL_RESOLUTION);
151 		const EGLint	vRes	= eglu::querySurfaceInt(egl, display, surface, EGL_VERTICAL_RESOLUTION);
152 
153 		if ((hRes <= 0 || vRes <= 0) && (hRes != EGL_UNKNOWN && vRes != EGL_UNKNOWN))
154 		{
155 			log << TestLog::Message << "    Fail, invalid surface resolution " << hRes << "x" << vRes << TestLog::EndMessage;
156 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid surface resolution");
157 		}
158 	}
159 
160 	// Pixel aspect ratio
161 	{
162 		const EGLint	pixelRatio	= eglu::querySurfaceInt(egl, display, surface, EGL_PIXEL_ASPECT_RATIO);
163 
164 		if (pixelRatio <= 0 && pixelRatio != EGL_UNKNOWN)
165 		{
166 			log << TestLog::Message << "    Fail, invalid pixel aspect ratio " << eglu::querySurfaceInt(egl, display, surface, EGL_PIXEL_ASPECT_RATIO) << TestLog::EndMessage;
167 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid pixel aspect ratio");
168 		}
169 	}
170 
171 	// Render buffer
172 	{
173 		const EGLint	renderBuffer	= eglu::querySurfaceInt(egl, display, surface, EGL_RENDER_BUFFER);
174 
175 		if (renderBuffer != EGL_BACK_BUFFER && renderBuffer != EGL_SINGLE_BUFFER)
176 		{
177 			log << TestLog::Message << "    Fail, invalid render buffer value " << renderBuffer << TestLog::EndMessage;
178 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid render buffer");
179 		}
180 	}
181 
182 	// Multisample resolve
183 	{
184 		const EGLint	multisampleResolve	= eglu::querySurfaceInt(egl, display, surface, EGL_MULTISAMPLE_RESOLVE);
185 
186 		if (multisampleResolve != EGL_MULTISAMPLE_RESOLVE_DEFAULT && multisampleResolve != EGL_MULTISAMPLE_RESOLVE_BOX)
187 		{
188 			log << TestLog::Message << "    Fail, invalid multisample resolve value " << multisampleResolve << TestLog::EndMessage;
189 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid multisample resolve");
190 		}
191 
192 		if (multisampleResolve == EGL_MULTISAMPLE_RESOLVE_BOX && !(info.surfaceType & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
193 		{
194 			log << TestLog::Message << "    Fail, multisample resolve is reported as box filter but configuration does not support it." << TestLog::EndMessage;
195 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid multisample resolve");
196 		}
197 	}
198 
199 	// Swap behavior
200 	{
201 		const EGLint	swapBehavior	= eglu::querySurfaceInt(egl, display, surface, EGL_SWAP_BEHAVIOR);
202 
203 		if (swapBehavior != EGL_BUFFER_DESTROYED && swapBehavior != EGL_BUFFER_PRESERVED)
204 		{
205 			log << TestLog::Message << "    Fail, invalid swap behavior value " << swapBehavior << TestLog::EndMessage;
206 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid swap behavior");
207 		}
208 
209 		if (swapBehavior == EGL_BUFFER_PRESERVED && !(info.surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
210 		{
211 			log << TestLog::Message << "    Fail, swap behavior is reported as preserve but configuration does not support it." << TestLog::EndMessage;
212 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid swap behavior");
213 		}
214 	}
215 
216 	// alpha format
217 	{
218 		const EGLint	alphaFormat	= eglu::querySurfaceInt(egl, display, surface, EGL_ALPHA_FORMAT);
219 
220 		if (alphaFormat != EGL_ALPHA_FORMAT_NONPRE && alphaFormat != EGL_ALPHA_FORMAT_PRE)
221 		{
222 			log << TestLog::Message << "    Fail, invalid alpha format value " << alphaFormat << TestLog::EndMessage;
223 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid alpha format");
224 		}
225 
226 		if (alphaFormat == EGL_ALPHA_FORMAT_PRE && !(info.surfaceType & EGL_VG_ALPHA_FORMAT_PRE_BIT))
227 		{
228 			log << TestLog::Message << "    Fail, is set to use premultiplied alpha but configuration does not support it." << TestLog::EndMessage;
229 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid alpha format");
230 		}
231 	}
232 
233 	// color space
234 	{
235 		const EGLint	colorspace	= eglu::querySurfaceInt(egl, display, surface, EGL_COLORSPACE);
236 
237 		if (colorspace != EGL_VG_COLORSPACE_sRGB && colorspace != EGL_VG_COLORSPACE_LINEAR)
238 		{
239 			log << TestLog::Message << "    Fail, invalid color space value " << colorspace << TestLog::EndMessage;
240 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid color space");
241 		}
242 
243 		if (colorspace == EGL_VG_COLORSPACE_LINEAR && !(info.surfaceType & EGL_VG_COLORSPACE_LINEAR_BIT))
244 		{
245 			log << TestLog::Message << "    Fail, is set to use a linear color space but configuration does not support it." << TestLog::EndMessage;
246 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid color space");
247 		}
248 	}
249 }
250 
checkNonPbufferAttributes(EGLDisplay display,EGLSurface surface)251 void QuerySurfaceCase::checkNonPbufferAttributes (EGLDisplay display, EGLSurface surface)
252 {
253 	const Library&	egl						= m_eglTestCtx.getLibrary();
254 	const EGLint	uninitializedMagicValue	= -42;
255 	tcu::TestLog&	log						= m_testCtx.getLog();
256 	EGLint			value					= uninitializedMagicValue;
257 
258 	static const EGLint pbufferAttribs[] =
259 	{
260 		EGL_LARGEST_PBUFFER,
261 		EGL_TEXTURE_FORMAT,
262 		EGL_TEXTURE_TARGET,
263 		EGL_MIPMAP_TEXTURE,
264 		EGL_MIPMAP_LEVEL,
265 	};
266 
267 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pbufferAttribs); ndx++)
268 	{
269 		const EGLint		attribute	= pbufferAttribs[ndx];
270 		const std::string	name		= eglu::getSurfaceAttribName(pbufferAttribs[ndx]);
271 
272 		egl.querySurface(display, surface, attribute, &value);
273 
274 		{
275 			const EGLint	error	= egl.getError();
276 
277 			if (error != EGL_SUCCESS)
278 			{
279 				log << TestLog::Message << "    Fail, querying " << name << " from a non-pbuffer surface should not result in an error, received "
280 					<< eglu::getErrorStr(error) << TestLog::EndMessage;
281 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Illegal error condition");
282 				break;
283 			}
284 		}
285 
286 		// "For a window or pixmap surface, the contents of value are not modified."
287 		if (value != uninitializedMagicValue)
288 		{
289 			log << TestLog::Message << "    Fail, return value contents were modified when querying " << name << " from a non-pbuffer surface." << TestLog::EndMessage;
290 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Illegal modification of return value");
291 		}
292 	}
293 }
294 
295 class QuerySurfaceSimpleWindowCase : public QuerySurfaceCase
296 {
297 public:
QuerySurfaceSimpleWindowCase(EglTestContext & eglTestCtx,const char * name,const char * description,const eglu::FilterList & filters)298 	QuerySurfaceSimpleWindowCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters)
299 		: QuerySurfaceCase(eglTestCtx, name, description, filters)
300 	{
301 	}
302 
executeForConfig(EGLDisplay display,EGLConfig config)303 	void executeForConfig (EGLDisplay display, EGLConfig config)
304 	{
305 		const Library&						egl				= m_eglTestCtx.getLibrary();
306 		tcu::TestLog&						log				= m_testCtx.getLog();
307 		const int							width			= 64;
308 		const int							height			= 64;
309 		const eglu::NativeWindowFactory&	windowFactory	= eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
310 		ConfigInfo							info;
311 
312 		eglu::queryConfigInfo(egl, display, config, &info);
313 
314 		log << TestLog::Message << "Creating window surface with config ID " << info.configId << TestLog::EndMessage;
315 		EGLU_CHECK_MSG(egl, "before queries");
316 
317 		de::UniquePtr<eglu::NativeWindow>	window	(windowFactory.createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, eglu::WindowParams(width, height, eglu::parseWindowVisibility(m_testCtx.getCommandLine()))));
318 		eglu::UniqueSurface					surface	(egl, display, eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, display, config, DE_NULL));
319 
320 		logCommonSurfaceAttributes	(log, egl, display, *surface);
321 		checkCommonAttributes		(display, *surface, info);
322 		checkNonPbufferAttributes	(display, *surface);
323 	}
324 };
325 
326 class QuerySurfaceSimplePixmapCase : public QuerySurfaceCase
327 {
328 public:
QuerySurfaceSimplePixmapCase(EglTestContext & eglTestCtx,const char * name,const char * description,const eglu::FilterList & filters)329 	QuerySurfaceSimplePixmapCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters)
330 		: QuerySurfaceCase(eglTestCtx, name, description, filters)
331 	{
332 	}
333 
executeForConfig(EGLDisplay display,EGLConfig config)334 	void executeForConfig (EGLDisplay display, EGLConfig config)
335 	{
336 		const Library&						egl				= m_eglTestCtx.getLibrary();
337 		tcu::TestLog&						log				= m_testCtx.getLog();
338 		const int							width			= 64;
339 		const int							height			= 64;
340 		const eglu::NativePixmapFactory&	pixmapFactory	= eglu::selectNativePixmapFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
341 		ConfigInfo							info;
342 
343 		eglu::queryConfigInfo(egl, display, config, &info);
344 
345 		log << TestLog::Message << "Creating pixmap surface with config ID " << info.configId << TestLog::EndMessage;
346 		EGLU_CHECK_MSG(egl, "before queries");
347 
348 		de::UniquePtr<eglu::NativePixmap>	pixmap	(pixmapFactory.createPixmap(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, width, height));
349 		eglu::UniqueSurface					surface	(egl, display, eglu::createPixmapSurface(m_eglTestCtx.getNativeDisplay(), *pixmap, display, config, DE_NULL));
350 
351 		logCommonSurfaceAttributes	(log, egl, display, *surface);
352 		checkCommonAttributes		(display, *surface, info);
353 		checkNonPbufferAttributes	(display, *surface);
354 	}
355 };
356 
357 class QuerySurfaceSimplePbufferCase : public QuerySurfaceCase
358 {
359 public:
QuerySurfaceSimplePbufferCase(EglTestContext & eglTestCtx,const char * name,const char * description,const eglu::FilterList & filters)360 	QuerySurfaceSimplePbufferCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters)
361 		: QuerySurfaceCase(eglTestCtx, name, description, filters)
362 	{
363 	}
364 
executeForConfig(EGLDisplay display,EGLConfig config)365 	void executeForConfig (EGLDisplay display, EGLConfig config)
366 	{
367 		const Library&	egl		= m_eglTestCtx.getLibrary();
368 		tcu::TestLog&	log		= m_testCtx.getLog();
369 		int				width	= 64;
370 		int				height	= 64;
371 		ConfigInfo		info;
372 
373 		eglu::queryConfigInfo(egl, display, config, &info);
374 
375 		log << TestLog::Message << "Creating pbuffer surface with config ID " << info.configId << TestLog::EndMessage;
376 		EGLU_CHECK_MSG(egl, "before queries");
377 
378 		// Clamp to maximums reported by implementation
379 		width	= deMin32(width, eglu::getConfigAttribInt(egl, display, config, EGL_MAX_PBUFFER_WIDTH));
380 		height	= deMin32(height, eglu::getConfigAttribInt(egl, display, config, EGL_MAX_PBUFFER_HEIGHT));
381 
382 		if (width == 0 || height == 0)
383 		{
384 			log << TestLog::Message << "    Fail, maximum pbuffer size of " << width << "x" << height << " reported" << TestLog::EndMessage;
385 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid maximum pbuffer size");
386 			return;
387 		}
388 
389 		const EGLint attribs[] =
390 		{
391 			EGL_WIDTH,			width,
392 			EGL_HEIGHT,			height,
393 			EGL_TEXTURE_FORMAT,	EGL_NO_TEXTURE,
394 			EGL_NONE
395 		};
396 
397 		{
398 			eglu::UniqueSurface surface(egl, display, egl.createPbufferSurface(display, config, attribs));
399 
400 			logCommonSurfaceAttributes	(log, egl, display, *surface);
401 			logPbufferSurfaceAttributes	(log, egl, display, *surface);
402 			checkCommonAttributes		(display, *surface, info);
403 
404 			// Pbuffer-specific attributes
405 
406 			// Largest pbuffer
407 			{
408 				const EGLint	largestPbuffer	= eglu::querySurfaceInt(egl, display, *surface, EGL_LARGEST_PBUFFER);
409 
410 				if (largestPbuffer != EGL_FALSE && largestPbuffer != EGL_TRUE)
411 				{
412 					log << TestLog::Message << "    Fail, invalid largest pbuffer value " << largestPbuffer << TestLog::EndMessage;
413 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid largest pbuffer");
414 				}
415 			}
416 
417 			// Texture format
418 			{
419 				const EGLint	textureFormat	= eglu::querySurfaceInt(egl, display, *surface, EGL_TEXTURE_FORMAT);
420 
421 				if (textureFormat != EGL_NO_TEXTURE && textureFormat != EGL_TEXTURE_RGB && textureFormat != EGL_TEXTURE_RGBA)
422 				{
423 					log << TestLog::Message << "    Fail, invalid texture format value " << textureFormat << TestLog::EndMessage;
424 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid texture format");
425 				}
426 			}
427 
428 			// Texture target
429 			{
430 				const EGLint	textureTarget	= eglu::querySurfaceInt(egl, display, *surface, EGL_TEXTURE_TARGET);
431 
432 				if (textureTarget != EGL_NO_TEXTURE && textureTarget != EGL_TEXTURE_2D)
433 				{
434 					log << TestLog::Message << "    Fail, invalid texture target value " << textureTarget << TestLog::EndMessage;
435 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid texture target");
436 				}
437 			}
438 
439 			// Mipmap texture
440 			{
441 				const EGLint	mipmapTexture	= eglu::querySurfaceInt(egl, display, *surface, EGL_MIPMAP_TEXTURE);
442 
443 				if (mipmapTexture != EGL_FALSE && mipmapTexture != EGL_TRUE)
444 				{
445 					log << TestLog::Message << "    Fail, invalid mipmap texture value " << mipmapTexture << TestLog::EndMessage;
446 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid mipmap texture");
447 				}
448 			}
449 		}
450 	}
451 };
452 
453 class SurfaceAttribCase : public SimpleConfigCase
454 {
455 public:
456 			SurfaceAttribCase	(EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters);
~SurfaceAttribCase(void)457 	virtual	~SurfaceAttribCase	(void) {}
458 
459 	void	testAttributes		(EGLDisplay display, EGLSurface surface, EGLint surfaceType, const ConfigInfo& info);
460 };
461 
SurfaceAttribCase(EglTestContext & eglTestCtx,const char * name,const char * description,const eglu::FilterList & filters)462 SurfaceAttribCase::SurfaceAttribCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters)
463 		: SimpleConfigCase(eglTestCtx, name, description, filters)
464 {
465 }
466 
testAttributes(EGLDisplay display,EGLSurface surface,EGLint surfaceType,const ConfigInfo & info)467 void SurfaceAttribCase::testAttributes (EGLDisplay display, EGLSurface surface, EGLint surfaceType, const ConfigInfo& info)
468 {
469 	const Library&		egl		= m_eglTestCtx.getLibrary();
470 	tcu::TestLog&		log		= m_testCtx.getLog();
471 	const eglu::Version	version	= eglu::getVersion(egl, display);
472 
473 	if (version.getMajor() == 1 && version.getMinor() == 0)
474 	{
475 		log << TestLog::Message << "No attributes can be set in EGL 1.0" << TestLog::EndMessage;
476 		return;
477 	}
478 
479 	// Mipmap level
480 	if (info.renderableType & EGL_OPENGL_ES_BIT || info.renderableType & EGL_OPENGL_ES2_BIT)
481 	{
482 		const EGLint initialValue = 0xDEADBAAD;
483 		EGLint value = initialValue;
484 
485 		EGLU_CHECK_CALL(egl, querySurface(display, surface, EGL_MIPMAP_LEVEL, &value));
486 
487 		logSurfaceAttribute(log, EGL_MIPMAP_LEVEL, value);
488 
489 		if (surfaceType == EGL_PBUFFER_BIT)
490 		{
491 			if (value != 0)
492 			{
493 				log << TestLog::Message << "    Fail, initial mipmap level value should be 0, is " << value << TestLog::EndMessage;
494 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid default mipmap level");
495 			}
496 		}
497 		else if (value != initialValue)
498 		{
499 			log << TestLog::Message << "    Fail, eglQuerySurface changed value when querying EGL_MIPMAP_LEVEL for non-pbuffer surface. Result: " << value << ". Expected: " << initialValue << TestLog::EndMessage;
500 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "EGL_MIPMAP_LEVEL query modified result for non-pbuffer surface.");
501 		}
502 
503 		egl.surfaceAttrib(display, surface, EGL_MIPMAP_LEVEL, 1);
504 
505 		{
506 			const EGLint	error	= egl.getError();
507 
508 			if (error != EGL_SUCCESS)
509 			{
510 				log << TestLog::Message << "    Fail, setting EGL_MIPMAP_LEVEL should not result in an error, received " << eglu::getErrorStr(error) << TestLog::EndMessage;
511 
512 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Illegal error condition");
513 			}
514 		}
515 	}
516 
517 	// Only mipmap level can be set in EGL 1.3 and lower
518 	if (version.getMajor() == 1 && version.getMinor() <= 3) return;
519 
520 	// Multisample resolve
521 	{
522 		const EGLint	value	= eglu::querySurfaceInt(egl, display, surface, EGL_MULTISAMPLE_RESOLVE);
523 
524 		logSurfaceAttribute(log, EGL_MULTISAMPLE_RESOLVE, value);
525 
526 		if (value != EGL_MULTISAMPLE_RESOLVE_DEFAULT)
527 		{
528 			log << TestLog::Message << "    Fail, initial multisample resolve value should be EGL_MULTISAMPLE_RESOLVE_DEFAULT, is "
529 				<< eglu::getSurfaceAttribValueStr(EGL_MULTISAMPLE_RESOLVE, value) << TestLog::EndMessage;
530 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid default multisample resolve");
531 		}
532 
533 		if (info.renderableType & EGL_MULTISAMPLE_RESOLVE_BOX_BIT)
534 		{
535 			log << TestLog::Message << "    Box filter is supported by surface, trying to set." << TestLog::EndMessage;
536 
537 			egl.surfaceAttrib(display, surface, EGL_MULTISAMPLE_RESOLVE, EGL_MULTISAMPLE_RESOLVE_BOX);
538 
539 			if (eglu::querySurfaceInt(egl, display, surface, EGL_MULTISAMPLE_RESOLVE) != EGL_MULTISAMPLE_RESOLVE_BOX)
540 			{
541 				log << TestLog::Message << "    Fail, tried to enable box filter but value did not change.";
542 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to set multisample resolve");
543 			}
544 		}
545 	}
546 
547 	// Swap behavior
548 	{
549 		const EGLint	value	= eglu::querySurfaceInt(egl, display, surface, EGL_SWAP_BEHAVIOR);
550 
551 		logSurfaceAttribute(log, EGL_SWAP_BEHAVIOR, value);
552 
553 		if (info.renderableType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)
554 		{
555 			const EGLint	nextValue	= (value == EGL_BUFFER_DESTROYED) ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED;
556 
557 			egl.surfaceAttrib(display, surface, EGL_SWAP_BEHAVIOR, nextValue);
558 
559 			if (eglu::querySurfaceInt(egl, display, surface, EGL_SWAP_BEHAVIOR) != nextValue)
560 			{
561 				log << TestLog::Message << "  Fail, tried to set swap behavior to " << eglu::getSurfaceAttribStr(nextValue) << TestLog::EndMessage;
562 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to set swap behavior");
563 			}
564 		}
565 	}
566 }
567 
568 class SurfaceAttribWindowCase : public SurfaceAttribCase
569 {
570 public:
SurfaceAttribWindowCase(EglTestContext & eglTestCtx,const char * name,const char * description,const eglu::FilterList & filters)571 	SurfaceAttribWindowCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters)
572 		: SurfaceAttribCase(eglTestCtx, name, description, filters)
573 	{
574 	}
575 
executeForConfig(EGLDisplay display,EGLConfig config)576 	void executeForConfig (EGLDisplay display, EGLConfig config)
577 	{
578 		const Library&						egl				= m_eglTestCtx.getLibrary();
579 		tcu::TestLog&						log				= m_testCtx.getLog();
580 		const int							width			= 64;
581 		const int							height			= 64;
582 		const eglu::NativeWindowFactory&	windowFactory	= eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
583 		ConfigInfo							info;
584 
585 		eglu::queryConfigInfo(egl, display, config, &info);
586 
587 		log << TestLog::Message << "Creating window surface with config ID " << info.configId << TestLog::EndMessage;
588 		EGLU_CHECK_MSG(egl, "before queries");
589 
590 		de::UniquePtr<eglu::NativeWindow>	window	(windowFactory.createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, eglu::WindowParams(width, height, eglu::parseWindowVisibility(m_testCtx.getCommandLine()))));
591 		eglu::UniqueSurface					surface	(egl, display, eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, display, config, DE_NULL));
592 
593 		testAttributes(display, *surface, EGL_WINDOW_BIT, info);
594 	}
595 };
596 
597 class SurfaceAttribPixmapCase : public SurfaceAttribCase
598 {
599 public:
SurfaceAttribPixmapCase(EglTestContext & eglTestCtx,const char * name,const char * description,const eglu::FilterList & filters)600 	SurfaceAttribPixmapCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters)
601 		: SurfaceAttribCase(eglTestCtx, name, description, filters)
602 	{
603 	}
604 
executeForConfig(EGLDisplay display,EGLConfig config)605 	void executeForConfig (EGLDisplay display, EGLConfig config)
606 	{
607 		const Library&						egl				= m_eglTestCtx.getLibrary();
608 		tcu::TestLog&						log				= m_testCtx.getLog();
609 		const int							width			= 64;
610 		const int							height			= 64;
611 		const eglu::NativePixmapFactory&	pixmapFactory	= eglu::selectNativePixmapFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
612 		ConfigInfo							info;
613 
614 		eglu::queryConfigInfo(egl, display, config, &info);
615 
616 		log << TestLog::Message << "Creating pixmap surface with config ID " << info.configId << TestLog::EndMessage;
617 		EGLU_CHECK_MSG(egl, "before queries");
618 
619 		de::UniquePtr<eglu::NativePixmap>	pixmap	(pixmapFactory.createPixmap(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, width, height));
620 		eglu::UniqueSurface					surface	(egl, display, eglu::createPixmapSurface(m_eglTestCtx.getNativeDisplay(), *pixmap, display, config, DE_NULL));
621 
622 		testAttributes(display, *surface, EGL_PIXMAP_BIT, info);
623 	}
624 };
625 
626 class SurfaceAttribPbufferCase : public SurfaceAttribCase
627 {
628 public:
SurfaceAttribPbufferCase(EglTestContext & eglTestCtx,const char * name,const char * description,const eglu::FilterList & filters)629 	SurfaceAttribPbufferCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters)
630 		: SurfaceAttribCase(eglTestCtx, name, description, filters)
631 	{
632 	}
633 
executeForConfig(EGLDisplay display,EGLConfig config)634 	void executeForConfig (EGLDisplay display, EGLConfig config)
635 	{
636 		const Library&	egl		= m_eglTestCtx.getLibrary();
637 		tcu::TestLog&	log		= m_testCtx.getLog();
638 		int				width	= 64;
639 		int				height	= 64;
640 		ConfigInfo		info;
641 
642 		eglu::queryConfigInfo(egl, display, config, &info);
643 
644 		log << TestLog::Message << "Creating pbuffer surface with config ID " << info.configId << TestLog::EndMessage;
645 		EGLU_CHECK_MSG(egl, "before queries");
646 
647 		// Clamp to maximums reported by implementation
648 		width	= deMin32(width, eglu::getConfigAttribInt(egl, display, config, EGL_MAX_PBUFFER_WIDTH));
649 		height	= deMin32(height, eglu::getConfigAttribInt(egl, display, config, EGL_MAX_PBUFFER_HEIGHT));
650 
651 		if (width == 0 || height == 0)
652 		{
653 			log << TestLog::Message << "    Fail, maximum pbuffer size of " << width << "x" << height << " reported" << TestLog::EndMessage;
654 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid maximum pbuffer size");
655 			return;
656 		}
657 
658 		const EGLint attribs[] =
659 		{
660 			EGL_WIDTH,			width,
661 			EGL_HEIGHT,			height,
662 			EGL_TEXTURE_FORMAT,	EGL_NO_TEXTURE,
663 			EGL_NONE
664 		};
665 
666 		eglu::UniqueSurface surface(egl, display, egl.createPbufferSurface(display, config, attribs));
667 
668 		testAttributes(display, *surface, EGL_PBUFFER_BIT, info);
669 	}
670 };
671 
QuerySurfaceTests(EglTestContext & eglTestCtx)672 QuerySurfaceTests::QuerySurfaceTests (EglTestContext& eglTestCtx)
673 	: TestCaseGroup(eglTestCtx, "query_surface", "Surface Query Tests")
674 {
675 }
676 
~QuerySurfaceTests(void)677 QuerySurfaceTests::~QuerySurfaceTests (void)
678 {
679 }
680 
681 template <deUint32 Type>
surfaceType(const eglu::CandidateConfig & c)682 static bool surfaceType (const eglu::CandidateConfig& c)
683 {
684 	return (c.surfaceType() & Type) == Type;
685 }
686 
init(void)687 void QuerySurfaceTests::init (void)
688 {
689 	// Simple queries
690 	{
691 		tcu::TestCaseGroup* simpleGroup = new tcu::TestCaseGroup(m_testCtx, "simple", "Simple queries");
692 		addChild(simpleGroup);
693 
694 		// Window
695 		{
696 			tcu::TestCaseGroup* windowGroup = new tcu::TestCaseGroup(m_testCtx, "window", "Window surfaces");
697 			simpleGroup->addChild(windowGroup);
698 
699 			eglu::FilterList baseFilters;
700 			baseFilters << surfaceType<EGL_WINDOW_BIT>;
701 
702 			std::vector<NamedFilterList> filterLists;
703 			getDefaultFilterLists(filterLists, baseFilters);
704 
705 			for (std::vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
706 				windowGroup->addChild(new QuerySurfaceSimpleWindowCase(m_eglTestCtx, i->getName(), i->getDescription(), *i));
707 		}
708 
709 		// Pixmap
710 		{
711 			tcu::TestCaseGroup* pixmapGroup = new tcu::TestCaseGroup(m_testCtx, "pixmap", "Pixmap surfaces");
712 			simpleGroup->addChild(pixmapGroup);
713 
714 			eglu::FilterList baseFilters;
715 			baseFilters << surfaceType<EGL_PIXMAP_BIT>;
716 
717 			std::vector<NamedFilterList> filterLists;
718 			getDefaultFilterLists(filterLists, baseFilters);
719 
720 			for (std::vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
721 				pixmapGroup->addChild(new QuerySurfaceSimplePixmapCase(m_eglTestCtx, i->getName(), i->getDescription(), *i));
722 		}
723 
724 		// Pbuffer
725 		{
726 			tcu::TestCaseGroup* pbufferGroup = new tcu::TestCaseGroup(m_testCtx, "pbuffer", "Pbuffer surfaces");
727 			simpleGroup->addChild(pbufferGroup);
728 
729 			eglu::FilterList baseFilters;
730 			baseFilters << surfaceType<EGL_PBUFFER_BIT>;
731 
732 			std::vector<NamedFilterList> filterLists;
733 			getDefaultFilterLists(filterLists, baseFilters);
734 
735 			for (std::vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
736 				pbufferGroup->addChild(new QuerySurfaceSimplePbufferCase(m_eglTestCtx, i->getName(), i->getDescription(), *i));
737 		}
738 	}
739 
740 	// Set surface attributes
741 	{
742 		tcu::TestCaseGroup* setAttributeGroup = new tcu::TestCaseGroup(m_testCtx, "set_attribute", "Setting attributes");
743 		addChild(setAttributeGroup);
744 
745 		// Window
746 		{
747 			tcu::TestCaseGroup* windowGroup = new tcu::TestCaseGroup(m_testCtx, "window", "Window surfaces");
748 			setAttributeGroup->addChild(windowGroup);
749 
750 			eglu::FilterList baseFilters;
751 			baseFilters << surfaceType<EGL_WINDOW_BIT>;
752 
753 			std::vector<NamedFilterList> filterLists;
754 			getDefaultFilterLists(filterLists, baseFilters);
755 
756 			for (std::vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
757 				windowGroup->addChild(new SurfaceAttribWindowCase(m_eglTestCtx, i->getName(), i->getDescription(), *i));
758 		}
759 
760 		// Pixmap
761 		{
762 			tcu::TestCaseGroup* pixmapGroup = new tcu::TestCaseGroup(m_testCtx, "pixmap", "Pixmap surfaces");
763 			setAttributeGroup->addChild(pixmapGroup);
764 
765 			eglu::FilterList baseFilters;
766 			baseFilters << surfaceType<EGL_PIXMAP_BIT>;
767 
768 			std::vector<NamedFilterList> filterLists;
769 			getDefaultFilterLists(filterLists, baseFilters);
770 
771 			for (std::vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
772 				pixmapGroup->addChild(new SurfaceAttribPixmapCase(m_eglTestCtx, i->getName(), i->getDescription(), *i));
773 		}
774 
775 		// Pbuffer
776 		{
777 			tcu::TestCaseGroup* pbufferGroup = new tcu::TestCaseGroup(m_testCtx, "pbuffer", "Pbuffer surfaces");
778 			setAttributeGroup->addChild(pbufferGroup);
779 
780 			eglu::FilterList baseFilters;
781 			baseFilters << surfaceType<EGL_PBUFFER_BIT>;
782 
783 			std::vector<NamedFilterList> filterLists;
784 			getDefaultFilterLists(filterLists, baseFilters);
785 
786 			for (std::vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
787 				pbufferGroup->addChild(new SurfaceAttribPbufferCase(m_eglTestCtx, i->getName(), i->getDescription(), *i));
788 		}
789 	}
790 }
791 
792 } // egl
793 } // deqp
794