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