xref: /aosp_15_r20/external/deqp/modules/egl/teglNativeCoordMappingTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 Tests for mapping client coordinates to native surface coordinates
22  *//*--------------------------------------------------------------------*/
23 
24 #include "teglNativeCoordMappingTests.hpp"
25 
26 #include "teglSimpleConfigCase.hpp"
27 
28 #include "tcuSurface.hpp"
29 #include "tcuTexture.hpp"
30 
31 #include "egluNativeDisplay.hpp"
32 #include "egluNativeWindow.hpp"
33 #include "egluNativePixmap.hpp"
34 #include "egluUnique.hpp"
35 #include "egluUtil.hpp"
36 
37 #include "eglwLibrary.hpp"
38 #include "eglwEnums.hpp"
39 
40 #include "gluDefs.hpp"
41 #include "glwFunctions.hpp"
42 #include "glwEnums.hpp"
43 
44 #include "tcuImageCompare.hpp"
45 #include "tcuTestLog.hpp"
46 #include "tcuTexture.hpp"
47 #include "tcuTextureUtil.hpp"
48 
49 #include "deUniquePtr.hpp"
50 #include "deStringUtil.hpp"
51 
52 #include "deThread.hpp"
53 #include "deMath.h"
54 
55 #include <vector>
56 #include <string>
57 
58 using std::string;
59 using std::vector;
60 using tcu::TestLog;
61 
62 using namespace eglw;
63 
64 namespace deqp
65 {
66 namespace egl
67 {
68 namespace
69 {
70 
createGLES2Context(const Library & egl,EGLDisplay display,EGLConfig config)71 EGLContext createGLES2Context(const Library &egl, EGLDisplay display, EGLConfig config)
72 {
73     EGLContext context        = EGL_NO_CONTEXT;
74     const EGLint attribList[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
75 
76     EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
77 
78     context = egl.createContext(display, config, EGL_NO_CONTEXT, attribList);
79     EGLU_CHECK_MSG(egl, "eglCreateContext() failed");
80     TCU_CHECK(context);
81 
82     return context;
83 }
84 
createGLES2Program(const glw::Functions & gl,TestLog & log)85 uint32_t createGLES2Program(const glw::Functions &gl, TestLog &log)
86 {
87     const char *const vertexShaderSource = "attribute highp vec2 a_pos;\n"
88                                            "void main (void)\n"
89                                            "{\n"
90                                            "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
91                                            "}";
92 
93     const char *const fragmentShaderSource = "void main (void)\n"
94                                              "{\n"
95                                              "\tgl_FragColor = vec4(1.0);\n"
96                                              "}";
97 
98     uint32_t program        = 0;
99     uint32_t vertexShader   = 0;
100     uint32_t fragmentShader = 0;
101 
102     int32_t vertexCompileStatus;
103     string vertexInfoLog;
104     int32_t fragmentCompileStatus;
105     string fragmentInfoLog;
106     int32_t linkStatus;
107     string programInfoLog;
108 
109     try
110     {
111         program        = gl.createProgram();
112         vertexShader   = gl.createShader(GL_VERTEX_SHADER);
113         fragmentShader = gl.createShader(GL_FRAGMENT_SHADER);
114 
115         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create shaders and program");
116 
117         gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL);
118         gl.compileShader(vertexShader);
119         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup vertex shader");
120 
121         gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL);
122         gl.compileShader(fragmentShader);
123         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup fragment shader");
124 
125         {
126             int32_t infoLogLength = 0;
127 
128             gl.getShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexCompileStatus);
129             gl.getShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength);
130 
131             vertexInfoLog.resize(infoLogLength, '\0');
132 
133             gl.getShaderInfoLog(vertexShader, (glw::GLsizei)vertexInfoLog.length(), &infoLogLength,
134                                 &(vertexInfoLog[0]));
135             GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get vertex shader compile info");
136 
137             vertexInfoLog.resize(infoLogLength);
138         }
139 
140         {
141             int32_t infoLogLength = 0;
142 
143             gl.getShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentCompileStatus);
144             gl.getShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLength);
145 
146             fragmentInfoLog.resize(infoLogLength, '\0');
147 
148             gl.getShaderInfoLog(fragmentShader, (glw::GLsizei)fragmentInfoLog.length(), &infoLogLength,
149                                 &(fragmentInfoLog[0]));
150             GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get fragment shader compile info");
151 
152             fragmentInfoLog.resize(infoLogLength);
153         }
154 
155         gl.attachShader(program, vertexShader);
156         gl.attachShader(program, fragmentShader);
157         gl.linkProgram(program);
158         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup program");
159 
160         {
161             int32_t infoLogLength = 0;
162 
163             gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus);
164             gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
165 
166             programInfoLog.resize(infoLogLength, '\0');
167 
168             gl.getProgramInfoLog(program, (glw::GLsizei)programInfoLog.length(), &infoLogLength, &(programInfoLog[0]));
169             GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get program link info");
170 
171             programInfoLog.resize(infoLogLength);
172         }
173 
174         if (linkStatus == 0 || vertexCompileStatus == 0 || fragmentCompileStatus == 0)
175         {
176 
177             log.startShaderProgram(linkStatus != 0, programInfoLog.c_str());
178 
179             log << TestLog::Shader(QP_SHADER_TYPE_VERTEX, vertexShaderSource, vertexCompileStatus != 0, vertexInfoLog);
180             log << TestLog::Shader(QP_SHADER_TYPE_FRAGMENT, fragmentShaderSource, fragmentCompileStatus != 0,
181                                    fragmentInfoLog);
182 
183             log.endShaderProgram();
184         }
185 
186         gl.deleteShader(vertexShader);
187         gl.deleteShader(fragmentShader);
188         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to delete shaders");
189 
190         TCU_CHECK(linkStatus != 0 && vertexCompileStatus != 0 && fragmentCompileStatus != 0);
191     }
192     catch (...)
193     {
194         if (program)
195             gl.deleteProgram(program);
196 
197         if (vertexShader)
198             gl.deleteShader(vertexShader);
199 
200         if (fragmentShader)
201             gl.deleteShader(fragmentShader);
202 
203         throw;
204     }
205 
206     return program;
207 }
208 
clear(const glw::Functions & gl,const tcu::Vec4 & color,int x,int y,int width,int height)209 void clear(const glw::Functions &gl, const tcu::Vec4 &color, int x, int y, int width, int height)
210 {
211     gl.enable(GL_SCISSOR_TEST);
212     gl.scissor(x, y, width, height);
213     gl.clearColor(color.x(), color.y(), color.z(), color.w());
214     gl.clear(GL_COLOR_BUFFER_BIT);
215     GLU_EXPECT_NO_ERROR(gl.getError(), "Color clear failed");
216 }
217 
toGLCoord(int width,int height,int x,int y)218 tcu::Vec2 toGLCoord(int width, int height, int x, int y)
219 {
220     const float xf = ((2.0f * float(x)) / (float)width) - 1.0f;
221     const float yf = ((2.0f * float(y)) / (float)height) - 1.0f;
222 
223     return tcu::Vec2(xf, yf);
224 }
225 
render(const glw::Functions & gl,uint32_t program,int targetWidth,int targetHeight,int x,int y,int width,int height)226 void render(const glw::Functions &gl, uint32_t program, int targetWidth, int targetHeight, int x, int y, int width,
227             int height)
228 {
229     const tcu::Vec2 positions[] = {toGLCoord(targetWidth, targetHeight, x, y),
230                                    toGLCoord(targetWidth, targetHeight, x + width, y),
231                                    toGLCoord(targetWidth, targetHeight, x + width, y + height),
232 
233                                    toGLCoord(targetWidth, targetHeight, x + width, y + height),
234                                    toGLCoord(targetWidth, targetHeight, x, y + height),
235                                    toGLCoord(targetWidth, targetHeight, x, y)};
236 
237     uint32_t posLocation;
238 
239     gl.useProgram(program);
240     posLocation = gl.getAttribLocation(program, "a_pos");
241     gl.enableVertexAttribArray(posLocation);
242     gl.vertexAttribPointer(posLocation, 2, GL_FLOAT, GL_FALSE, 0, positions);
243     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup shader program for rendering");
244 
245     gl.viewport(0, 0, targetWidth, targetHeight);
246     gl.drawArrays(GL_TRIANGLES, 0, 6);
247     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
248 }
249 
compareColor(const tcu::Vec4 & a,const tcu::Vec4 & b)250 bool compareColor(const tcu::Vec4 &a, const tcu::Vec4 &b)
251 {
252     const float threshold = 0.005f;
253 
254     return deFloatAbs(a.x() - b.x()) < threshold && deFloatAbs(a.y() - b.y()) < threshold &&
255            deFloatAbs(a.z() - b.z()) < threshold && deFloatAbs(a.w() - b.w()) < threshold;
256 }
257 
validate(TestLog & log,const tcu::TextureLevel & result,int rectX,int rectY,int rectW,int rectH)258 bool validate(TestLog &log, const tcu::TextureLevel &result, int rectX, int rectY, int rectW, int rectH)
259 {
260     const tcu::Vec4 black(0.0f, 0.0f, 0.0f, 1.0f);
261     const tcu::Vec4 white(1.0f, 1.0f, 1.0f, 1.0f);
262     tcu::Surface errorMask(result.getWidth(), result.getHeight());
263     bool isOk = true;
264 
265     for (int y = 0; y < result.getHeight(); y++)
266     {
267         for (int x = 0; x < result.getWidth(); x++)
268         {
269             const tcu::Vec4 resultColor = result.getAccess().getPixel(x, y);
270 
271             if (x > rectX && x < rectX + rectW - 1 && y > rectY && y < rectY + rectH - 1)
272             {
273                 if (!compareColor(resultColor, white))
274                 {
275                     errorMask.setPixel(x, y, tcu::RGBA(255, 0, 0, 255));
276                     isOk = false;
277                 }
278                 else
279                     errorMask.setPixel(x, y, tcu::RGBA(0, 255, 0, 255));
280             }
281             else if (x < rectX - 1 || x > rectX + rectW || y < rectY - 1 || y > rectY + rectH)
282             {
283                 if (!compareColor(resultColor, black))
284                 {
285                     errorMask.setPixel(x, y, tcu::RGBA(255, 0, 0, 255));
286                     isOk = false;
287                 }
288                 else
289                     errorMask.setPixel(x, y, tcu::RGBA(0, 255, 0, 255));
290             }
291             else
292             {
293                 // Pixel is close to edge of reference rectangle
294 
295                 if (!compareColor(resultColor, black) && !compareColor(resultColor, white))
296                 {
297                     errorMask.setPixel(x, y, tcu::RGBA(255, 0, 0, 255));
298                     isOk = false;
299                 }
300                 else
301                     errorMask.setPixel(x, y, tcu::RGBA(0, 255, 0, 255));
302             }
303         }
304     }
305 
306     log << TestLog::Image("Result", "Result of rendering", result.getAccess());
307 
308     if (!isOk)
309         log << TestLog::Image("Error Mask", "Error Mask", errorMask.getAccess());
310 
311     return isOk;
312 }
313 
314 class NativeCoordMappingCase : public SimpleConfigCase
315 {
316 public:
317     enum NativeType
318     {
319         NATIVETYPE_WINDOW = 0,
320         NATIVETYPE_PIXMAP,
321         NATIVETYPE_PBUFFER_COPY_TO_PIXMAP
322     };
323 
324     NativeCoordMappingCase(EglTestContext &eglTestCtx, const char *name, const char *description, bool render,
325                            NativeType nativeType, const eglu::FilterList &filters);
326     ~NativeCoordMappingCase(void);
327 
328 private:
329     void executeForConfig(EGLDisplay display, EGLConfig config);
330 
331     NativeType m_nativeType;
332     bool m_render;
333 };
334 
NativeCoordMappingCase(EglTestContext & eglTestCtx,const char * name,const char * description,bool render,NativeType nativeType,const eglu::FilterList & filters)335 NativeCoordMappingCase::NativeCoordMappingCase(EglTestContext &eglTestCtx, const char *name, const char *description,
336                                                bool render, NativeType nativeType, const eglu::FilterList &filters)
337     : SimpleConfigCase(eglTestCtx, name, description, filters)
338     , m_nativeType(nativeType)
339     , m_render(render)
340 {
341 }
342 
~NativeCoordMappingCase(void)343 NativeCoordMappingCase::~NativeCoordMappingCase(void)
344 {
345     deinit();
346 }
347 
logConfigInfo(TestLog & log,const Library & egl,EGLDisplay display,EGLConfig config,NativeCoordMappingCase::NativeType nativeType,int waitFrames)348 void logConfigInfo(TestLog &log, const Library &egl, EGLDisplay display, EGLConfig config,
349                    NativeCoordMappingCase::NativeType nativeType, int waitFrames)
350 {
351     log << TestLog::Message << "EGL_RED_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_RED_SIZE)
352         << TestLog::EndMessage;
353     log << TestLog::Message << "EGL_GREEN_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_GREEN_SIZE)
354         << TestLog::EndMessage;
355     log << TestLog::Message << "EGL_BLUE_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_BLUE_SIZE)
356         << TestLog::EndMessage;
357     log << TestLog::Message << "EGL_ALPHA_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_ALPHA_SIZE)
358         << TestLog::EndMessage;
359     log << TestLog::Message << "EGL_DEPTH_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_DEPTH_SIZE)
360         << TestLog::EndMessage;
361     log << TestLog::Message << "EGL_STENCIL_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_STENCIL_SIZE)
362         << TestLog::EndMessage;
363     log << TestLog::Message << "EGL_SAMPLES: " << eglu::getConfigAttribInt(egl, display, config, EGL_SAMPLES)
364         << TestLog::EndMessage;
365 
366     if (nativeType == NativeCoordMappingCase::NATIVETYPE_WINDOW)
367         log << TestLog::Message << "Waiting " << waitFrames * 16
368             << "ms after eglSwapBuffers() and glFinish() for frame to become visible" << TestLog::EndMessage;
369 }
370 
testNativeWindow(TestLog & log,eglu::NativeDisplay & nativeDisplay,eglu::NativeWindow & nativeWindow,EGLDisplay display,EGLContext context,EGLConfig config,const glw::Functions & gl,bool renderColor,int waitFrames)371 bool testNativeWindow(TestLog &log, eglu::NativeDisplay &nativeDisplay, eglu::NativeWindow &nativeWindow,
372                       EGLDisplay display, EGLContext context, EGLConfig config, const glw::Functions &gl,
373                       bool renderColor, int waitFrames)
374 {
375     const int rectX = 8;
376     const int rectY = 16;
377     const int rectW = 64;
378     const int rectH = 72;
379 
380     const Library &egl          = nativeDisplay.getLibrary();
381     const tcu::IVec2 screenSize = nativeWindow.getScreenSize();
382     eglu::UniqueSurface surface(egl, display,
383                                 eglu::createWindowSurface(nativeDisplay, nativeWindow, display, config, DE_NULL));
384     const tcu::IVec2 surfaceSize = eglu::getSurfaceSize(egl, display, *surface);
385     uint32_t program             = 0;
386     bool isOk                    = true;
387     tcu::TextureLevel result;
388 
389     try
390     {
391         EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, context));
392 
393         if (renderColor)
394             program = createGLES2Program(gl, log);
395 
396         clear(gl, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0, surfaceSize.x(), surfaceSize.y());
397 
398         if (renderColor)
399             render(gl, program, surfaceSize.x(), surfaceSize.y(), rectX, rectY, rectW, rectH);
400         else
401             clear(gl, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), rectX, rectY, rectW, rectH);
402 
403         EGLU_CHECK_CALL(egl, swapBuffers(display, *surface));
404         EGLU_CHECK_CALL(egl, waitClient());
405         deSleep(waitFrames * 16);
406         nativeWindow.readScreenPixels(&result);
407 
408         if (!validate(log, result, rectX, screenSize.y() - rectY - rectH, rectW, rectH))
409             isOk = false;
410 
411         EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
412     }
413     catch (...)
414     {
415         if (program)
416             gl.deleteProgram(program);
417         throw;
418     }
419 
420     return isOk;
421 }
422 
testNativePixmap(TestLog & log,eglu::NativeDisplay & nativeDisplay,eglu::NativePixmap & nativePixmap,int width,int height,EGLDisplay display,EGLContext context,EGLConfig config,const glw::Functions & gl,bool renderColor)423 bool testNativePixmap(TestLog &log, eglu::NativeDisplay &nativeDisplay, eglu::NativePixmap &nativePixmap, int width,
424                       int height, EGLDisplay display, EGLContext context, EGLConfig config, const glw::Functions &gl,
425                       bool renderColor)
426 {
427     const int rectX = 8;
428     const int rectY = 16;
429     const int rectW = 64;
430     const int rectH = 72;
431 
432     const Library &egl = nativeDisplay.getLibrary();
433     eglu::UniqueSurface surface(egl, display,
434                                 eglu::createPixmapSurface(nativeDisplay, nativePixmap, display, config, DE_NULL));
435     uint32_t program = 0;
436     bool isOk        = true;
437     tcu::TextureLevel result;
438 
439     try
440     {
441         EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, context));
442 
443         if (renderColor)
444             program = createGLES2Program(gl, log);
445 
446         clear(gl, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0, width, height);
447 
448         if (renderColor)
449             render(gl, program, width, height, rectX, rectY, rectW, rectH);
450         else
451             clear(gl, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), rectX, rectY, rectW, rectH);
452 
453         EGLU_CHECK_CALL(egl, waitClient());
454         nativePixmap.readPixels(&result);
455 
456         if (!validate(log, result, rectX, height - 1 - rectY - rectH, rectW, rectH))
457             isOk = false;
458 
459         EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
460     }
461     catch (...)
462     {
463         if (program)
464             gl.deleteProgram(program);
465         throw;
466     }
467 
468     return isOk;
469 }
470 
testNativePixmapCopy(TestLog & log,const Library & egl,eglu::NativePixmap & nativePixmap,int width,int height,EGLDisplay display,EGLContext context,EGLConfig config,const glw::Functions & gl,bool renderColor)471 bool testNativePixmapCopy(TestLog &log, const Library &egl, eglu::NativePixmap &nativePixmap, int width, int height,
472                           EGLDisplay display, EGLContext context, EGLConfig config, const glw::Functions &gl,
473                           bool renderColor)
474 {
475     const int rectX = 8;
476     const int rectY = 16;
477     const int rectW = 64;
478     const int rectH = 72;
479 
480     eglu::UniqueSurface surface(egl, display, egl.createPbufferSurface(display, config, DE_NULL));
481     uint32_t program = 0;
482     bool isOk        = true;
483     tcu::TextureLevel result;
484 
485     try
486     {
487         EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, context));
488 
489         if (renderColor)
490             program = createGLES2Program(gl, log);
491 
492         clear(gl, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0, width, height);
493 
494         if (renderColor)
495             render(gl, program, width, height, rectX, rectY, rectW, rectH);
496         else
497             clear(gl, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), rectX, rectY, rectW, rectH);
498 
499         EGLU_CHECK_CALL(egl, copyBuffers(display, *surface, nativePixmap.getLegacyNative()));
500         EGLU_CHECK_CALL(egl, waitClient());
501         nativePixmap.readPixels(&result);
502 
503         if (!validate(log, result, rectX, height - 1 - rectY, rectW, rectH))
504             isOk = false;
505 
506         EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
507     }
508     catch (...)
509     {
510         if (program)
511             gl.deleteProgram(program);
512         throw;
513     }
514 
515     return isOk;
516 }
517 
executeForConfig(EGLDisplay display,EGLConfig config)518 void NativeCoordMappingCase::executeForConfig(EGLDisplay display, EGLConfig config)
519 {
520     const Library &egl = m_eglTestCtx.getLibrary();
521     const string configIdStr(de::toString(eglu::getConfigAttribInt(egl, display, config, EGL_CONFIG_ID)));
522     tcu::ScopedLogSection logSection(m_testCtx.getLog(), ("Config ID " + configIdStr).c_str(),
523                                      ("Config ID " + configIdStr).c_str());
524     const int waitFrames = 5;
525     const int width      = 128;
526     const int height     = 128;
527     const eglu::NativeWindowFactory *windowFactory;
528     const eglu::NativePixmapFactory *pixmapFactory;
529 
530     logConfigInfo(m_testCtx.getLog(), egl, display, config, m_nativeType, waitFrames);
531 
532     try
533     {
534         windowFactory =
535             &eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
536 
537         if ((windowFactory->getCapabilities() & eglu::NativeWindow::CAPABILITY_READ_SCREEN_PIXELS) == 0)
538             TCU_THROW(NotSupportedError, "Native window doesn't support readPixels()");
539     }
540     catch (const tcu::NotSupportedError &)
541     {
542         if (m_nativeType == NATIVETYPE_WINDOW)
543             throw;
544         else
545             windowFactory = DE_NULL;
546     }
547 
548     try
549     {
550         pixmapFactory =
551             &eglu::selectNativePixmapFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
552 
553         if (m_nativeType == NATIVETYPE_PIXMAP)
554         {
555             if ((pixmapFactory->getCapabilities() & eglu::NativePixmap::CAPABILITY_READ_PIXELS) == 0)
556                 TCU_THROW(NotSupportedError, "Native pixmap doesn't support readPixels()");
557         }
558         else if (m_nativeType == NATIVETYPE_PBUFFER_COPY_TO_PIXMAP)
559         {
560             if ((pixmapFactory->getCapabilities() & eglu::NativePixmap::CAPABILITY_READ_PIXELS) == 0 ||
561                 (pixmapFactory->getCapabilities() & eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY) == 0)
562                 TCU_THROW(NotSupportedError, "Native pixmap doesn't support readPixels() or legacy create surface");
563         }
564     }
565     catch (const tcu::NotSupportedError &)
566     {
567         if (m_nativeType == NATIVETYPE_PIXMAP || m_nativeType == NATIVETYPE_PBUFFER_COPY_TO_PIXMAP)
568             throw;
569         else
570             pixmapFactory = DE_NULL;
571     }
572 
573     DE_ASSERT(m_nativeType != NATIVETYPE_WINDOW || windowFactory);
574     DE_ASSERT((m_nativeType != NATIVETYPE_PIXMAP && m_nativeType != NATIVETYPE_PBUFFER_COPY_TO_PIXMAP) ||
575               pixmapFactory);
576 
577     eglu::UniqueContext context(egl, display, createGLES2Context(egl, display, config));
578     glw::Functions gl;
579 
580     m_eglTestCtx.initGLFunctions(&gl, glu::ApiType::es(2, 0));
581 
582     switch (m_nativeType)
583     {
584     case NATIVETYPE_WINDOW:
585     {
586         de::UniquePtr<eglu::NativeWindow> nativeWindow(
587             windowFactory->createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL,
588                                         eglu::WindowParams(width, height, eglu::WindowParams::VISIBILITY_VISIBLE)));
589 
590         if (!testNativeWindow(m_testCtx.getLog(), m_eglTestCtx.getNativeDisplay(), *nativeWindow, display, *context,
591                               config, gl, m_render, waitFrames))
592             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid color rendered");
593 
594         break;
595     }
596 
597     case NATIVETYPE_PIXMAP:
598     {
599         de::UniquePtr<eglu::NativePixmap> nativePixmap(
600             pixmapFactory->createPixmap(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, width, height));
601 
602         if (!testNativePixmap(m_testCtx.getLog(), m_eglTestCtx.getNativeDisplay(), *nativePixmap, width, height,
603                               display, *context, config, gl, m_render))
604             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid color rendered");
605 
606         break;
607     }
608 
609     case NATIVETYPE_PBUFFER_COPY_TO_PIXMAP:
610     {
611         de::UniquePtr<eglu::NativePixmap> nativePixmap(
612             pixmapFactory->createPixmap(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, width, height));
613 
614         if (!testNativePixmapCopy(m_testCtx.getLog(), egl, *nativePixmap, width, height, display, *context, config, gl,
615                                   m_render))
616             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid color rendered");
617 
618         break;
619     }
620 
621     default:
622         DE_ASSERT(false);
623     }
624 }
625 
626 template <uint32_t Type>
surfaceType(const eglu::CandidateConfig & c)627 static bool surfaceType(const eglu::CandidateConfig &c)
628 {
629     return (c.surfaceType() & Type) == Type;
630 }
631 
addTestGroups(EglTestContext & eglTestCtx,TestCaseGroup * group,NativeCoordMappingCase::NativeType type)632 void addTestGroups(EglTestContext &eglTestCtx, TestCaseGroup *group, NativeCoordMappingCase::NativeType type)
633 {
634     eglu::FilterList baseFilters;
635 
636     switch (type)
637     {
638     case NativeCoordMappingCase::NATIVETYPE_WINDOW:
639         baseFilters << surfaceType<EGL_WINDOW_BIT>;
640         break;
641 
642     case NativeCoordMappingCase::NATIVETYPE_PIXMAP:
643         baseFilters << surfaceType<EGL_PIXMAP_BIT>;
644         break;
645 
646     case NativeCoordMappingCase::NATIVETYPE_PBUFFER_COPY_TO_PIXMAP:
647         baseFilters << surfaceType<EGL_PBUFFER_BIT>;
648         break;
649 
650     default:
651         DE_ASSERT(false);
652     }
653 
654     vector<NamedFilterList> filterLists;
655     getDefaultFilterLists(filterLists, baseFilters);
656 
657     for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
658     {
659         group->addChild(new NativeCoordMappingCase(eglTestCtx, (string(i->getName()) + "_clear").c_str(),
660                                                    i->getDescription(), false, type, *i));
661         group->addChild(new NativeCoordMappingCase(eglTestCtx, (string(i->getName()) + "_render").c_str(),
662                                                    i->getDescription(), true, type, *i));
663     }
664 }
665 
666 } // namespace
667 
NativeCoordMappingTests(EglTestContext & eglTestCtx)668 NativeCoordMappingTests::NativeCoordMappingTests(EglTestContext &eglTestCtx)
669     : TestCaseGroup(eglTestCtx, "native_coord_mapping", "Tests for mapping client coordinates to native surface")
670 {
671 }
672 
init(void)673 void NativeCoordMappingTests::init(void)
674 {
675     {
676         TestCaseGroup *windowGroup =
677             new TestCaseGroup(m_eglTestCtx, "native_window", "Tests for mapping client color to native window");
678         addTestGroups(m_eglTestCtx, windowGroup, NativeCoordMappingCase::NATIVETYPE_WINDOW);
679         addChild(windowGroup);
680     }
681 
682     {
683         TestCaseGroup *pixmapGroup =
684             new TestCaseGroup(m_eglTestCtx, "native_pixmap", "Tests for mapping client color to native pixmap");
685         addTestGroups(m_eglTestCtx, pixmapGroup, NativeCoordMappingCase::NATIVETYPE_PIXMAP);
686         addChild(pixmapGroup);
687     }
688 
689     {
690         TestCaseGroup *pbufferGroup =
691             new TestCaseGroup(m_eglTestCtx, "pbuffer_to_native_pixmap",
692                               "Tests for mapping client color to native pixmap with eglCopyBuffers()");
693         addTestGroups(m_eglTestCtx, pbufferGroup, NativeCoordMappingCase::NATIVETYPE_PBUFFER_COPY_TO_PIXMAP);
694         addChild(pbufferGroup);
695     }
696 }
697 
698 } // namespace egl
699 } // namespace deqp
700