xref: /aosp_15_r20/external/angle/src/tests/gl_tests/EGLImageMECFriendlyTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2022 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 // EGLImageMECFriendlyTest:
7 //   MEC friendly tests are tests that use all of the created resources, so that
8 //   MEC will have to capture everything, and we can test with capture/replay
9 //   whether this is done correctly. In this case the focus is on external images
10 
11 #include "test_utils/ANGLETest.h"
12 #include "test_utils/gl_raii.h"
13 #include "util/EGLWindow.h"
14 
15 constexpr int kPixelThreshold = 1;
16 
17 namespace angle
18 {
19 class EGLImageMECFriendlyTest : public ANGLETest<>
20 {
21   protected:
EGLImageMECFriendlyTest()22     EGLImageMECFriendlyTest()
23     {
24         setWindowWidth(128);
25         setWindowHeight(128);
26         setConfigRedBits(8);
27         setConfigGreenBits(8);
28         setConfigBlueBits(8);
29         setConfigAlphaBits(8);
30         setConfigDepthBits(24);
31     }
32 
testSetUp()33     void testSetUp() override
34     {
35         if (!IsGLExtensionEnabled("GL_OES_EGL_image_external"))
36         {
37             return;
38         }
39 
40         constexpr GLsizei texSize = 32;
41         GLubyte data[texSize * texSize * 4];
42 
43         for (int y = 0; y < texSize; y++)
44         {
45             float green = static_cast<float>(y) / texSize;
46             for (int x = 0; x < texSize; x++)
47             {
48                 float blue = static_cast<float>(x) / texSize;
49 
50                 data[(y * texSize + x) * 4 + 0] = 0;
51                 data[(y * texSize + x) * 4 + 1] = static_cast<GLubyte>(green * 255);
52                 data[(y * texSize + x) * 4 + 2] = static_cast<GLubyte>(blue * 255);
53                 ;
54                 data[(y * texSize + x) * 4 + 3] = 255;
55             }
56         }
57 
58         glGenTextures(1, &mSourceTexture);
59         glBindTexture(GL_TEXTURE_2D, mSourceTexture);
60         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texSize, texSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
61                      data);
62         glBindTexture(GL_TEXTURE_2D, 0);
63         glGenTextures(1, &mExternalTexture);
64 
65         const char *vertSrc = R"(precision highp float;
66 attribute vec4 a_position;
67 varying vec2 v_texcoord;
68 
69 uniform vec2 u_offset;
70 
71 void main()
72 {
73     gl_Position = a_position;
74     v_texcoord = (a_position.xy * 0.5) + 0.5 + u_offset;
75 }
76 )";
77         const char *fragSrc = R"(#extension GL_OES_EGL_image_external : require
78 precision highp float;
79 uniform samplerExternalOES s_tex;
80 varying vec2 v_texcoord;
81 
82 void main()
83 {
84     gl_FragColor = texture2D(s_tex, v_texcoord);
85 }
86 )";
87 
88         mProgram = CompileProgram(vertSrc, fragSrc);
89         ASSERT_GL_NO_ERROR();
90         ASSERT_NE(mProgram, 0u);
91     }
92 
testTearDown()93     void testTearDown() override
94     {
95         if (mExternalTexture != 0)
96         {
97             glDeleteTextures(1, &mExternalTexture);
98         }
99         if (mSourceTexture != 0)
100         {
101             glDeleteTextures(1, &mSourceTexture);
102         }
103     }
104 
createExternalTexture()105     void createExternalTexture()
106     {
107         ASSERT_TRUE(IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(),
108                                                  "EGL_KHR_gl_texture_2D_image"));
109         ASSERT_TRUE(IsGLExtensionEnabled("GL_OES_EGL_image_external"));
110 
111         EGLWindow *window = getEGLWindow();
112         EGLint attribs[]  = {
113              EGL_IMAGE_PRESERVED,
114              EGL_TRUE,
115              EGL_NONE,
116         };
117         EGLImageKHR image = eglCreateImageKHR(
118             window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
119             reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(mSourceTexture)), attribs);
120         ASSERT_EGL_SUCCESS();
121 
122         glBindTexture(GL_TEXTURE_EXTERNAL_OES, mExternalTexture);
123         glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
124 
125         glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
126         glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
127 
128         ASSERT_GL_NO_ERROR();
129     }
130     GLuint mSourceTexture{0};
131     EGLImageKHR mExternalImage{nullptr};
132     GLuint mExternalTexture{0};
133     GLuint mProgram{0};
134 };
135 
136 // Test the use of an external texture, make the test friendly for triggering MEC
137 // that is - use all the created resources in all frames
TEST_P(EGLImageMECFriendlyTest,DrawExternalTextureInLoop)138 TEST_P(EGLImageMECFriendlyTest, DrawExternalTextureInLoop)
139 {
140     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_EGL_image_external"));
141     ANGLE_SKIP_TEST_IF(
142         !IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_gl_texture_2D_image"));
143 
144     // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
145     ANGLE_SKIP_TEST_IF(IsOzone());
146 
147     createExternalTexture();
148 
149     ASSERT_NE(mProgram, 0u);
150     glUseProgram(mProgram);
151     glBindTexture(GL_TEXTURE_EXTERNAL_OES, mExternalTexture);
152     glUniform2f(glGetUniformLocation(mProgram, "u_offset"), 0.0, 0.0);
153 
154     for (int i = 0; i < 10; ++i)
155     {
156         glClearColor(i / 10.0, 0.0, 0.0, 1.0);
157         glClear(GL_COLOR_BUFFER_BIT);
158         drawQuad(mProgram, "a_position", 0);
159         EXPECT_GL_NO_ERROR();
160         EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 255), kPixelThreshold);
161         EXPECT_PIXEL_COLOR_NEAR(127, 0, GLColor(0, 0, 247, 255), kPixelThreshold);
162         EXPECT_PIXEL_COLOR_NEAR(0, 127, GLColor(0, 247, 0, 255), kPixelThreshold);
163         EXPECT_PIXEL_COLOR_NEAR(127, 127, GLColor(0, 247, 247, 255), kPixelThreshold);
164         swapBuffers();
165     }
166 }
167 
168 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(EGLImageMECFriendlyTest);
169 }  // namespace angle
170