x11_egl: use quotes to include glesv1_cm directories am: f5e7ab6b79
[platform/upstream/VK-GL-CTS.git] / modules / egl / teglSwapBuffersTests.cpp
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 Test eglSwapBuffers() interaction with native window.
22  *//*--------------------------------------------------------------------*/
23
24 #include "teglSwapBuffersTests.hpp"
25
26 #include "teglSimpleConfigCase.hpp"
27
28 #include "egluNativeWindow.hpp"
29 #include "egluUtil.hpp"
30 #include "egluUnique.hpp"
31 #include "eglwLibrary.hpp"
32 #include "eglwEnums.hpp"
33
34 #include "gluDefs.hpp"
35 #include "glwEnums.hpp"
36 #include "glwFunctions.hpp"
37
38 #include "tcuTestLog.hpp"
39 #include "tcuSurface.hpp"
40 #include "tcuTexture.hpp"
41 #include "tcuTextureUtil.hpp"
42 #include "tcuImageCompare.hpp"
43 #include "tcuVector.hpp"
44 #include "tcuVectorUtil.hpp"
45
46 #include "deUniquePtr.hpp"
47 #include "deThread.hpp"
48
49 #include <string>
50 #include <vector>
51 #include <sstream>
52
53 namespace deqp
54 {
55 namespace egl
56 {
57
58 using tcu::TestLog;
59 using std::string;
60 using std::vector;
61 using namespace eglw;
62
63 namespace
64 {
65
66 EGLContext createGLES2Context (const Library& egl, EGLDisplay display, EGLConfig config)
67 {
68         EGLContext              context = EGL_NO_CONTEXT;
69         const EGLint    attribList[] =
70         {
71                 EGL_CONTEXT_CLIENT_VERSION, 2,
72                 EGL_NONE
73         };
74
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
85 class SwapBuffersTest : public SimpleConfigCase
86 {
87 public:
88                                                 SwapBuffersTest         (EglTestContext& eglTestCtx, const NamedFilterList& filters);
89                                                 ~SwapBuffersTest        (void);
90
91 private:
92         void                            executeForConfig        (EGLDisplay display, EGLConfig config);
93
94         // Not allowed
95                                                 SwapBuffersTest         (const SwapBuffersTest&);
96         SwapBuffersTest&        operator=                       (const SwapBuffersTest&);
97 };
98
99
100 SwapBuffersTest::SwapBuffersTest (EglTestContext& eglTestCtx, const NamedFilterList& filters)
101         : SimpleConfigCase(eglTestCtx, filters.getName(), filters.getDescription(), filters)
102 {
103 }
104
105 SwapBuffersTest::~SwapBuffersTest (void)
106 {
107 }
108
109 string getConfigIdString (const Library& egl, EGLDisplay display, EGLConfig config)
110 {
111         std::ostringstream      stream;
112         EGLint                          id;
113
114         EGLU_CHECK_CALL(egl, getConfigAttrib(display, config , EGL_CONFIG_ID, &id));
115
116         stream << id;
117
118         return stream.str();
119 }
120
121 deUint32 createGLES2Program (const glw::Functions& gl, TestLog& log)
122 {
123         const char* const vertexShaderSource =
124         "attribute highp vec2 a_pos;\n"
125         "void main (void)\n"
126         "{\n"
127         "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
128         "}";
129
130         const char* const fragmentShaderSource =
131         "void main (void)\n"
132         "{\n"
133         "\tgl_FragColor = vec4(0.9, 0.1, 0.4, 1.0);\n"
134         "}";
135
136         deUint32        program                 = 0;
137         deUint32        vertexShader    = 0;
138         deUint32        fragmentShader  = 0;
139
140         deInt32         vertexCompileStatus;
141         string          vertexInfoLog;
142         deInt32         fragmentCompileStatus;
143         string          fragmentInfoLog;
144         deInt32         linkStatus;
145         string          programInfoLog;
146
147         try
148         {
149                 program                 = gl.createProgram();
150                 vertexShader    = gl.createShader(GL_VERTEX_SHADER);
151                 fragmentShader  = gl.createShader(GL_FRAGMENT_SHADER);
152
153                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create shaders and program");
154
155                 gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL);
156                 gl.compileShader(vertexShader);
157                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup vertex shader");
158
159                 gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL);
160                 gl.compileShader(fragmentShader);
161                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup fragment shader");
162
163                 {
164                         deInt32         infoLogLength = 0;
165
166                         gl.getShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexCompileStatus);
167                         gl.getShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength);
168
169                         vertexInfoLog.resize(infoLogLength, '\0');
170
171                         gl.getShaderInfoLog(vertexShader, (glw::GLsizei)vertexInfoLog.length(), &infoLogLength, &(vertexInfoLog[0]));
172                         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get vertex shader compile info");
173
174                         vertexInfoLog.resize(infoLogLength);
175                 }
176
177                 {
178                         deInt32         infoLogLength = 0;
179
180                         gl.getShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentCompileStatus);
181                         gl.getShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLength);
182
183                         fragmentInfoLog.resize(infoLogLength, '\0');
184
185                         gl.getShaderInfoLog(fragmentShader, (glw::GLsizei)fragmentInfoLog.length(), &infoLogLength, &(fragmentInfoLog[0]));
186                         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get fragment shader compile info");
187
188                         fragmentInfoLog.resize(infoLogLength);
189                 }
190
191                 gl.attachShader(program, vertexShader);
192                 gl.attachShader(program, fragmentShader);
193                 gl.linkProgram(program);
194                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup program");
195
196                 {
197                         deInt32         infoLogLength = 0;
198
199                         gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus);
200                         gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
201
202                         programInfoLog.resize(infoLogLength, '\0');
203
204                         gl.getProgramInfoLog(program, (glw::GLsizei)programInfoLog.length(), &infoLogLength, &(programInfoLog[0]));
205                         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get program link info");
206
207                         programInfoLog.resize(infoLogLength);
208                 }
209
210                 if (linkStatus == 0 || vertexCompileStatus == 0 || fragmentCompileStatus == 0)
211                 {
212
213                         log.startShaderProgram(linkStatus != 0, programInfoLog.c_str());
214
215                         log << TestLog::Shader(QP_SHADER_TYPE_VERTEX, vertexShaderSource, vertexCompileStatus != 0, vertexInfoLog);
216                         log << TestLog::Shader(QP_SHADER_TYPE_FRAGMENT, fragmentShaderSource, fragmentCompileStatus != 0, fragmentInfoLog);
217
218                         log.endShaderProgram();
219                 }
220
221                 gl.deleteShader(vertexShader);
222                 gl.deleteShader(fragmentShader);
223                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to delete shaders");
224
225                 TCU_CHECK(linkStatus != 0 && vertexCompileStatus != 0 && fragmentCompileStatus != 0);
226         }
227         catch (...)
228         {
229                 if (program)
230                         gl.deleteProgram(program);
231
232                 if (vertexShader)
233                         gl.deleteShader(vertexShader);
234
235                 if (fragmentShader)
236                         gl.deleteShader(fragmentShader);
237
238                 throw;
239         }
240
241         return program;
242 }
243
244 bool checkColor (tcu::TestLog& log, const tcu::TextureLevel& screen, const tcu::Vec4& color)
245 {
246         const tcu::Vec4 threshold(0.01f, 0.01f, 0.01f, 1.00f);
247
248         for (int y = 0; y < screen.getHeight(); y++)
249         {
250                 for (int x = 0; x < screen.getWidth(); x++)
251                 {
252                         const tcu::Vec4 pixel(screen.getAccess().getPixel(x, y));
253                         const tcu::Vec4 diff(abs(pixel - color));
254
255                         if (!boolAll(lessThanEqual(diff, threshold)))
256                         {
257                                 log << TestLog::Message << "Unexpected color values read from screen expected: " << color << TestLog::EndMessage;
258                                 log << TestLog::Image("Screen", "Screen", screen.getAccess());
259                                 return false;
260                         }
261                 }
262         }
263
264         return true;
265 }
266
267 void SwapBuffersTest::executeForConfig (EGLDisplay display, EGLConfig config)
268 {
269         const Library&                                          egl                     = m_eglTestCtx.getLibrary();
270         const string                                            configIdStr     (getConfigIdString(egl, display, config));
271         tcu::ScopedLogSection                           logSection      (m_testCtx.getLog(), ("Config ID " + configIdStr).c_str(), ("Config ID " + configIdStr).c_str());
272         const int                                                       waitFrames      = 5;
273         const eglu::NativeWindowFactory&        factory         = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
274
275         if ((factory.getCapabilities() & eglu::NativeWindow::CAPABILITY_READ_SCREEN_PIXELS) == 0)
276                 TCU_THROW(NotSupportedError, "eglu::NativeWindow doesn't support readScreenPixels()");
277
278         {
279                 TestLog& log = m_testCtx.getLog();
280
281                 log << TestLog::Message << "EGL_RED_SIZE: "             << eglu::getConfigAttribInt(egl, display, config, EGL_RED_SIZE)         << TestLog::EndMessage;
282                 log << TestLog::Message << "EGL_GREEN_SIZE: "   << eglu::getConfigAttribInt(egl, display, config, EGL_GREEN_SIZE)       << TestLog::EndMessage;
283                 log << TestLog::Message << "EGL_BLUE_SIZE: "    << eglu::getConfigAttribInt(egl, display, config, EGL_BLUE_SIZE)        << TestLog::EndMessage;
284                 log << TestLog::Message << "EGL_ALPHA_SIZE: "   << eglu::getConfigAttribInt(egl, display, config, EGL_ALPHA_SIZE)       << TestLog::EndMessage;
285                 log << TestLog::Message << "EGL_DEPTH_SIZE: "   << eglu::getConfigAttribInt(egl, display, config, EGL_DEPTH_SIZE)       << TestLog::EndMessage;
286                 log << TestLog::Message << "EGL_STENCIL_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_STENCIL_SIZE)     << TestLog::EndMessage;
287                 log << TestLog::Message << "EGL_SAMPLES: "              << eglu::getConfigAttribInt(egl, display, config, EGL_SAMPLES)          << TestLog::EndMessage;
288
289                 log << TestLog::Message << "Waiting " << waitFrames * 16 << "ms after eglSwapBuffers() and glFinish() for frame to become visible" << TestLog::EndMessage;
290         }
291
292         de::UniquePtr<eglu::NativeWindow>       window  (factory.createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, eglu::WindowParams(128, 128, eglu::WindowParams::VISIBILITY_VISIBLE)));
293
294         eglu::UniqueSurface                                     surface (egl, display, eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, display, config, DE_NULL));
295         eglu::UniqueContext                                     context (egl, display, createGLES2Context(egl, display, config));
296         glw::Functions                                          gl;
297         deUint32                                                        program = 0;
298
299         tcu::TextureLevel                                       whiteFrame;
300         tcu::TextureLevel                                       blackFrame;
301         tcu::TextureLevel                                       frameBegin;
302         tcu::TextureLevel                                       frameEnd;
303
304         m_eglTestCtx.initGLFunctions(&gl, glu::ApiType::es(2,0));
305         EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, *context));
306
307         try
308         {
309                 const float positions1[] = {
310                          0.00f,  0.00f,
311                          0.75f,  0.00f,
312                          0.75f,  0.75f,
313
314                          0.75f,  0.75f,
315                          0.00f,  0.75f,
316                          0.00f,  0.00f
317                 };
318
319                 const float positions2[] = {
320                         -0.75f, -0.75f,
321                          0.00f, -0.75f,
322                          0.00f,  0.00f,
323
324                          0.00f,  0.00f,
325                         -0.75f,  0.00f,
326                         -0.75f, -0.75f
327                 };
328
329                 deUint32 posLocation;
330
331                 program = createGLES2Program(gl, m_testCtx.getLog());
332
333                 gl.useProgram(program);
334                 posLocation     = gl.getAttribLocation(program, "a_pos");
335                 gl.enableVertexAttribArray(posLocation);
336                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup shader program for rendering");
337
338                 // Clear screen to white and check that sceen is white
339                 gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
340                 gl.clear(GL_COLOR_BUFFER_BIT);
341                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear surface");
342
343                 EGLU_CHECK_CALL(egl, swapBuffers(display, *surface));
344                 gl.finish();
345                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFinish() failed");
346                 deSleep(waitFrames * 16);
347                 window->processEvents();
348                 window->readScreenPixels(&whiteFrame);
349
350                 if (!checkColor(m_testCtx.getLog(), whiteFrame, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f)))
351                 {
352                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Couldn't reliably read pixels from screen");
353                         return;
354                 }
355
356                 // Clear screen to black and check that sceen is black
357                 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
358                 gl.clear(GL_COLOR_BUFFER_BIT);
359                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear surface");
360
361                 EGLU_CHECK_CALL(egl, swapBuffers(display, *surface));
362                 gl.finish();
363                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFinish() failed");
364                 deSleep(waitFrames * 16);
365                 window->processEvents();
366                 window->readScreenPixels(&blackFrame);
367
368                 if (!checkColor(m_testCtx.getLog(), blackFrame, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)))
369                 {
370                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Couldn't reliably read pixels from screen");
371                         return;
372                 }
373
374                 gl.clearColor(0.7f, 1.0f, 0.3f, 1.0f);
375                 gl.clear(GL_COLOR_BUFFER_BIT);
376                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear surface");
377
378                 gl.vertexAttribPointer(posLocation, 2, GL_FLOAT, GL_FALSE, 0, positions1);
379                 gl.drawArrays(GL_TRIANGLES, 0, 6);
380                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
381
382                 EGLU_CHECK_CALL(egl, swapBuffers(display, *surface));
383                 gl.finish();
384                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFinish() failed");
385                 deSleep(waitFrames * 16);
386                 window->processEvents();
387                 window->readScreenPixels(&frameBegin);
388
389                 gl.clearColor(0.7f, 0.7f, 1.0f, 1.0f);
390                 gl.clear(GL_COLOR_BUFFER_BIT);
391                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear surface");
392
393                 gl.vertexAttribPointer(posLocation, 2, GL_FLOAT, GL_FALSE, 0, positions2);
394                 gl.drawArrays(GL_TRIANGLES, 0, 6);
395                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
396
397                 gl.finish();
398                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFinish() failed");
399                 deSleep(waitFrames * 16);
400                 window->readScreenPixels(&frameEnd);
401
402                 EGLU_CHECK_CALL(egl, swapBuffers(display, *surface));
403                 gl.finish();
404                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFinish() failed");
405                 deSleep(waitFrames * 16);
406                 window->processEvents();
407
408                 gl.disableVertexAttribArray(posLocation);
409                 gl.useProgram(0);
410                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to release program state");
411
412                 gl.deleteProgram(program);
413                 program = 0;
414                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram()");
415
416                 if (!tcu::intThresholdCompare(m_testCtx.getLog(), "Compare end of frame against beginning of frame" , "Compare end of frame against beginning of frame", frameBegin.getAccess(), frameEnd.getAccess(), tcu::UVec4(0, 0, 0, 0), tcu::COMPARE_LOG_RESULT))
417                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Screen pixels changed during frame");
418         }
419         catch (...)
420         {
421                 if (program != 0)
422                         gl.deleteProgram(program);
423
424                 EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
425                 throw;
426         }
427
428         EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
429 }
430
431 } // anonymous
432
433 SwapBuffersTests::SwapBuffersTests (EglTestContext& eglTestCtx)
434         : TestCaseGroup(eglTestCtx, "swap_buffers", "Swap buffers tests")
435 {
436 }
437
438 static bool isWindow (const eglu::CandidateConfig& c) { return (c.surfaceType() & EGL_WINDOW_BIT) != 0; }
439
440 void SwapBuffersTests::init (void)
441 {
442         eglu::FilterList baseFilters;
443         baseFilters << isWindow;
444
445         vector<NamedFilterList> filterLists;
446         getDefaultFilterLists(filterLists, baseFilters);
447
448         for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
449                 addChild(new SwapBuffersTest(m_eglTestCtx, *i));
450 }
451
452 } // egl
453 } // deqp