• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2020 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 
7 #include "test_utils/ANGLETest.h"
8 #include "test_utils/gl_raii.h"
9 #include "util/EGLWindow.h"
10 #include "util/OSPixmap.h"
11 #include "util/OSWindow.h"
12 
13 #include <iostream>
14 
15 using namespace angle;
16 
17 class PixmapTest : public ANGLETest
18 {
19   protected:
PixmapTest()20     PixmapTest()
21     {
22         setWindowWidth(512);
23         setWindowHeight(512);
24         setConfigRedBits(8);
25         setConfigGreenBits(8);
26         setConfigBlueBits(8);
27         setConfigAlphaBits(8);
28     }
29 
testSetUp()30     void testSetUp() override
31     {
32         mTextureProgram =
33             CompileProgram(essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
34         if (mTextureProgram == 0)
35         {
36             FAIL() << "shader compilation failed.";
37         }
38 
39         mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "u_tex2D");
40         ASSERT_NE(-1, mTextureUniformLocation);
41 
42         EGLWindow *window = getEGLWindow();
43 
44         EGLint surfaceType = 0;
45         eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_SURFACE_TYPE,
46                            &surfaceType);
47         mSupportsPixmaps = (surfaceType & EGL_PIXMAP_BIT) != 0;
48 
49         EGLint bindToTextureRGBA = 0;
50         eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_BIND_TO_TEXTURE_RGBA,
51                            &bindToTextureRGBA);
52         mSupportsBindTexImage =
53             IsEGLDisplayExtensionEnabled(window->getDisplay(), "EGL_NOK_texture_from_pixmap") &&
54             (bindToTextureRGBA == EGL_TRUE);
55 
56         if (mSupportsPixmaps)
57         {
58             mOSPixmap.reset(CreateOSPixmap());
59 
60             OSWindow *osWindow = getOSWindow();
61 
62             EGLint nativeVisual = 0;
63             ASSERT_TRUE(eglGetConfigAttrib(window->getDisplay(), window->getConfig(),
64                                            EGL_NATIVE_VISUAL_ID, &nativeVisual));
65             ASSERT_TRUE(mOSPixmap->initialize(osWindow->getNativeDisplay(), mPixmapSize,
66                                               mPixmapSize, nativeVisual));
67 
68             std::vector<EGLint> attribs;
69             if (mSupportsBindTexImage)
70             {
71                 attribs.push_back(EGL_TEXTURE_FORMAT);
72                 attribs.push_back(EGL_TEXTURE_RGBA);
73 
74                 attribs.push_back(EGL_TEXTURE_TARGET);
75                 attribs.push_back(EGL_TEXTURE_2D);
76             }
77 
78             attribs.push_back(EGL_NONE);
79 
80             mPixmap = eglCreatePixmapSurface(window->getDisplay(), window->getConfig(),
81                                              mOSPixmap->getNativePixmap(), attribs.data());
82             ASSERT_NE(mPixmap, EGL_NO_SURFACE);
83             ASSERT_EGL_SUCCESS();
84         }
85 
86         ASSERT_GL_NO_ERROR();
87     }
88 
testTearDown()89     void testTearDown() override
90     {
91         glDeleteProgram(mTextureProgram);
92 
93         if (mPixmap)
94         {
95             EGLWindow *window = getEGLWindow();
96             eglDestroySurface(window->getDisplay(), mPixmap);
97         }
98 
99         mOSPixmap = nullptr;
100     }
101 
102     GLuint mTextureProgram;
103     GLint mTextureUniformLocation;
104 
105     std::unique_ptr<OSPixmap> mOSPixmap;
106     EGLSurface mPixmap = EGL_NO_SURFACE;
107 
108     const size_t mPixmapSize = 32;
109     bool mSupportsPixmaps;
110     bool mSupportsBindTexImage;
111 };
112 
113 // Test clearing a Pixmap and checking the color is correct
TEST_P(PixmapTest,Clearing)114 TEST_P(PixmapTest, Clearing)
115 {
116     ANGLE_SKIP_TEST_IF(!mSupportsPixmaps);
117 
118     EGLWindow *window = getEGLWindow();
119 
120     // Clear the window surface to blue and verify
121     window->makeCurrent();
122     ASSERT_EGL_SUCCESS();
123 
124     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
125     glClear(GL_COLOR_BUFFER_BIT);
126     ASSERT_GL_NO_ERROR();
127     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
128 
129     // Apply the Pixmap and clear it to purple and verify
130     eglMakeCurrent(window->getDisplay(), mPixmap, mPixmap, window->getContext());
131     ASSERT_EGL_SUCCESS();
132 
133     glViewport(0, 0, static_cast<GLsizei>(mPixmapSize), static_cast<GLsizei>(mPixmapSize));
134     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
135     glClear(GL_COLOR_BUFFER_BIT);
136     ASSERT_GL_NO_ERROR();
137     EXPECT_PIXEL_EQ(static_cast<GLint>(mPixmapSize) / 2, static_cast<GLint>(mPixmapSize) / 2, 255,
138                     0, 255, 255);
139 
140     // Rebind the window surface and verify that it is still blue
141     window->makeCurrent();
142     ASSERT_EGL_SUCCESS();
143     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
144 }
145 
146 // Bind the Pixmap to a texture and verify it renders correctly
TEST_P(PixmapTest,BindTexImage)147 TEST_P(PixmapTest, BindTexImage)
148 {
149     // Test skipped because pixmaps are not supported or pixmaps do not support binding to RGBA
150     // textures.
151     ANGLE_SKIP_TEST_IF(!mSupportsPixmaps || !mSupportsBindTexImage);
152 
153     // This test fails flakily on Linux intel when run with many other tests.
154     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel());
155     // http://anglebug.com/5385
156     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
157 
158     EGLWindow *window = getEGLWindow();
159 
160     // Apply the Pixmap and clear it to purple
161     eglMakeCurrent(window->getDisplay(), mPixmap, mPixmap, window->getContext());
162     ASSERT_EGL_SUCCESS();
163 
164     glViewport(0, 0, static_cast<GLsizei>(mPixmapSize), static_cast<GLsizei>(mPixmapSize));
165     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
166     glClear(GL_COLOR_BUFFER_BIT);
167     ASSERT_GL_NO_ERROR();
168 
169     EXPECT_PIXEL_EQ(static_cast<GLint>(mPixmapSize) / 2, static_cast<GLint>(mPixmapSize) / 2, 255,
170                     0, 255, 255);
171 
172     // Apply the window surface
173     window->makeCurrent();
174 
175     // Create a texture and bind the pixmap to it
176     GLuint texture = 0;
177     glGenTextures(1, &texture);
178     glBindTexture(GL_TEXTURE_2D, texture);
179     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
180     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
181     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
182     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
183     EXPECT_GL_NO_ERROR();
184 
185     eglBindTexImage(window->getDisplay(), mPixmap, EGL_BACK_BUFFER);
186     glViewport(0, 0, getWindowWidth(), getWindowHeight());
187     ASSERT_EGL_SUCCESS();
188 
189     // Draw a quad and verify that it is purple
190     glUseProgram(mTextureProgram);
191     glUniform1i(mTextureUniformLocation, 0);
192 
193     drawQuad(mTextureProgram, essl31_shaders::PositionAttrib(), 0.5f);
194     EXPECT_GL_NO_ERROR();
195 
196     // Unbind the texture
197     eglReleaseTexImage(window->getDisplay(), mPixmap, EGL_BACK_BUFFER);
198     ASSERT_EGL_SUCCESS();
199 
200     // Verify that purple was drawn
201     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
202 
203     glDeleteTextures(1, &texture);
204 }
205 
206 // Bind a Pixmap, redefine the texture, and verify it renders correctly
TEST_P(PixmapTest,BindTexImageAndRedefineTexture)207 TEST_P(PixmapTest, BindTexImageAndRedefineTexture)
208 {
209     // Test skipped because pixmaps are not supported or Pixmaps do not support binding to RGBA
210     // textures.
211     ANGLE_SKIP_TEST_IF(!mSupportsPixmaps || !mSupportsBindTexImage);
212 
213     EGLWindow *window = getEGLWindow();
214 
215     // Apply the Pixmap and clear it to purple
216     eglMakeCurrent(window->getDisplay(), mPixmap, mPixmap, window->getContext());
217     ASSERT_EGL_SUCCESS();
218 
219     glViewport(0, 0, static_cast<GLsizei>(mPixmapSize), static_cast<GLsizei>(mPixmapSize));
220     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
221     glClear(GL_COLOR_BUFFER_BIT);
222     ASSERT_GL_NO_ERROR();
223 
224     EXPECT_PIXEL_EQ(static_cast<GLint>(mPixmapSize) / 2, static_cast<GLint>(mPixmapSize) / 2, 255,
225                     0, 255, 255);
226 
227     // Apply the window surface
228     window->makeCurrent();
229 
230     // Create a texture and bind the Pixmap to it
231     GLuint texture = 0;
232     glGenTextures(1, &texture);
233     glBindTexture(GL_TEXTURE_2D, texture);
234     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
235     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
236     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
237     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
238     EXPECT_GL_NO_ERROR();
239 
240     eglBindTexImage(window->getDisplay(), mPixmap, EGL_BACK_BUFFER);
241     glViewport(0, 0, getWindowWidth(), getWindowHeight());
242     ASSERT_EGL_SUCCESS();
243 
244     // Redefine the texture
245     unsigned int pixelValue = 0xFFFF00FF;
246     std::vector<unsigned int> pixelData(getWindowWidth() * getWindowHeight(), pixelValue);
247     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
248                  GL_UNSIGNED_BYTE, &pixelData[0]);
249 
250     // Draw a quad and verify that it is magenta
251     glUseProgram(mTextureProgram);
252     glUniform1i(mTextureUniformLocation, 0);
253 
254     drawQuad(mTextureProgram, essl31_shaders::PositionAttrib(), 0.5f);
255     EXPECT_GL_NO_ERROR();
256 
257     // Verify that magenta was drawn
258     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
259 
260     glDeleteTextures(1, &texture);
261 }
262 
263 ANGLE_INSTANTIATE_TEST_ES2(PixmapTest);
264