• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // EGLSurfaceTest:
7 //   Tests pertaining to egl::Surface.
8 //
9 
10 #include <gtest/gtest.h>
11 
12 #include <vector>
13 
14 #include "common/platform.h"
15 #include "test_utils/ANGLETest.h"
16 #include "util/EGLWindow.h"
17 #include "util/OSWindow.h"
18 #include "util/Timer.h"
19 
20 #if defined(ANGLE_ENABLE_D3D11)
21 #    define INITGUID
22 #    include <guiddef.h>
23 
24 #    include <d3d11.h>
25 #    include <dcomp.h>
26 #endif
27 
28 using namespace angle;
29 
30 namespace
31 {
32 
33 class EGLSurfaceTest : public ANGLETest
34 {
35   protected:
EGLSurfaceTest()36     EGLSurfaceTest()
37         : mDisplay(EGL_NO_DISPLAY),
38           mWindowSurface(EGL_NO_SURFACE),
39           mPbufferSurface(EGL_NO_SURFACE),
40           mContext(EGL_NO_CONTEXT),
41           mSecondContext(EGL_NO_CONTEXT),
42           mOSWindow(nullptr)
43     {}
44 
testSetUp()45     void testSetUp() override
46     {
47         mOSWindow = OSWindow::New();
48         mOSWindow->initialize("EGLSurfaceTest", 64, 64);
49     }
50 
51     // Release any resources created in the test body
testTearDown()52     void testTearDown() override
53     {
54         if (mDisplay != EGL_NO_DISPLAY)
55         {
56             eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
57 
58             if (mWindowSurface != EGL_NO_SURFACE)
59             {
60                 eglDestroySurface(mDisplay, mWindowSurface);
61                 mWindowSurface = EGL_NO_SURFACE;
62             }
63 
64             if (mPbufferSurface != EGL_NO_SURFACE)
65             {
66                 eglDestroySurface(mDisplay, mPbufferSurface);
67                 mPbufferSurface = EGL_NO_SURFACE;
68             }
69 
70             if (mContext != EGL_NO_CONTEXT)
71             {
72                 eglDestroyContext(mDisplay, mContext);
73                 mContext = EGL_NO_CONTEXT;
74             }
75 
76             if (mSecondContext != EGL_NO_CONTEXT)
77             {
78                 eglDestroyContext(mDisplay, mSecondContext);
79                 mSecondContext = EGL_NO_CONTEXT;
80             }
81 
82             eglTerminate(mDisplay);
83             mDisplay = EGL_NO_DISPLAY;
84         }
85 
86         mOSWindow->destroy();
87         OSWindow::Delete(&mOSWindow);
88 
89         ASSERT_TRUE(mWindowSurface == EGL_NO_SURFACE && mContext == EGL_NO_CONTEXT);
90     }
91 
initializeDisplay()92     void initializeDisplay()
93     {
94         GLenum platformType = GetParam().getRenderer();
95         GLenum deviceType   = GetParam().getDeviceType();
96 
97         std::vector<EGLint> displayAttributes;
98         displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
99         displayAttributes.push_back(platformType);
100         displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
101         displayAttributes.push_back(EGL_DONT_CARE);
102         displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
103         displayAttributes.push_back(EGL_DONT_CARE);
104         displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
105         displayAttributes.push_back(deviceType);
106         displayAttributes.push_back(EGL_NONE);
107 
108         mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
109                                             reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
110                                             displayAttributes.data());
111         ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);
112 
113         EGLint majorVersion, minorVersion;
114         ASSERT_TRUE(eglInitialize(mDisplay, &majorVersion, &minorVersion) == EGL_TRUE);
115 
116         eglBindAPI(EGL_OPENGL_ES_API);
117         ASSERT_EGL_SUCCESS();
118     }
119 
initializeContext()120     void initializeContext()
121     {
122         EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION, GetParam().majorVersion, EGL_NONE};
123 
124         mContext = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes);
125         ASSERT_EGL_SUCCESS();
126 
127         mSecondContext = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes);
128         ASSERT_EGL_SUCCESS();
129     }
130 
initializeSurface(EGLConfig config)131     void initializeSurface(EGLConfig config)
132     {
133         mConfig = config;
134 
135         std::vector<EGLint> windowAttributes;
136         windowAttributes.push_back(EGL_NONE);
137 
138         // Create first window surface
139         mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(),
140                                                 windowAttributes.data());
141         ASSERT_EGL_SUCCESS();
142 
143         // Give pbuffer non-zero dimensions.
144         std::vector<EGLint> pbufferAttributes;
145         pbufferAttributes.push_back(EGL_WIDTH);
146         pbufferAttributes.push_back(64);
147         pbufferAttributes.push_back(EGL_HEIGHT);
148         pbufferAttributes.push_back(64);
149         pbufferAttributes.push_back(EGL_NONE);
150 
151         mPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, pbufferAttributes.data());
152         ASSERT_EGL_SUCCESS();
153         initializeContext();
154     }
155 
initializeSurfaceWithDefaultConfig()156     void initializeSurfaceWithDefaultConfig()
157     {
158         const EGLint configAttributes[] = {EGL_RED_SIZE,
159                                            EGL_DONT_CARE,
160                                            EGL_GREEN_SIZE,
161                                            EGL_DONT_CARE,
162                                            EGL_BLUE_SIZE,
163                                            EGL_DONT_CARE,
164                                            EGL_ALPHA_SIZE,
165                                            EGL_DONT_CARE,
166                                            EGL_DEPTH_SIZE,
167                                            EGL_DONT_CARE,
168                                            EGL_STENCIL_SIZE,
169                                            EGL_DONT_CARE,
170                                            EGL_SAMPLE_BUFFERS,
171                                            0,
172                                            EGL_NONE};
173 
174         EGLint configCount;
175         EGLConfig config;
176         ASSERT_TRUE(eglChooseConfig(mDisplay, configAttributes, &config, 1, &configCount) ||
177                     (configCount != 1) == EGL_TRUE);
178 
179         initializeSurface(config);
180     }
181 
createProgram()182     GLuint createProgram()
183     {
184         return CompileProgram(angle::essl1_shaders::vs::Simple(), angle::essl1_shaders::fs::Red());
185     }
186 
drawWithProgram(GLuint program)187     void drawWithProgram(GLuint program)
188     {
189         glClearColor(0, 0, 0, 1);
190         glClear(GL_COLOR_BUFFER_BIT);
191 
192         GLint positionLocation =
193             glGetAttribLocation(program, angle::essl1_shaders::PositionAttrib());
194 
195         glUseProgram(program);
196 
197         const GLfloat vertices[] = {
198             -1.0f, 1.0f, 0.5f, -1.0f, -1.0f, 0.5f, 1.0f, -1.0f, 0.5f,
199 
200             -1.0f, 1.0f, 0.5f, 1.0f,  -1.0f, 0.5f, 1.0f, 1.0f,  0.5f,
201         };
202 
203         glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
204         glEnableVertexAttribArray(positionLocation);
205 
206         glDrawArrays(GL_TRIANGLES, 0, 6);
207 
208         glDisableVertexAttribArray(positionLocation);
209         glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
210 
211         EXPECT_PIXEL_EQ(mOSWindow->getWidth() / 2, mOSWindow->getHeight() / 2, 255, 0, 0, 255);
212     }
213 
runMessageLoopTest(EGLSurface secondSurface,EGLContext secondContext)214     void runMessageLoopTest(EGLSurface secondSurface, EGLContext secondContext)
215     {
216         eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
217         ASSERT_EGL_SUCCESS();
218 
219         // Make a second context current
220         eglMakeCurrent(mDisplay, secondSurface, secondSurface, secondContext);
221         eglDestroySurface(mDisplay, mWindowSurface);
222 
223         // Create second window surface
224         std::vector<EGLint> surfaceAttributes;
225         surfaceAttributes.push_back(EGL_NONE);
226         surfaceAttributes.push_back(EGL_NONE);
227 
228         mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(),
229                                                 &surfaceAttributes[0]);
230         ASSERT_EGL_SUCCESS();
231 
232         eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
233         ASSERT_EGL_SUCCESS();
234 
235         mOSWindow->signalTestEvent();
236         mOSWindow->messageLoop();
237         ASSERT_TRUE(mOSWindow->didTestEventFire());
238 
239         // Simple operation to test the FBO is set appropriately
240         glClear(GL_COLOR_BUFFER_BIT);
241     }
242 
243     EGLDisplay mDisplay;
244     EGLSurface mWindowSurface;
245     EGLSurface mPbufferSurface;
246     EGLContext mContext;
247     EGLContext mSecondContext;
248     EGLConfig mConfig;
249     OSWindow *mOSWindow;
250 };
251 
252 class EGLFloatSurfaceTest : public EGLSurfaceTest
253 {
254   protected:
EGLFloatSurfaceTest()255     EGLFloatSurfaceTest() : EGLSurfaceTest()
256     {
257         setWindowWidth(512);
258         setWindowHeight(512);
259     }
260 
testSetUp()261     void testSetUp() override
262     {
263         mOSWindow = OSWindow::New();
264         mOSWindow->initialize("EGLFloatSurfaceTest", 64, 64);
265     }
266 
testTearDown()267     void testTearDown() override
268     {
269         EGLSurfaceTest::testTearDown();
270         glDeleteProgram(mProgram);
271     }
272 
createProgram()273     GLuint createProgram()
274     {
275         constexpr char kFS[] =
276             "precision highp float;\n"
277             "void main()\n"
278             "{\n"
279             "   gl_FragColor = vec4(1.0, 2.0, 3.0, 4.0);\n"
280             "}\n";
281         return CompileProgram(angle::essl1_shaders::vs::Simple(), kFS);
282     }
283 
initializeSurfaceWithFloatConfig()284     bool initializeSurfaceWithFloatConfig()
285     {
286         const EGLint configAttributes[] = {EGL_RED_SIZE,
287                                            16,
288                                            EGL_GREEN_SIZE,
289                                            16,
290                                            EGL_BLUE_SIZE,
291                                            16,
292                                            EGL_ALPHA_SIZE,
293                                            16,
294                                            EGL_COLOR_COMPONENT_TYPE_EXT,
295                                            EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
296                                            EGL_NONE,
297                                            EGL_NONE};
298 
299         initializeDisplay();
300         EGLConfig config;
301         if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
302         {
303             std::cout << "EGLConfig for a float surface is not supported, skipping test"
304                       << std::endl;
305             return false;
306         }
307 
308         initializeSurface(config);
309 
310         eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
311         mProgram = createProgram();
312         return true;
313     }
314 
315     GLuint mProgram;
316 };
317 
318 // Test clearing and checking the color is correct
TEST_P(EGLFloatSurfaceTest,Clearing)319 TEST_P(EGLFloatSurfaceTest, Clearing)
320 {
321     ANGLE_SKIP_TEST_IF(!initializeSurfaceWithFloatConfig());
322 
323     ASSERT_NE(0u, mProgram) << "shader compilation failed.";
324     ASSERT_GL_NO_ERROR();
325 
326     GLColor32F clearColor(0.0f, 1.0f, 2.0f, 3.0f);
327     glClearColor(clearColor.R, clearColor.G, clearColor.B, clearColor.A);
328     glClear(GL_COLOR_BUFFER_BIT);
329     ASSERT_GL_NO_ERROR();
330 
331     EXPECT_PIXEL_COLOR32F_EQ(0, 0, clearColor);
332 }
333 
334 // Test drawing and checking the color is correct
TEST_P(EGLFloatSurfaceTest,Drawing)335 TEST_P(EGLFloatSurfaceTest, Drawing)
336 {
337     ANGLE_SKIP_TEST_IF(!initializeSurfaceWithFloatConfig());
338 
339     ASSERT_NE(0u, mProgram) << "shader compilation failed.";
340     ASSERT_GL_NO_ERROR();
341 
342     glUseProgram(mProgram);
343     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
344 
345     EXPECT_PIXEL_32F_EQ(0, 0, 1.0f, 2.0f, 3.0f, 4.0f);
346 }
347 
348 class EGLSurfaceTest3 : public EGLSurfaceTest
349 {};
350 
351 // Test a surface bug where we could have two Window surfaces active
352 // at one time, blocking message loops. See http://crbug.com/475085
TEST_P(EGLSurfaceTest,MessageLoopBug)353 TEST_P(EGLSurfaceTest, MessageLoopBug)
354 {
355     // TODO(syoussefi): http://anglebug.com/3123
356     ANGLE_SKIP_TEST_IF(IsAndroid());
357 
358     // http://anglebug.com/3138
359     ANGLE_SKIP_TEST_IF(IsOzone());
360 
361     initializeDisplay();
362     initializeSurfaceWithDefaultConfig();
363 
364     runMessageLoopTest(EGL_NO_SURFACE, EGL_NO_CONTEXT);
365 }
366 
367 // Tests the message loop bug, but with setting a second context
368 // instead of null.
TEST_P(EGLSurfaceTest,MessageLoopBugContext)369 TEST_P(EGLSurfaceTest, MessageLoopBugContext)
370 {
371     // TODO(syoussefi): http://anglebug.com/3123
372     ANGLE_SKIP_TEST_IF(IsAndroid());
373 
374     // http://anglebug.com/3138
375     ANGLE_SKIP_TEST_IF(IsOzone());
376 
377     initializeDisplay();
378     initializeSurfaceWithDefaultConfig();
379 
380     runMessageLoopTest(mPbufferSurface, mSecondContext);
381 }
382 
383 // Test a bug where calling makeCurrent twice would release the surface
TEST_P(EGLSurfaceTest,MakeCurrentTwice)384 TEST_P(EGLSurfaceTest, MakeCurrentTwice)
385 {
386     initializeDisplay();
387     initializeSurfaceWithDefaultConfig();
388 
389     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
390     ASSERT_EGL_SUCCESS();
391 
392     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
393     ASSERT_EGL_SUCCESS();
394 
395     // Simple operation to test the FBO is set appropriately
396     glClear(GL_COLOR_BUFFER_BIT);
397 }
398 
399 // Test that the window surface is correctly resized after calling swapBuffers
TEST_P(EGLSurfaceTest,ResizeWindow)400 TEST_P(EGLSurfaceTest, ResizeWindow)
401 {
402     // http://anglebug.com/4453
403     ANGLE_SKIP_TEST_IF(isVulkanRenderer() && IsLinux() && IsIntel());
404     // Flaky on Linux SwANGLE http://anglebug.com/4453
405     ANGLE_SKIP_TEST_IF(IsLinux() && isSwiftshader());
406 
407     // Necessary for a window resizing test if there is no per-frame window size query
408     setWindowVisible(mOSWindow, true);
409 
410     GLenum platform               = GetParam().getRenderer();
411     bool platformSupportsZeroSize = platform == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||
412                                     platform == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
413     int minSize = platformSupportsZeroSize ? 0 : 1;
414 
415     initializeDisplay();
416     initializeSurfaceWithDefaultConfig();
417     initializeContext();
418 
419     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
420     eglSwapBuffers(mDisplay, mWindowSurface);
421     ASSERT_EGL_SUCCESS();
422 
423     EGLint height;
424     eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
425     ASSERT_EGL_SUCCESS();
426     ASSERT_EQ(64, height);  // initial size
427 
428     // set window's height to 0 (if possible) or 1
429     mOSWindow->resize(64, minSize);
430 
431     eglSwapBuffers(mDisplay, mWindowSurface);
432     ASSERT_EGL_SUCCESS();
433 
434     // TODO(syoussefi): the GLX implementation still reads the window size as 64x64 through
435     // XGetGeometry.  http://anglebug.com/3122
436     ANGLE_SKIP_TEST_IF(IsLinux() && IsOpenGL());
437 
438     eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
439     ASSERT_EGL_SUCCESS();
440     ASSERT_EQ(minSize, height);
441 
442     // restore window's height
443     mOSWindow->resize(64, 64);
444 
445     eglSwapBuffers(mDisplay, mWindowSurface);
446     ASSERT_EGL_SUCCESS();
447 
448     eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
449     ASSERT_EGL_SUCCESS();
450     ASSERT_EQ(64, height);
451 }
452 
453 // Test that the backbuffer is correctly resized after calling swapBuffers
TEST_P(EGLSurfaceTest,ResizeWindowWithDraw)454 TEST_P(EGLSurfaceTest, ResizeWindowWithDraw)
455 {
456     // http://anglebug.com/4453
457     ANGLE_SKIP_TEST_IF(isVulkanRenderer() && IsLinux() && IsIntel());
458 
459     // Flaky on Linux SwANGLE http://anglebug.com/4453
460     ANGLE_SKIP_TEST_IF(IsLinux() && isSwiftshader());
461 
462     // Necessary for a window resizing test if there is no per-frame window size query
463     setWindowVisible(mOSWindow, true);
464 
465     initializeDisplay();
466     initializeSurfaceWithDefaultConfig();
467     initializeContext();
468 
469     int size      = 64;
470     EGLint height = 0;
471     EGLint width  = 0;
472 
473     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
474     eglSwapBuffers(mDisplay, mWindowSurface);
475     ASSERT_EGL_SUCCESS();
476 
477     // Clear to red
478     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
479     glClear(GL_COLOR_BUFFER_BIT);
480 
481     eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
482     eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width);
483     ASSERT_EGL_SUCCESS();
484 
485     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
486     EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::red);
487     EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::red);
488     EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::red);
489     EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack);
490     EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack);
491     EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack);
492     EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack);
493 
494     // set window's size small
495     size = 1;
496     mOSWindow->resize(size, size);
497 
498     eglSwapBuffers(mDisplay, mWindowSurface);
499     ASSERT_EGL_SUCCESS();
500 
501     // Clear to green
502     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
503     glClear(GL_COLOR_BUFFER_BIT);
504 
505     eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
506     eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width);
507     ASSERT_EGL_SUCCESS();
508 
509     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
510     EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::green);
511     EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::green);
512     EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::green);
513     EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack);
514     EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack);
515     EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack);
516     EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack);
517 
518     // set window's height large
519     size = 128;
520     mOSWindow->resize(size, size);
521 
522     eglSwapBuffers(mDisplay, mWindowSurface);
523     ASSERT_EGL_SUCCESS();
524 
525     // Clear to blue
526     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
527     glClear(GL_COLOR_BUFFER_BIT);
528 
529     eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
530     eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width);
531     ASSERT_EGL_SUCCESS();
532 
533     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
534     EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::blue);
535     EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::blue);
536     EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::blue);
537     EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack);
538     EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack);
539     EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack);
540     EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack);
541 }
542 
543 // Test that the window can be reset repeatedly before surface creation.
TEST_P(EGLSurfaceTest,ResetNativeWindow)544 TEST_P(EGLSurfaceTest, ResetNativeWindow)
545 {
546     setWindowVisible(mOSWindow, true);
547 
548     initializeDisplay();
549 
550     for (int i = 0; i < 10; ++i)
551     {
552         mOSWindow->resetNativeWindow();
553     }
554 
555     initializeSurfaceWithDefaultConfig();
556     initializeContext();
557 
558     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
559 
560     eglSwapBuffers(mDisplay, mWindowSurface);
561     ASSERT_EGL_SUCCESS();
562 }
563 
564 // Test creating a surface that supports a EGLConfig with 16bit
565 // support GL_RGB565
TEST_P(EGLSurfaceTest,CreateWithEGLConfig5650Support)566 TEST_P(EGLSurfaceTest, CreateWithEGLConfig5650Support)
567 {
568     const EGLint configAttributes[] = {
569         EGL_RED_SIZE,   5, EGL_GREEN_SIZE,   6, EGL_BLUE_SIZE,      5, EGL_ALPHA_SIZE, 0,
570         EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};
571 
572     initializeDisplay();
573     EGLConfig config;
574     if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
575     {
576         std::cout << "EGLConfig for a GL_RGB565 surface is not supported, skipping test"
577                   << std::endl;
578         return;
579     }
580 
581     initializeSurface(config);
582 
583     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
584     ASSERT_EGL_SUCCESS();
585 
586     GLuint program = createProgram();
587     ASSERT_NE(0u, program);
588     drawWithProgram(program);
589     EXPECT_GL_NO_ERROR();
590     glDeleteProgram(program);
591 }
592 
593 // Test creating a surface that supports a EGLConfig with 16bit
594 // support GL_RGBA4
TEST_P(EGLSurfaceTest,CreateWithEGLConfig4444Support)595 TEST_P(EGLSurfaceTest, CreateWithEGLConfig4444Support)
596 {
597     const EGLint configAttributes[] = {
598         EGL_RED_SIZE,   4, EGL_GREEN_SIZE,   4, EGL_BLUE_SIZE,      4, EGL_ALPHA_SIZE, 4,
599         EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};
600 
601     initializeDisplay();
602     EGLConfig config;
603     if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
604     {
605         std::cout << "EGLConfig for a GL_RGBA4 surface is not supported, skipping test"
606                   << std::endl;
607         return;
608     }
609 
610     initializeSurface(config);
611 
612     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
613     ASSERT_EGL_SUCCESS();
614 
615     GLuint program = createProgram();
616     ASSERT_NE(0u, program);
617     drawWithProgram(program);
618     EXPECT_GL_NO_ERROR();
619     glDeleteProgram(program);
620 }
621 
622 // Test creating a surface that supports a EGLConfig with 16bit
623 // support GL_RGB5_A1
TEST_P(EGLSurfaceTest,CreateWithEGLConfig5551Support)624 TEST_P(EGLSurfaceTest, CreateWithEGLConfig5551Support)
625 {
626     const EGLint configAttributes[] = {
627         EGL_RED_SIZE,   5, EGL_GREEN_SIZE,   5, EGL_BLUE_SIZE,      5, EGL_ALPHA_SIZE, 1,
628         EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};
629 
630     initializeDisplay();
631     EGLConfig config;
632     if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
633     {
634         std::cout << "EGLConfig for a GL_RGB5_A1 surface is not supported, skipping test"
635                   << std::endl;
636         return;
637     }
638 
639     initializeSurface(config);
640 
641     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
642     ASSERT_EGL_SUCCESS();
643 
644     GLuint program = createProgram();
645     ASSERT_NE(0u, program);
646     drawWithProgram(program);
647     EXPECT_GL_NO_ERROR();
648     glDeleteProgram(program);
649 }
650 
651 // Test creating a surface that supports a EGLConfig without alpha support
TEST_P(EGLSurfaceTest,CreateWithEGLConfig8880Support)652 TEST_P(EGLSurfaceTest, CreateWithEGLConfig8880Support)
653 {
654     const EGLint configAttributes[] = {
655         EGL_RED_SIZE,   8, EGL_GREEN_SIZE,   8, EGL_BLUE_SIZE,      8, EGL_ALPHA_SIZE, 0,
656         EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};
657 
658     initializeDisplay();
659     EGLConfig config;
660     if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
661     {
662         std::cout << "EGLConfig for a GL_RGB8_OES surface is not supported, skipping test"
663                   << std::endl;
664         return;
665     }
666 
667     initializeSurface(config);
668 
669     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
670     ASSERT_EGL_SUCCESS();
671 
672     GLuint program = createProgram();
673     ASSERT_NE(0u, program);
674     drawWithProgram(program);
675     EXPECT_GL_NO_ERROR();
676     glDeleteProgram(program);
677 }
678 
TEST_P(EGLSurfaceTest,FixedSizeWindow)679 TEST_P(EGLSurfaceTest, FixedSizeWindow)
680 {
681     const EGLint configAttributes[] = {
682         EGL_RED_SIZE,   8, EGL_GREEN_SIZE,   8, EGL_BLUE_SIZE,      8, EGL_ALPHA_SIZE, 0,
683         EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};
684 
685     initializeDisplay();
686     ANGLE_SKIP_TEST_IF(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &mConfig) == EGL_FALSE);
687 
688     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_window_fixed_size"));
689 
690     constexpr EGLint kInitialSize = 64;
691     constexpr EGLint kUpdateSize  = 32;
692 
693     EGLint surfaceAttributes[] = {
694         EGL_FIXED_SIZE_ANGLE, EGL_TRUE, EGL_WIDTH, kInitialSize, EGL_HEIGHT, kInitialSize, EGL_NONE,
695     };
696 
697     // Create first window surface
698     mWindowSurface =
699         eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), surfaceAttributes);
700     ASSERT_EGL_SUCCESS();
701     ASSERT_NE(EGL_NO_SURFACE, mWindowSurface);
702 
703     initializeContext();
704     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext));
705     ASSERT_EGL_SUCCESS();
706 
707     EGLint queryIsFixedSize = 0;
708     EXPECT_EGL_TRUE(
709         eglQuerySurface(mDisplay, mWindowSurface, EGL_FIXED_SIZE_ANGLE, &queryIsFixedSize));
710     ASSERT_EGL_SUCCESS();
711     EXPECT_EGL_TRUE(queryIsFixedSize);
712 
713     EGLint queryWidth = 0;
714     EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &queryWidth));
715     ASSERT_EGL_SUCCESS();
716     EXPECT_EQ(kInitialSize, queryWidth);
717 
718     EGLint queryHeight = 0;
719     EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &queryHeight));
720     ASSERT_EGL_SUCCESS();
721     EXPECT_EQ(kInitialSize, queryHeight);
722 
723     // Update the size
724     EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, mWindowSurface, EGL_WIDTH, kUpdateSize));
725     ASSERT_EGL_SUCCESS();
726 
727     EXPECT_EGL_TRUE(eglWaitNative(EGL_CORE_NATIVE_ENGINE));
728     ASSERT_EGL_SUCCESS();
729 
730     EGLint queryUpdatedWidth = 0;
731     EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &queryUpdatedWidth));
732     ASSERT_EGL_SUCCESS();
733     EXPECT_EQ(kUpdateSize, queryUpdatedWidth);
734 }
735 
TEST_P(EGLSurfaceTest3,MakeCurrentDifferentSurfaces)736 TEST_P(EGLSurfaceTest3, MakeCurrentDifferentSurfaces)
737 {
738     const EGLint configAttributes[] = {
739         EGL_RED_SIZE,   8, EGL_GREEN_SIZE,   8, EGL_BLUE_SIZE,      8, EGL_ALPHA_SIZE, 8,
740         EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};
741     EGLSurface firstPbufferSurface;
742     EGLSurface secondPbufferSurface;
743 
744     initializeDisplay();
745     ANGLE_SKIP_TEST_IF(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &mConfig) == EGL_FALSE);
746 
747     EGLint surfaceType = 0;
748     eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType);
749     bool supportsPbuffers    = (surfaceType & EGL_PBUFFER_BIT) != 0;
750     EGLint bindToTextureRGBA = 0;
751     eglGetConfigAttrib(mDisplay, mConfig, EGL_BIND_TO_TEXTURE_RGBA, &bindToTextureRGBA);
752     bool supportsBindTexImage = (bindToTextureRGBA == EGL_TRUE);
753 
754     const EGLint pBufferAttributes[] = {
755         EGL_WIDTH,          64,
756         EGL_HEIGHT,         64,
757         EGL_TEXTURE_FORMAT, supportsPbuffers ? EGL_TEXTURE_RGBA : EGL_NO_TEXTURE,
758         EGL_TEXTURE_TARGET, supportsBindTexImage ? EGL_TEXTURE_2D : EGL_NO_TEXTURE,
759         EGL_NONE,           EGL_NONE,
760     };
761 
762     // Create the surfaces
763     firstPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, pBufferAttributes);
764     ASSERT_EGL_SUCCESS();
765     ASSERT_NE(EGL_NO_SURFACE, firstPbufferSurface);
766     secondPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, pBufferAttributes);
767     ASSERT_EGL_SUCCESS();
768     ASSERT_NE(EGL_NO_SURFACE, secondPbufferSurface);
769 
770     initializeContext();
771 
772     // Use the same surface for both draw and read
773     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, firstPbufferSurface, firstPbufferSurface, mContext));
774     glClearColor(GLColor::red.R, GLColor::red.G, GLColor::red.B, GLColor::red.A);
775     glClear(GL_COLOR_BUFFER_BIT);
776     ASSERT_GL_NO_ERROR();
777     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
778 
779     // Use different surfaces for draw and read, read should stay the same
780     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, secondPbufferSurface, firstPbufferSurface, mContext));
781     glClearColor(GLColor::blue.R, GLColor::blue.G, GLColor::blue.B, GLColor::blue.A);
782     glClear(GL_COLOR_BUFFER_BIT);
783     ASSERT_GL_NO_ERROR();
784     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
785     // Verify draw surface was cleared
786     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, secondPbufferSurface, secondPbufferSurface, mContext));
787     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
788 
789     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, firstPbufferSurface, secondPbufferSurface, mContext));
790     ASSERT_EGL_SUCCESS();
791 
792     // Blit the source surface to the destination surface
793     glBlitFramebuffer(0, 0, 64, 64, 0, 0, 64, 64, GL_COLOR_BUFFER_BIT, GL_NEAREST);
794     ASSERT_GL_NO_ERROR();
795     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, firstPbufferSurface, firstPbufferSurface, mContext));
796     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
797 }
798 
799 #if defined(ANGLE_ENABLE_D3D11)
800 class EGLSurfaceTestD3D11 : public EGLSurfaceTest
801 {};
802 
803 // Test that rendering to an IDCompositionSurface using a pbuffer works.
TEST_P(EGLSurfaceTestD3D11,CreateDirectCompositionSurface)804 TEST_P(EGLSurfaceTestD3D11, CreateDirectCompositionSurface)
805 {
806     ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d"));
807     initializeDisplay();
808 
809     EGLAttrib device       = 0;
810     EGLAttrib newEglDevice = 0;
811     ASSERT_EGL_TRUE(eglQueryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, &newEglDevice));
812     ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(newEglDevice),
813                                             EGL_D3D11_DEVICE_ANGLE, &device));
814     angle::ComPtr<ID3D11Device> d3d11Device(reinterpret_cast<ID3D11Device *>(device));
815     ASSERT_TRUE(!!d3d11Device);
816 
817     HMODULE dcompLibrary = LoadLibraryA("dcomp.dll");
818     if (!dcompLibrary)
819     {
820         std::cout << "DirectComposition not supported" << std::endl;
821         return;
822     }
823     typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE2)(IUnknown * dxgiDevice, REFIID iid,
824                                                               void **dcompositionDevice);
825     PFN_DCOMPOSITION_CREATE_DEVICE2 createDComp = reinterpret_cast<PFN_DCOMPOSITION_CREATE_DEVICE2>(
826         GetProcAddress(dcompLibrary, "DCompositionCreateDevice2"));
827     if (!createDComp)
828     {
829         std::cout << "DirectComposition2 not supported" << std::endl;
830         FreeLibrary(dcompLibrary);
831         return;
832     }
833 
834     angle::ComPtr<IDCompositionDevice> dcompDevice;
835     HRESULT hr = createDComp(d3d11Device.Get(), IID_PPV_ARGS(dcompDevice.GetAddressOf()));
836     ASSERT_TRUE(SUCCEEDED(hr));
837 
838     angle::ComPtr<IDCompositionSurface> dcompSurface;
839     hr = dcompDevice->CreateSurface(100, 100, DXGI_FORMAT_B8G8R8A8_UNORM,
840                                     DXGI_ALPHA_MODE_PREMULTIPLIED, dcompSurface.GetAddressOf());
841     ASSERT_TRUE(SUCCEEDED(hr));
842 
843     angle::ComPtr<ID3D11Texture2D> texture;
844     POINT updateOffset;
845     hr = dcompSurface->BeginDraw(nullptr, IID_PPV_ARGS(texture.GetAddressOf()), &updateOffset);
846     ASSERT_TRUE(SUCCEEDED(hr));
847 
848     const EGLint configAttributes[] = {
849         EGL_RED_SIZE,   8, EGL_GREEN_SIZE,   8, EGL_BLUE_SIZE,      8, EGL_ALPHA_SIZE, 8,
850         EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};
851 
852     EGLConfig config;
853     ASSERT_EGL_TRUE(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config));
854 
855     const EGLint surfaceAttributes[] = {EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE};
856 
857     EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(texture.Get());
858     mPbufferSurface = eglCreatePbufferFromClientBuffer(mDisplay, EGL_D3D_TEXTURE_ANGLE, buffer,
859                                                        config, surfaceAttributes);
860     ASSERT_EGL_SUCCESS();
861 
862     mConfig = config;
863     initializeContext();
864 
865     eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mContext);
866     ASSERT_EGL_SUCCESS();
867 
868     GLuint program = createProgram();
869     ASSERT_NE(0u, program);
870     drawWithProgram(program);
871     EXPECT_GL_NO_ERROR();
872     glDeleteProgram(program);
873 }
874 
TEST_P(EGLSurfaceTestD3D11,CreateSurfaceWithMSAA)875 TEST_P(EGLSurfaceTestD3D11, CreateSurfaceWithMSAA)
876 {
877     ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d"));
878 
879     // clang-format off
880     const EGLint configAttributes[] =
881     {
882         EGL_RED_SIZE, 8,
883         EGL_GREEN_SIZE, 8,
884         EGL_BLUE_SIZE, 8,
885         EGL_ALPHA_SIZE, 0,
886         EGL_DEPTH_SIZE, 0,
887         EGL_STENCIL_SIZE, 0,
888         EGL_SAMPLE_BUFFERS, 1,
889         EGL_SAMPLES, 4,
890         EGL_NONE
891     };
892     // clang-format on
893 
894     initializeDisplay();
895     EGLConfig config;
896     if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
897     {
898         std::cout << "EGLConfig for 4xMSAA is not supported, skipping test" << std::endl;
899         return;
900     }
901 
902     initializeSurface(config);
903 
904     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
905     ASSERT_EGL_SUCCESS();
906 
907     GLuint program = createProgram();
908     ASSERT_NE(0u, program);
909 
910     glClearColor(0, 0, 0, 1);
911     glClear(GL_COLOR_BUFFER_BIT);
912 
913     GLint positionLocation = glGetAttribLocation(program, angle::essl1_shaders::PositionAttrib());
914     ASSERT_NE(-1, positionLocation);
915 
916     glUseProgram(program);
917 
918     const GLfloat halfPixelOffset = 0.5f * 2.0f / mOSWindow->getWidth();
919     // clang-format off
920     const GLfloat vertices[] =
921     {
922         -1.0f + halfPixelOffset,  1.0f, 0.5f,
923         -1.0f + halfPixelOffset, -1.0f, 0.5f,
924          1.0f,                   -1.0f, 0.5f
925     };
926     // clang-format on
927 
928     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
929     glEnableVertexAttribArray(positionLocation);
930 
931     glDrawArrays(GL_TRIANGLES, 0, 3);
932 
933     glDisableVertexAttribArray(positionLocation);
934     glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
935 
936     EXPECT_PIXEL_NEAR(0, 0, 127, 0, 0, 255, 10);
937     EXPECT_GL_NO_ERROR();
938 
939     glDeleteProgram(program);
940 }
941 
942 #endif  // ANGLE_ENABLE_D3D11
943 
944 }  // anonymous namespace
945 
946 ANGLE_INSTANTIATE_TEST(EGLSurfaceTest,
947                        WithNoFixture(ES2_D3D9()),
948                        WithNoFixture(ES2_D3D11()),
949                        WithNoFixture(ES3_D3D11()),
950                        WithNoFixture(ES2_OPENGL()),
951                        WithNoFixture(ES3_OPENGL()),
952                        WithNoFixture(ES2_OPENGLES()),
953                        WithNoFixture(ES3_OPENGLES()),
954                        WithNoFixture(ES2_VULKAN()),
955                        WithNoFixture(ES3_VULKAN()),
956                        WithNoFixture(ES2_VULKAN_SWIFTSHADER()),
957                        WithNoFixture(ES3_VULKAN_SWIFTSHADER()));
958 ANGLE_INSTANTIATE_TEST(EGLFloatSurfaceTest,
959                        WithNoFixture(ES2_OPENGL()),
960                        WithNoFixture(ES3_OPENGL()),
961                        WithNoFixture(ES2_VULKAN()),
962                        WithNoFixture(ES3_VULKAN()));
963 ANGLE_INSTANTIATE_TEST(EGLSurfaceTest3, WithNoFixture(ES3_VULKAN()));
964 
965 #if defined(ANGLE_ENABLE_D3D11)
966 ANGLE_INSTANTIATE_TEST(EGLSurfaceTestD3D11, WithNoFixture(ES2_D3D11()), WithNoFixture(ES3_D3D11()));
967 #endif
968