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 Simple surface construction test.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "teglCreateSurfaceTests.hpp"
25 
26 #include "egluNativeDisplay.hpp"
27 #include "egluNativeWindow.hpp"
28 #include "egluNativePixmap.hpp"
29 #include "egluUtil.hpp"
30 #include "egluUnique.hpp"
31 
32 #include "eglwLibrary.hpp"
33 #include "eglwEnums.hpp"
34 
35 #include "teglSimpleConfigCase.hpp"
36 #include "tcuTestContext.hpp"
37 #include "tcuCommandLine.hpp"
38 #include "tcuTestLog.hpp"
39 
40 #include "deSTLUtil.hpp"
41 #include "deUniquePtr.hpp"
42 
43 #include <memory>
44 
45 namespace deqp
46 {
47 namespace egl
48 {
49 
50 using std::vector;
51 using tcu::TestLog;
52 using namespace eglw;
53 
54 namespace
55 {
56 
checkEGLPlatformSupport(const Library & egl,const char * platformExt)57 void checkEGLPlatformSupport (const Library& egl, const char* platformExt)
58 {
59 	std::vector<std::string> extensions = eglu::getPlatformExtensions(egl);
60 
61 	if (!de::contains(extensions.begin(), extensions.end(), platformExt))
62 		throw tcu::NotSupportedError((std::string("Platform extension '") + platformExt + "' not supported").c_str(), "", __FILE__, __LINE__);
63 }
64 
createWindowSurface(EGLDisplay display,EGLConfig config,eglu::NativeDisplay & nativeDisplay,eglu::NativeWindow & window,bool useLegacyCreate)65 EGLSurface createWindowSurface (EGLDisplay display, EGLConfig config, eglu::NativeDisplay& nativeDisplay, eglu::NativeWindow& window, bool useLegacyCreate)
66 {
67 	const Library&	egl		= nativeDisplay.getLibrary();
68 	EGLSurface		surface	= EGL_NO_SURFACE;
69 
70 	if (useLegacyCreate)
71 	{
72 		surface = egl.createWindowSurface(display, config, window.getLegacyNative(), DE_NULL);
73 		EGLU_CHECK_MSG(egl, "eglCreateWindowSurface() failed");
74 	}
75 	else
76 	{
77 		checkEGLPlatformSupport(egl, nativeDisplay.getPlatformExtensionName());
78 
79 		surface = egl.createPlatformWindowSurfaceEXT(display, config, window.getPlatformNative(), DE_NULL);
80 		EGLU_CHECK_MSG(egl, "eglCreatePlatformWindowSurfaceEXT() failed");
81 	}
82 
83 	return surface;
84 }
85 
createPixmapSurface(EGLDisplay display,EGLConfig config,eglu::NativeDisplay & nativeDisplay,eglu::NativePixmap & pixmap,bool useLegacyCreate)86 EGLSurface createPixmapSurface (EGLDisplay display, EGLConfig config, eglu::NativeDisplay& nativeDisplay, eglu::NativePixmap& pixmap, bool useLegacyCreate)
87 {
88 	const Library&	egl		= nativeDisplay.getLibrary();
89 	EGLSurface		surface	= EGL_NO_SURFACE;
90 
91 	if (useLegacyCreate)
92 	{
93 		surface = egl.createPixmapSurface(display, config, pixmap.getLegacyNative(), DE_NULL);
94 		EGLU_CHECK_MSG(egl, "eglCreatePixmapSurface() failed");
95 	}
96 	else
97 	{
98 		checkEGLPlatformSupport(egl, nativeDisplay.getPlatformExtensionName());
99 
100 		surface = egl.createPlatformPixmapSurfaceEXT(display, config, pixmap.getPlatformNative(), DE_NULL);
101 		EGLU_CHECK_MSG(egl, "eglCreatePlatformPixmapSurfaceEXT() failed");
102 	}
103 
104 	return surface;
105 }
106 
107 class CreateWindowSurfaceCase : public SimpleConfigCase
108 {
109 public:
CreateWindowSurfaceCase(EglTestContext & eglTestCtx,const char * name,const char * description,bool useLegacyCreate,const eglu::FilterList & filters)110 	CreateWindowSurfaceCase (EglTestContext& eglTestCtx, const char* name, const char* description, bool useLegacyCreate, const eglu::FilterList& filters)
111 		: SimpleConfigCase	(eglTestCtx, name, description, filters)
112 		, m_useLegacyCreate	(useLegacyCreate)
113 	{
114 	}
115 
executeForConfig(EGLDisplay display,EGLConfig config)116 	void executeForConfig (EGLDisplay display, EGLConfig config)
117 	{
118 		const Library&						egl				= m_eglTestCtx.getLibrary();
119 		TestLog&							log				= m_testCtx.getLog();
120 		EGLint								id				= eglu::getConfigID(egl, display, config);
121 		const eglu::NativeWindowFactory&	windowFactory	= eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
122 
123 		// \todo [2011-03-23 pyry] Iterate thru all possible combinations of EGL_RENDER_BUFFER, EGL_VG_COLORSPACE and EGL_VG_ALPHA_FORMAT
124 
125 		if (m_useLegacyCreate)
126 		{
127 			if ((windowFactory.getCapabilities() & eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY) == 0)
128 				TCU_THROW(NotSupportedError, "Native window doesn't support legacy eglCreateWindowSurface()");
129 		}
130 		else
131 		{
132 			if ((windowFactory.getCapabilities() & eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_PLATFORM) == 0)
133 				TCU_THROW(NotSupportedError, "Native window doesn't support eglCreatePlatformWindowSurfaceEXT()");
134 		}
135 
136 		log << TestLog::Message << "Creating window surface with config ID " << id << TestLog::EndMessage;
137 		EGLU_CHECK_MSG(egl, "init");
138 
139 		{
140 			const int							width			= 64;
141 			const int							height			= 64;
142 			de::UniquePtr<eglu::NativeWindow>	window			(windowFactory.createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, eglu::WindowParams(width, height, eglu::parseWindowVisibility(m_testCtx.getCommandLine()))));
143 			eglu::UniqueSurface					surface			(egl, display, createWindowSurface(display, config, m_eglTestCtx.getNativeDisplay(), *window, m_useLegacyCreate));
144 
145 			EGLint								windowWidth		= 0;
146 			EGLint								windowHeight	= 0;
147 
148 			EGLU_CHECK_CALL(egl, querySurface(display, *surface, EGL_WIDTH,		&windowWidth));
149 			EGLU_CHECK_CALL(egl, querySurface(display, *surface, EGL_HEIGHT,	&windowHeight));
150 
151 			if (windowWidth <= 0 || windowHeight <= 0)
152 			{
153 				log << TestLog::Message << "  Fail, invalid surface size " << windowWidth << "x" << windowHeight << TestLog::EndMessage;
154 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid surface size");
155 			}
156 			else
157 				log << TestLog::Message << "  Pass" << TestLog::EndMessage;
158 		}
159 	}
160 
161 private:
162 	bool	m_useLegacyCreate;
163 };
164 
165 class CreatePixmapSurfaceCase : public SimpleConfigCase
166 {
167 public:
CreatePixmapSurfaceCase(EglTestContext & eglTestCtx,const char * name,const char * description,bool useLegacyCreate,const eglu::FilterList & filters)168 	CreatePixmapSurfaceCase (EglTestContext& eglTestCtx, const char* name, const char* description, bool useLegacyCreate, const eglu::FilterList& filters)
169 		: SimpleConfigCase(eglTestCtx, name, description, filters)
170 		, m_useLegacyCreate	(useLegacyCreate)
171 	{
172 	}
173 
executeForConfig(EGLDisplay display,EGLConfig config)174 	void executeForConfig (EGLDisplay display, EGLConfig config)
175 	{
176 		const Library&						egl				= m_eglTestCtx.getLibrary();
177 		TestLog&							log				= m_testCtx.getLog();
178 		EGLint								id				= eglu::getConfigID(egl, display, config);
179 		const eglu::NativePixmapFactory&	pixmapFactory	= eglu::selectNativePixmapFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
180 
181 		// \todo [2011-03-23 pyry] Iterate thru all possible combinations of EGL_RENDER_BUFFER, EGL_VG_COLORSPACE and EGL_VG_ALPHA_FORMAT
182 
183 		if (m_useLegacyCreate)
184 		{
185 			if ((pixmapFactory.getCapabilities() & eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY) == 0)
186 				TCU_THROW(NotSupportedError, "Native pixmap doesn't support legacy eglCreatePixmapSurface()");
187 		}
188 		else
189 		{
190 			if ((pixmapFactory.getCapabilities() & eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_PLATFORM) == 0)
191 				TCU_THROW(NotSupportedError, "Native pixmap doesn't support eglCreatePlatformPixmapSurfaceEXT()");
192 		}
193 
194 		log << TestLog::Message << "Creating pixmap surface with config ID " << id << TestLog::EndMessage;
195 		EGLU_CHECK_MSG(egl, "init");
196 
197 		{
198 			const int							width			= 64;
199 			const int							height			= 64;
200 			de::UniquePtr<eglu::NativePixmap>	pixmap			(pixmapFactory.createPixmap(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, width, height));
201 			eglu::UniqueSurface					surface			(egl, display, createPixmapSurface(display, config, m_eglTestCtx.getNativeDisplay(), *pixmap, m_useLegacyCreate));
202 			EGLint								pixmapWidth		= 0;
203 			EGLint								pixmapHeight	= 0;
204 
205 			EGLU_CHECK_CALL(egl, querySurface(display, *surface, EGL_WIDTH,		&pixmapWidth));
206 			EGLU_CHECK_CALL(egl, querySurface(display, *surface, EGL_HEIGHT,	&pixmapHeight));
207 
208 			if (pixmapWidth <= 0 || pixmapHeight <= 0)
209 			{
210 				log << TestLog::Message << "  Fail, invalid surface size " << pixmapWidth << "x" << pixmapHeight << TestLog::EndMessage;
211 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid surface size");
212 			}
213 			else
214 				log << TestLog::Message << "  Pass" << TestLog::EndMessage;
215 		}
216 	}
217 
218 private:
219 	bool	m_useLegacyCreate;
220 };
221 
222 class CreatePbufferSurfaceCase : public SimpleConfigCase
223 {
224 public:
CreatePbufferSurfaceCase(EglTestContext & eglTestCtx,const char * name,const char * description,const eglu::FilterList & filters)225 	CreatePbufferSurfaceCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters)
226 		: SimpleConfigCase(eglTestCtx, name, description, filters)
227 	{
228 	}
229 
executeForConfig(EGLDisplay display,EGLConfig config)230 	void executeForConfig (EGLDisplay display, EGLConfig config)
231 	{
232 		const Library&	egl		= m_eglTestCtx.getLibrary();
233 		TestLog&		log		= m_testCtx.getLog();
234 		EGLint			id		= eglu::getConfigID(egl, display, config);
235 		int				width	= 64;
236 		int				height	= 64;
237 
238 		// \todo [2011-03-23 pyry] Iterate thru all possible combinations of EGL_RENDER_BUFFER, EGL_VG_COLORSPACE and EGL_VG_ALPHA_FORMAT
239 
240 		log << TestLog::Message << "Creating pbuffer surface with config ID " << id << TestLog::EndMessage;
241 		EGLU_CHECK_MSG(egl, "init");
242 
243 		// Clamp to maximums reported by implementation
244 		width	= deMin32(width, eglu::getConfigAttribInt(egl, display, config, EGL_MAX_PBUFFER_WIDTH));
245 		height	= deMin32(height, eglu::getConfigAttribInt(egl, display, config, EGL_MAX_PBUFFER_HEIGHT));
246 
247 		if (width == 0 || height == 0)
248 		{
249 			log << TestLog::Message << "  Fail, maximum pbuffer size of " << width << "x" << height << " reported" << TestLog::EndMessage;
250 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid maximum pbuffer size");
251 			return;
252 		}
253 
254 		// \todo [2011-03-23 pyry] Texture-backed variants!
255 
256 		const EGLint attribs[] =
257 		{
258 			EGL_WIDTH,			width,
259 			EGL_HEIGHT,			height,
260 			EGL_TEXTURE_FORMAT,	EGL_NO_TEXTURE,
261 			EGL_NONE
262 		};
263 
264 		EGLSurface surface = egl.createPbufferSurface(display, config, attribs);
265 		EGLU_CHECK_MSG(egl, "Failed to create pbuffer");
266 		TCU_CHECK(surface != EGL_NO_SURFACE);
267 		egl.destroySurface(display, surface);
268 
269 		log << TestLog::Message << "  Pass" << TestLog::EndMessage;
270 	}
271 };
272 
273 } // anonymous
274 
CreateSurfaceTests(EglTestContext & eglTestCtx)275 CreateSurfaceTests::CreateSurfaceTests (EglTestContext& eglTestCtx)
276 	: TestCaseGroup(eglTestCtx, "create_surface", "Basic surface construction tests")
277 {
278 }
279 
~CreateSurfaceTests(void)280 CreateSurfaceTests::~CreateSurfaceTests (void)
281 {
282 }
283 
284 template <deUint32 Type>
surfaceType(const eglu::CandidateConfig & c)285 static bool surfaceType (const eglu::CandidateConfig& c)
286 {
287 	return (c.surfaceType() & Type) == Type;
288 }
289 
init(void)290 void CreateSurfaceTests::init (void)
291 {
292 	// Window surfaces
293 	{
294 		tcu::TestCaseGroup* windowGroup = new tcu::TestCaseGroup(m_testCtx, "window", "Window surfaces");
295 		addChild(windowGroup);
296 
297 		eglu::FilterList baseFilters;
298 		baseFilters << surfaceType<EGL_WINDOW_BIT>;
299 
300 		vector<NamedFilterList> filterLists;
301 		getDefaultFilterLists(filterLists, baseFilters);
302 
303 		for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
304 			windowGroup->addChild(new CreateWindowSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), true, *i));
305 	}
306 
307 	// Pixmap surfaces
308 	{
309 		tcu::TestCaseGroup* pixmapGroup = new tcu::TestCaseGroup(m_testCtx, "pixmap", "Pixmap surfaces");
310 		addChild(pixmapGroup);
311 
312 		eglu::FilterList baseFilters;
313 		baseFilters << surfaceType<EGL_PIXMAP_BIT>;
314 
315 		vector<NamedFilterList> filterLists;
316 		getDefaultFilterLists(filterLists, baseFilters);
317 
318 		for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
319 			pixmapGroup->addChild(new CreatePixmapSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), true, *i));
320 	}
321 
322 	// Pbuffer surfaces
323 	{
324 		tcu::TestCaseGroup* pbufferGroup = new tcu::TestCaseGroup(m_testCtx, "pbuffer", "Pbuffer surfaces");
325 		addChild(pbufferGroup);
326 
327 		eglu::FilterList baseFilters;
328 		baseFilters << surfaceType<EGL_PBUFFER_BIT>;
329 
330 		vector<NamedFilterList> filterLists;
331 		getDefaultFilterLists(filterLists, baseFilters);
332 
333 		for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
334 			pbufferGroup->addChild(new CreatePbufferSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), *i));
335 	}
336 
337 	// Window surfaces with new platform extension
338 	{
339 		tcu::TestCaseGroup* windowGroup = new tcu::TestCaseGroup(m_testCtx, "platform_window", "Window surfaces with platform extension");
340 		addChild(windowGroup);
341 
342 		eglu::FilterList baseFilters;
343 		baseFilters << surfaceType<EGL_WINDOW_BIT>;
344 
345 		vector<NamedFilterList> filterLists;
346 		getDefaultFilterLists(filterLists, baseFilters);
347 
348 		for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
349 			windowGroup->addChild(new CreateWindowSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), false, *i));
350 	}
351 
352 	// Pixmap surfaces with new platform extension
353 	{
354 		tcu::TestCaseGroup* pixmapGroup = new tcu::TestCaseGroup(m_testCtx, "platform_pixmap", "Pixmap surfaces with platform extension");
355 		addChild(pixmapGroup);
356 
357 		eglu::FilterList baseFilters;
358 		baseFilters << surfaceType<EGL_PIXMAP_BIT>;
359 
360 		vector<NamedFilterList> filterLists;
361 		getDefaultFilterLists(filterLists, baseFilters);
362 
363 		for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
364 			pixmapGroup->addChild(new CreatePixmapSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), false, *i));
365 	}
366 }
367 
368 } // egl
369 } // deqp
370