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