• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
7 #include "test_utils/ANGLETest.h"
8 #include "test_utils/gl_raii.h"
9 
10 using namespace angle;
11 
12 class CubeMapTextureTest : public ANGLETest
13 {
14   protected:
CubeMapTextureTest()15     CubeMapTextureTest()
16     {
17         setWindowWidth(256);
18         setWindowHeight(256);
19         setConfigRedBits(8);
20         setConfigGreenBits(8);
21         setConfigBlueBits(8);
22         setConfigAlphaBits(8);
23     }
24 
testSetUp()25     void testSetUp() override
26     {
27         mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
28         if (mProgram == 0)
29         {
30             FAIL() << "shader compilation failed.";
31         }
32 
33         mColorLocation = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
34 
35         glUseProgram(mProgram);
36 
37         glClearColor(0, 0, 0, 0);
38         glClearDepthf(0.0);
39         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
40 
41         glEnable(GL_BLEND);
42         glDisable(GL_DEPTH_TEST);
43 
44         ASSERT_GL_NO_ERROR();
45     }
46 
testTearDown()47     void testTearDown() override { glDeleteProgram(mProgram); }
48 
49     void runSampleCoordinateTransformTest(const char *shader);
50 
51     GLuint mProgram;
52     GLint mColorLocation;
53 };
54 
55 // Verify that rendering to the faces of a cube map consecutively will correctly render to each
56 // face.
TEST_P(CubeMapTextureTest,RenderToFacesConsecutively)57 TEST_P(CubeMapTextureTest, RenderToFacesConsecutively)
58 {
59     // TODO: Diagnose and fix. http://anglebug.com/2954
60     ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsWindows());
61 
62     // http://anglebug.com/3145
63     ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsFuchsia());
64 
65     // TODO(hqle): Find what wrong with NVIDIA GPU. http://anglebug.com/4138
66     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsMetal());
67 
68     const GLfloat faceColors[] = {
69         1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
70         1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
71     };
72 
73     GLuint tex = 0;
74     glGenTextures(1, &tex);
75     glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
76     for (GLenum face = 0; face < 6; face++)
77     {
78         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
79                      GL_UNSIGNED_BYTE, nullptr);
80     }
81     EXPECT_GL_NO_ERROR();
82 
83     GLuint fbo = 0;
84     glGenFramebuffers(1, &fbo);
85     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
86     EXPECT_GL_NO_ERROR();
87 
88     for (GLenum face = 0; face < 6; face++)
89     {
90         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
91                                GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, tex, 0);
92         EXPECT_GL_NO_ERROR();
93 
94         glUseProgram(mProgram);
95 
96         const GLfloat *faceColor = faceColors + (face * 4);
97         glUniform4f(mColorLocation, faceColor[0], faceColor[1], faceColor[2], faceColor[3]);
98 
99         drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
100         EXPECT_GL_NO_ERROR();
101     }
102 
103     for (GLenum face = 0; face < 6; face++)
104     {
105         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
106                                GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, tex, 0);
107         EXPECT_GL_NO_ERROR();
108 
109         const GLfloat *faceColor = faceColors + (face * 4);
110         EXPECT_PIXEL_EQ(0, 0, faceColor[0] * 255, faceColor[1] * 255, faceColor[2] * 255,
111                         faceColor[3] * 255);
112         EXPECT_GL_NO_ERROR();
113     }
114 
115     glDeleteFramebuffers(1, &fbo);
116     glDeleteTextures(1, &tex);
117 
118     EXPECT_GL_NO_ERROR();
119 }
120 
runSampleCoordinateTransformTest(const char * shader)121 void CubeMapTextureTest::runSampleCoordinateTransformTest(const char *shader)
122 {
123     // Fails to compile the shader.  anglebug.com/3776
124     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows());
125 
126     constexpr GLsizei kCubeFaceCount            = 6;
127     constexpr GLsizei kCubeFaceSectionCount     = 4;
128     constexpr GLsizei kCubeFaceSectionCountSqrt = 2;
129 
130     constexpr GLColor faceColors[kCubeFaceCount][kCubeFaceSectionCount] = {
131         {GLColor(255, 0, 0, 255), GLColor(191, 0, 0, 255), GLColor(127, 0, 0, 255),
132          GLColor(63, 0, 0, 255)},
133         {GLColor(0, 255, 0, 255), GLColor(0, 191, 0, 255), GLColor(0, 127, 0, 255),
134          GLColor(0, 63, 0, 255)},
135         {GLColor(0, 0, 255, 255), GLColor(0, 0, 191, 255), GLColor(0, 0, 127, 255),
136          GLColor(0, 0, 63, 255)},
137         {GLColor(255, 63, 0, 255), GLColor(191, 127, 0, 255), GLColor(127, 191, 0, 255),
138          GLColor(63, 255, 0, 255)},
139         {GLColor(0, 255, 63, 255), GLColor(0, 191, 127, 255), GLColor(0, 127, 191, 255),
140          GLColor(0, 63, 255, 255)},
141         {GLColor(63, 0, 255, 255), GLColor(127, 0, 191, 255), GLColor(191, 0, 127, 255),
142          GLColor(255, 0, 63, 255)},
143     };
144 
145     constexpr GLsizei kTextureSize = 32;
146 
147     GLTexture tex;
148     glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
149     for (GLenum face = 0; face < kCubeFaceCount; face++)
150     {
151         std::vector<GLColor> faceData(kTextureSize * kTextureSize);
152 
153         // Create the face with four sections, each with a solid color from |faceColors|.
154         for (size_t row = 0; row < kTextureSize / kCubeFaceSectionCountSqrt; ++row)
155         {
156             for (size_t col = 0; col < kTextureSize / kCubeFaceSectionCountSqrt; ++col)
157             {
158                 for (size_t srow = 0; srow < kCubeFaceSectionCountSqrt; ++srow)
159                 {
160                     for (size_t scol = 0; scol < kCubeFaceSectionCountSqrt; ++scol)
161                     {
162                         size_t r = row + srow * kTextureSize / kCubeFaceSectionCountSqrt;
163                         size_t c = col + scol * kTextureSize / kCubeFaceSectionCountSqrt;
164                         size_t s = srow * kCubeFaceSectionCountSqrt + scol;
165                         faceData[r * kTextureSize + c] = faceColors[face][s];
166                     }
167                 }
168             }
169         }
170 
171         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, kTextureSize, kTextureSize,
172                      0, GL_RGBA, GL_UNSIGNED_BYTE, faceData.data());
173     }
174     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
175     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
176     EXPECT_GL_NO_ERROR();
177 
178     GLTexture fboTex;
179     glBindTexture(GL_TEXTURE_2D, fboTex);
180     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kCubeFaceCount, kCubeFaceSectionCount, 0, GL_RGBA,
181                  GL_UNSIGNED_BYTE, nullptr);
182 
183     GLFramebuffer fbo;
184     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
185     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
186     EXPECT_GL_NO_ERROR();
187 
188     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), shader);
189     glUseProgram(program);
190 
191     GLint texCubeLocation = glGetUniformLocation(program, "texCube");
192     ASSERT_NE(-1, texCubeLocation);
193     glUniform1i(texCubeLocation, 0);
194 
195     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
196     EXPECT_GL_NO_ERROR();
197 
198     for (GLenum face = 0; face < kCubeFaceCount; face++)
199     {
200         // The following table defines the translation from textureCube coordinates to coordinates
201         // in each face.  The framebuffer has width 6 and height 4.  Every column corresponding to
202         // an x value represents one cube face.  The values in rows are samples from the four
203         // sections of the face.
204         //
205         // Major    Axis Direction Target    sc  tc  ma
206         //  +rx  TEXTURE_CUBE_MAP_POSITIVE_X −rz −ry rx
207         //  −rx  TEXTURE_CUBE_MAP_NEGATIVE_X  rz −ry rx
208         //  +ry  TEXTURE_CUBE_MAP_POSITIVE_Y  rx  rz ry
209         //  −ry  TEXTURE_CUBE_MAP_NEGATIVE_Y  rx −rz ry
210         //  +rz  TEXTURE_CUBE_MAP_POSITIVE_Z  rx −ry rz
211         //  −rz  TEXTURE_CUBE_MAP_NEGATIVE_Z −rx −ry rz
212         //
213         // This table is used only to determine the direction of growth for s and t.  The shader
214         // always generates (row,col) coordinates (0, 0), (0, 1), (1, 0), (1, 1) which is the order
215         // the data is uploaded to the faces, but based on the table above, the sample order would
216         // be different.
217         constexpr size_t faceSampledSections[kCubeFaceCount][kCubeFaceSectionCount] = {
218             {3, 2, 1, 0}, {2, 3, 0, 1}, {0, 1, 2, 3}, {2, 3, 0, 1}, {2, 3, 0, 1}, {3, 2, 1, 0},
219         };
220 
221         for (size_t section = 0; section < kCubeFaceSectionCount; ++section)
222         {
223             const GLColor sectionColor = faceColors[face][faceSampledSections[face][section]];
224 
225             EXPECT_PIXEL_COLOR_EQ(face, section, sectionColor)
226                 << "face " << face << ", section " << section;
227         }
228     }
229     EXPECT_GL_NO_ERROR();
230 }
231 
232 // Verify that cube map sampling follows the rules that map cubemap coordinates to coordinates
233 // within each face.  See section 3.7.5 of GLES2.0 (Cube Map Texture Selection).
TEST_P(CubeMapTextureTest,SampleCoordinateTransform)234 TEST_P(CubeMapTextureTest, SampleCoordinateTransform)
235 {
236     // http://anglebug.com/4092
237     ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D9());
238     // Create a program that samples from 6x4 directions of the cubemap, draw and verify that the
239     // colors match the right color from |faceColors|.
240     constexpr char kFS[] = R"(precision mediump float;
241 
242 uniform samplerCube texCube;
243 
244 const mat4 coordInSection = mat4(
245     vec4(-0.5, -0.5, 0, 0),
246     vec4( 0.5, -0.5, 0, 0),
247     vec4(-0.5,  0.5, 0, 0),
248     vec4( 0.5,  0.5, 0, 0)
249 );
250 
251 void main()
252 {
253     vec3 coord;
254     if (gl_FragCoord.x < 2.0)
255     {
256         coord.x = gl_FragCoord.x < 1.0 ? 1.0 : -1.0;
257         coord.zy = coordInSection[int(gl_FragCoord.y)].xy;
258     }
259     else if (gl_FragCoord.x < 4.0)
260     {
261         coord.y = gl_FragCoord.x < 3.0 ? 1.0 : -1.0;
262         coord.xz = coordInSection[int(gl_FragCoord.y)].xy;
263     }
264     else
265     {
266         coord.z = gl_FragCoord.x < 5.0 ? 1.0 : -1.0;
267         coord.xy = coordInSection[int(gl_FragCoord.y)].xy;
268     }
269 
270     gl_FragColor = textureCube(texCube, coord);
271 })";
272 
273     runSampleCoordinateTransformTest(kFS);
274 }
275 
276 // On Android Vulkan, unequal x and y derivatives cause this test to fail.
TEST_P(CubeMapTextureTest,SampleCoordinateTransformGrad)277 TEST_P(CubeMapTextureTest, SampleCoordinateTransformGrad)
278 {
279     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());  // anglebug.com/3814
280     ANGLE_SKIP_TEST_IF(IsD3D11());                  // anglebug.com/3856
281     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_texture_lod"));
282     // http://anglebug.com/4092
283     ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D9());
284 
285     constexpr char kFS[] = R"(#extension GL_EXT_shader_texture_lod : require
286 precision mediump float;
287 
288 uniform samplerCube texCube;
289 
290 const mat4 coordInSection = mat4(
291     vec4(-0.5, -0.5, 0, 0),
292     vec4( 0.5, -0.5, 0, 0),
293     vec4(-0.5,  0.5, 0, 0),
294     vec4( 0.5,  0.5, 0, 0)
295 );
296 
297 void main()
298 {
299     vec3 coord;
300     if (gl_FragCoord.x < 2.0)
301     {
302         coord.x = gl_FragCoord.x < 1.0 ? 1.0 : -1.0;
303         coord.zy = coordInSection[int(gl_FragCoord.y)].xy;
304     }
305     else if (gl_FragCoord.x < 4.0)
306     {
307         coord.y = gl_FragCoord.x < 3.0 ? 1.0 : -1.0;
308         coord.xz = coordInSection[int(gl_FragCoord.y)].xy;
309     }
310     else
311     {
312         coord.z = gl_FragCoord.x < 5.0 ? 1.0 : -1.0;
313         coord.xy = coordInSection[int(gl_FragCoord.y)].xy;
314     }
315 
316     gl_FragColor = textureCubeGradEXT(texCube, coord,
317                                       vec3(10.0, 10.0, 0.0), vec3(0.0, 10.0, 10.0));
318 })";
319 
320     runSampleCoordinateTransformTest(kFS);
321 }
322 
323 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
324 // tests should be run against.
325 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(CubeMapTextureTest);
326