xref: /aosp_15_r20/external/angle/src/tests/gl_tests/gles1/DrawTextureTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2018 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 // DrawTextureTest.cpp: Tests basic usage of glDrawTex*.
8 
9 #include "test_utils/ANGLETest.h"
10 #include "test_utils/gl_raii.h"
11 
12 #include <memory>
13 #include <vector>
14 
15 using namespace angle;
16 
17 class DrawTextureTest : public ANGLETest<>
18 {
19   protected:
DrawTextureTest()20     DrawTextureTest()
21     {
22         setWindowWidth(kWindowWidth);
23         setWindowHeight(kWindowHeight);
24         setConfigRedBits(8);
25         setConfigGreenBits(8);
26         setConfigBlueBits(8);
27         setConfigAlphaBits(8);
28         setConfigDepthBits(24);
29     }
30 
testSetUp()31     void testSetUp() override
32     {
33         mTexture.reset(new GLTexture());
34         glEnable(GL_TEXTURE_2D);
35         glBindTexture(GL_TEXTURE_2D, mTexture->get());
36     }
37 
testTearDown()38     void testTearDown() override { mTexture.reset(); }
39 
40     std::unique_ptr<GLTexture> mTexture;
41 
42     static constexpr int kWindowWidth  = 32;
43     static constexpr int kWindowHeight = 32;
44 };
45 
46 // Negative test for invalid width/height values.
TEST_P(DrawTextureTest,NegativeValue)47 TEST_P(DrawTextureTest, NegativeValue)
48 {
49     glDrawTexiOES(0, 0, 0, 0, 0);
50     EXPECT_GL_ERROR(GL_INVALID_VALUE);
51     glDrawTexiOES(0, 0, 0, -1, 0);
52     EXPECT_GL_ERROR(GL_INVALID_VALUE);
53     glDrawTexiOES(0, 0, 0, 0, -1);
54     EXPECT_GL_ERROR(GL_INVALID_VALUE);
55     glDrawTexiOES(0, 0, 0, -1, -1);
56     EXPECT_GL_ERROR(GL_INVALID_VALUE);
57 }
58 
59 // Basic draw.
TEST_P(DrawTextureTest,Basic)60 TEST_P(DrawTextureTest, Basic)
61 {
62     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
63     glDrawTexiOES(0, 0, 0, 1, 1);
64     EXPECT_GL_NO_ERROR();
65     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
66 }
67 
68 // Tests that odd viewport dimensions are handled correctly.
69 // If the viewport dimension is even, then the incorrect way
70 // of getting the center screen coordinate by dividing by 2 and
71 // converting to integer will work in that case, but not if
72 // the viewport dimension is odd.
TEST_P(DrawTextureTest,CorrectNdcForOddViewportDimensions)73 TEST_P(DrawTextureTest, CorrectNdcForOddViewportDimensions)
74 {
75     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
76     glClear(GL_COLOR_BUFFER_BIT);
77 
78     // clang-format off
79     std::array<GLColor, 2> textureData = {
80         GLColor::green, GLColor::green
81     };
82     // clang-format on
83 
84     glViewport(0, 0, 3, 3);
85     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData.data());
86 
87     GLint cropRect[] = {0, 0, 2, 1};
88     glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
89     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
90     EXPECT_GL_NO_ERROR();
91 
92     GLint x = 1;
93     GLint y = 1;
94     glDrawTexiOES(x, y, 0, 2, 1);
95     EXPECT_GL_NO_ERROR();
96 
97     EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
98     EXPECT_PIXEL_COLOR_EQ(x + 1, y, GLColor::green);
99 
100     EXPECT_PIXEL_COLOR_EQ(x, y + 1, GLColor::black);
101     EXPECT_PIXEL_COLOR_EQ(x + 1, y + 1, GLColor::black);
102     EXPECT_PIXEL_COLOR_EQ(x + 2, y, GLColor::black);
103     EXPECT_PIXEL_COLOR_EQ(x + 3, y, GLColor::black);
104 }
105 
106 // Tests that vertex attributes enabled with fewer than 6 verts do not cause a crash.
TEST_P(DrawTextureTest,VertexAttributesNoCrash)107 TEST_P(DrawTextureTest, VertexAttributesNoCrash)
108 {
109     glEnableClientState(GL_COLOR_ARRAY);
110     glColorPointer(4, GL_FLOAT, 0, &GLColor::white);
111 
112     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
113     EXPECT_GL_NO_ERROR();
114 
115     glDrawTexiOES(0, 0, 0, 1, 1);
116     EXPECT_GL_NO_ERROR();
117     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
118 }
119 
120 // Tests that the color array, if enabled, is not used as the vertex color.
TEST_P(DrawTextureTest,ColorArrayNotUsed)121 TEST_P(DrawTextureTest, ColorArrayNotUsed)
122 {
123     glEnableClientState(GL_COLOR_ARRAY);
124 
125     // This color is set to black on purpose to ensure that the color in the upcoming vertex array
126     // is not used in the texture draw. If it is used, then the texture we want to read will be
127     // modulated with the color in the vertex array instead of GL_CURRENT_COLOR (which at the moment
128     // is white (1.0, 1.0, 1.0, 1.0).
129     glColorPointer(4, GL_FLOAT, 0, &GLColor::black);
130 
131     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
132     EXPECT_GL_NO_ERROR();
133 
134     glDrawTexiOES(0, 0, 0, 1, 1);
135     EXPECT_GL_NO_ERROR();
136     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
137 }
138 
139 // Tests that values of differenty types are properly normalized with glColorPointer
TEST_P(DrawTextureTest,ColorArrayDifferentTypes)140 TEST_P(DrawTextureTest, ColorArrayDifferentTypes)
141 {
142     constexpr GLubyte kTextureColorData[] = {0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF,
143                                              0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF};
144     constexpr GLfloat kVertexPtrData[]    = {-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f};
145     constexpr GLfloat kTexCoordPtrData[]  = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f};
146     constexpr GLubyte kGLubyteData[]      = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
147                                              0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
148     constexpr GLfloat kGLfloatData[]      = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
149                                              1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
150     constexpr GLfixed kGLfixedData[]      = {0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000,
151                                              0x10000, 0x10000, 0x10000, 0x10000, 0x10000, 0x10000,
152                                              0x10000, 0x10000, 0x10000, 0x10000};
153 
154     // We check a pixel coordinate at the border of where linear interpolation starts as
155     // we fail to get correct interpolated values when we do not normalize the GLbyte values.
156     constexpr GLint kCheckedPixelX         = 16;
157     constexpr GLint kCheckedPixelY         = 8;
158     constexpr unsigned int kPixelTolerance = 10u;
159 
160     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
161     glClear(GL_COLOR_BUFFER_BIT);
162     glEnableClientState(GL_VERTEX_ARRAY);
163     glEnableClientState(GL_COLOR_ARRAY);
164     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
165     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
166     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
167     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
168     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
169     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, kTextureColorData);
170     glVertexPointer(2, GL_FLOAT, 0, kVertexPtrData);
171     glTexCoordPointer(2, GL_FLOAT, 0, kTexCoordPtrData);
172 
173     // Ensure the results do not change unexpectedly regardless of the color data format
174 
175     // Test GLubyte
176     glColorPointer(4, GL_UNSIGNED_BYTE, 0, kGLubyteData);
177     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
178     EXPECT_GL_NO_ERROR();
179     EXPECT_PIXEL_COLOR_NEAR(kCheckedPixelX, kCheckedPixelY, GLColor::red, kPixelTolerance);
180 
181     // Test GLfloat
182     glColorPointer(4, GL_FLOAT, 0, kGLfloatData);
183     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
184     EXPECT_GL_NO_ERROR();
185     EXPECT_PIXEL_COLOR_NEAR(kCheckedPixelX, kCheckedPixelY, GLColor::red, kPixelTolerance);
186 
187     // Test GLfixed
188     glColorPointer(4, GL_FIXED, 0, kGLfixedData);
189     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
190     EXPECT_GL_NO_ERROR();
191     EXPECT_PIXEL_COLOR_NEAR(kCheckedPixelX, kCheckedPixelY, GLColor::red, kPixelTolerance);
192 }
193 
194 // Tests that drawing a primitive works with enabled tex coord pointer, but with texture disabled.
TEST_P(DrawTextureTest,DrawWithTexCoordPtrDataAndDisabledTexture2D)195 TEST_P(DrawTextureTest, DrawWithTexCoordPtrDataAndDisabledTexture2D)
196 {
197     std::vector<GLfloat> vertexPtrData   = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f};
198     std::vector<GLfloat> texCoordPtrData = {0.0f};
199 
200     glEnableClientState(GL_VERTEX_ARRAY);
201     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
202     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
203     glClear(GL_COLOR_BUFFER_BIT);
204 
205     // Draw a triangle fan that covers the entire window. GL_TEXTURE_2D is disabled even though
206     // texture coord pointer is set.
207     glVertexPointer(2, GL_FLOAT, 0, vertexPtrData.data());
208     glTexCoordPointer(2, GL_FLOAT, 0, texCoordPtrData.data());
209     glDisable(GL_TEXTURE_2D);
210     glColor4ub(0, 0xFF, 0xFF, 0xFF);
211     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
212     EXPECT_GL_NO_ERROR();
213     EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth, kWindowHeight, GLColor::cyan);
214 }
215 
216 // Tests that drawing a primitive works with enabled tex coord pointer and texture environment set
217 // so the used texture replaces the current color.
TEST_P(DrawTextureTest,DrawWithTexCoordPtrDataAndEnvModeReplace)218 TEST_P(DrawTextureTest, DrawWithTexCoordPtrDataAndEnvModeReplace)
219 {
220     std::vector<GLfloat> vertexPtrData   = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f};
221     std::vector<GLfloat> texCoordPtrData = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f};
222 
223     glEnableClientState(GL_VERTEX_ARRAY);
224     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
225     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
226     glClear(GL_COLOR_BUFFER_BIT);
227 
228     // Set up the texture. By default, the texture is multiplied by the current color set through
229     // glColor calls. Here the environment is set so it would replace the color instead.
230     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
231     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
232     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
233     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
234     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
235     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
236 
237     // Draw a triangle fan that covers the entire window. The texture should replace the color
238     // regardless of the value of the current color.
239     glVertexPointer(2, GL_FLOAT, 0, vertexPtrData.data());
240     glTexCoordPointer(2, GL_FLOAT, 0, texCoordPtrData.data());
241     glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
242     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
243     EXPECT_GL_NO_ERROR();
244     EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth, kWindowHeight, GLColor::red);
245 }
246 
247 // Tests that tex coord pointer is only used when texture is enabled, and that it is possible to
248 // disable the texture and draw another primitive by setting a color without using the texture data.
TEST_P(DrawTextureTest,DrawWithTexCoordPtrThenDisableTexture2DAndDrawAnother)249 TEST_P(DrawTextureTest, DrawWithTexCoordPtrThenDisableTexture2DAndDrawAnother)
250 {
251     // There will be two vertex arrays for triangle fan draws. Both cover the entire screen, but the
252     // one with no texture uses more vertices.
253     std::vector<GLfloat> vertexPtrDataWithTexture = {-1.0f, -1.0f, -1.0f, 1.0f,
254                                                      1.0f,  1.0f,  1.0f,  -1.0f};
255     std::vector<GLfloat> vertexPtrDataNoTexture   = {-1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
256                                                      1.0f,  1.0f,  1.0f,  0.0f, 1.0f, -1.0f};
257     std::vector<GLfloat> texCoordPtrData = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f};
258 
259     // Enable vertex and texture coordinate pointers. Also set up texture data with four colors; one
260     // color per corner.
261     glEnableClientState(GL_VERTEX_ARRAY);
262     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
263 
264     constexpr GLColor kColorCornerBL = GLColor(0x11, 0x22, 0x33, 0xFF);
265     constexpr GLColor kColorCornerBR = GLColor(0x44, 0x55, 0x66, 0xFF);
266     constexpr GLColor kColorCornerTL = GLColor(0x77, 0x88, 0x99, 0xFF);
267     constexpr GLColor kColorCornerTR = GLColor(0xAA, 0xBB, 0xCC, 0xFF);
268 
269     std::vector<GLColor> textureData;
270     textureData.push_back(kColorCornerBL);
271     textureData.push_back(kColorCornerBR);
272     textureData.push_back(kColorCornerTL);
273     textureData.push_back(kColorCornerTR);
274 
275     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
276     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
277     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
278     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
279     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData.data());
280 
281     // Draw the first triangle fan using texture coord pointer.
282     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
283     glClear(GL_COLOR_BUFFER_BIT);
284     glEnable(GL_TEXTURE_2D);
285 
286     glVertexPointer(2, GL_FLOAT, 0, vertexPtrDataWithTexture.data());
287     glTexCoordPointer(2, GL_FLOAT, 0, texCoordPtrData.data());
288     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
289     EXPECT_GL_NO_ERROR();
290     EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth / 2, kWindowHeight / 2, kColorCornerBL);
291     EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, 0, kWindowWidth / 2, kWindowHeight / 2, kColorCornerBR);
292     EXPECT_PIXEL_RECT_EQ(0, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, kColorCornerTL);
293     EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2,
294                          kColorCornerTR);
295 
296     // Disable texture and draw the second triangle fan. This time, the draw uses more vertex
297     // coordinates and a preset color. Note that the texture coord pointer must no longer be used.
298     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
299     glClear(GL_COLOR_BUFFER_BIT);
300     glDisable(GL_TEXTURE_2D);
301 
302     glVertexPointer(2, GL_FLOAT, 0, vertexPtrDataNoTexture.data());
303     glColor4ub(0, 0, 0xFF, 0xFF);
304     glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
305     EXPECT_GL_NO_ERROR();
306     EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth, kWindowHeight, GLColor::blue);
307 
308     // Re-enable texture and draw using the same vertex pointer. This is to make sure that enabling
309     // GL_TEXTURE_2D is enough to use the texture data.
310     // There is no need to set the texture coord pointer again. However, since GL_TEXTURE_ENV_MODE
311     // is set to the default GL_MODULATE, the effect of glColor4ub() from before should be reversed
312     // by resetting the color to the default (1, 1, 1, 1).
313     // In addition, since the tex coord pointer is not defined for the current vertex pointer, the
314     // texture colors will shift position to be mapped to the new primitive, which will only cover
315     // the top-left half of the window.
316     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
317     glClear(GL_COLOR_BUFFER_BIT);
318     glEnable(GL_TEXTURE_2D);
319 
320     glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
321     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
322     EXPECT_GL_NO_ERROR();
323     EXPECT_PIXEL_COLOR_EQ(0, kWindowHeight / 4, kColorCornerBL);
324     EXPECT_PIXEL_COLOR_EQ(kWindowWidth * 3 / 4, kWindowHeight - 1, kColorCornerBR);
325     EXPECT_PIXEL_COLOR_EQ(0, kWindowHeight * 3 / 4, kColorCornerTL);
326     EXPECT_PIXEL_COLOR_EQ(kWindowWidth / 2, kWindowHeight - 1, kColorCornerTR);
327 
328     // Update the vertex pointer to the original and draw a final triangle fan.
329     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
330     glClear(GL_COLOR_BUFFER_BIT);
331 
332     glVertexPointer(2, GL_FLOAT, 0, vertexPtrDataWithTexture.data());
333     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
334     EXPECT_GL_NO_ERROR();
335     EXPECT_PIXEL_RECT_EQ(0, 0, kWindowWidth / 2, kWindowHeight / 2, kColorCornerBL);
336     EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, 0, kWindowWidth / 2, kWindowHeight / 2, kColorCornerBR);
337     EXPECT_PIXEL_RECT_EQ(0, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2, kColorCornerTL);
338     EXPECT_PIXEL_RECT_EQ(kWindowWidth / 2, kWindowHeight / 2, kWindowWidth / 2, kWindowHeight / 2,
339                          kColorCornerTR);
340 }
341 
342 ANGLE_INSTANTIATE_TEST_ES1(DrawTextureTest);
343