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 "deStringUtil.hpp"
41 #include "deSTLUtil.hpp"
42 #include "deUniquePtr.hpp"
43
44 #include <memory>
45
46 namespace deqp
47 {
48 namespace egl
49 {
50
51 using std::vector;
52 using tcu::TestLog;
53 using namespace eglw;
54
55 namespace
56 {
57
58 #define EGL_MAKE_VERSION(major, minor) (((major) << 12) | (minor))
59
60 enum ApiType
61 {
62 LEGACY,
63 EXTENSION,
64 EGL15
65 };
66
checkEGLPlatformSupport(const Library & egl)67 void checkEGLPlatformSupport(const Library &egl)
68 {
69 const vector<std::string> extensions = eglu::getClientExtensions(egl);
70 if (!de::contains(extensions.begin(), extensions.end(), "EGL_EXT_platform_base"))
71 throw tcu::NotSupportedError("Platform extension 'EGL_EXT_platform_base' not supported", "", __FILE__,
72 __LINE__);
73 }
74
checkEGL15Support(const Library & egl,EGLDisplay display)75 void checkEGL15Support(const Library &egl, EGLDisplay display)
76 {
77 // The EGL_VERSION string is laid out as follows:
78 // major_version.minor_version space vendor_specific_info
79 // Split version from vendor_specific_info
80 std::vector<std::string> tokens = de::splitString(egl.queryString(display, EGL_VERSION), ' ');
81 // split version into major & minor
82 std::vector<std::string> values = de::splitString(tokens[0], '.');
83 EGLint eglVersion = EGL_MAKE_VERSION(atoi(values[0].c_str()), atoi(values[1].c_str()));
84 if (eglVersion < EGL_MAKE_VERSION(1, 5))
85 throw tcu::NotSupportedError("EGL 1.5 not supported", "", __FILE__, __LINE__);
86 }
87
createWindowSurface(EGLDisplay display,EGLConfig config,eglu::NativeDisplay & nativeDisplay,eglu::NativeWindow & window,ApiType createType)88 EGLSurface createWindowSurface(EGLDisplay display, EGLConfig config, eglu::NativeDisplay &nativeDisplay,
89 eglu::NativeWindow &window, ApiType createType)
90 {
91 const Library &egl = nativeDisplay.getLibrary();
92 EGLSurface surface = EGL_NO_SURFACE;
93
94 switch (createType)
95 {
96 case LEGACY:
97 {
98 surface = egl.createWindowSurface(display, config, window.getLegacyNative(), DE_NULL);
99 EGLU_CHECK_MSG(egl, "eglCreateWindowSurface() failed");
100 }
101 break;
102 case EXTENSION:
103 {
104 checkEGLPlatformSupport(egl);
105 void *nativeWindow = window.getPlatformExtension();
106 surface = egl.createPlatformWindowSurfaceEXT(display, config, nativeWindow, DE_NULL);
107 EGLU_CHECK_MSG(egl, "eglCreatePlatformWindowSurfaceEXT() failed");
108 }
109 break;
110 case EGL15:
111 {
112 checkEGL15Support(egl, display);
113 surface = egl.createPlatformWindowSurface(display, config, window.getPlatformNative(), DE_NULL);
114 EGLU_CHECK_MSG(egl, "eglCreatePlatformWindowSurface() failed");
115 }
116 }
117
118 return surface;
119 }
120
createPixmapSurface(EGLDisplay display,EGLConfig config,eglu::NativeDisplay & nativeDisplay,eglu::NativePixmap & pixmap,ApiType createType)121 EGLSurface createPixmapSurface(EGLDisplay display, EGLConfig config, eglu::NativeDisplay &nativeDisplay,
122 eglu::NativePixmap &pixmap, ApiType createType)
123 {
124 const Library &egl = nativeDisplay.getLibrary();
125 EGLSurface surface = EGL_NO_SURFACE;
126
127 switch (createType)
128 {
129 case LEGACY:
130 surface = egl.createPixmapSurface(display, config, pixmap.getLegacyNative(), DE_NULL);
131 EGLU_CHECK_MSG(egl, "eglCreatePixmapSurface() failed");
132 break;
133 case EXTENSION:
134 checkEGLPlatformSupport(egl);
135 surface = egl.createPlatformPixmapSurfaceEXT(display, config, pixmap.getPlatformExtension(), DE_NULL);
136 EGLU_CHECK_MSG(egl, "eglCreatePlatformPixmapSurfaceEXT() failed");
137 break;
138 case EGL15:
139 checkEGL15Support(egl, display);
140 surface = egl.createPlatformPixmapSurface(display, config, pixmap.getPlatformNative(), DE_NULL);
141 EGLU_CHECK_MSG(egl, "eglCreatePlatformPixmapSurface() failed");
142 break;
143 }
144
145 return surface;
146 }
147
148 class CreateWindowSurfaceCase : public SimpleConfigCase
149 {
150 public:
CreateWindowSurfaceCase(EglTestContext & eglTestCtx,const char * name,const char * description,ApiType createType,const eglu::FilterList & filters)151 CreateWindowSurfaceCase(EglTestContext &eglTestCtx, const char *name, const char *description, ApiType createType,
152 const eglu::FilterList &filters)
153 : SimpleConfigCase(eglTestCtx, name, description, filters)
154 , m_createType(createType)
155 {
156 }
157
executeForConfig(EGLDisplay display,EGLConfig config)158 void executeForConfig(EGLDisplay display, EGLConfig config)
159 {
160 const Library &egl = m_eglTestCtx.getLibrary();
161 TestLog &log = m_testCtx.getLog();
162 EGLint id = eglu::getConfigID(egl, display, config);
163 const eglu::NativeWindowFactory &windowFactory =
164 eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
165
166 // \todo [2011-03-23 pyry] Iterate thru all possible combinations of EGL_RENDER_BUFFER, EGL_VG_COLORSPACE and EGL_VG_ALPHA_FORMAT
167
168 switch (m_createType)
169 {
170 case LEGACY:
171 {
172 if ((windowFactory.getCapabilities() & eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY) == 0)
173 TCU_THROW(NotSupportedError, "Native window doesn't support legacy eglCreateWindowSurface()");
174 }
175 break;
176 case EXTENSION:
177 {
178 if ((windowFactory.getCapabilities() & eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_PLATFORM_EXTENSION) ==
179 0)
180 TCU_THROW(NotSupportedError, "Native window doesn't support eglCreatePlatformWindowSurfaceEXT()");
181 }
182 break;
183 case EGL15:
184 {
185 if ((windowFactory.getCapabilities() & eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_PLATFORM) == 0)
186 TCU_THROW(NotSupportedError, "Native window doesn't support eglCreatePlatformWindowSurface()");
187 }
188 break;
189 }
190
191 log << TestLog::Message << "Creating window surface with config ID " << id << TestLog::EndMessage;
192 EGLU_CHECK_MSG(egl, "init");
193
194 {
195 const int width = 64;
196 const int height = 64;
197 de::UniquePtr<eglu::NativeWindow> window(windowFactory.createWindow(
198 &m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL,
199 eglu::WindowParams(width, height, eglu::parseWindowVisibility(m_testCtx.getCommandLine()))));
200 eglu::UniqueSurface surface(
201 egl, display,
202 createWindowSurface(display, config, m_eglTestCtx.getNativeDisplay(), *window, m_createType));
203
204 EGLint windowWidth = 0;
205 EGLint windowHeight = 0;
206
207 EGLU_CHECK_CALL(egl, querySurface(display, *surface, EGL_WIDTH, &windowWidth));
208 EGLU_CHECK_CALL(egl, querySurface(display, *surface, EGL_HEIGHT, &windowHeight));
209
210 if (windowWidth <= 0 || windowHeight <= 0)
211 {
212 log << TestLog::Message << " Fail, invalid surface size " << windowWidth << "x" << windowHeight
213 << TestLog::EndMessage;
214 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid surface size");
215 }
216 else
217 log << TestLog::Message << " Pass" << TestLog::EndMessage;
218 }
219 }
220
221 private:
222 ApiType m_createType;
223 };
224
225 class CreatePixmapSurfaceCase : public SimpleConfigCase
226 {
227 public:
CreatePixmapSurfaceCase(EglTestContext & eglTestCtx,const char * name,const char * description,ApiType createType,const eglu::FilterList & filters)228 CreatePixmapSurfaceCase(EglTestContext &eglTestCtx, const char *name, const char *description, ApiType createType,
229 const eglu::FilterList &filters)
230 : SimpleConfigCase(eglTestCtx, name, description, filters)
231 , m_createType(createType)
232 {
233 }
234
executeForConfig(EGLDisplay display,EGLConfig config)235 void executeForConfig(EGLDisplay display, EGLConfig config)
236 {
237 const Library &egl = m_eglTestCtx.getLibrary();
238 TestLog &log = m_testCtx.getLog();
239 EGLint id = eglu::getConfigID(egl, display, config);
240 const eglu::NativePixmapFactory &pixmapFactory =
241 eglu::selectNativePixmapFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
242
243 // \todo [2011-03-23 pyry] Iterate thru all possible combinations of EGL_RENDER_BUFFER, EGL_VG_COLORSPACE and EGL_VG_ALPHA_FORMAT
244
245 switch (m_createType)
246 {
247 case LEGACY:
248 {
249 if ((pixmapFactory.getCapabilities() & eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY) == 0)
250 TCU_THROW(NotSupportedError, "Native pixmap doesn't support legacy eglCreatePixmapSurface()");
251 }
252 break;
253 case EXTENSION:
254 {
255 if ((pixmapFactory.getCapabilities() & eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_PLATFORM_EXTENSION) ==
256 0)
257 TCU_THROW(NotSupportedError, "Native pixmap doesn't support eglCreatePlatformPixmapSurfaceEXT()");
258 }
259 break;
260 case EGL15:
261 {
262 if ((pixmapFactory.getCapabilities() & eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_PLATFORM) == 0)
263 TCU_THROW(NotSupportedError, "Native pixmap doesn't support eglCreatePlatformPixmapSurface()");
264 }
265 break;
266 }
267
268 log << TestLog::Message << "Creating pixmap surface with config ID " << id << TestLog::EndMessage;
269 EGLU_CHECK_MSG(egl, "init");
270
271 {
272 const int width = 64;
273 const int height = 64;
274 de::UniquePtr<eglu::NativePixmap> pixmap(
275 pixmapFactory.createPixmap(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, width, height));
276 eglu::UniqueSurface surface(
277 egl, display,
278 createPixmapSurface(display, config, m_eglTestCtx.getNativeDisplay(), *pixmap, m_createType));
279 EGLint pixmapWidth = 0;
280 EGLint pixmapHeight = 0;
281
282 EGLU_CHECK_CALL(egl, querySurface(display, *surface, EGL_WIDTH, &pixmapWidth));
283 EGLU_CHECK_CALL(egl, querySurface(display, *surface, EGL_HEIGHT, &pixmapHeight));
284
285 if (pixmapWidth <= 0 || pixmapHeight <= 0)
286 {
287 log << TestLog::Message << " Fail, invalid surface size " << pixmapWidth << "x" << pixmapHeight
288 << TestLog::EndMessage;
289 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid surface size");
290 }
291 else
292 log << TestLog::Message << " Pass" << TestLog::EndMessage;
293 }
294 }
295
296 private:
297 ApiType m_createType;
298 };
299
300 class CreatePbufferSurfaceCase : public SimpleConfigCase
301 {
302 public:
CreatePbufferSurfaceCase(EglTestContext & eglTestCtx,const char * name,const char * description,const eglu::FilterList & filters)303 CreatePbufferSurfaceCase(EglTestContext &eglTestCtx, const char *name, const char *description,
304 const eglu::FilterList &filters)
305 : SimpleConfigCase(eglTestCtx, name, description, filters)
306 {
307 }
308
executeForConfig(EGLDisplay display,EGLConfig config)309 void executeForConfig(EGLDisplay display, EGLConfig config)
310 {
311 const Library &egl = m_eglTestCtx.getLibrary();
312 TestLog &log = m_testCtx.getLog();
313 EGLint id = eglu::getConfigID(egl, display, config);
314 int width = 64;
315 int height = 64;
316
317 // \todo [2011-03-23 pyry] Iterate thru all possible combinations of EGL_RENDER_BUFFER, EGL_VG_COLORSPACE and EGL_VG_ALPHA_FORMAT
318
319 log << TestLog::Message << "Creating pbuffer surface with config ID " << id << TestLog::EndMessage;
320 EGLU_CHECK_MSG(egl, "init");
321
322 // Clamp to maximums reported by implementation
323 width = deMin32(width, eglu::getConfigAttribInt(egl, display, config, EGL_MAX_PBUFFER_WIDTH));
324 height = deMin32(height, eglu::getConfigAttribInt(egl, display, config, EGL_MAX_PBUFFER_HEIGHT));
325
326 if (width == 0 || height == 0)
327 {
328 log << TestLog::Message << " Fail, maximum pbuffer size of " << width << "x" << height << " reported"
329 << TestLog::EndMessage;
330 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid maximum pbuffer size");
331 return;
332 }
333
334 // \todo [2011-03-23 pyry] Texture-backed variants!
335
336 const EGLint attribs[] = {EGL_WIDTH, width, EGL_HEIGHT, height, EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE, EGL_NONE};
337
338 EGLSurface surface = egl.createPbufferSurface(display, config, attribs);
339 EGLU_CHECK_MSG(egl, "Failed to create pbuffer");
340 TCU_CHECK(surface != EGL_NO_SURFACE);
341 egl.destroySurface(display, surface);
342
343 log << TestLog::Message << " Pass" << TestLog::EndMessage;
344 }
345 };
346
347 } // namespace
348
CreateSurfaceTests(EglTestContext & eglTestCtx)349 CreateSurfaceTests::CreateSurfaceTests(EglTestContext &eglTestCtx)
350 : TestCaseGroup(eglTestCtx, "create_surface", "Basic surface construction tests")
351 {
352 }
353
~CreateSurfaceTests(void)354 CreateSurfaceTests::~CreateSurfaceTests(void)
355 {
356 }
357
358 template <uint32_t Type>
surfaceType(const eglu::CandidateConfig & c)359 static bool surfaceType(const eglu::CandidateConfig &c)
360 {
361 return (c.surfaceType() & Type) == Type;
362 }
363
init(void)364 void CreateSurfaceTests::init(void)
365 {
366 // Window surfaces
367 {
368 tcu::TestCaseGroup *windowGroup = new tcu::TestCaseGroup(m_testCtx, "window", "Window surfaces");
369 addChild(windowGroup);
370
371 eglu::FilterList baseFilters;
372 baseFilters << surfaceType<EGL_WINDOW_BIT>;
373
374 vector<NamedFilterList> filterLists;
375 getDefaultFilterLists(filterLists, baseFilters);
376
377 for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
378 windowGroup->addChild(
379 new CreateWindowSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), LEGACY, *i));
380 }
381
382 // Pixmap surfaces
383 {
384 tcu::TestCaseGroup *pixmapGroup = new tcu::TestCaseGroup(m_testCtx, "pixmap", "Pixmap surfaces");
385 addChild(pixmapGroup);
386
387 eglu::FilterList baseFilters;
388 baseFilters << surfaceType<EGL_PIXMAP_BIT>;
389
390 vector<NamedFilterList> filterLists;
391 getDefaultFilterLists(filterLists, baseFilters);
392
393 for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
394 pixmapGroup->addChild(
395 new CreatePixmapSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), LEGACY, *i));
396 }
397
398 // Pbuffer surfaces
399 {
400 tcu::TestCaseGroup *pbufferGroup = new tcu::TestCaseGroup(m_testCtx, "pbuffer", "Pbuffer surfaces");
401 addChild(pbufferGroup);
402
403 eglu::FilterList baseFilters;
404 baseFilters << surfaceType<EGL_PBUFFER_BIT>;
405
406 vector<NamedFilterList> filterLists;
407 getDefaultFilterLists(filterLists, baseFilters);
408
409 for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
410 pbufferGroup->addChild(new CreatePbufferSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), *i));
411 }
412
413 // Window surfaces with new platform extension
414 {
415 tcu::TestCaseGroup *windowGroup =
416 new tcu::TestCaseGroup(m_testCtx, "platform_ext_window", "Window surfaces with platform extension");
417 addChild(windowGroup);
418
419 eglu::FilterList baseFilters;
420 baseFilters << surfaceType<EGL_WINDOW_BIT>;
421
422 vector<NamedFilterList> filterLists;
423 getDefaultFilterLists(filterLists, baseFilters);
424
425 for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
426 windowGroup->addChild(
427 new CreateWindowSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), EXTENSION, *i));
428 }
429
430 // Pixmap surfaces with new platform extension
431 {
432 tcu::TestCaseGroup *pixmapGroup =
433 new tcu::TestCaseGroup(m_testCtx, "platform_ext_pixmap", "Pixmap surfaces with platform extension");
434 addChild(pixmapGroup);
435
436 eglu::FilterList baseFilters;
437 baseFilters << surfaceType<EGL_PIXMAP_BIT>;
438
439 vector<NamedFilterList> filterLists;
440 getDefaultFilterLists(filterLists, baseFilters);
441
442 for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
443 pixmapGroup->addChild(
444 new CreatePixmapSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), EXTENSION, *i));
445 }
446 //
447 // Window surfaces with EGL 1.5 CreateWindowSurface
448 {
449 tcu::TestCaseGroup *windowGroup =
450 new tcu::TestCaseGroup(m_testCtx, "platform_window", "Window surfaces with EGL 1.5");
451 addChild(windowGroup);
452
453 eglu::FilterList baseFilters;
454 baseFilters << surfaceType<EGL_WINDOW_BIT>;
455
456 vector<NamedFilterList> filterLists;
457 getDefaultFilterLists(filterLists, baseFilters);
458
459 for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
460 windowGroup->addChild(
461 new CreateWindowSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), EGL15, *i));
462 }
463
464 // Pixmap surfaces with EGL 1.5 CreateWindowSurface
465 {
466 tcu::TestCaseGroup *pixmapGroup =
467 new tcu::TestCaseGroup(m_testCtx, "platform_pixmap", "Pixmap surfaces with EGL 1.5");
468 addChild(pixmapGroup);
469
470 eglu::FilterList baseFilters;
471 baseFilters << surfaceType<EGL_PIXMAP_BIT>;
472
473 vector<NamedFilterList> filterLists;
474 getDefaultFilterLists(filterLists, baseFilters);
475
476 for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
477 pixmapGroup->addChild(
478 new CreatePixmapSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), EGL15, *i));
479 }
480 }
481
482 } // namespace egl
483 } // namespace deqp
484