• 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 <thread>
13 #include <vector>
14 
15 #include "common/Color.h"
16 #include "common/platform.h"
17 #include "test_utils/ANGLETest.h"
18 #include "test_utils/gl_raii.h"
19 #include "util/EGLWindow.h"
20 #include "util/OSWindow.h"
21 #include "util/Timer.h"
22 
23 #if defined(ANGLE_ENABLE_D3D11)
24 #    define INITGUID
25 #    include <guiddef.h>
26 
27 #    include <d3d11.h>
28 #    include <dcomp.h>
29 #endif
30 
31 using namespace angle;
32 
33 namespace
34 {
35 
36 class EGLSurfaceTest : public ANGLETest<>
37 {
38   protected:
EGLSurfaceTest()39     EGLSurfaceTest()
40         : mDisplay(EGL_NO_DISPLAY),
41           mWindowSurface(EGL_NO_SURFACE),
42           mPbufferSurface(EGL_NO_SURFACE),
43           mContext(EGL_NO_CONTEXT),
44           mSecondContext(EGL_NO_CONTEXT),
45           mOSWindow(nullptr)
46     {}
47 
testSetUp()48     void testSetUp() override
49     {
50         mOSWindow = OSWindow::New();
51         mOSWindow->initialize("EGLSurfaceTest", 64, 64);
52     }
53 
tearDownContextAndSurface()54     void tearDownContextAndSurface()
55     {
56         if (mDisplay == EGL_NO_DISPLAY)
57         {
58             return;
59         }
60 
61         eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
62 
63         if (mWindowSurface != EGL_NO_SURFACE)
64         {
65             eglDestroySurface(mDisplay, mWindowSurface);
66             mWindowSurface = EGL_NO_SURFACE;
67         }
68 
69         if (mPbufferSurface != EGL_NO_SURFACE)
70         {
71             eglDestroySurface(mDisplay, mPbufferSurface);
72             mPbufferSurface = EGL_NO_SURFACE;
73         }
74 
75         if (mContext != EGL_NO_CONTEXT)
76         {
77             eglDestroyContext(mDisplay, mContext);
78             mContext = EGL_NO_CONTEXT;
79         }
80 
81         if (mSecondContext != EGL_NO_CONTEXT)
82         {
83             eglDestroyContext(mDisplay, mSecondContext);
84             mSecondContext = EGL_NO_CONTEXT;
85         }
86     }
87 
88     // Release any resources created in the test body
testTearDown()89     void testTearDown() override
90     {
91         tearDownContextAndSurface();
92 
93         if (mDisplay != EGL_NO_DISPLAY)
94         {
95             eglTerminate(mDisplay);
96             mDisplay = EGL_NO_DISPLAY;
97         }
98 
99         mOSWindow->destroy();
100         OSWindow::Delete(&mOSWindow);
101 
102         ASSERT_TRUE(mWindowSurface == EGL_NO_SURFACE && mContext == EGL_NO_CONTEXT);
103     }
104 
initializeDisplay()105     void initializeDisplay()
106     {
107         GLenum platformType = GetParam().getRenderer();
108         GLenum deviceType   = GetParam().getDeviceType();
109 
110         std::vector<EGLint> displayAttributes;
111         displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
112         displayAttributes.push_back(platformType);
113         displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
114         displayAttributes.push_back(EGL_DONT_CARE);
115         displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
116         displayAttributes.push_back(EGL_DONT_CARE);
117         displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
118         displayAttributes.push_back(deviceType);
119         displayAttributes.push_back(EGL_NONE);
120 
121         mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
122                                             reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
123                                             displayAttributes.data());
124         ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);
125 
126         EGLint majorVersion, minorVersion;
127         ASSERT_TRUE(eglInitialize(mDisplay, &majorVersion, &minorVersion) == EGL_TRUE);
128 
129         eglBindAPI(EGL_OPENGL_ES_API);
130         ASSERT_EGL_SUCCESS();
131     }
132 
initializeSingleContext(EGLContext * context,EGLint virtualizationGroup=EGL_DONT_CARE)133     void initializeSingleContext(EGLContext *context, EGLint virtualizationGroup = EGL_DONT_CARE)
134     {
135         ASSERT_TRUE(*context == EGL_NO_CONTEXT);
136 
137         EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION, GetParam().majorVersion,
138                                      EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE, virtualizationGroup,
139                                      EGL_NONE};
140 
141         if (!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_context_virtualization"))
142         {
143             contextAttibutes[2] = EGL_NONE;
144         }
145 
146         *context = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes);
147         ASSERT_EGL_SUCCESS();
148         ASSERT_TRUE(*context != EGL_NO_CONTEXT);
149     }
150 
initializeMainContext()151     void initializeMainContext() { initializeSingleContext(&mContext); }
152 
initializeAllContexts()153     void initializeAllContexts()
154     {
155         initializeSingleContext(&mContext);
156         initializeSingleContext(&mSecondContext);
157     }
158 
initializeWindowSurfaceWithAttribs(EGLConfig config,const std::vector<EGLint> & additionalAttributes,EGLenum expectedResult)159     void initializeWindowSurfaceWithAttribs(EGLConfig config,
160                                             const std::vector<EGLint> &additionalAttributes,
161                                             EGLenum expectedResult)
162     {
163         ASSERT_TRUE(mWindowSurface == EGL_NO_SURFACE);
164 
165         EGLint surfaceType = EGL_NONE;
166         eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType);
167 
168         if (surfaceType & EGL_WINDOW_BIT)
169         {
170             std::vector<EGLint> windowAttributes = additionalAttributes;
171             windowAttributes.push_back(EGL_NONE);
172 
173             // Create first window surface
174             mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(),
175                                                     windowAttributes.data());
176         }
177 
178         ASSERT_EGLENUM_EQ(eglGetError(), expectedResult);
179     }
180 
initializeSurfaceWithAttribs(EGLConfig config,const std::vector<EGLint> & additionalAttributes)181     void initializeSurfaceWithAttribs(EGLConfig config,
182                                       const std::vector<EGLint> &additionalAttributes)
183     {
184         mConfig = config;
185 
186         EGLint surfaceType = EGL_NONE;
187         eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType);
188 
189         if (surfaceType & EGL_WINDOW_BIT)
190         {
191             initializeWindowSurfaceWithAttribs(config, additionalAttributes, EGL_SUCCESS);
192         }
193 
194         if (surfaceType & EGL_PBUFFER_BIT)
195         {
196             ASSERT_TRUE(mPbufferSurface == EGL_NO_SURFACE);
197 
198             std::vector<EGLint> pbufferAttributes = additionalAttributes;
199 
200             // Give pbuffer non-zero dimensions.
201             pbufferAttributes.push_back(EGL_WIDTH);
202             pbufferAttributes.push_back(64);
203             pbufferAttributes.push_back(EGL_HEIGHT);
204             pbufferAttributes.push_back(64);
205             pbufferAttributes.push_back(EGL_NONE);
206 
207             mPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, pbufferAttributes.data());
208             ASSERT_EGL_SUCCESS();
209         }
210     }
211 
initializeSurface(EGLConfig config)212     void initializeSurface(EGLConfig config)
213     {
214         std::vector<EGLint> additionalAttributes;
215         initializeSurfaceWithAttribs(config, additionalAttributes);
216     }
217 
chooseDefaultConfig(bool requireWindowSurface) const218     EGLConfig chooseDefaultConfig(bool requireWindowSurface) const
219     {
220         const EGLint configAttributes[] = {EGL_RED_SIZE,
221                                            EGL_DONT_CARE,
222                                            EGL_GREEN_SIZE,
223                                            EGL_DONT_CARE,
224                                            EGL_BLUE_SIZE,
225                                            EGL_DONT_CARE,
226                                            EGL_ALPHA_SIZE,
227                                            EGL_DONT_CARE,
228                                            EGL_DEPTH_SIZE,
229                                            EGL_DONT_CARE,
230                                            EGL_STENCIL_SIZE,
231                                            EGL_DONT_CARE,
232                                            EGL_SAMPLE_BUFFERS,
233                                            0,
234                                            EGL_SURFACE_TYPE,
235                                            requireWindowSurface ? EGL_WINDOW_BIT : EGL_DONT_CARE,
236                                            EGL_NONE};
237 
238         EGLint configCount;
239         EGLConfig config;
240         if (eglChooseConfig(mDisplay, configAttributes, &config, 1, &configCount) != EGL_TRUE)
241             return nullptr;
242         if (configCount != 1)
243             return nullptr;
244         return config;
245     }
246 
initializeSurfaceWithDefaultConfig(bool requireWindowSurface)247     void initializeSurfaceWithDefaultConfig(bool requireWindowSurface)
248     {
249         EGLConfig defaultConfig = chooseDefaultConfig(requireWindowSurface);
250         ASSERT_NE(defaultConfig, nullptr);
251         initializeSurface(defaultConfig);
252     }
253 
createProgram(const char * fs=angle::essl1_shaders::fs::Red ())254     GLuint createProgram(const char *fs = angle::essl1_shaders::fs::Red())
255     {
256         return CompileProgram(angle::essl1_shaders::vs::Simple(), fs);
257     }
258 
drawWithProgram(GLuint program)259     void drawWithProgram(GLuint program)
260     {
261         glClearColor(0, 0, 0, 1);
262         glClear(GL_COLOR_BUFFER_BIT);
263 
264         GLint positionLocation =
265             glGetAttribLocation(program, angle::essl1_shaders::PositionAttrib());
266 
267         glUseProgram(program);
268 
269         const GLfloat vertices[] = {
270             -1.0f, 1.0f, 0.5f, -1.0f, -1.0f, 0.5f, 1.0f, -1.0f, 0.5f,
271 
272             -1.0f, 1.0f, 0.5f, 1.0f,  -1.0f, 0.5f, 1.0f, 1.0f,  0.5f,
273         };
274 
275         glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
276         glEnableVertexAttribArray(positionLocation);
277 
278         glDrawArrays(GL_TRIANGLES, 0, 6);
279 
280         glDisableVertexAttribArray(positionLocation);
281         glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
282 
283         EXPECT_PIXEL_EQ(mOSWindow->getWidth() / 2, mOSWindow->getHeight() / 2, 255, 0, 0, 255);
284     }
285 
runMessageLoopTest(EGLSurface secondSurface,EGLContext secondContext)286     void runMessageLoopTest(EGLSurface secondSurface, EGLContext secondContext)
287     {
288         eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
289         ASSERT_EGL_SUCCESS();
290 
291         // Make a second context current
292         eglMakeCurrent(mDisplay, secondSurface, secondSurface, secondContext);
293         eglDestroySurface(mDisplay, mWindowSurface);
294 
295         // Create second window surface
296         std::vector<EGLint> surfaceAttributes;
297         surfaceAttributes.push_back(EGL_NONE);
298         surfaceAttributes.push_back(EGL_NONE);
299 
300         mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(),
301                                                 &surfaceAttributes[0]);
302         ASSERT_EGL_SUCCESS();
303 
304         eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
305         ASSERT_EGL_SUCCESS();
306 
307         mOSWindow->signalTestEvent();
308         mOSWindow->messageLoop();
309         ASSERT_TRUE(mOSWindow->didTestEventFire());
310 
311         // Simple operation to test the FBO is set appropriately
312         glClear(GL_COLOR_BUFFER_BIT);
313     }
314 
315     void runWaitSemaphoreTest(bool useSecondContext);
316     void runDestroyNotCurrentSurfaceTest(bool testWindowsSurface);
317 
318     void drawQuadThenTearDown();
319 
320     EGLDisplay mDisplay;
321     EGLSurface mWindowSurface;
322     EGLSurface mPbufferSurface;
323     EGLContext mContext;
324     EGLContext mSecondContext;
325     EGLConfig mConfig;
326     OSWindow *mOSWindow;
327 };
328 
329 class EGLFloatSurfaceTest : public EGLSurfaceTest
330 {
331   protected:
EGLFloatSurfaceTest()332     EGLFloatSurfaceTest() : EGLSurfaceTest()
333     {
334         setWindowWidth(512);
335         setWindowHeight(512);
336     }
337 
testSetUp()338     void testSetUp() override
339     {
340         mOSWindow = OSWindow::New();
341         mOSWindow->initialize("EGLFloatSurfaceTest", 64, 64);
342     }
343 
testTearDown()344     void testTearDown() override
345     {
346         EGLSurfaceTest::testTearDown();
347         glDeleteProgram(mProgram);
348     }
349 
createProgram()350     GLuint createProgram()
351     {
352         constexpr char kFS[] =
353             "precision highp float;\n"
354             "void main()\n"
355             "{\n"
356             "   gl_FragColor = vec4(1.0, 2.0, 3.0, 4.0);\n"
357             "}\n";
358         return CompileProgram(angle::essl1_shaders::vs::Simple(), kFS);
359     }
360 
initializeSurfaceWithFloatConfig()361     bool initializeSurfaceWithFloatConfig()
362     {
363         const EGLint configAttributes[] = {EGL_SURFACE_TYPE,
364                                            EGL_WINDOW_BIT,
365                                            EGL_RED_SIZE,
366                                            16,
367                                            EGL_GREEN_SIZE,
368                                            16,
369                                            EGL_BLUE_SIZE,
370                                            16,
371                                            EGL_ALPHA_SIZE,
372                                            16,
373                                            EGL_COLOR_COMPONENT_TYPE_EXT,
374                                            EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
375                                            EGL_NONE,
376                                            EGL_NONE};
377 
378         initializeDisplay();
379         EGLConfig config;
380         if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
381         {
382             std::cout << "EGLConfig for a float surface is not supported, skipping test"
383                       << std::endl;
384             return false;
385         }
386 
387         initializeSurface(config);
388         initializeMainContext();
389 
390         eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
391         mProgram = createProgram();
392         return true;
393     }
394 
395     GLuint mProgram;
396 };
397 
398 class EGLSingleBufferTest : public ANGLETest<>
399 {
400   protected:
EGLSingleBufferTest()401     EGLSingleBufferTest() {}
402 
testSetUp()403     void testSetUp() override
404     {
405         EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE};
406         mDisplay           = eglGetPlatformDisplayEXT(
407             EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
408         ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);
409         ASSERT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr));
410         mMajorVersion = GetParam().majorVersion;
411     }
412 
testTearDown()413     void testTearDown() override
414     {
415         eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
416         eglTerminate(mDisplay);
417     }
418 
chooseConfig(EGLConfig * config,bool mutableRenderBuffer) const419     bool chooseConfig(EGLConfig *config, bool mutableRenderBuffer) const
420     {
421         bool result          = false;
422         EGLint count         = 0;
423         EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
424         EGLint attribs[]     = {
425             EGL_RED_SIZE,
426             8,
427             EGL_GREEN_SIZE,
428             8,
429             EGL_BLUE_SIZE,
430             8,
431             EGL_ALPHA_SIZE,
432             0,
433             EGL_RENDERABLE_TYPE,
434             clientVersion,
435             EGL_SURFACE_TYPE,
436             EGL_WINDOW_BIT | (mutableRenderBuffer ? EGL_MUTABLE_RENDER_BUFFER_BIT_KHR : 0),
437             EGL_NONE};
438 
439         result = eglChooseConfig(mDisplay, attribs, config, 1, &count);
440         return result && (count > 0);
441     }
442 
createContext(EGLConfig config,EGLContext * context)443     bool createContext(EGLConfig config, EGLContext *context)
444     {
445         EXPECT_TRUE(*context == EGL_NO_CONTEXT);
446 
447         bool result      = false;
448         EGLint attribs[] = {EGL_CONTEXT_MAJOR_VERSION, mMajorVersion, EGL_NONE};
449 
450         *context = eglCreateContext(mDisplay, config, nullptr, attribs);
451         result   = (*context != EGL_NO_CONTEXT);
452         EXPECT_TRUE(result);
453         return result;
454     }
455 
createWindowSurface(EGLConfig config,EGLNativeWindowType win,EGLSurface * surface,EGLint renderBuffer) const456     bool createWindowSurface(EGLConfig config,
457                              EGLNativeWindowType win,
458                              EGLSurface *surface,
459                              EGLint renderBuffer) const
460     {
461         EXPECT_TRUE(*surface == EGL_NO_SURFACE);
462 
463         bool result      = false;
464         EGLint attribs[] = {EGL_RENDER_BUFFER, renderBuffer, EGL_NONE};
465 
466         *surface = eglCreateWindowSurface(mDisplay, config, win, attribs);
467         result   = (*surface != EGL_NO_SURFACE);
468         EXPECT_TRUE(result);
469         return result;
470     }
471 
472     uint32_t drawAndSwap(EGLSurface &surface, EGLDisplay &display, uint32_t color, bool flush);
473 
474     EGLDisplay mDisplay  = EGL_NO_DISPLAY;
475     EGLint mMajorVersion = 0;
476     const EGLint kWidth  = 32;
477     const EGLint kHeight = 32;
478 };
479 
480 class EGLAndroidAutoRefreshTest : public EGLSingleBufferTest
481 {};
482 
483 // Test clearing and checking the color is correct
TEST_P(EGLFloatSurfaceTest,Clearing)484 TEST_P(EGLFloatSurfaceTest, Clearing)
485 {
486     ANGLE_SKIP_TEST_IF(!initializeSurfaceWithFloatConfig());
487 
488     ASSERT_NE(0u, mProgram) << "shader compilation failed.";
489     ASSERT_GL_NO_ERROR();
490 
491     GLColor32F clearColor(0.0f, 1.0f, 2.0f, 3.0f);
492     glClearColor(clearColor.R, clearColor.G, clearColor.B, clearColor.A);
493     glClear(GL_COLOR_BUFFER_BIT);
494     ASSERT_GL_NO_ERROR();
495 
496     EXPECT_PIXEL_COLOR32F_EQ(0, 0, clearColor);
497 }
498 
499 // Test drawing and checking the color is correct
TEST_P(EGLFloatSurfaceTest,Drawing)500 TEST_P(EGLFloatSurfaceTest, Drawing)
501 {
502     ANGLE_SKIP_TEST_IF(!initializeSurfaceWithFloatConfig());
503 
504     ASSERT_NE(0u, mProgram) << "shader compilation failed.";
505     ASSERT_GL_NO_ERROR();
506 
507     glUseProgram(mProgram);
508     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
509 
510     EXPECT_PIXEL_32F_EQ(0, 0, 1.0f, 2.0f, 3.0f, 4.0f);
511 }
512 
513 class EGLSurfaceTest3 : public EGLSurfaceTest
514 {};
515 
516 // Test a surface bug where we could have two Window surfaces active
517 // at one time, blocking message loops. See http://crbug.com/475085
TEST_P(EGLSurfaceTest,MessageLoopBug)518 TEST_P(EGLSurfaceTest, MessageLoopBug)
519 {
520     // http://anglebug.com/3123
521     ANGLE_SKIP_TEST_IF(IsAndroid());
522 
523     // http://anglebug.com/3138
524     ANGLE_SKIP_TEST_IF(IsOzone());
525 
526     // http://anglebug.com/5485
527     ANGLE_SKIP_TEST_IF(IsIOS());
528 
529     initializeDisplay();
530     initializeSurfaceWithDefaultConfig(true);
531     initializeMainContext();
532 
533     runMessageLoopTest(EGL_NO_SURFACE, EGL_NO_CONTEXT);
534 }
535 
536 // Tests the message loop bug, but with setting a second context
537 // instead of null.
TEST_P(EGLSurfaceTest,MessageLoopBugContext)538 TEST_P(EGLSurfaceTest, MessageLoopBugContext)
539 {
540     // http://anglebug.com/3123
541     ANGLE_SKIP_TEST_IF(IsAndroid());
542 
543     // http://anglebug.com/3138
544     ANGLE_SKIP_TEST_IF(IsOzone());
545 
546     // http://anglebug.com/5485
547     ANGLE_SKIP_TEST_IF(IsIOS());
548 
549     initializeDisplay();
550     initializeSurfaceWithDefaultConfig(true);
551     initializeAllContexts();
552 
553     ANGLE_SKIP_TEST_IF(!mPbufferSurface);
554     runMessageLoopTest(mPbufferSurface, mSecondContext);
555 }
556 
557 // Test a bug where calling makeCurrent twice would release the surface
TEST_P(EGLSurfaceTest,MakeCurrentTwice)558 TEST_P(EGLSurfaceTest, MakeCurrentTwice)
559 {
560     initializeDisplay();
561     initializeSurfaceWithDefaultConfig(false);
562     initializeMainContext();
563 
564     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
565     ASSERT_EGL_SUCCESS();
566 
567     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
568     ASSERT_EGL_SUCCESS();
569 
570     // Simple operation to test the FBO is set appropriately
571     glClear(GL_COLOR_BUFFER_BIT);
572 }
573 
574 // Test that we dont crash during a clear when specified scissor is outside render area
575 // due to reducing window size.
TEST_P(EGLSurfaceTest,ShrinkWindowThenScissoredClear)576 TEST_P(EGLSurfaceTest, ShrinkWindowThenScissoredClear)
577 {
578     initializeDisplay();
579     initializeSurfaceWithDefaultConfig(false);
580     initializeMainContext();
581 
582     // Create 64x64 window and make it current
583     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
584     ASSERT_EGL_SUCCESS();
585 
586     // Resize window to 32x32
587     mOSWindow->resize(32, 32);
588 
589     // Perform empty swap
590     eglSwapBuffers(mDisplay, mWindowSurface);
591 
592     // Enable scissor test
593     glEnable(GL_SCISSOR_TEST);
594     ASSERT_GL_NO_ERROR();
595 
596     // Set scissor to (50, 50, 10, 10)
597     glScissor(50, 50, 10, 10);
598     ASSERT_GL_NO_ERROR();
599 
600     // Clear to specific color
601     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
602     glClear(GL_COLOR_BUFFER_BIT);
603 
604     // Disable scissor test
605     glDisable(GL_SCISSOR_TEST);
606     ASSERT_GL_NO_ERROR();
607 }
608 
609 // Test that we dont early return from a clear when specified scissor is outside render area
610 // before increasing window size.
TEST_P(EGLSurfaceTest,GrowWindowThenScissoredClear)611 TEST_P(EGLSurfaceTest, GrowWindowThenScissoredClear)
612 {
613     initializeDisplay();
614     initializeSurfaceWithDefaultConfig(false);
615     initializeMainContext();
616 
617     // Create 64x64 window and make it current
618     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
619     ASSERT_EGL_SUCCESS();
620 
621     // Resize window to 128x128
622     mOSWindow->resize(128, 128);
623 
624     // Perform empty swap
625     eglSwapBuffers(mDisplay, mWindowSurface);
626 
627     // Enable scissor test
628     glEnable(GL_SCISSOR_TEST);
629     ASSERT_GL_NO_ERROR();
630 
631     // Set scissor to (64, 64, 10, 10)
632     glScissor(64, 64, 10, 10);
633     ASSERT_GL_NO_ERROR();
634 
635     // Clear to specific color
636     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
637     glClear(GL_COLOR_BUFFER_BIT);
638 
639     // Disable scissor test
640     glDisable(GL_SCISSOR_TEST);
641     ASSERT_GL_NO_ERROR();
642 
643     EXPECT_PIXEL_RECT_EQ(64, 64, 10, 10, GLColor::blue);
644     ASSERT_GL_NO_ERROR();
645 }
646 
647 // Test that just a ClearBuffer* with an invalid scissor doesn't cause an assert.
TEST_P(EGLSurfaceTest3,ShrinkWindowThenScissoredClearBuffer)648 TEST_P(EGLSurfaceTest3, ShrinkWindowThenScissoredClearBuffer)
649 {
650     initializeDisplay();
651     initializeSurfaceWithDefaultConfig(false);
652     initializeMainContext();
653 
654     // Create 64x64 window and make it current
655     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
656     ASSERT_EGL_SUCCESS();
657 
658     // Resize window to 32x32
659     mOSWindow->resize(32, 32);
660 
661     // Perform empty swap
662     eglSwapBuffers(mDisplay, mWindowSurface);
663 
664     // Enable scissor test
665     glEnable(GL_SCISSOR_TEST);
666     ASSERT_GL_NO_ERROR();
667 
668     // Set scissor to (50, 50, 10, 10)
669     glScissor(50, 50, 10, 10);
670     ASSERT_GL_NO_ERROR();
671 
672     std::vector<GLint> testInt(4);
673     glClearBufferiv(GL_COLOR, 0, testInt.data());
674     std::vector<GLuint> testUint(4);
675     glClearBufferuiv(GL_COLOR, 0, testUint.data());
676     std::vector<GLfloat> testFloat(4);
677     glClearBufferfv(GL_COLOR, 0, testFloat.data());
678 
679     // Disable scissor test
680     glDisable(GL_SCISSOR_TEST);
681     ASSERT_GL_NO_ERROR();
682 }
683 
684 // This is a regression test to verify that surfaces are not prematurely destroyed.
TEST_P(EGLSurfaceTest,SurfaceUseAfterFreeBug)685 TEST_P(EGLSurfaceTest, SurfaceUseAfterFreeBug)
686 {
687     initializeDisplay();
688 
689     // Initialize an RGBA8 window and pbuffer surface
690     constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE,     8,
691                                              EGL_GREEN_SIZE,   8,
692                                              EGL_BLUE_SIZE,    8,
693                                              EGL_ALPHA_SIZE,   8,
694                                              EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
695                                              EGL_NONE};
696 
697     EGLint configCount      = 0;
698     EGLConfig surfaceConfig = nullptr;
699     ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount));
700     ASSERT_NE(configCount, 0);
701     ASSERT_NE(surfaceConfig, nullptr);
702 
703     initializeSurface(surfaceConfig);
704     initializeAllContexts();
705     ASSERT_EGL_SUCCESS();
706     ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
707     ASSERT_NE(mPbufferSurface, EGL_NO_SURFACE);
708 
709     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mSecondContext);
710     ASSERT_EGL_SUCCESS();
711     glClear(GL_COLOR_BUFFER_BIT);
712 
713     eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mContext);
714     ASSERT_EGL_SUCCESS();
715     glClear(GL_COLOR_BUFFER_BIT);
716 
717     eglDestroySurface(mDisplay, mPbufferSurface);
718     ASSERT_EGL_SUCCESS();
719     mPbufferSurface = EGL_NO_SURFACE;
720 
721     eglDestroyContext(mDisplay, mSecondContext);
722     ASSERT_EGL_SUCCESS();
723     mSecondContext = EGL_NO_CONTEXT;
724 }
725 
726 // Test that the window surface is correctly resized after calling swapBuffers
TEST_P(EGLSurfaceTest,ResizeWindow)727 TEST_P(EGLSurfaceTest, ResizeWindow)
728 {
729     // http://anglebug.com/4453
730     ANGLE_SKIP_TEST_IF(isVulkanRenderer() && IsLinux() && IsIntel());
731     // Flaky on Linux SwANGLE http://anglebug.com/4453
732     ANGLE_SKIP_TEST_IF(IsLinux() && isSwiftshader());
733     // http://anglebug.com/5485
734     ANGLE_SKIP_TEST_IF(IsIOS());
735     ANGLE_SKIP_TEST_IF(IsLinux() && IsARM());
736 
737     // Necessary for a window resizing test if there is no per-frame window size query
738     setWindowVisible(mOSWindow, true);
739 
740     GLenum platform               = GetParam().getRenderer();
741     bool platformSupportsZeroSize = platform == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||
742                                     platform == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
743     int minSize = platformSupportsZeroSize ? 0 : 1;
744 
745     initializeDisplay();
746     initializeSurfaceWithDefaultConfig(true);
747     initializeMainContext();
748     ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
749 
750     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
751     eglSwapBuffers(mDisplay, mWindowSurface);
752     ASSERT_EGL_SUCCESS();
753 
754     EGLint height;
755     eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
756     ASSERT_EGL_SUCCESS();
757     ASSERT_EQ(64, height);  // initial size
758 
759     // set window's height to 0 (if possible) or 1
760     mOSWindow->resize(64, minSize);
761 
762     eglSwapBuffers(mDisplay, mWindowSurface);
763     ASSERT_EGL_SUCCESS();
764 
765     // TODO(syoussefi): the GLX implementation still reads the window size as 64x64 through
766     // XGetGeometry.  http://anglebug.com/3122
767     ANGLE_SKIP_TEST_IF(IsLinux() && IsOpenGL());
768 
769     eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
770     ASSERT_EGL_SUCCESS();
771     ASSERT_EQ(minSize, height);
772 
773     // restore window's height
774     mOSWindow->resize(64, 64);
775 
776     eglSwapBuffers(mDisplay, mWindowSurface);
777     ASSERT_EGL_SUCCESS();
778 
779     eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
780     ASSERT_EGL_SUCCESS();
781     ASSERT_EQ(64, height);
782 }
783 
784 // Test that the backbuffer is correctly resized after calling swapBuffers
TEST_P(EGLSurfaceTest,ResizeWindowWithDraw)785 TEST_P(EGLSurfaceTest, ResizeWindowWithDraw)
786 {
787     // http://anglebug.com/4453
788     ANGLE_SKIP_TEST_IF(IsLinux());
789     // http://anglebug.com/5485
790     ANGLE_SKIP_TEST_IF(IsIOS());
791 
792     // Necessary for a window resizing test if there is no per-frame window size query
793     setWindowVisible(mOSWindow, true);
794 
795     initializeDisplay();
796     initializeSurfaceWithDefaultConfig(true);
797     initializeMainContext();
798     ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
799 
800     int size      = 64;
801     EGLint height = 0;
802     EGLint width  = 0;
803 
804     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
805     eglSwapBuffers(mDisplay, mWindowSurface);
806     ASSERT_EGL_SUCCESS();
807 
808     // Clear to red
809     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
810     glClear(GL_COLOR_BUFFER_BIT);
811 
812     eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
813     eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width);
814     ASSERT_EGL_SUCCESS();
815 
816     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
817     EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::red);
818     EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::red);
819     EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::red);
820     EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack);
821     EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack);
822     EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack);
823     EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack);
824 
825     // set window's size small
826     size = 1;
827     mOSWindow->resize(size, size);
828 
829     eglSwapBuffers(mDisplay, mWindowSurface);
830     ASSERT_EGL_SUCCESS();
831 
832     // Clear to green
833     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
834     glClear(GL_COLOR_BUFFER_BIT);
835 
836     eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
837     eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width);
838     ASSERT_EGL_SUCCESS();
839 
840     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
841     EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::green);
842     EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::green);
843     EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::green);
844     EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack);
845     EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack);
846     EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack);
847     EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack);
848 
849     // set window's height large
850     size = 128;
851     mOSWindow->resize(size, size);
852 
853     eglSwapBuffers(mDisplay, mWindowSurface);
854     ASSERT_EGL_SUCCESS();
855 
856     // Clear to blue
857     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
858     glClear(GL_COLOR_BUFFER_BIT);
859 
860     eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);
861     eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width);
862     ASSERT_EGL_SUCCESS();
863 
864     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
865     EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::blue);
866     EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::blue);
867     EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::blue);
868     EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack);
869     EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack);
870     EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack);
871     EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack);
872 }
873 
874 // Test that the window can be reset repeatedly before surface creation.
TEST_P(EGLSurfaceTest,ResetNativeWindow)875 TEST_P(EGLSurfaceTest, ResetNativeWindow)
876 {
877     setWindowVisible(mOSWindow, true);
878 
879     initializeDisplay();
880 
881     for (int i = 0; i < 10; ++i)
882     {
883         mOSWindow->resetNativeWindow();
884     }
885 
886     initializeSurfaceWithDefaultConfig(true);
887     initializeMainContext();
888     ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
889 
890     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
891 
892     eglSwapBuffers(mDisplay, mWindowSurface);
893     ASSERT_EGL_SUCCESS();
894 }
895 
896 // Test swap buffer without any draw calls.
TEST_P(EGLSurfaceTest,SwapWithoutAnyDraw)897 TEST_P(EGLSurfaceTest, SwapWithoutAnyDraw)
898 {
899     initializeDisplay();
900     initializeSurfaceWithDefaultConfig(true);
901     initializeMainContext();
902     ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
903 
904     for (int i = 0; i < 10; ++i)
905     {
906         eglSwapBuffers(mDisplay, mWindowSurface);
907     }
908 }
909 
910 // Test creating a surface that supports a EGLConfig with 16bit
911 // support GL_RGB565
TEST_P(EGLSurfaceTest,CreateWithEGLConfig5650Support)912 TEST_P(EGLSurfaceTest, CreateWithEGLConfig5650Support)
913 {
914     const EGLint configAttributes[] = {EGL_SURFACE_TYPE,
915                                        EGL_WINDOW_BIT,
916                                        EGL_RED_SIZE,
917                                        5,
918                                        EGL_GREEN_SIZE,
919                                        6,
920                                        EGL_BLUE_SIZE,
921                                        5,
922                                        EGL_ALPHA_SIZE,
923                                        0,
924                                        EGL_DEPTH_SIZE,
925                                        0,
926                                        EGL_STENCIL_SIZE,
927                                        0,
928                                        EGL_SAMPLE_BUFFERS,
929                                        0,
930                                        EGL_NONE};
931 
932     initializeDisplay();
933     EGLConfig config;
934     if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
935     {
936         std::cout << "EGLConfig for a GL_RGB565 surface is not supported, skipping test"
937                   << std::endl;
938         return;
939     }
940 
941     initializeSurface(config);
942     initializeMainContext();
943 
944     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
945     ASSERT_EGL_SUCCESS();
946 
947     GLuint program = createProgram();
948     ASSERT_NE(0u, program);
949     drawWithProgram(program);
950     EXPECT_GL_NO_ERROR();
951     glDeleteProgram(program);
952 }
953 
954 // Test creating a surface that supports a EGLConfig with 16bit
955 // support GL_RGBA4
TEST_P(EGLSurfaceTest,CreateWithEGLConfig4444Support)956 TEST_P(EGLSurfaceTest, CreateWithEGLConfig4444Support)
957 {
958     const EGLint configAttributes[] = {EGL_SURFACE_TYPE,
959                                        EGL_WINDOW_BIT,
960                                        EGL_RED_SIZE,
961                                        4,
962                                        EGL_GREEN_SIZE,
963                                        4,
964                                        EGL_BLUE_SIZE,
965                                        4,
966                                        EGL_ALPHA_SIZE,
967                                        4,
968                                        EGL_DEPTH_SIZE,
969                                        0,
970                                        EGL_STENCIL_SIZE,
971                                        0,
972                                        EGL_SAMPLE_BUFFERS,
973                                        0,
974                                        EGL_NONE};
975 
976     initializeDisplay();
977     EGLConfig config;
978     if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
979     {
980         std::cout << "EGLConfig for a GL_RGBA4 surface is not supported, skipping test"
981                   << std::endl;
982         return;
983     }
984 
985     initializeSurface(config);
986     initializeMainContext();
987 
988     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
989     ASSERT_EGL_SUCCESS();
990 
991     GLuint program = createProgram();
992     ASSERT_NE(0u, program);
993     drawWithProgram(program);
994     EXPECT_GL_NO_ERROR();
995     glDeleteProgram(program);
996 }
997 
998 // Test creating a surface that supports a EGLConfig with 16bit
999 // support GL_RGB5_A1
TEST_P(EGLSurfaceTest,CreateWithEGLConfig5551Support)1000 TEST_P(EGLSurfaceTest, CreateWithEGLConfig5551Support)
1001 {
1002     const EGLint configAttributes[] = {EGL_SURFACE_TYPE,
1003                                        EGL_WINDOW_BIT,
1004                                        EGL_RED_SIZE,
1005                                        5,
1006                                        EGL_GREEN_SIZE,
1007                                        5,
1008                                        EGL_BLUE_SIZE,
1009                                        5,
1010                                        EGL_ALPHA_SIZE,
1011                                        1,
1012                                        EGL_DEPTH_SIZE,
1013                                        0,
1014                                        EGL_STENCIL_SIZE,
1015                                        0,
1016                                        EGL_SAMPLE_BUFFERS,
1017                                        0,
1018                                        EGL_NONE};
1019 
1020     initializeDisplay();
1021     EGLConfig config;
1022     if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
1023     {
1024         std::cout << "EGLConfig for a GL_RGB5_A1 surface is not supported, skipping test"
1025                   << std::endl;
1026         return;
1027     }
1028 
1029     initializeSurface(config);
1030     initializeMainContext();
1031 
1032     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
1033     ASSERT_EGL_SUCCESS();
1034 
1035     GLuint program = createProgram();
1036     ASSERT_NE(0u, program);
1037     drawWithProgram(program);
1038     EXPECT_GL_NO_ERROR();
1039     glDeleteProgram(program);
1040 }
1041 
1042 // Test creating a surface that supports a EGLConfig without alpha support
TEST_P(EGLSurfaceTest,CreateWithEGLConfig8880Support)1043 TEST_P(EGLSurfaceTest, CreateWithEGLConfig8880Support)
1044 {
1045     const EGLint configAttributes[] = {EGL_SURFACE_TYPE,
1046                                        EGL_WINDOW_BIT,
1047                                        EGL_RED_SIZE,
1048                                        8,
1049                                        EGL_GREEN_SIZE,
1050                                        8,
1051                                        EGL_BLUE_SIZE,
1052                                        8,
1053                                        EGL_ALPHA_SIZE,
1054                                        0,
1055                                        EGL_DEPTH_SIZE,
1056                                        0,
1057                                        EGL_STENCIL_SIZE,
1058                                        0,
1059                                        EGL_SAMPLE_BUFFERS,
1060                                        0,
1061                                        EGL_NONE};
1062 
1063     initializeDisplay();
1064     EGLConfig config;
1065     if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
1066     {
1067         std::cout << "EGLConfig for a GL_RGB8_OES surface is not supported, skipping test"
1068                   << std::endl;
1069         return;
1070     }
1071 
1072     initializeSurface(config);
1073     initializeMainContext();
1074 
1075     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
1076     ASSERT_EGL_SUCCESS();
1077 
1078     GLuint program = createProgram();
1079     ASSERT_NE(0u, program);
1080     drawWithProgram(program);
1081     EXPECT_GL_NO_ERROR();
1082     glDeleteProgram(program);
1083 }
1084 
1085 // Test creating a surface that supports GL_RGB10_A2 with BT2020 colorspaces
TEST_P(EGLSurfaceTest,CreateWithEGLConfig1010102Support)1086 TEST_P(EGLSurfaceTest, CreateWithEGLConfig1010102Support)
1087 {
1088     const EGLint configAttributes[] = {EGL_SURFACE_TYPE,
1089                                        EGL_WINDOW_BIT,
1090                                        EGL_RED_SIZE,
1091                                        10,
1092                                        EGL_GREEN_SIZE,
1093                                        10,
1094                                        EGL_BLUE_SIZE,
1095                                        10,
1096                                        EGL_ALPHA_SIZE,
1097                                        2,
1098                                        EGL_DEPTH_SIZE,
1099                                        0,
1100                                        EGL_STENCIL_SIZE,
1101                                        0,
1102                                        EGL_SAMPLE_BUFFERS,
1103                                        0,
1104                                        EGL_NONE};
1105 
1106     initializeDisplay();
1107     ASSERT_NE(mDisplay, EGL_NO_DISPLAY);
1108 
1109     if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &mConfig) == EGL_FALSE)
1110     {
1111         std::cout << "EGLConfig for a GL_RGB10_A2 surface is not supported, skipping test"
1112                   << std::endl;
1113         return;
1114     }
1115 
1116     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_gl_colorspace_bt2020_hlg"));
1117     ANGLE_SKIP_TEST_IF(
1118         !IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_gl_colorspace_bt2020_linear"));
1119     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_gl_colorspace_bt2020_pq"));
1120 
1121     initializeMainContext();
1122     ASSERT_NE(mContext, EGL_NO_CONTEXT);
1123 
1124     constexpr std::array<EGLint, 3u> kBt2020Colorspaces = {EGL_GL_COLORSPACE_BT2020_HLG_EXT,
1125                                                            EGL_GL_COLORSPACE_BT2020_LINEAR_EXT,
1126                                                            EGL_GL_COLORSPACE_BT2020_PQ_EXT};
1127     for (EGLint bt2020Colorspace : kBt2020Colorspaces)
1128     {
1129         std::vector<EGLint> winSurfaceAttribs;
1130         winSurfaceAttribs.push_back(EGL_GL_COLORSPACE_KHR);
1131         winSurfaceAttribs.push_back(bt2020Colorspace);
1132 
1133         initializeWindowSurfaceWithAttribs(mConfig, winSurfaceAttribs, EGL_SUCCESS);
1134         ASSERT_EGL_SUCCESS();
1135         ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
1136 
1137         EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext));
1138         ASSERT_EGL_SUCCESS();
1139 
1140         GLuint program = createProgram();
1141         ASSERT_NE(0u, program);
1142         drawWithProgram(program);
1143         EXPECT_GL_NO_ERROR();
1144         glDeleteProgram(program);
1145 
1146         eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
1147         eglDestroySurface(mDisplay, mWindowSurface);
1148         mWindowSurface = EGL_NO_SURFACE;
1149     }
1150 }
1151 
TEST_P(EGLSurfaceTest,FixedSizeWindow)1152 TEST_P(EGLSurfaceTest, FixedSizeWindow)
1153 {
1154     const EGLint configAttributes[] = {EGL_SURFACE_TYPE,
1155                                        EGL_WINDOW_BIT,
1156                                        EGL_RED_SIZE,
1157                                        8,
1158                                        EGL_GREEN_SIZE,
1159                                        8,
1160                                        EGL_BLUE_SIZE,
1161                                        8,
1162                                        EGL_ALPHA_SIZE,
1163                                        0,
1164                                        EGL_DEPTH_SIZE,
1165                                        0,
1166                                        EGL_STENCIL_SIZE,
1167                                        0,
1168                                        EGL_SAMPLE_BUFFERS,
1169                                        0,
1170                                        EGL_NONE};
1171 
1172     initializeDisplay();
1173     ANGLE_SKIP_TEST_IF(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &mConfig) == EGL_FALSE);
1174 
1175     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_window_fixed_size"));
1176 
1177     constexpr EGLint kInitialSize = 64;
1178     constexpr EGLint kUpdateSize  = 32;
1179 
1180     EGLint surfaceAttributes[] = {
1181         EGL_FIXED_SIZE_ANGLE, EGL_TRUE, EGL_WIDTH, kInitialSize, EGL_HEIGHT, kInitialSize, EGL_NONE,
1182     };
1183 
1184     // Create first window surface
1185     mWindowSurface =
1186         eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), surfaceAttributes);
1187     ASSERT_EGL_SUCCESS();
1188     ASSERT_NE(EGL_NO_SURFACE, mWindowSurface);
1189 
1190     initializeMainContext();
1191     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext));
1192     ASSERT_EGL_SUCCESS();
1193 
1194     EGLint queryIsFixedSize = 0;
1195     EXPECT_EGL_TRUE(
1196         eglQuerySurface(mDisplay, mWindowSurface, EGL_FIXED_SIZE_ANGLE, &queryIsFixedSize));
1197     ASSERT_EGL_SUCCESS();
1198     EXPECT_EGL_TRUE(queryIsFixedSize);
1199 
1200     EGLint queryWidth = 0;
1201     EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &queryWidth));
1202     ASSERT_EGL_SUCCESS();
1203     EXPECT_EQ(kInitialSize, queryWidth);
1204 
1205     EGLint queryHeight = 0;
1206     EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &queryHeight));
1207     ASSERT_EGL_SUCCESS();
1208     EXPECT_EQ(kInitialSize, queryHeight);
1209 
1210     // Update the size
1211     EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, mWindowSurface, EGL_WIDTH, kUpdateSize));
1212     ASSERT_EGL_SUCCESS();
1213 
1214     EXPECT_EGL_TRUE(eglWaitNative(EGL_CORE_NATIVE_ENGINE));
1215     ASSERT_EGL_SUCCESS();
1216 
1217     EGLint queryUpdatedWidth = 0;
1218     EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &queryUpdatedWidth));
1219     ASSERT_EGL_SUCCESS();
1220     EXPECT_EQ(kUpdateSize, queryUpdatedWidth);
1221 }
1222 
TEST_P(EGLSurfaceTest3,MakeCurrentDifferentSurfaces)1223 TEST_P(EGLSurfaceTest3, MakeCurrentDifferentSurfaces)
1224 {
1225     const EGLint configAttributes[] = {
1226         EGL_RED_SIZE,   8, EGL_GREEN_SIZE,   8, EGL_BLUE_SIZE,      8, EGL_ALPHA_SIZE, 8,
1227         EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};
1228     EGLSurface firstPbufferSurface;
1229     EGLSurface secondPbufferSurface;
1230 
1231     initializeDisplay();
1232     ANGLE_SKIP_TEST_IF(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &mConfig) == EGL_FALSE);
1233 
1234     EGLint surfaceType = 0;
1235     eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType);
1236     bool supportsPbuffers    = (surfaceType & EGL_PBUFFER_BIT) != 0;
1237     EGLint bindToTextureRGBA = 0;
1238     eglGetConfigAttrib(mDisplay, mConfig, EGL_BIND_TO_TEXTURE_RGBA, &bindToTextureRGBA);
1239     bool supportsBindTexImage = (bindToTextureRGBA == EGL_TRUE);
1240 
1241     const EGLint pBufferAttributes[] = {
1242         EGL_WIDTH,          64,
1243         EGL_HEIGHT,         64,
1244         EGL_TEXTURE_FORMAT, supportsPbuffers ? EGL_TEXTURE_RGBA : EGL_NO_TEXTURE,
1245         EGL_TEXTURE_TARGET, supportsBindTexImage ? EGL_TEXTURE_2D : EGL_NO_TEXTURE,
1246         EGL_NONE,           EGL_NONE,
1247     };
1248 
1249     // Create the surfaces
1250     firstPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, pBufferAttributes);
1251     ASSERT_EGL_SUCCESS();
1252     ASSERT_NE(EGL_NO_SURFACE, firstPbufferSurface);
1253     secondPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, pBufferAttributes);
1254     ASSERT_EGL_SUCCESS();
1255     ASSERT_NE(EGL_NO_SURFACE, secondPbufferSurface);
1256 
1257     initializeMainContext();
1258 
1259     // Use the same surface for both draw and read
1260     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, firstPbufferSurface, firstPbufferSurface, mContext));
1261 
1262     // TODO(http://www.anglebug.com/6284): Failing with OpenGL ES backend on Android.
1263     // Must be after the eglMakeCurrent() so the renderer string is initialized.
1264     ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsAndroid());
1265 
1266     glClearColor(kFloatRed.R, kFloatRed.G, kFloatRed.B, kFloatRed.A);
1267     glClear(GL_COLOR_BUFFER_BIT);
1268     ASSERT_GL_NO_ERROR();
1269     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1270 
1271     // Use different surfaces for draw and read, read should stay the same
1272     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, secondPbufferSurface, firstPbufferSurface, mContext));
1273     glClearColor(kFloatBlue.R, kFloatBlue.G, kFloatBlue.B, kFloatBlue.A);
1274     glClear(GL_COLOR_BUFFER_BIT);
1275     ASSERT_GL_NO_ERROR();
1276     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1277     // Verify draw surface was cleared
1278     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, secondPbufferSurface, secondPbufferSurface, mContext));
1279     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1280 
1281     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, firstPbufferSurface, secondPbufferSurface, mContext));
1282     ASSERT_EGL_SUCCESS();
1283 
1284     // Blit the source surface to the destination surface
1285     glBlitFramebuffer(0, 0, 64, 64, 0, 0, 64, 64, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1286     ASSERT_GL_NO_ERROR();
1287     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, firstPbufferSurface, firstPbufferSurface, mContext));
1288     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1289 }
1290 
1291 #if defined(ANGLE_ENABLE_D3D11)
1292 class EGLSurfaceTestD3D11 : public EGLSurfaceTest
1293 {
1294   protected:
1295     // offset - draw into the texture at offset (|offset|, |offset|)
1296     // pix25 - the expected pixel value at (25, 25)
1297     // pix75 - the expected pixel value at (75, 75)
testTextureOffset(int offset,UINT pix25,UINT pix75)1298     void testTextureOffset(int offset, UINT pix25, UINT pix75)
1299     {
1300         initializeDisplay();
1301 
1302         const EGLint configAttributes[] = {
1303             EGL_RED_SIZE,   8, EGL_GREEN_SIZE,   8, EGL_BLUE_SIZE,      8, EGL_ALPHA_SIZE, 8,
1304             EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};
1305 
1306         EGLConfig config;
1307         ASSERT_EGL_TRUE(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config));
1308 
1309         mConfig = config;
1310         initializeMainContext();
1311 
1312         EGLAttrib device       = 0;
1313         EGLAttrib newEglDevice = 0;
1314         ASSERT_EGL_TRUE(eglQueryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, &newEglDevice));
1315         ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(newEglDevice),
1316                                                 EGL_D3D11_DEVICE_ANGLE, &device));
1317         angle::ComPtr<ID3D11Device> d3d11Device(reinterpret_cast<ID3D11Device *>(device));
1318         ASSERT_TRUE(!!d3d11Device);
1319 
1320         constexpr UINT kTextureWidth  = 100;
1321         constexpr UINT kTextureHeight = 100;
1322         constexpr Color<uint8_t> kOpaqueBlack(0, 0, 0, 255);
1323         std::vector<Color<uint8_t>> textureData(kTextureWidth * kTextureHeight, kOpaqueBlack);
1324 
1325         D3D11_SUBRESOURCE_DATA initialData = {};
1326         initialData.pSysMem                = textureData.data();
1327         initialData.SysMemPitch            = kTextureWidth * sizeof(kOpaqueBlack);
1328 
1329         D3D11_TEXTURE2D_DESC desc = {};
1330         desc.Format               = DXGI_FORMAT_B8G8R8A8_UNORM;
1331         desc.Width                = kTextureWidth;
1332         desc.Height               = kTextureHeight;
1333         desc.ArraySize            = 1;
1334         desc.MipLevels            = 1;
1335         desc.SampleDesc.Count     = 1;
1336         desc.Usage                = D3D11_USAGE_DEFAULT;
1337         desc.BindFlags            = D3D11_BIND_RENDER_TARGET;
1338         angle::ComPtr<ID3D11Texture2D> texture;
1339         HRESULT hr = d3d11Device->CreateTexture2D(&desc, &initialData, &texture);
1340         ASSERT_TRUE(SUCCEEDED(hr));
1341 
1342         angle::ComPtr<ID3D11DeviceContext> d3d11Context;
1343         d3d11Device->GetImmediateContext(&d3d11Context);
1344 
1345         // Specify a texture offset of (50, 50) when rendering to the pbuffer surface.
1346         const EGLint surfaceAttributes[] = {EGL_WIDTH,
1347                                             kTextureWidth,
1348                                             EGL_HEIGHT,
1349                                             kTextureHeight,
1350                                             EGL_TEXTURE_OFFSET_X_ANGLE,
1351                                             offset,
1352                                             EGL_TEXTURE_OFFSET_Y_ANGLE,
1353                                             offset,
1354                                             EGL_NONE};
1355         EGLClientBuffer buffer           = reinterpret_cast<EGLClientBuffer>(texture.Get());
1356         mPbufferSurface = eglCreatePbufferFromClientBuffer(mDisplay, EGL_D3D_TEXTURE_ANGLE, buffer,
1357                                                            config, surfaceAttributes);
1358         ASSERT_EGL_SUCCESS();
1359 
1360         eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mContext);
1361         ASSERT_EGL_SUCCESS();
1362 
1363         // glClear should only clear subrect at offset (50, 50) without explicit scissor.
1364         glClearColor(0, 0, 1, 1);  // Blue
1365         glClear(GL_COLOR_BUFFER_BIT);
1366         EXPECT_PIXEL_EQ(25, 25, 0, 0, pix25, 255);
1367         EXPECT_PIXEL_EQ(75, 75, 0, 0, pix75, 255);
1368         EXPECT_GL_NO_ERROR();
1369 
1370         // Drawing with a shader should also update the same subrect only without explicit viewport.
1371         GLuint program = createProgram();  // Red
1372         ASSERT_NE(0u, program);
1373         GLint positionLocation =
1374             glGetAttribLocation(program, angle::essl1_shaders::PositionAttrib());
1375         glUseProgram(program);
1376         const GLfloat vertices[] = {
1377             -1.0f, 1.0f, 0.5f, -1.0f, -1.0f, 0.5f, 1.0f, -1.0f, 0.5f,
1378             -1.0f, 1.0f, 0.5f, 1.0f,  -1.0f, 0.5f, 1.0f, 1.0f,  0.5f,
1379         };
1380         glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
1381         glEnableVertexAttribArray(positionLocation);
1382         glDrawArrays(GL_TRIANGLES, 0, 6);
1383         glDisableVertexAttribArray(positionLocation);
1384         glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
1385 
1386         EXPECT_PIXEL_EQ(25, 25, pix25, 0, 0, 255);
1387         EXPECT_PIXEL_EQ(75, 75, pix75, 0, 0, 255);
1388         EXPECT_GL_NO_ERROR();
1389 
1390         glDeleteProgram(program);
1391         EXPECT_GL_NO_ERROR();
1392 
1393         // Blit framebuffer should also blit to the same subrect despite the dstX/Y arguments.
1394         GLRenderbuffer renderBuffer;
1395         glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
1396         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 50, 50);
1397         EXPECT_GL_NO_ERROR();
1398 
1399         GLFramebuffer framebuffer;
1400         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1401         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1402                                   renderBuffer);
1403         EXPECT_GL_NO_ERROR();
1404 
1405         glClearColor(0, 1, 0, 1);  // Green
1406         glClear(GL_COLOR_BUFFER_BIT);
1407         EXPECT_PIXEL_EQ(25, 25, 0, 255, 0, 255);
1408         EXPECT_GL_NO_ERROR();
1409 
1410         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0u);
1411         glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1412         glBlitFramebuffer(0, 0, 50, 50, 0, 0, kTextureWidth, kTextureWidth, GL_COLOR_BUFFER_BIT,
1413                           GL_NEAREST);
1414         EXPECT_GL_NO_ERROR();
1415 
1416         glBindFramebuffer(GL_READ_FRAMEBUFFER, 0u);
1417         EXPECT_PIXEL_EQ(25, 25, 0, pix25, 0, 255);
1418         EXPECT_PIXEL_EQ(75, 75, 0, pix75, 0, 255);
1419         EXPECT_GL_NO_ERROR();
1420     }
1421 
1422     // Draws into a surface at the specified offset using the values of gl_FragCoord in the
1423     // fragment shader.
1424     // texturedimension - dimension of the D3D texture and surface.
1425     // offset - draw into the texture at offset (|offset|, |offset|)
setupFragCoordOffset(int textureDimension,int offset)1426     void setupFragCoordOffset(int textureDimension, int offset)
1427     {
1428         ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d"));
1429         initializeDisplay();
1430 
1431         EGLAttrib device       = 0;
1432         EGLAttrib newEglDevice = 0;
1433         ASSERT_EGL_TRUE(eglQueryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, &newEglDevice));
1434         ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(newEglDevice),
1435                                                 EGL_D3D11_DEVICE_ANGLE, &device));
1436         angle::ComPtr<ID3D11Device> d3d11Device(reinterpret_cast<ID3D11Device *>(device));
1437         ASSERT_TRUE(!!d3d11Device);
1438 
1439         D3D11_TEXTURE2D_DESC desc = {};
1440         desc.Format               = DXGI_FORMAT_B8G8R8A8_UNORM;
1441         desc.Width                = textureDimension;
1442         desc.Height               = textureDimension;
1443         desc.ArraySize            = 1;
1444         desc.MipLevels            = 1;
1445         desc.SampleDesc.Count     = 1;
1446         desc.Usage                = D3D11_USAGE_DEFAULT;
1447         desc.BindFlags            = D3D11_BIND_RENDER_TARGET;
1448         angle::ComPtr<ID3D11Texture2D> texture;
1449         HRESULT hr = d3d11Device->CreateTexture2D(&desc, nullptr, &texture);
1450         ASSERT_TRUE(SUCCEEDED(hr));
1451 
1452         const EGLint surfaceAttributes[] = {EGL_WIDTH,
1453                                             textureDimension,
1454                                             EGL_HEIGHT,
1455                                             textureDimension,
1456                                             EGL_TEXTURE_OFFSET_X_ANGLE,
1457                                             offset,
1458                                             EGL_TEXTURE_OFFSET_Y_ANGLE,
1459                                             offset,
1460                                             EGL_NONE};
1461         EGLClientBuffer buffer           = reinterpret_cast<EGLClientBuffer>(texture.Get());
1462 
1463         const EGLint configAttributes[] = {
1464             EGL_RED_SIZE,   8, EGL_GREEN_SIZE,   8, EGL_BLUE_SIZE,      8, EGL_ALPHA_SIZE, 8,
1465             EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};
1466 
1467         EGLConfig config;
1468         ASSERT_EGL_TRUE(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config));
1469         mConfig = config;
1470 
1471         mPbufferSurface = eglCreatePbufferFromClientBuffer(mDisplay, EGL_D3D_TEXTURE_ANGLE, buffer,
1472                                                            config, surfaceAttributes);
1473         ASSERT_EGL_SUCCESS();
1474 
1475         initializeMainContext();
1476 
1477         eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mContext);
1478         ASSERT_EGL_SUCCESS();
1479 
1480         // Fragment shader that uses the gl_FragCoord values to output the (x, y) position of
1481         // the current pixel as the color.
1482         //    - Reverse the offset that was applied to the original coordinates
1483         //    - 0.5 is subtracted because gl_FragCoord gives the pixel center
1484         //    - Divided by the size to give a max value of 1
1485         std::stringstream fs;
1486         fs << "precision mediump float;" << "void main()" << "{" << "    float dimension = float("
1487            << textureDimension << ");" << "    float offset = float(" << offset << ");"
1488            << "    gl_FragColor = vec4((gl_FragCoord.x + offset - 0.5) / dimension,"
1489            << "                        (gl_FragCoord.y + offset - 0.5) / dimension,"
1490            << "                         gl_FragCoord.z,"
1491            << "                         gl_FragCoord.w);" << "}";
1492 
1493         GLuint program = createProgram(fs.str().c_str());
1494         ASSERT_NE(0u, program);
1495         glUseProgram(program);
1496 
1497         glClearColor(0, 0, 0, 1);
1498         glClear(GL_COLOR_BUFFER_BIT);
1499 
1500         const GLfloat vertices[] = {
1501             -1.0f, 1.0f, 0.5f, -1.0f, -1.0f, 0.5f, 1.0f, -1.0f, 0.5f,
1502             -1.0f, 1.0f, 0.5f, 1.0f,  -1.0f, 0.5f, 1.0f, 1.0f,  0.5f,
1503         };
1504 
1505         GLint positionLocation =
1506             glGetAttribLocation(program, angle::essl1_shaders::PositionAttrib());
1507         glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
1508         glEnableVertexAttribArray(positionLocation);
1509 
1510         glDrawArrays(GL_TRIANGLES, 0, 6);
1511 
1512         glDisableVertexAttribArray(positionLocation);
1513 
1514         glDeleteProgram(program);
1515 
1516         EXPECT_GL_NO_ERROR();
1517     }
1518 };
1519 
1520 // Test that rendering to an IDCompositionSurface using a pbuffer works.
TEST_P(EGLSurfaceTestD3D11,CreateDirectCompositionSurface)1521 TEST_P(EGLSurfaceTestD3D11, CreateDirectCompositionSurface)
1522 {
1523     ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d"));
1524     initializeDisplay();
1525 
1526     EGLAttrib device       = 0;
1527     EGLAttrib newEglDevice = 0;
1528     ASSERT_EGL_TRUE(eglQueryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, &newEglDevice));
1529     ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(newEglDevice),
1530                                             EGL_D3D11_DEVICE_ANGLE, &device));
1531     angle::ComPtr<ID3D11Device> d3d11Device(reinterpret_cast<ID3D11Device *>(device));
1532     ASSERT_TRUE(!!d3d11Device);
1533 
1534     HMODULE dcompLibrary = LoadLibraryA("dcomp.dll");
1535     if (!dcompLibrary)
1536     {
1537         std::cout << "DirectComposition not supported" << std::endl;
1538         return;
1539     }
1540     typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE2)(IUnknown * dxgiDevice, REFIID iid,
1541                                                               void **dcompositionDevice);
1542     PFN_DCOMPOSITION_CREATE_DEVICE2 createDComp = reinterpret_cast<PFN_DCOMPOSITION_CREATE_DEVICE2>(
1543         GetProcAddress(dcompLibrary, "DCompositionCreateDevice2"));
1544     if (!createDComp)
1545     {
1546         std::cout << "DirectComposition2 not supported" << std::endl;
1547         FreeLibrary(dcompLibrary);
1548         return;
1549     }
1550 
1551     angle::ComPtr<IDCompositionDevice> dcompDevice;
1552     HRESULT hr = createDComp(d3d11Device.Get(), IID_PPV_ARGS(dcompDevice.GetAddressOf()));
1553     ASSERT_TRUE(SUCCEEDED(hr));
1554 
1555     angle::ComPtr<IDCompositionSurface> dcompSurface;
1556     hr = dcompDevice->CreateSurface(100, 100, DXGI_FORMAT_B8G8R8A8_UNORM,
1557                                     DXGI_ALPHA_MODE_PREMULTIPLIED, dcompSurface.GetAddressOf());
1558     ASSERT_TRUE(SUCCEEDED(hr));
1559 
1560     angle::ComPtr<ID3D11Texture2D> texture;
1561     POINT updateOffset;
1562     hr = dcompSurface->BeginDraw(nullptr, IID_PPV_ARGS(texture.GetAddressOf()), &updateOffset);
1563     ASSERT_TRUE(SUCCEEDED(hr));
1564 
1565     const EGLint configAttributes[] = {
1566         EGL_RED_SIZE,   8, EGL_GREEN_SIZE,   8, EGL_BLUE_SIZE,      8, EGL_ALPHA_SIZE, 8,
1567         EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};
1568 
1569     EGLConfig config;
1570     ASSERT_EGL_TRUE(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config));
1571 
1572     const EGLint surfaceAttributes[] = {EGL_WIDTH,
1573                                         100,
1574                                         EGL_HEIGHT,
1575                                         100,
1576                                         EGL_TEXTURE_OFFSET_X_ANGLE,
1577                                         updateOffset.x,
1578                                         EGL_TEXTURE_OFFSET_Y_ANGLE,
1579                                         updateOffset.y,
1580                                         EGL_NONE};
1581 
1582     EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(texture.Get());
1583     mPbufferSurface = eglCreatePbufferFromClientBuffer(mDisplay, EGL_D3D_TEXTURE_ANGLE, buffer,
1584                                                        config, surfaceAttributes);
1585     ASSERT_EGL_SUCCESS();
1586 
1587     mConfig = config;
1588     initializeMainContext();
1589 
1590     eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mContext);
1591     ASSERT_EGL_SUCCESS();
1592 
1593     GLuint program = createProgram();
1594     ASSERT_NE(0u, program);
1595     drawWithProgram(program);
1596     EXPECT_GL_NO_ERROR();
1597     glDeleteProgram(program);
1598 }
1599 
1600 // Tests drawing into a surface created with negative offsets.
TEST_P(EGLSurfaceTestD3D11,CreateSurfaceWithTextureNegativeOffset)1601 TEST_P(EGLSurfaceTestD3D11, CreateSurfaceWithTextureNegativeOffset)
1602 {
1603     ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d"));
1604     testTextureOffset(-50, 255, 0);
1605 }
1606 
1607 // Tests drawing into a surface created with offsets.
TEST_P(EGLSurfaceTestD3D11,CreateSurfaceWithTextureOffset)1608 TEST_P(EGLSurfaceTestD3D11, CreateSurfaceWithTextureOffset)
1609 {
1610     ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d"));
1611     testTextureOffset(50, 0, 255);
1612 }
1613 
TEST_P(EGLSurfaceTestD3D11,CreateSurfaceWithMSAA)1614 TEST_P(EGLSurfaceTestD3D11, CreateSurfaceWithMSAA)
1615 {
1616     ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d"));
1617 
1618     // clang-format off
1619     const EGLint configAttributes[] =
1620     {
1621         EGL_RED_SIZE, 8,
1622         EGL_GREEN_SIZE, 8,
1623         EGL_BLUE_SIZE, 8,
1624         EGL_ALPHA_SIZE, 0,
1625         EGL_DEPTH_SIZE, 0,
1626         EGL_STENCIL_SIZE, 0,
1627         EGL_SAMPLE_BUFFERS, 1,
1628         EGL_SAMPLES, 4,
1629         EGL_NONE
1630     };
1631     // clang-format on
1632 
1633     initializeDisplay();
1634     EGLConfig config;
1635     if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)
1636     {
1637         std::cout << "EGLConfig for 4xMSAA is not supported, skipping test" << std::endl;
1638         return;
1639     }
1640 
1641     initializeSurface(config);
1642     initializeMainContext();
1643 
1644     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
1645     ASSERT_EGL_SUCCESS();
1646 
1647     GLuint program = createProgram();
1648     ASSERT_NE(0u, program);
1649 
1650     glClearColor(0, 0, 0, 1);
1651     glClear(GL_COLOR_BUFFER_BIT);
1652 
1653     GLint positionLocation = glGetAttribLocation(program, angle::essl1_shaders::PositionAttrib());
1654     ASSERT_NE(-1, positionLocation);
1655 
1656     glUseProgram(program);
1657 
1658     const GLfloat halfPixelOffset = 0.5f * 2.0f / mOSWindow->getWidth();
1659     // clang-format off
1660     const GLfloat vertices[] =
1661     {
1662         -1.0f + halfPixelOffset,  1.0f, 0.5f,
1663         -1.0f + halfPixelOffset, -1.0f, 0.5f,
1664          1.0f,                   -1.0f, 0.5f
1665     };
1666     // clang-format on
1667 
1668     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
1669     glEnableVertexAttribArray(positionLocation);
1670 
1671     glDrawArrays(GL_TRIANGLES, 0, 3);
1672 
1673     glDisableVertexAttribArray(positionLocation);
1674     glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
1675 
1676     EXPECT_PIXEL_NEAR(0, 0, 127, 0, 0, 255, 10);
1677     EXPECT_GL_NO_ERROR();
1678 
1679     glDeleteProgram(program);
1680 }
1681 
1682 // Tests that gl_FragCoord.xy is offset with the EGL_TEXTURE_OFFSET_[X|Y]_ANGLE values specified
1683 // at surface creation, using positive offsets
TEST_P(EGLSurfaceTestD3D11,FragCoordOffset)1684 TEST_P(EGLSurfaceTestD3D11, FragCoordOffset)
1685 {
1686     constexpr int kTextureDimension = 28;
1687     constexpr int kOffset           = 6;
1688 
1689     setupFragCoordOffset(kTextureDimension, kOffset);
1690 
1691     // With a positive offset, nothing is drawn in any pixels to the left of and above |kOffset|.
1692     for (int x = 0; x < kOffset; x++)
1693     {
1694         for (int y = 0; y < kOffset; y++)
1695         {
1696             EXPECT_PIXEL_EQ(x, y, 0, 0, 0, 0);
1697         }
1698     }
1699 
1700     // The rest of the texture's color should be the value of the (x, y) coordinates.
1701     for (int x = kOffset; x < kTextureDimension; x++)
1702     {
1703         for (int y = kOffset; y < kTextureDimension; y++)
1704         {
1705             EXPECT_PIXEL_NEAR(x, y, x * 255.0 / kTextureDimension, y * 255.0 / kTextureDimension,
1706                               191, 255, 0.5);
1707         }
1708     }
1709 }
1710 
1711 // Tests that gl_FragCoord.xy is offset with the EGL_TEXTURE_OFFSET_[X|Y]_ANGLE values specified
1712 // at surface creation, using negative offsets.
TEST_P(EGLSurfaceTestD3D11,FragCoordOffsetNegative)1713 TEST_P(EGLSurfaceTestD3D11, FragCoordOffsetNegative)
1714 {
1715     constexpr int kTextureDimension = 28;
1716     constexpr int kOffset           = 6;
1717 
1718     setupFragCoordOffset(kTextureDimension, -kOffset);
1719 
1720     // With a negative offset, nothing is drawn in pixels to the right of and below |koffset|.
1721     for (int x = kTextureDimension - kOffset; x < kTextureDimension; x++)
1722     {
1723         for (int y = kTextureDimension - kOffset; y < kTextureDimension; y++)
1724         {
1725             EXPECT_PIXEL_EQ(x, y, 0, 0, 0, 0);
1726         }
1727     }
1728 
1729     // The rest of the texture's color should be the value of the (x, y) coordinates.
1730     for (int x = 0; x < kTextureDimension - kOffset; x++)
1731     {
1732         for (int y = 0; y < kTextureDimension - kOffset; y++)
1733         {
1734             EXPECT_PIXEL_NEAR(x, y, x * 255.0 / kTextureDimension, y * 255.0 / kTextureDimension,
1735                               191, 255, 0.5);
1736         }
1737     }
1738 }
1739 
1740 #endif  // ANGLE_ENABLE_D3D11
1741 
1742 // Verify bliting between two surfaces works correctly.
TEST_P(EGLSurfaceTest3,BlitBetweenSurfaces)1743 TEST_P(EGLSurfaceTest3, BlitBetweenSurfaces)
1744 {
1745     initializeDisplay();
1746     ASSERT_NE(mDisplay, EGL_NO_DISPLAY);
1747 
1748     initializeSurfaceWithDefaultConfig(true);
1749     initializeMainContext();
1750     ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
1751     ASSERT_NE(mContext, EGL_NO_CONTEXT);
1752 
1753     EGLSurface surface1;
1754     EGLSurface surface2;
1755 
1756     const EGLint surfaceAttributes[] = {
1757         EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE,
1758     };
1759 
1760     surface1 = eglCreatePbufferSurface(mDisplay, mConfig, surfaceAttributes);
1761     ASSERT_EGL_SUCCESS();
1762     surface2 = eglCreatePbufferSurface(mDisplay, mConfig, surfaceAttributes);
1763     ASSERT_EGL_SUCCESS();
1764 
1765     // Clear surface1.
1766     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface1, surface1, mContext));
1767 
1768     // TODO(http://www.anglebug.com/6284): Failing with OpenGL ES backend on Android and Windows.
1769     // Must be after the eglMakeCurrent() so the renderer string is initialized.
1770     ANGLE_SKIP_TEST_IF(IsOpenGLES() && (IsAndroid() || IsWindows()));
1771 
1772     glClearColor(kFloatRed.R, kFloatRed.G, kFloatRed.B, kFloatRed.A);
1773     glClear(GL_COLOR_BUFFER_BIT);
1774     ASSERT_GL_NO_ERROR();
1775 
1776     // Blit from surface1 to surface2.
1777     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface2, surface1, mContext));
1778     glBlitFramebuffer(0, 0, 64, 64, 0, 0, 64, 64, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1779     ASSERT_GL_NO_ERROR();
1780 
1781     // Confirm surface1 has the clear color.
1782     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface1, surface1, mContext));
1783     EXPECT_PIXEL_COLOR_EQ(32, 32, GLColor::red);
1784 
1785     // Confirm surface2 has the blited clear color.
1786     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface2, surface2, mContext));
1787     EXPECT_PIXEL_COLOR_EQ(32, 32, GLColor::red);
1788 
1789     eglDestroySurface(mDisplay, surface1);
1790     eglDestroySurface(mDisplay, surface2);
1791 }
1792 
1793 // Verify bliting between two surfaces works correctly.
TEST_P(EGLSurfaceTest3,BlitBetweenSurfacesWithDeferredClear)1794 TEST_P(EGLSurfaceTest3, BlitBetweenSurfacesWithDeferredClear)
1795 {
1796     initializeDisplay();
1797     ASSERT_NE(mDisplay, EGL_NO_DISPLAY);
1798 
1799     initializeSurfaceWithDefaultConfig(true);
1800     initializeMainContext();
1801     ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
1802     ASSERT_NE(mContext, EGL_NO_CONTEXT);
1803 
1804     EGLSurface surface1;
1805     EGLSurface surface2;
1806 
1807     const EGLint surfaceAttributes[] = {
1808         EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE,
1809     };
1810 
1811     surface1 = eglCreatePbufferSurface(mDisplay, mConfig, surfaceAttributes);
1812     ASSERT_EGL_SUCCESS();
1813     surface2 = eglCreatePbufferSurface(mDisplay, mConfig, surfaceAttributes);
1814     ASSERT_EGL_SUCCESS();
1815 
1816     // Clear surface1.
1817     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface1, surface1, mContext));
1818 
1819     // TODO(http://www.anglebug.com/6284): Failing with OpenGL ES backend on Android and Windows.
1820     // Must be after the eglMakeCurrent() so the renderer string is initialized.
1821     ANGLE_SKIP_TEST_IF(IsOpenGLES() && (IsAndroid() || IsWindows()));
1822 
1823     glClearColor(kFloatRed.R, kFloatRed.G, kFloatRed.B, kFloatRed.A);
1824     glClear(GL_COLOR_BUFFER_BIT);
1825     ASSERT_GL_NO_ERROR();
1826     // Force the clear to be flushed
1827     EXPECT_PIXEL_COLOR_EQ(32, 32, GLColor::red);
1828 
1829     // Clear to green, but don't read it back so the clear is deferred.
1830     glClearColor(kFloatGreen.R, kFloatGreen.G, kFloatGreen.B, kFloatGreen.A);
1831     glClear(GL_COLOR_BUFFER_BIT);
1832     ASSERT_GL_NO_ERROR();
1833 
1834     // Blit from surface1 to surface2.
1835     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface2, surface1, mContext));
1836     glBlitFramebuffer(0, 0, 64, 64, 0, 0, 64, 64, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1837     ASSERT_GL_NO_ERROR();
1838 
1839     // Confirm surface1 has the clear color.
1840     EXPECT_PIXEL_COLOR_EQ(32, 32, GLColor::green);
1841 
1842     // Confirm surface2 has the blited clear color.
1843     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface2, surface2, mContext));
1844     EXPECT_PIXEL_COLOR_EQ(32, 32, GLColor::green);
1845 
1846     eglDestroySurface(mDisplay, surface1);
1847     eglDestroySurface(mDisplay, surface2);
1848 }
1849 
1850 // Verify switching between a surface with robust resource init and one without still clears alpha.
TEST_P(EGLSurfaceTest,RobustResourceInitAndEmulatedAlpha)1851 TEST_P(EGLSurfaceTest, RobustResourceInitAndEmulatedAlpha)
1852 {
1853     // http://anglebug.com/5279
1854     ANGLE_SKIP_TEST_IF(IsNVIDIA() && isGLRenderer() && IsLinux());
1855 
1856     // http://anglebug.com/5280
1857     ANGLE_SKIP_TEST_IF(IsAndroid() && IsNexus5X() && isGLESRenderer());
1858 
1859     initializeDisplay();
1860     ASSERT_NE(mDisplay, EGL_NO_DISPLAY);
1861 
1862     ANGLE_SKIP_TEST_IF(
1863         !IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_robust_resource_initialization"));
1864 
1865     // Initialize and draw red to a Surface with robust resource init enabled.
1866     constexpr EGLint kRGBAAttributes[] = {EGL_RED_SIZE,     8,
1867                                           EGL_GREEN_SIZE,   8,
1868                                           EGL_BLUE_SIZE,    8,
1869                                           EGL_ALPHA_SIZE,   8,
1870                                           EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1871                                           EGL_NONE};
1872 
1873     EGLint configCount   = 0;
1874     EGLConfig rgbaConfig = nullptr;
1875     ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kRGBAAttributes, &rgbaConfig, 1, &configCount));
1876     ASSERT_EQ(configCount, 1);
1877     ASSERT_NE(rgbaConfig, nullptr);
1878 
1879     std::vector<EGLint> robustInitAttribs;
1880     robustInitAttribs.push_back(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE);
1881     robustInitAttribs.push_back(EGL_TRUE);
1882 
1883     initializeSurfaceWithAttribs(rgbaConfig, robustInitAttribs);
1884     ASSERT_EGL_SUCCESS();
1885     ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
1886 
1887     initializeMainContext();
1888     ASSERT_EGL_SUCCESS();
1889     ASSERT_NE(mContext, EGL_NO_CONTEXT);
1890 
1891     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
1892     ASSERT_EGL_SUCCESS();
1893     eglSwapBuffers(mDisplay, mWindowSurface);
1894 
1895     // RGBA robust init setup complete. Draw red and verify.
1896     {
1897         ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1898         glUseProgram(program);
1899 
1900         drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1901         ASSERT_GL_NO_ERROR();
1902         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1903 
1904         eglSwapBuffers(mDisplay, mWindowSurface);
1905     }
1906 
1907     tearDownContextAndSurface();
1908 
1909     // Create second RGB surface with robust resource disabled.
1910     constexpr EGLint kRGBAttributes[] = {EGL_RED_SIZE,     8,
1911                                          EGL_GREEN_SIZE,   8,
1912                                          EGL_BLUE_SIZE,    8,
1913                                          EGL_ALPHA_SIZE,   0,
1914                                          EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1915                                          EGL_NONE};
1916 
1917     configCount         = 0;
1918     EGLConfig rgbConfig = nullptr;
1919     ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kRGBAttributes, &rgbConfig, 1, &configCount));
1920     ASSERT_EQ(configCount, 1);
1921     ASSERT_NE(rgbConfig, nullptr);
1922 
1923     initializeSurface(rgbConfig);
1924     ASSERT_EGL_SUCCESS();
1925     ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
1926 
1927     initializeMainContext();
1928 
1929     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
1930     ASSERT_EGL_SUCCESS();
1931 
1932     // RGB non-robust init setup complete. Draw red and verify.
1933     {
1934         ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1935         glUseProgram(program);
1936 
1937         drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1938         ASSERT_GL_NO_ERROR();
1939         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1940 
1941         eglSwapBuffers(mDisplay, mWindowSurface);
1942     }
1943 }
1944 
drawQuadThenTearDown()1945 void EGLSurfaceTest::drawQuadThenTearDown()
1946 {
1947     initializeMainContext();
1948 
1949     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
1950     ASSERT_EGL_SUCCESS();
1951 
1952     {
1953         ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1954         drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
1955         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1956         eglSwapBuffers(mDisplay, mWindowSurface);
1957         ASSERT_EGL_SUCCESS();
1958     }
1959 
1960     tearDownContextAndSurface();
1961 }
1962 
1963 // Tests the EGL_ANGLE_create_surface_swap_interval extension if available.
TEST_P(EGLSurfaceTest,CreateSurfaceSwapIntervalANGLE)1964 TEST_P(EGLSurfaceTest, CreateSurfaceSwapIntervalANGLE)
1965 {
1966     initializeDisplay();
1967     ASSERT_NE(mDisplay, EGL_NO_DISPLAY);
1968 
1969     mConfig = chooseDefaultConfig(true);
1970     ASSERT_NE(mConfig, nullptr);
1971 
1972     if (IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_create_surface_swap_interval"))
1973     {
1974         // Test error conditions.
1975         EGLint minSwapInterval = 0;
1976         eglGetConfigAttrib(mDisplay, mConfig, EGL_MIN_SWAP_INTERVAL, &minSwapInterval);
1977         ASSERT_EGL_SUCCESS();
1978 
1979         if (minSwapInterval > 0)
1980         {
1981             std::vector<EGLint> min1SwapAttribs = {EGL_SWAP_INTERVAL_ANGLE, minSwapInterval - 1};
1982             initializeWindowSurfaceWithAttribs(mConfig, min1SwapAttribs, EGL_BAD_ATTRIBUTE);
1983         }
1984 
1985         EGLint maxSwapInterval = 0;
1986         eglGetConfigAttrib(mDisplay, mConfig, EGL_MAX_SWAP_INTERVAL, &maxSwapInterval);
1987         ASSERT_EGL_SUCCESS();
1988 
1989         if (maxSwapInterval < std::numeric_limits<EGLint>::max())
1990         {
1991             std::vector<EGLint> max1SwapAttribs = {EGL_SWAP_INTERVAL_ANGLE, maxSwapInterval + 1};
1992             initializeWindowSurfaceWithAttribs(mConfig, max1SwapAttribs, EGL_BAD_ATTRIBUTE);
1993         }
1994 
1995         // Test valid min/max usage.
1996         {
1997             std::vector<EGLint> minSwapAttribs = {EGL_SWAP_INTERVAL_ANGLE, minSwapInterval};
1998             initializeWindowSurfaceWithAttribs(mConfig, minSwapAttribs, EGL_SUCCESS);
1999             drawQuadThenTearDown();
2000         }
2001 
2002         if (minSwapInterval != maxSwapInterval)
2003         {
2004             std::vector<EGLint> maxSwapAttribs = {EGL_SWAP_INTERVAL_ANGLE, maxSwapInterval};
2005             initializeWindowSurfaceWithAttribs(mConfig, maxSwapAttribs, EGL_SUCCESS);
2006             drawQuadThenTearDown();
2007         }
2008     }
2009     else
2010     {
2011         // Test extension unavailable error.
2012         std::vector<EGLint> swapInterval1Attribs = {EGL_SWAP_INTERVAL_ANGLE, 1};
2013         initializeWindowSurfaceWithAttribs(mConfig, swapInterval1Attribs, EGL_BAD_ATTRIBUTE);
2014     }
2015 }
2016 
2017 // Test that setting a surface's timestamp attribute works when the extension
2018 // EGL_ANGLE_timestamp_surface_attribute is supported.
TEST_P(EGLSurfaceTest,TimestampSurfaceAttribute)2019 TEST_P(EGLSurfaceTest, TimestampSurfaceAttribute)
2020 {
2021     initializeDisplay();
2022     ASSERT_NE(mDisplay, EGL_NO_DISPLAY);
2023     mConfig = chooseDefaultConfig(true);
2024     ASSERT_NE(mConfig, nullptr);
2025     initializeSurface(mConfig);
2026     ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
2027     initializeMainContext();
2028 
2029     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext));
2030     ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
2031 
2032     const bool extensionSupported =
2033         IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANDROID_get_frame_timestamps") ||
2034         IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_timestamp_surface_attribute");
2035 
2036     EGLBoolean setSurfaceAttrib =
2037         eglSurfaceAttrib(mDisplay, mWindowSurface, EGL_TIMESTAMPS_ANDROID, EGL_TRUE);
2038 
2039     if (extensionSupported)
2040     {
2041         EXPECT_EGL_TRUE(setSurfaceAttrib);
2042 
2043         // Swap so the swapchain gets created.
2044         glClearColor(1.0, 1.0, 1.0, 1.0);
2045         glClear(GL_COLOR_BUFFER_BIT);
2046         EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, mWindowSurface));
2047 
2048         // Query to confirm the attribute persists across swaps.
2049         EGLint timestampEnabled = 0;
2050         EXPECT_EGL_TRUE(
2051             eglQuerySurface(mDisplay, mWindowSurface, EGL_TIMESTAMPS_ANDROID, &timestampEnabled));
2052         EXPECT_NE(timestampEnabled, 0);
2053 
2054         // Resize window and swap.
2055         mOSWindow->resize(256, 256);
2056         glClearColor(1.0, 1.0, 1.0, 1.0);
2057         glClear(GL_COLOR_BUFFER_BIT);
2058         EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, mWindowSurface));
2059 
2060         // Query to confirm the attribute persists across swapchain recreations.
2061         timestampEnabled = 0;
2062         EXPECT_EGL_TRUE(
2063             eglQuerySurface(mDisplay, mWindowSurface, EGL_TIMESTAMPS_ANDROID, &timestampEnabled));
2064         EXPECT_NE(timestampEnabled, 0);
2065     }
2066     else
2067     {
2068         EXPECT_EGL_FALSE(setSurfaceAttrib);
2069         EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
2070     }
2071 
2072     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
2073     ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
2074 }
2075 
TEST_P(EGLSingleBufferTest,OnCreateWindowSurface)2076 TEST_P(EGLSingleBufferTest, OnCreateWindowSurface)
2077 {
2078     EGLConfig config = EGL_NO_CONFIG_KHR;
2079     ANGLE_SKIP_TEST_IF(!chooseConfig(&config, false));
2080 
2081     EGLContext context = EGL_NO_CONTEXT;
2082     EXPECT_EGL_TRUE(createContext(config, &context));
2083     ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
2084 
2085     EGLSurface surface = EGL_NO_SURFACE;
2086     OSWindow *osWindow = OSWindow::New();
2087     osWindow->initialize("EGLSingleBufferTest", kWidth, kHeight);
2088     EXPECT_EGL_TRUE(
2089         createWindowSurface(config, osWindow->getNativeWindow(), &surface, EGL_SINGLE_BUFFER));
2090     ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
2091 
2092     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
2093     ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
2094 
2095     EGLint actualRenderbuffer;
2096     EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer));
2097     if (actualRenderbuffer == EGL_SINGLE_BUFFER)
2098     {
2099         EXPECT_EGL_TRUE(actualRenderbuffer == EGL_SINGLE_BUFFER);
2100 
2101         glClearColor(0.0, 1.0, 0.0, 1.0);
2102         glClear(GL_COLOR_BUFFER_BIT);
2103         glFlush();
2104         ASSERT_GL_NO_ERROR();
2105         // Flush should result in update of screen. Must be visually confirmed.
2106         // Pixel test for automation.
2107         EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
2108     }
2109     else
2110     {
2111         std::cout << "SKIP test, no EGL_SINGLE_BUFFER support." << std::endl;
2112     }
2113 
2114     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
2115     ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
2116 
2117     eglDestroySurface(mDisplay, surface);
2118     surface = EGL_NO_SURFACE;
2119     osWindow->destroy();
2120     OSWindow::Delete(&osWindow);
2121 
2122     eglDestroyContext(mDisplay, context);
2123     context = EGL_NO_CONTEXT;
2124 }
2125 
TEST_P(EGLSingleBufferTest,OnSetSurfaceAttrib)2126 TEST_P(EGLSingleBufferTest, OnSetSurfaceAttrib)
2127 {
2128     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer"));
2129 
2130     EGLConfig config = EGL_NO_CONFIG_KHR;
2131     ANGLE_SKIP_TEST_IF(!chooseConfig(&config, true));
2132 
2133     EGLContext context = EGL_NO_CONTEXT;
2134     EXPECT_EGL_TRUE(createContext(config, &context));
2135     ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
2136 
2137     EGLSurface surface = EGL_NO_SURFACE;
2138     OSWindow *osWindow = OSWindow::New();
2139     osWindow->initialize("EGLSingleBufferTest", kWidth, kHeight);
2140     EXPECT_EGL_TRUE(
2141         createWindowSurface(config, osWindow->getNativeWindow(), &surface, EGL_BACK_BUFFER));
2142     ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
2143 
2144     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
2145     ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
2146 
2147     if (eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER))
2148     {
2149         // Transition into EGL_SINGLE_BUFFER mode.
2150         glClearColor(1.0, 1.0, 1.0, 1.0);
2151         glClear(GL_COLOR_BUFFER_BIT);
2152         EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, surface));
2153 
2154         EGLint actualRenderbuffer;
2155         EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer));
2156         EXPECT_EGL_TRUE(actualRenderbuffer == EGL_SINGLE_BUFFER);
2157 
2158         glClearColor(0.0, 1.0, 0.0, 1.0);
2159         glClear(GL_COLOR_BUFFER_BIT);
2160         glFlush();
2161         // Flush should result in update of screen. Must be visually confirmed Green window.
2162 
2163         // Check color for automation.
2164         EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
2165 
2166         // Switch back to EGL_BACK_BUFFEr and check.
2167         EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_BACK_BUFFER));
2168         glClearColor(1.0, 1.0, 1.0, 1.0);
2169         glClear(GL_COLOR_BUFFER_BIT);
2170         EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, surface));
2171 
2172         EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer));
2173         EXPECT_EGL_TRUE(actualRenderbuffer == EGL_BACK_BUFFER);
2174 
2175         glClearColor(1.0, 0.0, 0.0, 1.0);
2176         glClear(GL_COLOR_BUFFER_BIT);
2177         EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
2178     }
2179     else
2180     {
2181         std::cout << "EGL_SINGLE_BUFFER mode is not supported." << std::endl;
2182     }
2183 
2184     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
2185     ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
2186 
2187     eglDestroySurface(mDisplay, surface);
2188     surface = EGL_NO_SURFACE;
2189     osWindow->destroy();
2190     OSWindow::Delete(&osWindow);
2191 
2192     eglDestroyContext(mDisplay, context);
2193     context = EGL_NO_CONTEXT;
2194 }
2195 
drawAndSwap(EGLSurface & surface,EGLDisplay & display,uint32_t color,bool flush)2196 uint32_t EGLSingleBufferTest::drawAndSwap(EGLSurface &surface,
2197                                           EGLDisplay &display,
2198                                           uint32_t color,
2199                                           bool flush)
2200 {
2201     ASSERT(color < 256);
2202 
2203     glClearColor((float)color / 255.f, (float)color / 255.f, (float)color / 255.f,
2204                  (float)color / 255.f);
2205     glClear(GL_COLOR_BUFFER_BIT);
2206 
2207     if (flush)
2208     {
2209         glFlush();
2210     }
2211     else
2212     {
2213         eglSwapBuffers(display, surface);
2214     }
2215 
2216     return (color | color << 8 | color << 16 | color << 24);
2217 }
2218 
2219 // Replicate dEQP-EGL.functional.mutable_render_buffer#basic
TEST_P(EGLSingleBufferTest,MutableRenderBuffer)2220 TEST_P(EGLSingleBufferTest, MutableRenderBuffer)
2221 {
2222     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer"));
2223 
2224     EGLConfig config       = EGL_NO_CONFIG_KHR;
2225     const EGLint attribs[] = {EGL_RED_SIZE,
2226                               8,
2227                               EGL_GREEN_SIZE,
2228                               8,
2229                               EGL_BLUE_SIZE,
2230                               8,
2231                               EGL_ALPHA_SIZE,
2232                               8,
2233                               EGL_SURFACE_TYPE,
2234                               EGL_WINDOW_BIT | EGL_MUTABLE_RENDER_BUFFER_BIT_KHR,
2235                               EGL_RENDERABLE_TYPE,
2236                               EGL_OPENGL_ES2_BIT,
2237                               EGL_NONE};
2238     EGLint count           = 0;
2239     ANGLE_SKIP_TEST_IF(!eglChooseConfig(mDisplay, attribs, &config, 1, &count));
2240 
2241     EGLContext context = EGL_NO_CONTEXT;
2242     EXPECT_EGL_TRUE(createContext(config, &context));
2243     ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
2244 
2245     EGLSurface surface = EGL_NO_SURFACE;
2246     OSWindow *osWindow = OSWindow::New();
2247     osWindow->initialize("EGLSingleBufferTest", kWidth, kHeight);
2248     EXPECT_EGL_TRUE(
2249         createWindowSurface(config, osWindow->getNativeWindow(), &surface, EGL_BACK_BUFFER));
2250     ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
2251 
2252     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
2253     ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
2254 
2255     int frameNumber = 1;
2256 
2257     // run a few back-buffered frames
2258     for (; frameNumber < 5; frameNumber++)
2259     {
2260         drawAndSwap(surface, mDisplay, frameNumber, false);
2261     }
2262 
2263     if (eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER))
2264     {
2265         drawAndSwap(surface, mDisplay, frameNumber, false);
2266         frameNumber++;
2267 
2268         // test a few single-buffered frames
2269         for (; frameNumber < 10; frameNumber++)
2270         {
2271             uint32_t backBufferPixel  = 0xFFFFFFFF;
2272             uint32_t frontBufferPixel = drawAndSwap(surface, mDisplay, frameNumber, true);
2273             glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &backBufferPixel);
2274             EXPECT_EQ(backBufferPixel, frontBufferPixel);
2275         }
2276     }
2277 
2278     else
2279     {
2280         std::cout << "EGL_SINGLE_BUFFER mode is not supported." << std::endl;
2281     }
2282 
2283     // switch back to back-buffer rendering
2284     if (eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_BACK_BUFFER))
2285     {
2286         for (; frameNumber < 14; frameNumber++)
2287         {
2288             drawAndSwap(surface, mDisplay, frameNumber, false);
2289         }
2290     }
2291     else
2292     {
2293         std::cout << "EGL_BACK_BUFFER mode is not supported." << std::endl;
2294     }
2295 
2296     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
2297     ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
2298 
2299     eglDestroySurface(mDisplay, surface);
2300     surface = EGL_NO_SURFACE;
2301     osWindow->destroy();
2302     OSWindow::Delete(&osWindow);
2303 
2304     eglDestroyContext(mDisplay, context);
2305     context = EGL_NO_CONTEXT;
2306 }
2307 
2308 // Tests bug with incorrect ImageLayout::SharedPresent barrier.
TEST_P(EGLSingleBufferTest,SharedPresentBarrier)2309 TEST_P(EGLSingleBufferTest, SharedPresentBarrier)
2310 {
2311     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer"));
2312 
2313     EGLConfig config = EGL_NO_CONFIG_KHR;
2314     ANGLE_SKIP_TEST_IF(!chooseConfig(&config, true));
2315 
2316     EGLContext context = EGL_NO_CONTEXT;
2317     EXPECT_EGL_TRUE(createContext(config, &context));
2318     ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
2319 
2320     EGLSurface surface = EGL_NO_SURFACE;
2321     OSWindow *osWindow = OSWindow::New();
2322     osWindow->initialize("EGLSingleBufferTest", kWidth, kHeight);
2323     EXPECT_EGL_TRUE(
2324         createWindowSurface(config, osWindow->getNativeWindow(), &surface, EGL_BACK_BUFFER));
2325     ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
2326 
2327     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
2328     ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
2329 
2330     if (eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER))
2331     {
2332         // Transition into EGL_SINGLE_BUFFER mode.
2333         glClearColor(1.0, 1.0, 1.0, 1.0);
2334         glClear(GL_COLOR_BUFFER_BIT);
2335         EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, surface));
2336 
2337         EGLint actualRenderbuffer;
2338         EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer));
2339         EXPECT_EGL_TRUE(actualRenderbuffer == EGL_SINGLE_BUFFER);
2340 
2341         for (int i = 0; i < 5; ++i)
2342         {
2343             GLColor testColor(rand() % 256, rand() % 256, rand() % 256, 255);
2344             angle::Vector4 clearColor = testColor.toNormalizedVector();
2345             glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
2346             glClear(GL_COLOR_BUFFER_BIT);
2347             // Skip flush because present operations may add other barriers that will make appear
2348             // that everything works as expected.
2349 
2350             // Check color without flush - may get invalid result if have incorrect barrier bug.
2351             EXPECT_PIXEL_COLOR_EQ(1, 1, testColor);
2352         }
2353     }
2354     else
2355     {
2356         std::cout << "EGL_SINGLE_BUFFER mode is not supported." << std::endl;
2357     }
2358 
2359     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
2360     ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
2361 
2362     eglDestroySurface(mDisplay, surface);
2363     surface = EGL_NO_SURFACE;
2364     osWindow->destroy();
2365     OSWindow::Delete(&osWindow);
2366 
2367     eglDestroyContext(mDisplay, context);
2368     context = EGL_NO_CONTEXT;
2369 }
2370 
2371 // Tests scissored clear on single buffer surface
TEST_P(EGLSingleBufferTest,ScissoredClear)2372 TEST_P(EGLSingleBufferTest, ScissoredClear)
2373 {
2374     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer"));
2375 
2376     EGLConfig config = EGL_NO_CONFIG_KHR;
2377     ANGLE_SKIP_TEST_IF(!chooseConfig(&config, true));
2378 
2379     EGLContext context = EGL_NO_CONTEXT;
2380     EXPECT_EGL_TRUE(createContext(config, &context));
2381     ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
2382 
2383     EGLSurface surface = EGL_NO_SURFACE;
2384     OSWindow *osWindow = OSWindow::New();
2385     osWindow->initialize("EGLSingleBufferTest", kWidth, kHeight);
2386     EXPECT_EGL_TRUE(
2387         createWindowSurface(config, osWindow->getNativeWindow(), &surface, EGL_BACK_BUFFER));
2388     ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
2389 
2390     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
2391     ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
2392 
2393     if (eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER))
2394     {
2395         eglSwapBuffers(mDisplay, surface);
2396 
2397         glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2398         glClear(GL_COLOR_BUFFER_BIT);
2399         glFlush();
2400 
2401         glEnable(GL_SCISSOR_TEST);
2402         glScissor(1, 1, 10, 10);
2403         glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2404         glClear(GL_COLOR_BUFFER_BIT);
2405         glFlush();
2406         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2407         EXPECT_PIXEL_COLOR_EQ(2, 2, GLColor::green);
2408     }
2409     else
2410     {
2411         std::cout << "EGL_SINGLE_BUFFER mode is not supported." << std::endl;
2412     }
2413 
2414     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
2415     ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
2416 
2417     eglDestroySurface(mDisplay, surface);
2418     surface = EGL_NO_SURFACE;
2419     osWindow->destroy();
2420     OSWindow::Delete(&osWindow);
2421 
2422     eglDestroyContext(mDisplay, context);
2423     context = EGL_NO_CONTEXT;
2424 }
2425 
2426 // Tests scissored clear on single buffer surface
TEST_P(EGLSingleBufferTest,ScissoredDraw)2427 TEST_P(EGLSingleBufferTest, ScissoredDraw)
2428 {
2429     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer"));
2430 
2431     EGLConfig config = EGL_NO_CONFIG_KHR;
2432     ANGLE_SKIP_TEST_IF(!chooseConfig(&config, true));
2433 
2434     EGLContext context = EGL_NO_CONTEXT;
2435     EXPECT_EGL_TRUE(createContext(config, &context));
2436     ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
2437 
2438     EGLSurface surface = EGL_NO_SURFACE;
2439     OSWindow *osWindow = OSWindow::New();
2440     osWindow->initialize("EGLSingleBufferTest", kWidth, kHeight);
2441     EXPECT_EGL_TRUE(
2442         createWindowSurface(config, osWindow->getNativeWindow(), &surface, EGL_BACK_BUFFER));
2443     ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
2444 
2445     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
2446     ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
2447 
2448     if (eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER))
2449     {
2450         eglSwapBuffers(mDisplay, surface);
2451 
2452         glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2453         glClear(GL_COLOR_BUFFER_BIT);
2454         glFlush();
2455 
2456         glEnable(GL_SCISSOR_TEST);
2457         glScissor(1, 1, 10, 10);
2458         glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2459         ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2460         drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
2461         glFlush();
2462         glDisable(GL_SCISSOR_TEST);
2463         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2464         EXPECT_PIXEL_COLOR_EQ(2, 2, GLColor::green);
2465     }
2466     else
2467     {
2468         std::cout << "EGL_SINGLE_BUFFER mode is not supported." << std::endl;
2469     }
2470 
2471     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
2472     ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
2473 
2474     eglDestroySurface(mDisplay, surface);
2475     surface = EGL_NO_SURFACE;
2476     osWindow->destroy();
2477     OSWindow::Delete(&osWindow);
2478 
2479     eglDestroyContext(mDisplay, context);
2480     context = EGL_NO_CONTEXT;
2481 }
2482 
2483 // Tests that "one off" submission is waited before destroying the surface.
TEST_P(EGLSingleBufferTest,WaitOneOffSubmission)2484 TEST_P(EGLSingleBufferTest, WaitOneOffSubmission)
2485 {
2486     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer"));
2487 
2488     EGLConfig config = EGL_NO_CONFIG_KHR;
2489     ANGLE_SKIP_TEST_IF(!chooseConfig(&config, true));
2490 
2491     EGLContext context = EGL_NO_CONTEXT;
2492     EXPECT_EGL_TRUE(createContext(config, &context));
2493     ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
2494 
2495     EGLContext context2 = EGL_NO_CONTEXT;
2496     EXPECT_EGL_TRUE(createContext(config, &context2));
2497     ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
2498 
2499     const EGLint pbufferSurfaceAttrs[] = {
2500         EGL_WIDTH, 1024, EGL_HEIGHT, 1024, EGL_NONE,
2501     };
2502     EGLSurface pbufferSurface = eglCreatePbufferSurface(mDisplay, config, pbufferSurfaceAttrs);
2503     ASSERT_EGL_SUCCESS() << "eglCreatePbufferSurface failed.";
2504 
2505     EGLSurface surface = EGL_NO_SURFACE;
2506     OSWindow *osWindow = OSWindow::New();
2507     osWindow->initialize("EGLSingleBufferTest", kWidth, kHeight);
2508     EXPECT_EGL_TRUE(
2509         createWindowSurface(config, osWindow->getNativeWindow(), &surface, EGL_BACK_BUFFER));
2510     ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
2511 
2512     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
2513     ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
2514 
2515     // Query age for the first time to avoid submitting debug information a second time.
2516     EGLint age = 0;
2517     EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, surface, EGL_BUFFER_AGE_EXT, &age));
2518 
2519     if (eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER))
2520     {
2521         // Transition into EGL_SINGLE_BUFFER mode.
2522         EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, surface));
2523 
2524         // Submit heavy work to the GPU before querying the buffer age.
2525         std::thread([this, context2, pbufferSurface]() {
2526             EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, pbufferSurface, pbufferSurface, context2));
2527             ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
2528 
2529             ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2530             drawQuadInstanced(greenProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, false,
2531                               1000);
2532 
2533             EXPECT_EGL_TRUE(
2534                 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
2535             ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
2536         }).join();
2537 
2538         // Querying the buffer age should perform first acquire of the image and "one off"
2539         // submission to change image layout to the VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR.
2540         EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, surface, EGL_BUFFER_AGE_EXT, &age));
2541     }
2542     else
2543     {
2544         std::cout << "EGL_SINGLE_BUFFER mode is not supported." << std::endl;
2545     }
2546 
2547     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
2548     ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
2549 
2550     eglDestroySurface(mDisplay, surface);
2551     surface = EGL_NO_SURFACE;
2552     osWindow->destroy();
2553     OSWindow::Delete(&osWindow);
2554 
2555     eglDestroySurface(mDisplay, pbufferSurface);
2556     pbufferSurface = EGL_NO_SURFACE;
2557 
2558     eglDestroyContext(mDisplay, context);
2559     context = EGL_NO_CONTEXT;
2560 
2561     eglDestroyContext(mDisplay, context2);
2562     context2 = EGL_NO_CONTEXT;
2563 }
2564 
2565 // Test that setting a surface to EGL_SINGLE_BUFFER after enabling
2566 // EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID does not disable auto refresh
TEST_P(EGLAndroidAutoRefreshTest,Basic)2567 TEST_P(EGLAndroidAutoRefreshTest, Basic)
2568 {
2569     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer"));
2570     ANGLE_SKIP_TEST_IF(!IsAndroid());
2571 
2572     EGLConfig config = EGL_NO_CONFIG_KHR;
2573     ANGLE_SKIP_TEST_IF(!chooseConfig(&config, true));
2574 
2575     EGLContext context = EGL_NO_CONTEXT;
2576     EXPECT_EGL_TRUE(createContext(config, &context));
2577     ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
2578 
2579     EGLSurface surface = EGL_NO_SURFACE;
2580     OSWindow *osWindow = OSWindow::New();
2581     osWindow->initialize("EGLSingleBufferTest", kWidth, kHeight);
2582     EXPECT_EGL_TRUE(
2583         createWindowSurface(config, osWindow->getNativeWindow(), &surface, EGL_BACK_BUFFER));
2584     ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
2585 
2586     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
2587     ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
2588 
2589     EXPECT_EGL_TRUE(
2590         eglSurfaceAttrib(mDisplay, surface, EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID, EGL_TRUE));
2591 
2592     if (eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER))
2593     {
2594         // Transition into EGL_SINGLE_BUFFER mode.
2595         glClearColor(1.0, 1.0, 1.0, 1.0);
2596         glClear(GL_COLOR_BUFFER_BIT);
2597         EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, surface));
2598 
2599         EGLint actualRenderbuffer;
2600         EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer));
2601         EXPECT_EGL_TRUE(actualRenderbuffer == EGL_SINGLE_BUFFER);
2602 
2603         glClearColor(0.0, 1.0, 0.0, 1.0);
2604         glClear(GL_COLOR_BUFFER_BIT);
2605         glFlush();
2606         // Flush should result in update of screen. Must be visually confirmed Green window.
2607 
2608         // Check color for automation.
2609         EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
2610 
2611         // Switch back to EGL_BACK_BUFFER and check.
2612         EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_BACK_BUFFER));
2613         glClearColor(1.0, 1.0, 1.0, 1.0);
2614         glClear(GL_COLOR_BUFFER_BIT);
2615         EXPECT_EGL_TRUE(eglSwapBuffers(mDisplay, surface));
2616 
2617         EXPECT_EGL_TRUE(eglQueryContext(mDisplay, context, EGL_RENDER_BUFFER, &actualRenderbuffer));
2618         EXPECT_EGL_TRUE(actualRenderbuffer == EGL_BACK_BUFFER);
2619 
2620         glClearColor(1.0, 0.0, 0.0, 1.0);
2621         glClear(GL_COLOR_BUFFER_BIT);
2622         EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
2623     }
2624     else
2625     {
2626         std::cout << "EGL_SINGLE_BUFFER mode is not supported." << std::endl;
2627     }
2628 
2629     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
2630     ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
2631 
2632     eglDestroySurface(mDisplay, surface);
2633     surface = EGL_NO_SURFACE;
2634     osWindow->destroy();
2635     OSWindow::Delete(&osWindow);
2636 
2637     eglDestroyContext(mDisplay, context);
2638     context = EGL_NO_CONTEXT;
2639 }
2640 
runWaitSemaphoreTest(bool useSecondContext)2641 void EGLSurfaceTest::runWaitSemaphoreTest(bool useSecondContext)
2642 {
2643     // Note: This test requires visual inspection for rendering artifacts.
2644     // However, absence of artifacts does not guarantee that there is no problem.
2645 
2646     initializeDisplay();
2647 
2648     constexpr int kInitialSize   = 64;
2649     constexpr int kWindowWidth   = 1080;
2650     constexpr int kWindowWHeight = 1920;
2651 
2652     mOSWindow->resize(kWindowWidth, kWindowWHeight);
2653 
2654     // Initialize an RGBA8 window and pbuffer surface
2655     constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE,     8,
2656                                              EGL_GREEN_SIZE,   8,
2657                                              EGL_BLUE_SIZE,    8,
2658                                              EGL_ALPHA_SIZE,   8,
2659                                              EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
2660                                              EGL_NONE};
2661 
2662     EGLint configCount      = 0;
2663     EGLConfig surfaceConfig = nullptr;
2664     ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount));
2665     ASSERT_NE(configCount, 0);
2666     ASSERT_NE(surfaceConfig, nullptr);
2667 
2668     initializeSurface(surfaceConfig);
2669     initializeMainContext();
2670     ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
2671     ASSERT_NE(mPbufferSurface, EGL_NO_SURFACE);
2672 
2673     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
2674     ASSERT_EGL_SUCCESS();
2675 
2676     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_disjoint_timer_query"));
2677 
2678     if (useSecondContext)
2679     {
2680         ANGLE_SKIP_TEST_IF(!platformSupportsMultithreading());
2681         initializeSingleContext(&mSecondContext, 0);
2682     }
2683 
2684     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2685     glUseProgram(program);
2686     ASSERT_GL_NO_ERROR();
2687 
2688     GLint posAttrib = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
2689     ASSERT_NE(posAttrib, -1);
2690     glEnableVertexAttribArray(posAttrib);
2691     ASSERT_GL_NO_ERROR();
2692 
2693     GLint colorUniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
2694     ASSERT_NE(colorUniformLocation, -1);
2695 
2696     constexpr int kFrameCount = 60 * 4;  // 4 sec @ 60Hz; 2 sec @ 120Hz;
2697     constexpr int kGridW      = 5;
2698     constexpr int kGridH      = 5;
2699     constexpr int kAnimDiv    = 20;
2700 
2701     for (int frame = 0; frame < kFrameCount; ++frame)
2702     {
2703         glClearColor(0.1f, 0.1f, 0.2f, 1.0f);
2704         glClear(GL_COLOR_BUFFER_BIT);
2705         ASSERT_GL_NO_ERROR();
2706 
2707         for (int y = 0; y < kGridH; ++y)
2708         {
2709             // This should force "flushToPrimary()" each line in ANGLE
2710             GLuint query;
2711             glGenQueries(1, &query);
2712             ASSERT_GL_NO_ERROR();
2713             glBeginQuery(GL_TIME_ELAPSED_EXT, query);
2714             ASSERT_GL_NO_ERROR();
2715 
2716             for (int x = 0; x < kGridW; ++x)
2717             {
2718                 const int xc        = (x + frame / kAnimDiv) % kGridW;
2719                 const Vector4 color = {(xc + 0.5f) / kGridW, (y + 0.5f) / kGridH, 0.0f, 1.0f};
2720 
2721                 const GLfloat x0 = (x + 0.1f) / kGridW * 2.0f - 1.0f;
2722                 const GLfloat x1 = (x + 0.9f) / kGridW * 2.0f - 1.0f;
2723                 const GLfloat y0 = (y + 0.1f) / kGridH * 2.0f - 1.0f;
2724                 const GLfloat y1 = (y + 0.9f) / kGridH * 2.0f - 1.0f;
2725 
2726                 std::array<Vector3, 6> vertexData;
2727                 vertexData[0] = {x0, y1, 0.5f};
2728                 vertexData[1] = {x0, y0, 0.5f};
2729                 vertexData[2] = {x1, y1, 0.5f};
2730                 vertexData[3] = {x1, y1, 0.5f};
2731                 vertexData[4] = {x0, y0, 0.5f};
2732                 vertexData[5] = {x1, y0, 0.5f};
2733 
2734                 glUniform4f(colorUniformLocation, color.x(), color.y(), color.z(), color.w());
2735                 glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, vertexData.data());
2736                 glDrawArrays(GL_TRIANGLES, 0, 6);
2737                 ASSERT_GL_NO_ERROR();
2738             }
2739 
2740             glEndQuery(GL_TIME_ELAPSED_EXT);
2741             glDeleteQueries(1, &query);
2742             ASSERT_GL_NO_ERROR();
2743         }
2744 
2745         if (useSecondContext)
2746         {
2747             std::thread([this] {
2748                 eglBindAPI(EGL_OPENGL_ES_API);
2749                 ASSERT_EGL_SUCCESS();
2750                 eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mSecondContext);
2751                 ASSERT_EGL_SUCCESS();
2752                 glEnable(GL_SCISSOR_TEST);
2753                 glScissor(0, 0, 1, 1);
2754                 glClear(GL_COLOR_BUFFER_BIT);
2755                 ASSERT_GL_NO_ERROR();
2756                 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
2757                 ASSERT_EGL_SUCCESS();
2758             }).join();
2759         }
2760         else
2761         {
2762             eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mContext);
2763             ASSERT_EGL_SUCCESS();
2764             eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
2765             ASSERT_EGL_SUCCESS();
2766             eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
2767             ASSERT_EGL_SUCCESS();
2768         }
2769 
2770         eglSwapBuffers(mDisplay, mWindowSurface);
2771         ASSERT_EGL_SUCCESS();
2772     }
2773 
2774     mOSWindow->resize(kInitialSize, kInitialSize);
2775 }
2776 
2777 // Test that there no artifacts because of the bug when wait semaphore could be added after
2778 // rendering commands. This was possible by switching to Pbuffer surface and submit.
TEST_P(EGLSurfaceTest,DISABLED_WaitSemaphoreAddedAfterCommands)2779 TEST_P(EGLSurfaceTest, DISABLED_WaitSemaphoreAddedAfterCommands)
2780 {
2781     runWaitSemaphoreTest(false);
2782 }
2783 
2784 // Test that there no artifacts because of the bug when rendering commands could be submitted
2785 // without adding wait semaphore. This was possible if submit commands from other thread.
TEST_P(EGLSurfaceTest,DISABLED_CommandsSubmittedWithoutWaitSemaphore)2786 TEST_P(EGLSurfaceTest, DISABLED_CommandsSubmittedWithoutWaitSemaphore)
2787 {
2788     runWaitSemaphoreTest(true);
2789 }
2790 
runDestroyNotCurrentSurfaceTest(bool testWindowsSurface)2791 void EGLSurfaceTest::runDestroyNotCurrentSurfaceTest(bool testWindowsSurface)
2792 {
2793     initializeDisplay();
2794 
2795     // Initialize an RGBA8 window and pbuffer surface
2796     constexpr EGLint kSurfaceAttributes[] = {EGL_RED_SIZE,     8,
2797                                              EGL_GREEN_SIZE,   8,
2798                                              EGL_BLUE_SIZE,    8,
2799                                              EGL_ALPHA_SIZE,   8,
2800                                              EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
2801                                              EGL_NONE};
2802 
2803     EGLint configCount      = 0;
2804     EGLConfig surfaceConfig = nullptr;
2805     ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kSurfaceAttributes, &surfaceConfig, 1, &configCount));
2806     ASSERT_NE(configCount, 0);
2807     ASSERT_NE(surfaceConfig, nullptr);
2808 
2809     initializeSurface(surfaceConfig);
2810     initializeMainContext();
2811     ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
2812     ASSERT_NE(mPbufferSurface, EGL_NO_SURFACE);
2813 
2814     EGLSurface &testSurface  = testWindowsSurface ? mWindowSurface : mPbufferSurface;
2815     EGLSurface &otherSurface = testWindowsSurface ? mPbufferSurface : mWindowSurface;
2816 
2817     eglMakeCurrent(mDisplay, testSurface, testSurface, mContext);
2818     ASSERT_EGL_SUCCESS();
2819 
2820     // Start RenderPass in the testSurface
2821     glEnable(GL_SCISSOR_TEST);
2822     glScissor(0, 0, 4, 4);
2823     glClearColor(0.5f, 0.0f, 0.0f, 1.0f);
2824     glClear(GL_COLOR_BUFFER_BIT);
2825     glDisable(GL_SCISSOR_TEST);
2826     ASSERT_GL_NO_ERROR();
2827 
2828     // Make other surface current keeping the context.
2829     // If bug present, the context may have unflushed work, related to the testSurface.
2830     eglMakeCurrent(mDisplay, otherSurface, otherSurface, mContext);
2831     ASSERT_EGL_SUCCESS();
2832 
2833     if (testWindowsSurface)
2834     {
2835         // This may flush Window Surface RenderPass
2836         glEnable(GL_SCISSOR_TEST);
2837         glScissor(0, 0, 4, 4);
2838         glClearColor(0.5f, 0.0f, 0.0f, 1.0f);
2839         glClear(GL_COLOR_BUFFER_BIT);
2840         glDisable(GL_SCISSOR_TEST);
2841         ASSERT_GL_NO_ERROR();
2842     }
2843 
2844     // Destroy the surface
2845     eglDestroySurface(mDisplay, testSurface);
2846     testSurface = EGL_NO_SURFACE;
2847 
2848     // This will submit all work (if bug present - include work related to the deleted testSurface).
2849     eglMakeCurrent(mDisplay, otherSurface, otherSurface, mContext);
2850     ASSERT_EGL_SUCCESS();
2851 }
2852 
2853 // Test that there is no crash because of the bug when not current PBuffer Surface destroyed, while
2854 // there are still unflushed work in the Context.
TEST_P(EGLSurfaceTest,DestroyNotCurrentPbufferSurface)2855 TEST_P(EGLSurfaceTest, DestroyNotCurrentPbufferSurface)
2856 {
2857     runDestroyNotCurrentSurfaceTest(false);
2858 }
2859 
2860 // Test that there is no crash because of the bug when not current Window Surface destroyed, while
2861 // there are still unflushed work in the Context.
TEST_P(EGLSurfaceTest,DestroyNotCurrentWindowSurface)2862 TEST_P(EGLSurfaceTest, DestroyNotCurrentWindowSurface)
2863 {
2864     runDestroyNotCurrentSurfaceTest(true);
2865 }
2866 
2867 // Test that there is no tearing because of incorrect pipeline barriers
TEST_P(EGLSurfaceTest,DISABLED_RandomClearTearing)2868 TEST_P(EGLSurfaceTest, DISABLED_RandomClearTearing)
2869 {
2870     // Note: This test requires visual inspection for rendering artifacts.
2871     // However, absence of artifacts does not guarantee that there is no problem.
2872 
2873     initializeDisplay();
2874 
2875     constexpr int kInitialSize   = 64;
2876     constexpr int kWindowWidth   = 1080;
2877     constexpr int kWindowWHeight = 1920;
2878 
2879     mOSWindow->resize(kWindowWidth, kWindowWHeight);
2880 
2881     initializeSurfaceWithDefaultConfig(true);
2882     initializeMainContext();
2883     ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);
2884 
2885     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
2886     ASSERT_EGL_SUCCESS();
2887 
2888     constexpr int kFrameCount = 60 * 4;  // 4 sec @ 60Hz; 2 sec @ 120Hz;
2889 
2890     for (int frame = 0; frame < kFrameCount; ++frame)
2891     {
2892         glClearColor(rand() % 256 / 255.0f, rand() % 256 / 255.0f, rand() % 256 / 255.0f, 1.0f);
2893         glClear(GL_COLOR_BUFFER_BIT);
2894         ASSERT_GL_NO_ERROR();
2895 
2896         eglSwapBuffers(mDisplay, mWindowSurface);
2897         ASSERT_EGL_SUCCESS();
2898     }
2899 
2900     mOSWindow->resize(kInitialSize, kInitialSize);
2901 }
2902 
2903 // Make sure a surface (from the same window) can be recreated after being destroyed, even if it's
2904 // still current.
2905 // This is to recreate the app behavior in https://issuetracker.google.com/292285899, which is
2906 // not the correct spec behavior. It serves as a purpose to test the workaround feature
2907 // uncurrent_egl_surface_upon_surface_destroy that is enabled only on vulkan backend to help
2908 // the app get over the problem.
TEST_P(EGLSurfaceTest,DestroyAndRecreateWhileCurrent)2909 TEST_P(EGLSurfaceTest, DestroyAndRecreateWhileCurrent)
2910 {
2911     setWindowVisible(mOSWindow, true);
2912 
2913     initializeDisplay();
2914 
2915     mConfig = chooseDefaultConfig(true);
2916     ASSERT_NE(mConfig, nullptr);
2917 
2918     EGLint surfaceType = EGL_NONE;
2919     eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType);
2920     ASSERT_NE((surfaceType & EGL_WINDOW_BIT), 0);
2921 
2922     initializeWindowSurfaceWithAttribs(mConfig, {}, EGL_SUCCESS);
2923     initializeMainContext();
2924 
2925     eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);
2926     ASSERT_EGL_SUCCESS();
2927 
2928     // Draw with this surface to make sure it's used.
2929     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2930     glViewport(0, 0, 64, 64);
2931     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2932     ASSERT_GL_NO_ERROR();
2933 
2934     // Destroy the surface while it's current; it won't actually be destroyed.
2935     eglDestroySurface(mDisplay, mWindowSurface);
2936     mWindowSurface = EGL_NO_SURFACE;
2937 
2938     // Create another surface from the same window right away.
2939     initializeWindowSurfaceWithAttribs(mConfig, {}, EGL_SUCCESS);
2940 
2941     // Make the new surface current; this leads to the actual destruction of the previous surface.
2942     EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext));
2943     ASSERT_EGL_SUCCESS();
2944 
2945     // Verify everything still works
2946     ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2947     drawQuad(program2, essl1_shaders::PositionAttrib(), 0.5f);
2948     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2949     ASSERT_GL_NO_ERROR();
2950 }
2951 }  // anonymous namespace
2952 
2953 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLSingleBufferTest);
2954 ANGLE_INSTANTIATE_TEST(EGLSingleBufferTest,
2955                        WithNoFixture(ES2_VULKAN()),
2956                        WithNoFixture(ES3_VULKAN()));
2957 
2958 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLAndroidAutoRefreshTest);
2959 ANGLE_INSTANTIATE_TEST(EGLAndroidAutoRefreshTest, WithNoFixture(ES3_VULKAN()));
2960 
2961 ANGLE_INSTANTIATE_TEST(EGLSurfaceTest,
2962                        WithNoFixture(ES2_D3D9()),
2963                        WithNoFixture(ES2_D3D11()),
2964                        WithNoFixture(ES3_D3D11()),
2965                        WithNoFixture(ES2_OPENGL()),
2966                        WithNoFixture(ES3_OPENGL()),
2967                        WithNoFixture(ES2_OPENGLES()),
2968                        WithNoFixture(ES3_OPENGLES()),
2969                        WithNoFixture(ES2_VULKAN()),
2970                        WithNoFixture(ES3_VULKAN()),
2971                        WithNoFixture(ES2_VULKAN_SWIFTSHADER()),
2972                        WithNoFixture(ES3_VULKAN_SWIFTSHADER()));
2973 
2974 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLFloatSurfaceTest);
2975 ANGLE_INSTANTIATE_TEST(EGLFloatSurfaceTest,
2976                        WithNoFixture(ES2_OPENGL()),
2977                        WithNoFixture(ES3_OPENGL()),
2978                        WithNoFixture(ES2_VULKAN()),
2979                        WithNoFixture(ES3_VULKAN()));
2980 
2981 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLSurfaceTest3);
2982 ANGLE_INSTANTIATE_TEST(EGLSurfaceTest3,
2983                        WithNoFixture(ES3_D3D11()),
2984                        WithNoFixture(ES3_OPENGLES()),
2985                        WithNoFixture(ES3_VULKAN()),
2986                        WithNoFixture(ES3_VULKAN_SWIFTSHADER()));
2987 
2988 #if defined(ANGLE_ENABLE_D3D11)
2989 ANGLE_INSTANTIATE_TEST(EGLSurfaceTestD3D11, WithNoFixture(ES2_D3D11()), WithNoFixture(ES3_D3D11()));
2990 #endif
2991