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, ×tampEnabled));
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, ×tampEnabled));
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