xref: /aosp_15_r20/external/angle/src/tests/gl_tests/CopyTexImageTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 namespace angle
11 {
12 
13 class CopyTexImageTest : public ANGLETest<>
14 {
15   protected:
CopyTexImageTest()16     CopyTexImageTest()
17     {
18         setWindowWidth(32);
19         setWindowHeight(32);
20         setConfigRedBits(8);
21         setConfigGreenBits(8);
22         setConfigBlueBits(8);
23         setConfigAlphaBits(8);
24     }
25 
testSetUp()26     void testSetUp() override
27     {
28         mTextureProgram =
29             CompileProgram(essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
30         if (mTextureProgram == 0)
31         {
32             FAIL() << "shader compilation failed.";
33         }
34 
35         mTextureUniformLocation =
36             glGetUniformLocation(mTextureProgram, essl1_shaders::Texture2DUniform());
37 
38         ASSERT_GL_NO_ERROR();
39     }
40 
testTearDown()41     void testTearDown() override { glDeleteProgram(mTextureProgram); }
42 
initializeResources(GLenum internalFormat,GLenum format,GLenum type,bool solidColor)43     void initializeResources(GLenum internalFormat, GLenum format, GLenum type, bool solidColor)
44     {
45         for (size_t i = 0; i < kFboCount; ++i)
46         {
47             glBindTexture(GL_TEXTURE_2D, mFboTextures[i]);
48             glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kFboSizes[i], kFboSizes[i], 0, format,
49                          type, nullptr);
50 
51             // Disable mipmapping
52             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
53             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
54 
55             glBindFramebuffer(GL_FRAMEBUFFER, mFbos[i]);
56             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
57                                    mFboTextures[i], 0);
58 
59             if (solidColor)
60             {
61                 glClearColor(kSolidColors[i][0], kSolidColors[i][1], kSolidColors[i][2],
62                              kSolidColors[i][3]);
63             }
64             else
65             {
66                 glClearColor(kFboColors[i][0], kFboColors[i][1], kFboColors[i][2],
67                              kFboColors[i][3]);
68             }
69             glClear(GL_COLOR_BUFFER_BIT);
70         }
71 
72         ASSERT_GL_NO_ERROR();
73     }
74 
initializeResources(GLenum format,GLenum type)75     void initializeResources(GLenum format, GLenum type)
76     {
77         initializeResources(format, format, type, false);
78     }
79 
verifyResults(GLuint texture,const GLubyte data[4],GLint fboSize,GLint xs,GLint ys,GLint xe,GLint ye,double errorBounds)80     void verifyResults(GLuint texture,
81                        const GLubyte data[4],
82                        GLint fboSize,
83                        GLint xs,
84                        GLint ys,
85                        GLint xe,
86                        GLint ye,
87                        double errorBounds)
88     {
89         glViewport(0, 0, fboSize, fboSize);
90 
91         glBindFramebuffer(GL_FRAMEBUFFER, 0);
92 
93         // Draw a quad with the target texture
94         glUseProgram(mTextureProgram);
95         glBindTexture(GL_TEXTURE_2D, texture);
96         glUniform1i(mTextureUniformLocation, 0);
97 
98         drawQuad(mTextureProgram, essl1_shaders::PositionAttrib(), 0.5f);
99 
100         // Expect that the rendered quad has the same color as the source texture
101         EXPECT_PIXEL_NEAR(xs, ys, data[0], data[1], data[2], data[3], errorBounds);
102         EXPECT_PIXEL_NEAR(xs, ye - 1, data[0], data[1], data[2], data[3], errorBounds);
103         EXPECT_PIXEL_NEAR(xe - 1, ys, data[0], data[1], data[2], data[3], errorBounds);
104         EXPECT_PIXEL_NEAR(xe - 1, ye - 1, data[0], data[1], data[2], data[3], errorBounds);
105         EXPECT_PIXEL_NEAR((xs + xe) / 2, (ys + ye) / 2, data[0], data[1], data[2], data[3],
106                           errorBounds);
107     }
108 
verifyCheckeredResults(GLuint texture,const GLubyte data0[4],const GLubyte data1[4],const GLubyte data2[4],const GLubyte data3[4],GLint fboWidth,GLint fboHeight)109     void verifyCheckeredResults(GLuint texture,
110                                 const GLubyte data0[4],
111                                 const GLubyte data1[4],
112                                 const GLubyte data2[4],
113                                 const GLubyte data3[4],
114                                 GLint fboWidth,
115                                 GLint fboHeight)
116     {
117         glViewport(0, 0, fboWidth, fboHeight);
118 
119         glBindFramebuffer(GL_FRAMEBUFFER, 0);
120 
121         // Draw a quad with the target texture
122         glUseProgram(mTextureProgram);
123         glBindTexture(GL_TEXTURE_2D, texture);
124         glUniform1i(mTextureUniformLocation, 0);
125 
126         drawQuad(mTextureProgram, essl1_shaders::PositionAttrib(), 0.5f);
127 
128         // Expect that the rendered quad has the same color as the source texture
129         EXPECT_PIXEL_EQ(fboWidth / 4, fboHeight / 4, data0[0], data0[1], data0[2], data0[3]);
130         EXPECT_PIXEL_EQ(fboWidth / 4, 3 * fboHeight / 4, data1[0], data1[1], data1[2], data1[3]);
131         EXPECT_PIXEL_EQ(3 * fboWidth / 4, fboHeight / 4, data2[0], data2[1], data2[2], data2[3]);
132         EXPECT_PIXEL_EQ(3 * fboWidth / 4, 3 * fboHeight / 4, data3[0], data3[1], data3[2],
133                         data3[3]);
134     }
135 
runCopyTexImageTest(GLenum format,GLubyte expected[3][4],double errorBounds=1.0)136     void runCopyTexImageTest(GLenum format, GLubyte expected[3][4], double errorBounds = 1.0)
137     {
138         GLTexture tex;
139         glBindTexture(GL_TEXTURE_2D, tex);
140 
141         // Disable mipmapping
142         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
143         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
144 
145         // Perform the copy multiple times.
146         //
147         // - The first time, a new texture is created
148         // - The second time, as the fbo size is the same as previous, the texture storage is not
149         //   recreated.
150         // - The third time, the fbo size is different, so a new texture is created.
151         for (size_t i = 0; i < kFboCount; ++i)
152         {
153             glBindFramebuffer(GL_FRAMEBUFFER, mFbos[i]);
154 
155             glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, kFboSizes[i], kFboSizes[i], 0);
156             ASSERT_GL_NO_ERROR();
157 
158             verifyResults(tex, expected[i], kFboSizes[i], 0, 0, kFboSizes[i], kFboSizes[i],
159                           errorBounds);
160         }
161     }
162 
163     // x, y, width, height specify the portion of fbo to be copied into tex.
164     // flip_y specifies if the glCopyTextImage must be done from y-flipped fbo.
runCopyTexImageTestCheckered(GLenum format,const uint32_t x[3],const uint32_t y[3],const uint32_t width[3],const uint32_t height[3],const GLubyte expectedData0[4],const GLubyte expectedData1[4],const GLubyte expectedData2[4],const GLubyte expectedData3[4],bool mesaFlipY)165     void runCopyTexImageTestCheckered(GLenum format,
166                                       const uint32_t x[3],
167                                       const uint32_t y[3],
168                                       const uint32_t width[3],
169                                       const uint32_t height[3],
170                                       const GLubyte expectedData0[4],
171                                       const GLubyte expectedData1[4],
172                                       const GLubyte expectedData2[4],
173                                       const GLubyte expectedData3[4],
174                                       bool mesaFlipY)
175     {
176         GLTexture tex;
177         glBindTexture(GL_TEXTURE_2D, tex);
178 
179         // Disable mipmapping
180         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
181         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
182 
183         // Perform the copy multiple times.
184         for (size_t i = 0; i < kFboCount; ++i)
185         {
186             glViewport(0, 0, kFboSizes[i], kFboSizes[i]);
187             glBindFramebuffer(GL_FRAMEBUFFER, mFbos[i]);
188 
189             ANGLE_GL_PROGRAM(checkerProgram, essl1_shaders::vs::Passthrough(),
190                              essl1_shaders::fs::Checkered());
191             drawQuad(checkerProgram, essl1_shaders::PositionAttrib(), 0.5f);
192             EXPECT_GL_NO_ERROR();
193 
194             if (mesaFlipY)
195                 glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
196             glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x[i], y[i], width[i], height[i], 0);
197             ASSERT_GL_NO_ERROR();
198 
199             verifyCheckeredResults(tex, expectedData0, expectedData1, expectedData2, expectedData3,
200                                    kFboSizes[i], kFboSizes[i]);
201         }
202     }
203 
runCopyTexSubImageTest(GLenum format,GLubyte expected[3][4],double errorBounds=1.0)204     void runCopyTexSubImageTest(GLenum format, GLubyte expected[3][4], double errorBounds = 1.0)
205     {
206         GLTexture tex;
207         glBindTexture(GL_TEXTURE_2D, tex);
208 
209         // Disable mipmapping
210         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
211         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
212 
213         // Create the texture with copy of the first fbo.
214         glBindFramebuffer(GL_FRAMEBUFFER, mFbos[0]);
215         glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, kFboSizes[0], kFboSizes[0], 0);
216         ASSERT_GL_NO_ERROR();
217 
218         verifyResults(tex, expected[0], kFboSizes[0], 0, 0, kFboSizes[0], kFboSizes[0],
219                       errorBounds);
220 
221         // Make sure out-of-bound writes to the texture return invalid value.
222         glBindFramebuffer(GL_FRAMEBUFFER, mFbos[1]);
223 
224         // xoffset < 0 and yoffset < 0
225         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, -1, -1, 0, 0, kFboSizes[0], kFboSizes[0]);
226         ASSERT_GL_ERROR(GL_INVALID_VALUE);
227 
228         // xoffset + width > w and yoffset + height > h
229         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 0, 0, kFboSizes[0], kFboSizes[0]);
230         ASSERT_GL_ERROR(GL_INVALID_VALUE);
231 
232         // xoffset + width > w and yoffset + height > h, out of bounds
233         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, -1, -1, 1 + kFboSizes[0], 1 + kFboSizes[0]);
234         ASSERT_GL_ERROR(GL_INVALID_VALUE);
235 
236         // Copy the second fbo over a portion of the image.
237         GLint offset = kFboSizes[0] / 2;
238         GLint extent = kFboSizes[0] - offset;
239 
240         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, offset, offset, kFboSizes[1] / 2, kFboSizes[1] / 2,
241                             extent, extent);
242         ASSERT_GL_NO_ERROR();
243 
244         verifyResults(tex, expected[1], kFboSizes[0], offset, offset, kFboSizes[0], kFboSizes[0],
245                       errorBounds);
246 
247         // The rest of the image should be untouched
248         verifyResults(tex, expected[0], kFboSizes[0], 0, 0, offset, offset, errorBounds);
249         verifyResults(tex, expected[0], kFboSizes[0], offset, 0, kFboSizes[0], offset, errorBounds);
250         verifyResults(tex, expected[0], kFboSizes[0], 0, offset, offset, kFboSizes[0], errorBounds);
251 
252         // Copy the third fbo over another portion of the image.
253         glBindFramebuffer(GL_FRAMEBUFFER, mFbos[2]);
254 
255         offset = kFboSizes[0] / 4;
256         extent = kFboSizes[0] - offset;
257 
258         // While width and height are set as 3/4 of the size, the fbo offset is given such that
259         // after clipping, width and height are effectively 1/2 of the size.
260         GLint srcOffset       = kFboSizes[2] - kFboSizes[0] / 2;
261         GLint effectiveExtent = kFboSizes[0] / 2;
262 
263         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, offset, offset, srcOffset, srcOffset, extent, extent);
264         ASSERT_GL_NO_ERROR();
265 
266         verifyResults(tex, expected[2], kFboSizes[0], offset, offset, effectiveExtent,
267                       effectiveExtent, errorBounds);
268 
269         // The rest of the image should be untouched
270         verifyResults(tex, expected[1], kFboSizes[0], offset + effectiveExtent, kFboSizes[0] / 2,
271                       kFboSizes[0], kFboSizes[0], errorBounds);
272         verifyResults(tex, expected[1], kFboSizes[0], kFboSizes[0] / 2, offset + effectiveExtent,
273                       kFboSizes[0], kFboSizes[0], errorBounds);
274 
275         verifyResults(tex, expected[0], kFboSizes[0], 0, 0, kFboSizes[0], offset, errorBounds);
276         verifyResults(tex, expected[0], kFboSizes[0], 0, 0, offset, kFboSizes[0], errorBounds);
277         verifyResults(tex, expected[0], kFboSizes[0], offset + effectiveExtent, 0, kFboSizes[0],
278                       kFboSizes[0] / 2, errorBounds);
279         verifyResults(tex, expected[0], kFboSizes[0], 0, offset + effectiveExtent, kFboSizes[0] / 2,
280                       kFboSizes[0], errorBounds);
281     }
282 
testBGRAToRGBAConversion()283     void testBGRAToRGBAConversion()
284     {
285         GLFramebuffer framebuffer;
286         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
287 
288         GLColor bgraInputData(128, 64, 255, 255);
289         GLColor bgraExpectedData(255, 64, 128, 255);
290 
291         GLTexture bgraTexture;
292         glBindTexture(GL_TEXTURE_2D, bgraTexture);
293         glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, 1, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
294                      &bgraInputData);
295 
296         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, bgraTexture, 0);
297         EXPECT_PIXEL_COLOR_EQ(0, 0, bgraExpectedData);
298 
299         // Copy BGRA framebuffer -> RGBA texture
300         GLTexture rgbaTexture;
301         glBindTexture(GL_TEXTURE_2D, rgbaTexture);
302         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
303         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
304 
305         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rgbaTexture, 0);
306         EXPECT_PIXEL_COLOR_EQ(0, 0, bgraExpectedData);
307     }
308 
testRGBAToBGRAConversion()309     void testRGBAToBGRAConversion()
310     {
311         GLFramebuffer framebuffer;
312         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
313 
314         GLColor rgbaData(255, 128, 64, 255);
315 
316         GLTexture rgbaTexture;
317         glBindTexture(GL_TEXTURE_2D, rgbaTexture);
318         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &rgbaData);
319 
320         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rgbaTexture, 0);
321         EXPECT_PIXEL_COLOR_EQ(0, 0, rgbaData);
322 
323         // Copy RGBA framebuffer -> BGRA Texture
324         GLTexture bgraTexture;
325         glBindTexture(GL_TEXTURE_2D, bgraTexture);
326         glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, 1, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
327                      nullptr);
328 
329         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
330 
331         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, bgraTexture, 0);
332         EXPECT_PIXEL_COLOR_EQ(0, 0, rgbaData);
333     }
334 
335     GLuint mTextureProgram;
336     GLint mTextureUniformLocation;
337 
338     static constexpr uint32_t kFboCount = 3;
339     GLFramebuffer mFbos[kFboCount];
340     GLTexture mFboTextures[kFboCount];
341 
342     static constexpr uint32_t kFboSizes[kFboCount]    = {16, 16, 32};
343     static constexpr GLfloat kFboColors[kFboCount][4] = {{0.25f, 1.0f, 0.75f, 0.5f},
344                                                          {1.0f, 0.75f, 0.5f, 0.25f},
345                                                          {0.5f, 0.25f, 1.0f, 0.75f}};
346     static constexpr GLfloat kSolidColors[kFboCount][4] = {{1.0f, 0.0f, 0.0f, 1.0f},
347                                                            {0.0f, 1.0f, 0.0f, 1.0f},
348                                                            {0.0f, 0.0f, 1.0f, 1.0f}};
349 };
350 
351 // CopyTexImage from GL_RGBA to GL_RGB8
TEST_P(CopyTexImageTest,RGBAToRGB8)352 TEST_P(CopyTexImageTest, RGBAToRGB8)
353 {
354     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_required_internalformat"));
355     GLubyte expected[3][4] = {
356         {64, 255, 191, 255},
357         {255, 191, 127, 255},
358         {127, 64, 255, 255},
359     };
360 
361     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
362     runCopyTexImageTest(GL_RGB8, expected);
363 }
364 
365 // CopyTexImage from GL_RGBA to GL_RGBA
TEST_P(CopyTexImageTest,RGBAToRGBA)366 TEST_P(CopyTexImageTest, RGBAToRGBA)
367 {
368     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_required_internalformat"));
369     GLubyte expected[3][4] = {
370         {64, 255, 191, 128},
371         {255, 191, 127, 64},
372         {127, 64, 255, 192},
373     };
374 
375     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
376     runCopyTexImageTest(GL_RGBA, expected);
377 }
378 
TEST_P(CopyTexImageTest,RGBAToL)379 TEST_P(CopyTexImageTest, RGBAToL)
380 {
381     GLubyte expected[3][4] = {
382         {64, 64, 64, 255},
383         {255, 255, 255, 255},
384         {127, 127, 127, 255},
385     };
386 
387     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
388     runCopyTexImageTest(GL_LUMINANCE, expected);
389 }
390 
391 // CopyTexImage from GL_RGBA to GL_LUMINANCE8_OES
TEST_P(CopyTexImageTest,RGBAToL8)392 TEST_P(CopyTexImageTest, RGBAToL8)
393 {
394     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_required_internalformat"));
395     GLubyte expected[3][4] = {
396         {64, 64, 64, 255},
397         {255, 255, 255, 255},
398         {127, 127, 127, 255},
399     };
400 
401     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
402     runCopyTexImageTest(GL_LUMINANCE8_OES, expected);
403 }
404 
TEST_P(CopyTexImageTest,RGBAToLA)405 TEST_P(CopyTexImageTest, RGBAToLA)
406 {
407     GLubyte expected[3][4] = {
408         {64, 64, 64, 127},
409         {255, 255, 255, 64},
410         {127, 127, 127, 191},
411     };
412 
413     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
414     runCopyTexImageTest(GL_LUMINANCE_ALPHA, expected);
415 }
416 
417 // CopyTexImage from GL_RGBA to GL_LUMINANCE8_ALPHA8_OES
TEST_P(CopyTexImageTest,RGBAToL8A8)418 TEST_P(CopyTexImageTest, RGBAToL8A8)
419 {
420     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_required_internalformat"));
421     GLubyte expected[3][4] = {
422         {64, 64, 64, 127},
423         {255, 255, 255, 64},
424         {127, 127, 127, 191},
425     };
426 
427     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
428     runCopyTexImageTest(GL_LUMINANCE8_ALPHA8_OES, expected);
429 }
430 
431 // CopyTexImage from GL_RGBA to GL_LUMINANCE4_ALPHA4_OES
TEST_P(CopyTexImageTest,RGBAToL4A4)432 TEST_P(CopyTexImageTest, RGBAToL4A4)
433 {
434     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_required_internalformat"));
435     GLubyte expected[3][4] = {
436         {64, 64, 64, 127},
437         {255, 255, 255, 64},
438         {127, 127, 127, 191},
439     };
440 
441     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
442     runCopyTexImageTest(GL_LUMINANCE4_ALPHA4_OES, expected, 9.0);
443 }
444 
TEST_P(CopyTexImageTest,RGBAToA)445 TEST_P(CopyTexImageTest, RGBAToA)
446 {
447     GLubyte expected[3][4] = {
448         {0, 0, 0, 127},
449         {0, 0, 0, 64},
450         {0, 0, 0, 191},
451     };
452 
453     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
454     runCopyTexImageTest(GL_ALPHA, expected);
455 }
456 // CopyTexImage from GL_RGBA to GL_ALPHA8_OES
TEST_P(CopyTexImageTest,RGBAToA8)457 TEST_P(CopyTexImageTest, RGBAToA8)
458 {
459     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_required_internalformat"));
460     GLubyte expected[3][4] = {
461         {0, 0, 0, 127},
462         {0, 0, 0, 64},
463         {0, 0, 0, 191},
464     };
465 
466     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
467     runCopyTexImageTest(GL_ALPHA8_OES, expected);
468 }
469 
470 // CopyTexImage from GL_RGBA to GL_RGBA4
TEST_P(CopyTexImageTest,RGBAToRGBA4)471 TEST_P(CopyTexImageTest, RGBAToRGBA4)
472 {
473     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_required_internalformat"));
474     GLubyte expected[3][4] = {
475         {255, 0, 0, 255},
476         {0, 255, 0, 255},
477         {0, 0, 255, 255},
478     };
479 
480     initializeResources(GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE, true);
481     runCopyTexImageTest(GL_RGBA4, expected);
482 }
483 
484 // CopyTexImage from GL_RGB to GL_RGB565
TEST_P(CopyTexImageTest,RGBToRGB565)485 TEST_P(CopyTexImageTest, RGBToRGB565)
486 {
487     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_required_internalformat"));
488     GLubyte expected[3][4] = {
489         {255, 0, 0, 255},
490         {0, 255, 0, 255},
491         {0, 0, 255, 255},
492     };
493 
494     initializeResources(GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE, true);
495     runCopyTexImageTest(GL_RGB565, expected);
496 }
497 
498 // CopyTexImage from GL_RGBA to GL_RGB5_A1
TEST_P(CopyTexImageTest,RGBAToRGB5A1)499 TEST_P(CopyTexImageTest, RGBAToRGB5A1)
500 {
501     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_required_internalformat"));
502     GLubyte expected[3][4] = {
503         {255, 0, 0, 255},
504         {0, 255, 0, 255},
505         {0, 0, 255, 255},
506     };
507 
508     initializeResources(GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE, true);
509     runCopyTexImageTest(GL_RGB5_A1, expected);
510 }
511 
512 // CopyTexImage from GL_RGB to GL_LUMINANCE
TEST_P(CopyTexImageTest,RGBToL)513 TEST_P(CopyTexImageTest, RGBToL)
514 {
515     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_required_internalformat"));
516     GLubyte expected[3][4] = {
517         {64, 64, 64, 255},
518         {255, 255, 255, 255},
519         {127, 127, 127, 255},
520     };
521 
522     initializeResources(GL_RGB, GL_UNSIGNED_BYTE);
523     runCopyTexImageTest(GL_LUMINANCE, expected);
524 }
TEST_P(CopyTexImageTest,SubImageRGBAToRGB)525 TEST_P(CopyTexImageTest, SubImageRGBAToRGB)
526 {
527     GLubyte expected[3][4] = {
528         {64, 255, 191, 255},
529         {255, 191, 127, 255},
530         {127, 64, 255, 255},
531     };
532 
533     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
534     runCopyTexSubImageTest(GL_RGB, expected);
535 }
536 
TEST_P(CopyTexImageTest,SubImageRGBAToL)537 TEST_P(CopyTexImageTest, SubImageRGBAToL)
538 {
539     GLubyte expected[3][4] = {
540         {64, 64, 64, 255},
541         {255, 255, 255, 255},
542         {127, 127, 127, 255},
543     };
544 
545     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
546     runCopyTexSubImageTest(GL_LUMINANCE, expected);
547 }
548 
TEST_P(CopyTexImageTest,SubImageRGBAToLA)549 TEST_P(CopyTexImageTest, SubImageRGBAToLA)
550 {
551     GLubyte expected[3][4] = {
552         {64, 64, 64, 127},
553         {255, 255, 255, 64},
554         {127, 127, 127, 191},
555     };
556 
557     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
558     runCopyTexSubImageTest(GL_LUMINANCE_ALPHA, expected);
559 }
560 
TEST_P(CopyTexImageTest,SubImageRGBToL)561 TEST_P(CopyTexImageTest, SubImageRGBToL)
562 {
563     GLubyte expected[3][4] = {
564         {64, 64, 64, 255},
565         {255, 255, 255, 255},
566         {127, 127, 127, 255},
567     };
568 
569     initializeResources(GL_RGB, GL_UNSIGNED_BYTE);
570     runCopyTexSubImageTest(GL_LUMINANCE, expected);
571 }
572 
TEST_P(CopyTexImageTest,RGBXToL)573 TEST_P(CopyTexImageTest, RGBXToL)
574 {
575     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format"));
576 
577     GLubyte expected[3][4] = {
578         {64, 64, 64, 255},
579         {255, 255, 255, 255},
580         {127, 127, 127, 255},
581     };
582 
583     initializeResources(GL_RGBX8_ANGLE, GL_RGB, GL_UNSIGNED_BYTE, false);
584     runCopyTexImageTest(GL_LUMINANCE, expected);
585 }
586 
587 // Read default framebuffer with glCopyTexImage2D().
TEST_P(CopyTexImageTest,DefaultFramebuffer)588 TEST_P(CopyTexImageTest, DefaultFramebuffer)
589 {
590     // Seems to be a bug in Mesa with the GLX back end: cannot read framebuffer until we draw to it.
591     // glCopyTexImage2D() below will fail without this clear.
592     glClear(GL_COLOR_BUFFER_BIT);
593 
594     const GLint w = getWindowWidth(), h = getWindowHeight();
595     GLTexture tex;
596     glBindTexture(GL_TEXTURE_2D, tex);
597     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
598     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, w, h, 0);
599     EXPECT_GL_NO_ERROR();
600 }
601 
602 // Read default framebuffer with glCopyTexSubImage2D().
TEST_P(CopyTexImageTest,SubDefaultFramebuffer)603 TEST_P(CopyTexImageTest, SubDefaultFramebuffer)
604 {
605     // Seems to be a bug in Mesa with the GLX back end: cannot read framebuffer until we draw to it.
606     // glCopyTexSubImage2D() below will fail without this clear.
607     glClear(GL_COLOR_BUFFER_BIT);
608 
609     const GLint w = getWindowWidth(), h = getWindowHeight();
610     GLTexture tex;
611     glBindTexture(GL_TEXTURE_2D, tex);
612     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
613     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, w, h);
614     EXPECT_GL_NO_ERROR();
615 }
616 
617 // Calling CopyTexSubImage from cubeMap texture.
TEST_P(CopyTexImageTest,CopyTexSubImageFromCubeMap)618 TEST_P(CopyTexImageTest, CopyTexSubImageFromCubeMap)
619 {
620     constexpr GLsizei kCubeMapFaceCount = 6;
621 
622     // The framebuffer will be a face of a cube map with a different colors for each face.  Each
623     // glCopyTexSubImage2D will take one face of this image to copy over a pixel in a 1x6
624     // framebuffer.
625     GLColor fboPixels[kCubeMapFaceCount]   = {GLColor::red,  GLColor::yellow, GLColor::green,
626                                               GLColor::cyan, GLColor::blue,   GLColor::magenta};
627     GLColor whitePixels[kCubeMapFaceCount] = {GLColor::white, GLColor::white, GLColor::white,
628                                               GLColor::white, GLColor::white, GLColor::white};
629 
630     GLTexture fboTex;
631     glBindTexture(GL_TEXTURE_CUBE_MAP, fboTex);
632     for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
633          face++)
634     {
635         GLsizei faceIndex = face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
636 
637         glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &fboPixels[faceIndex]);
638     }
639 
640     GLTexture dstTex;
641     glBindTexture(GL_TEXTURE_2D, dstTex);
642     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kCubeMapFaceCount, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
643                  whitePixels);
644 
645     GLFramebuffer fbo;
646     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
647 
648     for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
649          face++)
650     {
651         GLsizei faceIndex = face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
652 
653         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, face, fboTex, 0);
654 
655         ASSERT_GL_NO_ERROR();
656         ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
657 
658         // Copy the fbo (a cube map face) into a pixel of the destination texture.
659         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, faceIndex, 0, 0, 0, 1, 1);
660     }
661 
662     // Make sure all the copies are done correctly.
663     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dstTex, 0);
664 
665     ASSERT_GL_NO_ERROR();
666     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
667 
668     for (GLsizei faceIndex = 0; faceIndex < kCubeMapFaceCount; ++faceIndex)
669     {
670         EXPECT_PIXEL_COLOR_EQ(faceIndex, 0, fboPixels[faceIndex]);
671     }
672 }
673 
674 // Calling CopyTexSubImage to a non-cube-complete texture.
TEST_P(CopyTexImageTest,CopyTexSubImageToNonCubeCompleteDestination)675 TEST_P(CopyTexImageTest, CopyTexSubImageToNonCubeCompleteDestination)
676 {
677     constexpr GLsizei kCubeMapFaceCount = 6;
678 
679     // The framebuffer will be a 1x6 image with 6 different colors.  Each glCopyTexSubImage2D will
680     // take one pixel of this image to copy over each face of a cube map.
681     GLColor fboPixels[kCubeMapFaceCount] = {GLColor::red,  GLColor::yellow, GLColor::green,
682                                             GLColor::cyan, GLColor::blue,   GLColor::magenta};
683     GLColor whitePixel                   = GLColor::white;
684 
685     GLTexture fboTex;
686     glBindTexture(GL_TEXTURE_2D, fboTex);
687     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kCubeMapFaceCount, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
688                  fboPixels);
689 
690     GLFramebuffer fbo;
691     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
692     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
693 
694     ASSERT_GL_NO_ERROR();
695     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
696 
697     GLTexture cubeMap;
698     glBindTexture(GL_TEXTURE_CUBE_MAP, cubeMap);
699 
700     for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
701          face++)
702     {
703         GLsizei faceIndex = face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
704 
705         // Initialize the face with a color not found in the fbo.
706         glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &whitePixel);
707 
708         // Copy one pixel from the fbo into this face.  The first 5 copies are done on a
709         // non-cube-complete texture.
710         glCopyTexSubImage2D(face, 0, 0, 0, faceIndex, 0, 1, 1);
711     }
712 
713     // Make sure all the copies are done correctly.
714     for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
715          face++)
716     {
717         GLsizei faceIndex = face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
718 
719         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, face, cubeMap, 0);
720 
721         ASSERT_GL_NO_ERROR();
722         ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
723 
724         EXPECT_PIXEL_COLOR_EQ(0, 0, fboPixels[faceIndex]);
725     }
726 }
727 
728 // Deleting textures after copying to them. http://anglebug.com/40644715
TEST_P(CopyTexImageTest,DeleteAfterCopyingToTextures)729 TEST_P(CopyTexImageTest, DeleteAfterCopyingToTextures)
730 {
731     GLTexture texture;
732     glBindTexture(GL_TEXTURE_2D, texture);
733     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
734     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
735     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
736     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
737     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
738 
739     GLTexture texture2;
740     glBindTexture(GL_TEXTURE_2D, texture2);
741     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
742     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
743     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
744     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
745     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
746 
747     GLFramebuffer framebuffer;
748     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
749     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
750     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
751 
752     // Perform CopyTexImage2D
753     glBindTexture(GL_TEXTURE_2D, texture);
754     glCopyTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 0, 0, 2, 2, 0);
755     ASSERT_GL_NO_ERROR();
756     // Not necessary to do any CopyTexImage2D operations to texture2.
757 
758     // Perform CopyTexSubImage2D
759     glBindTexture(GL_TEXTURE_2D, texture);
760     glCopyTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 0, 0, 1, 1);
761     ASSERT_GL_NO_ERROR();
762     glBindTexture(GL_TEXTURE_2D, texture2);
763     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
764     ASSERT_GL_NO_ERROR();
765 
766     // Clean up - provokes crash on buggy drivers.
767     texture.reset();
768     // Crashes on Intel GPUs on macOS.
769     texture2.reset();
770 }
771 
772 // Test if glCopyTexImage2D() implementation performs conversions well from GL_TEXTURE_3D to
773 // GL_TEXTURE_2D.
774 // This is similar to CopyTexImageTestES3.CopyTexSubImageFromTexture3D but for GL_OES_texture_3D
775 // extension.
TEST_P(CopyTexImageTest,CopyTexSubImageFrom3DTexureOES)776 TEST_P(CopyTexImageTest, CopyTexSubImageFrom3DTexureOES)
777 {
778     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_3D"));
779     // TODO(anglebug.com/42262446)
780     // Seems to fail on D3D11 Windows.
781     ANGLE_SKIP_TEST_IF(IsD3D11() && IsWindows());
782 
783     // http://anglebug.com/42263501
784     ANGLE_SKIP_TEST_IF((IsPixel2() || IsNexus5X()) && IsOpenGLES());
785 
786     constexpr GLsizei kDepth = 6;
787 
788     // The framebuffer will be a slice of a 3d texture with a different colors for each slice.  Each
789     // glCopyTexSubImage2D will take one face of this image to copy over a pixel in a 1x6
790     // framebuffer.
791     GLColor fboPixels[kDepth]   = {GLColor::red,  GLColor::yellow, GLColor::green,
792                                    GLColor::cyan, GLColor::blue,   GLColor::magenta};
793     GLColor whitePixels[kDepth] = {GLColor::white, GLColor::white, GLColor::white,
794                                    GLColor::white, GLColor::white, GLColor::white};
795 
796     GLTexture fboTex;
797     glBindTexture(GL_TEXTURE_3D, fboTex);
798     glTexImage3DOES(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, kDepth, 0, GL_RGBA, GL_UNSIGNED_BYTE,
799                     fboPixels);
800 
801     GLTexture dstTex;
802     glBindTexture(GL_TEXTURE_2D, dstTex);
803     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kDepth, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, whitePixels);
804 
805     GLFramebuffer fbo;
806     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
807 
808     for (GLsizei slice = 0; slice < kDepth; ++slice)
809     {
810         glFramebufferTexture3DOES(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, fboTex, 0,
811                                   slice);
812 
813         ASSERT_GL_NO_ERROR();
814         ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
815 
816         // Copy the fbo (a 3d slice) into a pixel of the destination texture.
817         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, slice, 0, 0, 0, 1, 1);
818     }
819 
820     // Make sure all the copies are done correctly.
821     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dstTex, 0);
822 
823     ASSERT_GL_NO_ERROR();
824     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
825 
826     for (GLsizei slice = 0; slice < kDepth; ++slice)
827     {
828         EXPECT_PIXEL_COLOR_EQ(slice, 0, fboPixels[slice]);
829     }
830 }
831 
832 // Tests image copy from y-flipped fbo works.
TEST_P(CopyTexImageTest,CopyTexImageMesaYFlip)833 TEST_P(CopyTexImageTest, CopyTexImageMesaYFlip)
834 {
835     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
836 
837     std::array<uint32_t, 3> copyOrigin{0};
838     std::array<uint32_t, 3> copySize;
839     for (size_t i = 0; i < kFboCount; i++)
840         copySize[i] = kFboSizes[i];
841 
842     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
843     runCopyTexImageTestCheckered(GL_RGBA, copyOrigin.data(), copyOrigin.data(), copySize.data(),
844                                  copySize.data(), GLColor::green.data(), GLColor::red.data(),
845                                  GLColor::yellow.data(), GLColor::blue.data(),
846                                  true /* mesaFlipY */);
847 }
848 
849 // Tests image partial copy from y-flipped fbo works.
TEST_P(CopyTexImageTest,CopyTexImageMesaYFlipPartial)850 TEST_P(CopyTexImageTest, CopyTexImageMesaYFlipPartial)
851 {
852     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
853 
854     std::array<uint32_t, kFboCount> copyX;
855     std::array<uint32_t, kFboCount> copyY{0};
856     std::array<uint32_t, kFboCount> copyWidth;
857     std::array<uint32_t, kFboCount> copyHeight;
858 
859     for (size_t i = 0; i < kFboCount; i++)
860     {
861         copyX[i]      = kFboSizes[i] / 2;
862         copyHeight[i] = kFboSizes[i];
863     }
864     copyWidth = copyX;
865 
866     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
867     runCopyTexImageTestCheckered(GL_RGBA, copyX.data(), copyY.data(), copyWidth.data(),
868                                  copyHeight.data(), GLColor::yellow.data(), GLColor::blue.data(),
869                                  GLColor::yellow.data(), GLColor::blue.data(),
870                                  true /* mesaFlipY */);
871 }
872 
873 // Tests subimage copy from y-flipped fbo works.
TEST_P(CopyTexImageTest,CopyTexSubImageMesaYFlip)874 TEST_P(CopyTexImageTest, CopyTexSubImageMesaYFlip)
875 {
876     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
877 
878     GLuint format = GL_RGBA;
879     initializeResources(format, GL_UNSIGNED_BYTE);
880 
881     glViewport(0, 0, kFboSizes[0], kFboSizes[0]);
882     glBindFramebuffer(GL_FRAMEBUFFER, mFbos[0]);
883 
884     ANGLE_GL_PROGRAM(checkerProgram, essl1_shaders::vs::Passthrough(),
885                      essl1_shaders::fs::Checkered());
886     drawQuad(checkerProgram, essl1_shaders::PositionAttrib(), 0.5f);
887     EXPECT_GL_NO_ERROR();
888 
889     GLTexture tex;
890     glBindTexture(GL_TEXTURE_2D, tex);
891 
892     // Disable mipmapping
893     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
894     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
895 
896     // Create the texture with copy of the first fbo.
897     glBindFramebuffer(GL_FRAMEBUFFER, mFbos[0]);
898     glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
899     glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, kFboSizes[0], kFboSizes[0], 0);
900     ASSERT_GL_NO_ERROR();
901 
902     // Make sure out-of-bound writes to the texture return invalid value.
903     glBindFramebuffer(GL_FRAMEBUFFER, mFbos[1]);
904     drawQuad(checkerProgram, essl1_shaders::PositionAttrib(), 0.5f);
905     EXPECT_GL_NO_ERROR();
906 
907     glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
908 
909     // xoffset < 0 and yoffset < 0
910     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, -1, -1, 0, 0, kFboSizes[0], kFboSizes[0]);
911     ASSERT_GL_ERROR(GL_INVALID_VALUE);
912 
913     // xoffset + width > w and yoffset + height > h
914     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 0, 0, kFboSizes[0], kFboSizes[0]);
915     ASSERT_GL_ERROR(GL_INVALID_VALUE);
916 
917     // xoffset + width > w and yoffset + height > h, out of bounds
918     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, -1, -1, 1 + kFboSizes[0], 1 + kFboSizes[0]);
919     ASSERT_GL_ERROR(GL_INVALID_VALUE);
920 
921     // Copy the second fbo over a portion of the image.
922     GLint offset = kFboSizes[0] / 2;
923     GLint extent = kFboSizes[0] - offset;
924     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, offset, offset, kFboSizes[1] / 2, kFboSizes[1] / 2,
925                         extent, extent);
926     ASSERT_GL_NO_ERROR();
927 
928     // Only part of the image is changed.
929     verifyCheckeredResults(tex, GLColor::green.data(), GLColor::red.data(), GLColor::yellow.data(),
930                            GLColor::blue.data(), kFboSizes[0], kFboSizes[0]);
931 }
932 
933 // Tests that set RobustResourceInit to true, so that code path with
934 // RobustResourceInit == true can be checked
935 class CopyTexImageTestRobustResourceInit : public CopyTexImageTest
936 {
937   protected:
CopyTexImageTestRobustResourceInit()938     CopyTexImageTestRobustResourceInit() : CopyTexImageTest() { setRobustResourceInit(true); }
939 };
940 
941 // Adapted from the fuzz test with invalid input
TEST_P(CopyTexImageTestRobustResourceInit,InvalidInputParam)942 TEST_P(CopyTexImageTestRobustResourceInit, InvalidInputParam)
943 {
944     glClear(GL_COLOR_BUFFER_BIT);
945 
946     const GLint w = getWindowWidth(), h = getWindowHeight();
947     GLTexture tex;
948     glBindTexture(GL_TEXTURE_2D, tex);
949     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
950 
951     // pass y that is greater than max2DTextureSize
952     GLenum target         = GL_TEXTURE_2D;
953     GLint level           = 0;
954     GLenum internalFormat = GL_LUMINANCE_ALPHA;
955     GLint x               = 0;
956     GLint y               = 13434880;
957     GLsizei width         = 0;
958     GLsizei height        = 65830;
959     GLint border          = 0;
960     glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
961     EXPECT_GL_ERROR(GL_INVALID_VALUE);
962 
963     // pass x and width that will result in integer overflow when we apply x+width
964     target         = GL_TEXTURE_2D;
965     level          = 0;
966     internalFormat = GL_LUMINANCE_ALPHA;
967     x              = std::numeric_limits<GLint>::max();
968     y              = 0;
969     width          = 253;
970     height         = 1;
971     border         = 0;
972     glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
973     EXPECT_GL_ERROR(GL_INVALID_VALUE);
974 }
975 
976 // specialization of CopyTexImageTest is added so that some tests can be explicitly run with an ES3
977 // context
978 class CopyTexImageTestES3 : public CopyTexImageTest
979 {
980   protected:
981     void initialize3DTexture(GLTexture &texture,
982                              const GLsizei imageWidth,
983                              const GLsizei imageHeight,
984                              const GLsizei imageDepth,
985                              const GLColor *textureData);
986     void initialize2DTexture(GLTexture &texture,
987                              const GLsizei imageWidth,
988                              const GLsizei imageHeight,
989                              const GLColor *textureData);
990     void initialize2DTextureUShort4444(GLTexture &texture,
991                                        const GLsizei imageWidth,
992                                        const GLsizei imageHeight,
993                                        const GLColor *textureData);
994     void fillTexture(std::vector<GLColor> &texture, const GLColor color);
995     void clearTexture(GLFramebuffer &fbo, GLTexture &texture, const GLColor color);
996     void copyTexSubImage3D(GLTexture &subTexture2D,
997                            const GLint xOffset,
998                            const GLint yOffset,
999                            const GLsizei subImageWidth,
1000                            const GLsizei subImageHeight,
1001                            const GLsizei imageDepth);
1002     void verifyCopyTexSubImage3D(GLTexture &texture3D,
1003                                  const GLint xOffset,
1004                                  const GLint yOffset,
1005                                  const GLColor subImageColor);
1006 
1007     // Constants
1008     const GLColor kSubImageColor = GLColor::yellow;
1009     // 3D image dimensions
1010     const GLsizei kImageWidth  = getWindowWidth();
1011     const GLsizei kImageHeight = getWindowHeight();
1012     const GLsizei kImageDepth  = 4;
1013     // 2D sub-image dimensions
1014     const GLsizei kSubImageWidth  = getWindowWidth() / 4;
1015     const GLsizei kSubImageHeight = getWindowHeight() / 4;
1016     // Sub-Image Offsets
1017     const GLint kXOffset = getWindowWidth() - kSubImageWidth;
1018     const GLint kYOffset = getWindowHeight() - kSubImageHeight;
1019 };
1020 
1021 //  The test verifies that glCopyTexSubImage2D generates a GL_INVALID_OPERATION error
1022 //  when the read buffer is GL_NONE.
1023 //  Reference: GLES 3.0.4, Section 3.8.5 Alternate Texture Image Specification Commands
TEST_P(CopyTexImageTestES3,ReadBufferIsNone)1024 TEST_P(CopyTexImageTestES3, ReadBufferIsNone)
1025 {
1026     initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
1027 
1028     GLTexture tex;
1029     glBindTexture(GL_TEXTURE_2D, tex);
1030     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1031     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1032 
1033     glBindFramebuffer(GL_FRAMEBUFFER, mFbos[0]);
1034     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kFboSizes[0], kFboSizes[0], 0);
1035 
1036     glReadBuffer(GL_NONE);
1037 
1038     EXPECT_GL_NO_ERROR();
1039     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 4, 4);
1040     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1041 }
1042 
1043 // Test CopyTexImage3D with some simple parameters with a 2D array texture.
1044 TEST_P(CopyTexImageTestES3, 2DArraySubImage)
1045 {
1046     // Seems to fail on AMD OpenGL Windows.
1047     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && IsWindows());
1048 
1049     GLTexture tex;
1050     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
1051 
1052     constexpr GLsizei kTexSize     = 4;
1053     constexpr GLsizei kLayerOffset = 1;
1054     constexpr GLsizei kLayers      = 2;
1055 
1056     // Clear screen to green.
1057     glClearColor(0, 1, 0, 1);
1058     glClear(GL_COLOR_BUFFER_BIT);
1059 
1060     // Initialize a two-layer 2D array texture with red.
1061     std::vector<GLColor> red(kTexSize * kTexSize * kLayers, GLColor::red);
1062     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kTexSize, kTexSize, kLayers, 0, GL_RGBA,
1063                  GL_UNSIGNED_BYTE, red.data());
1064     glCopyTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, kLayerOffset, 0, 0, kTexSize, kTexSize);
1065     ASSERT_GL_NO_ERROR();
1066 
1067     // Check level 0 (red from image data) and 1 (green from backbuffer clear).
1068     GLFramebuffer fbo;
1069     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1070     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0);
1071     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1072     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
1073     for (int x = 0; x < kTexSize; x++)
1074     {
1075         for (int y = 0; y < kTexSize; y++)
1076         {
1077             EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
1078         }
1079     }
1080     ASSERT_GL_NO_ERROR();
1081 }
1082 
1083 // Test if glCopyTexImage2D() implementation performs conversions well from GL_TEXTURE_3D to
1084 // GL_TEXTURE_2D.
TEST_P(CopyTexImageTestES3,CopyTexSubImageFromTexture3D)1085 TEST_P(CopyTexImageTestES3, CopyTexSubImageFromTexture3D)
1086 {
1087     // TODO(anglebug.com/42262446)
1088     // Seems to fail on D3D11 Windows.
1089     ANGLE_SKIP_TEST_IF(IsD3D11() && IsWindows());
1090 
1091     constexpr GLsizei kTexSize = 4;
1092     constexpr GLsizei kLayers  = 2;
1093     std::vector<GLColor> red(kTexSize * kTexSize * kLayers, GLColor::red);
1094 
1095     GLFramebuffer fbo;
1096     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
1097     glBindTexture(GL_TEXTURE_2D, 0);
1098 
1099     // We will be reading from zeroth color attachment.
1100     glReadBuffer(GL_COLOR_ATTACHMENT0);
1101 
1102     GLTexture src_object_id;
1103     glBindTexture(GL_TEXTURE_3D, src_object_id);
1104     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, kTexSize, kTexSize, kLayers, 0, GL_RGBA,
1105                  GL_UNSIGNED_BYTE, NULL);
1106     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 1, kTexSize, kTexSize, 1, GL_RGBA, GL_UNSIGNED_BYTE,
1107                     red.data());
1108     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, src_object_id, 0, 1);
1109     ASSERT_GL_NO_ERROR();
1110 
1111     GLTexture dst_object_id;
1112     glBindTexture(GL_TEXTURE_2D, dst_object_id);
1113     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, kTexSize, kTexSize, 0);
1114     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_object_id,
1115                            0);
1116     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1117     ASSERT_GL_NO_ERROR();
1118 }
1119 
1120 // Test that copying a 3D texture slice into another 3D texture slice via framebuffer works
TEST_P(CopyTexImageTestES3,CopyTexSubImage3DFromTexture3D)1121 TEST_P(CopyTexImageTestES3, CopyTexSubImage3DFromTexture3D)
1122 {
1123     constexpr GLsizei kTexSize = 4;
1124     constexpr GLsizei kLayers  = 2;
1125     std::vector<GLColor> red(kTexSize * kTexSize, GLColor::red);
1126     std::vector<GLColor> green(kTexSize * kTexSize, GLColor::green);
1127 
1128     GLTexture srcTex;
1129     glBindTexture(GL_TEXTURE_3D, srcTex);
1130     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, kTexSize, kTexSize, kLayers, 0, GL_RGBA,
1131                  GL_UNSIGNED_BYTE, nullptr);
1132     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kTexSize, kTexSize, 1, GL_RGBA, GL_UNSIGNED_BYTE,
1133                     red.data());
1134     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 1, kTexSize, kTexSize, 1, GL_RGBA, GL_UNSIGNED_BYTE,
1135                     green.data());
1136     ASSERT_GL_NO_ERROR();
1137 
1138     GLFramebuffer fbo;
1139     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
1140 
1141     GLTexture dstTex;
1142     glBindTexture(GL_TEXTURE_3D, dstTex);
1143     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, kTexSize, kTexSize, kLayers, 0, GL_RGBA,
1144                  GL_UNSIGNED_BYTE, nullptr);
1145     ASSERT_GL_NO_ERROR();
1146 
1147     // Copy while swapping the layers
1148     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, srcTex, 0, 0);
1149     glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 1, 0, 0, kTexSize, kTexSize);
1150     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, srcTex, 0, 1);
1151     glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, kTexSize, kTexSize);
1152     ASSERT_GL_NO_ERROR();
1153 
1154     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dstTex, 0, 0);
1155     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1156     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dstTex, 0, 1);
1157     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1158 }
1159 
1160 // Test that copying from a non-zero base texture works.
TEST_P(CopyTexImageTestES3,CopyTexSubImageFromNonZeroBase)1161 TEST_P(CopyTexImageTestES3, CopyTexSubImageFromNonZeroBase)
1162 {
1163     // http://anglebug.com/40644750
1164     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows());
1165 
1166     constexpr GLsizei kTexSize = 4;
1167     std::vector<GLColor> red(kTexSize * kTexSize, GLColor::red);
1168     std::vector<GLColor> green(kTexSize * kTexSize, GLColor::green);
1169 
1170     // Create a framebuffer attached to a non-zero base texture
1171     GLTexture srcColor;
1172     glBindTexture(GL_TEXTURE_2D, srcColor);
1173     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1174                  red.data());
1175     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1176                  green.data());
1177     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1178     ASSERT_GL_NO_ERROR();
1179 
1180     GLFramebuffer fbo;
1181     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1182     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcColor, 1);
1183     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1184 
1185     // Create a texture with an identical format
1186     GLTexture dstColor;
1187     glBindTexture(GL_TEXTURE_2D, dstColor);
1188     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1189                  nullptr);
1190     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1191     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1192     ASSERT_GL_NO_ERROR();
1193 
1194     // Copy into a part of this texture.
1195     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kTexSize / 2, kTexSize / 2);
1196     ASSERT_GL_NO_ERROR();
1197 
1198     // Verify it.
1199     constexpr std::array<GLubyte, 4> kExpected = {0, 255, 0, 255};
1200     verifyResults(dstColor, kExpected.data(), kTexSize, 0, 0, kTexSize / 2, kTexSize / 2, 1.0);
1201 
1202     // Copy into another part of the texture.  The previous verification ensures that the texture's
1203     // internal image is allocated, so this should be a direct copy.
1204     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1205     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kTexSize / 2, kTexSize / 2, 0, 0, kTexSize / 2,
1206                         kTexSize / 2);
1207     ASSERT_GL_NO_ERROR();
1208 
1209     // Verify it.
1210     verifyResults(dstColor, kExpected.data(), kTexSize, kTexSize / 2, kTexSize / 2, kTexSize,
1211                   kTexSize, 1.0);
1212 }
1213 
1214 // Test that copying into a non-zero base texture works.
TEST_P(CopyTexImageTestES3,CopyTexSubImageToNonZeroBase)1215 TEST_P(CopyTexImageTestES3, CopyTexSubImageToNonZeroBase)
1216 {
1217     // http://anglebug.com/40644750
1218     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows());
1219 
1220     constexpr GLsizei kTexSize = 4;
1221     std::vector<GLColor> green(kTexSize * kTexSize, GLColor::green);
1222 
1223     // Create a framebuffer attached to a non-zero base texture
1224     GLTexture srcColor;
1225     glBindTexture(GL_TEXTURE_2D, srcColor);
1226     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1227                  green.data());
1228     ASSERT_GL_NO_ERROR();
1229 
1230     GLFramebuffer fbo;
1231     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1232     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcColor, 0);
1233     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1234 
1235     // Create a texture with an identical format
1236     GLTexture dstColor;
1237     glBindTexture(GL_TEXTURE_2D, dstColor);
1238     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1239                  nullptr);
1240     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1241                  nullptr);
1242     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1243     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
1244     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1245     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1246     ASSERT_GL_NO_ERROR();
1247 
1248     // Copy into a part of this texture.
1249     glCopyTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 0, 0, kTexSize / 2, kTexSize / 2);
1250     ASSERT_GL_NO_ERROR();
1251 
1252     // Verify it.
1253     constexpr std::array<GLubyte, 4> kExpected = {0, 255, 0, 255};
1254     verifyResults(dstColor, kExpected.data(), kTexSize, 0, 0, kTexSize / 2, kTexSize / 2, 1.0);
1255 
1256     // Copy into another part of the texture.  The previous verification ensures that the texture's
1257     // internal image is allocated, so this should be a direct copy.
1258     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1259     glCopyTexSubImage2D(GL_TEXTURE_2D, 1, kTexSize / 2, kTexSize / 2, 0, 0, kTexSize / 2,
1260                         kTexSize / 2);
1261     ASSERT_GL_NO_ERROR();
1262 
1263     // Verify it.
1264     verifyResults(dstColor, kExpected.data(), kTexSize, kTexSize / 2, kTexSize / 2, kTexSize,
1265                   kTexSize, 1.0);
1266 }
1267 
1268 // Initialize the 3D texture we will copy the subImage data into
initialize3DTexture(GLTexture & texture,const GLsizei imageWidth,const GLsizei imageHeight,const GLsizei imageDepth,const GLColor * textureData)1269 void CopyTexImageTestES3::initialize3DTexture(GLTexture &texture,
1270                                               const GLsizei imageWidth,
1271                                               const GLsizei imageHeight,
1272                                               const GLsizei imageDepth,
1273                                               const GLColor *textureData)
1274 {
1275     glBindTexture(GL_TEXTURE_3D, texture);
1276     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, imageWidth, imageHeight, imageDepth, 0, GL_RGBA,
1277                  GL_UNSIGNED_BYTE, textureData);
1278     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1279     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1280     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
1281     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1282     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1283 }
1284 
initialize2DTexture(GLTexture & texture,const GLsizei imageWidth,const GLsizei imageHeight,const GLColor * textureData)1285 void CopyTexImageTestES3::initialize2DTexture(GLTexture &texture,
1286                                               const GLsizei imageWidth,
1287                                               const GLsizei imageHeight,
1288                                               const GLColor *textureData)
1289 {
1290     glBindTexture(GL_TEXTURE_2D, texture);
1291     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1292                  textureData);
1293     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1294     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1295 }
1296 
initialize2DTextureUShort4444(GLTexture & texture,const GLsizei imageWidth,const GLsizei imageHeight,const GLColor * textureData)1297 void CopyTexImageTestES3::initialize2DTextureUShort4444(GLTexture &texture,
1298                                                         const GLsizei imageWidth,
1299                                                         const GLsizei imageHeight,
1300                                                         const GLColor *textureData)
1301 {
1302     glBindTexture(GL_TEXTURE_2D, texture);
1303     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_RGBA,
1304                  GL_UNSIGNED_SHORT_4_4_4_4, textureData);
1305     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1306     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1307 }
1308 
fillTexture(std::vector<GLColor> & texture,const GLColor color)1309 void CopyTexImageTestES3::fillTexture(std::vector<GLColor> &texture, const GLColor color)
1310 {
1311     for (auto &texel : texture)
1312     {
1313         texel = color;
1314     }
1315 }
1316 
clearTexture(GLFramebuffer & fbo,GLTexture & texture,const GLColor color)1317 void CopyTexImageTestES3::clearTexture(GLFramebuffer &fbo, GLTexture &texture, const GLColor color)
1318 {
1319     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1320     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1321     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1322     glClearColor(color.R, color.G, color.B, color.A);
1323     glClear(GL_COLOR_BUFFER_BIT);
1324     EXPECT_PIXEL_COLOR_EQ(0, 0, color);
1325 }
1326 
copyTexSubImage3D(GLTexture & subTexture2D,const GLint xOffset,const GLint yOffset,const GLsizei subImageWidth,const GLsizei subImageHeight,const GLsizei imageDepth)1327 void CopyTexImageTestES3::copyTexSubImage3D(GLTexture &subTexture2D,
1328                                             const GLint xOffset,
1329                                             const GLint yOffset,
1330                                             const GLsizei subImageWidth,
1331                                             const GLsizei subImageHeight,
1332                                             const GLsizei imageDepth)
1333 {
1334     // Copy the 2D sub-image into the 3D texture
1335     for (int currLayer = 0; currLayer < imageDepth; ++currLayer)
1336     {
1337         // Bind the 2D texture to GL_COLOR_ATTACHMENT0
1338         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1339                                subTexture2D, 0);
1340         ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1341         glCopyTexSubImage3D(GL_TEXTURE_3D, 0, xOffset, yOffset, currLayer, 0, 0, subImageWidth,
1342                             subImageHeight);
1343         ASSERT_GL_NO_ERROR();
1344     }
1345 }
1346 
verifyCopyTexSubImage3D(GLTexture & texture3D,const GLint xOffset,const GLint yOffset,const GLColor subImageColor)1347 void CopyTexImageTestES3::verifyCopyTexSubImage3D(GLTexture &texture3D,
1348                                                   const GLint xOffset,
1349                                                   const GLint yOffset,
1350                                                   const GLColor subImageColor)
1351 {
1352     // Bind to an FBO to check the copy was successful
1353     for (int currLayer = 0; currLayer < kImageDepth; ++currLayer)
1354     {
1355         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture3D, 0, currLayer);
1356         ASSERT_GL_NO_ERROR();
1357         EXPECT_PIXEL_COLOR_EQ(xOffset, yOffset, subImageColor);
1358     }
1359 }
1360 
1361 // Test glCopyTexSubImage3D with initialized texture data
1362 TEST_P(CopyTexImageTestES3, 3DSubImageRawTextureData)
1363 {
1364     // Texture data
1365     std::vector<GLColor> textureData(kImageWidth * kImageHeight * kImageDepth);
1366 
1367     // Fill the textures with color
1368     fillTexture(textureData, GLColor::red);
1369 
1370     GLFramebuffer fbo;
1371     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1372 
1373     GLTexture texture3D;
1374     initialize3DTexture(texture3D, kImageWidth, kImageHeight, kImageDepth, textureData.data());
1375 
1376     // The 2D texture that will be the sub-image copied into the destination texture
1377     GLTexture subTexture2D;
1378     initialize2DTexture(subTexture2D, kSubImageWidth, kSubImageHeight, nullptr);
1379     clearTexture(fbo, subTexture2D, kSubImageColor);
1380 
1381     // Copy the 2D subimage into the 3D texture
1382     copyTexSubImage3D(subTexture2D, kXOffset, kYOffset, kSubImageWidth, kSubImageHeight,
1383                       kImageDepth);
1384 
1385     // Verify the color wasn't overwritten
1386     verifyCopyTexSubImage3D(texture3D, 0, 0, GLColor::red);
1387     // Verify the copy succeeded
1388     verifyCopyTexSubImage3D(texture3D, kXOffset, kYOffset, kSubImageColor);
1389 
1390     glBindFramebuffer(GL_FRAMEBUFFER, 0);
1391     glBindTexture(GL_TEXTURE_2D, 0);
1392     glBindTexture(GL_TEXTURE_3D, 0);
1393 }
1394 
1395 // Test glCopyTexSubImage3D with initialized texture data that was drawn to
1396 TEST_P(CopyTexImageTestES3, 3DSubImageDrawTextureData)
1397 {
1398     GLFramebuffer fbo;
1399     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1400 
1401     // The 3D texture we will copy the sub-image into
1402     GLTexture texture3D;
1403     initialize3DTexture(texture3D, kImageWidth, kImageHeight, kImageDepth, nullptr);
1404 
1405     // Draw to each layer in the 3D texture
1406     for (int currLayer = 0; currLayer < kImageDepth; ++currLayer)
1407     {
1408         ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1409         glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture3D, 0,
1410                                   currLayer);
1411         glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture3D, 0,
1412                                   currLayer);
1413         ASSERT_GL_NO_ERROR();
1414         glUseProgram(greenProgram);
1415         drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1416         ASSERT_GL_NO_ERROR();
1417         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1418     }
1419 
1420     // The 2D texture that will be the sub-image copied into the destination texture
1421     GLTexture subTexture2D;
1422     initialize2DTexture(subTexture2D, kSubImageWidth, kSubImageHeight, nullptr);
1423     clearTexture(fbo, subTexture2D, kSubImageColor);
1424 
1425     // Copy the 2D sub-image into the 3D texture
1426     copyTexSubImage3D(subTexture2D, kXOffset, kYOffset, kSubImageWidth, kSubImageHeight,
1427                       kImageDepth);
1428 
1429     // Verify the color wasn't overwritten
1430     verifyCopyTexSubImage3D(texture3D, 0, 0, GLColor::green);
1431     // Verify the copy succeeded
1432     verifyCopyTexSubImage3D(texture3D, kXOffset, kYOffset, kSubImageColor);
1433 
1434     glBindFramebuffer(GL_FRAMEBUFFER, 0);
1435     glBindTexture(GL_TEXTURE_2D, 0);
1436     glBindTexture(GL_TEXTURE_3D, 0);
1437 }
1438 
1439 // Test glCopyTexSubImage3D with mismatched texture formats
1440 TEST_P(CopyTexImageTestES3, 3DSubImageDrawMismatchedTextureTypes)
1441 {
1442     GLFramebuffer fbo;
1443     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1444 
1445     // The 3D texture we will copy the sub-image into
1446     GLTexture texture3D;
1447     initialize3DTexture(texture3D, kImageWidth, kImageHeight, kImageDepth, nullptr);
1448 
1449     // Draw to each layer in the 3D texture
1450     for (int currLayer = 0; currLayer < kImageDepth; ++currLayer)
1451     {
1452         ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1453         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture3D, 0, currLayer);
1454         ASSERT_GL_NO_ERROR();
1455         glUseProgram(greenProgram);
1456         drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1457         ASSERT_GL_NO_ERROR();
1458         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1459     }
1460 
1461     // The 2D texture that will be the sub-image copied into the destination texture
1462     GLTexture subTexture2D;
1463     initialize2DTextureUShort4444(subTexture2D, kSubImageWidth, kSubImageHeight, nullptr);
1464     clearTexture(fbo, subTexture2D, kSubImageColor);
1465 
1466     // Copy the 2D sub-image into the 3D texture
1467     copyTexSubImage3D(subTexture2D, kXOffset, kYOffset, kSubImageWidth, kSubImageHeight,
1468                       kImageDepth);
1469 
1470     // Verify the color wasn't overwritten
1471     verifyCopyTexSubImage3D(texture3D, 0, 0, GLColor::green);
1472     // Verify the copy succeeded
1473     verifyCopyTexSubImage3D(texture3D, kXOffset, kYOffset, kSubImageColor);
1474 
1475     glBindFramebuffer(GL_FRAMEBUFFER, 0);
1476     glBindTexture(GL_TEXTURE_2D, 0);
1477     glBindTexture(GL_TEXTURE_3D, 0);
1478 }
1479 
1480 // Make sure a single-level texture can be redefined through glCopyTexImage2D from a framebuffer
1481 // bound to the same texture.  Regression test for a bug in the Vulkan backend where the texture was
1482 // released before the copy.
TEST_P(CopyTexImageTestES3,RedefineSameLevel)1483 TEST_P(CopyTexImageTestES3, RedefineSameLevel)
1484 {
1485     constexpr GLsizei kSize     = 32;
1486     constexpr GLsizei kHalfSize = kSize / 2;
1487 
1488     // Create a single-level texture with four colors in different regions.
1489     std::vector<GLColor> initData(kSize * kSize);
1490     for (GLsizei y = 0; y < kSize; ++y)
1491     {
1492         const bool isTop = y < kHalfSize;
1493         for (GLsizei x = 0; x < kSize; ++x)
1494         {
1495             const bool isLeft = x < kHalfSize;
1496 
1497             GLColor color           = isLeft && isTop    ? GLColor::red
1498                                       : isLeft && !isTop ? GLColor::green
1499                                       : !isLeft && isTop ? GLColor::blue
1500                                                          : GLColor::yellow;
1501             color.A                 = 123;
1502             initData[y * kSize + x] = color;
1503         }
1504     }
1505 
1506     GLTexture tex;
1507     glBindTexture(GL_TEXTURE_2D, tex);
1508     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1509                  initData.data());
1510 
1511     // Bind the framebuffer to the same texture
1512     GLFramebuffer framebuffer;
1513     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1514     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1515 
1516     // Redefine the texture
1517     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, kHalfSize / 2, kHalfSize / 2, kHalfSize, kHalfSize,
1518                      0);
1519 
1520     // Verify copy is done correctly.
1521     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1522 
1523     EXPECT_PIXEL_RECT_EQ(0, 0, kHalfSize / 2, kHalfSize / 2, GLColor::red);
1524     EXPECT_PIXEL_RECT_EQ(kHalfSize / 2, 0, kHalfSize / 2, kHalfSize / 2, GLColor::blue);
1525     EXPECT_PIXEL_RECT_EQ(0, kHalfSize / 2, kHalfSize / 2, kHalfSize / 2, GLColor::green);
1526     EXPECT_PIXEL_RECT_EQ(kHalfSize / 2, kHalfSize / 2, kHalfSize / 2, kHalfSize / 2,
1527                          GLColor::yellow);
1528 }
1529 
1530 class CopyTexImagePreRotationTest : public ANGLETest<>
1531 {
1532   protected:
CopyTexImagePreRotationTest()1533     CopyTexImagePreRotationTest()
1534     {
1535         // Use a non-square window to catch width/height mismatch bugs
1536         setWindowWidth(54);
1537         setWindowHeight(32);
1538         setConfigRedBits(8);
1539         setConfigGreenBits(8);
1540         setConfigBlueBits(8);
1541         setConfigAlphaBits(8);
1542     }
1543 };
1544 
1545 // Basic copy test in the presence of pre-rotation
TEST_P(CopyTexImagePreRotationTest,Basic)1546 TEST_P(CopyTexImagePreRotationTest, Basic)
1547 {
1548     glClearColor(1, 0, 1, 1);
1549     glClear(GL_COLOR_BUFFER_BIT);
1550 
1551     const int w = getWindowWidth();
1552     const int h = getWindowHeight();
1553 
1554     GLTexture texture;
1555     glBindTexture(GL_TEXTURE_2D, texture);
1556     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w, h);
1557 
1558     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, w, h);
1559 
1560     // Verify results
1561     GLFramebuffer fbo;
1562     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1563     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1564 
1565     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::magenta);
1566     ASSERT_GL_NO_ERROR();
1567 }
1568 
1569 // Copy test in the presence of pre-rotation with non-zero offsets and non-square sizes
TEST_P(CopyTexImagePreRotationTest,NonZeroNonSquare)1570 TEST_P(CopyTexImagePreRotationTest, NonZeroNonSquare)
1571 {
1572     // Draw four colors in the framebuffer
1573     ANGLE_GL_PROGRAM(checkerProgram, essl1_shaders::vs::Passthrough(),
1574                      essl1_shaders::fs::Checkered());
1575     drawQuad(checkerProgram, essl1_shaders::PositionAttrib(), 0.5f);
1576 
1577     const int w = getWindowWidth();
1578     const int h = getWindowHeight();
1579 
1580     const int texWidth  = (w + 6) * 2;
1581     const int texHeight = (h - 8) * 2;
1582 
1583     GLTexture texture;
1584     glBindTexture(GL_TEXTURE_2D, texture);
1585     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, texWidth * 2, texHeight * 2);
1586 
1587     // Copy with non-zero non-symmetric offsets to mips 0 and 1.
1588     //
1589     // The framebuffer is:
1590     //
1591     //                 54
1592     //      ____________^____________
1593     //     /                         \
1594     //     +------------+------------+\
1595     //     |            |            | |
1596     //     |    Red     |    Blue    | |
1597     //     |            |            | |
1598     //     |            |            | |
1599     //     +------------+------------+  > 32
1600     //     |            |            | |
1601     //     |   Green    |   Yellow   | |
1602     //     |            |            | |
1603     //     |            |            | |
1604     //     +------------+------------+/
1605     //
1606     // The texture's mip 0 is 120x48 and mip 1 is 60x24.
1607     //
1608     struct Copy
1609     {
1610         int mip;
1611         int texX, texY;
1612         int x, y;
1613         int width, height;
1614         GLColor expect;
1615     };
1616 
1617     // Make random copies with non-zero offsets, non-zero sizes and generally different numbers to
1618     // catch any mix up.
1619     const std::array<Copy, 4> kCopies = {{
1620         {1, 20, 13, 11, 2, 9, 13, GLColor::red},
1621         {1, 31, 17, 29, 27, 20, 5, GLColor::yellow},
1622         {0, 57, 1, 3, 22, 17, 9, GLColor::green},
1623         {0, 19, 38, 46, 4, 3, 11, GLColor::blue},
1624     }};
1625 
1626     for (size_t i = 0; i < kCopies.size(); ++i)
1627     {
1628         glCopyTexSubImage2D(GL_TEXTURE_2D, kCopies[i].mip, kCopies[i].texX, kCopies[i].texY,
1629                             kCopies[i].x, kCopies[i].y, kCopies[i].width, kCopies[i].height);
1630     }
1631 
1632     // Verify results
1633     GLFramebuffer fbo;
1634     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1635 
1636     for (int mip = 0; mip < 2; ++mip)
1637     {
1638         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, mip);
1639         for (size_t i = 0; i < kCopies.size(); ++i)
1640         {
1641             if (kCopies[i].mip == mip)
1642             {
1643                 EXPECT_PIXEL_RECT_EQ(kCopies[i].texX, kCopies[i].texY, kCopies[i].width,
1644                                      kCopies[i].height, kCopies[i].expect);
1645             }
1646         }
1647     }
1648     ASSERT_GL_NO_ERROR();
1649 }
1650 
1651 // ANGLE allows BGRA <-> RGBA copies. Test that these work and correctly swizzle the channels.
TEST_P(CopyTexImageTest,BGRAAndRGBAConversions)1652 TEST_P(CopyTexImageTest, BGRAAndRGBAConversions)
1653 {
1654     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888"));
1655     testBGRAToRGBAConversion();
1656     testRGBAToBGRAConversion();
1657 }
1658 
1659 // ANGLE allows BGRA <-> RGBA copies. Test that these work and correctly swizzle the channels.
1660 // ES3 uses different validation code for glCopyTexImage.
TEST_P(CopyTexImageTestES3,BGRAAndRGBAConversions)1661 TEST_P(CopyTexImageTestES3, BGRAAndRGBAConversions)
1662 {
1663     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888"));
1664     testBGRAToRGBAConversion();
1665     testRGBAToBGRAConversion();
1666 }
1667 
1668 ANGLE_INSTANTIATE_TEST_ES2_AND(
1669     CopyTexImageTest,
1670     ES2_D3D11_PRESENT_PATH_FAST(),
1671     ES3_VULKAN(),
1672     ES2_OPENGL().enable(Feature::EmulateCopyTexImage2D),
1673     ES2_OPENGLES().enable(Feature::EmulateCopyTexImage2D),
1674     ES2_OPENGL().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers),
1675     ES2_OPENGLES().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers));
1676 
1677 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CopyTexImageTestES3);
1678 ANGLE_INSTANTIATE_TEST_ES3_AND(
1679     CopyTexImageTestES3,
1680     ES3_OPENGL().enable(Feature::EmulateCopyTexImage2D),
1681     ES3_OPENGLES().enable(Feature::EmulateCopyTexImage2D),
1682     ES3_OPENGL().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers),
1683     ES3_OPENGLES().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers));
1684 
1685 ANGLE_INSTANTIATE_TEST_ES2_AND(
1686     CopyTexImageTestRobustResourceInit,
1687     ES2_D3D11_PRESENT_PATH_FAST(),
1688     ES3_VULKAN(),
1689     ES2_OPENGL().enable(Feature::EmulateCopyTexImage2D),
1690     ES2_OPENGLES().enable(Feature::EmulateCopyTexImage2D),
1691     ES2_OPENGL().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers),
1692     ES2_OPENGLES().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers));
1693 
1694 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CopyTexImagePreRotationTest);
1695 ANGLE_INSTANTIATE_TEST_ES3_AND(CopyTexImagePreRotationTest,
1696                                ES3_VULKAN().enable(Feature::EmulatedPrerotation90),
1697                                ES3_VULKAN().enable(Feature::EmulatedPrerotation180),
1698                                ES3_VULKAN().enable(Feature::EmulatedPrerotation270));
1699 
1700 }  // namespace angle
1701