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 "common/mathutil.h"
8 #include "test_utils/ANGLETest.h"
9 #include "test_utils/gl_raii.h"
10
11 #include <limits>
12
13 using namespace angle;
14
15 namespace
16 {
17
18 constexpr GLuint kPixelTolerance = 1u;
19 constexpr GLfloat kPixelTolerance32F = 0.01f;
20
21 // Single compressed ETC2 block of source pixels all set red
22 constexpr uint8_t kCompressedImageETC2[] = {0x7E, 0x80, 0x04, 0x7F, 0x00, 0x07, 0xE0, 0x00};
23
24 // Take a pixel, and reset the components not covered by the format to default
25 // values. In particular, the default value for the alpha component is 255
26 // (1.0 as unsigned normalized fixed point value).
27 // For legacy formats, the components may be reordered to match the color that
28 // would be created if a pixel of that format was initialized from the given color
SliceFormatColor(GLenum format,GLColor full)29 GLColor SliceFormatColor(GLenum format, GLColor full)
30 {
31 switch (format)
32 {
33 case GL_RED:
34 return GLColor(full.R, 0, 0, 255u);
35 case GL_RG:
36 return GLColor(full.R, full.G, 0, 255u);
37 case GL_RGB:
38 return GLColor(full.R, full.G, full.B, 255u);
39 case GL_RGBA:
40 return full;
41 case GL_LUMINANCE:
42 return GLColor(full.R, full.R, full.R, 255u);
43 case GL_ALPHA:
44 return GLColor(0, 0, 0, full.R);
45 case GL_LUMINANCE_ALPHA:
46 return GLColor(full.R, full.R, full.R, full.G);
47 default:
48 EXPECT_TRUE(false);
49 return GLColor::white;
50 }
51 }
52
SliceFormatColor16UI(GLenum format,GLColor16UI full)53 GLColor16UI SliceFormatColor16UI(GLenum format, GLColor16UI full)
54 {
55 switch (format)
56 {
57 case GL_RED:
58 return GLColor16UI(full.R, 0, 0, 0xFFFF);
59 case GL_RG:
60 return GLColor16UI(full.R, full.G, 0, 0xFFFF);
61 case GL_RGB:
62 return GLColor16UI(full.R, full.G, full.B, 0xFFFF);
63 case GL_RGBA:
64 return full;
65 case GL_LUMINANCE:
66 return GLColor16UI(full.R, full.R, full.R, 0xFFFF);
67 case GL_ALPHA:
68 return GLColor16UI(0, 0, 0, full.R);
69 case GL_LUMINANCE_ALPHA:
70 return GLColor16UI(full.R, full.R, full.R, full.G);
71 default:
72 EXPECT_TRUE(false);
73 return GLColor16UI(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF);
74 }
75 }
76
77 // As above, for 32F colors
SliceFormatColor32F(GLenum format,GLColor32F full)78 GLColor32F SliceFormatColor32F(GLenum format, GLColor32F full)
79 {
80 switch (format)
81 {
82 case GL_RED:
83 return GLColor32F(full.R, 0.0f, 0.0f, 1.0f);
84 case GL_RG:
85 return GLColor32F(full.R, full.G, 0.0f, 1.0f);
86 case GL_RGB:
87 return GLColor32F(full.R, full.G, full.B, 1.0f);
88 case GL_RGBA:
89 return full;
90 case GL_LUMINANCE:
91 return GLColor32F(full.R, full.R, full.R, 1.0f);
92 case GL_ALPHA:
93 return GLColor32F(0.0f, 0.0f, 0.0f, full.R);
94 case GL_LUMINANCE_ALPHA:
95 return GLColor32F(full.R, full.R, full.R, full.G);
96 default:
97 EXPECT_TRUE(false);
98 return GLColor32F(1.0f, 1.0f, 1.0f, 1.0f);
99 }
100 }
101
102 class TexCoordDrawTest : public ANGLETest<>
103 {
104 protected:
TexCoordDrawTest()105 TexCoordDrawTest() : ANGLETest(), mProgram(0), mFramebuffer(0), mFramebufferColorTexture(0)
106 {
107 setWindowWidth(128);
108 setWindowHeight(128);
109 setConfigRedBits(8);
110 setConfigGreenBits(8);
111 setConfigBlueBits(8);
112 setConfigAlphaBits(8);
113 }
114
getVertexShaderSource()115 virtual const char *getVertexShaderSource()
116 {
117 return R"(precision highp float;
118 attribute vec4 position;
119 varying vec2 texcoord;
120
121 void main()
122 {
123 gl_Position = vec4(position.xy, 0.0, 1.0);
124 texcoord = (position.xy * 0.5) + 0.5;
125 })";
126 }
127
128 virtual const char *getFragmentShaderSource() = 0;
129
setUpProgram()130 virtual void setUpProgram()
131 {
132 const char *vertexShaderSource = getVertexShaderSource();
133 const char *fragmentShaderSource = getFragmentShaderSource();
134
135 mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
136 ASSERT_NE(0u, mProgram);
137 ASSERT_GL_NO_ERROR();
138 }
139
testSetUp()140 void testSetUp() override { setUpFramebuffer(); }
141
testTearDown()142 void testTearDown() override
143 {
144 glBindFramebuffer(GL_FRAMEBUFFER, 0);
145 glDeleteFramebuffers(1, &mFramebuffer);
146 glDeleteTextures(1, &mFramebufferColorTexture);
147 glDeleteProgram(mProgram);
148 }
149
setUpFramebuffer()150 void setUpFramebuffer()
151 {
152 // We use an FBO to work around an issue where the default framebuffer applies SRGB
153 // conversion (particularly known to happen incorrectly on Intel GL drivers). It's not
154 // clear whether this issue can even be fixed on all backends. For example GLES 3.0.4 spec
155 // section 4.4 says that the format of the default framebuffer is entirely up to the window
156 // system, so it might be SRGB, and GLES 3.0 doesn't have a "FRAMEBUFFER_SRGB" to turn off
157 // SRGB conversion like desktop GL does.
158 // TODO(oetuaho): Get rid of this if the underlying issue is fixed.
159 glGenFramebuffers(1, &mFramebuffer);
160 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
161
162 glGenTextures(1, &mFramebufferColorTexture);
163 glBindTexture(GL_TEXTURE_2D, mFramebufferColorTexture);
164 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
165 GL_UNSIGNED_BYTE, nullptr);
166 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
167 mFramebufferColorTexture, 0);
168 ASSERT_GL_NO_ERROR();
169 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
170 glBindTexture(GL_TEXTURE_2D, 0);
171 }
172
173 // Returns the created texture ID.
create2DTexture()174 GLuint create2DTexture()
175 {
176 GLuint texture2D;
177 glGenTextures(1, &texture2D);
178 glBindTexture(GL_TEXTURE_2D, texture2D);
179 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
180 EXPECT_GL_NO_ERROR();
181 return texture2D;
182 }
183
184 GLuint mProgram;
185 GLuint mFramebuffer;
186
187 protected:
188 GLuint mFramebufferColorTexture;
189 };
190
191 class Texture2DTest : public TexCoordDrawTest
192 {
193 protected:
Texture2DTest()194 Texture2DTest() : TexCoordDrawTest(), mTexture2D(0), mTexture2DUniformLocation(-1) {}
195
getFragmentShaderSource()196 const char *getFragmentShaderSource() override
197 {
198 return R"(precision highp float;
199 uniform sampler2D tex;
200 varying vec2 texcoord;
201
202 void main()
203 {
204 gl_FragColor = texture2D(tex, texcoord);
205 })";
206 }
207
getTextureUniformName()208 virtual const char *getTextureUniformName() { return "tex"; }
209
setUpProgram()210 void setUpProgram() override
211 {
212 TexCoordDrawTest::setUpProgram();
213 mTexture2DUniformLocation = glGetUniformLocation(mProgram, getTextureUniformName());
214 ASSERT_NE(-1, mTexture2DUniformLocation);
215 }
216
testSetUp()217 void testSetUp() override
218 {
219 TexCoordDrawTest::testSetUp();
220 mTexture2D = create2DTexture();
221
222 ASSERT_GL_NO_ERROR();
223 }
224
testTearDown()225 void testTearDown() override
226 {
227 glDeleteTextures(1, &mTexture2D);
228 TexCoordDrawTest::testTearDown();
229 }
230
231 // Tests CopyTexSubImage with floating point textures of various formats.
testFloatCopySubImage(int sourceImageChannels,int destImageChannels)232 void testFloatCopySubImage(int sourceImageChannels, int destImageChannels)
233 {
234 setUpProgram();
235
236 if (getClientMajorVersion() < 3)
237 {
238 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage") ||
239 !IsGLExtensionEnabled("GL_OES_texture_float"));
240
241 ANGLE_SKIP_TEST_IF((sourceImageChannels < 3 || destImageChannels < 3) &&
242 !IsGLExtensionEnabled("GL_EXT_texture_rg"));
243
244 ANGLE_SKIP_TEST_IF(destImageChannels == 3 &&
245 !IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"));
246
247 ANGLE_SKIP_TEST_IF(destImageChannels == 4 &&
248 !IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"));
249
250 ANGLE_SKIP_TEST_IF(destImageChannels <= 2);
251 }
252 else
253 {
254 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_color_buffer_float"));
255
256 ANGLE_SKIP_TEST_IF(destImageChannels == 3 &&
257 !IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"));
258 }
259
260 // clang-format off
261 GLfloat sourceImageData[4][16] =
262 {
263 { // R
264 1.0f,
265 0.0f,
266 0.0f,
267 1.0f
268 },
269 { // RG
270 1.0f, 0.0f,
271 0.0f, 1.0f,
272 0.0f, 0.0f,
273 1.0f, 1.0f
274 },
275 { // RGB
276 1.0f, 0.0f, 0.0f,
277 0.0f, 1.0f, 0.0f,
278 0.0f, 0.0f, 1.0f,
279 1.0f, 1.0f, 0.0f
280 },
281 { // RGBA
282 1.0f, 0.0f, 0.0f, 1.0f,
283 0.0f, 1.0f, 0.0f, 1.0f,
284 0.0f, 0.0f, 1.0f, 1.0f,
285 1.0f, 1.0f, 0.0f, 1.0f
286 },
287 };
288 // clang-format on
289
290 GLenum imageFormats[] = {
291 GL_R32F,
292 GL_RG32F,
293 GL_RGB32F,
294 GL_RGBA32F,
295 };
296
297 GLenum sourceUnsizedFormats[] = {
298 GL_RED,
299 GL_RG,
300 GL_RGB,
301 GL_RGBA,
302 };
303
304 GLTexture textures[2];
305
306 GLfloat *imageData = sourceImageData[sourceImageChannels - 1];
307 GLenum sourceImageFormat = imageFormats[sourceImageChannels - 1];
308 GLenum sourceUnsizedFormat = sourceUnsizedFormats[sourceImageChannels - 1];
309 GLenum destImageFormat = imageFormats[destImageChannels - 1];
310
311 glBindTexture(GL_TEXTURE_2D, textures[0]);
312 if (getClientMajorVersion() >= 3)
313 {
314 glTexStorage2D(GL_TEXTURE_2D, 1, sourceImageFormat, 2, 2);
315 }
316 else
317 {
318 glTexStorage2DEXT(GL_TEXTURE_2D, 1, sourceImageFormat, 2, 2);
319 }
320 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
321 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
322 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, sourceUnsizedFormat, GL_FLOAT, imageData);
323
324 if (sourceImageChannels < 3 && !IsGLExtensionEnabled("GL_EXT_texture_rg"))
325 {
326 // This is not supported
327 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
328 }
329 else
330 {
331 ASSERT_GL_NO_ERROR();
332 }
333
334 GLuint fbo;
335 glGenFramebuffers(1, &fbo);
336 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
337 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
338
339 glBindTexture(GL_TEXTURE_2D, textures[1]);
340 if (getClientMajorVersion() >= 3)
341 {
342 glTexStorage2D(GL_TEXTURE_2D, 1, destImageFormat, 2, 2);
343 }
344 else
345 {
346 glTexStorage2DEXT(GL_TEXTURE_2D, 1, destImageFormat, 2, 2);
347 }
348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
350
351 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 2, 2);
352 ASSERT_GL_NO_ERROR();
353
354 glBindFramebuffer(GL_FRAMEBUFFER, 0);
355 drawQuad(mProgram, "position", 0.5f);
356
357 int testImageChannels = std::min(sourceImageChannels, destImageChannels);
358
359 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
360 if (testImageChannels > 1)
361 {
362 EXPECT_PIXEL_EQ(getWindowHeight() - 1, 0, 0, 255, 0, 255);
363 EXPECT_PIXEL_EQ(getWindowHeight() - 1, getWindowWidth() - 1, 255, 255, 0, 255);
364 if (testImageChannels > 2)
365 {
366 EXPECT_PIXEL_EQ(0, getWindowWidth() - 1, 0, 0, 255, 255);
367 }
368 }
369
370 glDeleteFramebuffers(1, &fbo);
371
372 ASSERT_GL_NO_ERROR();
373 }
374
375 void testTextureSize(int testCaseIndex);
376 void testTextureSizeError();
377
378 struct UploadThenUseStageParam
379 {
380 GLenum useStage;
381 bool closeRenderPassAfterUse;
382 };
383
384 void testUploadThenUseInDifferentStages(const std::vector<UploadThenUseStageParam> &uses);
385
386 GLuint mTexture2D;
387 GLint mTexture2DUniformLocation;
388 };
389
390 class Texture2DTestES3 : public Texture2DTest
391 {
392 protected:
Texture2DTestES3()393 Texture2DTestES3() : Texture2DTest() {}
394
getVertexShaderSource()395 const char *getVertexShaderSource() override
396 {
397 return "#version 300 es\n"
398 "out vec2 texcoord;\n"
399 "in vec4 position;\n"
400 "void main()\n"
401 "{\n"
402 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
403 " texcoord = (position.xy * 0.5) + 0.5;\n"
404 "}\n";
405 }
406
getFragmentShaderSource()407 const char *getFragmentShaderSource() override
408 {
409 return "#version 300 es\n"
410 "precision highp float;\n"
411 "uniform highp sampler2D tex;\n"
412 "in vec2 texcoord;\n"
413 "out vec4 fragColor;\n"
414 "void main()\n"
415 "{\n"
416 " fragColor = texture(tex, texcoord);\n"
417 "}\n";
418 }
419
testSetUp()420 void testSetUp() override
421 {
422 Texture2DTest::testSetUp();
423 setUpProgram();
424 }
425
createImmutableTexture2D(GLuint texture,size_t width,size_t height,GLenum format,GLenum internalFormat,GLenum type,GLsizei levels,GLubyte data[4])426 void createImmutableTexture2D(GLuint texture,
427 size_t width,
428 size_t height,
429 GLenum format,
430 GLenum internalFormat,
431 GLenum type,
432 GLsizei levels,
433 GLubyte data[4])
434 {
435 // Support only 1 level for now
436 ASSERT(levels == 1);
437
438 glBindTexture(GL_TEXTURE_2D, texture);
439
440 glTexStorage2D(GL_TEXTURE_2D, levels, internalFormat, width, height);
441 ASSERT_GL_NO_ERROR();
442
443 if (data != nullptr)
444 {
445 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data);
446 ASSERT_GL_NO_ERROR();
447 }
448
449 // Disable mipmapping
450 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
451 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
452 ASSERT_GL_NO_ERROR();
453 }
454
verifyResults2D(GLuint texture,GLubyte referenceColor[4])455 void verifyResults2D(GLuint texture, GLubyte referenceColor[4])
456 {
457 // Draw a quad with the target texture
458 glUseProgram(mProgram);
459 glBindTexture(GL_TEXTURE_2D, texture);
460 glUniform1i(mTexture2DUniformLocation, 0);
461
462 drawQuad(mProgram, "position", 0.5f);
463
464 // Expect that the rendered quad's color is the same as the reference color with a tolerance
465 // of 1
466 EXPECT_PIXEL_NEAR(0, 0, referenceColor[0], referenceColor[1], referenceColor[2],
467 referenceColor[3], 1);
468 }
469
470 void testCopyImage(const APIExtensionVersion usedExtension);
471 void testCopyImageDepthStencil(const APIExtensionVersion usedExtension);
472 };
473
474 class Texture2DMemoryTestES3 : public Texture2DTestES3
475 {
476 protected:
getPerfCounters()477 angle::VulkanPerfCounters getPerfCounters()
478 {
479 if (mIndexMap.empty())
480 {
481 mIndexMap = BuildCounterNameToIndexMap();
482 }
483
484 return GetPerfCounters(mIndexMap);
485 }
486
487 CounterNameToIndexMap mIndexMap;
488 };
489
490 class Texture2DTestES3YUV : public Texture2DTestES3
491 {};
492
493 class Texture2DTestES3RobustInit : public Texture2DTestES3
494 {
495 protected:
Texture2DTestES3RobustInit()496 Texture2DTestES3RobustInit() : Texture2DTestES3() { setRobustResourceInit(true); }
497 };
498
499 class Texture2DTestES3Foveation : public Texture2DTestES3
500 {
501 protected:
Texture2DTestES3Foveation()502 Texture2DTestES3Foveation() : Texture2DTestES3()
503 {
504 setWindowWidth(256);
505 setWindowHeight(256);
506 }
507 };
508
509 class Texture2DTestES31Foveation : public Texture2DTestES3Foveation
510 {};
511
512 class Texture2DBaseMaxTestES3 : public ANGLETest<>
513 {
514 protected:
515 static constexpr size_t kMip0Size = 13;
516 static constexpr uint32_t kMipCount = 4;
517
Texture2DBaseMaxTestES3()518 Texture2DBaseMaxTestES3() : ANGLETest(), mTextureLocation(0), mLodLocation(0)
519 {
520 setWindowWidth(128);
521 setWindowHeight(128);
522 setConfigRedBits(8);
523 setConfigGreenBits(8);
524 setConfigBlueBits(8);
525 setConfigAlphaBits(8);
526 }
527
getMipDataSize(size_t mip0Size,size_t mip)528 static constexpr size_t getMipDataSize(size_t mip0Size, size_t mip)
529 {
530 size_t mipSize = std::max<size_t>(1u, mip0Size >> mip);
531 return mipSize * mipSize;
532 }
533
getTotalMipDataSize(size_t mip0Size)534 static constexpr size_t getTotalMipDataSize(size_t mip0Size)
535 {
536 size_t totalCount = 0;
537 for (size_t mip = 0; mip < kMipCount; ++mip)
538 {
539 totalCount += getMipDataSize(mip0Size, mip);
540 }
541 return totalCount;
542 }
543
getMipDataOffset(size_t mip0Size,size_t mip)544 static constexpr size_t getMipDataOffset(size_t mip0Size, size_t mip)
545 {
546 // This calculates:
547 //
548 // mip == 0: 0
549 // o.w.: sum(0, mip-1) getMipDataSize(i)
550 //
551 // The above can be calculated simply as:
552 //
553 // (mip0 >> (kMipCount-1))^2 * (0x55555555 & ((1 << (2*mip)) - 1))
554 // \__________ ___________/ \_______________ ________________/
555 // \/ \/
556 // last mip size sum(0, mip-1) (4^i)
557 //
558 // But let's loop explicitly for clarity.
559 size_t offset = 0;
560 for (size_t m = 0; m < mip; ++m)
561 {
562 offset += getMipDataSize(mip0Size, m);
563 }
564 return offset;
565 }
566
567 template <typename colorType = GLColor>
fillMipData(colorType * data,size_t mip0Size,const colorType mipColors[kMipCount])568 void fillMipData(colorType *data, size_t mip0Size, const colorType mipColors[kMipCount])
569 {
570 for (size_t mip = 0; mip < kMipCount; ++mip)
571 {
572 size_t offset = getMipDataOffset(mip0Size, mip);
573 size_t size = getMipDataSize(mip0Size, mip);
574 std::fill(data + offset, data + offset + size, mipColors[mip]);
575 }
576 }
577
initTest(bool immutable)578 void initTest(bool immutable)
579 {
580 // Set up program to sample from specific lod level.
581 mProgram.makeRaster(essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
582 ASSERT(mProgram.valid());
583
584 glUseProgram(mProgram);
585
586 mTextureLocation = glGetUniformLocation(mProgram, essl3_shaders::Texture2DUniform());
587 ASSERT_NE(-1, mTextureLocation);
588
589 mLodLocation = glGetUniformLocation(mProgram, essl3_shaders::LodUniform());
590 ASSERT_NE(-1, mLodLocation);
591
592 // Set up texture with a handful of lods.
593 glActiveTexture(GL_TEXTURE0);
594 glBindTexture(GL_TEXTURE_2D, mTexture);
595
596 std::array<GLColor, getTotalMipDataSize(kMip0Size)> mipData;
597 fillMipData(mipData.data(), kMip0Size, kMipColors);
598
599 if (immutable)
600 {
601 glTexStorage2D(GL_TEXTURE_2D, kMipCount, GL_RGBA8, kMip0Size, kMip0Size);
602 for (size_t mip = 0; mip < kMipCount; ++mip)
603 {
604 glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip,
605 GL_RGBA, GL_UNSIGNED_BYTE,
606 mipData.data() + getMipDataOffset(kMip0Size, mip));
607 }
608 }
609 else
610 {
611 for (size_t mip = 0; mip < kMipCount; ++mip)
612 {
613 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, kMip0Size >> mip, kMip0Size >> mip, 0,
614 GL_RGBA, GL_UNSIGNED_BYTE,
615 mipData.data() + getMipDataOffset(kMip0Size, mip));
616 }
617 }
618
619 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
620 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
621
622 EXPECT_GL_NO_ERROR();
623 }
624
setLodUniform(uint32_t lod)625 void setLodUniform(uint32_t lod) { glUniform1f(mLodLocation, lod); }
626
627 void testPingPongBaseLevel(bool immutable);
628 void testGenerateMipmapAfterRebase(bool immutable);
629
630 GLProgram mProgram;
631 GLTexture mTexture;
632 GLint mTextureLocation;
633 GLint mLodLocation;
634
635 const GLColor kMipColors[kMipCount] = {
636 GLColor::red,
637 GLColor::green,
638 GLColor::blue,
639 GLColor::magenta,
640 };
641 };
642
643 class TextureES31PPO
644 {
645 protected:
TextureES31PPO()646 TextureES31PPO() : mVertProg(0), mFragProg(0), mPipeline(0) {}
647
get2DTexturedVertexShaderSource()648 const char *get2DTexturedVertexShaderSource()
649 {
650 return "#version 310 es\n"
651 "precision mediump float;\n"
652 "in vec2 position;\n"
653 "out vec2 texCoord;\n"
654 "void main()\n"
655 "{\n"
656 " gl_Position = vec4(position, 0, 1);\n"
657 " texCoord = position * 0.5 + vec2(0.5);\n"
658 "}";
659 }
660
get2DTexturedFragmentShaderSource()661 const char *get2DTexturedFragmentShaderSource()
662 {
663 return "#version 310 es\n"
664 "precision mediump float;\n"
665 "in vec2 texCoord;\n"
666 "uniform sampler2D tex1;\n"
667 "uniform sampler2D tex2;\n"
668 "uniform sampler2D tex3;\n"
669 "uniform sampler2D tex4;\n"
670 "out vec4 color;\n"
671 "void main()\n"
672 "{\n"
673 " color = (texture(tex1, texCoord) + texture(tex2, texCoord) \n"
674 " + texture(tex3, texCoord) + texture(tex4, texCoord)) * 0.25;\n"
675 "}";
676 }
677
bindProgramPipeline(const GLchar * vertString,const GLchar * fragString)678 void bindProgramPipeline(const GLchar *vertString, const GLchar *fragString)
679 {
680 mVertProg = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vertString);
681 ASSERT_NE(mVertProg, 0u);
682 mFragProg = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragString);
683 ASSERT_NE(mFragProg, 0u);
684
685 // Generate a program pipeline and attach the programs to their respective stages
686 glGenProgramPipelines(1, &mPipeline);
687 EXPECT_GL_NO_ERROR();
688 glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
689 EXPECT_GL_NO_ERROR();
690 glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
691 EXPECT_GL_NO_ERROR();
692 glBindProgramPipeline(mPipeline);
693 EXPECT_GL_NO_ERROR();
694 }
695
bind2DTexturedQuadProgramPipeline()696 void bind2DTexturedQuadProgramPipeline()
697 {
698 const char *vertexShaderSource = get2DTexturedVertexShaderSource();
699 const char *fragmentShaderSource = get2DTexturedFragmentShaderSource();
700
701 m2DTexturedQuadVertProg = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vertexShaderSource);
702 ASSERT_NE(m2DTexturedQuadVertProg, 0u);
703 m2DTexturedQuadFragProg =
704 glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragmentShaderSource);
705 ASSERT_NE(m2DTexturedQuadFragProg, 0u);
706
707 // Generate a program pipeline and attach the programs to their respective stages
708 glGenProgramPipelines(1, &m2DTexturedQuadPipeline);
709 EXPECT_GL_NO_ERROR();
710 glUseProgramStages(m2DTexturedQuadPipeline, GL_VERTEX_SHADER_BIT, m2DTexturedQuadVertProg);
711 EXPECT_GL_NO_ERROR();
712 glUseProgramStages(m2DTexturedQuadPipeline, GL_FRAGMENT_SHADER_BIT,
713 m2DTexturedQuadFragProg);
714 EXPECT_GL_NO_ERROR();
715 glBindProgramPipeline(m2DTexturedQuadPipeline);
716 EXPECT_GL_NO_ERROR();
717 }
718
ppoDrawQuad(std::array<Vector3,6> & quadVertices,const std::string & positionAttribName,const GLfloat positionAttribZ,const GLfloat positionAttribXYScale)719 void ppoDrawQuad(std::array<Vector3, 6> &quadVertices,
720 const std::string &positionAttribName,
721 const GLfloat positionAttribZ,
722 const GLfloat positionAttribXYScale)
723 {
724 glUseProgram(0);
725
726 for (Vector3 &vertex : quadVertices)
727 {
728 vertex.x() *= positionAttribXYScale;
729 vertex.y() *= positionAttribXYScale;
730 vertex.z() = positionAttribZ;
731 }
732
733 GLint positionLocation = glGetAttribLocation(mVertProg, positionAttribName.c_str());
734
735 glBindBuffer(GL_ARRAY_BUFFER, 0);
736 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
737 glEnableVertexAttribArray(positionLocation);
738
739 glDrawArrays(GL_TRIANGLES, 0, 6);
740
741 glDisableVertexAttribArray(positionLocation);
742 glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
743 }
744
745 GLuint mVertProg;
746 GLuint mFragProg;
747 GLuint mPipeline;
748 GLuint m2DTexturedQuadVertProg;
749 GLuint m2DTexturedQuadFragProg;
750 GLuint m2DTexturedQuadPipeline;
751 };
752
753 class Texture2DTestES31PPO : public TextureES31PPO, public Texture2DTest
754 {
755 protected:
Texture2DTestES31PPO()756 Texture2DTestES31PPO() : TextureES31PPO(), Texture2DTest() {}
757
testSetUp()758 void testSetUp() override { Texture2DTest::testSetUp(); }
759 };
760
761 class Texture2DIntegerAlpha1TestES3 : public Texture2DTest
762 {
763 protected:
Texture2DIntegerAlpha1TestES3()764 Texture2DIntegerAlpha1TestES3() : Texture2DTest() {}
765
getVertexShaderSource()766 const char *getVertexShaderSource() override
767 {
768 return "#version 300 es\n"
769 "out vec2 texcoord;\n"
770 "in vec4 position;\n"
771 "void main()\n"
772 "{\n"
773 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
774 " texcoord = (position.xy * 0.5) + 0.5;\n"
775 "}\n";
776 }
777
getFragmentShaderSource()778 const char *getFragmentShaderSource() override
779 {
780 return "#version 300 es\n"
781 "precision highp float;\n"
782 "uniform highp isampler2D tex;\n"
783 "in vec2 texcoord;\n"
784 "out vec4 fragColor;\n"
785 "void main()\n"
786 "{\n"
787 " vec4 green = vec4(0, 1, 0, 1);\n"
788 " vec4 black = vec4(0, 0, 0, 0);\n"
789 " fragColor = (texture(tex, texcoord).a == 1) ? green : black;\n"
790 "}\n";
791 }
792
testSetUp()793 void testSetUp() override
794 {
795 Texture2DTest::testSetUp();
796 setUpProgram();
797 }
798 };
799
800 class Texture2DUnsignedIntegerAlpha1TestES3 : public Texture2DTest
801 {
802 protected:
Texture2DUnsignedIntegerAlpha1TestES3()803 Texture2DUnsignedIntegerAlpha1TestES3() : Texture2DTest() {}
804
getVertexShaderSource()805 const char *getVertexShaderSource() override
806 {
807 return "#version 300 es\n"
808 "out vec2 texcoord;\n"
809 "in vec4 position;\n"
810 "void main()\n"
811 "{\n"
812 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
813 " texcoord = (position.xy * 0.5) + 0.5;\n"
814 "}\n";
815 }
816
getFragmentShaderSource()817 const char *getFragmentShaderSource() override
818 {
819 return "#version 300 es\n"
820 "precision highp float;\n"
821 "uniform highp usampler2D tex;\n"
822 "in vec2 texcoord;\n"
823 "out vec4 fragColor;\n"
824 "void main()\n"
825 "{\n"
826 " vec4 green = vec4(0, 1, 0, 1);\n"
827 " vec4 black = vec4(0, 0, 0, 0);\n"
828 " fragColor = (texture(tex, texcoord).a == 1u) ? green : black;\n"
829 "}\n";
830 }
831
testSetUp()832 void testSetUp() override
833 {
834 Texture2DTest::testSetUp();
835 setUpProgram();
836 }
837 };
838
839 class Texture2DTestWithDrawScale : public Texture2DTest
840 {
841 protected:
Texture2DTestWithDrawScale()842 Texture2DTestWithDrawScale() : Texture2DTest(), mDrawScaleUniformLocation(-1) {}
843
getVertexShaderSource()844 const char *getVertexShaderSource() override
845 {
846 return
847 R"(precision highp float;
848 attribute vec4 position;
849 varying vec2 texcoord;
850
851 uniform vec2 drawScale;
852
853 void main()
854 {
855 gl_Position = vec4(position.xy * drawScale, 0.0, 1.0);
856 texcoord = (position.xy * 0.5) + 0.5;
857 })";
858 }
859
testSetUp()860 void testSetUp() override
861 {
862 Texture2DTest::testSetUp();
863
864 setUpProgram();
865
866 mDrawScaleUniformLocation = glGetUniformLocation(mProgram, "drawScale");
867 ASSERT_NE(-1, mDrawScaleUniformLocation);
868
869 glUseProgram(mProgram);
870 glUniform2f(mDrawScaleUniformLocation, 1.0f, 1.0f);
871 glUseProgram(0);
872 ASSERT_GL_NO_ERROR();
873 }
874
875 GLint mDrawScaleUniformLocation;
876 };
877
878 class Sampler2DAsFunctionParameterTest : public Texture2DTest
879 {
880 protected:
Sampler2DAsFunctionParameterTest()881 Sampler2DAsFunctionParameterTest() : Texture2DTest() {}
882
getFragmentShaderSource()883 const char *getFragmentShaderSource() override
884 {
885 return
886 R"(precision highp float;
887 uniform sampler2D tex;
888 varying vec2 texcoord;
889
890 vec4 computeFragColor(sampler2D aTex)
891 {
892 return texture2D(aTex, texcoord);
893 }
894
895 void main()
896 {
897 gl_FragColor = computeFragColor(tex);
898 })";
899 }
900
testSetUp()901 void testSetUp() override
902 {
903 Texture2DTest::testSetUp();
904 setUpProgram();
905 }
906 };
907
908 class TextureCubeTest : public TexCoordDrawTest
909 {
910 protected:
TextureCubeTest()911 TextureCubeTest()
912 : TexCoordDrawTest(),
913 mTexture2D(0),
914 mTextureCube(0),
915 mTexture2DUniformLocation(-1),
916 mTextureCubeUniformLocation(-1)
917 {}
918
getFragmentShaderSource()919 const char *getFragmentShaderSource() override
920 {
921 return
922 R"(precision highp float;
923 uniform sampler2D tex2D;
924 uniform samplerCube texCube;
925 uniform int cubeFace;
926 varying vec2 texcoord;
927
928 void main()
929 {
930 gl_FragColor = texture2D(tex2D, texcoord);
931
932 vec2 scaled = vec2(1) - vec2(2) * texcoord.xy;
933 vec3 cubecoord = vec3(1, scaled.xy);
934 if (cubeFace == 1)
935 cubecoord = vec3(-1, scaled.xy);
936 else if (cubeFace == 2)
937 cubecoord = vec3(scaled.x, 1, scaled.y);
938 else if (cubeFace == 3)
939 cubecoord = vec3(scaled.x, -1, scaled.y);
940 else if (cubeFace == 4)
941 cubecoord = vec3(scaled.xy, 1);
942 else if (cubeFace == 5)
943 cubecoord = vec3(scaled.xy, -1);
944
945 gl_FragColor += textureCube(texCube, cubecoord);
946 })";
947 }
948
testSetUp()949 void testSetUp() override
950 {
951 TexCoordDrawTest::testSetUp();
952
953 glGenTextures(1, &mTextureCube);
954 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
955 for (GLenum face = 0; face < 6; face++)
956 {
957 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
958 GL_UNSIGNED_BYTE, nullptr);
959 }
960 EXPECT_GL_NO_ERROR();
961
962 mTexture2D = create2DTexture();
963
964 setUpProgram();
965
966 mTexture2DUniformLocation = glGetUniformLocation(mProgram, "tex2D");
967 ASSERT_NE(-1, mTexture2DUniformLocation);
968 mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
969 ASSERT_NE(-1, mTextureCubeUniformLocation);
970 mTextureCubeFaceUniformLocation = glGetUniformLocation(mProgram, "cubeFace");
971 ASSERT_NE(-1, mTextureCubeFaceUniformLocation);
972 }
973
testTearDown()974 void testTearDown() override
975 {
976 glDeleteTextures(1, &mTextureCube);
977 TexCoordDrawTest::testTearDown();
978 }
979
980 GLuint mTexture2D;
981 GLuint mTextureCube;
982 GLint mTexture2DUniformLocation;
983 GLint mTextureCubeUniformLocation;
984 GLint mTextureCubeFaceUniformLocation;
985 };
986
987 class TextureCubeTestES3 : public TextureCubeTest
988 {
989 protected:
TextureCubeTestES3()990 TextureCubeTestES3() {}
991 };
992
993 class SamplerArrayTest : public TexCoordDrawTest
994 {
995 protected:
SamplerArrayTest()996 SamplerArrayTest()
997 : TexCoordDrawTest(),
998 mTexture2DA(0),
999 mTexture2DB(0),
1000 mTexture0UniformLocation(-1),
1001 mTexture1UniformLocation(-1)
1002 {}
1003
getFragmentShaderSource()1004 const char *getFragmentShaderSource() override
1005 {
1006 return
1007 R"(precision mediump float;
1008 uniform highp sampler2D tex2DArray[2];
1009 varying vec2 texcoord;
1010 void main()
1011 {
1012 gl_FragColor = texture2D(tex2DArray[0], texcoord);
1013 gl_FragColor += texture2D(tex2DArray[1], texcoord);
1014 })";
1015 }
1016
testSetUp()1017 void testSetUp() override
1018 {
1019 TexCoordDrawTest::testSetUp();
1020
1021 setUpProgram();
1022
1023 mTexture0UniformLocation = glGetUniformLocation(mProgram, "tex2DArray[0]");
1024 ASSERT_NE(-1, mTexture0UniformLocation);
1025 mTexture1UniformLocation = glGetUniformLocation(mProgram, "tex2DArray[1]");
1026 ASSERT_NE(-1, mTexture1UniformLocation);
1027
1028 mTexture2DA = create2DTexture();
1029 mTexture2DB = create2DTexture();
1030 ASSERT_GL_NO_ERROR();
1031 }
1032
testTearDown()1033 void testTearDown() override
1034 {
1035 glDeleteTextures(1, &mTexture2DA);
1036 glDeleteTextures(1, &mTexture2DB);
1037 TexCoordDrawTest::testTearDown();
1038 }
1039
testSamplerArrayDraw()1040 void testSamplerArrayDraw()
1041 {
1042 GLubyte texData[4];
1043 texData[0] = 0;
1044 texData[1] = 60;
1045 texData[2] = 0;
1046 texData[3] = 255;
1047
1048 glActiveTexture(GL_TEXTURE0);
1049 glBindTexture(GL_TEXTURE_2D, mTexture2DA);
1050 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
1051
1052 texData[1] = 120;
1053 glActiveTexture(GL_TEXTURE1);
1054 glBindTexture(GL_TEXTURE_2D, mTexture2DB);
1055 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
1056 EXPECT_GL_ERROR(GL_NO_ERROR);
1057
1058 glUseProgram(mProgram);
1059 glUniform1i(mTexture0UniformLocation, 0);
1060 glUniform1i(mTexture1UniformLocation, 1);
1061 drawQuad(mProgram, "position", 0.5f);
1062 EXPECT_GL_NO_ERROR();
1063
1064 EXPECT_PIXEL_NEAR(0, 0, 0, 180, 0, 255, 2);
1065 }
1066
1067 GLuint mTexture2DA;
1068 GLuint mTexture2DB;
1069 GLint mTexture0UniformLocation;
1070 GLint mTexture1UniformLocation;
1071 };
1072
1073 class SamplerArrayAsFunctionParameterTest : public SamplerArrayTest
1074 {
1075 protected:
SamplerArrayAsFunctionParameterTest()1076 SamplerArrayAsFunctionParameterTest() : SamplerArrayTest() {}
1077
getFragmentShaderSource()1078 const char *getFragmentShaderSource() override
1079 {
1080 return
1081 R"(precision mediump float;
1082 uniform highp sampler2D tex2DArray[2];
1083 varying vec2 texcoord;
1084
1085 vec4 computeFragColor(highp sampler2D aTex2DArray[2])
1086 {
1087 return texture2D(aTex2DArray[0], texcoord) + texture2D(aTex2DArray[1], texcoord);
1088 }
1089
1090 void main()
1091 {
1092 gl_FragColor = computeFragColor(tex2DArray);
1093 })";
1094 }
1095 };
1096
1097 class Texture2DArrayTestES3 : public TexCoordDrawTest
1098 {
1099 protected:
Texture2DArrayTestES3()1100 Texture2DArrayTestES3()
1101 : TexCoordDrawTest(),
1102 m2DArrayTexture(0),
1103 mTextureArrayLocation(-1),
1104 mTextureArraySliceUniformLocation(-1)
1105 {}
1106
getVertexShaderSource()1107 const char *getVertexShaderSource() override
1108 {
1109 return R"(#version 300 es
1110 out vec2 texcoord;
1111 in vec4 position;
1112 void main()
1113 {
1114 gl_Position = vec4(position.xy, 0.0, 1.0);
1115 texcoord = (position.xy * 0.5) + 0.5;
1116 })";
1117 }
1118
getFragmentShaderSource()1119 const char *getFragmentShaderSource() override
1120 {
1121 return R"(#version 300 es
1122 precision highp float;
1123 uniform highp sampler2DArray tex2DArray;
1124 uniform int slice;
1125 in vec2 texcoord;
1126 out vec4 fragColor;
1127 void main()
1128 {
1129 fragColor = texture(tex2DArray, vec3(texcoord, float(slice)));
1130 })";
1131 }
1132
testSetUp()1133 void testSetUp() override
1134 {
1135 TexCoordDrawTest::testSetUp();
1136
1137 setUpProgram();
1138
1139 mTextureArrayLocation = glGetUniformLocation(mProgram, "tex2DArray");
1140 ASSERT_NE(-1, mTextureArrayLocation);
1141
1142 mTextureArraySliceUniformLocation = glGetUniformLocation(mProgram, "slice");
1143 ASSERT_NE(-1, mTextureArraySliceUniformLocation);
1144
1145 glGenTextures(1, &m2DArrayTexture);
1146 ASSERT_GL_NO_ERROR();
1147 }
1148
testTearDown()1149 void testTearDown() override
1150 {
1151 glDeleteTextures(1, &m2DArrayTexture);
1152 TexCoordDrawTest::testTearDown();
1153 }
1154
1155 GLuint m2DArrayTexture;
1156 GLint mTextureArrayLocation;
1157 GLint mTextureArraySliceUniformLocation;
1158 };
1159
1160 class TextureSizeTextureArrayTest : public TexCoordDrawTest
1161 {
1162 protected:
TextureSizeTextureArrayTest()1163 TextureSizeTextureArrayTest()
1164 : TexCoordDrawTest(),
1165 mTexture2DA(0),
1166 mTexture2DB(0),
1167 mTexture0Location(-1),
1168 mTexture1Location(-1)
1169 {}
1170
getVertexShaderSource()1171 const char *getVertexShaderSource() override { return essl3_shaders::vs::Simple(); }
1172
getFragmentShaderSource()1173 const char *getFragmentShaderSource() override
1174 {
1175 return "#version 300 es\n"
1176 "precision highp float;\n"
1177 "uniform highp sampler2D tex2DArray[2];\n"
1178 "out vec4 fragColor;\n"
1179 "void main()\n"
1180 "{\n"
1181 " float red = float(textureSize(tex2DArray[0], 0).x) / 255.0;\n"
1182 " float green = float(textureSize(tex2DArray[1], 0).x) / 255.0;\n"
1183 " fragColor = vec4(red, green, 0.0, 1.0);\n"
1184 "}\n";
1185 }
1186
testSetUp()1187 void testSetUp() override
1188 {
1189 TexCoordDrawTest::testSetUp();
1190
1191 setUpProgram();
1192
1193 mTexture0Location = glGetUniformLocation(mProgram, "tex2DArray[0]");
1194 ASSERT_NE(-1, mTexture0Location);
1195 mTexture1Location = glGetUniformLocation(mProgram, "tex2DArray[1]");
1196 ASSERT_NE(-1, mTexture1Location);
1197
1198 mTexture2DA = create2DTexture();
1199 mTexture2DB = create2DTexture();
1200 ASSERT_GL_NO_ERROR();
1201 }
1202
testTearDown()1203 void testTearDown() override
1204 {
1205 glDeleteTextures(1, &mTexture2DA);
1206 glDeleteTextures(1, &mTexture2DB);
1207 TexCoordDrawTest::testTearDown();
1208 }
1209
1210 GLuint mTexture2DA;
1211 GLuint mTexture2DB;
1212 GLint mTexture0Location;
1213 GLint mTexture1Location;
1214 };
1215
1216 // Test for GL_OES_texture_3D extension
1217 class Texture3DTestES2 : public TexCoordDrawTest
1218 {
1219 protected:
Texture3DTestES2()1220 Texture3DTestES2() : TexCoordDrawTest(), mTexture3D(0), mTexture3DUniformLocation(-1) {}
1221
getVertexShaderSource()1222 const char *getVertexShaderSource() override
1223 {
1224 return "#version 100\n"
1225 "varying vec2 texcoord;\n"
1226 "attribute vec4 position;\n"
1227 "void main()\n"
1228 "{\n"
1229 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1230 " texcoord = (position.xy * 0.5) + 0.5;\n"
1231 "}\n";
1232 }
1233
getFragmentShaderSource()1234 const char *getFragmentShaderSource() override
1235 {
1236 if (!hasTexture3DExt())
1237 {
1238 return "#version 100\n"
1239 "precision highp float;\n"
1240 "varying vec2 texcoord;\n"
1241 "void main()\n"
1242 "{\n"
1243 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
1244 "}\n";
1245 }
1246 return "#version 100\n"
1247 "#extension GL_OES_texture_3D : enable\n"
1248 "precision highp float;\n"
1249 "uniform highp sampler3D tex3D;\n"
1250 "uniform highp float level;\n"
1251 "varying vec2 texcoord;\n"
1252 "void main()\n"
1253 "{\n"
1254 " gl_FragColor = texture3DLod(tex3D, vec3(texcoord, 0.0), level);\n"
1255 "}\n";
1256 }
1257
testSetUp()1258 void testSetUp() override
1259 {
1260 // http://anglebug.com/5728
1261 ANGLE_SKIP_TEST_IF(IsOzone());
1262
1263 TexCoordDrawTest::testSetUp();
1264
1265 glGenTextures(1, &mTexture3D);
1266
1267 setUpProgram();
1268
1269 mTexture3DUniformLocation = glGetUniformLocation(mProgram, "tex3D");
1270 if (hasTexture3DExt())
1271 {
1272 ASSERT_NE(-1, mTexture3DUniformLocation);
1273 }
1274 }
1275
testTearDown()1276 void testTearDown() override
1277 {
1278 glDeleteTextures(1, &mTexture3D);
1279 TexCoordDrawTest::testTearDown();
1280 }
1281
hasTexture3DExt() const1282 bool hasTexture3DExt() const
1283 {
1284 // http://anglebug.com/4927
1285 if ((IsPixel2() || IsNexus5X()) && IsOpenGLES())
1286 {
1287 return false;
1288 }
1289 return IsGLExtensionEnabled("GL_OES_texture_3D");
1290 }
1291
1292 GLuint mTexture3D;
1293 GLint mTexture3DUniformLocation;
1294 };
1295
1296 class Texture3DTestES3 : public Texture3DTestES2
1297 {
1298 protected:
Texture3DTestES3()1299 Texture3DTestES3() : Texture3DTestES2() {}
1300
getVertexShaderSource()1301 const char *getVertexShaderSource() override
1302 {
1303 return "#version 300 es\n"
1304 "out vec2 texcoord;\n"
1305 "in vec4 position;\n"
1306 "void main()\n"
1307 "{\n"
1308 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1309 " texcoord = (position.xy * 0.5) + 0.5;\n"
1310 "}\n";
1311 }
1312
getFragmentShaderSource()1313 const char *getFragmentShaderSource() override
1314 {
1315 return "#version 300 es\n"
1316 "precision highp float;\n"
1317 "uniform highp sampler3D tex3D;\n"
1318 "in vec2 texcoord;\n"
1319 "out vec4 fragColor;\n"
1320 "void main()\n"
1321 "{\n"
1322 " fragColor = texture(tex3D, vec3(texcoord, 0.0));\n"
1323 "}\n";
1324 }
1325 };
1326
1327 class ShadowSamplerPlusSampler3DTestES3 : public TexCoordDrawTest
1328 {
1329 protected:
ShadowSamplerPlusSampler3DTestES3()1330 ShadowSamplerPlusSampler3DTestES3()
1331 : TexCoordDrawTest(),
1332 mTextureShadow(0),
1333 mTexture3D(0),
1334 mTextureShadowUniformLocation(-1),
1335 mTexture3DUniformLocation(-1),
1336 mDepthRefUniformLocation(-1)
1337 {}
1338
getVertexShaderSource()1339 const char *getVertexShaderSource() override
1340 {
1341 return "#version 300 es\n"
1342 "out vec2 texcoord;\n"
1343 "in vec4 position;\n"
1344 "void main()\n"
1345 "{\n"
1346 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1347 " texcoord = (position.xy * 0.5) + 0.5;\n"
1348 "}\n";
1349 }
1350
getFragmentShaderSource()1351 const char *getFragmentShaderSource() override
1352 {
1353 return "#version 300 es\n"
1354 "precision highp float;\n"
1355 "uniform highp sampler2DShadow tex2DShadow;\n"
1356 "uniform highp sampler3D tex3D;\n"
1357 "in vec2 texcoord;\n"
1358 "uniform float depthRef;\n"
1359 "out vec4 fragColor;\n"
1360 "void main()\n"
1361 "{\n"
1362 " fragColor = vec4(texture(tex2DShadow, vec3(texcoord, depthRef)) * 0.5);\n"
1363 " fragColor += texture(tex3D, vec3(texcoord, 0.0));\n"
1364 "}\n";
1365 }
1366
testSetUp()1367 void testSetUp() override
1368 {
1369 TexCoordDrawTest::testSetUp();
1370
1371 glGenTextures(1, &mTexture3D);
1372
1373 glGenTextures(1, &mTextureShadow);
1374 glBindTexture(GL_TEXTURE_2D, mTextureShadow);
1375 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1376
1377 setUpProgram();
1378
1379 mTextureShadowUniformLocation = glGetUniformLocation(mProgram, "tex2DShadow");
1380 ASSERT_NE(-1, mTextureShadowUniformLocation);
1381 mTexture3DUniformLocation = glGetUniformLocation(mProgram, "tex3D");
1382 ASSERT_NE(-1, mTexture3DUniformLocation);
1383 mDepthRefUniformLocation = glGetUniformLocation(mProgram, "depthRef");
1384 ASSERT_NE(-1, mDepthRefUniformLocation);
1385 }
1386
testTearDown()1387 void testTearDown() override
1388 {
1389 glDeleteTextures(1, &mTextureShadow);
1390 glDeleteTextures(1, &mTexture3D);
1391 TexCoordDrawTest::testTearDown();
1392 }
1393
1394 GLuint mTextureShadow;
1395 GLuint mTexture3D;
1396 GLint mTextureShadowUniformLocation;
1397 GLint mTexture3DUniformLocation;
1398 GLint mDepthRefUniformLocation;
1399 };
1400
1401 class SamplerTypeMixTestES3 : public TexCoordDrawTest
1402 {
1403 protected:
SamplerTypeMixTestES3()1404 SamplerTypeMixTestES3()
1405 : TexCoordDrawTest(),
1406 mTexture2D(0),
1407 mTextureCube(0),
1408 mTexture2DShadow(0),
1409 mTextureCubeShadow(0),
1410 mTexture2DUniformLocation(-1),
1411 mTextureCubeUniformLocation(-1),
1412 mTexture2DShadowUniformLocation(-1),
1413 mTextureCubeShadowUniformLocation(-1),
1414 mDepthRefUniformLocation(-1)
1415 {}
1416
getVertexShaderSource()1417 const char *getVertexShaderSource() override
1418 {
1419 return "#version 300 es\n"
1420 "out vec2 texcoord;\n"
1421 "in vec4 position;\n"
1422 "void main()\n"
1423 "{\n"
1424 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1425 " texcoord = (position.xy * 0.5) + 0.5;\n"
1426 "}\n";
1427 }
1428
getFragmentShaderSource()1429 const char *getFragmentShaderSource() override
1430 {
1431 return "#version 300 es\n"
1432 "precision highp float;\n"
1433 "uniform highp sampler2D tex2D;\n"
1434 "uniform highp samplerCube texCube;\n"
1435 "uniform highp sampler2DShadow tex2DShadow;\n"
1436 "uniform highp samplerCubeShadow texCubeShadow;\n"
1437 "in vec2 texcoord;\n"
1438 "uniform float depthRef;\n"
1439 "out vec4 fragColor;\n"
1440 "void main()\n"
1441 "{\n"
1442 " fragColor = texture(tex2D, texcoord);\n"
1443 " fragColor += texture(texCube, vec3(1.0, 0.0, 0.0));\n"
1444 " fragColor += vec4(texture(tex2DShadow, vec3(texcoord, depthRef)) * 0.25);\n"
1445 " fragColor += vec4(texture(texCubeShadow, vec4(1.0, 0.0, 0.0, depthRef)) * "
1446 "0.125);\n"
1447 "}\n";
1448 }
1449
testSetUp()1450 void testSetUp() override
1451 {
1452 TexCoordDrawTest::testSetUp();
1453
1454 glGenTextures(1, &mTexture2D);
1455 glGenTextures(1, &mTextureCube);
1456
1457 glGenTextures(1, &mTexture2DShadow);
1458 glBindTexture(GL_TEXTURE_2D, mTexture2DShadow);
1459 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1460
1461 glGenTextures(1, &mTextureCubeShadow);
1462 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow);
1463 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1464
1465 setUpProgram();
1466
1467 mTexture2DUniformLocation = glGetUniformLocation(mProgram, "tex2D");
1468 ASSERT_NE(-1, mTexture2DUniformLocation);
1469 mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
1470 ASSERT_NE(-1, mTextureCubeUniformLocation);
1471 mTexture2DShadowUniformLocation = glGetUniformLocation(mProgram, "tex2DShadow");
1472 ASSERT_NE(-1, mTexture2DShadowUniformLocation);
1473 mTextureCubeShadowUniformLocation = glGetUniformLocation(mProgram, "texCubeShadow");
1474 ASSERT_NE(-1, mTextureCubeShadowUniformLocation);
1475 mDepthRefUniformLocation = glGetUniformLocation(mProgram, "depthRef");
1476 ASSERT_NE(-1, mDepthRefUniformLocation);
1477
1478 ASSERT_GL_NO_ERROR();
1479 }
1480
testTearDown()1481 void testTearDown() override
1482 {
1483 glDeleteTextures(1, &mTexture2D);
1484 glDeleteTextures(1, &mTextureCube);
1485 glDeleteTextures(1, &mTexture2DShadow);
1486 glDeleteTextures(1, &mTextureCubeShadow);
1487 TexCoordDrawTest::testTearDown();
1488 }
1489
1490 GLuint mTexture2D;
1491 GLuint mTextureCube;
1492 GLuint mTexture2DShadow;
1493 GLuint mTextureCubeShadow;
1494 GLint mTexture2DUniformLocation;
1495 GLint mTextureCubeUniformLocation;
1496 GLint mTexture2DShadowUniformLocation;
1497 GLint mTextureCubeShadowUniformLocation;
1498 GLint mDepthRefUniformLocation;
1499 };
1500
1501 class SamplerInStructTest : public Texture2DTest
1502 {
1503 protected:
SamplerInStructTest()1504 SamplerInStructTest() : Texture2DTest() {}
1505
getTextureUniformName()1506 const char *getTextureUniformName() override { return "us.tex"; }
1507
getFragmentShaderSource()1508 const char *getFragmentShaderSource() override
1509 {
1510 return "precision highp float;\n"
1511 "struct S\n"
1512 "{\n"
1513 " vec4 a;\n"
1514 " highp sampler2D tex;\n"
1515 "};\n"
1516 "uniform S us;\n"
1517 "varying vec2 texcoord;\n"
1518 "void main()\n"
1519 "{\n"
1520 " gl_FragColor = texture2D(us.tex, texcoord + us.a.x);\n"
1521 "}\n";
1522 }
1523
runSamplerInStructTest()1524 void runSamplerInStructTest()
1525 {
1526 setUpProgram();
1527
1528 glActiveTexture(GL_TEXTURE0);
1529 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1530 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1531 &GLColor::green);
1532 drawQuad(mProgram, "position", 0.5f);
1533 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1534 }
1535 };
1536
1537 class SamplerInStructAsFunctionParameterTest : public SamplerInStructTest
1538 {
1539 protected:
SamplerInStructAsFunctionParameterTest()1540 SamplerInStructAsFunctionParameterTest() : SamplerInStructTest() {}
1541
getFragmentShaderSource()1542 const char *getFragmentShaderSource() override
1543 {
1544 return "precision highp float;\n"
1545 "struct S\n"
1546 "{\n"
1547 " vec4 a;\n"
1548 " highp sampler2D tex;\n"
1549 "};\n"
1550 "uniform S us;\n"
1551 "varying vec2 texcoord;\n"
1552 "vec4 sampleFrom(S s) {\n"
1553 " return texture2D(s.tex, texcoord + s.a.x);\n"
1554 "}\n"
1555 "void main()\n"
1556 "{\n"
1557 " gl_FragColor = sampleFrom(us);\n"
1558 "}\n";
1559 }
1560 };
1561
1562 class SamplerInStructArrayAsFunctionParameterTest : public SamplerInStructTest
1563 {
1564 protected:
SamplerInStructArrayAsFunctionParameterTest()1565 SamplerInStructArrayAsFunctionParameterTest() : SamplerInStructTest() {}
1566
getTextureUniformName()1567 const char *getTextureUniformName() override { return "us[0].tex"; }
1568
getFragmentShaderSource()1569 const char *getFragmentShaderSource() override
1570 {
1571 return "precision highp float;\n"
1572 "struct S\n"
1573 "{\n"
1574 " vec4 a;\n"
1575 " highp sampler2D tex;\n"
1576 "};\n"
1577 "uniform S us[1];\n"
1578 "varying vec2 texcoord;\n"
1579 "vec4 sampleFrom(S s) {\n"
1580 " return texture2D(s.tex, texcoord + s.a.x);\n"
1581 "}\n"
1582 "void main()\n"
1583 "{\n"
1584 " gl_FragColor = sampleFrom(us[0]);\n"
1585 "}\n";
1586 }
1587 };
1588
1589 class SamplerInNestedStructAsFunctionParameterTest : public SamplerInStructTest
1590 {
1591 protected:
SamplerInNestedStructAsFunctionParameterTest()1592 SamplerInNestedStructAsFunctionParameterTest() : SamplerInStructTest() {}
1593
getTextureUniformName()1594 const char *getTextureUniformName() override { return "us[0].sub.tex"; }
1595
getFragmentShaderSource()1596 const char *getFragmentShaderSource() override
1597 {
1598 return "precision highp float;\n"
1599 "struct SUB\n"
1600 "{\n"
1601 " vec4 a;\n"
1602 " highp sampler2D tex;\n"
1603 "};\n"
1604 "struct S\n"
1605 "{\n"
1606 " SUB sub;\n"
1607 "};\n"
1608 "uniform S us[1];\n"
1609 "varying vec2 texcoord;\n"
1610 "vec4 sampleFrom(SUB s) {\n"
1611 " return texture2D(s.tex, texcoord + s.a.x);\n"
1612 "}\n"
1613 "void main()\n"
1614 "{\n"
1615 " gl_FragColor = sampleFrom(us[0].sub);\n"
1616 "}\n";
1617 }
1618 };
1619
1620 class SamplerInStructAndOtherVariableTest : public SamplerInStructTest
1621 {
1622 protected:
SamplerInStructAndOtherVariableTest()1623 SamplerInStructAndOtherVariableTest() : SamplerInStructTest() {}
1624
getFragmentShaderSource()1625 const char *getFragmentShaderSource() override
1626 {
1627 return "precision highp float;\n"
1628 "struct S\n"
1629 "{\n"
1630 " vec4 a;\n"
1631 " highp sampler2D tex;\n"
1632 "};\n"
1633 "uniform S us;\n"
1634 "uniform float us_tex;\n"
1635 "varying vec2 texcoord;\n"
1636 "void main()\n"
1637 "{\n"
1638 " gl_FragColor = texture2D(us.tex, texcoord + us.a.x + us_tex);\n"
1639 "}\n";
1640 }
1641 };
1642
1643 class Texture2DIntegerTestES3 : public Texture2DTest
1644 {
1645 protected:
Texture2DIntegerTestES3()1646 Texture2DIntegerTestES3() : Texture2DTest() {}
1647
getVertexShaderSource()1648 const char *getVertexShaderSource() override
1649 {
1650 return "#version 300 es\n"
1651 "out vec2 texcoord;\n"
1652 "in vec4 position;\n"
1653 "void main()\n"
1654 "{\n"
1655 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1656 " texcoord = (position.xy * 0.5) + 0.5;\n"
1657 "}\n";
1658 }
1659
getFragmentShaderSource()1660 const char *getFragmentShaderSource() override
1661 {
1662 return "#version 300 es\n"
1663 "precision highp float;\n"
1664 "precision highp usampler2D;\n"
1665 "uniform usampler2D tex;\n"
1666 "in vec2 texcoord;\n"
1667 "out vec4 fragColor;\n"
1668 "void main()\n"
1669 "{\n"
1670 " fragColor = vec4(texture(tex, texcoord))/255.0;\n"
1671 "}\n";
1672 }
1673 };
1674
1675 class TextureCubeIntegerTestES3 : public TexCoordDrawTest
1676 {
1677 protected:
TextureCubeIntegerTestES3()1678 TextureCubeIntegerTestES3()
1679 : TexCoordDrawTest(), mTextureCube(0), mTextureCubeUniformLocation(-1)
1680 {}
1681
getVertexShaderSource()1682 const char *getVertexShaderSource() override
1683 {
1684 return "#version 300 es\n"
1685 "out vec2 texcoord;\n"
1686 "in vec4 position;\n"
1687 "void main()\n"
1688 "{\n"
1689 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1690 " texcoord = 0.5*position.xy;\n"
1691 "}\n";
1692 }
1693
getFragmentShaderSource()1694 const char *getFragmentShaderSource() override
1695 {
1696 return "#version 300 es\n"
1697 "precision highp float;\n"
1698 "precision highp usamplerCube;\n"
1699 "uniform usamplerCube texCube;\n"
1700 "in vec2 texcoord;\n"
1701 "out vec4 fragColor;\n"
1702 "void main()\n"
1703 "{\n"
1704 " fragColor = vec4(texture(texCube, vec3(texcoord, 1)))/255.0;\n"
1705 "}\n";
1706 }
1707
testSetUp()1708 void testSetUp() override
1709 {
1710 TexCoordDrawTest::testSetUp();
1711 glGenTextures(1, &mTextureCube);
1712 setUpProgram();
1713
1714 mTextureCubeUniformLocation = glGetUniformLocation(mProgram, "texCube");
1715 ASSERT_NE(-1, mTextureCubeUniformLocation);
1716 }
1717
testTearDown()1718 void testTearDown() override
1719 {
1720 glDeleteTextures(1, &mTextureCube);
1721 TexCoordDrawTest::testTearDown();
1722 }
1723
1724 GLuint mTextureCube;
1725 GLint mTextureCubeUniformLocation;
1726 };
1727
1728 class TextureCubeIntegerEdgeTestES3 : public TextureCubeIntegerTestES3
1729 {
1730 protected:
TextureCubeIntegerEdgeTestES3()1731 TextureCubeIntegerEdgeTestES3() : TextureCubeIntegerTestES3() {}
1732
getVertexShaderSource()1733 const char *getVertexShaderSource() override
1734 {
1735 return "#version 300 es\n"
1736 "out vec2 texcoord;\n"
1737 "in vec4 position;\n"
1738 "void main()\n"
1739 "{\n"
1740 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1741 " texcoord = position.xy;\n"
1742 "}\n";
1743 }
1744
getFragmentShaderSource()1745 const char *getFragmentShaderSource() override
1746 {
1747 return "#version 300 es\n"
1748 "precision highp float;\n"
1749 "precision highp usamplerCube;\n"
1750 "uniform usamplerCube texCube;\n"
1751 "in vec2 texcoord;\n"
1752 "out vec4 fragColor;\n"
1753 "void main()\n"
1754 "{\n"
1755 " fragColor = vec4(texture(texCube, vec3(texcoord, 0)))/255.0;\n"
1756 "}\n";
1757 }
1758 };
1759
1760 class Texture2DIntegerProjectiveOffsetTestES3 : public Texture2DTest
1761 {
1762 protected:
Texture2DIntegerProjectiveOffsetTestES3()1763 Texture2DIntegerProjectiveOffsetTestES3() : Texture2DTest() {}
1764
getVertexShaderSource()1765 const char *getVertexShaderSource() override
1766 {
1767 return "#version 300 es\n"
1768 "out vec2 texcoord;\n"
1769 "in vec4 position;\n"
1770 "void main()\n"
1771 "{\n"
1772 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1773 " texcoord = 0.5*position.xy + vec2(0.5, 0.5);\n"
1774 "}\n";
1775 }
1776
getFragmentShaderSource()1777 const char *getFragmentShaderSource() override
1778 {
1779 return "#version 300 es\n"
1780 "precision highp float;\n"
1781 "precision highp usampler2D;\n"
1782 "uniform usampler2D tex;\n"
1783 "in vec2 texcoord;\n"
1784 "out vec4 fragColor;\n"
1785 "void main()\n"
1786 "{\n"
1787 " fragColor = vec4(textureProjOffset(tex, vec3(texcoord, 1), ivec2(0,0), "
1788 "0.0))/255.0;\n"
1789 "}\n";
1790 }
1791 };
1792
1793 class Texture2DArrayIntegerTestES3 : public Texture2DArrayTestES3
1794 {
1795 protected:
Texture2DArrayIntegerTestES3()1796 Texture2DArrayIntegerTestES3() : Texture2DArrayTestES3() {}
1797
getVertexShaderSource()1798 const char *getVertexShaderSource() override
1799 {
1800 return R"(#version 300 es
1801 out vec2 texcoord;
1802 in vec4 position;
1803 void main()
1804 {
1805 gl_Position = vec4(position.xy, 0.0, 1.0);
1806 texcoord = (position.xy * 0.5) + 0.5;
1807 })";
1808 }
1809
getFragmentShaderSource()1810 const char *getFragmentShaderSource() override
1811 {
1812 return R"(#version 300 es
1813 precision highp float;
1814 uniform highp usampler2DArray tex2DArray;
1815 uniform int slice;
1816 in vec2 texcoord;
1817 out vec4 fragColor;
1818 void main()
1819 {
1820 fragColor = vec4(texture(tex2DArray, vec3(texcoord, slice)))/255.0;
1821 })";
1822 }
1823 };
1824
1825 class Texture3DIntegerTestES3 : public Texture3DTestES3
1826 {
1827 protected:
Texture3DIntegerTestES3()1828 Texture3DIntegerTestES3() : Texture3DTestES3() {}
1829
getVertexShaderSource()1830 const char *getVertexShaderSource() override
1831 {
1832 return "#version 300 es\n"
1833 "out vec2 texcoord;\n"
1834 "in vec4 position;\n"
1835 "void main()\n"
1836 "{\n"
1837 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1838 " texcoord = (position.xy * 0.5) + 0.5;\n"
1839 "}\n";
1840 }
1841
getFragmentShaderSource()1842 const char *getFragmentShaderSource() override
1843 {
1844 return "#version 300 es\n"
1845 "precision highp float;\n"
1846 "uniform highp usampler3D tex3D;\n"
1847 "in vec2 texcoord;\n"
1848 "out vec4 fragColor;\n"
1849 "void main()\n"
1850 "{\n"
1851 " fragColor = vec4(texture(tex3D, vec3(texcoord, 0.0)))/255.0;\n"
1852 "}\n";
1853 }
1854 };
1855
1856 class PBOCompressedTextureTest : public Texture2DTest
1857 {
1858 protected:
PBOCompressedTextureTest()1859 PBOCompressedTextureTest() : Texture2DTest() {}
1860
testSetUp()1861 void testSetUp() override
1862 {
1863 TexCoordDrawTest::testSetUp();
1864 glGenTextures(1, &mTexture2D);
1865 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1866 EXPECT_GL_NO_ERROR();
1867
1868 setUpProgram();
1869
1870 glGenBuffers(1, &mPBO);
1871 }
1872
testTearDown()1873 void testTearDown() override
1874 {
1875 glDeleteBuffers(1, &mPBO);
1876 Texture2DTest::testTearDown();
1877 }
1878
1879 void runCompressedSubImage();
1880
1881 GLuint mPBO;
1882 };
1883
1884 class ETC1CompressedTextureTest : public Texture2DTest
1885 {
1886 protected:
ETC1CompressedTextureTest()1887 ETC1CompressedTextureTest() : Texture2DTest() {}
1888
testSetUp()1889 void testSetUp() override
1890 {
1891 TexCoordDrawTest::testSetUp();
1892 glGenTextures(1, &mTexture2D);
1893 glBindTexture(GL_TEXTURE_2D, mTexture2D);
1894 EXPECT_GL_NO_ERROR();
1895
1896 setUpProgram();
1897 }
1898
testTearDown()1899 void testTearDown() override { Texture2DTest::testTearDown(); }
1900 };
1901
1902 class Texture2DDepthStencilTestES3 : public Texture2DTest
1903 {
1904 protected:
Texture2DDepthStencilTestES3()1905 Texture2DDepthStencilTestES3() : Texture2DTest() {}
1906
1907 void TestSampleWithDepthStencilMode(GLenum format, GLenum mode, bool swizzle);
1908 };
1909
TestSampleWithDepthStencilMode(GLenum format,GLenum mode,bool swizzle)1910 void Texture2DDepthStencilTestES3::TestSampleWithDepthStencilMode(GLenum format,
1911 GLenum mode,
1912 bool swizzle)
1913 {
1914 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_stencil_texturing"));
1915
1916 constexpr GLsizei kSize = 4;
1917
1918 ASSERT(mode == GL_STENCIL_INDEX || mode == GL_DEPTH_COMPONENT);
1919
1920 bool isStencilMode;
1921 GLenum attachment;
1922 switch (format)
1923 {
1924 case GL_DEPTH_COMPONENT16:
1925 case GL_DEPTH_COMPONENT24:
1926 case GL_DEPTH_COMPONENT32F:
1927 attachment = GL_DEPTH_ATTACHMENT;
1928 isStencilMode = false;
1929 break;
1930 case GL_DEPTH24_STENCIL8:
1931 case GL_DEPTH32F_STENCIL8:
1932 attachment = GL_DEPTH_STENCIL_ATTACHMENT;
1933 isStencilMode = mode == GL_STENCIL_INDEX;
1934 break;
1935 case GL_STENCIL_INDEX8:
1936 attachment = GL_STENCIL_ATTACHMENT;
1937 isStencilMode = true;
1938 break;
1939 default:
1940 UNREACHABLE();
1941 }
1942
1943 // Set up a color texture.
1944 GLTexture colorTexture;
1945 glBindTexture(GL_TEXTURE_2D, colorTexture);
1946 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
1947 ASSERT_GL_NO_ERROR();
1948
1949 // Set up a depth/stencil texture to be sampled as mode.
1950 GLTexture depthStencilTexture;
1951 glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
1952 glTexStorage2D(GL_TEXTURE_2D, 1, format, kSize, kSize);
1953 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1954 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1955 glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE_ANGLE, mode);
1956 if (swizzle)
1957 {
1958 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ALPHA);
1959 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
1960 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_GREEN);
1961 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
1962 }
1963 ASSERT_GL_NO_ERROR();
1964
1965 constexpr char kStencilFS[] =
1966 R"(#version 300 es
1967 precision mediump float;
1968 uniform highp usampler2D tex;
1969 out vec4 color;
1970 void main()
1971 {
1972 color = vec4(texelFetch(tex, ivec2(0, 0), 0)) / 255.0f;
1973 })";
1974
1975 constexpr char kDepthFS[] =
1976 R"(#version 300 es
1977 precision mediump float;
1978 uniform highp sampler2D tex;
1979 out vec4 color;
1980 void main()
1981 {
1982 color = texture(tex, vec2(0, 0));
1983 })";
1984
1985 // Clear stencil to 42.
1986 GLFramebuffer clearFBO;
1987 glBindFramebuffer(GL_FRAMEBUFFER, clearFBO);
1988 glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, depthStencilTexture, 0);
1989 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1990 glClearDepthf(0.5);
1991 glClearStencil(42);
1992 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1993 ASSERT_GL_NO_ERROR();
1994
1995 glActiveTexture(GL_TEXTURE0);
1996 glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
1997 EXPECT_GL_ERROR(GL_NO_ERROR);
1998
1999 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), isStencilMode ? kStencilFS : kDepthFS);
2000 GLint texLocation = glGetUniformLocation(program, "tex");
2001 ASSERT_NE(-1, texLocation);
2002 ASSERT_GL_NO_ERROR();
2003
2004 glUseProgram(program);
2005 glUniform1i(texLocation, 0);
2006
2007 GLFramebuffer drawFBO;
2008 glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
2009 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
2010 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2011 ASSERT_GL_NO_ERROR();
2012
2013 drawQuad(program, essl3_shaders::PositionAttrib(), 0.95f);
2014 ASSERT_GL_NO_ERROR();
2015
2016 if (isStencilMode)
2017 {
2018 GLColor expected = swizzle ? GLColor(1, 0, 0, 42) : GLColor(42, 0, 0, 1);
2019 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, expected);
2020 }
2021 else
2022 {
2023 GLColor expected = swizzle ? GLColor(255, 0, 0, 127) : GLColor(127, 0, 0, 255);
2024 EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
2025 }
2026 }
2027
TEST_P(Texture2DTest,NegativeAPISubImage)2028 TEST_P(Texture2DTest, NegativeAPISubImage)
2029 {
2030 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2031 EXPECT_GL_ERROR(GL_NO_ERROR);
2032
2033 setUpProgram();
2034
2035 const GLubyte *pixels[20] = {0};
2036 glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
2037 EXPECT_GL_ERROR(GL_INVALID_VALUE);
2038
2039 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
2040 {
2041 // Create a 1-level immutable texture.
2042 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
2043
2044 // Try calling sub image on the second level.
2045 glTexSubImage2D(GL_TEXTURE_2D, 1, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
2046 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2047 }
2048 }
2049
2050 // Test that querying GL_TEXTURE_BINDING* doesn't cause an unexpected error.
TEST_P(Texture2DTest,QueryBinding)2051 TEST_P(Texture2DTest, QueryBinding)
2052 {
2053 glBindTexture(GL_TEXTURE_2D, 0);
2054 EXPECT_GL_ERROR(GL_NO_ERROR);
2055
2056 GLint textureBinding;
2057 glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
2058 EXPECT_GL_NO_ERROR();
2059 EXPECT_EQ(0, textureBinding);
2060
2061 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &textureBinding);
2062 if (IsGLExtensionEnabled("GL_OES_EGL_image_external") ||
2063 IsGLExtensionEnabled("GL_NV_EGL_stream_consumer_external"))
2064 {
2065 EXPECT_GL_NO_ERROR();
2066 EXPECT_EQ(0, textureBinding);
2067 }
2068 else
2069 {
2070 EXPECT_GL_ERROR(GL_INVALID_ENUM);
2071 }
2072 }
2073
TEST_P(Texture2DTest,ZeroSizedUploads)2074 TEST_P(Texture2DTest, ZeroSizedUploads)
2075 {
2076 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2077 EXPECT_GL_ERROR(GL_NO_ERROR);
2078
2079 setUpProgram();
2080
2081 // Use the texture first to make sure it's in video memory
2082 glUseProgram(mProgram);
2083 glUniform1i(mTexture2DUniformLocation, 0);
2084 drawQuad(mProgram, "position", 0.5f);
2085
2086 const GLubyte *pixel[4] = {0};
2087
2088 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
2089 EXPECT_GL_NO_ERROR();
2090
2091 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
2092 EXPECT_GL_NO_ERROR();
2093
2094 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
2095 EXPECT_GL_NO_ERROR();
2096 }
2097
2098 // Tests uploading a red texture and immediately reading from it.
TEST_P(Texture2DTest,SimpleUpload)2099 TEST_P(Texture2DTest, SimpleUpload)
2100 {
2101 const GLuint width = getWindowWidth();
2102 const GLuint height = getWindowHeight();
2103 const GLuint windowPixelCount = width * height;
2104 std::vector<GLColor> pixelsRed(windowPixelCount, GLColor::red);
2105 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2106 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2107 pixelsRed.data());
2108 EXPECT_GL_ERROR(GL_NO_ERROR);
2109
2110 GLFramebuffer fbo;
2111 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2112
2113 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture2D, 0);
2114
2115 EXPECT_GL_ERROR(GL_NO_ERROR);
2116 std::vector<GLColor> output(windowPixelCount, GLColor::green);
2117 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, output.data());
2118 EXPECT_EQ(pixelsRed, output);
2119 }
2120
2121 // Test that interleaved superseded updates work as expected
TEST_P(Texture2DTest,InterleavedSupersedingTextureUpdates)2122 TEST_P(Texture2DTest, InterleavedSupersedingTextureUpdates)
2123 {
2124 constexpr uint32_t kTexWidth = 3840;
2125 constexpr uint32_t kTexHeight = 2160;
2126 constexpr uint32_t kBpp = 4;
2127
2128 // Create the texture
2129 glActiveTexture(GL_TEXTURE0);
2130 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2131 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2132 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2133 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2134 nullptr);
2135 EXPECT_GL_ERROR(GL_NO_ERROR);
2136
2137 // 1. One big upload followed by many small identical uploads
2138 // Update the entire texture
2139 std::vector<GLubyte> fullTextureData(kTexWidth * kTexHeight * kBpp, 128);
2140 constexpr GLColor kFullTextureColor = GLColor(128u, 128u, 128u, 128u);
2141 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2142 fullTextureData.data());
2143
2144 // Make a number of identical updates to the right half of the texture
2145 std::vector<GLubyte> rightHalfData(kTexWidth * kTexHeight * kBpp, 201);
2146 constexpr GLColor kRightHalfColor = GLColor(201u, 201u, 201u, 201u);
2147 for (uint32_t iteration = 0; iteration < 10; iteration++)
2148 {
2149 glTexSubImage2D(GL_TEXTURE_2D, 0, kTexWidth / 2, 0, kTexWidth / 2, kTexHeight, GL_RGBA,
2150 GL_UNSIGNED_BYTE, rightHalfData.data());
2151 }
2152
2153 setUpProgram();
2154 glUseProgram(mProgram);
2155 glUniform1i(mTexture2DUniformLocation, 0);
2156 drawQuad(mProgram, "position", 0.5f);
2157 EXPECT_GL_NO_ERROR();
2158 EXPECT_PIXEL_COLOR_EQ(1 * getWindowWidth() / 4, getWindowHeight() / 2, kFullTextureColor);
2159 EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 2, kRightHalfColor);
2160
2161 // 2. Some small uploads followed by one big upload followed by many identical uploads
2162 // Clear the entire texture
2163 std::vector<GLubyte> zeroTextureData(kTexWidth * kTexHeight * kBpp, 255);
2164 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2165 zeroTextureData.data());
2166
2167 // Update the top left quadrant of the texture
2168 std::vector<GLubyte> topLeftQuadrantData(kTexWidth * kTexHeight * kBpp, 128);
2169 constexpr GLColor kTopLeftQuandrantTextureColor = GLColor(128u, 128u, 128u, 128u);
2170 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, kTexHeight / 2, kTexWidth / 2, kTexHeight / 2, GL_RGBA,
2171 GL_UNSIGNED_BYTE, topLeftQuadrantData.data());
2172
2173 // Update the top right quadrant of the texture
2174 std::vector<GLubyte> topRightQuadrantData(kTexWidth * kTexHeight * kBpp, 156);
2175 constexpr GLColor kTopRightQuadrantTextureColor = GLColor(156u, 156u, 156u, 156u);
2176 glTexSubImage2D(GL_TEXTURE_2D, 0, kTexWidth / 2, kTexHeight / 2, kTexWidth / 2, kTexHeight / 2,
2177 GL_RGBA, GL_UNSIGNED_BYTE, topRightQuadrantData.data());
2178
2179 // Update the bottom half of the texture
2180 std::vector<GLubyte> bottomHalfTextureData(kTexWidth * kTexHeight * kBpp, 187);
2181 constexpr GLColor kBottomHalfTextureColor = GLColor(187u, 187u, 187u, 187u);
2182 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight / 2, GL_RGBA, GL_UNSIGNED_BYTE,
2183 bottomHalfTextureData.data());
2184
2185 // Make a number of identical updates to the bottom right quadrant of the texture
2186 std::vector<GLubyte> bottomRightQuadrantData(kTexWidth * kTexHeight * kBpp, 201);
2187 constexpr GLColor kBottomRightQuadrantColor = GLColor(201u, 201u, 201u, 201u);
2188 for (uint32_t iteration = 0; iteration < 10; iteration++)
2189 {
2190 glTexSubImage2D(GL_TEXTURE_2D, 0, kTexWidth / 2, 0, kTexWidth / 2, kTexHeight / 2, GL_RGBA,
2191 GL_UNSIGNED_BYTE, bottomRightQuadrantData.data());
2192 }
2193
2194 setUpProgram();
2195 glUseProgram(mProgram);
2196 glUniform1i(mTexture2DUniformLocation, 0);
2197 drawQuad(mProgram, "position", 0.5f);
2198 EXPECT_GL_NO_ERROR();
2199 EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, kTopLeftQuandrantTextureColor);
2200 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1,
2201 kTopRightQuadrantTextureColor);
2202 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, kBottomHalfTextureColor);
2203 EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4,
2204 kBottomRightQuadrantColor);
2205
2206 // 3. Many small uploads folloed by one big upload
2207 // Clear the entire texture
2208 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2209 zeroTextureData.data());
2210
2211 // Make a number of small updates to different parts of the texture
2212 std::vector<std::pair<GLint, GLint>> xyOffsets = {
2213 {1, 4}, {128, 34}, {1208, 1090}, {2560, 2022}};
2214 constexpr GLColor kRandomColor = GLColor(55u, 128u, 201u, 255u);
2215 for (const std::pair<GLint, GLint> &xyOffset : xyOffsets)
2216 {
2217 glTexSubImage2D(GL_TEXTURE_2D, 0, xyOffset.first, xyOffset.second, 1, 1, GL_RGBA,
2218 GL_UNSIGNED_BYTE, kRandomColor.data());
2219 }
2220
2221 // Update the entire texture
2222 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2223 fullTextureData.data());
2224
2225 setUpProgram();
2226 glUseProgram(mProgram);
2227 glUniform1i(mTexture2DUniformLocation, 0);
2228 drawQuad(mProgram, "position", 0.5f);
2229 EXPECT_GL_NO_ERROR();
2230 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth() - 1, getWindowHeight() - 1, kFullTextureColor);
2231 }
2232
2233 // Test that repeated calls to glTexSubImage2D with superseding updates works
TEST_P(Texture2DTest,ManySupersedingTextureUpdates)2234 TEST_P(Texture2DTest, ManySupersedingTextureUpdates)
2235 {
2236 constexpr uint32_t kTexWidth = 3840;
2237 constexpr uint32_t kTexHeight = 2160;
2238 constexpr uint32_t kBpp = 4;
2239 std::vector<GLubyte> data(kTexWidth * kTexHeight * kBpp, 0);
2240
2241 // Create the texture
2242 glActiveTexture(GL_TEXTURE0);
2243 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2244 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2245 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2246 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2247 nullptr);
2248 EXPECT_GL_ERROR(GL_NO_ERROR);
2249
2250 // Make a large number of superseding updates
2251 for (uint32_t width = kTexWidth / 2, height = kTexHeight / 2;
2252 width < kTexWidth && height < kTexHeight; width++, height++)
2253 {
2254 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
2255 data.data());
2256 }
2257
2258 // Upload different color to the whole texture thus superseding all prior updates.
2259 std::vector<GLubyte> supersedingData(kTexWidth * kTexHeight * kBpp, 128);
2260 constexpr GLColor kGray = GLColor(128u, 128u, 128u, 128u);
2261 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
2262 supersedingData.data());
2263
2264 setUpProgram();
2265 glUseProgram(mProgram);
2266 glUniform1i(mTexture2DUniformLocation, 0);
2267 drawQuad(mProgram, "position", 0.5f);
2268 EXPECT_GL_NO_ERROR();
2269 EXPECT_PIXEL_COLOR_EQ(0, 0, kGray);
2270 }
2271
TEST_P(Texture2DTest,DefineMultipleLevelsWithoutMipmapping)2272 TEST_P(Texture2DTest, DefineMultipleLevelsWithoutMipmapping)
2273 {
2274 setUpProgram();
2275
2276 constexpr size_t kImageSize = 256;
2277 std::array<GLColor, kImageSize * kImageSize> kMipColors[2];
2278
2279 std::fill(kMipColors[0].begin(), kMipColors[0].end(), GLColor::red);
2280 std::fill(kMipColors[1].begin(), kMipColors[1].end(), GLColor::green);
2281
2282 glActiveTexture(GL_TEXTURE0);
2283 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2284 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2285 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2286
2287 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2288 kMipColors[0].data());
2289 EXPECT_GL_NO_ERROR();
2290
2291 // Draw so the image is created.
2292 glUseProgram(mProgram);
2293 glUniform1i(mTexture2DUniformLocation, 0);
2294 drawQuad(mProgram, "position", 0.5f);
2295
2296 // Define level 1 of the texture.
2297 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2298 kMipColors[1].data());
2299 EXPECT_GL_NO_ERROR();
2300
2301 // Draw again.
2302 drawQuad(mProgram, "position", 0.5f);
2303 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0][0]);
2304 }
2305
2306 // Test drawing with two texture types, to trigger an ANGLE bug in validation
TEST_P(TextureCubeTest,CubeMapBug)2307 TEST_P(TextureCubeTest, CubeMapBug)
2308 {
2309 glActiveTexture(GL_TEXTURE0);
2310 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2311 glActiveTexture(GL_TEXTURE1);
2312 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
2313 EXPECT_GL_ERROR(GL_NO_ERROR);
2314
2315 glUseProgram(mProgram);
2316 glUniform1i(mTexture2DUniformLocation, 0);
2317 glUniform1i(mTextureCubeUniformLocation, 1);
2318 drawQuad(mProgram, "position", 0.5f);
2319 EXPECT_GL_NO_ERROR();
2320 }
2321
2322 // Test drawing with two texture types accessed from the same shader and check that the result of
2323 // drawing is correct.
TEST_P(TextureCubeTest,CubeMapDraw)2324 TEST_P(TextureCubeTest, CubeMapDraw)
2325 {
2326 GLubyte texData[4];
2327 texData[0] = 0;
2328 texData[1] = 60;
2329 texData[2] = 0;
2330 texData[3] = 255;
2331
2332 glActiveTexture(GL_TEXTURE0);
2333 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2334 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
2335
2336 glActiveTexture(GL_TEXTURE1);
2337 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
2338 texData[1] = 120;
2339 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2340 texData);
2341 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2342 texData);
2343 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2344 texData);
2345 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2346 texData);
2347 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2348 texData);
2349 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2350 texData);
2351 EXPECT_GL_ERROR(GL_NO_ERROR);
2352
2353 glUseProgram(mProgram);
2354 glUniform1i(mTexture2DUniformLocation, 0);
2355 glUniform1i(mTextureCubeUniformLocation, 1);
2356 drawQuad(mProgram, "position", 0.5f);
2357 EXPECT_GL_NO_ERROR();
2358
2359 int px = getWindowWidth() - 1;
2360 int py = 0;
2361 EXPECT_PIXEL_NEAR(px, py, 0, 180, 0, 255, 2);
2362 }
2363
TEST_P(Sampler2DAsFunctionParameterTest,Sampler2DAsFunctionParameter)2364 TEST_P(Sampler2DAsFunctionParameterTest, Sampler2DAsFunctionParameter)
2365 {
2366 glActiveTexture(GL_TEXTURE0);
2367 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2368 GLubyte texData[4];
2369 texData[0] = 0;
2370 texData[1] = 128;
2371 texData[2] = 0;
2372 texData[3] = 255;
2373 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texData);
2374 glUseProgram(mProgram);
2375 glUniform1i(mTexture2DUniformLocation, 0);
2376 drawQuad(mProgram, "position", 0.5f);
2377 EXPECT_GL_NO_ERROR();
2378
2379 EXPECT_PIXEL_NEAR(0, 0, 0, 128, 0, 255, 2);
2380 }
2381
2382 // Test drawing with two textures passed to the shader in a sampler array.
TEST_P(SamplerArrayTest,SamplerArrayDraw)2383 TEST_P(SamplerArrayTest, SamplerArrayDraw)
2384 {
2385 testSamplerArrayDraw();
2386 }
2387
2388 // Test drawing with two textures passed to the shader in a sampler array which is passed to a
2389 // user-defined function in the shader.
TEST_P(SamplerArrayAsFunctionParameterTest,SamplerArrayAsFunctionParameter)2390 TEST_P(SamplerArrayAsFunctionParameterTest, SamplerArrayAsFunctionParameter)
2391 {
2392 // TODO: Diagnose and fix. http://anglebug.com/2955
2393 ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
2394
2395 testSamplerArrayDraw();
2396 }
2397
2398 // Copy of a test in conformance/textures/texture-mips, to test generate mipmaps
TEST_P(Texture2DTestWithDrawScale,MipmapsTwice)2399 TEST_P(Texture2DTestWithDrawScale, MipmapsTwice)
2400 {
2401 int px = getWindowWidth() / 2;
2402 int py = getWindowHeight() / 2;
2403
2404 glActiveTexture(GL_TEXTURE0);
2405 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2406
2407 std::vector<GLColor> pixelsRed(16u * 16u, GLColor::red);
2408
2409 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelsRed.data());
2410 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
2411 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2412 glGenerateMipmap(GL_TEXTURE_2D);
2413
2414 glUseProgram(mProgram);
2415 glUniform1i(mTexture2DUniformLocation, 0);
2416 glUniform2f(mDrawScaleUniformLocation, 0.0625f, 0.0625f);
2417 drawQuad(mProgram, "position", 0.5f);
2418 EXPECT_GL_NO_ERROR();
2419 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
2420
2421 std::vector<GLColor> pixelsBlue(16u * 16u, GLColor::blue);
2422
2423 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2424 pixelsBlue.data());
2425 glGenerateMipmap(GL_TEXTURE_2D);
2426
2427 drawQuad(mProgram, "position", 0.5f);
2428
2429 EXPECT_GL_NO_ERROR();
2430 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::blue);
2431
2432 std::vector<GLColor> pixelsGreen(16u * 16u, GLColor::green);
2433
2434 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2435 pixelsGreen.data());
2436 glGenerateMipmap(GL_TEXTURE_2D);
2437
2438 drawQuad(mProgram, "position", 0.5f);
2439
2440 EXPECT_GL_NO_ERROR();
2441 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
2442 }
2443
2444 // Test creating a FBO with a cube map render target, to test an ANGLE bug
2445 // https://code.google.com/p/angleproject/issues/detail?id=849
TEST_P(TextureCubeTest,CubeMapFBO)2446 TEST_P(TextureCubeTest, CubeMapFBO)
2447 {
2448 // http://anglebug.com/3145
2449 ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
2450
2451 GLFramebuffer fbo;
2452 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2453
2454 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
2455 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
2456 mTextureCube, 0);
2457
2458 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2459 EXPECT_GL_NO_ERROR();
2460
2461 // Test clearing the six mip faces individually.
2462 std::array<GLColor, 6> faceColors = {{GLColor::red, GLColor::green, GLColor::blue,
2463 GLColor::yellow, GLColor::cyan, GLColor::magenta}};
2464
2465 for (size_t faceIndex = 0; faceIndex < 6; ++faceIndex)
2466 {
2467 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2468 GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, mTextureCube, 0);
2469
2470 Vector4 clearColorF = faceColors[faceIndex].toNormalizedVector();
2471 glClearColor(clearColorF.x(), clearColorF.y(), clearColorF.z(), clearColorF.w());
2472 glClear(GL_COLOR_BUFFER_BIT);
2473
2474 EXPECT_PIXEL_COLOR_EQ(0, 0, faceColors[faceIndex]);
2475 }
2476
2477 // Iterate the faces again to make sure the colors haven't changed.
2478 for (size_t faceIndex = 0; faceIndex < 6; ++faceIndex)
2479 {
2480 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2481 GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, mTextureCube, 0);
2482 EXPECT_PIXEL_COLOR_EQ(0, 0, faceColors[faceIndex])
2483 << "face color " << faceIndex << " shouldn't change";
2484 }
2485 }
2486
2487 // Tests clearing a cube map with a scissor enabled.
TEST_P(TextureCubeTest,CubeMapFBOScissoredClear)2488 TEST_P(TextureCubeTest, CubeMapFBOScissoredClear)
2489 {
2490 // http://anglebug.com/3145
2491 ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
2492
2493 constexpr size_t kSize = 16;
2494
2495 GLFramebuffer fbo;
2496 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2497 glViewport(0, 0, kSize, kSize);
2498
2499 GLTexture texcube;
2500 glBindTexture(GL_TEXTURE_CUBE_MAP, texcube);
2501 for (GLenum face = 0; face < 6; face++)
2502 {
2503 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA,
2504 GL_UNSIGNED_BYTE, nullptr);
2505 }
2506 ASSERT_GL_NO_ERROR();
2507
2508 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
2509 texcube, 0);
2510
2511 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2512 ASSERT_GL_NO_ERROR();
2513
2514 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2515 glClear(GL_COLOR_BUFFER_BIT);
2516 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2517
2518 glEnable(GL_SCISSOR_TEST);
2519 glScissor(kSize / 2, 0, kSize / 2, kSize);
2520 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2521 glClear(GL_COLOR_BUFFER_BIT);
2522
2523 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2524 EXPECT_PIXEL_COLOR_EQ(kSize / 2 + 1, 0, GLColor::green);
2525
2526 ASSERT_GL_NO_ERROR();
2527 }
2528
2529 // Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a
2530 // default color.
TEST_P(Texture2DTest,TexStorage)2531 TEST_P(Texture2DTest, TexStorage)
2532 {
2533 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
2534 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
2535
2536 int width = getWindowWidth();
2537 int height = getWindowHeight();
2538
2539 GLTexture tex2D;
2540 glActiveTexture(GL_TEXTURE0);
2541 glBindTexture(GL_TEXTURE_2D, tex2D);
2542
2543 // Fill with red
2544 std::vector<GLubyte> pixels(3 * 16 * 16);
2545 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2546 {
2547 pixels[pixelId * 3 + 0] = 255;
2548 pixels[pixelId * 3 + 1] = 0;
2549 pixels[pixelId * 3 + 2] = 0;
2550 }
2551
2552 // ANGLE internally uses RGBA as the DirectX format for RGB images
2553 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent
2554 // alpha color. The data is kept in a CPU-side image and the image is marked as dirty.
2555 if (getClientMajorVersion() >= 3)
2556 {
2557 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
2558 }
2559 else
2560 {
2561 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
2562 }
2563
2564 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
2565 // glTexSubImage2D should take into account that the image is dirty.
2566 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
2567 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2568 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2569
2570 setUpProgram();
2571
2572 glUseProgram(mProgram);
2573 glUniform1i(mTexture2DUniformLocation, 0);
2574 drawQuad(mProgram, "position", 0.5f);
2575 EXPECT_GL_NO_ERROR();
2576 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
2577
2578 // Validate that the region of the texture without data has an alpha of 1.0
2579 angle::GLColor pixel = ReadColor(3 * width / 4, 3 * height / 4);
2580 EXPECT_EQ(255, pixel.A);
2581 }
2582
2583 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
2584 // initialized the image with a default color.
TEST_P(Texture2DTest,TexStorageWithPBO)2585 TEST_P(Texture2DTest, TexStorageWithPBO)
2586 {
2587 if (getClientMajorVersion() < 3)
2588 {
2589 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2590 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2591 }
2592
2593 const int width = getWindowWidth();
2594 const int height = getWindowHeight();
2595 const size_t pixelCount = width * height;
2596 const int componentCount = 3;
2597
2598 GLTexture tex2D;
2599 glActiveTexture(GL_TEXTURE0);
2600 glBindTexture(GL_TEXTURE_2D, tex2D);
2601
2602 // Fill with red
2603 std::vector<GLubyte> pixels(componentCount * pixelCount);
2604 for (size_t pixelId = 0; pixelId < pixelCount; ++pixelId)
2605 {
2606 pixels[pixelId * componentCount + 0] = 255;
2607 pixels[pixelId * componentCount + 1] = 0;
2608 pixels[pixelId * componentCount + 2] = 0;
2609 }
2610
2611 // Read 16x16 region from red backbuffer to PBO
2612 GLuint pbo;
2613 glGenBuffers(1, &pbo);
2614 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2615 glBufferData(GL_PIXEL_UNPACK_BUFFER, componentCount * pixelCount, pixels.data(),
2616 GL_STATIC_DRAW);
2617
2618 // ANGLE internally uses RGBA as the DirectX format for RGB images
2619 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent
2620 // alpha color. The data is kept in a CPU-side image and the image is marked as dirty.
2621 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, width, height);
2622
2623 // Initializes the color of the upper-left quadrant of pixels, leaves the other pixels
2624 // untouched. glTexSubImage2D should take into account that the image is dirty.
2625 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RGB, GL_UNSIGNED_BYTE,
2626 nullptr);
2627 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2628 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2629
2630 setUpProgram();
2631
2632 glUseProgram(mProgram);
2633 glUniform1i(mTexture2DUniformLocation, 0);
2634 drawQuad(mProgram, "position", 0.5f);
2635 glDeleteBuffers(1, &pbo);
2636 EXPECT_GL_NO_ERROR();
2637 EXPECT_PIXEL_RECT_EQ(0, 0, width / 2, height / 2, GLColor(255, 0, 0, 255));
2638 }
2639
2640 // Test that glTexSubImage2D combined with a PBO works properly after deleting the PBO
2641 // and drawing with the texture
2642 // Pseudo code for the follow test:
2643 // 1. Upload PBO to mTexture2D
2644 // 2. Delete PBO
2645 // 3. Draw with otherTexture (x5)
2646 // 4. Draw with mTexture2D
2647 // 5. Validate color output
TEST_P(Texture2DTest,PBOWithMultipleDraws)2648 TEST_P(Texture2DTest, PBOWithMultipleDraws)
2649 {
2650 if (getClientMajorVersion() < 3)
2651 {
2652 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2653 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2654 }
2655
2656 const GLuint width = getWindowWidth();
2657 const GLuint height = getWindowHeight();
2658 const GLuint windowPixelCount = width * height;
2659 std::vector<GLColor> pixelsRed(windowPixelCount, GLColor::red);
2660 std::vector<GLColor> pixelsGreen(windowPixelCount, GLColor::green);
2661
2662 // Create secondary draw that does not use mTexture
2663 const char *vertexShaderSource = getVertexShaderSource();
2664 const char *fragmentShaderSource = getFragmentShaderSource();
2665 ANGLE_GL_PROGRAM(otherProgram, vertexShaderSource, fragmentShaderSource);
2666
2667 GLint uniformLoc = glGetUniformLocation(otherProgram, getTextureUniformName());
2668 ASSERT_NE(-1, uniformLoc);
2669 glUseProgram(0);
2670
2671 // Create secondary Texture to draw with
2672 GLTexture otherTexture;
2673 glActiveTexture(GL_TEXTURE0);
2674 glBindTexture(GL_TEXTURE_2D, otherTexture);
2675 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
2676 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
2677 pixelsRed.data());
2678 ASSERT_GL_NO_ERROR();
2679
2680 // Setup primary Texture
2681 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2682 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2683 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2684 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
2685 ASSERT_GL_NO_ERROR();
2686
2687 // Setup PBO
2688 GLuint pbo = 0;
2689 glGenBuffers(1, &pbo);
2690 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2691 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
2692 GL_STATIC_DRAW);
2693 ASSERT_GL_NO_ERROR();
2694
2695 // Write PBO to mTexture
2696 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2697 ASSERT_GL_NO_ERROR();
2698 // Delete PBO as ANGLE should be properly handling refcount of this buffer
2699 glDeleteBuffers(1, &pbo);
2700 pixelsGreen.clear();
2701
2702 // Do 5 draws not involving primary texture that the PBO updated
2703 glUseProgram(otherProgram);
2704 glUniform1i(uniformLoc, 0);
2705 glBindTexture(GL_TEXTURE_2D, otherTexture);
2706 drawQuad(otherProgram, "position", 0.5f);
2707 glBindTexture(GL_TEXTURE_2D, 0);
2708 glUseProgram(0);
2709
2710 glUseProgram(otherProgram);
2711 glUniform1i(uniformLoc, 0);
2712 glBindTexture(GL_TEXTURE_2D, otherTexture);
2713 drawQuad(otherProgram, "position", 0.5f);
2714 glBindTexture(GL_TEXTURE_2D, 0);
2715 glUseProgram(0);
2716
2717 glUseProgram(otherProgram);
2718 glUniform1i(uniformLoc, 0);
2719 glBindTexture(GL_TEXTURE_2D, otherTexture);
2720 drawQuad(otherProgram, "position", 0.5f);
2721 glBindTexture(GL_TEXTURE_2D, 0);
2722 glUseProgram(0);
2723
2724 glUseProgram(otherProgram);
2725 glUniform1i(uniformLoc, 0);
2726 glBindTexture(GL_TEXTURE_2D, otherTexture);
2727 drawQuad(otherProgram, "position", 0.5f);
2728 glBindTexture(GL_TEXTURE_2D, 0);
2729 glUseProgram(0);
2730 ASSERT_GL_NO_ERROR();
2731
2732 std::vector<GLColor> output(windowPixelCount, GLColor::black);
2733 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
2734 output.data());
2735 EXPECT_EQ(pixelsRed, output);
2736
2737 setUpProgram();
2738 // Draw using PBO updated texture
2739 glUseProgram(mProgram);
2740 glUniform1i(mTexture2DUniformLocation, 0);
2741 glBindTexture(GL_TEXTURE_2D, mTexture2D);
2742 drawQuad(mProgram, "position", 0.5f);
2743 ASSERT_GL_NO_ERROR();
2744
2745 std::vector<GLColor> actual(windowPixelCount, GLColor::black);
2746 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
2747 actual.data());
2748 // Value should be green as it was updated during PBO transfer to mTexture
2749 std::vector<GLColor> expected(windowPixelCount, GLColor::green);
2750 EXPECT_EQ(expected, actual);
2751 }
2752
2753 // Test that stencil texture uploads work.
TEST_P(Texture2DTestES3,TexImageWithStencilData)2754 TEST_P(Texture2DTestES3, TexImageWithStencilData)
2755 {
2756 constexpr GLsizei kSize = 4;
2757
2758 const std::array<std::tuple<GLenum, GLenum, int, int>, 3> testConfigs = {
2759 std::make_tuple(GL_DEPTH32F_STENCIL8, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8, 4),
2760 std::make_tuple(GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8, 4, 0),
2761 std::make_tuple(GL_STENCIL_INDEX8, GL_UNSIGNED_BYTE, 1, 0)};
2762
2763 for (auto testConfig : testConfigs)
2764 {
2765 const GLenum format = std::get<0>(testConfig);
2766 const GLenum type = std::get<1>(testConfig);
2767 const GLenum typeLength = std::get<2>(testConfig);
2768 const GLenum typeOffset = std::get<3>(testConfig);
2769
2770 ANGLE_SKIP_TEST_IF(format == GL_STENCIL_INDEX8 &&
2771 !IsGLExtensionEnabled("GL_OES_texture_stencil8"));
2772
2773 // Set up the framebuffer
2774 GLTexture colorTexture;
2775 glBindTexture(GL_TEXTURE_2D, colorTexture);
2776 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2777 nullptr);
2778 ASSERT_GL_NO_ERROR();
2779
2780 GLTexture depthStencilTexture;
2781 glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
2782
2783 GLubyte pixels[kSize * kSize * 8] = {};
2784 for (size_t pixelId = 0; pixelId < kSize * kSize; ++pixelId)
2785 {
2786 pixels[pixelId * typeLength + typeOffset] = 0xD5;
2787 }
2788 glTexImage2D(GL_TEXTURE_2D, 0, format, kSize, kSize, 0,
2789 format == GL_STENCIL_INDEX8 ? GL_STENCIL_INDEX : GL_DEPTH_STENCIL, type,
2790 pixels);
2791 ASSERT_GL_NO_ERROR();
2792
2793 GLFramebuffer fbo;
2794 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2795 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture,
2796 0);
2797 glFramebufferTexture2D(
2798 GL_FRAMEBUFFER,
2799 format == GL_STENCIL_INDEX8 ? GL_STENCIL_ATTACHMENT : GL_DEPTH_STENCIL_ATTACHMENT,
2800 GL_TEXTURE_2D, depthStencilTexture, 0);
2801 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2802 ASSERT_GL_NO_ERROR();
2803
2804 // Clear only color.
2805 glClearColor(0, 0, 0, 1);
2806 glClear(GL_COLOR_BUFFER_BIT);
2807 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
2808
2809 // If stencil is not set to 0xD5, rendering would fail.
2810 glEnable(GL_STENCIL_TEST);
2811 glStencilFunc(GL_EQUAL, 0xD5, 0xFF);
2812 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2813 glStencilMask(0xFF);
2814
2815 // Draw red
2816 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2817 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f);
2818 ASSERT_GL_NO_ERROR();
2819
2820 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
2821 }
2822 }
2823
2824 // Test that glTexSubImage2D combined with a PBO works properly. PBO has all pixels as red
2825 // except the middle one being green.
TEST_P(Texture2DTest,TexStorageWithPBOMiddlePixelDifferent)2826 TEST_P(Texture2DTest, TexStorageWithPBOMiddlePixelDifferent)
2827 {
2828 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2829 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2830
2831 int width = getWindowWidth();
2832 int height = getWindowHeight();
2833
2834 GLTexture tex2D;
2835 glActiveTexture(GL_TEXTURE0);
2836 glBindTexture(GL_TEXTURE_2D, tex2D);
2837
2838 std::vector<GLubyte> pixels(3 * 16 * 16);
2839
2840 // Initialize texture with default black color.
2841 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
2842 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
2843
2844 // Fill PBO's data with red, with middle one as green
2845 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2846 {
2847 if (pixelId == 8 * 7 + 7)
2848 {
2849 pixels[pixelId * 3 + 0] = 0;
2850 pixels[pixelId * 3 + 1] = 255;
2851 pixels[pixelId * 3 + 2] = 0;
2852 }
2853 else
2854 {
2855 pixels[pixelId * 3 + 0] = 255;
2856 pixels[pixelId * 3 + 1] = 0;
2857 pixels[pixelId * 3 + 2] = 0;
2858 }
2859 }
2860
2861 GLuint pbo;
2862 glGenBuffers(1, &pbo);
2863 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2864 glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
2865
2866 // Update the color of the texture's upper-left 8x8 pixels, leaves the other pixels untouched.
2867 // glTexSubImage2D should take into account that the image is dirty.
2868 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
2869 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2870 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2871
2872 setUpProgram();
2873
2874 glUseProgram(mProgram);
2875 glUniform1i(mTexture2DUniformLocation, 0);
2876 drawQuad(mProgram, "position", 0.5f);
2877 glDeleteBuffers(1, &pbo);
2878 EXPECT_GL_NO_ERROR();
2879 EXPECT_PIXEL_EQ(3 * width / 4, 3 * height / 4, 0, 0, 0, 255);
2880 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
2881 EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
2882 }
2883
2884 // Test that glTexSubImage2D combined with a PBO works properly when glTexImage2D has
2885 // initialized the image with a luminance color
TEST_P(Texture2DTest,TexImageWithLuminancePBO)2886 TEST_P(Texture2DTest, TexImageWithLuminancePBO)
2887 {
2888 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2889
2890 int width = getWindowWidth();
2891 int height = getWindowHeight();
2892
2893 GLTexture tex2D;
2894 glActiveTexture(GL_TEXTURE0);
2895 glBindTexture(GL_TEXTURE_2D, tex2D);
2896
2897 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 16, 16, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
2898 nullptr);
2899
2900 // Fill PBO with white, with middle one as grey
2901 std::vector<GLubyte> pixels(16 * 16);
2902 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2903 {
2904 if (pixelId == 8 * 7 + 7)
2905 {
2906 pixels[pixelId] = 128;
2907 }
2908 else
2909 {
2910 pixels[pixelId] = 255;
2911 }
2912 }
2913
2914 GLuint pbo;
2915 glGenBuffers(1, &pbo);
2916 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2917 glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16, pixels.data(), GL_STATIC_DRAW);
2918
2919 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
2920 // glTexSubImage2D should take into account that the image is dirty.
2921 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr);
2922 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2923 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2924
2925 setUpProgram();
2926
2927 glUseProgram(mProgram);
2928 glUniform1i(mTexture2DUniformLocation, 0);
2929 drawQuad(mProgram, "position", 0.5f);
2930 glDeleteBuffers(1, &pbo);
2931 EXPECT_GL_NO_ERROR();
2932 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 255, 255, 255);
2933 EXPECT_PIXEL_NEAR(width / 2 - 1, height / 2 - 1, 128, 128, 128, 255, 1);
2934 }
2935
2936 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
2937 // initialized the image with a RGB656 color
TEST_P(Texture2DTest,TexImageWithRGB565PBO)2938 TEST_P(Texture2DTest, TexImageWithRGB565PBO)
2939 {
2940 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2941 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2942
2943 int width = getWindowWidth();
2944 int height = getWindowHeight();
2945
2946 GLTexture tex2D;
2947 glActiveTexture(GL_TEXTURE0);
2948 glBindTexture(GL_TEXTURE_2D, tex2D);
2949
2950 // Fill PBO with red, with middle one as green
2951 std::vector<GLushort> pixels(16 * 16);
2952 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
2953 {
2954 if (pixelId == 8 * 7 + 8)
2955 {
2956 pixels[pixelId] = 0x7E0;
2957 }
2958 else
2959 {
2960 pixels[pixelId] = 0xF800;
2961 }
2962 }
2963
2964 GLuint pbo;
2965 glGenBuffers(1, &pbo);
2966 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
2967 glBufferData(GL_PIXEL_UNPACK_BUFFER, 2 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
2968
2969 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB565, 16, 16);
2970
2971 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
2972 // glTexSubImage2D should take into account that the image is dirty.
2973 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
2974 reinterpret_cast<void *>(2));
2975 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2976 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2977
2978 setUpProgram();
2979
2980 glUseProgram(mProgram);
2981 glUniform1i(mTexture2DUniformLocation, 0);
2982 drawQuad(mProgram, "position", 0.5f);
2983 glDeleteBuffers(1, &pbo);
2984 EXPECT_GL_NO_ERROR();
2985 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
2986 EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
2987 }
2988
2989 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
2990 // initialized the image with a RGBA4444 color
TEST_P(Texture2DTest,TexImageWithRGBA4444PBO)2991 TEST_P(Texture2DTest, TexImageWithRGBA4444PBO)
2992 {
2993 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
2994 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
2995
2996 int width = getWindowWidth();
2997 int height = getWindowHeight();
2998
2999 GLTexture tex2D;
3000 glActiveTexture(GL_TEXTURE0);
3001 glBindTexture(GL_TEXTURE_2D, tex2D);
3002
3003 // Fill PBO with red, with middle one as green
3004 std::vector<GLushort> pixels(16 * 16);
3005 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
3006 {
3007 if (pixelId == 8 * 7 + 8)
3008 {
3009 pixels[pixelId] = 0xF0F;
3010 }
3011 else
3012 {
3013 pixels[pixelId] = 0xF00F;
3014 }
3015 }
3016
3017 GLuint pbo;
3018 glGenBuffers(1, &pbo);
3019 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3020 glBufferData(GL_PIXEL_UNPACK_BUFFER, 2 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
3021
3022 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA4, 16, 16);
3023
3024 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
3025 // glTexSubImage2D should take into account that the image is dirty.
3026 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
3027 reinterpret_cast<void *>(2));
3028 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3029 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3030
3031 setUpProgram();
3032
3033 glUseProgram(mProgram);
3034 glUniform1i(mTexture2DUniformLocation, 0);
3035 drawQuad(mProgram, "position", 0.5f);
3036 glDeleteBuffers(1, &pbo);
3037 EXPECT_GL_NO_ERROR();
3038 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
3039 EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
3040 }
3041
3042 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has
3043 // initialized the image with a RGBA5551 color
TEST_P(Texture2DTest,TexImageWithRGBA5551PBO)3044 TEST_P(Texture2DTest, TexImageWithRGBA5551PBO)
3045 {
3046 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3047 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3048
3049 int width = getWindowWidth();
3050 int height = getWindowHeight();
3051
3052 GLTexture tex2D;
3053 glActiveTexture(GL_TEXTURE0);
3054 glBindTexture(GL_TEXTURE_2D, tex2D);
3055
3056 // Fill PBO with red, with middle one as green
3057 std::vector<GLushort> pixels(16 * 16);
3058 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
3059 {
3060 if (pixelId == 8 * 7 + 7)
3061 {
3062 pixels[pixelId] = 0x7C1;
3063 }
3064 else
3065 {
3066 pixels[pixelId] = 0xF801;
3067 }
3068 }
3069
3070 GLuint pbo;
3071 glGenBuffers(1, &pbo);
3072 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3073 glBufferData(GL_PIXEL_UNPACK_BUFFER, 2 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
3074
3075 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB5_A1, 16, 16);
3076
3077 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
3078 // glTexSubImage2D should take into account that the image is dirty.
3079 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, nullptr);
3080 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3081 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3082
3083 setUpProgram();
3084
3085 glUseProgram(mProgram);
3086 glUniform1i(mTexture2DUniformLocation, 0);
3087 drawQuad(mProgram, "position", 0.5f);
3088 glDeleteBuffers(1, &pbo);
3089 EXPECT_GL_NO_ERROR();
3090 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
3091 EXPECT_PIXEL_EQ(width / 2 - 1, height / 2 - 1, 0, 255, 0, 255);
3092 }
3093
3094 // Test that glTexSubImage2D from a PBO respects GL_UNPACK_ROW_LENGTH.
TEST_P(Texture2DTest,TexImageUnpackRowLengthPBO)3095 TEST_P(Texture2DTest, TexImageUnpackRowLengthPBO)
3096 {
3097 if (getClientMajorVersion() < 3)
3098 {
3099 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3100 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3101 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_unpack_subimage"));
3102 }
3103
3104 const int width = getWindowWidth() / 2;
3105 const int height = getWindowHeight();
3106 const int rowLength = getWindowWidth();
3107 const int bufferSize = rowLength * height;
3108
3109 GLTexture tex2D;
3110 glActiveTexture(GL_TEXTURE0);
3111 glBindTexture(GL_TEXTURE_2D, tex2D);
3112
3113 std::vector<GLColor> pixels(bufferSize);
3114 for (int y = 0; y < rowLength; ++y)
3115 {
3116 for (int x = 0; x < width; ++x)
3117 {
3118 pixels[y * rowLength + x] =
3119 x < width ? (y < height / 2 ? GLColor::green : GLColor::blue) : GLColor::red;
3120 }
3121 }
3122
3123 GLuint pbo;
3124 glGenBuffers(1, &pbo);
3125 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3126 glBufferData(GL_PIXEL_UNPACK_BUFFER, bufferSize * sizeof(GLColor), pixels.data(),
3127 GL_STATIC_DRAW);
3128
3129 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
3130
3131 // Initializes the texture from width x height of the PBO.
3132 glPixelStorei(GL_UNPACK_ROW_LENGTH, rowLength);
3133 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3134 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3135 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3136
3137 setUpProgram();
3138
3139 glUseProgram(mProgram);
3140 glUniform1i(mTexture2DUniformLocation, 0);
3141 drawQuad(mProgram, "position", 0.5f);
3142 glDeleteBuffers(1, &pbo);
3143 EXPECT_GL_NO_ERROR();
3144 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3145 EXPECT_PIXEL_COLOR_EQ(0, height - 1, GLColor::blue);
3146 }
3147
3148 // Test if the KHR debug label is set and passed to D3D correctly using glCopyTexImage2D.
TEST_P(Texture2DTest,TextureKHRDebugLabelWithCopyTexImage2D)3149 TEST_P(Texture2DTest, TextureKHRDebugLabelWithCopyTexImage2D)
3150 {
3151 GLTexture texture2D;
3152 glBindTexture(GL_TEXTURE_2D, texture2D);
3153
3154 // Create a texture and copy into, to initialize storage object.
3155 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 32, 32, 0);
3156
3157 // Set KHR Debug Label.
3158 std::string label = "TestKHR.DebugLabel";
3159 glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3160
3161 std::vector<char> labelBuf(label.length() + 1);
3162 GLsizei labelLengthBuf = 0;
3163
3164 glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3165 &labelLengthBuf, labelBuf.data());
3166
3167 EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
3168 EXPECT_STREQ(label.c_str(), labelBuf.data());
3169
3170 // Delete the texture.
3171 texture2D.reset();
3172 EXPECT_GL_NO_ERROR();
3173
3174 glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3175 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3176
3177 glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3178 &labelLengthBuf, labelBuf.data());
3179 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3180 }
3181
3182 // Test to call labeling API before the storage texture is created.
TEST_P(Texture2DTest,CallKHRDebugLabelBeforeTexStorageCreation)3183 TEST_P(Texture2DTest, CallKHRDebugLabelBeforeTexStorageCreation)
3184 {
3185 GLTexture texture2D;
3186 glBindTexture(GL_TEXTURE_2D, texture2D);
3187
3188 // Set label before texture storage creation.
3189 std::string label = "TestKHR.DebugLabel";
3190 glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3191
3192 // Create a texture and copy into, to initialize storage object.
3193 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 32, 32, 0);
3194
3195 std::vector<char> labelBuf(label.length() + 1);
3196 GLsizei labelLengthBuf = 0;
3197
3198 glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3199 &labelLengthBuf, labelBuf.data());
3200
3201 EXPECT_EQ(static_cast<GLsizei>(label.length()), labelLengthBuf);
3202 EXPECT_STREQ(label.c_str(), labelBuf.data());
3203
3204 // Delete the texture.
3205 texture2D.reset();
3206 EXPECT_GL_NO_ERROR();
3207
3208 glObjectLabelKHR(GL_TEXTURE, texture2D, -1, label.c_str());
3209 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3210
3211 glGetObjectLabelKHR(GL_TEXTURE, texture2D, static_cast<GLsizei>(labelBuf.size()),
3212 &labelLengthBuf, labelBuf.data());
3213 EXPECT_GL_ERROR(GL_INVALID_VALUE);
3214 }
3215
3216 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2D has
3217 // initialized the image with a depth-only format.
TEST_P(Texture2DTestES3,TexImageWithDepthPBO)3218 TEST_P(Texture2DTestES3, TexImageWithDepthPBO)
3219 {
3220 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3221 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3222
3223 // http://anglebug.com/5315
3224 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac());
3225
3226 constexpr GLsizei kSize = 4;
3227
3228 // Set up the framebuffer.
3229 GLTexture colorTexture;
3230 glBindTexture(GL_TEXTURE_2D, colorTexture);
3231 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3232 ASSERT_GL_NO_ERROR();
3233
3234 GLTexture depthTexture;
3235 glBindTexture(GL_TEXTURE_2D, depthTexture);
3236 glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT16, kSize, kSize);
3237 ASSERT_GL_NO_ERROR();
3238
3239 GLFramebuffer fbo;
3240 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3241 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3242 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
3243 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3244 ASSERT_GL_NO_ERROR();
3245
3246 // Clear depth to 0, ensuring the texture's image is allocated.
3247 glClearDepthf(0);
3248 glClearColor(0, 0, 0, 1);
3249 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3250 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3251
3252 // Fill depth with 1.0f.
3253 std::vector<GLushort> pixels(kSize * kSize);
3254 for (size_t pixelId = 0; pixelId < pixels.size(); ++pixelId)
3255 {
3256 pixels[pixelId] = 0xFFFF;
3257 }
3258
3259 GLuint pbo;
3260 glGenBuffers(1, &pbo);
3261 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3262 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(pixels[0]), pixels.data(),
3263 GL_STATIC_DRAW);
3264 ASSERT_GL_NO_ERROR();
3265
3266 // Upload PBO data.
3267 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,
3268 nullptr);
3269
3270 // If depth is not set to 1, rendering would fail.
3271 glEnable(GL_DEPTH_TEST);
3272 glDepthFunc(GL_LESS);
3273
3274 // Draw red
3275 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3276 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.95f);
3277 ASSERT_GL_NO_ERROR();
3278
3279 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
3280 }
3281
3282 // Test sampling modes with a DEPTH_COMPONENT16 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth16)3283 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth16)
3284 {
3285 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, false);
3286 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_STENCIL_INDEX, false);
3287 }
3288
3289 // Test sampling modes with a swizzled DEPTH_COMPONENT16 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth16Swizzled)3290 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth16Swizzled)
3291 {
3292 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, true);
3293 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT16, GL_STENCIL_INDEX, true);
3294 }
3295
3296 // Test sampling modes with a DEPTH_COMPONENT24 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24)3297 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24)
3298 {
3299 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, false);
3300 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_STENCIL_INDEX, false);
3301 }
3302
3303 // Test sampling modes with a swizzled DEPTH_COMPONENT24 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24Swizzled)3304 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24Swizzled)
3305 {
3306 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, true);
3307 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT24, GL_STENCIL_INDEX, true);
3308 }
3309
3310 // Test depth sampling with a DEPTH_COMPONENT32F texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32f)3311 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32f)
3312 {
3313 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, false);
3314 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_STENCIL_INDEX, false);
3315 }
3316
3317 // Test depth sampling with a swizzled DEPTH_COMPONENT32F texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32fSwizzled)3318 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32fSwizzled)
3319 {
3320 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, true);
3321 TestSampleWithDepthStencilMode(GL_DEPTH_COMPONENT32F, GL_STENCIL_INDEX, true);
3322 }
3323
3324 // Test sampling modes with a DEPTH24_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24Stencil8)3325 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24Stencil8)
3326 {
3327 TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_DEPTH_COMPONENT, false);
3328 TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_STENCIL_INDEX, false);
3329 }
3330
3331 // Test sampling modes with a swizzled DEPTH24_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth24Stencil8Swizzled)3332 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth24Stencil8Swizzled)
3333 {
3334 TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_DEPTH_COMPONENT, true);
3335 TestSampleWithDepthStencilMode(GL_DEPTH24_STENCIL8, GL_STENCIL_INDEX, true);
3336 }
3337
3338 // Test sampling modes with a DEPTH32F_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32fStencil8)3339 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32fStencil8)
3340 {
3341 TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_DEPTH_COMPONENT, false);
3342 TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_STENCIL_INDEX, false);
3343 }
3344
3345 // Test sampling modes with a swizzled DEPTH32F_STENCIL8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithDepth32fStencil8Swizzled)3346 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithDepth32fStencil8Swizzled)
3347 {
3348 TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_DEPTH_COMPONENT, true);
3349 TestSampleWithDepthStencilMode(GL_DEPTH32F_STENCIL8, GL_STENCIL_INDEX, true);
3350 }
3351
3352 // Test sampling modes with a STENCIL_INDEX8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithStencil8)3353 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithStencil8)
3354 {
3355 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_stencil8"));
3356 TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_DEPTH_COMPONENT, false);
3357 TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_STENCIL_INDEX, false);
3358 }
3359
3360 // Test sampling modes with a swizzled STENCIL_INDEX8 texture.
TEST_P(Texture2DDepthStencilTestES3,TexSampleModesWithStencil8Swizzled)3361 TEST_P(Texture2DDepthStencilTestES3, TexSampleModesWithStencil8Swizzled)
3362 {
3363 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_stencil8"));
3364 TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_DEPTH_COMPONENT, true);
3365 TestSampleWithDepthStencilMode(GL_STENCIL_INDEX8, GL_STENCIL_INDEX, true);
3366 }
3367
3368 // Test that updating a texture format triggers depth/stencil mode resync.
TEST_P(Texture2DDepthStencilTestES3,Redefinition)3369 TEST_P(Texture2DDepthStencilTestES3, Redefinition)
3370 {
3371 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_stencil_texturing"));
3372
3373 constexpr char kDepthFS[] =
3374 R"(#version 300 es
3375 precision mediump float;
3376 uniform highp sampler2D tex;
3377 out vec4 color;
3378 void main()
3379 {
3380 color = texture(tex, vec2(0, 0));
3381 })";
3382 ANGLE_GL_PROGRAM(programDepth, essl3_shaders::vs::Simple(), kDepthFS);
3383
3384 constexpr char kStencilFS[] =
3385 R"(#version 300 es
3386 precision mediump float;
3387 uniform highp usampler2D tex;
3388 out vec4 color;
3389 void main()
3390 {
3391 color = vec4(texelFetch(tex, ivec2(0, 0), 0)) / 255.0;
3392 })";
3393 ANGLE_GL_PROGRAM(programStencil, essl3_shaders::vs::Simple(), kStencilFS);
3394
3395 // Set up a D32F with stencil mode.
3396 GLTexture texture;
3397 glBindTexture(GL_TEXTURE_2D, texture);
3398 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3399 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3400 glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE_ANGLE, GL_STENCIL_INDEX);
3401
3402 const GLfloat d32f = 0.5f;
3403 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
3404 &d32f);
3405 ASSERT_GL_NO_ERROR();
3406
3407 drawQuad(programDepth, essl3_shaders::PositionAttrib(), 0.5f);
3408 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
3409
3410 // Redefine the same texture as D24S8
3411 const GLuint d24s8 = 0xC0;
3412 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 1, 1, 0, GL_DEPTH_STENCIL,
3413 GL_UNSIGNED_INT_24_8, &d24s8);
3414 ASSERT_GL_NO_ERROR();
3415
3416 drawQuad(programStencil, essl3_shaders::PositionAttrib(), 0.5f);
3417 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(192, 0, 0, 1), 1);
3418
3419 // Redefine the same texture as D16
3420 const GLushort d16 = 0x4000;
3421 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 1, 1, 0, GL_DEPTH_COMPONENT,
3422 GL_UNSIGNED_SHORT, &d16);
3423 ASSERT_GL_NO_ERROR();
3424
3425 drawQuad(programDepth, essl3_shaders::PositionAttrib(), 0.5f);
3426 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(64, 0, 0, 255), 1);
3427 }
3428
3429 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2D has
3430 // initialized the image with a stencil-only format.
TEST_P(Texture2DTestES3,TexImageWithStencilPBO)3431 TEST_P(Texture2DTestES3, TexImageWithStencilPBO)
3432 {
3433 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3434 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3435
3436 // http://anglebug.com/5315
3437 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac());
3438
3439 constexpr GLsizei kSize = 4;
3440
3441 // Set up the framebuffer.
3442 GLTexture colorTexture;
3443 glBindTexture(GL_TEXTURE_2D, colorTexture);
3444 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3445 ASSERT_GL_NO_ERROR();
3446
3447 GLTexture stencilTexture;
3448 glBindTexture(GL_TEXTURE_2D, stencilTexture);
3449 glTexStorage2D(GL_TEXTURE_2D, 1, GL_STENCIL_INDEX8, kSize, kSize);
3450 ASSERT_GL_NO_ERROR();
3451
3452 GLFramebuffer fbo;
3453 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3454 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3455 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, stencilTexture, 0);
3456 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3457 ASSERT_GL_NO_ERROR();
3458
3459 // Clear stencil to 0, ensuring the texture's image is allocated.
3460 glClearStencil(0);
3461 glClearColor(0, 0, 0, 1);
3462 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3463 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3464
3465 // Fill stencil with 0x4E
3466 std::vector<GLubyte> pixels(kSize * kSize);
3467 for (size_t pixelId = 0; pixelId < pixels.size(); ++pixelId)
3468 {
3469 pixels[pixelId] = 0x4E;
3470 }
3471
3472 GLuint pbo;
3473 glGenBuffers(1, &pbo);
3474 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3475 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(pixels[0]), pixels.data(),
3476 GL_STATIC_DRAW);
3477 ASSERT_GL_NO_ERROR();
3478
3479 // Upload PBO data.
3480 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
3481 nullptr);
3482 ASSERT_GL_NO_ERROR();
3483
3484 // If stencil is not set to 0x4E, rendering would fail.
3485 glEnable(GL_STENCIL_TEST);
3486 glStencilFunc(GL_EQUAL, 0x4E, 0xFF);
3487 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3488 glStencilMask(0xFF);
3489
3490 // Draw red
3491 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3492 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.95f);
3493 ASSERT_GL_NO_ERROR();
3494
3495 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
3496 }
3497
3498 // Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2D has
3499 // initialized the image with a depth/stencil format.
TEST_P(Texture2DTestES3,TexImageWithDepthStencilPBO)3500 TEST_P(Texture2DTestES3, TexImageWithDepthStencilPBO)
3501 {
3502 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
3503 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
3504
3505 // http://anglebug.com/5315
3506 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac());
3507
3508 constexpr GLsizei kSize = 4;
3509
3510 // Set up the framebuffer.
3511 GLTexture colorTexture;
3512 glBindTexture(GL_TEXTURE_2D, colorTexture);
3513 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3514 ASSERT_GL_NO_ERROR();
3515
3516 GLTexture depthStencilTexture;
3517 glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
3518 glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
3519 ASSERT_GL_NO_ERROR();
3520
3521 GLFramebuffer fbo;
3522 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3523 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3524 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
3525 depthStencilTexture, 0);
3526 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3527 ASSERT_GL_NO_ERROR();
3528
3529 // Clear depth and stencil to 0, ensuring the texture's image is allocated.
3530 glClearDepthf(0);
3531 glClearStencil(0);
3532 glClearColor(0, 0, 0, 1);
3533 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3534 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3535
3536 // Fill depth with 1.0f and stencil with 0xD5
3537 std::vector<GLuint> pixels(kSize * kSize);
3538 for (size_t pixelId = 0; pixelId < pixels.size(); ++pixelId)
3539 {
3540 pixels[pixelId] = 0xFFFFFFD5;
3541 }
3542
3543 GLuint pbo;
3544 glGenBuffers(1, &pbo);
3545 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
3546 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(pixels[0]), pixels.data(),
3547 GL_STATIC_DRAW);
3548 ASSERT_GL_NO_ERROR();
3549
3550 // Upload PBO data.
3551 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8,
3552 nullptr);
3553
3554 // If depth is not set to 1, rendering would fail.
3555 glEnable(GL_DEPTH_TEST);
3556 glDepthFunc(GL_LESS);
3557
3558 // If stencil is not set to 0xD5, rendering would fail.
3559 glEnable(GL_STENCIL_TEST);
3560 glStencilFunc(GL_EQUAL, 0xD5, 0xFF);
3561 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3562 glStencilMask(0xFF);
3563
3564 // Draw red
3565 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3566 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.95f);
3567 ASSERT_GL_NO_ERROR();
3568
3569 EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
3570 }
3571
3572 // Test that the driver performs a flush when there is a large amount of image updates.
TEST_P(Texture2DMemoryTestES3,TextureDataInLoopUntilFlush)3573 TEST_P(Texture2DMemoryTestES3, TextureDataInLoopUntilFlush)
3574 {
3575 // Run this test for Vulkan only.
3576 ANGLE_SKIP_TEST_IF(!IsVulkan());
3577
3578 // If VK_EXT_host_image_copy is used, uploads will all be done on the CPU and there would be no
3579 // submissions.
3580 ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::SupportsHostImageCopy));
3581
3582 uint64_t expectedSubmitCalls = getPerfCounters().commandQueueSubmitCallsTotal + 1;
3583
3584 // Set up program
3585 const char *kFS = R"(#version 300 es
3586 precision highp float;
3587 uniform uni { vec4 color; };
3588 out vec4 fragColor;
3589 void main()
3590 {
3591 fragColor = color;
3592 })";
3593 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3594 ASSERT_NE(program, 0u);
3595
3596 // Set up the uniform buffer and framebuffer
3597 GLint uniformBufferIndex;
3598 uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
3599 ASSERT_NE(uniformBufferIndex, -1);
3600
3601 glClear(GL_COLOR_BUFFER_BIT);
3602 constexpr size_t kBufferSize = 4 * 1024 * 1024;
3603 std::vector<float> floatData;
3604 floatData.resize(kBufferSize / (sizeof(float)), 0.0f);
3605 floatData[0] = 0.5f;
3606 floatData[1] = 0.75f;
3607 floatData[2] = 0.25f;
3608 floatData[3] = 1.0f;
3609
3610 GLBuffer uniformBuffer;
3611 glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
3612 glBufferData(GL_UNIFORM_BUFFER, kBufferSize, floatData.data(), GL_STATIC_DRAW);
3613 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
3614 glUniformBlockBinding(program, uniformBufferIndex, 0);
3615
3616 GLFramebuffer fbo;
3617 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3618
3619 // Create textures and draw
3620 constexpr uint32_t kTextureWidth = 512;
3621 constexpr uint32_t kTextureHeight = 512;
3622 std::vector<GLColor> textureColor(kTextureWidth * kTextureHeight, GLColor::red);
3623 constexpr uint32_t kIterationCount = 4096;
3624 GLTexture textures[kIterationCount];
3625
3626 for (auto &texture : textures)
3627 {
3628 glBindTexture(GL_TEXTURE_2D, texture);
3629 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTextureWidth, kTextureHeight);
3630 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RGBA,
3631 GL_UNSIGNED_BYTE, textureColor.data());
3632
3633 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3634 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3635 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3636
3637 if (getPerfCounters().commandQueueSubmitCallsTotal == expectedSubmitCalls)
3638 {
3639 break;
3640 }
3641 }
3642 EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedSubmitCalls);
3643 ASSERT_GL_NO_ERROR();
3644 EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
3645 }
3646
3647 // Creating a texture and drawing with it in a loop without glFlush() should still work. Driver is
3648 // supposedly to issue flush if needed. There should be no fallbacks to allocate outside the device
3649 // memory.
TEST_P(Texture2DMemoryTestES3,TextureDataInLoopManyTimes)3650 TEST_P(Texture2DMemoryTestES3, TextureDataInLoopManyTimes)
3651 {
3652 // Run this test for Vulkan only.
3653 ANGLE_SKIP_TEST_IF(!IsVulkan());
3654 uint64_t expectedSubmitCalls = getPerfCounters().commandQueueSubmitCallsTotal + 1;
3655 uint64_t expectedDeviceMemoryFallbacks = getPerfCounters().deviceMemoryImageAllocationFallbacks;
3656
3657 // Set up program
3658 const char *kFS = R"(#version 300 es
3659 precision highp float;
3660 uniform uni { vec4 color; };
3661 out vec4 fragColor;
3662 void main()
3663 {
3664 fragColor = color;
3665 })";
3666 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3667 ASSERT_NE(program, 0u);
3668
3669 // Set up the uniform buffer and framebuffer
3670 GLint uniformBufferIndex;
3671 uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
3672 ASSERT_NE(uniformBufferIndex, -1);
3673
3674 glClear(GL_COLOR_BUFFER_BIT);
3675 constexpr size_t kBufferSize = 4 * 1024 * 1024;
3676 std::vector<float> floatData;
3677 floatData.resize(kBufferSize / (sizeof(float)), 0.0f);
3678 floatData[0] = 0.5f;
3679 floatData[1] = 0.75f;
3680 floatData[2] = 0.25f;
3681 floatData[3] = 1.0f;
3682
3683 GLBuffer uniformBuffer;
3684 glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
3685 glBufferData(GL_UNIFORM_BUFFER, kBufferSize, floatData.data(), GL_STATIC_DRAW);
3686 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
3687 glUniformBlockBinding(program, uniformBufferIndex, 0);
3688
3689 GLFramebuffer fbo;
3690 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3691
3692 // Create textures and draw. We will use very small image updates to prevent flush before the
3693 // device runs out of memory.
3694 constexpr uint32_t kTextureWidth = 4096;
3695 constexpr uint32_t kTextureHeight = 4096;
3696 std::vector<GLColor> textureColor(kTextureWidth * kTextureHeight, GLColor::red);
3697 constexpr uint32_t kIterationCount = 4096;
3698
3699 for (uint32_t i = 0; i < kIterationCount; i++)
3700 {
3701 GLTexture texture;
3702 glBindTexture(GL_TEXTURE_2D, texture);
3703 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureWidth, kTextureHeight, 0, GL_RGBA,
3704 GL_UNSIGNED_BYTE, nullptr);
3705 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
3706 textureColor.data());
3707
3708 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3709 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3710 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3711
3712 if (getPerfCounters().commandQueueSubmitCallsTotal == expectedSubmitCalls)
3713 {
3714 break;
3715 }
3716 }
3717 EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedSubmitCalls);
3718 EXPECT_EQ(getPerfCounters().deviceMemoryImageAllocationFallbacks,
3719 expectedDeviceMemoryFallbacks);
3720 ASSERT_GL_NO_ERROR();
3721 }
3722
3723 // Test functionality of GL_ANGLE_yuv_internal_format with min/mag filters
3724 // set to nearest and linear modes.
TEST_P(Texture2DTestES3YUV,TexStorage2DYuvFilterModes)3725 TEST_P(Texture2DTestES3YUV, TexStorage2DYuvFilterModes)
3726 {
3727 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3728
3729 // Create YUV texture
3730 GLTexture yuvTexture;
3731 GLubyte yuvColor[] = {40, 40, 40, 40, 40, 40, 40, 40, 240, 109, 240, 109};
3732 GLubyte expectedRgbColor[] = {0, 0, 255, 255};
3733 createImmutableTexture2D(yuvTexture, 2, 4, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3734 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor);
3735
3736 // Default is nearest filter mode
3737 verifyResults2D(yuvTexture, expectedRgbColor);
3738 ASSERT_GL_NO_ERROR();
3739
3740 // Enable linear filter mode
3741 glBindTexture(GL_TEXTURE_2D, yuvTexture);
3742 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3743 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3744 verifyResults2D(yuvTexture, expectedRgbColor);
3745 ASSERT_GL_NO_ERROR();
3746
3747 const int windowHeight = getWindowHeight();
3748 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::blue, 1);
3749 EXPECT_PIXEL_COLOR_NEAR(0, windowHeight - 1, GLColor::blue, 1);
3750 EXPECT_PIXEL_COLOR_NEAR(0, windowHeight / 2, GLColor::blue, 1);
3751 }
3752
3753 // Test functionality of GL_ANGLE_yuv_internal_format while cycling through RGB and YUV sources
TEST_P(Texture2DTestES3,TexStorage2DCycleThroughYuvAndRgbSources)3754 TEST_P(Texture2DTestES3, TexStorage2DCycleThroughYuvAndRgbSources)
3755 {
3756 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3757
3758 // Create YUV texture
3759 GLTexture yuvTexture;
3760 GLubyte yuvColor[6] = {40, 40, 40, 40, 240, 109};
3761 GLubyte expectedRgbColor[4] = {0, 0, 255, 255};
3762 createImmutableTexture2D(yuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3763 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor);
3764
3765 // Create RGBA texture
3766 GLTexture rgbaTexture;
3767 GLubyte rgbaColor[4] = {0, 0, 255, 255};
3768 createImmutableTexture2D(rgbaTexture, 1, 1, GL_RGBA, GL_RGBA8, GL_UNSIGNED_BYTE, 1, rgbaColor);
3769
3770 // Cycle through source textures
3771 // RGBA source
3772 verifyResults2D(rgbaTexture, rgbaColor);
3773 ASSERT_GL_NO_ERROR();
3774
3775 // YUV source
3776 verifyResults2D(yuvTexture, expectedRgbColor);
3777 ASSERT_GL_NO_ERROR();
3778
3779 // RGBA source
3780 verifyResults2D(rgbaTexture, rgbaColor);
3781 ASSERT_GL_NO_ERROR();
3782 }
3783
3784 // Test functionality of GL_ANGLE_yuv_internal_format with large number of YUV sources
TEST_P(Texture2DTestES3,TexStorage2DLargeYuvTextureCount)3785 TEST_P(Texture2DTestES3, TexStorage2DLargeYuvTextureCount)
3786 {
3787 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3788
3789 constexpr uint32_t kTextureCount = 16;
3790
3791 // Create YUV texture
3792 GLTexture yuvTexture[kTextureCount];
3793 for (uint32_t i = 0; i < kTextureCount; i++)
3794 {
3795 // Create 2 plane YCbCr 420 texture
3796 createImmutableTexture2D(yuvTexture[i], 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3797 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3798 }
3799
3800 // Cycle through YUV source textures
3801 glUseProgram(mProgram);
3802 glUniform1i(mTexture2DUniformLocation, 0);
3803
3804 for (uint32_t i = 0; i < kTextureCount; i++)
3805 {
3806 glBindTexture(GL_TEXTURE_2D, yuvTexture[i]);
3807 drawQuad(mProgram, "position", 0.5f);
3808 ASSERT_GL_NO_ERROR();
3809 }
3810 }
3811
3812 // Test functionality of GL_ANGLE_yuv_internal_format with simultaneous use of multiple YUV sources
TEST_P(Texture2DTestES3,TexStorage2DSimultaneousUseOfMultipleYuvSourcesNoData)3813 TEST_P(Texture2DTestES3, TexStorage2DSimultaneousUseOfMultipleYuvSourcesNoData)
3814 {
3815 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3816
3817 // Create YUV texture
3818 // Create 2 plane YCbCr 420 texture
3819 GLTexture twoPlaneYuvTexture;
3820 createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3821 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3822
3823 // Create 3 plane YCbCr 420 texture
3824 GLTexture threePlaneYuvTexture;
3825 createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
3826 GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3827
3828 // Cycle through YUV source textures
3829 // Create program with 2 samplers
3830 const char *vertexShaderSource = getVertexShaderSource();
3831 const char *fragmentShaderSource = R"(#version 300 es
3832 precision highp float;
3833 uniform sampler2D tex0;
3834 uniform sampler2D tex1;
3835 in vec2 texcoord;
3836 out vec4 fragColor;
3837
3838 void main()
3839 {
3840 vec4 color0 = texture(tex0, texcoord);
3841 vec4 color1 = texture(tex1, texcoord);
3842 fragColor = color0 + color1;
3843 })";
3844
3845 ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource);
3846 glUseProgram(twoSamplersProgram);
3847 GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0");
3848 ASSERT_NE(-1, tex0Location);
3849 GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1");
3850 ASSERT_NE(-1, tex1Location);
3851
3852 glUniform1i(tex0Location, 0);
3853 glUniform1i(tex1Location, 1);
3854
3855 // Bind 2 plane YUV source
3856 glActiveTexture(GL_TEXTURE0);
3857 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
3858 ASSERT_GL_NO_ERROR();
3859
3860 // Bind 3 plane YUV source
3861 glActiveTexture(GL_TEXTURE1);
3862 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
3863 ASSERT_GL_NO_ERROR();
3864
3865 drawQuad(twoSamplersProgram, "position", 0.5f);
3866 ASSERT_GL_NO_ERROR();
3867
3868 // Switch active texture index and draw again
3869 // Bind 2 plane YUV source
3870 glActiveTexture(GL_TEXTURE1);
3871 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
3872 ASSERT_GL_NO_ERROR();
3873
3874 // Bind 3 plane YUV source
3875 glActiveTexture(GL_TEXTURE0);
3876 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
3877 ASSERT_GL_NO_ERROR();
3878
3879 drawQuad(twoSamplersProgram, "position", 0.5f);
3880 ASSERT_GL_NO_ERROR();
3881 }
3882
3883 // Test functional of GL_ANGLE_yuv_internal_format while cycling through YUV sources
TEST_P(Texture2DTestES3,TexStorage2DCycleThroughYuvSourcesNoData)3884 TEST_P(Texture2DTestES3, TexStorage2DCycleThroughYuvSourcesNoData)
3885 {
3886 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3887
3888 // Create YUV texture
3889 // Create 2 plane YCbCr 420 texture
3890 GLTexture twoPlaneYuvTexture;
3891 createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3892 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3893
3894 // Create 3 plane YCbCr 420 texture
3895 GLTexture threePlaneYuvTexture;
3896 createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
3897 GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3898
3899 // Cycle through YUV source textures
3900 glUseProgram(mProgram);
3901 glUniform1i(mTexture2DUniformLocation, 0);
3902
3903 // 2 plane YUV source
3904 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
3905 drawQuad(mProgram, "position", 0.5f);
3906 ASSERT_GL_NO_ERROR();
3907
3908 // 3 plane YUV source
3909 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
3910 drawQuad(mProgram, "position", 0.5f);
3911 ASSERT_GL_NO_ERROR();
3912
3913 // 2 plane YUV source
3914 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
3915 drawQuad(mProgram, "position", 0.5f);
3916 ASSERT_GL_NO_ERROR();
3917 }
3918
3919 // Test functionality of GL_ANGLE_yuv_internal_format with multiple YUV samplers while
3920 // switching sampler uniform values.
TEST_P(Texture2DTestES3,TexStorage2DMultipleYuvSamplersSwitchSamplerUniformValues)3921 TEST_P(Texture2DTestES3, TexStorage2DMultipleYuvSamplersSwitchSamplerUniformValues)
3922 {
3923 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
3924
3925 // Create YUV texture
3926 GLTexture yuvTexture;
3927 GLubyte yuvColor[6] = {40, 40, 40, 40, 240, 109};
3928 GLubyte expectedRgbColor[4] = {0, 0, 255, 255};
3929
3930 // Create YUV texture
3931 // Create 2 plane YCbCr 420 texture
3932 GLTexture twoPlaneYuvTexture;
3933 createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3934 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor);
3935 // Create 3 plane YCbCr 420 texture
3936 GLTexture threePlaneYuvTexture;
3937 createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
3938 GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
3939 // Create program with 2 samplers
3940 const char *vertexShaderSource = getVertexShaderSource();
3941 const char *fragmentShaderSource = R"(#version 300 es
3942 precision highp float;
3943 uniform sampler2D tex0;
3944 uniform sampler2D tex1;
3945 uniform int texIndex;
3946 in vec2 texcoord;
3947 out vec4 fragColor;
3948 void main()
3949 {
3950 vec4 color0 = texture(tex0, texcoord);
3951 vec4 color1 = texture(tex1, texcoord);
3952 if (texIndex == 0)
3953 {
3954 fragColor = color0;
3955 }
3956 else
3957 {
3958 fragColor = color1;
3959 }
3960 })";
3961 ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource);
3962 glUseProgram(twoSamplersProgram);
3963 GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0");
3964 ASSERT_NE(-1, tex0Location);
3965 GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1");
3966 ASSERT_NE(-1, tex1Location);
3967 GLint texIndexLocation = glGetUniformLocation(twoSamplersProgram, "texIndex");
3968 ASSERT_NE(-1, texIndexLocation);
3969 // Bind 2 plane YUV source
3970 glActiveTexture(GL_TEXTURE0);
3971 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
3972 ASSERT_GL_NO_ERROR();
3973 // Bind 3 plane YUV source
3974 glActiveTexture(GL_TEXTURE1);
3975 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
3976 ASSERT_GL_NO_ERROR();
3977
3978 // Set sampler uniform values and draw
3979 glUniform1i(tex0Location, 0);
3980 glUniform1i(tex1Location, 1);
3981 // Set texture index selector to the 2 plane texture unit
3982 glUniform1i(texIndexLocation, 0);
3983 drawQuad(twoSamplersProgram, "position", 0.5f);
3984 ASSERT_GL_NO_ERROR();
3985 EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
3986 expectedRgbColor[3], 1);
3987 ASSERT_GL_NO_ERROR();
3988
3989 // Switch sampler uniform values and draw
3990 glUniform1i(tex0Location, 1);
3991 glUniform1i(tex1Location, 0);
3992 // Set texture index selector to the 2 plane texture unit
3993 glUniform1i(texIndexLocation, 1);
3994 drawQuad(twoSamplersProgram, "position", 0.5f);
3995 ASSERT_GL_NO_ERROR();
3996 EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
3997 expectedRgbColor[3], 1);
3998 ASSERT_GL_NO_ERROR();
3999
4000 // Switch back sampler uniform values and draw
4001 glUniform1i(tex0Location, 0);
4002 glUniform1i(tex1Location, 1);
4003 // Set texture index selector to the 2 plane texture unit
4004 glUniform1i(texIndexLocation, 0);
4005 drawQuad(twoSamplersProgram, "position", 0.5f);
4006 ASSERT_GL_NO_ERROR();
4007 EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
4008 expectedRgbColor[3], 1);
4009 ASSERT_GL_NO_ERROR();
4010 }
4011
4012 // Test functionality of GL_ANGLE_yuv_internal_format with multiple YUV samplers while
4013 // switching bound textures.
TEST_P(Texture2DTestES3,TexStorage2DMultipleYuvSamplersSwitchBoundTextures)4014 TEST_P(Texture2DTestES3, TexStorage2DMultipleYuvSamplersSwitchBoundTextures)
4015 {
4016 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_yuv_internal_format"));
4017
4018 // Create YUV texture
4019 GLTexture yuvTexture;
4020 GLubyte yuvColor[6] = {40, 40, 40, 40, 240, 109};
4021 GLubyte expectedRgbColor[4] = {0, 0, 255, 255};
4022
4023 // Create YUV texture
4024 // Create 2 plane YCbCr 420 texture
4025 GLTexture twoPlaneYuvTexture;
4026 createImmutableTexture2D(twoPlaneYuvTexture, 2, 2, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
4027 GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, yuvColor);
4028 // Create 3 plane YCbCr 420 texture
4029 GLTexture threePlaneYuvTexture;
4030 createImmutableTexture2D(threePlaneYuvTexture, 2, 2, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
4031 GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, 1, nullptr);
4032 // Create program with 2 samplers
4033 const char *vertexShaderSource = getVertexShaderSource();
4034 const char *fragmentShaderSource = R"(#version 300 es
4035 precision highp float;
4036 uniform sampler2D tex0;
4037 uniform sampler2D tex1;
4038 uniform int texIndex;
4039 in vec2 texcoord;
4040 out vec4 fragColor;
4041 void main()
4042 {
4043 vec4 color0 = texture(tex0, texcoord);
4044 vec4 color1 = texture(tex1, texcoord);
4045 if (texIndex == 0)
4046 {
4047 fragColor = color0;
4048 }
4049 else
4050 {
4051 fragColor = color1;
4052 }
4053 })";
4054 ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource);
4055 glUseProgram(twoSamplersProgram);
4056 GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0");
4057 ASSERT_NE(-1, tex0Location);
4058 GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1");
4059 ASSERT_NE(-1, tex1Location);
4060 GLint texIndexLocation = glGetUniformLocation(twoSamplersProgram, "texIndex");
4061 ASSERT_NE(-1, texIndexLocation);
4062 // Set sampler uniform values
4063 glUniform1i(tex0Location, 0);
4064 glUniform1i(tex1Location, 1);
4065
4066 // Bind 2 plane YUV source
4067 glActiveTexture(GL_TEXTURE0);
4068 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
4069 ASSERT_GL_NO_ERROR();
4070 // Bind 3 plane YUV source
4071 glActiveTexture(GL_TEXTURE1);
4072 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
4073 ASSERT_GL_NO_ERROR();
4074 // Set texture index selector to the 2 plane texture unit
4075 glUniform1i(texIndexLocation, 0);
4076 // Draw
4077 drawQuad(twoSamplersProgram, "position", 0.5f);
4078 ASSERT_GL_NO_ERROR();
4079 EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
4080 expectedRgbColor[3], 1);
4081 ASSERT_GL_NO_ERROR();
4082
4083 // Bind 3 plane YUV source
4084 glActiveTexture(GL_TEXTURE0);
4085 glBindTexture(GL_TEXTURE_2D, threePlaneYuvTexture);
4086 ASSERT_GL_NO_ERROR();
4087 // Bind 2 plane YUV source
4088 glActiveTexture(GL_TEXTURE1);
4089 glBindTexture(GL_TEXTURE_2D, twoPlaneYuvTexture);
4090 ASSERT_GL_NO_ERROR();
4091 // Set texture index selector to the 2 plane texture unit
4092 glUniform1i(texIndexLocation, 1);
4093 // Draw
4094 drawQuad(twoSamplersProgram, "position", 0.5f);
4095 ASSERT_GL_NO_ERROR();
4096 EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
4097 expectedRgbColor[3], 1);
4098 ASSERT_GL_NO_ERROR();
4099 }
4100
4101 // Tests CopySubImage for float formats
TEST_P(Texture2DTest,CopySubImageFloat_R_R)4102 TEST_P(Texture2DTest, CopySubImageFloat_R_R)
4103 {
4104 testFloatCopySubImage(1, 1);
4105 }
4106
TEST_P(Texture2DTest,CopySubImageFloat_RG_R)4107 TEST_P(Texture2DTest, CopySubImageFloat_RG_R)
4108 {
4109 testFloatCopySubImage(2, 1);
4110 }
4111
TEST_P(Texture2DTest,CopySubImageFloat_RG_RG)4112 TEST_P(Texture2DTest, CopySubImageFloat_RG_RG)
4113 {
4114 testFloatCopySubImage(2, 2);
4115 }
4116
TEST_P(Texture2DTest,CopySubImageFloat_RGB_R)4117 TEST_P(Texture2DTest, CopySubImageFloat_RGB_R)
4118 {
4119 testFloatCopySubImage(3, 1);
4120 }
4121
TEST_P(Texture2DTest,CopySubImageFloat_RGB_RG)4122 TEST_P(Texture2DTest, CopySubImageFloat_RGB_RG)
4123 {
4124 testFloatCopySubImage(3, 2);
4125 }
4126
TEST_P(Texture2DTest,CopySubImageFloat_RGB_RGB)4127 TEST_P(Texture2DTest, CopySubImageFloat_RGB_RGB)
4128 {
4129 // TODO(cwallez): Fix on Linux Intel drivers (http://anglebug.com/1346)
4130 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4131
4132 testFloatCopySubImage(3, 3);
4133 }
4134
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_R)4135 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_R)
4136 {
4137 testFloatCopySubImage(4, 1);
4138 }
4139
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_RG)4140 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RG)
4141 {
4142 testFloatCopySubImage(4, 2);
4143 }
4144
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_RGB)4145 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGB)
4146 {
4147 testFloatCopySubImage(4, 3);
4148 }
4149
TEST_P(Texture2DTest,CopySubImageFloat_RGBA_RGBA)4150 TEST_P(Texture2DTest, CopySubImageFloat_RGBA_RGBA)
4151 {
4152 testFloatCopySubImage(4, 4);
4153 }
4154
4155 // Port of
4156 // https://www.khronos.org/registry/webgl/conformance-suites/1.0.3/conformance/textures/texture-npot.html
4157 // Run against GL_ALPHA/UNSIGNED_BYTE format, to ensure that D3D11 Feature Level 9_3 correctly
4158 // handles GL_ALPHA
TEST_P(Texture2DTest,TextureNPOT_GL_ALPHA_UBYTE)4159 TEST_P(Texture2DTest, TextureNPOT_GL_ALPHA_UBYTE)
4160 {
4161 const int npotTexSize = 5;
4162 const int potTexSize = 4; // Should be less than npotTexSize
4163 GLTexture tex2D;
4164
4165 if (IsGLExtensionEnabled("GL_OES_texture_npot"))
4166 {
4167 // This test isn't applicable if texture_npot is enabled
4168 return;
4169 }
4170
4171 setUpProgram();
4172
4173 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4174
4175 // Default unpack alignment is 4. The values of 'pixels' below needs it to be 1.
4176 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
4177
4178 glActiveTexture(GL_TEXTURE0);
4179 glBindTexture(GL_TEXTURE_2D, tex2D);
4180
4181 const std::vector<GLubyte> pixels(1 * npotTexSize * npotTexSize, 64);
4182
4183 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4184 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4185
4186 // Check that an NPOT texture not on level 0 generates INVALID_VALUE
4187 glTexImage2D(GL_TEXTURE_2D, 1, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA,
4188 GL_UNSIGNED_BYTE, pixels.data());
4189 EXPECT_GL_ERROR(GL_INVALID_VALUE);
4190
4191 // Check that an NPOT texture on level 0 succeeds
4192 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA,
4193 GL_UNSIGNED_BYTE, pixels.data());
4194 EXPECT_GL_NO_ERROR();
4195
4196 // Check that generateMipmap fails on NPOT
4197 glGenerateMipmap(GL_TEXTURE_2D);
4198 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4199
4200 // Check that nothing is drawn if filtering is not correct for NPOT
4201 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4202 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4203 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
4204 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
4205 glClear(GL_COLOR_BUFFER_BIT);
4206 drawQuad(mProgram, "position", 1.0f);
4207 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
4208
4209 // NPOT texture with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255
4210 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4211 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
4213 glClear(GL_COLOR_BUFFER_BIT);
4214 drawQuad(mProgram, "position", 1.0f);
4215 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
4216
4217 // NPOT texture with TEXTURE_MIN_FILTER set to LINEAR should draw
4218 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4219 glClear(GL_COLOR_BUFFER_BIT);
4220 drawQuad(mProgram, "position", 1.0f);
4221 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
4222
4223 // Check that glTexImage2D for POT texture succeeds
4224 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, potTexSize, potTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE,
4225 pixels.data());
4226 EXPECT_GL_NO_ERROR();
4227
4228 // Check that generateMipmap for an POT texture succeeds
4229 glGenerateMipmap(GL_TEXTURE_2D);
4230 EXPECT_GL_NO_ERROR();
4231
4232 // POT texture with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw
4233 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
4234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
4236 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
4237 glClear(GL_COLOR_BUFFER_BIT);
4238 drawQuad(mProgram, "position", 1.0f);
4239 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
4240 EXPECT_GL_NO_ERROR();
4241 }
4242
4243 // Test to ensure that glTexSubImage2D always accepts data for non-power-of-two subregions.
4244 // ANGLE previously rejected this if GL_OES_texture_npot wasn't active, which is incorrect.
TEST_P(Texture2DTest,NPOTSubImageParameters)4245 TEST_P(Texture2DTest, NPOTSubImageParameters)
4246 {
4247 glActiveTexture(GL_TEXTURE0);
4248 glBindTexture(GL_TEXTURE_2D, mTexture2D);
4249
4250 // Create an 8x8 (i.e. power-of-two) texture.
4251 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4252 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4253 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4254 glGenerateMipmap(GL_TEXTURE_2D);
4255
4256 // Supply a 3x3 (i.e. non-power-of-two) subimage to the texture.
4257 // This should always work, even if GL_OES_texture_npot isn't active.
4258 std::array<GLColor, 3 * 3> data;
4259 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 3, 3, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
4260
4261 EXPECT_GL_NO_ERROR();
4262 }
4263
4264 // Regression test for https://crbug.com/1222516 to prevent integer overflow during validation.
TEST_P(Texture2DTest,SubImageValidationOverflow)4265 TEST_P(Texture2DTest, SubImageValidationOverflow)
4266 {
4267 glActiveTexture(GL_TEXTURE0);
4268 glBindTexture(GL_TEXTURE_2D, mTexture2D);
4269
4270 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4271 EXPECT_GL_NO_ERROR();
4272
4273 glTexSubImage2D(GL_TEXTURE_2D, 0, -4, 0, 2147483647, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4274 EXPECT_GL_ERROR(GL_INVALID_VALUE);
4275
4276 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, -4, 1, 2147483647, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4277 EXPECT_GL_ERROR(GL_INVALID_VALUE);
4278 }
4279
4280 // Test that when a mutable texture is deleted, its corresponding pointer in the Vulkan backend,
4281 // which is used for mutable texture flushing, is also deleted, and is not accessed by the new
4282 // mutable texture after it.
TEST_P(Texture2DTest,MutableUploadThenDeleteThenMutableUpload)4283 TEST_P(Texture2DTest, MutableUploadThenDeleteThenMutableUpload)
4284 {
4285 GLTexture texture1;
4286 glBindTexture(GL_TEXTURE_2D, texture1);
4287 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4288 GLColor::red.data());
4289 texture1.reset();
4290 EXPECT_GL_NO_ERROR();
4291
4292 GLTexture texture2;
4293 glBindTexture(GL_TEXTURE_2D, texture2);
4294 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4295 GLColor::green.data());
4296 texture2.reset();
4297 EXPECT_GL_NO_ERROR();
4298 }
4299
4300 // Test to ensure that glTexStorage3D accepts ASTC sliced 3D. https://crbug.com/1060012
TEST_P(Texture3DTestES3,ImmutableASTCSliced3D)4301 TEST_P(Texture3DTestES3, ImmutableASTCSliced3D)
4302 {
4303 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_texture_compression_astc_sliced_3d"));
4304
4305 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4306 glTexStorage3D(GL_TEXTURE_3D, 1, GL_COMPRESSED_RGBA_ASTC_4x4, 4, 4, 1);
4307 EXPECT_GL_NO_ERROR();
4308 }
4309
FillLevel(GLint level,GLuint width,GLuint height,const GLColor & color,bool cubemap,bool subTex)4310 void FillLevel(GLint level,
4311 GLuint width,
4312 GLuint height,
4313 const GLColor &color,
4314 bool cubemap,
4315 bool subTex)
4316 {
4317 std::vector<GLColor> pixels(width * height, color);
4318 std::vector<GLenum> targets;
4319 if (cubemap)
4320 {
4321 targets = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
4322 GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
4323 GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
4324 }
4325 else
4326 {
4327 targets = {GL_TEXTURE_2D};
4328 }
4329
4330 for (GLenum target : targets)
4331 {
4332 if (subTex)
4333 {
4334 glTexSubImage2D(target, level, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
4335 pixels.data());
4336 }
4337 else
4338 {
4339 glTexImage2D(target, level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4340 pixels.data());
4341 }
4342 }
4343 }
4344
4345 // This is part of tests that webgl_conformance_vulkan_passthrough_tests
4346 // conformance/textures/misc/texture-size.html does
testTextureSize(int testCaseIndex)4347 void Texture2DTest::testTextureSize(int testCaseIndex)
4348 {
4349 std::array<GLColor, 6> kNewMipColors = {
4350 GLColor::green, GLColor::red, GLColor::blue,
4351 GLColor::yellow, GLColor::magenta, GLColor::cyan,
4352 };
4353 GLuint colorCount = 0;
4354
4355 setUpProgram();
4356
4357 constexpr char kVS[] =
4358 R"(precision highp float;
4359 attribute vec4 position;
4360 varying vec3 texcoord;
4361 void main()
4362 {
4363 gl_Position = position;
4364 texcoord = (position.xyz * 0.5) + 0.5;
4365 }
4366 )";
4367 constexpr char kFS[] =
4368 R"(precision mediump float;
4369 uniform samplerCube tex;
4370 varying vec3 texcoord;
4371 void main()
4372 {
4373 gl_FragColor = textureCube(tex, texcoord);
4374 })";
4375 ANGLE_GL_PROGRAM(programCubeMap, kVS, kFS);
4376 GLint textureCubeUniformLocation = glGetUniformLocation(programCubeMap, "tex");
4377 ASSERT_NE(-1, textureCubeUniformLocation);
4378 ASSERT_GL_NO_ERROR();
4379
4380 GLint max2DSize = 0;
4381 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max2DSize);
4382 GLint maxCubeMapSize = 0;
4383 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeMapSize);
4384 // Assuming 2048x2048xRGBA (22 mb with mips) will run on all WebGL platforms
4385 GLint max2DSquareSize = std::min(max2DSize, 2048);
4386 // I'd prefer this to be 2048 but that's 16 mb x 6 faces or 128 mb (with mips)
4387 // 1024 is 33.5 mb (with mips)
4388 maxCubeMapSize = std::min(maxCubeMapSize, 1024);
4389 ASSERT_GL_NO_ERROR();
4390
4391 for (GLint size = 1; size <= max2DSize; size *= 2)
4392 {
4393 bool cubeMap = testCaseIndex == 3;
4394 GLenum texTarget = cubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
4395 GLuint program = cubeMap ? programCubeMap : mProgram;
4396 GLint texWidth = 0, texHeight = 0;
4397
4398 switch (testCaseIndex)
4399 {
4400 case 0:
4401 texWidth = size;
4402 texHeight = 1;
4403 break;
4404 case 1:
4405 texWidth = 1;
4406 texHeight = size;
4407 break;
4408 case 2:
4409 case 3:
4410 texWidth = size;
4411 texHeight = size;
4412 break;
4413 }
4414
4415 if (texWidth == texHeight && size > max2DSquareSize)
4416 {
4417 return;
4418 }
4419
4420 if (cubeMap && size > maxCubeMapSize)
4421 {
4422 return;
4423 }
4424
4425 GLTexture texture;
4426 glActiveTexture(GL_TEXTURE0);
4427 glBindTexture(texTarget, texture);
4428 FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, false);
4429 glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4430 glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4431 glTexParameteri(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4432 glTexParameteri(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4433 ASSERT_GL_NO_ERROR();
4434
4435 glClear(GL_COLOR_BUFFER_BIT);
4436 ASSERT_GL_NO_ERROR();
4437
4438 glUseProgram(program);
4439 if (cubeMap)
4440 {
4441 glUniform1i(textureCubeUniformLocation, 0);
4442 }
4443 else
4444 {
4445 glUniform1i(mTexture2DUniformLocation, 0);
4446 }
4447
4448 drawQuad(program, "position", 1.0f);
4449 ASSERT_GL_NO_ERROR();
4450 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]);
4451
4452 colorCount = (colorCount + 1) % kNewMipColors.size();
4453 FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, false);
4454 glGenerateMipmap(texTarget);
4455 ASSERT_GL_NO_ERROR();
4456
4457 glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4458 glClear(GL_COLOR_BUFFER_BIT);
4459 drawQuad(program, "position", 1.0f);
4460 ASSERT_GL_NO_ERROR();
4461 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]);
4462
4463 colorCount = (colorCount + 1) % kNewMipColors.size();
4464 FillLevel(0, texWidth, texHeight, kNewMipColors[colorCount], cubeMap, true);
4465 glGenerateMipmap(texTarget);
4466
4467 glClear(GL_COLOR_BUFFER_BIT);
4468 drawQuad(program, "position", 1.0f);
4469 ASSERT_GL_NO_ERROR();
4470 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[colorCount]);
4471 }
4472 }
4473
testTextureSizeError()4474 void Texture2DTest::testTextureSizeError()
4475 {
4476 GLint max2DSize = 0;
4477 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max2DSize);
4478 glActiveTexture(GL_TEXTURE0);
4479 GLTexture texture;
4480 glBindTexture(GL_TEXTURE_2D, texture);
4481 FillLevel(0, max2DSize, max2DSize, GLColor::red, false, false);
4482 GLenum err = glGetError();
4483 bool passed = (err == GL_NO_ERROR || err == GL_OUT_OF_MEMORY);
4484 ASSERT_TRUE(passed);
4485 }
4486
4487 // Permutation 0 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase0)4488 TEST_P(Texture2DTest, TextureSizeCase0)
4489 {
4490 testTextureSize(0);
4491 }
4492
4493 // Permutation 1 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase1)4494 TEST_P(Texture2DTest, TextureSizeCase1)
4495 {
4496 testTextureSize(1);
4497 }
4498
4499 // Permutation 2 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase2)4500 TEST_P(Texture2DTest, TextureSizeCase2)
4501 {
4502 testTextureSize(2);
4503 }
4504
4505 // Permutation 3 of testTextureSize.
TEST_P(Texture2DTest,TextureSizeCase3)4506 TEST_P(Texture2DTest, TextureSizeCase3)
4507 {
4508 testTextureSize(3);
4509 }
4510
4511 // Test allocating a very large texture
TEST_P(Texture2DTest,TextureMaxSize)4512 TEST_P(Texture2DTest, TextureMaxSize)
4513 {
4514 testTextureSizeError();
4515 }
4516
4517 // Test that drawing works correctly RGBA 3D texture
TEST_P(Texture3DTestES2,RGBA)4518 TEST_P(Texture3DTestES2, RGBA)
4519 {
4520 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4521
4522 // http://anglebug.com/5728
4523 ANGLE_SKIP_TEST_IF(IsOzone());
4524
4525 glActiveTexture(GL_TEXTURE0);
4526 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4527 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
4528 std::vector<GLColor> texDataRed(1u * 1u * 1u, GLColor::red);
4529 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4530 texDataGreen.data());
4531 glTexImage3DOES(GL_TEXTURE_3D, 1, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4532 texDataRed.data());
4533 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4534 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4535
4536 EXPECT_GL_NO_ERROR();
4537
4538 drawQuad(mProgram, "position", 0.5f);
4539
4540 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4541 }
4542
4543 // Test that drawing works correctly Luminance 3D texture
TEST_P(Texture3DTestES2,Luminance)4544 TEST_P(Texture3DTestES2, Luminance)
4545 {
4546 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4547
4548 // http://anglebug.com/5728
4549 ANGLE_SKIP_TEST_IF(IsOzone());
4550
4551 glActiveTexture(GL_TEXTURE0);
4552 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4553 std::vector<GLubyte> texData(2u * 2u * 2u, 125);
4554 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
4555 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_LUMINANCE, 2, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4556 texData.data());
4557 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4558 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4559
4560 EXPECT_GL_NO_ERROR();
4561
4562 drawQuad(mProgram, "position", 0.5f);
4563
4564 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(125, 125, 125, 255));
4565 }
4566
4567 // Test that drawing works correctly with glCopyTexSubImage3D
TEST_P(Texture3DTestES2,CopySubImageRGBA)4568 TEST_P(Texture3DTestES2, CopySubImageRGBA)
4569 {
4570 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4571
4572 // http://anglebug.com/5728
4573 ANGLE_SKIP_TEST_IF(IsOzone());
4574
4575 glClearColor(0, 0, 1, 1);
4576 glClear(GL_COLOR_BUFFER_BIT);
4577
4578 glActiveTexture(GL_TEXTURE0);
4579 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4580 std::vector<GLColor> texDataRed(4u * 4u * 4u, GLColor::red);
4581 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4582 texDataRed.data());
4583 glTexImage3DOES(GL_TEXTURE_3D, 1, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4584 texDataRed.data());
4585 glTexImage3DOES(GL_TEXTURE_3D, 2, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4586 texDataRed.data());
4587 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
4588 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2);
4589 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4590 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4591
4592 EXPECT_GL_NO_ERROR();
4593
4594 glClearColor(0, 1, 0, 1);
4595 glClear(GL_COLOR_BUFFER_BIT);
4596 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4597
4598 glUseProgram(mProgram);
4599 glUniform1f(glGetUniformLocation(mProgram, "level"), 1);
4600 drawQuad(mProgram, "position", 0.5f);
4601
4602 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4603 }
4604
TEST_P(Texture3DTestES2,CopySubImageLuminance)4605 TEST_P(Texture3DTestES2, CopySubImageLuminance)
4606 {
4607 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4608
4609 // http://anglebug.com/5728
4610 ANGLE_SKIP_TEST_IF(IsOzone());
4611
4612 glClearColor(1, 0, 0, 1);
4613 glClear(GL_COLOR_BUFFER_BIT);
4614
4615 glActiveTexture(GL_TEXTURE0);
4616 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4617 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_LUMINANCE, 4, 4, 4, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4618 nullptr);
4619 glTexImage3DOES(GL_TEXTURE_3D, 1, GL_LUMINANCE, 2, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4620 nullptr);
4621 glTexImage3DOES(GL_TEXTURE_3D, 2, GL_LUMINANCE, 1, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4622 nullptr);
4623 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
4624 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2);
4625 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4626 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4627
4628 EXPECT_GL_NO_ERROR();
4629
4630 glClearColor(0, 1, 0, 1);
4631 glClear(GL_COLOR_BUFFER_BIT);
4632 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4633
4634 glUseProgram(mProgram);
4635 glUniform1f(glGetUniformLocation(mProgram, "level"), 1);
4636 drawQuad(mProgram, "position", 0.5f);
4637
4638 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
4639 }
4640
TEST_P(Texture3DTestES2,CopySubImageAlpha)4641 TEST_P(Texture3DTestES2, CopySubImageAlpha)
4642 {
4643 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4644
4645 // http://anglebug.com/5728
4646 ANGLE_SKIP_TEST_IF(IsOzone());
4647
4648 glClearColor(1, 0, 0, 0.5);
4649 glClear(GL_COLOR_BUFFER_BIT);
4650
4651 glActiveTexture(GL_TEXTURE0);
4652 glBindTexture(GL_TEXTURE_3D, mTexture3D);
4653 glTexImage3DOES(GL_TEXTURE_3D, 0, GL_ALPHA, 4, 4, 4, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
4654 glTexImage3DOES(GL_TEXTURE_3D, 1, GL_ALPHA, 2, 2, 2, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
4655 glTexImage3DOES(GL_TEXTURE_3D, 2, GL_ALPHA, 1, 1, 1, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
4656 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 0, 0, 0, 2, 2);
4657 glCopyTexSubImage3DOES(GL_TEXTURE_3D, 1, 0, 0, 1, 0, 0, 2, 2);
4658 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4659 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
4660
4661 EXPECT_GL_NO_ERROR();
4662
4663 glClearColor(0, 1, 0, 1);
4664 glClear(GL_COLOR_BUFFER_BIT);
4665 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4666
4667 glUseProgram(mProgram);
4668 glUniform1f(glGetUniformLocation(mProgram, "level"), 1);
4669 drawQuad(mProgram, "position", 0.5f);
4670
4671 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 128), 1.0);
4672 }
4673
4674 // Test that defining a 2D texture array fails with Texture3DOES on ES2.
TEST_P(Texture3DTestES2,DefineTexture2DArrayShouldFail)4675 TEST_P(Texture3DTestES2, DefineTexture2DArrayShouldFail)
4676 {
4677 ANGLE_SKIP_TEST_IF(!hasTexture3DExt());
4678
4679 // http://anglebug.com/5728
4680 ANGLE_SKIP_TEST_IF(IsOzone());
4681
4682 glClearColor(1, 0, 0, 1);
4683 glClear(GL_COLOR_BUFFER_BIT);
4684
4685 glActiveTexture(GL_TEXTURE0);
4686 glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
4687 EXPECT_GL_ERROR(GL_INVALID_ENUM);
4688
4689 glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4690 nullptr);
4691 glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4692 nullptr);
4693 glTexImage3DOES(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA, 1, 1, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4694 nullptr);
4695 EXPECT_GL_ERROR(GL_INVALID_ENUM);
4696 }
4697
4698 // Verify shrinking a texture with glTexStorage2D works correctly
TEST_P(Texture2DTestES3,ChangeTexSizeWithTexStorage)4699 TEST_P(Texture2DTestES3, ChangeTexSizeWithTexStorage)
4700 {
4701 // TODO: http://anglebug.com/5256
4702 ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL());
4703
4704 constexpr uint32_t kSizeLarge = 128;
4705 constexpr uint32_t kSizeSmall = 64;
4706
4707 glActiveTexture(GL_TEXTURE0);
4708 glBindTexture(GL_TEXTURE_2D, mTexture2D);
4709 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4710 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4711
4712 // Create the texture with 'large' dimensions
4713 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeLarge, kSizeLarge, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4714 nullptr);
4715 ASSERT_GL_NO_ERROR();
4716
4717 GLFramebuffer destFbo;
4718 glBindFramebuffer(GL_FRAMEBUFFER, destFbo);
4719 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture2D, 0);
4720 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4721
4722 // Draw with the new texture so it's created in the back end
4723 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
4724 glUseProgram(blueProgram);
4725 drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
4726 ASSERT_GL_NO_ERROR();
4727 EXPECT_PIXEL_RECT_EQ(0, 0, kSizeLarge, kSizeLarge, GLColor::blue);
4728
4729 // Shrink the texture
4730 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSizeSmall, kSizeSmall);
4731 ASSERT_GL_NO_ERROR();
4732
4733 // Create a source texture/FBO to blit from
4734 GLTexture sourceTex;
4735 glBindTexture(GL_TEXTURE_2D, sourceTex);
4736 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSizeSmall, kSizeSmall);
4737 ASSERT_GL_NO_ERROR();
4738 GLFramebuffer sourceFbo;
4739 glBindFramebuffer(GL_FRAMEBUFFER, sourceFbo);
4740 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sourceTex, 0);
4741 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4742 // Fill the source texture with green
4743 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4744 glUseProgram(greenProgram);
4745 drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
4746 ASSERT_GL_NO_ERROR();
4747 EXPECT_PIXEL_RECT_EQ(0, 0, kSizeSmall, kSizeSmall, GLColor::green);
4748
4749 // Blit the source (green) to the destination
4750 glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceFbo);
4751 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destFbo);
4752 glBlitFramebuffer(0, 0, kSizeSmall, kSizeSmall, 0, 0, kSizeSmall, kSizeSmall,
4753 GL_COLOR_BUFFER_BIT, GL_NEAREST);
4754 ASSERT_GL_NO_ERROR();
4755
4756 // Render to the default framebuffer sampling from the blited texture and verify it's green
4757 glBindFramebuffer(GL_FRAMEBUFFER, 0);
4758 glBindTexture(GL_TEXTURE_2D, mTexture2D);
4759 ANGLE_GL_PROGRAM(texProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
4760 glUseProgram(texProgram);
4761 drawQuad(texProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
4762 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
4763 }
4764
4765 // Regression test for http://crbug.com/949985 to make sure dirty bits are propagated up from
4766 // TextureImpl and the texture is synced before being used in a draw call.
TEST_P(Texture2DTestES3,TextureImplPropogatesDirtyBits)4767 TEST_P(Texture2DTestES3, TextureImplPropogatesDirtyBits)
4768 {
4769 ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
4770 // Flaky hangs on Win10 AMD RX 550 GL. http://anglebug.com/3371
4771 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
4772 // D3D Debug device reports an error. http://anglebug.com/3501
4773 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11());
4774 // Support copy from levels outside the image range. http://anglebug.com/4733
4775 ANGLE_SKIP_TEST_IF(IsVulkan());
4776
4777 // The workaround in the GL backend required to trigger this bug generates driver warning
4778 // messages.
4779 ScopedIgnorePlatformMessages ignoreMessages;
4780
4781 setUpProgram();
4782 glUseProgram(mProgram);
4783 glActiveTexture(GL_TEXTURE0 + mTexture2DUniformLocation);
4784
4785 GLTexture dest;
4786 glBindTexture(GL_TEXTURE_2D, dest);
4787
4788 GLTexture source;
4789 glBindTexture(GL_TEXTURE_2D, source);
4790
4791 // Put data in mip 0 and 1
4792 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4793 GLColor::red.data());
4794 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4795 GLColor::green.data());
4796
4797 // Disable mipmapping so source is complete
4798 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4799 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4800
4801 // Force the dirty bits to be synchronized in source
4802 drawQuad(mProgram, "position", 1.0f);
4803
4804 // Copy from mip 1 of the source. In the GL backend this internally sets the base level to mip
4805 // 1 and sets a dirty bit.
4806 glCopyTextureCHROMIUM(source, 1, GL_TEXTURE_2D, dest, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_FALSE,
4807 GL_FALSE, GL_FALSE);
4808
4809 // Draw again, assertions are generated if the texture has internal dirty bits at draw time
4810 drawQuad(mProgram, "position", 1.0f);
4811 }
4812
4813 // This test case changes the base level of a texture that's attached to a framebuffer, clears every
4814 // level to green, and then samples the texture when rendering. Test is taken from
4815 // https://www.khronos.org/registry/webgl/sdk/tests/conformance2/rendering/framebuffer-texture-changing-base-level.html
TEST_P(Texture2DTestES3,FramebufferTextureChangingBaselevel)4816 TEST_P(Texture2DTestES3, FramebufferTextureChangingBaselevel)
4817 {
4818 // TODO(cnorthrop): Failing on Vulkan/Windows/AMD. http://anglebug.com/3996
4819 ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD());
4820
4821 setUpProgram();
4822
4823 constexpr GLint width = 8;
4824 constexpr GLint height = 4;
4825
4826 GLTexture texture;
4827 glBindTexture(GL_TEXTURE_2D, texture);
4828 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
4829 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4830 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4831 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4832
4833 // Create all mipmap levels for the texture from level 0 to the 1x1 pixel level.
4834 GLint level = 0;
4835 GLint levelW = width;
4836 GLint levelH = height;
4837 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, levelW, levelH, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4838 nullptr);
4839 while (levelW > 1 || levelH > 1)
4840 {
4841 ++level;
4842 levelW = static_cast<GLint>(std::max(1.0, std::floor(width / std::pow(2, level))));
4843 levelH = static_cast<GLint>(std::max(1.0, std::floor(height / std::pow(2, level))));
4844 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, levelW, levelH, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4845 nullptr);
4846 }
4847
4848 // Clear each level of the texture using an FBO. Change the base level to match the level used
4849 // for the FBO on each iteration.
4850 GLFramebuffer fbo;
4851 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4852 level = 0;
4853 levelW = width;
4854 levelH = height;
4855 while (levelW > 1 || levelH > 1)
4856 {
4857 levelW = static_cast<GLint>(std::floor(width / std::pow(2, level)));
4858 levelH = static_cast<GLint>(std::floor(height / std::pow(2, level)));
4859
4860 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level);
4861 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, level);
4862
4863 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
4864 EXPECT_GL_NO_ERROR();
4865
4866 glClearColor(0, 1, 0, 1);
4867 glClear(GL_COLOR_BUFFER_BIT);
4868
4869 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4870
4871 ++level;
4872 }
4873
4874 glBindFramebuffer(GL_FRAMEBUFFER, 0);
4875 glViewport(0, 0, 16, 16);
4876 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
4877
4878 drawQuad(mProgram, "position", 0.5f);
4879
4880 EXPECT_GL_NO_ERROR();
4881 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4882 }
4883
4884 // Test that changing the base level of a texture after redefining a level outside the mip-chain
4885 // preserves the other mips' data.
TEST_P(Texture2DBaseMaxTestES3,ExtendMipChainAfterRedefine)4886 TEST_P(Texture2DBaseMaxTestES3, ExtendMipChainAfterRedefine)
4887 {
4888 // http://anglebug.com/4699
4889 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac());
4890
4891 // http://anglebug.com/5153
4892 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA() && IsMac());
4893
4894 GLFramebuffer framebuffer;
4895 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4896
4897 GLTexture texture;
4898 glBindTexture(GL_TEXTURE_2D, texture);
4899
4900 std::array<GLColor, getTotalMipDataSize(kMip0Size)> mipData;
4901 fillMipData(mipData.data(), kMip0Size, kMipColors);
4902
4903 for (size_t mip = 1; mip < kMipCount; ++mip)
4904 {
4905 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, kMip0Size >> mip, kMip0Size >> mip, 0, GL_RGBA,
4906 GL_UNSIGNED_BYTE, mipData.data() + getMipDataOffset(kMip0Size, mip));
4907 }
4908
4909 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
4910 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
4911 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4912
4913 // Mip 1 is green. Verify this.
4914 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]);
4915
4916 // http://anglebug.com/4709
4917 ANGLE_SKIP_TEST_IF(IsOpenGL() && (IsIntel() || IsAMD()) && IsWindows());
4918
4919 // Add mip 0 and rebase the mip chain.
4920 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4921 mipData.data() + getMipDataOffset(kMip0Size, 0));
4922 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
4923
4924 // Mip 1 should still be green.
4925 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]);
4926
4927 // Verify the other mips too.
4928 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2);
4929 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4930 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[2]);
4931
4932 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3);
4933 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4934 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[3]);
4935
4936 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4937 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4938
4939 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]);
4940 }
4941
4942 // Test that changing the base level of a texture multiple times preserves the data.
TEST_P(Texture2DBaseMaxTestES3,PingPongBaseLevel)4943 TEST_P(Texture2DBaseMaxTestES3, PingPongBaseLevel)
4944 {
4945 testPingPongBaseLevel(false);
4946 }
TEST_P(Texture2DBaseMaxTestES3,PingPongBaseLevelImmutable)4947 TEST_P(Texture2DBaseMaxTestES3, PingPongBaseLevelImmutable)
4948 {
4949 testPingPongBaseLevel(true);
4950 }
testPingPongBaseLevel(bool immutable)4951 void Texture2DBaseMaxTestES3::testPingPongBaseLevel(bool immutable)
4952 {
4953 // http://anglebug.com/4710
4954 ANGLE_SKIP_TEST_IF(IsD3D());
4955
4956 // http://anglebug.com/4711
4957 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsAMD() && IsWindows());
4958
4959 // http://anglebug.com/4701
4960 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac());
4961
4962 initTest(immutable);
4963
4964 // Ping pong a few times.
4965 for (uint32_t tries = 0; tries < 2; ++tries)
4966 {
4967 // Rebase to different mips and verify mips.
4968 for (uint32_t base = 0; base < kMipCount; ++base)
4969 {
4970 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base);
4971 for (uint32_t lod = 0; lod < kMipCount - base; ++lod)
4972 {
4973 setLodUniform(lod);
4974 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4975 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[base + lod]);
4976 }
4977 }
4978
4979 // Rebase backwards and verify mips.
4980 for (uint32_t base = kMipCount - 2; base > 0; --base)
4981 {
4982 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, base);
4983 for (uint32_t lod = 0; lod < kMipCount - base; ++lod)
4984 {
4985 setLodUniform(lod);
4986 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
4987 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[base + lod]);
4988 }
4989 }
4990 }
4991 }
4992
4993 // Test that glTexSubImage2D after incompatibly redefining a mip level correctly applies the update
4994 // after the redefine data.
TEST_P(Texture2DBaseMaxTestES3,SubImageAfterRedefine)4995 TEST_P(Texture2DBaseMaxTestES3, SubImageAfterRedefine)
4996 {
4997 initTest(false);
4998
4999 // Test that all mips have the expected data initially (this makes sure the texture image is
5000 // created already).
5001 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5002 {
5003 setLodUniform(lod);
5004 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5005 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5006 }
5007
5008 // Redefine every level, followed by a glTexSubImage2D
5009 const GLColor kNewMipColors[kMipCount] = {
5010 GLColor::yellow,
5011 GLColor::cyan,
5012 GLColor(127, 0, 0, 255),
5013 GLColor(0, 127, 0, 255),
5014 };
5015 std::array<GLColor, getTotalMipDataSize(kMip0Size * 2)> newMipData;
5016 fillMipData(newMipData.data(), kMip0Size * 2, kNewMipColors);
5017
5018 const GLColor kSubImageMipColors[kMipCount] = {
5019 GLColor(0, 0, 127, 255),
5020 GLColor(127, 127, 0, 255),
5021 GLColor(0, 127, 127, 255),
5022 GLColor(127, 0, 127, 255),
5023 };
5024 std::array<GLColor, getTotalMipDataSize(kMip0Size)> subImageMipData;
5025 fillMipData(subImageMipData.data(), kMip0Size, kSubImageMipColors);
5026
5027 for (size_t mip = 0; mip < kMipCount; ++mip)
5028 {
5029 // Redefine the level.
5030 size_t newMipSize = (kMip0Size * 2) >> mip;
5031 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, newMipSize, newMipSize, 0, GL_RGBA,
5032 GL_UNSIGNED_BYTE, newMipData.data() + getMipDataOffset(kMip0Size * 2, mip));
5033
5034 // Immediately follow that with a subimage update.
5035 glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip, GL_RGBA,
5036 GL_UNSIGNED_BYTE,
5037 subImageMipData.data() + getMipDataOffset(kMip0Size, mip));
5038 }
5039 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 1);
5040
5041 // Test that the texture looks as expected.
5042 const int w = getWindowWidth() - 1;
5043 const int h = getWindowHeight() - 1;
5044 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5045 {
5046 setLodUniform(lod);
5047 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5048 EXPECT_PIXEL_COLOR_EQ(0, 0, kSubImageMipColors[lod]);
5049 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColors[lod]);
5050 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColors[lod]);
5051 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColors[lod]);
5052 }
5053 }
5054
5055 // Test that incompatibly redefining a level then redefining it back to its original size works.
TEST_P(Texture2DBaseMaxTestES3,IncompatiblyRedefineLevelThenRevert)5056 TEST_P(Texture2DBaseMaxTestES3, IncompatiblyRedefineLevelThenRevert)
5057 {
5058 initTest(false);
5059
5060 // Test that all mips have the expected data initially (this makes sure the texture image is
5061 // created already).
5062 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5063 {
5064 setLodUniform(lod);
5065 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5066 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5067 }
5068
5069 // Redefine Mip 1 to be larger.
5070 constexpr size_t kLargeMip1Size = getMipDataSize(kMip0Size * 2, 1);
5071 std::array<GLColor, kLargeMip1Size> interimMipData;
5072 std::fill(interimMipData.data(), interimMipData.data() + kLargeMip1Size, GLColor::yellow);
5073
5074 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5075 interimMipData.data());
5076
5077 // Redefine Mip 1 back to its original size.
5078 constexpr size_t kNormalMip1Size = getMipDataSize(kMip0Size, 1);
5079 std::array<GLColor, kLargeMip1Size> newMipData;
5080 std::fill(newMipData.data(), newMipData.data() + kNormalMip1Size, GLColor::cyan);
5081
5082 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size / 2, kMip0Size / 2, 0, GL_RGBA,
5083 GL_UNSIGNED_BYTE, newMipData.data());
5084
5085 // Verify texture colors.
5086 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5087 {
5088 setLodUniform(lod);
5089 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5090 EXPECT_PIXEL_COLOR_EQ(0, 0, lod == 1 ? GLColor::cyan : kMipColors[lod]);
5091 }
5092 }
5093
5094 // Test that redefining every level of a texture to another format works. The format uses more
5095 // bits per component, to ensure alignment requirements for the new format are taken into account.
TEST_P(Texture2DBaseMaxTestES3,RedefineEveryLevelToAnotherFormat)5096 TEST_P(Texture2DBaseMaxTestES3, RedefineEveryLevelToAnotherFormat)
5097 {
5098 initTest(false);
5099
5100 // Test that all mips have the expected data initially (this makes sure the texture image is
5101 // created already).
5102 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5103 {
5104 setLodUniform(lod);
5105 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5106 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5107 }
5108
5109 const GLColor32F kNewMipColors[kMipCount] = {
5110 GLColor32F(1.0, 1.0, 0.0, 1.0f),
5111 GLColor32F(1.0, 0.0, 1.0, 1.0f),
5112 GLColor32F(0.0, 1.0, 1.0, 1.0f),
5113 GLColor32F(1.0, 1.0, 1.0, 1.0f),
5114 };
5115
5116 std::array<GLColor32F, getTotalMipDataSize(kMip0Size)> newMipData;
5117 fillMipData(newMipData.data(), kMip0Size, kNewMipColors);
5118
5119 // Redefine every level with the new format.
5120 for (size_t mip = 0; mip < kMipCount; ++mip)
5121 {
5122 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA32F, kMip0Size >> mip, kMip0Size >> mip, 0, GL_RGBA,
5123 GL_FLOAT, newMipData.data() + getMipDataOffset(kMip0Size, mip));
5124 }
5125
5126 // Verify texture colors.
5127 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5128 {
5129 setLodUniform(lod);
5130 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5131
5132 GLColor32F mipColor32F = kNewMipColors[lod];
5133 GLColor mipColor(static_cast<GLubyte>(std::roundf(mipColor32F.R * 255)),
5134 static_cast<GLubyte>(std::roundf(mipColor32F.G * 255)),
5135 static_cast<GLubyte>(std::roundf(mipColor32F.B * 255)),
5136 static_cast<GLubyte>(std::roundf(mipColor32F.A * 255)));
5137
5138 EXPECT_PIXEL_COLOR_EQ(0, 0, mipColor);
5139 }
5140 }
5141
5142 // Test that generating mipmaps after change base level.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRebase)5143 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRebase)
5144 {
5145 // http://anglebug.com/5880
5146 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
5147
5148 testGenerateMipmapAfterRebase(false);
5149 }
5150
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRebaseImmutable)5151 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRebaseImmutable)
5152 {
5153 // http://anglebug.com/4710
5154 ANGLE_SKIP_TEST_IF(IsD3D());
5155 // http://anglebug.com/5798
5156 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA());
5157 // http://anglebug.com/5880
5158 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
5159
5160 testGenerateMipmapAfterRebase(true);
5161 }
5162
testGenerateMipmapAfterRebase(bool immutable)5163 void Texture2DBaseMaxTestES3::testGenerateMipmapAfterRebase(bool immutable)
5164 {
5165 initTest(immutable);
5166
5167 // Test that all mips have the expected data initially (this makes sure the texture image is
5168 // created already).
5169 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5170 {
5171 setLodUniform(lod);
5172 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5173 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5174 }
5175
5176 // Update level 1 (any level would do other than 0) with new data
5177 const GLColor kNewMipColor = GLColor::yellow;
5178 std::array<GLColor, getMipDataSize(kMip0Size >> 1, 0)> newMipData;
5179 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5180
5181 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kMip0Size >> 1, kMip0Size >> 1, GL_RGBA,
5182 GL_UNSIGNED_BYTE, newMipData.data());
5183
5184 // Change base level and max level and then generate mipmaps. This should redefine level 1 and 2
5185 // with kNewMipColor and leave levels 0 and 3 unchanged.
5186 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5187 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 2);
5188 glGenerateMipmap(GL_TEXTURE_2D);
5189 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5190 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMipCount - 1);
5191
5192 // Test that the texture looks as expected.
5193 const int w = getWindowWidth() - 1;
5194 const int h = getWindowHeight() - 1;
5195 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5196 {
5197 setLodUniform(lod);
5198 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5199 if (lod == 0)
5200 {
5201 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << "lod " << lod;
5202 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]) << "lod " << lod;
5203 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]) << "lod " << lod;
5204 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]) << "lod " << lod;
5205 }
5206 else if (lod == kMipCount - 1)
5207 {
5208 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << "lod " << lod;
5209 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]) << "lod " << lod;
5210 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]) << "lod " << lod;
5211 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]) << "lod " << lod;
5212 }
5213 else
5214 {
5215 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor) << "lod " << lod;
5216 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor) << "lod " << lod;
5217 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor) << "lod " << lod;
5218 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor) << "lod " << lod;
5219 }
5220 }
5221 }
5222
5223 // Test that generating mipmaps after incompatibly redefining a level works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefine)5224 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefine)
5225 {
5226 initTest(false);
5227
5228 // Test that all mips have the expected data initially (this makes sure the texture image is
5229 // created already).
5230 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5231 {
5232 setLodUniform(lod);
5233 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5234 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5235 }
5236
5237 // Redefine level 1 (any level would do other than 0) to an incompatible size, say the same size
5238 // as level 0.
5239 const GLColor kNewMipColor = GLColor::yellow;
5240 std::array<GLColor, getMipDataSize(kMip0Size, 0)> newMipData;
5241 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5242
5243 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5244 newMipData.data());
5245
5246 // Generate mipmaps. This should redefine level 1 back to being compatible with level 0.
5247 glGenerateMipmap(GL_TEXTURE_2D);
5248
5249 // Test that the texture looks as expected.
5250 const int w = getWindowWidth() - 1;
5251 const int h = getWindowHeight() - 1;
5252 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5253 {
5254 setLodUniform(lod);
5255 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5256 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]);
5257 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[0]);
5258 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[0]);
5259 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[0]);
5260 }
5261 }
5262
5263 // Test that generating mipmaps after incompatibly redefining a level while simultaneously changing
5264 // the base level works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefineAndRebase)5265 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefineAndRebase)
5266 {
5267 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
5268
5269 // http://crbug.com/1100613
5270 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
5271
5272 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
5273 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && IsDesktopOpenGL());
5274
5275 initTest(false);
5276
5277 // Test that all mips have the expected data initially (this makes sure the texture image is
5278 // created already).
5279 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5280 {
5281 setLodUniform(lod);
5282 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5283 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << lod;
5284 }
5285
5286 // Redefine level 2 to an incompatible size, say the same size as level 0.
5287 const GLColor kNewMipColor = GLColor::yellow;
5288 std::array<GLColor, getMipDataSize(kMip0Size, 0)> newMipData;
5289 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5290
5291 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5292 newMipData.data());
5293
5294 // Set base level of the texture to 1 then generate mipmaps. Level 2 that's redefined should
5295 // go back to being compatibly defined.
5296 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5297 glGenerateMipmap(GL_TEXTURE_2D);
5298
5299 // Test that the texture looks as expected.
5300 const int w = getWindowWidth() - 1;
5301 const int h = getWindowHeight() - 1;
5302 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5303 {
5304 setLodUniform(lod);
5305 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5306 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[1]) << lod;
5307 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[1]) << lod;
5308 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[1]) << lod;
5309 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[1]) << lod;
5310 }
5311
5312 // Redefine level 1 (current base level) to an incompatible size.
5313 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kMip0Size, kMip0Size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5314 newMipData.data());
5315
5316 // Set base level of the texture back to 0 then generate mipmaps. Level 1 should go back to
5317 // being compatibly defined.
5318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5319 glGenerateMipmap(GL_TEXTURE_2D);
5320
5321 // Test that the texture looks as expected.
5322 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5323 {
5324 setLodUniform(lod);
5325 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5326 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[0]) << lod;
5327 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[0]) << lod;
5328 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[0]) << lod;
5329 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[0]) << lod;
5330 }
5331 }
5332
5333 // Test that generating mipmaps after incompatibly redefining the base level of the texture works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefiningBase)5334 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefiningBase)
5335 {
5336 initTest(false);
5337
5338 // Test that all mips have the expected data initially (this makes sure the texture image is
5339 // created already).
5340 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5341 {
5342 setLodUniform(lod);
5343 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5344 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5345 }
5346
5347 // Redefine level 0 to an incompatible size.
5348 const GLColor kNewMipColor = GLColor::yellow;
5349 std::array<GLColor, getMipDataSize(kMip0Size * 2, 0)> newMipData;
5350 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5351
5352 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size * 2, kMip0Size * 2, 0, GL_RGBA,
5353 GL_UNSIGNED_BYTE, newMipData.data());
5354
5355 // Generate mipmaps.
5356 glGenerateMipmap(GL_TEXTURE_2D);
5357
5358 // Test that the texture looks as expected.
5359 const int w = getWindowWidth() - 1;
5360 const int h = getWindowHeight() - 1;
5361 for (uint32_t lod = 0; lod < kMipCount + 1; ++lod)
5362 {
5363 setLodUniform(lod);
5364 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5365 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor);
5366 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor);
5367 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor);
5368 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor);
5369 }
5370 }
5371
5372 // Test that generating mipmaps after incompatibly redefining the base level while simultaneously
5373 // changing MAX_LEVEL works.
TEST_P(Texture2DBaseMaxTestES3,GenerateMipmapAfterRedefiningBaseAndChangingMax)5374 TEST_P(Texture2DBaseMaxTestES3, GenerateMipmapAfterRedefiningBaseAndChangingMax)
5375 {
5376 initTest(false);
5377
5378 // Test that all mips have the expected data initially (this makes sure the texture image is
5379 // created already).
5380 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5381 {
5382 setLodUniform(lod);
5383 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5384 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5385 }
5386
5387 // Redefine level 0 to an incompatible size.
5388 const GLColor kNewMipColor = GLColor::yellow;
5389 std::array<GLColor, getMipDataSize(kMip0Size * 2, 0)> newMipData;
5390 std::fill(newMipData.begin(), newMipData.end(), kNewMipColor);
5391
5392 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kMip0Size * 2, kMip0Size * 2, 0, GL_RGBA,
5393 GL_UNSIGNED_BYTE, newMipData.data());
5394
5395 // Set max level of the texture to 2 then generate mipmaps.
5396 constexpr uint32_t kMaxLevel = 2;
5397 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, kMaxLevel);
5398 glGenerateMipmap(GL_TEXTURE_2D);
5399
5400 // Test that the texture looks as expected.
5401 const int w = getWindowWidth() - 1;
5402 const int h = getWindowHeight() - 1;
5403 for (uint32_t lod = 0; lod <= kMaxLevel; ++lod)
5404 {
5405 setLodUniform(lod);
5406 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5407 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor);
5408 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor);
5409 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor);
5410 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor);
5411 }
5412 }
5413
5414 // Test that stage invalid texture levels work.
TEST_P(Texture2DBaseMaxTestES3,StageInvalidLevels)5415 TEST_P(Texture2DBaseMaxTestES3, StageInvalidLevels)
5416 {
5417 constexpr uint32_t kMaxLevel = 2;
5418 const GLColor kMipColor[kMaxLevel + 1] = {GLColor::red, GLColor::green, GLColor::blue};
5419
5420 initTest(false);
5421
5422 GLTexture texture;
5423 glBindTexture(GL_TEXTURE_2D, texture);
5424
5425 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5426 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5427 std::vector<GLColor> texDataCyan(2u * 2u, GLColor::cyan);
5428 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataCyan.data());
5429 setLodUniform(0);
5430 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5431 EXPECT_GL_NO_ERROR();
5432
5433 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
5434 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5435 texDataGreen.data());
5436 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::blue);
5437 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5438 EXPECT_GL_NO_ERROR();
5439
5440 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
5441 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
5442 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5443 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5444
5445 // Test that the texture looks as expected.
5446 const int w = getWindowWidth() - 1;
5447 const int h = getWindowHeight() - 1;
5448 for (uint32_t lod = 0; lod <= kMaxLevel; ++lod)
5449 {
5450 setLodUniform(lod);
5451 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5452 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColor[lod]);
5453 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColor[lod]);
5454 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColor[lod]);
5455 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColor[lod]);
5456 }
5457 }
5458
5459 // Test redefine a mutable texture into an immutable texture.
TEST_P(Texture2DBaseMaxTestES3,RedefineMutableToImmutable)5460 TEST_P(Texture2DBaseMaxTestES3, RedefineMutableToImmutable)
5461 {
5462 // http://anglebug.com/4710
5463 ANGLE_SKIP_TEST_IF(IsD3D());
5464
5465 // http://anglebug.com/4701
5466 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsMac());
5467
5468 constexpr uint32_t kBaseLevel = 1;
5469 const GLColor kNewMipColors[kMipCount] = {
5470 GLColor::yellow,
5471 GLColor::cyan,
5472 GLColor::white,
5473 GLColor(127u, 127u, 127u, 255u),
5474 };
5475
5476 initTest(false);
5477
5478 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, kBaseLevel);
5479
5480 // Test that all mips have the expected data
5481 for (uint32_t lod = kBaseLevel; lod < kMipCount; ++lod)
5482 {
5483 setLodUniform(lod - kBaseLevel);
5484 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5485 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5486 }
5487
5488 glTexStorage2D(GL_TEXTURE_2D, kMipCount, GL_RGBA8, kMip0Size, kMip0Size);
5489 std::array<GLColor, getTotalMipDataSize(kMip0Size)> mipData;
5490 fillMipData(mipData.data(), kMip0Size, kNewMipColors);
5491 for (size_t mip = 0; mip < kMipCount; ++mip)
5492 {
5493 glTexSubImage2D(GL_TEXTURE_2D, mip, 0, 0, kMip0Size >> mip, kMip0Size >> mip, GL_RGBA,
5494 GL_UNSIGNED_BYTE, mipData.data() + getMipDataOffset(kMip0Size, mip));
5495 }
5496
5497 // Test that all enabled mips have the expected data
5498 for (uint32_t lod = kBaseLevel; lod < kMipCount; ++lod)
5499 {
5500 setLodUniform(lod - kBaseLevel);
5501 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5502 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[lod]);
5503 }
5504
5505 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5506 for (uint32_t lod = 0; lod < kBaseLevel; ++lod)
5507 {
5508 setLodUniform(lod);
5509 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5510 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColors[lod]);
5511 }
5512 }
5513
5514 // Test that redefine a level with incompatible size beyond the max level.
TEST_P(Texture2DBaseMaxTestES3,RedefineIncompatibleLevelBeyondMaxLevel)5515 TEST_P(Texture2DBaseMaxTestES3, RedefineIncompatibleLevelBeyondMaxLevel)
5516 {
5517 initTest(false);
5518
5519 // Test that all mips have the expected data initially (this makes sure the texture image is
5520 // created already).
5521 for (uint32_t lod = 0; lod < kMipCount; ++lod)
5522 {
5523 setLodUniform(lod);
5524 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5525 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5526 }
5527
5528 uint32_t maxLevel = 1;
5529 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel);
5530
5531 // Update level 0
5532 const GLColor kNewMipLevle0Color = GLColor::yellow;
5533 std::array<GLColor, getMipDataSize(kMip0Size, 0)> newMipData;
5534 std::fill(newMipData.begin(), newMipData.end(), kNewMipLevle0Color);
5535 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kMip0Size, kMip0Size, GL_RGBA, GL_UNSIGNED_BYTE,
5536 newMipData.data());
5537
5538 // Update level 2 with incompatible data
5539 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5540 newMipData.data());
5541 EXPECT_GL_NO_ERROR();
5542
5543 // Test that the texture looks as expected.
5544 const int w = getWindowWidth() - 1;
5545 const int h = getWindowHeight() - 1;
5546 for (uint32_t lod = 0; lod < maxLevel; ++lod)
5547 {
5548 setLodUniform(lod);
5549 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
5550 if (lod == 0)
5551 {
5552 EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipLevle0Color);
5553 EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipLevle0Color);
5554 EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipLevle0Color);
5555 EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipLevle0Color);
5556 }
5557 else
5558 {
5559 EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
5560 EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]);
5561 EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]);
5562 EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]);
5563 }
5564 }
5565 }
5566
5567 // Port test from web_gl/conformance2/textures/misc/fuzz-545-immutable-tex-render-feedback.html.
5568 // What this tries to do is create a render feedback loop and ensure it is not crashing.
TEST_P(Texture2DBaseMaxTestES3,Fuzz545ImmutableTexRenderFeedback)5569 TEST_P(Texture2DBaseMaxTestES3, Fuzz545ImmutableTexRenderFeedback)
5570 {
5571 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5572
5573 constexpr uint32_t MIPS = 2;
5574 constexpr uint32_t SIZE = 10;
5575
5576 GLTexture immutTex;
5577 glBindTexture(GL_TEXTURE_2D, immutTex);
5578 glTexStorage2D(GL_TEXTURE_2D, MIPS, GL_RGBA8, SIZE, SIZE);
5579
5580 GLTexture mutTex;
5581 glBindTexture(GL_TEXTURE_2D, mutTex);
5582 for (uint32_t mip = 0; mip < MIPS; mip++)
5583 {
5584 const uint32_t size = SIZE >> mip;
5585 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5586 nullptr);
5587 }
5588
5589 constexpr GLenum MAG_FILTERS[] = {GL_LINEAR, GL_NEAREST};
5590 constexpr GLenum MIN_FILTERS[] = {
5591 GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST,
5592 GL_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_NEAREST};
5593
5594 GLFramebuffer fbo;
5595 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5596
5597 const GLuint texs[] = {immutTex, mutTex};
5598 for (const GLuint tex : texs)
5599 {
5600 glBindTexture(GL_TEXTURE_2D, tex);
5601
5602 for (GLuint level_prime_base = 0; level_prime_base < (MIPS + 1); level_prime_base++)
5603 { // `level_base` in GLES
5604 // ES 3.0.6 p150
5605 GLuint _level_base = level_prime_base;
5606 if (tex == immutTex)
5607 {
5608 _level_base = std::min(_level_base, MIPS - 1);
5609 }
5610 const GLuint level_base = _level_base;
5611
5612 for (GLuint _level_prime_max = (level_prime_base - 1); _level_prime_max < (MIPS + 2);
5613 _level_prime_max++)
5614 { // `q` in GLES
5615 if (_level_prime_max < 0)
5616 continue;
5617 if (_level_prime_max == (MIPS + 1))
5618 {
5619 _level_prime_max = 10000; // This is the default, after all!
5620 }
5621 const GLuint level_prime_max = _level_prime_max;
5622
5623 // ES 3.0.6 p150
5624 GLuint _level_max = level_prime_max;
5625 if (tex == immutTex)
5626 {
5627 _level_max = std::min(std::max(level_base, level_prime_max), MIPS - 1);
5628 }
5629 const GLuint level_max = _level_max;
5630
5631 const GLuint p = std::floor((float)std::log2(SIZE)) + level_base;
5632 const GLuint q = std::min(p, level_max);
5633
5634 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level_prime_base);
5635 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level_prime_max);
5636
5637 const bool mipComplete = (q <= MIPS - 1);
5638
5639 for (const GLenum minFilter : MIN_FILTERS)
5640 {
5641 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
5642
5643 for (const GLenum magFilter : MAG_FILTERS)
5644 {
5645 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
5646
5647 for (GLuint dstMip = 0; dstMip < (MIPS + 1); dstMip++)
5648 {
5649 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5650 GL_TEXTURE_2D, tex, dstMip);
5651
5652 // ES3.0 p213-214
5653 bool fbComplete = true;
5654
5655 // * "The width and height of `image` are non-zero"
5656 fbComplete &= (0 <= dstMip && dstMip <= MIPS - 1);
5657
5658 if (tex != immutTex)
5659 { // "...does not name an immutable-format texture..."
5660 // * "...the value of [level] must be in the range `[level_base,
5661 // q]`"
5662 fbComplete &= (level_base <= dstMip && dstMip <= q);
5663
5664 // * "...the value of [level] is not `level_base`, then the texture
5665 // must be mipmap complete"
5666 if (dstMip != level_base)
5667 {
5668 fbComplete &= mipComplete;
5669 }
5670 }
5671
5672 // -
5673 GLenum expectError = 0;
5674 GLenum expectStatus = GL_FRAMEBUFFER_COMPLETE;
5675 if (!fbComplete)
5676 {
5677 expectStatus = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
5678 expectError = GL_INVALID_FRAMEBUFFER_OPERATION;
5679 }
5680
5681 // -
5682 EXPECT_GLENUM_EQ(expectStatus,
5683 glCheckFramebufferStatus(GL_FRAMEBUFFER));
5684
5685 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
5686 EXPECT_EQ(expectError, glGetError());
5687 }
5688 }
5689 }
5690 }
5691 }
5692 }
5693 }
5694
5695 // Test sampling from a texture of a (usually) not color-renderable
5696 // base format with a color-renderable level beyond the max level.
TEST_P(Texture2DBaseMaxTestES3,NotColorRenderableWithColorRenderableBeyondMaxLevel)5697 TEST_P(Texture2DBaseMaxTestES3, NotColorRenderableWithColorRenderableBeyondMaxLevel)
5698 {
5699 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5700
5701 GLTexture texture;
5702 glBindTexture(GL_TEXTURE_2D, texture);
5703 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5704 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5705
5706 const GLuint data[4] = {0xC0040200, 0xC0040200, 0xC0040200, 0xC0040200};
5707 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 2, 2, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, data);
5708 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5709 ASSERT_GL_NO_ERROR();
5710
5711 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5712 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5713 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
5714 }
5715
5716 // Test sampling from a texture of a depth-renderable base format
5717 // with a color-renderable level beyond the max level.
TEST_P(Texture2DBaseMaxTestES3,DepthRenderableWithColorRenderableBeyondMaxLevel)5718 TEST_P(Texture2DBaseMaxTestES3, DepthRenderableWithColorRenderableBeyondMaxLevel)
5719 {
5720 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5721
5722 GLTexture texture;
5723 glBindTexture(GL_TEXTURE_2D, texture);
5724 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5725 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5726
5727 const GLfloat data[4] = {1.0f, 1.0f, 1.0f, 1.0f};
5728 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 2, 2, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
5729 data);
5730 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5731 ASSERT_GL_NO_ERROR();
5732
5733 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5734 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5735 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5736 }
5737
5738 // Test texture sampling while changing the base format from color-renderable
5739 // to (usually) not color-renderable by manipulating base and max levels.
TEST_P(Texture2DBaseMaxTestES3,NotColorRenderableAfterColorRenderableBelowBaseLevel)5740 TEST_P(Texture2DBaseMaxTestES3, NotColorRenderableAfterColorRenderableBelowBaseLevel)
5741 {
5742 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5743
5744 GLTexture texture;
5745 glBindTexture(GL_TEXTURE_2D, texture);
5746 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5747 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5748
5749 std::array<GLColor, 4> data0;
5750 data0.fill(GLColor::green);
5751 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data0.data());
5752
5753 const GLuint data1[1] = {0xC0040200};
5754 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB9_E5, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, data1);
5755 ASSERT_GL_NO_ERROR();
5756
5757 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5758 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5759 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5760
5761 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5762 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
5763 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5764 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
5765 }
5766
5767 // Test texture sampling while changing the base format from color-renderable
5768 // to depth-renderable by manipulating base and max levels.
TEST_P(Texture2DBaseMaxTestES3,DepthRenderableAfterColorRenderableBelowBaseLevel)5769 TEST_P(Texture2DBaseMaxTestES3, DepthRenderableAfterColorRenderableBelowBaseLevel)
5770 {
5771 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5772
5773 GLTexture texture;
5774 glBindTexture(GL_TEXTURE_2D, texture);
5775 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5776 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5777
5778 std::array<GLColor, 4> data0;
5779 data0.fill(GLColor::green);
5780 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data0.data());
5781
5782 const GLfloat data1[1] = {1.0f};
5783 glTexImage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
5784 data1);
5785 ASSERT_GL_NO_ERROR();
5786
5787 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5788 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5789 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5790
5791 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5792 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
5793 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
5794 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5795 }
5796
5797 // Test to check that texture completeness is determined correctly when the texture base level is
5798 // greater than 0, and also that level 0 is not sampled when base level is greater than 0.
TEST_P(Texture2DTestES3,DrawWithBaseLevel1)5799 TEST_P(Texture2DTestES3, DrawWithBaseLevel1)
5800 {
5801 glActiveTexture(GL_TEXTURE0);
5802 glBindTexture(GL_TEXTURE_2D, mTexture2D);
5803
5804 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
5805 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
5806 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
5807 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5808 texDataGreen.data());
5809 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5810 texDataGreen.data());
5811 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5812 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5813 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5814
5815 EXPECT_GL_NO_ERROR();
5816
5817 drawQuad(mProgram, "position", 0.5f);
5818
5819 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5820 }
5821
testCopyImage(const APIExtensionVersion usedExtension)5822 void Texture2DTestES3::testCopyImage(const APIExtensionVersion usedExtension)
5823 {
5824 ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
5825
5826 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
5827 GLTexture srcTexture;
5828 GLTexture destTexture;
5829
5830 glActiveTexture(GL_TEXTURE0);
5831 glBindTexture(GL_TEXTURE_2D, destTexture);
5832 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5833 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5834 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
5835 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
5836 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
5837
5838 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
5839 glBindTexture(GL_TEXTURE_2D, srcTexture);
5840 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5841 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5842 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
5843 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
5844 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5845 texDataGreen.data());
5846
5847 glBindTexture(GL_TEXTURE_2D, 0);
5848
5849 // copy
5850 if (usedExtension == APIExtensionVersion::OES)
5851 {
5852 glCopyImageSubDataOES(srcTexture, GL_TEXTURE_2D, 0, 2, 2, 0, destTexture, GL_TEXTURE_2D, 0,
5853 2, 2, 0, 2, 2, 1);
5854 }
5855 else
5856 {
5857 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 2, 2, 0, destTexture, GL_TEXTURE_2D, 0,
5858 2, 2, 0, 2, 2, 1);
5859 }
5860 glBindTexture(GL_TEXTURE_2D, destTexture);
5861 EXPECT_GL_NO_ERROR();
5862
5863 glViewport(0, 0, 4, 4);
5864 drawQuad(mProgram, "position", 0.5f);
5865 EXPECT_GL_NO_ERROR();
5866
5867 EXPECT_PIXEL_RECT_EQ(2, 2, 2, 2, GLColor::green);
5868 EXPECT_PIXEL_RECT_EQ(0, 0, 4, 2, GLColor::red);
5869 EXPECT_PIXEL_RECT_EQ(0, 0, 2, 4, GLColor::red);
5870 }
5871
5872 // Test basic GL_EXT_copy_image copy without any bound textures
TEST_P(Texture2DTestES3,CopyImageEXT)5873 TEST_P(Texture2DTestES3, CopyImageEXT)
5874 {
5875 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
5876 testCopyImage(APIExtensionVersion::EXT);
5877 }
5878
5879 // Test basic GL_OES_copy_image copy without any bound textures
TEST_P(Texture2DTestES3,CopyImageOES)5880 TEST_P(Texture2DTestES3, CopyImageOES)
5881 {
5882 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_copy_image"));
5883 testCopyImage(APIExtensionVersion::OES);
5884 }
5885
testCopyImageDepthStencil(const APIExtensionVersion usedExtension)5886 void Texture2DTestES3::testCopyImageDepthStencil(const APIExtensionVersion usedExtension)
5887 {
5888 ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES);
5889
5890 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
5891 GLTexture srcTexture;
5892 GLTexture destTexture;
5893
5894 constexpr GLsizei kSize = 4;
5895
5896 GLTexture src;
5897 glBindTexture(GL_TEXTURE_2D, src);
5898 glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
5899
5900 GLTexture dst;
5901 glBindTexture(GL_TEXTURE_2D, dst);
5902 glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
5903
5904 // A color image for testing depth/stencil
5905 GLTexture color;
5906 glBindTexture(GL_TEXTURE_2D, color);
5907 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
5908
5909 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5910 glUseProgram(program);
5911 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
5912 ASSERT_NE(colorLoc, -1);
5913
5914 // Initialize the src depth image
5915 GLFramebuffer fbo;
5916 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5917 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
5918 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, src, 0);
5919 glClearDepthf(0.3f);
5920 glClearStencil(0x57);
5921 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
5922
5923 glEnable(GL_DEPTH_TEST);
5924 glDepthMask(GL_FALSE);
5925 glEnable(GL_STENCIL_TEST);
5926 glStencilFunc(GL_EQUAL, 0x57, 0xFF);
5927 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
5928 glStencilMask(0xFF);
5929
5930 glDepthFunc(GL_LESS);
5931 glUniform4f(colorLoc, 1, 0, 0, 1);
5932 drawQuad(program, essl1_shaders::PositionAttrib(), -0.41f);
5933 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5934
5935 glDepthFunc(GL_GREATER);
5936 glUniform4f(colorLoc, 0, 1, 0, 1);
5937 drawQuad(program, essl1_shaders::PositionAttrib(), -0.39f);
5938 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5939 ASSERT_GL_NO_ERROR();
5940
5941 // Now that the depth stencil image is definitely initialized, copy it into the destination
5942 if (usedExtension == APIExtensionVersion::OES)
5943 {
5944 glCopyImageSubDataOES(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize,
5945 kSize, 1);
5946 }
5947 else
5948 {
5949 glCopyImageSubDataEXT(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize,
5950 kSize, 1);
5951 }
5952 ASSERT_GL_NO_ERROR();
5953
5954 // Verify the dst texture has the right depth/stencil values
5955 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, dst, 0);
5956
5957 glDepthFunc(GL_LESS);
5958 glUniform4f(colorLoc, 0, 0, 1, 1);
5959 drawQuad(program, essl1_shaders::PositionAttrib(), -0.41f);
5960 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5961
5962 glDepthFunc(GL_GREATER);
5963 glUniform4f(colorLoc, 1, 1, 0, 1);
5964 drawQuad(program, essl1_shaders::PositionAttrib(), -0.39f);
5965 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
5966 ASSERT_GL_NO_ERROR();
5967 }
5968
5969 // Test basic GL_EXT_copy_image copy with a depth/stencil texture
TEST_P(Texture2DTestES3,CopyImageEXTDepthStencil)5970 TEST_P(Texture2DTestES3, CopyImageEXTDepthStencil)
5971 {
5972 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
5973 testCopyImageDepthStencil(APIExtensionVersion::EXT);
5974 }
5975
5976 // Test basic GL_OES_copy_image copy with a depth/stencil texture
TEST_P(Texture2DTestES3,CopyImageOESDepthStencil)5977 TEST_P(Texture2DTestES3, CopyImageOESDepthStencil)
5978 {
5979 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_copy_image"));
5980 testCopyImageDepthStencil(APIExtensionVersion::OES);
5981 }
5982
5983 // Test GL_EXT_copy_image compressed texture copy with mipmaps smaller than the block size
TEST_P(Texture2DTestES3,CopyCompressedImageMipMaps)5984 TEST_P(Texture2DTestES3, CopyCompressedImageMipMaps)
5985 {
5986 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
5987 // TODO(http://anglebug.com/5634): Fix calls to vkCmdCopyBufferToImage() with images smaller
5988 // than the compressed format block size.
5989 ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllocateNonZeroMemory));
5990
5991 constexpr uint32_t kSize = 4;
5992 constexpr size_t kNumLevels = 3;
5993 const uint8_t CompressedImageETC1[8] = {0x0, 0x0, 0xf8, 0x2, 0xff, 0xff, 0x0, 0x0};
5994
5995 GLTexture srcTexture;
5996 glBindTexture(GL_TEXTURE_2D, srcTexture);
5997 for (size_t level = 0; level < kNumLevels; ++level)
5998 {
5999 glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, kSize >> level,
6000 kSize >> level, 0, 8, CompressedImageETC1);
6001 EXPECT_GL_NO_ERROR();
6002 }
6003
6004 GLTexture destTexture;
6005 glBindTexture(GL_TEXTURE_2D, destTexture);
6006 for (size_t level = 0; level < kNumLevels; ++level)
6007 {
6008 glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, kSize >> level,
6009 kSize >> level, 0, 8, nullptr);
6010 EXPECT_GL_NO_ERROR();
6011 }
6012
6013 glBindTexture(GL_TEXTURE_2D, 0);
6014
6015 // copy
6016 for (size_t level = 0; level < kNumLevels; ++level)
6017 {
6018 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, level, 0, 0, 0, destTexture, GL_TEXTURE_2D,
6019 level, 0, 0, 0, kSize >> level, kSize >> level, 1);
6020 EXPECT_GL_NO_ERROR();
6021 }
6022 }
6023
6024 // Test GL_EXT_copy_image copy with a non-zero base level
TEST_P(Texture2DTestES3,CopyImageBaseLevel1)6025 TEST_P(Texture2DTestES3, CopyImageBaseLevel1)
6026 {
6027 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
6028
6029 std::vector<GLColor> texDataBlack(8u * 8u, GLColor::black);
6030 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
6031 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
6032 std::vector<GLColor> texDataBlue(4u * 4u, GLColor::blue);
6033
6034 GLTexture srcTexture;
6035 GLTexture destTexture;
6036
6037 glActiveTexture(GL_TEXTURE0);
6038 glBindTexture(GL_TEXTURE_2D, destTexture);
6039 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6040 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6041 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6042 texDataBlack.data());
6043 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
6044 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6045 texDataGreen.data());
6046 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataBlue.data());
6047 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6048 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6049
6050 glBindTexture(GL_TEXTURE_2D, srcTexture);
6051 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6052 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6053 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6054 texDataBlack.data());
6055 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6056 texDataGreen.data());
6057 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataBlue.data());
6058 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
6059 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6060 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6061
6062 glBindTexture(GL_TEXTURE_2D, 0);
6063
6064 // copy
6065 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 1, 2, 2, 0, destTexture, GL_TEXTURE_2D, 1, 2,
6066 2, 0, 2, 2, 1);
6067
6068 glBindTexture(GL_TEXTURE_2D, destTexture);
6069
6070 EXPECT_GL_NO_ERROR();
6071
6072 glViewport(0, 0, 4, 4);
6073 drawQuad(mProgram, "position", 0.5f);
6074 EXPECT_GL_NO_ERROR();
6075
6076 EXPECT_PIXEL_RECT_EQ(2, 2, 2, 2, GLColor::green);
6077 EXPECT_PIXEL_RECT_EQ(0, 0, 4, 2, GLColor::red);
6078 EXPECT_PIXEL_RECT_EQ(0, 0, 2, 4, GLColor::red);
6079 }
6080
6081 // Test basic GL_EXT_copy_image copy without any draw calls by attaching the texture
6082 // to a framebuffer and reads from the framebuffer to validate the copy
TEST_P(Texture2DTestES3,CopyImageFB)6083 TEST_P(Texture2DTestES3, CopyImageFB)
6084 {
6085 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
6086
6087 glViewport(0, 0, 4, 4);
6088 std::vector<GLColor> texDataRed(4u * 4u, GLColor::red);
6089 GLTexture srcTexture;
6090 GLTexture destTexture;
6091
6092 glActiveTexture(GL_TEXTURE0);
6093 glBindTexture(GL_TEXTURE_2D, destTexture);
6094 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6095 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6096 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
6097 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
6098 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
6099
6100 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
6101 glBindTexture(GL_TEXTURE_2D, srcTexture);
6102 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6103 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
6105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
6106 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6107 texDataGreen.data());
6108 glBindTexture(GL_TEXTURE_2D, 0);
6109
6110 // copy
6111 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 0, 0, 0, destTexture, GL_TEXTURE_2D, 0, 0,
6112 1, 0, 3, 3, 1);
6113
6114 EXPECT_GL_NO_ERROR();
6115
6116 GLFramebuffer fb;
6117 glBindFramebuffer(GL_FRAMEBUFFER, fb);
6118 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, destTexture, 0);
6119 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6120
6121 EXPECT_PIXEL_RECT_EQ(0, 1, 3, 3, GLColor::green);
6122 EXPECT_PIXEL_RECT_EQ(3, 0, 1, 4, GLColor::red);
6123 EXPECT_PIXEL_RECT_EQ(0, 0, 4, 1, GLColor::red);
6124
6125 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6126 }
6127
6128 // Test GL_EXT_copy_image copy to a framebuffer attachment after
6129 // invalidation. Then draw with blending onto the framebuffer.
TEST_P(Texture2DTestES3,CopyImageFBInvalidateThenBlend)6130 TEST_P(Texture2DTestES3, CopyImageFBInvalidateThenBlend)
6131 {
6132 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
6133
6134 ANGLE_GL_PROGRAM(drawBlueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
6135 ANGLE_GL_PROGRAM(drawRedProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
6136
6137 glViewport(0, 0, 4, 4);
6138 GLTexture srcTexture;
6139 GLTexture textureAttachment;
6140
6141 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
6142 glBindTexture(GL_TEXTURE_2D, srcTexture);
6143 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6144 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6145 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6146 texDataGreen.data());
6147 glBindTexture(GL_TEXTURE_2D, 0);
6148
6149 glBindTexture(GL_TEXTURE_2D, textureAttachment);
6150 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6151 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6152 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6153 glBindTexture(GL_TEXTURE_2D, 0);
6154
6155 GLFramebuffer fb;
6156 glBindFramebuffer(GL_FRAMEBUFFER, fb);
6157 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureAttachment,
6158 0);
6159 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6160
6161 // Draw something in the texture to make sure it's image is defined.
6162 drawQuad(drawRedProgram, essl1_shaders::PositionAttrib(), 0.0f);
6163
6164 // Invalidate the framebuffer.
6165 const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
6166 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
6167 ASSERT_GL_NO_ERROR();
6168
6169 // Copy into the framebuffer attachment.
6170 glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, 0, 0, 0, 0, textureAttachment, GL_TEXTURE_2D,
6171 0, 0, 0, 0, 4, 4, 1);
6172 EXPECT_GL_NO_ERROR();
6173
6174 // Draw and blend, making sure both the copy and draw happen correctly.
6175 glEnable(GL_BLEND);
6176 glBlendFunc(GL_ONE, GL_ONE);
6177 drawQuad(drawBlueProgram, essl1_shaders::PositionAttrib(), 0.0f);
6178 ASSERT_GL_NO_ERROR();
6179
6180 EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::cyan);
6181
6182 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6183 }
6184
6185 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
6186 // have images defined.
TEST_P(Texture2DTestES3,DrawWithLevelsOutsideRangeUndefined)6187 TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeUndefined)
6188 {
6189 // Observed crashing on AMD. Oddly the crash only happens with 2D textures, not 3D or array.
6190 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
6191
6192 glActiveTexture(GL_TEXTURE0);
6193 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6194 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
6195 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6196 texDataGreen.data());
6197 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6198 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6199 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6200 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6201
6202 EXPECT_GL_NO_ERROR();
6203
6204 drawQuad(mProgram, "position", 0.5f);
6205
6206 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6207 }
6208
6209 // Test that drawing works correctly when level 0 is undefined and base level is 1.
TEST_P(Texture2DTestES3,DrawWithLevelZeroUndefined)6210 TEST_P(Texture2DTestES3, DrawWithLevelZeroUndefined)
6211 {
6212 // Observed crashing on AMD. Oddly the crash only happens with 2D textures, not 3D or array.
6213 ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
6214
6215 glActiveTexture(GL_TEXTURE0);
6216 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6217 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
6218 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6219 texDataGreen.data());
6220 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6221 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6222 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6223 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
6224
6225 EXPECT_GL_NO_ERROR();
6226
6227 // Texture is incomplete.
6228 drawQuad(mProgram, "position", 0.5f);
6229 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6230
6231 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6232 texDataGreen.data());
6233
6234 // Texture is now complete.
6235 drawQuad(mProgram, "position", 0.5f);
6236 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6237 }
6238
6239 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
6240 // dimensions that don't fit the images inside the range.
6241 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,DrawWithLevelsOutsideRangeWithInconsistentDimensions)6242 TEST_P(Texture2DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
6243 {
6244 glActiveTexture(GL_TEXTURE0);
6245 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6246 std::vector<GLColor> texDataRed(8u * 8u, GLColor::red);
6247 std::vector<GLColor> texDataGreen(2u * 2u, GLColor::green);
6248 std::vector<GLColor> texDataCyan(2u * 2u, GLColor::cyan);
6249
6250 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6251 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6252
6253 // Two levels that are initially unused.
6254 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed.data());
6255 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6256 texDataCyan.data());
6257
6258 // One level that is used - only this level should affect completeness.
6259 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6260 texDataGreen.data());
6261
6262 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6263 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6264
6265 EXPECT_GL_NO_ERROR();
6266
6267 drawQuad(mProgram, "position", 0.5f);
6268
6269 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6270
6271 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
6272
6273 // Switch the level that is being used to the cyan level 2.
6274 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
6275 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
6276
6277 EXPECT_GL_NO_ERROR();
6278
6279 drawQuad(mProgram, "position", 0.5f);
6280
6281 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6282 }
6283
6284 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
6285 // have images defined.
TEST_P(Texture3DTestES3,DrawWithLevelsOutsideRangeUndefined)6286 TEST_P(Texture3DTestES3, DrawWithLevelsOutsideRangeUndefined)
6287 {
6288 glActiveTexture(GL_TEXTURE0);
6289 glBindTexture(GL_TEXTURE_3D, mTexture3D);
6290 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
6291 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6292 texDataGreen.data());
6293 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6294 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6295 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 1);
6296 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
6297
6298 EXPECT_GL_NO_ERROR();
6299
6300 drawQuad(mProgram, "position", 0.5f);
6301
6302 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6303 }
6304
6305 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
6306 // dimensions that don't fit the images inside the range.
6307 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture3DTestES3,DrawWithLevelsOutsideRangeWithInconsistentDimensions)6308 TEST_P(Texture3DTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
6309 {
6310 glActiveTexture(GL_TEXTURE0);
6311 glBindTexture(GL_TEXTURE_3D, mTexture3D);
6312 std::vector<GLColor> texDataRed(8u * 8u * 8u, GLColor::red);
6313 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
6314 std::vector<GLColor> texDataCyan(2u * 2u * 2u, GLColor::cyan);
6315
6316 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6317 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6318
6319 // Two levels that are initially unused.
6320 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6321 texDataRed.data());
6322 glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6323 texDataCyan.data());
6324
6325 // One level that is used - only this level should affect completeness.
6326 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6327 texDataGreen.data());
6328
6329 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 1);
6330 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
6331
6332 EXPECT_GL_NO_ERROR();
6333
6334 drawQuad(mProgram, "position", 0.5f);
6335
6336 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6337
6338 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
6339
6340 // Switch the level that is being used to the cyan level 2.
6341 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 2);
6342 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 2);
6343
6344 EXPECT_GL_NO_ERROR();
6345
6346 drawQuad(mProgram, "position", 0.5f);
6347
6348 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6349 }
6350
6351 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range do not
6352 // have images defined.
TEST_P(Texture2DArrayTestES3,DrawWithLevelsOutsideRangeUndefined)6353 TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeUndefined)
6354 {
6355 glActiveTexture(GL_TEXTURE0);
6356 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6357 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
6358 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6359 texDataGreen.data());
6360 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6361 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6362 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
6363 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1);
6364
6365 EXPECT_GL_NO_ERROR();
6366
6367 drawQuad(mProgram, "position", 0.5f);
6368
6369 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6370 }
6371
6372 // Test that drawing works correctly when levels outside the BASE_LEVEL/MAX_LEVEL range have
6373 // dimensions that don't fit the images inside the range.
6374 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DArrayTestES3,DrawWithLevelsOutsideRangeWithInconsistentDimensions)6375 TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensions)
6376 {
6377 // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
6378 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
6379
6380 glActiveTexture(GL_TEXTURE0);
6381 glBindTexture(GL_TEXTURE_3D, m2DArrayTexture);
6382 std::vector<GLColor> texDataRed(8u * 8u * 8u, GLColor::red);
6383 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
6384 std::vector<GLColor> texDataCyan(2u * 2u * 2u, GLColor::cyan);
6385
6386 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6387 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6388
6389 // Two levels that are initially unused.
6390 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6391 texDataRed.data());
6392 glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6393 texDataCyan.data());
6394
6395 // One level that is used - only this level should affect completeness.
6396 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6397 texDataGreen.data());
6398
6399 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
6400 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1);
6401
6402 EXPECT_GL_NO_ERROR();
6403
6404 drawQuad(mProgram, "position", 0.5f);
6405
6406 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6407
6408 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
6409
6410 // Switch the level that is being used to the cyan level 2.
6411 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 2);
6412 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 2);
6413
6414 EXPECT_GL_NO_ERROR();
6415
6416 drawQuad(mProgram, "position", 0.5f);
6417
6418 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6419 }
6420
6421 // Create a 2D array, then immediately redefine it to have fewer layers. Regression test for a bug
6422 // in the Vulkan backend where the old higher-layer-count data upload was not removed.
TEST_P(Texture2DArrayTestES3,TextureArrayRedefineThenUse)6423 TEST_P(Texture2DArrayTestES3, TextureArrayRedefineThenUse)
6424 {
6425 int px = getWindowWidth() / 2;
6426 int py = getWindowHeight() / 2;
6427
6428 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6429
6430 // Fill the whole texture with red, then redefine it and fill with green
6431 std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
6432 std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
6433 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6434 pixelsRed.data());
6435 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6436 pixelsGreen.data());
6437
6438 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6439 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6440 EXPECT_GL_NO_ERROR();
6441
6442 glUseProgram(mProgram);
6443 EXPECT_GL_NO_ERROR();
6444
6445 // Draw the first slice
6446 glUniform1i(mTextureArraySliceUniformLocation, 0);
6447 drawQuad(mProgram, "position", 0.5f);
6448 EXPECT_GL_NO_ERROR();
6449 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
6450
6451 // Draw the second slice
6452 glUniform1i(mTextureArraySliceUniformLocation, 1);
6453 drawQuad(mProgram, "position", 0.5f);
6454 EXPECT_GL_NO_ERROR();
6455 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
6456 }
6457
6458 // Create a 2D array texture and update layers with data and test that pruning
6459 // of superseded updates works as expected.
TEST_P(Texture2DArrayTestES3,TextureArrayPruneSupersededUpdates)6460 TEST_P(Texture2DArrayTestES3, TextureArrayPruneSupersededUpdates)
6461 {
6462 constexpr uint32_t kTexWidth = 256;
6463 constexpr uint32_t kTexHeight = 256;
6464 constexpr uint32_t kTexLayers = 3;
6465
6466 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6467 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6468 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6469 EXPECT_GL_NO_ERROR();
6470
6471 // Initialize entire texture.
6472 constexpr GLColor kInitialExpectedColor = GLColor(201u, 201u, 201u, 201u);
6473 std::vector<GLColor> initialData(kTexWidth * kTexHeight * kTexLayers, kInitialExpectedColor);
6474 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kTexWidth, kTexHeight, kTexLayers, 0, GL_RGBA,
6475 GL_UNSIGNED_BYTE, initialData.data());
6476
6477 // Upate different layers with different colors, these together should supersed
6478 // the entire init update
6479 constexpr GLColor kExpectedColor[] = {GLColor(32u, 32u, 32u, 32u), GLColor(64u, 64u, 64u, 64u),
6480 GLColor(128u, 128u, 128u, 128u)};
6481 std::vector<GLColor> supersedingData[] = {
6482 std::vector<GLColor>(kTexWidth * kTexHeight, kExpectedColor[0]),
6483 std::vector<GLColor>(kTexWidth * kTexHeight, kExpectedColor[1]),
6484 std::vector<GLColor>(kTexWidth * kTexHeight, kExpectedColor[2])};
6485
6486 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kTexWidth, kTexHeight, 1, GL_RGBA,
6487 GL_UNSIGNED_BYTE, supersedingData[0].data());
6488 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, kTexWidth, kTexHeight, 1, GL_RGBA,
6489 GL_UNSIGNED_BYTE, supersedingData[1].data());
6490 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, kTexWidth, kTexHeight, 1, GL_RGBA,
6491 GL_UNSIGNED_BYTE, supersedingData[2].data());
6492
6493 glUseProgram(mProgram);
6494 EXPECT_GL_NO_ERROR();
6495
6496 // Draw layer 0
6497 glUniform1i(mTextureArraySliceUniformLocation, 0);
6498 drawQuad(mProgram, "position", 0.5f);
6499 EXPECT_GL_NO_ERROR();
6500 EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[0]);
6501
6502 // Draw layer 1
6503 glUniform1i(mTextureArraySliceUniformLocation, 1);
6504 drawQuad(mProgram, "position", 0.5f);
6505 EXPECT_GL_NO_ERROR();
6506 EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[1]);
6507
6508 // Draw layer 2
6509 glUniform1i(mTextureArraySliceUniformLocation, 2);
6510 drawQuad(mProgram, "position", 0.5f);
6511 EXPECT_GL_NO_ERROR();
6512 EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor[2]);
6513 }
6514
6515 // Create a 2D array, use it, then redefine it to have fewer layers. Regression test for a bug in
6516 // the Vulkan backend where the old higher-layer-count data upload was not removed.
TEST_P(Texture2DArrayTestES3,TextureArrayUseThenRedefineThenUse)6517 TEST_P(Texture2DArrayTestES3, TextureArrayUseThenRedefineThenUse)
6518 {
6519 int px = getWindowWidth() / 2;
6520 int py = getWindowHeight() / 2;
6521
6522 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6523
6524 // Fill the whole texture with red.
6525 std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
6526 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6527 pixelsRed.data());
6528
6529 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6530 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6531 EXPECT_GL_NO_ERROR();
6532
6533 glUseProgram(mProgram);
6534 EXPECT_GL_NO_ERROR();
6535
6536 // Draw the first slice
6537 glUniform1i(mTextureArraySliceUniformLocation, 0);
6538 drawQuad(mProgram, "position", 0.5f);
6539 EXPECT_GL_NO_ERROR();
6540 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
6541
6542 // Draw the fourth slice
6543 glUniform1i(mTextureArraySliceUniformLocation, 3);
6544 drawQuad(mProgram, "position", 0.5f);
6545 EXPECT_GL_NO_ERROR();
6546 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
6547
6548 // Redefine the image and fill with green
6549 std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
6550 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6551 pixelsGreen.data());
6552
6553 // Draw the first slice
6554 glUniform1i(mTextureArraySliceUniformLocation, 0);
6555 drawQuad(mProgram, "position", 0.5f);
6556 EXPECT_GL_NO_ERROR();
6557 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
6558
6559 // Draw the second slice
6560 glUniform1i(mTextureArraySliceUniformLocation, 1);
6561 drawQuad(mProgram, "position", 0.5f);
6562 EXPECT_GL_NO_ERROR();
6563 EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
6564 }
6565
6566 // Create a 2D array texture, use it, then redefine one level without changing dimensions.
TEST_P(Texture2DArrayTestES3,RedefineLevelData)6567 TEST_P(Texture2DArrayTestES3, RedefineLevelData)
6568 {
6569 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
6570
6571 // Fill both levels with red
6572 std::vector<GLColor> pixelsRed(2 * 2 * 1, GLColor::red);
6573 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6574 pixelsRed.data());
6575 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6576 pixelsRed.data());
6577 ASSERT_GL_NO_ERROR();
6578
6579 // Check that both levels are red
6580 GLFramebuffer fbo;
6581 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6582 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0);
6583 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6584 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 1, 0);
6585 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6586
6587 // Redefine level 1 with green
6588 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6589 &GLColor::green);
6590 ASSERT_GL_NO_ERROR();
6591
6592 // Check that level 0 is red and level 1 is green
6593 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 0, 0);
6594 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6595 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m2DArrayTexture, 1, 0);
6596 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6597 }
6598
6599 // Create a 3D texture, use it, then redefine one level without changing dimensions.
TEST_P(Texture3DTestES3,RedefineLevelData)6600 TEST_P(Texture3DTestES3, RedefineLevelData)
6601 {
6602 glBindTexture(GL_TEXTURE_3D, mTexture3D);
6603
6604 // Fill both levels with red
6605 std::vector<GLColor> pixelsRed(2 * 2 * 1, GLColor::red);
6606 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6607 pixelsRed.data());
6608 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6609 pixelsRed.data());
6610 ASSERT_GL_NO_ERROR();
6611
6612 // Check that both levels are red
6613 GLFramebuffer fbo;
6614 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6615 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 0, 0);
6616 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6617 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 1, 0);
6618 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6619
6620 // Redefine level 1 with green
6621 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6622 &GLColor::green);
6623 ASSERT_GL_NO_ERROR();
6624
6625 // Check that level 0 is red and level 1 is green
6626 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 0, 0);
6627 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6628 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture3D, 1, 0);
6629 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6630 }
6631
6632 // Test that texture completeness is updated if texture max level changes.
6633 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,TextureCompletenessChangesWithMaxLevel)6634 TEST_P(Texture2DTestES3, TextureCompletenessChangesWithMaxLevel)
6635 {
6636 glActiveTexture(GL_TEXTURE0);
6637 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6638 std::vector<GLColor> texDataGreen(8u * 8u, GLColor::green);
6639
6640 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6641 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6642
6643 // A level that is initially unused.
6644 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6645 texDataGreen.data());
6646
6647 // One level that is initially used - only this level should affect completeness.
6648 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6649 texDataGreen.data());
6650
6651 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6652 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6653
6654 EXPECT_GL_NO_ERROR();
6655
6656 drawQuad(mProgram, "position", 0.5f);
6657
6658 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6659
6660 // Switch the max level to level 1. The levels within the used range now have inconsistent
6661 // dimensions and the texture should be incomplete.
6662 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6663
6664 EXPECT_GL_NO_ERROR();
6665
6666 drawQuad(mProgram, "position", 0.5f);
6667
6668 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6669 }
6670
6671 // Test a bug that staged clear overlaps with glTexSubImage with multiple layers may incorrectly
6672 // keep the staged clear. http://anglebug.com/345532371
TEST_P(Texture2DArrayTestES3,ClearThenTexSubImageWithOverlappingLayersThenRead)6673 TEST_P(Texture2DArrayTestES3, ClearThenTexSubImageWithOverlappingLayersThenRead)
6674 {
6675 constexpr GLsizei kTexWidth = 128;
6676 constexpr GLsizei kTexHeight = 128;
6677 constexpr GLsizei kTexDepth = 6;
6678 // Create a single leveled texture with 6 layers
6679 GLTexture tex;
6680 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
6681 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kTexWidth, kTexHeight, kTexDepth);
6682
6683 // Stage clear to red on all layers
6684 GLFramebuffer drawFBO;
6685 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
6686 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
6687 for (GLsizei layer = 0; layer < kTexDepth; layer++)
6688 {
6689 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer);
6690 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
6691 glClear(GL_COLOR_BUFFER_BIT);
6692 }
6693
6694 // TexSubImage with green color on half of the image of layer 2,3,4
6695 std::vector<GLColor> updateData((kTexWidth / 2) * kTexHeight * 3, GLColor::green);
6696 GLsizei layerStart = 2;
6697 GLsizei layerCount = 3;
6698 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layerStart, kTexWidth / 2, kTexHeight, layerCount,
6699 GL_RGBA, GL_UNSIGNED_BYTE, updateData.data());
6700
6701 // Now read out layer 2/3/4
6702 GLFramebuffer readFBO;
6703 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
6704 for (GLsizei layer = layerStart; layer < layerStart + layerCount; layer++)
6705 {
6706 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer);
6707 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
6708 EXPECT_PIXEL_EQ(kTexWidth / 4, kTexHeight / 2, GLColor::green.R, GLColor::green.G,
6709 GLColor::green.B, GLColor::green.A);
6710 EXPECT_PIXEL_EQ(3 * kTexWidth / 4, kTexHeight / 2, GLColor::red.R, GLColor::red.G,
6711 GLColor::red.B, GLColor::red.A);
6712 }
6713 ASSERT_GL_NO_ERROR();
6714 }
6715
6716 // Test a bug that staged clear overlaps with glTexSubImage with multiple layers may incorrectly
6717 // keep the staged clear. http://anglebug.com/345532371
TEST_P(Texture2DArrayTestES3,ClearThenTexSubImageWithOverlappingLayersThenDrawAndRead)6718 TEST_P(Texture2DArrayTestES3, ClearThenTexSubImageWithOverlappingLayersThenDrawAndRead)
6719 {
6720 constexpr GLsizei kTexWidth = 128;
6721 constexpr GLsizei kTexHeight = 128;
6722 constexpr GLsizei kTexDepth = 6;
6723 // Create a single leveled texture with 6 layers
6724 GLTexture tex;
6725 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
6726 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kTexWidth, kTexHeight, kTexDepth);
6727
6728 // Stage clear to red on all layers
6729 GLFramebuffer drawFBO;
6730 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
6731 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
6732 for (GLsizei layer = 0; layer < kTexDepth; layer++)
6733 {
6734 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer);
6735 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
6736 glClear(GL_COLOR_BUFFER_BIT);
6737 }
6738
6739 // TexSubImage with green color on half of the image of layer 2,3,4
6740 std::vector<GLColor> updateData((kTexWidth / 2) * kTexHeight * 3, GLColor::green);
6741 GLsizei layerStart = 2;
6742 GLsizei layerCount = 3;
6743 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layerStart, kTexWidth / 2, kTexHeight, layerCount,
6744 GL_RGBA, GL_UNSIGNED_BYTE, updateData.data());
6745
6746 // Now Draw to fbo on layerStart with blue color
6747 GLsizei blueQuadLayer = 2;
6748 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, blueQuadLayer);
6749 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
6750 glEnable(GL_BLEND);
6751 glBlendFunc(GL_ONE, GL_ONE);
6752 ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Simple(), essl3_shaders::fs::Blue());
6753 glUseProgram(blueProgram);
6754 drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f);
6755
6756 // Now read out layer 2/3/4
6757 GLFramebuffer readFBO;
6758 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
6759 for (GLsizei layer = layerStart; layer < layerStart + layerCount; layer++)
6760 {
6761 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, layer);
6762 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
6763 if (layer == blueQuadLayer)
6764 {
6765 // green + blue = cyan
6766 EXPECT_PIXEL_EQ(kTexWidth / 4, kTexHeight / 2, GLColor::cyan.R, GLColor::cyan.G,
6767 GLColor::cyan.B, GLColor::cyan.A);
6768 // red + blue = magenta
6769 EXPECT_PIXEL_EQ(3 * kTexWidth / 4, kTexHeight / 2, GLColor::magenta.R,
6770 GLColor::magenta.G, GLColor::magenta.B, GLColor::magenta.A);
6771 }
6772 else
6773 {
6774 EXPECT_PIXEL_EQ(kTexWidth / 4, kTexHeight / 2, GLColor::green.R, GLColor::green.G,
6775 GLColor::green.B, GLColor::green.A);
6776 EXPECT_PIXEL_EQ(3 * kTexWidth / 4, kTexHeight / 2, GLColor::red.R, GLColor::red.G,
6777 GLColor::red.B, GLColor::red.A);
6778 }
6779 }
6780 ASSERT_GL_NO_ERROR();
6781 }
6782
6783 // Test that compressed textures ignore the pixel unpack state.
6784 // (https://crbug.org/1267496)
TEST_P(Texture3DTestES3,PixelUnpackStateTexImage)6785 TEST_P(Texture3DTestES3, PixelUnpackStateTexImage)
6786 {
6787 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
6788 !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
6789
6790 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5);
6791 glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
6792
6793 uint8_t data[64] = {0};
6794 glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64,
6795 data);
6796 EXPECT_GL_NO_ERROR();
6797 }
6798
6799 // Test that compressed textures ignore the pixel unpack state.
6800 // (https://crbug.org/1267496)
TEST_P(Texture3DTestES3,PixelUnpackStateTexSubImage)6801 TEST_P(Texture3DTestES3, PixelUnpackStateTexSubImage)
6802 {
6803 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
6804 !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
6805
6806 glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
6807
6808 uint8_t data[64] = {0};
6809 glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64,
6810 data);
6811 EXPECT_GL_NO_ERROR();
6812
6813 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5);
6814
6815 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 4,
6816 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64, data);
6817 EXPECT_GL_NO_ERROR();
6818 }
6819
6820 // Test that 3D texture completeness is updated if texture max level changes.
6821 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture3DTestES3,Texture3DCompletenessChangesWithMaxLevel)6822 TEST_P(Texture3DTestES3, Texture3DCompletenessChangesWithMaxLevel)
6823 {
6824 glActiveTexture(GL_TEXTURE0);
6825 glBindTexture(GL_TEXTURE_3D, mTexture3D);
6826 std::vector<GLColor> texDataGreen(2u * 2u * 2u, GLColor::green);
6827
6828 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6829 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6830
6831 // A level that is initially unused.
6832 glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 1, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6833 texDataGreen.data());
6834
6835 // One level that is initially used - only this level should affect completeness.
6836 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6837 texDataGreen.data());
6838
6839 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
6840 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0);
6841
6842 EXPECT_GL_NO_ERROR();
6843
6844 drawQuad(mProgram, "position", 0.5f);
6845
6846 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6847
6848 // Switch the max level to level 1. The levels within the used range now have inconsistent
6849 // dimensions and the texture should be incomplete.
6850 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1);
6851
6852 EXPECT_GL_NO_ERROR();
6853
6854 drawQuad(mProgram, "position", 0.5f);
6855
6856 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6857 }
6858
6859 // Test that texture completeness is updated if texture base level changes.
6860 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,TextureCompletenessChangesWithBaseLevel)6861 TEST_P(Texture2DTestES3, TextureCompletenessChangesWithBaseLevel)
6862 {
6863 glActiveTexture(GL_TEXTURE0);
6864 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6865 std::vector<GLColor> texDataGreen(8u * 8u, GLColor::green);
6866
6867 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6868 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6869
6870 // Two levels that are initially unused.
6871 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6872 texDataGreen.data());
6873 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6874 texDataGreen.data());
6875
6876 // One level that is initially used - only this level should affect completeness.
6877 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6878 texDataGreen.data());
6879
6880 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
6881 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
6882
6883 EXPECT_GL_NO_ERROR();
6884
6885 drawQuad(mProgram, "position", 0.5f);
6886
6887 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6888
6889 // Switch the base level to level 1. The levels within the used range now have inconsistent
6890 // dimensions and the texture should be incomplete.
6891 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6892
6893 EXPECT_GL_NO_ERROR();
6894
6895 drawQuad(mProgram, "position", 0.5f);
6896
6897 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6898 }
6899
6900 // Test that texture is not complete if base level is greater than max level.
6901 // GLES 3.0.4 section 3.8.13 Texture completeness
TEST_P(Texture2DTestES3,TextureBaseLevelGreaterThanMaxLevel)6902 TEST_P(Texture2DTestES3, TextureBaseLevelGreaterThanMaxLevel)
6903 {
6904 glActiveTexture(GL_TEXTURE0);
6905 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6906
6907 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6908 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6909
6910 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
6911
6912 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
6913 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6914
6915 EXPECT_GL_NO_ERROR();
6916
6917 drawQuad(mProgram, "position", 0.5f);
6918
6919 // Texture should be incomplete.
6920 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6921 }
6922
6923 // Test that immutable texture base level and max level are clamped.
6924 // GLES 3.0.4 section 3.8.10 subsection Mipmapping
TEST_P(Texture2DTestES3,ImmutableTextureBaseLevelOutOfRange)6925 TEST_P(Texture2DTestES3, ImmutableTextureBaseLevelOutOfRange)
6926 {
6927 glActiveTexture(GL_TEXTURE0);
6928 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6929
6930 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6931 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6932
6933 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
6934
6935 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
6936
6937 // For immutable-format textures, base level should be clamped to [0, levels - 1], and max level
6938 // should be clamped to [base_level, levels - 1].
6939 // GLES 3.0.4 section 3.8.10 subsection Mipmapping
6940 // In the case of this test, those rules make the effective base level and max level 0.
6941 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
6942 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10000);
6943
6944 EXPECT_GL_NO_ERROR();
6945
6946 drawQuad(mProgram, "position", 0.5f);
6947
6948 // Texture should be complete.
6949 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6950 }
6951
6952 // Test that changing base level works when it affects the format of the texture.
TEST_P(Texture2DTestES3,TextureFormatChangesWithBaseLevel)6953 TEST_P(Texture2DTestES3, TextureFormatChangesWithBaseLevel)
6954 {
6955 // TODO(crbug.com/998505): Test failing on Android FYI Release (NVIDIA Shield TV)
6956 ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
6957
6958 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsDesktopOpenGL());
6959
6960 // Observed incorrect rendering on AMD OpenGL.
6961 ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
6962
6963 glActiveTexture(GL_TEXTURE0);
6964 glBindTexture(GL_TEXTURE_2D, mTexture2D);
6965 std::vector<GLColor> texDataCyan(4u * 4u, GLColor::cyan);
6966 std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
6967
6968 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6969 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6970
6971 // RGBA8 level that's initially unused.
6972 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6973 texDataCyan.data());
6974
6975 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6976 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6977
6978 // RG8 level that's initially used, with consistent dimensions with level 0 but a different
6979 // format. It reads green channel data from the green and alpha channels of texDataGreen
6980 // (this is a bit hacky but works).
6981 glTexImage2D(GL_TEXTURE_2D, 1, GL_RG8, 2, 2, 0, GL_RG, GL_UNSIGNED_BYTE, texDataGreen.data());
6982
6983 EXPECT_GL_NO_ERROR();
6984
6985 drawQuad(mProgram, "position", 0.5f);
6986
6987 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6988
6989 // Switch the texture to use the cyan level 0 with the RGBA format.
6990 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6991 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6992
6993 EXPECT_GL_NO_ERROR();
6994
6995 drawQuad(mProgram, "position", 0.5f);
6996
6997 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6998 }
6999
7000 // Test that setting a texture image works when base level is out of range.
TEST_P(Texture2DTestES3,SetImageWhenBaseLevelOutOfRange)7001 TEST_P(Texture2DTestES3, SetImageWhenBaseLevelOutOfRange)
7002 {
7003 glActiveTexture(GL_TEXTURE0);
7004 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7005
7006 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7007 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7008
7009 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 10000);
7010 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 10000);
7011
7012 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
7013
7014 EXPECT_GL_NO_ERROR();
7015
7016 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7017
7018 drawQuad(mProgram, "position", 0.5f);
7019
7020 // Texture should be complete.
7021 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7022 }
7023
7024 // In the D3D11 renderer, we need to initialize some texture formats, to fill empty channels. EG
7025 // RBA->RGBA8, with 1.0 in the alpha channel. This test covers a bug where redefining array textures
7026 // with these formats does not work as expected.
TEST_P(Texture2DArrayTestES3,RedefineInittableArray)7027 TEST_P(Texture2DArrayTestES3, RedefineInittableArray)
7028 {
7029 std::vector<GLubyte> pixelData;
7030 for (size_t count = 0; count < 5000; count++)
7031 {
7032 pixelData.push_back(0u);
7033 pixelData.push_back(255u);
7034 pixelData.push_back(0u);
7035 }
7036
7037 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
7038 glUseProgram(mProgram);
7039 glUniform1i(mTextureArrayLocation, 0);
7040
7041 // The first draw worked correctly.
7042 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE,
7043 &pixelData[0]);
7044
7045 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7046 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7047 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
7048 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
7049 drawQuad(mProgram, "position", 1.0f);
7050 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7051
7052 // The dimension of the respecification must match the original exactly to trigger the bug.
7053 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE,
7054 &pixelData[0]);
7055 drawQuad(mProgram, "position", 1.0f);
7056 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7057
7058 ASSERT_GL_NO_ERROR();
7059 }
7060
7061 // Test shadow sampler and regular non-shadow sampler coexisting in the same shader.
7062 // This test is needed especially to confirm that sampler registers get assigned correctly on
7063 // the HLSL backend even when there's a mix of different HLSL sampler and texture types.
TEST_P(ShadowSamplerPlusSampler3DTestES3,ShadowSamplerPlusSampler3DDraw)7064 TEST_P(ShadowSamplerPlusSampler3DTestES3, ShadowSamplerPlusSampler3DDraw)
7065 {
7066 glActiveTexture(GL_TEXTURE0);
7067 glBindTexture(GL_TEXTURE_3D, mTexture3D);
7068 GLubyte texData[4];
7069 texData[0] = 0;
7070 texData[1] = 60;
7071 texData[2] = 0;
7072 texData[3] = 255;
7073 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7074
7075 glActiveTexture(GL_TEXTURE1);
7076 glBindTexture(GL_TEXTURE_2D, mTextureShadow);
7077 GLfloat depthTexData[1];
7078 depthTexData[0] = 0.5f;
7079 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
7080 depthTexData);
7081
7082 glUseProgram(mProgram);
7083 glUniform1f(mDepthRefUniformLocation, 0.3f);
7084 glUniform1i(mTexture3DUniformLocation, 0);
7085 glUniform1i(mTextureShadowUniformLocation, 1);
7086
7087 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
7088 drawQuad(mProgram, "position", 0.5f);
7089 EXPECT_GL_NO_ERROR();
7090 // The shader writes 0.5 * <comparison result (1.0)> + <texture color>
7091 EXPECT_PIXEL_NEAR(0, 0, 128, 188, 128, 255, 2);
7092
7093 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GREATER);
7094 drawQuad(mProgram, "position", 0.5f);
7095 EXPECT_GL_NO_ERROR();
7096 // The shader writes 0.5 * <comparison result (0.0)> + <texture color>
7097 EXPECT_PIXEL_NEAR(0, 0, 0, 60, 0, 255, 2);
7098 }
7099
7100 // Test multiple different sampler types in the same shader.
7101 // This test makes sure that even if sampler / texture registers get grouped together based on type
7102 // or otherwise get shuffled around in the HLSL backend of the shader translator, the D3D renderer
7103 // still has the right register index information for each ESSL sampler.
7104 // The tested ESSL samplers have the following types in D3D11 HLSL:
7105 // sampler2D: Texture2D + SamplerState
7106 // samplerCube: TextureCube + SamplerState
7107 // sampler2DShadow: Texture2D + SamplerComparisonState
7108 // samplerCubeShadow: TextureCube + SamplerComparisonState
TEST_P(SamplerTypeMixTestES3,SamplerTypeMixDraw)7109 TEST_P(SamplerTypeMixTestES3, SamplerTypeMixDraw)
7110 {
7111 glActiveTexture(GL_TEXTURE0);
7112 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7113 GLubyte texData[4];
7114 texData[0] = 0;
7115 texData[1] = 0;
7116 texData[2] = 120;
7117 texData[3] = 255;
7118 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
7119
7120 glActiveTexture(GL_TEXTURE1);
7121 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
7122 texData[0] = 0;
7123 texData[1] = 90;
7124 texData[2] = 0;
7125 texData[3] = 255;
7126 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 1, 1);
7127 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
7128 texData);
7129
7130 glActiveTexture(GL_TEXTURE2);
7131 glBindTexture(GL_TEXTURE_2D, mTexture2DShadow);
7132 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
7133 GLfloat depthTexData[1];
7134 depthTexData[0] = 0.5f;
7135 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 1, 1, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
7136 depthTexData);
7137
7138 glActiveTexture(GL_TEXTURE3);
7139 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCubeShadow);
7140 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
7141 depthTexData[0] = 0.2f;
7142 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_DEPTH_COMPONENT32F, 1, 1);
7143 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT,
7144 depthTexData);
7145
7146 // http://anglebug.com/3949: TODO: Add a DS texture case
7147
7148 EXPECT_GL_NO_ERROR();
7149
7150 glUseProgram(mProgram);
7151 glUniform1f(mDepthRefUniformLocation, 0.3f);
7152 glUniform1i(mTexture2DUniformLocation, 0);
7153 glUniform1i(mTextureCubeUniformLocation, 1);
7154 glUniform1i(mTexture2DShadowUniformLocation, 2);
7155 glUniform1i(mTextureCubeShadowUniformLocation, 3);
7156
7157 drawQuad(mProgram, "position", 0.5f);
7158 EXPECT_GL_NO_ERROR();
7159 // The shader writes:
7160 // <texture 2d color> +
7161 // <cube map color> +
7162 // 0.25 * <comparison result (1.0)> +
7163 // 0.125 * <comparison result (0.0)>
7164 EXPECT_PIXEL_NEAR(0, 0, 64, 154, 184, 255, 2);
7165 }
7166
7167 // Test different base levels on textures accessed through the same sampler array.
7168 // Calling textureSize() on the samplers hits the D3D sampler metadata workaround.
TEST_P(TextureSizeTextureArrayTest,BaseLevelVariesInTextureArray)7169 TEST_P(TextureSizeTextureArrayTest, BaseLevelVariesInTextureArray)
7170 {
7171 ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D11());
7172
7173 // http://anglebug.com/4391
7174 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsWindows() && IsD3D11());
7175
7176 glActiveTexture(GL_TEXTURE0);
7177 glBindTexture(GL_TEXTURE_2D, mTexture2DA);
7178 GLsizei size = 64;
7179 for (GLint level = 0; level < 7; ++level)
7180 {
7181 ASSERT_LT(0, size);
7182 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7183 nullptr);
7184 size = size / 2;
7185 }
7186 ASSERT_EQ(0, size);
7187 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
7188
7189 glActiveTexture(GL_TEXTURE1);
7190 glBindTexture(GL_TEXTURE_2D, mTexture2DB);
7191 size = 128;
7192 for (GLint level = 0; level < 8; ++level)
7193 {
7194 ASSERT_LT(0, size);
7195 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7196 nullptr);
7197 size = size / 2;
7198 }
7199 ASSERT_EQ(0, size);
7200 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 3);
7201 EXPECT_GL_NO_ERROR();
7202
7203 glUseProgram(mProgram);
7204 glUniform1i(mTexture0Location, 0);
7205 glUniform1i(mTexture1Location, 1);
7206
7207 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
7208 EXPECT_GL_NO_ERROR();
7209 // Red channel: width of level 1 of texture A: 32.
7210 // Green channel: width of level 3 of texture B: 16.
7211 EXPECT_PIXEL_NEAR(0, 0, 32, 16, 0, 255, 2);
7212 }
7213
7214 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7215 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGBImplicitAlpha1)7216 TEST_P(Texture2DTestES3, TextureRGBImplicitAlpha1)
7217 {
7218 glActiveTexture(GL_TEXTURE0);
7219 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7220 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
7221 EXPECT_GL_NO_ERROR();
7222
7223 drawQuad(mProgram, "position", 0.5f);
7224
7225 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7226 }
7227
7228 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7229 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGBXImplicitAlpha1)7230 TEST_P(Texture2DTestES3, TextureRGBXImplicitAlpha1)
7231 {
7232 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format"));
7233
7234 GLTexture texture2D;
7235 glBindTexture(GL_TEXTURE_2D, texture2D);
7236 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBX8_ANGLE, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
7237 glActiveTexture(GL_TEXTURE0);
7238 EXPECT_GL_NO_ERROR();
7239
7240 drawQuad(mProgram, "position", 0.5f);
7241
7242 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7243 }
7244
7245 // Test that data upload to RGBX works.
TEST_P(Texture2DTestES3,TextureRGBXUpload)7246 TEST_P(Texture2DTestES3, TextureRGBXUpload)
7247 {
7248 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format"));
7249
7250 const size_t kWidth = 32;
7251 const size_t kHeight = 32;
7252
7253 GLTexture color;
7254 glBindTexture(GL_TEXTURE_2D, color);
7255 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
7256
7257 GLFramebuffer fbo;
7258 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7259 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
7260 ASSERT_GL_NO_ERROR();
7261 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7262
7263 // Upload data to an RGBX texture
7264 const GLColorRGB kColor(100, 200, 55);
7265 std::vector<GLColorRGB> data(kWidth * kHeight, kColor);
7266
7267 GLTexture texture;
7268 glBindTexture(GL_TEXTURE_2D, texture);
7269 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBX8_ANGLE, kWidth, kHeight);
7270 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7271 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7272 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, data.data());
7273 ASSERT_GL_NO_ERROR();
7274
7275 // Sample from the texture
7276 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
7277 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
7278
7279 const GLColor kExpect(kColor.R, kColor.G, kColor.B, 255);
7280 EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
7281 EXPECT_PIXEL_COLOR_NEAR(0, 1, kExpect, 1);
7282 EXPECT_PIXEL_COLOR_NEAR(1, 0, kExpect, 1);
7283 EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, 0, kExpect, 1);
7284 EXPECT_PIXEL_COLOR_NEAR(0, kHeight - 1, kExpect, 1);
7285 EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, kHeight - 1, kExpect, 1);
7286 EXPECT_PIXEL_COLOR_NEAR(kWidth / 2, kHeight / 2, kExpect, 1);
7287 ASSERT_GL_NO_ERROR();
7288 }
7289
7290 // Test that data download from RGBX works.
TEST_P(Texture2DTestES3,TextureRGBXDownload)7291 TEST_P(Texture2DTestES3, TextureRGBXDownload)
7292 {
7293 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_rgbx_internal_format"));
7294
7295 const size_t kWidth = 32;
7296 const size_t kHeight = 32;
7297
7298 GLTexture color;
7299 glBindTexture(GL_TEXTURE_2D, color);
7300 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBX8_ANGLE, kWidth, kHeight);
7301
7302 GLFramebuffer fbo;
7303 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7304 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
7305 ASSERT_GL_NO_ERROR();
7306 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7307
7308 // Render to the RGBX texture
7309 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
7310 glUseProgram(program);
7311 GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
7312 ASSERT_NE(colorLoc, -1);
7313
7314 glUniform4f(colorLoc, 0.3f, 0.6f, 0.8f, 0.2f);
7315 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
7316 ASSERT_GL_NO_ERROR();
7317
7318 // Readback as RGBX.
7319 std::vector<GLColor> readback(kWidth * kHeight);
7320 glReadPixels(0, 0, kWidth, kHeight, GL_RGBX8_ANGLE, GL_UNSIGNED_BYTE, readback.data());
7321 ASSERT_GL_NO_ERROR();
7322
7323 const GLColor kExpect(76, // 0.3f * 255
7324 153, // 0.6f * 255
7325 204, // 0.8f * 255
7326 255);
7327
7328 for (size_t y = 0; y < kHeight; y++)
7329 {
7330 for (size_t x = 0; x < kWidth; x++)
7331 {
7332 const GLColor actualColor = readback[y * kWidth + x];
7333
7334 EXPECT_NEAR(actualColor.R, kExpect.R, 1) << x << "x" << y;
7335 EXPECT_NEAR(actualColor.G, kExpect.G, 1) << x << "x" << y;
7336 EXPECT_NEAR(actualColor.B, kExpect.B, 1) << x << "x" << y;
7337 EXPECT_EQ(actualColor.A, kExpect.A) << x << "x" << y;
7338 }
7339 }
7340 ASSERT_GL_NO_ERROR();
7341 }
7342
7343 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7344 // ES 3.0.4 table 3.24
TEST_P(Texture2DTest,TextureLuminanceImplicitAlpha1)7345 TEST_P(Texture2DTest, TextureLuminanceImplicitAlpha1)
7346 {
7347 setUpProgram();
7348
7349 glActiveTexture(GL_TEXTURE0);
7350 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7351 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr);
7352 EXPECT_GL_NO_ERROR();
7353
7354 drawQuad(mProgram, "position", 0.5f);
7355
7356 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7357 }
7358
7359 // Validate that every component of the pixel will be equal to the luminance value we've set
7360 // and that the alpha channel will be 1 (or 255 to be exact).
TEST_P(Texture2DTest,TextureLuminanceRGBSame)7361 TEST_P(Texture2DTest, TextureLuminanceRGBSame)
7362 {
7363 setUpProgram();
7364
7365 glActiveTexture(GL_TEXTURE0);
7366 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7367 uint8_t pixel = 50;
7368 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &pixel);
7369 EXPECT_GL_NO_ERROR();
7370
7371 drawQuad(mProgram, "position", 0.5f);
7372
7373 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(pixel, pixel, pixel, 255));
7374 }
7375
7376 // Validate that every component of the pixel will be equal to the luminance value we've set
7377 // and that the alpha channel will be the second component.
TEST_P(Texture2DTest,TextureLuminanceAlphaRGBSame)7378 TEST_P(Texture2DTest, TextureLuminanceAlphaRGBSame)
7379 {
7380 setUpProgram();
7381
7382 glActiveTexture(GL_TEXTURE0);
7383 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7384 uint8_t pixel[] = {50, 25};
7385 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 1, 1, 0, GL_LUMINANCE_ALPHA,
7386 GL_UNSIGNED_BYTE, pixel);
7387 EXPECT_GL_NO_ERROR();
7388
7389 drawQuad(mProgram, "position", 0.5f);
7390
7391 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(pixel[0], pixel[0], pixel[0], pixel[1]));
7392 }
7393
7394 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7395 // ES 3.0.4 table 3.24
TEST_P(Texture2DTest,TextureLuminance32ImplicitAlpha1)7396 TEST_P(Texture2DTest, TextureLuminance32ImplicitAlpha1)
7397 {
7398 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
7399 ANGLE_SKIP_TEST_IF(IsD3D9());
7400 ANGLE_SKIP_TEST_IF(IsVulkan());
7401
7402 setUpProgram();
7403
7404 glActiveTexture(GL_TEXTURE0);
7405 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7406 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_FLOAT, nullptr);
7407 EXPECT_GL_NO_ERROR();
7408
7409 drawQuad(mProgram, "position", 0.5f);
7410
7411 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7412 }
7413
7414 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7415 // ES 3.0.4 table 3.24
TEST_P(Texture2DTest,TextureLuminance16ImplicitAlpha1)7416 TEST_P(Texture2DTest, TextureLuminance16ImplicitAlpha1)
7417 {
7418 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
7419 ANGLE_SKIP_TEST_IF(IsD3D9());
7420 ANGLE_SKIP_TEST_IF(IsVulkan());
7421 // TODO(ynovikov): re-enable once root cause of http://anglebug.com/1420 is fixed
7422 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
7423
7424 setUpProgram();
7425
7426 glActiveTexture(GL_TEXTURE0);
7427 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7428 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES, nullptr);
7429 EXPECT_GL_NO_ERROR();
7430
7431 drawQuad(mProgram, "position", 0.5f);
7432
7433 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7434 }
7435
7436 // Test that CopyTexImage2D does not trigger assertion after CompressedTexImage2D.
7437 // https://crbug.com/1216276
TEST_P(Texture2DTest,CopyAfterCompressed)7438 TEST_P(Texture2DTest, CopyAfterCompressed)
7439 {
7440 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
7441
7442 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7443 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 0, 8, nullptr);
7444 EXPECT_GL_NO_ERROR();
7445
7446 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 0, 0, 4, 4, 0);
7447 EXPECT_GL_NO_ERROR();
7448 }
7449
7450 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7451 // ES 3.0.4 table 3.24
TEST_P(Texture2DUnsignedIntegerAlpha1TestES3,TextureRGB8UIImplicitAlpha1)7452 TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB8UIImplicitAlpha1)
7453 {
7454 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7455
7456 glActiveTexture(GL_TEXTURE0);
7457 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7458 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, nullptr);
7459 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7460 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7461 EXPECT_GL_NO_ERROR();
7462
7463 drawQuad(mProgram, "position", 0.5f);
7464
7465 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7466 }
7467
7468 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7469 // ES 3.0.4 table 3.24
TEST_P(Texture2DIntegerAlpha1TestES3,TextureRGB8IImplicitAlpha1)7470 TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB8IImplicitAlpha1)
7471 {
7472 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7473
7474 glActiveTexture(GL_TEXTURE0);
7475 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7476
7477 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8I, 1, 1, 0, GL_RGB_INTEGER, GL_BYTE, nullptr);
7478 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7479 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7480 EXPECT_GL_NO_ERROR();
7481
7482 drawQuad(mProgram, "position", 0.5f);
7483
7484 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7485 }
7486
7487 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7488 // ES 3.0.4 table 3.24
TEST_P(Texture2DUnsignedIntegerAlpha1TestES3,TextureRGB16UIImplicitAlpha1)7489 TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB16UIImplicitAlpha1)
7490 {
7491 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7492
7493 glActiveTexture(GL_TEXTURE0);
7494 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7495 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, nullptr);
7496 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7497 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7498 EXPECT_GL_NO_ERROR();
7499
7500 drawQuad(mProgram, "position", 0.5f);
7501
7502 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7503 }
7504
7505 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7506 // ES 3.0.4 table 3.24
TEST_P(Texture2DIntegerAlpha1TestES3,TextureRGB16IImplicitAlpha1)7507 TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB16IImplicitAlpha1)
7508 {
7509 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7510
7511 glActiveTexture(GL_TEXTURE0);
7512 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7513 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16I, 1, 1, 0, GL_RGB_INTEGER, GL_SHORT, nullptr);
7514 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7515 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7516 EXPECT_GL_NO_ERROR();
7517
7518 drawQuad(mProgram, "position", 0.5f);
7519
7520 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7521 }
7522
7523 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7524 // ES 3.0.4 table 3.24
TEST_P(Texture2DUnsignedIntegerAlpha1TestES3,TextureRGB32UIImplicitAlpha1)7525 TEST_P(Texture2DUnsignedIntegerAlpha1TestES3, TextureRGB32UIImplicitAlpha1)
7526 {
7527 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7528
7529 glActiveTexture(GL_TEXTURE0);
7530 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7531 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, nullptr);
7532 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7533 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7534 EXPECT_GL_NO_ERROR();
7535
7536 drawQuad(mProgram, "position", 0.5f);
7537
7538 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7539 }
7540
7541 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7542 // ES 3.0.4 table 3.24
TEST_P(Texture2DIntegerAlpha1TestES3,TextureRGB32IImplicitAlpha1)7543 TEST_P(Texture2DIntegerAlpha1TestES3, TextureRGB32IImplicitAlpha1)
7544 {
7545 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
7546
7547 glActiveTexture(GL_TEXTURE0);
7548 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7549 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32I, 1, 1, 0, GL_RGB_INTEGER, GL_INT, nullptr);
7550 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7551 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7552 EXPECT_GL_NO_ERROR();
7553
7554 drawQuad(mProgram, "position", 0.5f);
7555
7556 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7557 }
7558
7559 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7560 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGBSNORMImplicitAlpha1)7561 TEST_P(Texture2DTestES3, TextureRGBSNORMImplicitAlpha1)
7562 {
7563 glActiveTexture(GL_TEXTURE0);
7564 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7565 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8_SNORM, 1, 1, 0, GL_RGB, GL_BYTE, nullptr);
7566 EXPECT_GL_NO_ERROR();
7567
7568 drawQuad(mProgram, "position", 0.5f);
7569
7570 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7571 }
7572
7573 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7574 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureRGB9E5ImplicitAlpha1)7575 TEST_P(Texture2DTestES3, TextureRGB9E5ImplicitAlpha1)
7576 {
7577 glActiveTexture(GL_TEXTURE0);
7578 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7579 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV,
7580 nullptr);
7581 EXPECT_GL_NO_ERROR();
7582
7583 drawQuad(mProgram, "position", 0.5f);
7584
7585 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7586 }
7587
7588 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7589 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureCOMPRESSEDRGB8ETC2ImplicitAlpha1)7590 TEST_P(Texture2DTestES3, TextureCOMPRESSEDRGB8ETC2ImplicitAlpha1)
7591 {
7592 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
7593 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
7594
7595 glActiveTexture(GL_TEXTURE0);
7596 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7597 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, 1, 1, 0, 8, nullptr);
7598 EXPECT_GL_NO_ERROR();
7599
7600 drawQuad(mProgram, "position", 0.5f);
7601
7602 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7603 }
7604
7605 // When sampling a texture without an alpha channel, "1" is returned as the alpha value.
7606 // ES 3.0.4 table 3.24
TEST_P(Texture2DTestES3,TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1)7607 TEST_P(Texture2DTestES3, TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1)
7608 {
7609 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
7610 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
7611
7612 glActiveTexture(GL_TEXTURE0);
7613 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7614 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_ETC2, 1, 1, 0, 8, nullptr);
7615 EXPECT_GL_NO_ERROR();
7616
7617 drawQuad(mProgram, "position", 0.5f);
7618
7619 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7620 }
7621
7622 // ETC2 punchthrough alpha formats must be initialized to opaque black when emulated
7623 // http://anglebug.com/6936
TEST_P(Texture2DTestES3RobustInit,TextureCOMPRESSEDRGB8A1ETC2)7624 TEST_P(Texture2DTestES3RobustInit, TextureCOMPRESSEDRGB8A1ETC2)
7625 {
7626 glActiveTexture(GL_TEXTURE0);
7627 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7628 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 1, 1, 0,
7629 8, nullptr);
7630 EXPECT_GL_NO_ERROR();
7631
7632 drawQuad(mProgram, "position", 0.5f);
7633
7634 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7635 }
7636
7637 // ETC2 punchthrough alpha formats must be initialized to opaque black when emulated
7638 // http://anglebug.com/6936
TEST_P(Texture2DTestES3RobustInit,TextureCOMPRESSEDSRGB8A1ETC2)7639 TEST_P(Texture2DTestES3RobustInit, TextureCOMPRESSEDSRGB8A1ETC2)
7640 {
7641 glActiveTexture(GL_TEXTURE0);
7642 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7643 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 1, 1, 0,
7644 8, nullptr);
7645 EXPECT_GL_NO_ERROR();
7646
7647 drawQuad(mProgram, "position", 0.5f);
7648
7649 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
7650 }
7651
7652 // Test that compressed textures ignore the pixel unpack state.
7653 // (https://crbug.org/1267496)
TEST_P(Texture2DTestES3,PixelUnpackStateTexImage)7654 TEST_P(Texture2DTestES3, PixelUnpackStateTexImage)
7655 {
7656 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
7657 !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
7658
7659 glPixelStorei(GL_UNPACK_ROW_LENGTH, 9);
7660 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7661
7662 uint8_t data[64] = {0};
7663 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 8, 8, 0, 64, data);
7664 EXPECT_GL_NO_ERROR();
7665 }
7666
7667 // Test that compressed textures ignore the pixel unpack state.
7668 // (https://crbug.org/1267496)
TEST_P(Texture2DTestES3,PixelUnpackStateTexSubImage)7669 TEST_P(Texture2DTestES3, PixelUnpackStateTexSubImage)
7670 {
7671 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
7672 !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
7673
7674 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7675
7676 uint8_t data[64] = {0};
7677 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 8, 8, 0, 64, data);
7678 EXPECT_GL_NO_ERROR();
7679
7680 glPixelStorei(GL_UNPACK_ROW_LENGTH, 9);
7681
7682 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64,
7683 data);
7684 EXPECT_GL_NO_ERROR();
7685 }
7686
7687 // Test for http://anglebug.com/6926.
TEST_P(Texture2DTestES3,TextureRGBUpdateWithPBO)7688 TEST_P(Texture2DTestES3, TextureRGBUpdateWithPBO)
7689 {
7690 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
7691
7692 glViewport(0, 0, 16, 16);
7693
7694 GLTexture tex1;
7695 std::vector<GLColor> texDataRed(16u * 16u, GLColor::red);
7696 std::vector<GLColor> texDataGreen(16u * 16u, GLColor::green);
7697
7698 glBindTexture(GL_TEXTURE_2D, tex1);
7699 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
7700 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, texDataRed.data());
7701 ASSERT_GL_NO_ERROR();
7702
7703 GLBuffer pbo;
7704 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
7705 glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, texDataGreen.data(), GL_STATIC_DRAW);
7706 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
7707 ASSERT_GL_NO_ERROR();
7708
7709 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
7710 ASSERT_GL_NO_ERROR();
7711
7712 glBindTexture(GL_TEXTURE_2D, 0);
7713 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
7714 EXPECT_PIXEL_COLOR_EQ(4, 4, GLColor::green);
7715 }
7716
7717 // Copied from Texture2DTest::TexStorage
7718 // Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a
7719 // default color.
TEST_P(Texture2DTestES31PPO,TexStorage)7720 TEST_P(Texture2DTestES31PPO, TexStorage)
7721 {
7722 ANGLE_SKIP_TEST_IF(!IsVulkan());
7723 ANGLE_SKIP_TEST_IF((getClientMajorVersion() < 3 && getClientMinorVersion() < 1) &&
7724 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
7725
7726 const char *vertexShaderSource = getVertexShaderSource();
7727 const char *fragmentShaderSource = getFragmentShaderSource();
7728
7729 bindProgramPipeline(vertexShaderSource, fragmentShaderSource);
7730 mTexture2DUniformLocation = glGetUniformLocation(mFragProg, getTextureUniformName());
7731
7732 int width = getWindowWidth();
7733 int height = getWindowHeight();
7734
7735 GLTexture tex2D;
7736 glActiveTexture(GL_TEXTURE0);
7737 glBindTexture(GL_TEXTURE_2D, tex2D);
7738
7739 // Fill with red
7740 std::vector<GLubyte> pixels(3 * 16 * 16);
7741 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
7742 {
7743 pixels[pixelId * 3 + 0] = 255;
7744 pixels[pixelId * 3 + 1] = 0;
7745 pixels[pixelId * 3 + 2] = 0;
7746 }
7747
7748 // ANGLE internally uses RGBA as the internal format for RGB images, therefore glTexStorage2DEXT
7749 // initializes the image to a default color to get a consistent alpha color. The data is kept in
7750 // a CPU-side image and the image is marked as dirty.
7751 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
7752
7753 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
7754 // glTexSubImage2D should take into account that the image is dirty.
7755 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
7756 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7757 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
7758
7759 glActiveShaderProgram(mPipeline, mFragProg);
7760 glUniform1i(mTexture2DUniformLocation, 0);
7761
7762 std::array<Vector3, 6> quadVertices = ANGLETestBase::GetQuadVertices();
7763 ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
7764
7765 EXPECT_GL_NO_ERROR();
7766 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
7767
7768 // Validate that the region of the texture without data has an alpha of 1.0
7769 angle::GLColor pixel = ReadColor(3 * width / 4, 3 * height / 4);
7770 EXPECT_EQ(255, pixel.A);
7771 }
7772
7773 // Copied from Texture2DTestES3::SingleTextureMultipleSamplers
7774 // Tests behaviour with a single texture and multiple sampler objects.
TEST_P(Texture2DTestES31PPO,SingleTextureMultipleSamplers)7775 TEST_P(Texture2DTestES31PPO, SingleTextureMultipleSamplers)
7776 {
7777 ANGLE_SKIP_TEST_IF(!IsVulkan());
7778
7779 const char *vertexShaderSource = getVertexShaderSource();
7780 const char *fragmentShaderSource = getFragmentShaderSource();
7781
7782 bindProgramPipeline(vertexShaderSource, fragmentShaderSource);
7783 mTexture2DUniformLocation = glGetUniformLocation(mFragProg, getTextureUniformName());
7784
7785 GLint maxTextureUnits = 0;
7786 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
7787 ANGLE_SKIP_TEST_IF(maxTextureUnits < 4);
7788
7789 constexpr int kSize = 16;
7790 std::array<Vector3, 6> quadVertices = ANGLETestBase::GetQuadVertices();
7791
7792 // Make a single-level texture, fill it with red.
7793 std::vector<GLColor> redColors(kSize * kSize, GLColor::red);
7794 GLTexture tex;
7795 glBindTexture(GL_TEXTURE_2D, tex);
7796 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7797 redColors.data());
7798 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7799 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7800
7801 // Simple confidence check.
7802 bind2DTexturedQuadProgramPipeline();
7803 ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
7804 ASSERT_GL_NO_ERROR();
7805 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7806
7807 // Bind texture to unit 1 with a sampler object making it incomplete.
7808 GLSampler sampler;
7809 glBindSampler(0, sampler);
7810 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
7811 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7812
7813 // Make a mipmap texture, fill it with blue.
7814 std::vector<GLColor> blueColors(kSize * kSize, GLColor::blue);
7815 GLTexture mipmapTex;
7816 glBindTexture(GL_TEXTURE_2D, mipmapTex);
7817 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7818 blueColors.data());
7819 glGenerateMipmap(GL_TEXTURE_2D);
7820
7821 // Draw with the sampler, expect blue.
7822 draw2DTexturedQuad(0.5f, 1.0f, true);
7823 ASSERT_GL_NO_ERROR();
7824 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
7825
7826 // Simple multitexturing program.
7827 constexpr char kVS[] =
7828 "#version 310 es\n"
7829 "precision mediump float;\n"
7830 "in vec2 position;\n"
7831 "out vec2 texCoord;\n"
7832 "void main()\n"
7833 "{\n"
7834 " gl_Position = vec4(position, 0, 1);\n"
7835 " texCoord = position * 0.5 + vec2(0.5);\n"
7836 "}";
7837
7838 constexpr char kFS[] =
7839 "#version 310 es\n"
7840 "precision mediump float;\n"
7841 "in vec2 texCoord;\n"
7842 "uniform sampler2D tex1;\n"
7843 "uniform sampler2D tex2;\n"
7844 "uniform sampler2D tex3;\n"
7845 "uniform sampler2D tex4;\n"
7846 "out vec4 color;\n"
7847 "void main()\n"
7848 "{\n"
7849 " color = (texture(tex1, texCoord) + texture(tex2, texCoord) \n"
7850 " + texture(tex3, texCoord) + texture(tex4, texCoord)) * 0.25;\n"
7851 "}";
7852
7853 bindProgramPipeline(kVS, kFS);
7854
7855 std::array<GLint, 4> texLocations = {
7856 {glGetUniformLocation(mFragProg, "tex1"), glGetUniformLocation(mFragProg, "tex2"),
7857 glGetUniformLocation(mFragProg, "tex3"), glGetUniformLocation(mFragProg, "tex4")}};
7858 for (GLint location : texLocations)
7859 {
7860 ASSERT_NE(-1, location);
7861 }
7862
7863 // Init the uniform data.
7864 glActiveShaderProgram(mPipeline, mFragProg);
7865 for (GLint location = 0; location < 4; ++location)
7866 {
7867 glUniform1i(texLocations[location], location);
7868 }
7869
7870 // Initialize four samplers
7871 GLSampler samplers[4];
7872
7873 // 0: non-mipped.
7874 glBindSampler(0, samplers[0]);
7875 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7876 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7877
7878 // 1: mipped.
7879 glBindSampler(1, samplers[1]);
7880 glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
7881 glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7882
7883 // 2: non-mipped.
7884 glBindSampler(2, samplers[2]);
7885 glSamplerParameteri(samplers[2], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7886 glSamplerParameteri(samplers[2], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7887
7888 // 3: mipped.
7889 glBindSampler(3, samplers[3]);
7890 glSamplerParameteri(samplers[3], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
7891 glSamplerParameteri(samplers[3], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7892
7893 // Bind two blue mipped textures and two single layer textures, should all draw.
7894 glActiveTexture(GL_TEXTURE0);
7895 glBindTexture(GL_TEXTURE_2D, tex);
7896
7897 glActiveTexture(GL_TEXTURE1);
7898 glBindTexture(GL_TEXTURE_2D, mipmapTex);
7899
7900 glActiveTexture(GL_TEXTURE2);
7901 glBindTexture(GL_TEXTURE_2D, tex);
7902
7903 glActiveTexture(GL_TEXTURE3);
7904 glBindTexture(GL_TEXTURE_2D, mipmapTex);
7905
7906 ASSERT_GL_NO_ERROR();
7907
7908 ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
7909 ASSERT_GL_NO_ERROR();
7910 EXPECT_PIXEL_NEAR(0, 0, 128, 0, 128, 255, 2);
7911
7912 // Bind four single layer textures, two should be incomplete.
7913 glActiveTexture(GL_TEXTURE1);
7914 glBindTexture(GL_TEXTURE_2D, tex);
7915
7916 glActiveTexture(GL_TEXTURE3);
7917 glBindTexture(GL_TEXTURE_2D, tex);
7918
7919 ppoDrawQuad(quadVertices, "position", 0.5f, 1.0f);
7920 ASSERT_GL_NO_ERROR();
7921 EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 2);
7922 }
7923
7924 // Use a sampler in a uniform struct.
TEST_P(SamplerInStructTest,SamplerInStruct)7925 TEST_P(SamplerInStructTest, SamplerInStruct)
7926 {
7927 runSamplerInStructTest();
7928 }
7929
7930 // Use a sampler in a uniform struct that's passed as a function parameter.
TEST_P(SamplerInStructAsFunctionParameterTest,SamplerInStructAsFunctionParameter)7931 TEST_P(SamplerInStructAsFunctionParameterTest, SamplerInStructAsFunctionParameter)
7932 {
7933 // Fails on Nexus 5X due to a driver bug. http://anglebug.com/1427
7934 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
7935
7936 runSamplerInStructTest();
7937 }
7938
7939 // Use a sampler in a uniform struct array with a struct from the array passed as a function
7940 // parameter.
TEST_P(SamplerInStructArrayAsFunctionParameterTest,SamplerInStructArrayAsFunctionParameter)7941 TEST_P(SamplerInStructArrayAsFunctionParameterTest, SamplerInStructArrayAsFunctionParameter)
7942 {
7943 // Fails on Nexus 5X due to a driver bug. http://anglebug.com/1427
7944 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
7945
7946 runSamplerInStructTest();
7947 }
7948
7949 // Use a sampler in a struct inside a uniform struct with the nested struct passed as a function
7950 // parameter.
TEST_P(SamplerInNestedStructAsFunctionParameterTest,SamplerInNestedStructAsFunctionParameter)7951 TEST_P(SamplerInNestedStructAsFunctionParameterTest, SamplerInNestedStructAsFunctionParameter)
7952 {
7953 // Fails on Nexus 5X due to a driver bug. http://anglebug.com/1427
7954 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
7955
7956 runSamplerInStructTest();
7957 }
7958
7959 // Make sure that there isn't a name conflict between sampler extracted from a struct and a
7960 // similarly named uniform.
TEST_P(SamplerInStructAndOtherVariableTest,SamplerInStructAndOtherVariable)7961 TEST_P(SamplerInStructAndOtherVariableTest, SamplerInStructAndOtherVariable)
7962 {
7963 runSamplerInStructTest();
7964 }
7965
7966 // GL_EXT_texture_filter_anisotropic
7967 class TextureAnisotropyTest : public Texture2DTest
7968 {
7969 protected:
uploadTexture()7970 void uploadTexture()
7971 {
7972 glActiveTexture(GL_TEXTURE0);
7973 glBindTexture(GL_TEXTURE_2D, mTexture2D);
7974 GLColor texDataRed[1] = {GLColor::red};
7975 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDataRed);
7976 EXPECT_GL_NO_ERROR();
7977 }
7978 };
7979
7980 // Tests that setting anisotropic filtering doesn't cause failures at draw time.
TEST_P(TextureAnisotropyTest,AnisotropyFunctional)7981 TEST_P(TextureAnisotropyTest, AnisotropyFunctional)
7982 {
7983 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_filter_anisotropic"));
7984
7985 setUpProgram();
7986
7987 uploadTexture();
7988
7989 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7990 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7991 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
7992 EXPECT_GL_NO_ERROR();
7993
7994 drawQuad(mProgram, "position", 0.5f);
7995
7996 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
7997 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7998 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
7999 }
8000
8001 // GL_OES_texture_border_clamp
8002 class TextureBorderClampTest : public Texture2DTest
8003 {
8004 protected:
TextureBorderClampTest()8005 TextureBorderClampTest() : Texture2DTest() {}
8006
getVertexShaderSource()8007 const char *getVertexShaderSource() override
8008 {
8009 return
8010 R"(precision highp float;
8011 attribute vec4 position;
8012 varying vec2 texcoord;
8013
8014 void main()
8015 {
8016 gl_Position = vec4(position.xy, 0.0, 1.0);
8017 // texcoords in [-0.5, 1.5]
8018 texcoord = (position.xy) + 0.5;
8019 })";
8020 }
8021
uploadTexture()8022 void uploadTexture()
8023 {
8024 glActiveTexture(GL_TEXTURE0);
8025 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8026 std::vector<GLColor> texDataRed(1, GLColor::red);
8027 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8028 texDataRed.data());
8029 EXPECT_GL_NO_ERROR();
8030 }
8031
testFormat(GLenum format,GLenum type,GLColor32F borderColor)8032 void testFormat(GLenum format, GLenum type, GLColor32F borderColor)
8033 {
8034 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8035 glActiveTexture(GL_TEXTURE0);
8036 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &borderColor.R);
8037 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8038 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8039 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8040 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8041 glTexImage2D(GL_TEXTURE_2D, 0, format, 2, 2, 0, format, type, nullptr);
8042 drawQuad(mProgram, "position", 0.5f);
8043 }
8044
testCompressedFormat(GLenum format,GLsizei size,GLColor32F borderColor)8045 void testCompressedFormat(GLenum format, GLsizei size, GLColor32F borderColor)
8046 {
8047 setUpProgram();
8048 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8049 glActiveTexture(GL_TEXTURE0);
8050 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &borderColor.R);
8051 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8052 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8053 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8054 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8055 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, 4, 4, 0, size, nullptr);
8056 drawQuad(mProgram, "position", 0.5f);
8057 }
8058 };
8059
8060 // Test if the color set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the texture in
8061 // GL_CLAMP_TO_BORDER wrap mode (set with glTexParameter).
TEST_P(TextureBorderClampTest,TextureBorderClampFunctional)8062 TEST_P(TextureBorderClampTest, TextureBorderClampFunctional)
8063 {
8064 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8065
8066 setUpProgram();
8067
8068 uploadTexture();
8069
8070 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8071 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8072 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8073 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8074 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8075 EXPECT_GL_NO_ERROR();
8076
8077 drawQuad(mProgram, "position", 0.5f);
8078
8079 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8080 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8081 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8082 }
8083
8084 // Test reading back GL_TEXTURE_BORDER_COLOR by glGetTexParameter.
TEST_P(TextureBorderClampTest,TextureBorderClampFunctional2)8085 TEST_P(TextureBorderClampTest, TextureBorderClampFunctional2)
8086 {
8087 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8088
8089 glActiveTexture(GL_TEXTURE0);
8090 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8091
8092 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8093
8094 GLint colorFixedPoint[4] = {0};
8095 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorFixedPoint);
8096 constexpr GLint colorGreenFixedPoint[4] = {0, std::numeric_limits<GLint>::max(), 0,
8097 std::numeric_limits<GLint>::max()};
8098 EXPECT_EQ(colorFixedPoint[0], colorGreenFixedPoint[0]);
8099 EXPECT_EQ(colorFixedPoint[1], colorGreenFixedPoint[1]);
8100 EXPECT_EQ(colorFixedPoint[2], colorGreenFixedPoint[2]);
8101 EXPECT_EQ(colorFixedPoint[3], colorGreenFixedPoint[3]);
8102
8103 constexpr GLint colorBlueFixedPoint[4] = {0, 0, std::numeric_limits<GLint>::max(),
8104 std::numeric_limits<GLint>::max()};
8105 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorBlueFixedPoint);
8106
8107 GLfloat color[4] = {0.0f};
8108 glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
8109 EXPECT_EQ(color[0], kFloatBlue.R);
8110 EXPECT_EQ(color[1], kFloatBlue.G);
8111 EXPECT_EQ(color[2], kFloatBlue.B);
8112 EXPECT_EQ(color[3], kFloatBlue.A);
8113 }
8114
8115 // Test GL_TEXTURE_BORDER_COLOR parameter validation at glTexParameter.
TEST_P(TextureBorderClampTest,TextureBorderClampValidation)8116 TEST_P(TextureBorderClampTest, TextureBorderClampValidation)
8117 {
8118 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8119
8120 glActiveTexture(GL_TEXTURE0);
8121 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8122
8123 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, 1.0f);
8124 EXPECT_GL_ERROR(GL_INVALID_ENUM);
8125
8126 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, std::numeric_limits<GLint>::max());
8127 EXPECT_GL_ERROR(GL_INVALID_ENUM);
8128
8129 glTexParameterfv(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8130 EXPECT_GL_ERROR(GL_INVALID_ENUM);
8131
8132 GLint colorInt[4] = {0};
8133 glTexParameteriv(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_TEXTURE_BORDER_COLOR, colorInt);
8134 EXPECT_GL_ERROR(GL_INVALID_ENUM);
8135
8136 if (getClientMajorVersion() < 3)
8137 {
8138 glTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorInt);
8139 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8140 glGetTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorInt);
8141 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8142
8143 GLuint colorUInt[4] = {0};
8144 glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorUInt);
8145 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8146 glGetTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorUInt);
8147 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8148
8149 GLSampler sampler;
8150 glSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorInt);
8151 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8152 glGetSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorInt);
8153 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8154
8155 glSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorUInt);
8156 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8157 glGetSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorUInt);
8158 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8159 }
8160 }
8161
8162 // Test GL_TEXTURE_BORDER_COLOR parameter with unorm formats.
TEST_P(TextureBorderClampTest,TextureBorderClampUnorm8)8163 TEST_P(TextureBorderClampTest, TextureBorderClampUnorm8)
8164 {
8165 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8166
8167 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8168
8169 setUpProgram();
8170
8171 testFormat(GL_ALPHA, GL_UNSIGNED_BYTE, kBorder);
8172 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
8173
8174 testFormat(GL_RGB, GL_UNSIGNED_BYTE, kBorder);
8175 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8176
8177 testFormat(GL_RGBA, GL_UNSIGNED_BYTE, kBorder);
8178 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8179
8180 testFormat(GL_LUMINANCE, GL_UNSIGNED_BYTE, kBorder);
8181 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 255), 1);
8182
8183 testFormat(GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, kBorder);
8184 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
8185 }
8186
8187 // Test GL_TEXTURE_BORDER_COLOR parameter with sRGB formats.
TEST_P(TextureBorderClampTest,TextureBorderClampSrgb)8188 TEST_P(TextureBorderClampTest, TextureBorderClampSrgb)
8189 {
8190 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8191 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_sRGB"));
8192
8193 // AMD D3D9 drivers always sample sRGB formats with (0, 0, 0, 0) border color, won't fix.
8194 ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D9());
8195
8196 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8197
8198 setUpProgram();
8199
8200 testFormat(GL_SRGB_EXT, GL_UNSIGNED_BYTE, kBorder);
8201 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8202
8203 testFormat(GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, kBorder);
8204 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8205 }
8206
8207 // Test GL_TEXTURE_BORDER_COLOR parameter with half-float formats.
TEST_P(TextureBorderClampTest,TextureBorderClampFloat16)8208 TEST_P(TextureBorderClampTest, TextureBorderClampFloat16)
8209 {
8210 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8211 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
8212
8213 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8214
8215 setUpProgram();
8216
8217 testFormat(GL_ALPHA, GL_HALF_FLOAT_OES, kBorder);
8218 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
8219
8220 testFormat(GL_RGB, GL_HALF_FLOAT_OES, kBorder);
8221 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8222
8223 testFormat(GL_RGBA, GL_HALF_FLOAT_OES, kBorder);
8224 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8225
8226 testFormat(GL_LUMINANCE, GL_HALF_FLOAT_OES, kBorder);
8227 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 255), 1);
8228
8229 testFormat(GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, kBorder);
8230 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
8231 }
8232
8233 // Test GL_TEXTURE_BORDER_COLOR parameter with float formats.
TEST_P(TextureBorderClampTest,TextureBorderClampFloat32)8234 TEST_P(TextureBorderClampTest, TextureBorderClampFloat32)
8235 {
8236 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8237 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
8238
8239 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8240
8241 setUpProgram();
8242
8243 testFormat(GL_ALPHA, GL_FLOAT, kBorder);
8244 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
8245
8246 testFormat(GL_RGB, GL_FLOAT, kBorder);
8247 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8248
8249 testFormat(GL_RGBA, GL_FLOAT, kBorder);
8250 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8251
8252 testFormat(GL_LUMINANCE, GL_FLOAT, kBorder);
8253 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 255), 1);
8254
8255 testFormat(GL_LUMINANCE_ALPHA, GL_FLOAT, kBorder);
8256 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
8257 }
8258
8259 // Test GL_TEXTURE_BORDER_COLOR parameter with red and red-green formats.
TEST_P(TextureBorderClampTest,TextureBorderClampRG)8260 TEST_P(TextureBorderClampTest, TextureBorderClampRG)
8261 {
8262 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8263 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
8264
8265 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8266
8267 setUpProgram();
8268
8269 testFormat(GL_RED_EXT, GL_UNSIGNED_BYTE, kBorder);
8270 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
8271
8272 testFormat(GL_RG_EXT, GL_UNSIGNED_BYTE, kBorder);
8273 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 0, 255), 1);
8274
8275 if (IsGLExtensionEnabled("GL_OES_texture_half_float"))
8276 {
8277 testFormat(GL_RED_EXT, GL_HALF_FLOAT_OES, kBorder);
8278 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
8279
8280 testFormat(GL_RG_EXT, GL_HALF_FLOAT_OES, kBorder);
8281 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 0, 255), 1);
8282 }
8283
8284 if (IsGLExtensionEnabled("GL_OES_texture_float"))
8285 {
8286 testFormat(GL_RED_EXT, GL_FLOAT, kBorder);
8287 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 0, 0, 255), 1);
8288
8289 testFormat(GL_RG_EXT, GL_FLOAT, kBorder);
8290 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 0, 255), 1);
8291 }
8292 }
8293
8294 // Test GL_TEXTURE_BORDER_COLOR parameter with DXT1 formats.
TEST_P(TextureBorderClampTest,TextureBorderClampDXT1)8295 TEST_P(TextureBorderClampTest, TextureBorderClampDXT1)
8296 {
8297 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8298 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
8299
8300 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8301
8302 setUpProgram();
8303
8304 testCompressedFormat(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 8, kBorder);
8305 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8306
8307 testCompressedFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, kBorder);
8308 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8309 }
8310
8311 // Test GL_TEXTURE_BORDER_COLOR parameter with DXT1 sRGB formats.
TEST_P(TextureBorderClampTest,TextureBorderClampDXT1Srgb)8312 TEST_P(TextureBorderClampTest, TextureBorderClampDXT1Srgb)
8313 {
8314 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8315 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc_srgb"));
8316
8317 // AMD D3D9 drivers always sample sRGB formats with (0, 0, 0, 0) border color, won't fix.
8318 ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D9());
8319
8320 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8321
8322 setUpProgram();
8323
8324 testCompressedFormat(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 8, kBorder);
8325 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 255), 1);
8326
8327 testCompressedFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 8, kBorder);
8328 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8329 }
8330
8331 // Test GL_TEXTURE_BORDER_COLOR parameter with texture redefinition.
TEST_P(TextureBorderClampTest,Redefinition)8332 TEST_P(TextureBorderClampTest, Redefinition)
8333 {
8334 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8335
8336 GLColor32F kBorder = {0.5f, 0.25f, 0.125f, 0.0625f};
8337
8338 setUpProgram();
8339
8340 testFormat(GL_ALPHA, GL_UNSIGNED_BYTE, kBorder);
8341 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 0, 0, 16), 1);
8342
8343 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 2, 2, 0, GL_LUMINANCE_ALPHA,
8344 GL_UNSIGNED_BYTE, nullptr);
8345 drawQuad(mProgram, "position", 0.5f);
8346 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 128, 128, 16), 1);
8347
8348 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
8349 drawQuad(mProgram, "position", 0.5f);
8350 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
8351 }
8352
8353 class TextureBorderClampTestES3 : public TextureBorderClampTest
8354 {
8355 protected:
TextureBorderClampTestES3()8356 TextureBorderClampTestES3() : TextureBorderClampTest() {}
8357 };
8358
8359 // Test if the color set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the texture in
8360 // GL_CLAMP_TO_BORDER wrap mode (set with glSamplerParameter).
TEST_P(TextureBorderClampTestES3,TextureBorderClampES3Functional)8361 TEST_P(TextureBorderClampTestES3, TextureBorderClampES3Functional)
8362 {
8363 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8364
8365 setUpProgram();
8366
8367 uploadTexture();
8368
8369 GLSampler sampler;
8370 glBindSampler(0, sampler);
8371 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8372 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8373 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8374 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8375 glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8376 EXPECT_GL_NO_ERROR();
8377
8378 drawQuad(mProgram, "position", 0.5f);
8379
8380 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8381 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8382 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8383 }
8384
8385 // Test reading back GL_TEXTURE_BORDER_COLOR by glGetSamplerParameter.
TEST_P(TextureBorderClampTestES3,TextureBorderClampES3Functional2)8386 TEST_P(TextureBorderClampTestES3, TextureBorderClampES3Functional2)
8387 {
8388 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8389
8390 glActiveTexture(GL_TEXTURE0);
8391
8392 GLSampler sampler;
8393 glBindSampler(0, sampler);
8394
8395 glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, &kFloatGreen.R);
8396
8397 GLint colorFixedPoint[4] = {0};
8398 glGetSamplerParameteriv(sampler, GL_TEXTURE_BORDER_COLOR, colorFixedPoint);
8399 constexpr GLint colorGreenFixedPoint[4] = {0, std::numeric_limits<GLint>::max(), 0,
8400 std::numeric_limits<GLint>::max()};
8401 EXPECT_EQ(colorFixedPoint[0], colorGreenFixedPoint[0]);
8402 EXPECT_EQ(colorFixedPoint[1], colorGreenFixedPoint[1]);
8403 EXPECT_EQ(colorFixedPoint[2], colorGreenFixedPoint[2]);
8404 EXPECT_EQ(colorFixedPoint[3], colorGreenFixedPoint[3]);
8405
8406 constexpr GLint colorBlueFixedPoint[4] = {0, 0, std::numeric_limits<GLint>::max(),
8407 std::numeric_limits<GLint>::max()};
8408 glSamplerParameteriv(sampler, GL_TEXTURE_BORDER_COLOR, colorBlueFixedPoint);
8409
8410 GLfloat color[4] = {0.0f};
8411 glGetSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, color);
8412 EXPECT_EQ(color[0], kFloatBlue.R);
8413 EXPECT_EQ(color[1], kFloatBlue.G);
8414 EXPECT_EQ(color[2], kFloatBlue.B);
8415 EXPECT_EQ(color[3], kFloatBlue.A);
8416
8417 constexpr GLint colorSomewhatRedInt[4] = {500000, 0, 0, std::numeric_limits<GLint>::max()};
8418 glSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorSomewhatRedInt);
8419 GLint colorInt[4] = {0};
8420 glGetSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorInt);
8421 EXPECT_EQ(colorInt[0], colorSomewhatRedInt[0]);
8422 EXPECT_EQ(colorInt[1], colorSomewhatRedInt[1]);
8423 EXPECT_EQ(colorInt[2], colorSomewhatRedInt[2]);
8424 EXPECT_EQ(colorInt[3], colorSomewhatRedInt[3]);
8425
8426 constexpr GLuint colorSomewhatRedUInt[4] = {500000, 0, 0, std::numeric_limits<GLuint>::max()};
8427 glSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorSomewhatRedUInt);
8428 GLuint colorUInt[4] = {0};
8429 glGetSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, colorUInt);
8430 EXPECT_EQ(colorUInt[0], colorSomewhatRedUInt[0]);
8431 EXPECT_EQ(colorUInt[1], colorSomewhatRedUInt[1]);
8432 EXPECT_EQ(colorUInt[2], colorSomewhatRedUInt[2]);
8433 EXPECT_EQ(colorUInt[3], colorSomewhatRedUInt[3]);
8434
8435 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8436
8437 constexpr GLint colorSomewhatGreenInt[4] = {0, 500000, 0, std::numeric_limits<GLint>::max()};
8438 glTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorSomewhatGreenInt);
8439 glGetTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorInt);
8440 EXPECT_EQ(colorInt[0], colorSomewhatGreenInt[0]);
8441 EXPECT_EQ(colorInt[1], colorSomewhatGreenInt[1]);
8442 EXPECT_EQ(colorInt[2], colorSomewhatGreenInt[2]);
8443 EXPECT_EQ(colorInt[3], colorSomewhatGreenInt[3]);
8444
8445 constexpr GLuint colorSomewhatGreenUInt[4] = {0, 500000, 0, std::numeric_limits<GLuint>::max()};
8446 glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorSomewhatGreenUInt);
8447 glGetTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorUInt);
8448 EXPECT_EQ(colorUInt[0], colorSomewhatGreenUInt[0]);
8449 EXPECT_EQ(colorUInt[1], colorSomewhatGreenUInt[1]);
8450 EXPECT_EQ(colorUInt[2], colorSomewhatGreenUInt[2]);
8451 EXPECT_EQ(colorUInt[3], colorSomewhatGreenUInt[3]);
8452 }
8453
8454 // Test GL_TEXTURE_BORDER_COLOR parameter validation at glSamplerParameter.
TEST_P(TextureBorderClampTestES3,TextureBorderClampES3Validation)8455 TEST_P(TextureBorderClampTestES3, TextureBorderClampES3Validation)
8456 {
8457 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8458
8459 glActiveTexture(GL_TEXTURE0);
8460
8461 GLSampler sampler;
8462 glBindSampler(0, sampler);
8463
8464 glSamplerParameterf(sampler, GL_TEXTURE_BORDER_COLOR, 1.0f);
8465 EXPECT_GL_ERROR(GL_INVALID_ENUM);
8466
8467 glSamplerParameteri(sampler, GL_TEXTURE_BORDER_COLOR, std::numeric_limits<GLint>::max());
8468 EXPECT_GL_ERROR(GL_INVALID_ENUM);
8469 }
8470
8471 // Test that format-specific adjustments are applied
8472 // when the border color type does not match the texture type.
TEST_P(TextureBorderClampTestES3,TextureBorderTypeMismatch)8473 TEST_P(TextureBorderClampTestES3, TextureBorderTypeMismatch)
8474 {
8475 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8476
8477 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8478 glActiveTexture(GL_TEXTURE0);
8479 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8480 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8481 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8482 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8483
8484 GLColor32UI kBorder = {1, 2, 3, 0};
8485 glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, &kBorder.R);
8486 ASSERT_GL_NO_ERROR();
8487
8488 setUpProgram();
8489
8490 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
8491 drawQuad(mProgram, "position", 0.5f);
8492 EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
8493 }
8494
8495 class TextureBorderClampIntegerTestES3 : public Texture2DTest
8496 {
8497 protected:
TextureBorderClampIntegerTestES3()8498 TextureBorderClampIntegerTestES3() : Texture2DTest(), isUnsignedIntTest(false) {}
8499
getVertexShaderSource()8500 const char *getVertexShaderSource() override
8501 {
8502 return
8503 R"(#version 300 es
8504 out vec2 texcoord;
8505 in vec4 position;
8506
8507 void main()
8508 {
8509 gl_Position = vec4(position.xy, 0.0, 1.0);
8510 // texcoords in [-0.5, 1.5]
8511 texcoord = (position.xy) + 0.5;
8512 })";
8513 }
8514
getFragmentShaderSource()8515 const char *getFragmentShaderSource() override
8516 {
8517 if (isUnsignedIntTest)
8518 {
8519 return "#version 300 es\n"
8520 "precision highp float;\n"
8521 "uniform highp usampler2D tex;\n"
8522 "in vec2 texcoord;\n"
8523 "out vec4 fragColor;\n"
8524
8525 "void main()\n"
8526 "{\n"
8527 "vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
8528 "vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
8529 "fragColor = (texture(tex, texcoord).r == 150u)"
8530 " ? green : red;\n"
8531 "}\n";
8532 }
8533 else
8534 {
8535 return "#version 300 es\n"
8536 "precision highp float;\n"
8537 "uniform highp isampler2D tex;\n"
8538 "in vec2 texcoord;\n"
8539 "out vec4 fragColor;\n"
8540
8541 "void main()\n"
8542 "{\n"
8543 "vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
8544 "vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
8545 "fragColor = (texture(tex, texcoord).r == -50)"
8546 " ? green : red;\n"
8547 "}\n";
8548 }
8549 }
8550
uploadTexture()8551 void uploadTexture()
8552 {
8553 glActiveTexture(GL_TEXTURE0);
8554 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8555 if (isUnsignedIntTest)
8556 {
8557 std::vector<GLubyte> texData(4, 100);
8558 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
8559 texData.data());
8560 }
8561 else
8562 {
8563 std::vector<GLbyte> texData(4, 100);
8564 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8I, 1, 1, 0, GL_RGBA_INTEGER, GL_BYTE,
8565 texData.data());
8566 }
8567 EXPECT_GL_NO_ERROR();
8568 }
8569
8570 bool isUnsignedIntTest;
8571 };
8572
8573 // Test if the integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the
8574 // integer texture in GL_CLAMP_TO_BORDER wrap mode (set with glTexParameterIivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampInteger)8575 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampInteger)
8576 {
8577 // Fails on Win10 FYI x64 Release (AMD RX 550). http://anglebug.com/3760
8578 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
8579
8580 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8581
8582 setUpProgram();
8583
8584 uploadTexture();
8585
8586 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8587 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8588 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8589 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8590
8591 constexpr GLint borderColor[4] = {-50, -50, -50, -50};
8592 glTexParameterIivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
8593
8594 EXPECT_GL_NO_ERROR();
8595
8596 drawQuad(mProgram, "position", 0.5f);
8597
8598 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8599 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8600 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8601 }
8602
8603 // Test if the integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside of the
8604 // integer texture in GL_CLAMP_TO_BORDER wrap mode (set with glTexParameterIivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampInteger2)8605 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampInteger2)
8606 {
8607 // Fails on Win10 FYI x64 Release (AMD RX 550). http://anglebug.com/3760
8608 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
8609
8610 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8611
8612 setUpProgram();
8613
8614 uploadTexture();
8615
8616 GLSampler sampler;
8617 glBindSampler(0, sampler);
8618 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8619 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8620 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8621 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8622
8623 constexpr GLint borderColor[4] = {-50, -50, -50, -50};
8624 glSamplerParameterIivOES(sampler, GL_TEXTURE_BORDER_COLOR, borderColor);
8625
8626 EXPECT_GL_NO_ERROR();
8627
8628 drawQuad(mProgram, "position", 0.5f);
8629
8630 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8631 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8632 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8633 }
8634
8635 // Test if the unsigned integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside
8636 // of the unsigned integer texture in GL_CLAMP_TO_BORDER wrap mode (set with glTexParameterIuivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampIntegerUnsigned)8637 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampIntegerUnsigned)
8638 {
8639 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8640
8641 isUnsignedIntTest = true;
8642
8643 setUpProgram();
8644
8645 uploadTexture();
8646
8647 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8648 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8649 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8650 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8651
8652 constexpr GLuint borderColor[4] = {150, 150, 150, 150};
8653 glTexParameterIuivOES(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
8654
8655 EXPECT_GL_NO_ERROR();
8656
8657 drawQuad(mProgram, "position", 0.5f);
8658
8659 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8660 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8661 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8662 }
8663
8664 // Test if the unsigned integer values set as GL_TEXTURE_BORDER_COLOR is used when sampling outside
8665 // of the unsigned integer texture in GL_CLAMP_TO_BORDER wrap mode (set with
8666 // glSamplerParameterIuivOES).
TEST_P(TextureBorderClampIntegerTestES3,TextureBorderClampIntegerUnsigned2)8667 TEST_P(TextureBorderClampIntegerTestES3, TextureBorderClampIntegerUnsigned2)
8668 {
8669 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_border_clamp"));
8670
8671 isUnsignedIntTest = true;
8672
8673 setUpProgram();
8674
8675 uploadTexture();
8676
8677 GLSampler sampler;
8678 glBindSampler(0, sampler);
8679 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
8680 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
8681 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8682 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8683
8684 constexpr GLuint borderColor[4] = {150, 150, 150, 150};
8685 glSamplerParameterIuivOES(sampler, GL_TEXTURE_BORDER_COLOR, borderColor);
8686
8687 EXPECT_GL_NO_ERROR();
8688
8689 drawQuad(mProgram, "position", 0.5f);
8690
8691 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
8692 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8693 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
8694 }
8695
8696 // ~GL_OES_texture_border_clamp
8697
8698 // GL_EXT_texture_mirror_clamp_to_edge
8699 class TextureMirrorClampToEdgeTest : public Texture2DTest
8700 {
8701 protected:
TextureMirrorClampToEdgeTest()8702 TextureMirrorClampToEdgeTest() : Texture2DTest() {}
8703
getVertexShaderSource()8704 const char *getVertexShaderSource() override
8705 {
8706 return R"(precision highp float;
8707 attribute vec4 position;
8708 varying vec2 texcoord;
8709
8710 void main()
8711 {
8712 gl_Position = vec4(position.xy, 0.0, 1.0);
8713 texcoord = position.xy * 2.0;
8714 })";
8715 }
8716
uploadTexture(bool isInteger,bool isSigned,GLuint sampler)8717 void uploadTexture(bool isInteger, bool isSigned, GLuint sampler)
8718 {
8719 glActiveTexture(GL_TEXTURE0);
8720 glBindTexture(GL_TEXTURE_2D, mTexture2D);
8721 if (isInteger && isSigned)
8722 {
8723 const int8_t data[] = {0, 0, 0, -1, -1, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, -1};
8724 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8I, 2, 2, 0, GL_RGBA_INTEGER, GL_BYTE, data);
8725 }
8726 else if (isInteger)
8727 {
8728 const uint8_t data[] = {0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1};
8729 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 2, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
8730 data);
8731 }
8732 else
8733 {
8734 const uint8_t data[] = {0, 0, 0, 255, 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255};
8735 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
8736 }
8737
8738 if (sampler != 0)
8739 {
8740 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_MIRROR_CLAMP_TO_EDGE_EXT);
8741 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_MIRROR_CLAMP_TO_EDGE_EXT);
8742 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8743 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8744 }
8745 else
8746 {
8747 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRROR_CLAMP_TO_EDGE_EXT);
8748 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRROR_CLAMP_TO_EDGE_EXT);
8749 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8750 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8751 }
8752 ASSERT_GL_NO_ERROR();
8753 }
8754
checkTextureSampling()8755 void checkTextureSampling()
8756 {
8757 auto screenX = [&](float x) { return getWindowWidth() * (x * 0.25 + 0.5); };
8758 auto screenY = [&](float y) { return getWindowHeight() * (y * 0.25 + 0.5); };
8759
8760 // +S, +T
8761 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(0.25), GLColor::black);
8762 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(0.25), GLColor::red);
8763 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(0.25), GLColor::red);
8764 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(0.75), GLColor::green);
8765 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(1.50), GLColor::green);
8766 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(0.75), GLColor::blue);
8767 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(0.75), GLColor::blue);
8768 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(1.50), GLColor::blue);
8769 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(1.50), GLColor::blue);
8770
8771 // -S, +T
8772 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(0.25), GLColor::black);
8773 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(0.25), GLColor::red);
8774 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(0.25), GLColor::red);
8775 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(0.75), GLColor::green);
8776 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(1.50), GLColor::green);
8777 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(0.75), GLColor::blue);
8778 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(0.75), GLColor::blue);
8779 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(1.50), GLColor::blue);
8780 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(1.50), GLColor::blue);
8781
8782 // +S, -T
8783 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(-0.25), GLColor::black);
8784 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(-0.25), GLColor::red);
8785 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(-0.25), GLColor::red);
8786 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(-0.75), GLColor::green);
8787 EXPECT_PIXEL_COLOR_EQ(screenX(0.25), screenY(-1.50), GLColor::green);
8788 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(-0.75), GLColor::blue);
8789 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(-0.75), GLColor::blue);
8790 EXPECT_PIXEL_COLOR_EQ(screenX(0.75), screenY(-1.50), GLColor::blue);
8791 EXPECT_PIXEL_COLOR_EQ(screenX(1.50), screenY(-1.50), GLColor::blue);
8792
8793 // -S, -T
8794 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(-0.25), GLColor::black);
8795 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(-0.25), GLColor::red);
8796 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(-0.25), GLColor::red);
8797 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(-0.75), GLColor::green);
8798 EXPECT_PIXEL_COLOR_EQ(screenX(-0.25), screenY(-1.50), GLColor::green);
8799 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(-0.75), GLColor::blue);
8800 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(-0.75), GLColor::blue);
8801 EXPECT_PIXEL_COLOR_EQ(screenX(-0.75), screenY(-1.50), GLColor::blue);
8802 EXPECT_PIXEL_COLOR_EQ(screenX(-1.50), screenY(-1.50), GLColor::blue);
8803 }
8804 };
8805
8806 // Test that the texture is correctly mirrored in negative directions
8807 // and clamped to edge pixels outside of the normalized range.
TEST_P(TextureMirrorClampToEdgeTest,TexParameter)8808 TEST_P(TextureMirrorClampToEdgeTest, TexParameter)
8809 {
8810 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8811
8812 setUpProgram();
8813 uploadTexture(false, false, 0);
8814 drawQuad(mProgram, "position", 0.5f);
8815 ASSERT_GL_NO_ERROR();
8816
8817 checkTextureSampling();
8818 }
8819
8820 class TextureMirrorClampToEdgeTestES3 : public TextureMirrorClampToEdgeTest
8821 {
8822 protected:
TextureMirrorClampToEdgeTestES3()8823 TextureMirrorClampToEdgeTestES3() : TextureMirrorClampToEdgeTest() {}
8824 };
8825
8826 // Test that the texture is correctly mirrored in negative directions and clamped
8827 // to edge pixels outside of the normalized range with mode set via glSamplerParameter.
TEST_P(TextureMirrorClampToEdgeTestES3,SamplerParameter)8828 TEST_P(TextureMirrorClampToEdgeTestES3, SamplerParameter)
8829 {
8830 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8831
8832 GLSampler sampler;
8833 glBindSampler(0, sampler);
8834
8835 setUpProgram();
8836 uploadTexture(false, false, sampler);
8837 drawQuad(mProgram, "position", 0.5f);
8838 ASSERT_GL_NO_ERROR();
8839
8840 checkTextureSampling();
8841 }
8842
8843 class TextureMirrorClampToEdgeIntegerTestES3 : public TextureMirrorClampToEdgeTestES3
8844 {
8845 protected:
TextureMirrorClampToEdgeIntegerTestES3()8846 TextureMirrorClampToEdgeIntegerTestES3() : TextureMirrorClampToEdgeTestES3() {}
8847
getVertexShaderSource()8848 const char *getVertexShaderSource() override
8849 {
8850 return R"(#version 300 es
8851 precision highp float;
8852 in vec4 position;
8853 out vec2 texcoord;
8854
8855 void main()
8856 {
8857 gl_Position = vec4(position.xy, 0.0, 1.0);
8858 texcoord = position.xy * 2.0;
8859 })";
8860 }
8861
getFragmentShaderSource()8862 const char *getFragmentShaderSource() override
8863 {
8864 if (mIsSigned)
8865 {
8866 return R"(#version 300 es
8867 precision highp float;
8868 uniform highp isampler2D tex;
8869 in vec2 texcoord;
8870 out vec4 fragColor;
8871 void main() { fragColor = vec4(-texture(tex, texcoord)); })";
8872 }
8873 else
8874 {
8875 return R"(#version 300 es
8876 precision highp float;
8877 uniform highp usampler2D tex;
8878 in vec2 texcoord;
8879 out vec4 fragColor;
8880 void main() { fragColor = vec4(texture(tex, texcoord)); })";
8881 }
8882 }
8883
8884 bool mIsSigned = false;
8885 };
8886
8887 // Test that the texture is correctly mirrored in negative directions and clamped
8888 // to edge pixels outside of the normalized range with mode set with glTexParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,TexParameterSigned)8889 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, TexParameterSigned)
8890 {
8891 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8892
8893 mIsSigned = true;
8894 setUpProgram();
8895 uploadTexture(true, true, 0);
8896 drawQuad(mProgram, "position", 0.5f);
8897 ASSERT_GL_NO_ERROR();
8898
8899 checkTextureSampling();
8900 }
8901
8902 // Test that the texture is correctly mirrored in negative directions and clamped
8903 // to edge pixels outside of the normalized range with mode set with glSamplerParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,SamplerParameterSigned)8904 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, SamplerParameterSigned)
8905 {
8906 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8907
8908 GLSampler sampler;
8909 glBindSampler(0, sampler);
8910
8911 mIsSigned = true;
8912 setUpProgram();
8913 uploadTexture(true, true, sampler);
8914 drawQuad(mProgram, "position", 0.5f);
8915 ASSERT_GL_NO_ERROR();
8916
8917 checkTextureSampling();
8918 }
8919
8920 // Test that the unsigned integer texture is correctly mirrored in negative directions and clamped
8921 // to edge pixels outside of the normalized range with mode set with glTexParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,TexParameterUnsigned)8922 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, TexParameterUnsigned)
8923 {
8924 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8925
8926 setUpProgram();
8927 uploadTexture(true, false, 0);
8928 drawQuad(mProgram, "position", 0.5f);
8929 ASSERT_GL_NO_ERROR();
8930
8931 checkTextureSampling();
8932 }
8933
8934 // Test that the unsigned integer texture is correctly mirrored in negative directions and clamped
8935 // to edge pixels outside of the normalized range with mode set with glSamplerParameter.
TEST_P(TextureMirrorClampToEdgeIntegerTestES3,SamplerParameterUnsigned)8936 TEST_P(TextureMirrorClampToEdgeIntegerTestES3, SamplerParameterUnsigned)
8937 {
8938 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_mirror_clamp_to_edge"));
8939
8940 GLSampler sampler;
8941 glBindSampler(0, sampler);
8942
8943 setUpProgram();
8944 uploadTexture(true, false, sampler);
8945 drawQuad(mProgram, "position", 0.5f);
8946 ASSERT_GL_NO_ERROR();
8947
8948 checkTextureSampling();
8949 }
8950 // ~GL_EXT_texture_mirror_clamp_to_edge
8951
8952 class TextureLimitsTest : public ANGLETest<>
8953 {
8954 protected:
8955 struct RGBA8
8956 {
8957 uint8_t R, G, B, A;
8958 };
8959
TextureLimitsTest()8960 TextureLimitsTest()
8961 : mProgram(0), mMaxVertexTextures(0), mMaxFragmentTextures(0), mMaxCombinedTextures(0)
8962 {
8963 setWindowWidth(128);
8964 setWindowHeight(128);
8965 setConfigRedBits(8);
8966 setConfigGreenBits(8);
8967 setConfigBlueBits(8);
8968 setConfigAlphaBits(8);
8969 }
8970
testSetUp()8971 void testSetUp() override
8972 {
8973 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mMaxVertexTextures);
8974 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mMaxFragmentTextures);
8975 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mMaxCombinedTextures);
8976
8977 ASSERT_GL_NO_ERROR();
8978 }
8979
testTearDown()8980 void testTearDown() override
8981 {
8982 if (mProgram != 0)
8983 {
8984 glDeleteProgram(mProgram);
8985 mProgram = 0;
8986
8987 if (!mTextures.empty())
8988 {
8989 glDeleteTextures(static_cast<GLsizei>(mTextures.size()), &mTextures[0]);
8990 }
8991 }
8992 }
8993
compileProgramWithTextureCounts(const std::string & vertexPrefix,GLint vertexTextureCount,GLint vertexActiveTextureCount,const std::string & fragPrefix,GLint fragmentTextureCount,GLint fragmentActiveTextureCount)8994 void compileProgramWithTextureCounts(const std::string &vertexPrefix,
8995 GLint vertexTextureCount,
8996 GLint vertexActiveTextureCount,
8997 const std::string &fragPrefix,
8998 GLint fragmentTextureCount,
8999 GLint fragmentActiveTextureCount)
9000 {
9001 std::stringstream vertexShaderStr;
9002 vertexShaderStr << "attribute vec2 position;\n"
9003 << "varying vec4 color;\n"
9004 << "varying vec2 texCoord;\n";
9005
9006 for (GLint textureIndex = 0; textureIndex < vertexTextureCount; ++textureIndex)
9007 {
9008 vertexShaderStr << "uniform sampler2D " << vertexPrefix << textureIndex << ";\n";
9009 }
9010
9011 vertexShaderStr << "void main() {\n"
9012 << " gl_Position = vec4(position, 0, 1);\n"
9013 << " texCoord = (position * 0.5) + 0.5;\n"
9014 << " color = vec4(0);\n";
9015
9016 for (GLint textureIndex = 0; textureIndex < vertexActiveTextureCount; ++textureIndex)
9017 {
9018 vertexShaderStr << " color += texture2D(" << vertexPrefix << textureIndex
9019 << ", texCoord);\n";
9020 }
9021
9022 vertexShaderStr << "}";
9023
9024 std::stringstream fragmentShaderStr;
9025 fragmentShaderStr << "varying mediump vec4 color;\n" << "varying mediump vec2 texCoord;\n";
9026
9027 for (GLint textureIndex = 0; textureIndex < fragmentTextureCount; ++textureIndex)
9028 {
9029 fragmentShaderStr << "uniform sampler2D " << fragPrefix << textureIndex << ";\n";
9030 }
9031
9032 fragmentShaderStr << "void main() {\n" << " gl_FragColor = color;\n";
9033
9034 for (GLint textureIndex = 0; textureIndex < fragmentActiveTextureCount; ++textureIndex)
9035 {
9036 fragmentShaderStr << " gl_FragColor += texture2D(" << fragPrefix << textureIndex
9037 << ", texCoord);\n";
9038 }
9039
9040 fragmentShaderStr << "}";
9041
9042 const std::string &vertexShaderSource = vertexShaderStr.str();
9043 const std::string &fragmentShaderSource = fragmentShaderStr.str();
9044
9045 mProgram = CompileProgram(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
9046 }
9047
getPixel(GLint texIndex)9048 RGBA8 getPixel(GLint texIndex)
9049 {
9050 RGBA8 pixel = {static_cast<uint8_t>(texIndex & 0x7u), static_cast<uint8_t>(texIndex >> 3),
9051 0, 255u};
9052 return pixel;
9053 }
9054
initTextures(GLint tex2DCount,GLint texCubeCount)9055 void initTextures(GLint tex2DCount, GLint texCubeCount)
9056 {
9057 GLint totalCount = tex2DCount + texCubeCount;
9058 mTextures.assign(totalCount, 0);
9059 glGenTextures(totalCount, &mTextures[0]);
9060 ASSERT_GL_NO_ERROR();
9061
9062 std::vector<RGBA8> texData(16 * 16);
9063
9064 GLint texIndex = 0;
9065 for (; texIndex < tex2DCount; ++texIndex)
9066 {
9067 texData.assign(texData.size(), getPixel(texIndex));
9068 glActiveTexture(GL_TEXTURE0 + texIndex);
9069 glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]);
9070 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
9071 &texData[0]);
9072 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9073 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9074 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9075 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9076 }
9077
9078 ASSERT_GL_NO_ERROR();
9079
9080 for (; texIndex < texCubeCount; ++texIndex)
9081 {
9082 texData.assign(texData.size(), getPixel(texIndex));
9083 glActiveTexture(GL_TEXTURE0 + texIndex);
9084 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[texIndex]);
9085 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9086 GL_UNSIGNED_BYTE, &texData[0]);
9087 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9088 GL_UNSIGNED_BYTE, &texData[0]);
9089 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9090 GL_UNSIGNED_BYTE, &texData[0]);
9091 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9092 GL_UNSIGNED_BYTE, &texData[0]);
9093 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9094 GL_UNSIGNED_BYTE, &texData[0]);
9095 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
9096 GL_UNSIGNED_BYTE, &texData[0]);
9097 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9098 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9099 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9100 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9101 }
9102
9103 ASSERT_GL_NO_ERROR();
9104 }
9105
testWithTextures(GLint vertexTextureCount,const std::string & vertexTexturePrefix,GLint fragmentTextureCount,const std::string & fragmentTexturePrefix)9106 void testWithTextures(GLint vertexTextureCount,
9107 const std::string &vertexTexturePrefix,
9108 GLint fragmentTextureCount,
9109 const std::string &fragmentTexturePrefix)
9110 {
9111 // Generate textures
9112 initTextures(vertexTextureCount + fragmentTextureCount, 0);
9113
9114 glUseProgram(mProgram);
9115 RGBA8 expectedSum = {0};
9116 for (GLint texIndex = 0; texIndex < vertexTextureCount; ++texIndex)
9117 {
9118 std::stringstream uniformNameStr;
9119 uniformNameStr << vertexTexturePrefix << texIndex;
9120 const std::string &uniformName = uniformNameStr.str();
9121 GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
9122 ASSERT_NE(-1, location);
9123
9124 glUniform1i(location, texIndex);
9125 RGBA8 contribution = getPixel(texIndex);
9126 expectedSum.R += contribution.R;
9127 expectedSum.G += contribution.G;
9128 }
9129
9130 for (GLint texIndex = 0; texIndex < fragmentTextureCount; ++texIndex)
9131 {
9132 std::stringstream uniformNameStr;
9133 uniformNameStr << fragmentTexturePrefix << texIndex;
9134 const std::string &uniformName = uniformNameStr.str();
9135 GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
9136 ASSERT_NE(-1, location);
9137
9138 glUniform1i(location, texIndex + vertexTextureCount);
9139 RGBA8 contribution = getPixel(texIndex + vertexTextureCount);
9140 expectedSum.R += contribution.R;
9141 expectedSum.G += contribution.G;
9142 }
9143
9144 ASSERT_GE(256u, expectedSum.G);
9145
9146 drawQuad(mProgram, "position", 0.5f);
9147 ASSERT_GL_NO_ERROR();
9148 EXPECT_PIXEL_NEAR(0, 0, expectedSum.R, expectedSum.G, 0, 255, 1);
9149 }
9150
9151 GLuint mProgram;
9152 std::vector<GLuint> mTextures;
9153 GLint mMaxVertexTextures;
9154 GLint mMaxFragmentTextures;
9155 GLint mMaxCombinedTextures;
9156 };
9157
9158 // Test rendering with the maximum vertex texture units.
TEST_P(TextureLimitsTest,MaxVertexTextures)9159 TEST_P(TextureLimitsTest, MaxVertexTextures)
9160 {
9161 compileProgramWithTextureCounts("tex", mMaxVertexTextures, mMaxVertexTextures, "tex", 0, 0);
9162 ASSERT_NE(0u, mProgram);
9163 ASSERT_GL_NO_ERROR();
9164
9165 testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
9166 }
9167
9168 // Test rendering with the maximum fragment texture units.
TEST_P(TextureLimitsTest,MaxFragmentTextures)9169 TEST_P(TextureLimitsTest, MaxFragmentTextures)
9170 {
9171 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures, mMaxFragmentTextures);
9172 ASSERT_NE(0u, mProgram);
9173 ASSERT_GL_NO_ERROR();
9174
9175 testWithTextures(mMaxFragmentTextures, "tex", 0, "tex");
9176 }
9177
9178 // Test rendering with maximum combined texture units.
TEST_P(TextureLimitsTest,MaxCombinedTextures)9179 TEST_P(TextureLimitsTest, MaxCombinedTextures)
9180 {
9181 GLint vertexTextures = mMaxVertexTextures;
9182
9183 if (vertexTextures + mMaxFragmentTextures > mMaxCombinedTextures)
9184 {
9185 vertexTextures = mMaxCombinedTextures - mMaxFragmentTextures;
9186 }
9187
9188 compileProgramWithTextureCounts("vtex", vertexTextures, vertexTextures, "ftex",
9189 mMaxFragmentTextures, mMaxFragmentTextures);
9190 ASSERT_NE(0u, mProgram);
9191 ASSERT_GL_NO_ERROR();
9192
9193 testWithTextures(vertexTextures, "vtex", mMaxFragmentTextures, "ftex");
9194 }
9195
9196 // Negative test for exceeding the number of vertex textures
TEST_P(TextureLimitsTest,ExcessiveVertexTextures)9197 TEST_P(TextureLimitsTest, ExcessiveVertexTextures)
9198 {
9199 compileProgramWithTextureCounts("tex", mMaxVertexTextures + 1, mMaxVertexTextures + 1, "tex", 0,
9200 0);
9201 ASSERT_EQ(0u, mProgram);
9202 }
9203
9204 // Negative test for exceeding the number of fragment textures
TEST_P(TextureLimitsTest,ExcessiveFragmentTextures)9205 TEST_P(TextureLimitsTest, ExcessiveFragmentTextures)
9206 {
9207 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 1,
9208 mMaxFragmentTextures + 1);
9209 ASSERT_EQ(0u, mProgram);
9210 }
9211
9212 // Test active vertex textures under the limit, but excessive textures specified.
TEST_P(TextureLimitsTest,MaxActiveVertexTextures)9213 TEST_P(TextureLimitsTest, MaxActiveVertexTextures)
9214 {
9215 compileProgramWithTextureCounts("tex", mMaxVertexTextures + 4, mMaxVertexTextures, "tex", 0, 0);
9216 ASSERT_NE(0u, mProgram);
9217 ASSERT_GL_NO_ERROR();
9218
9219 testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
9220 }
9221
9222 // Test active fragment textures under the limit, but excessive textures specified.
TEST_P(TextureLimitsTest,MaxActiveFragmentTextures)9223 TEST_P(TextureLimitsTest, MaxActiveFragmentTextures)
9224 {
9225 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 4,
9226 mMaxFragmentTextures);
9227 ASSERT_NE(0u, mProgram);
9228 ASSERT_GL_NO_ERROR();
9229
9230 testWithTextures(0, "tex", mMaxFragmentTextures, "tex");
9231 }
9232
9233 // Negative test for pointing two sampler uniforms of different types to the same texture.
9234 // GLES 2.0.25 section 2.10.4 page 39.
TEST_P(TextureLimitsTest,TextureTypeConflict)9235 TEST_P(TextureLimitsTest, TextureTypeConflict)
9236 {
9237 constexpr char kVS[] =
9238 "attribute vec2 position;\n"
9239 "varying float color;\n"
9240 "uniform sampler2D tex2D;\n"
9241 "uniform samplerCube texCube;\n"
9242 "void main() {\n"
9243 " gl_Position = vec4(position, 0, 1);\n"
9244 " vec2 texCoord = (position * 0.5) + 0.5;\n"
9245 " color = texture2D(tex2D, texCoord).x;\n"
9246 " color += textureCube(texCube, vec3(texCoord, 0)).x;\n"
9247 "}";
9248 constexpr char kFS[] =
9249 "varying mediump float color;\n"
9250 "void main() {\n"
9251 " gl_FragColor = vec4(color, 0, 0, 1);\n"
9252 "}";
9253
9254 mProgram = CompileProgram(kVS, kFS);
9255 ASSERT_NE(0u, mProgram);
9256
9257 initTextures(1, 0);
9258
9259 glUseProgram(mProgram);
9260 GLint tex2DLocation = glGetUniformLocation(mProgram, "tex2D");
9261 ASSERT_NE(-1, tex2DLocation);
9262 GLint texCubeLocation = glGetUniformLocation(mProgram, "texCube");
9263 ASSERT_NE(-1, texCubeLocation);
9264
9265 glUniform1i(tex2DLocation, 0);
9266 glUniform1i(texCubeLocation, 0);
9267 ASSERT_GL_NO_ERROR();
9268
9269 drawQuad(mProgram, "position", 0.5f);
9270 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
9271 }
9272
9273 class Texture2DNorm16TestES3 : public Texture2DTestES3
9274 {
9275 protected:
Texture2DNorm16TestES3()9276 Texture2DNorm16TestES3() : Texture2DTestES3(), mTextures{0, 0, 0}, mFBO(0), mRenderbuffer(0) {}
9277
testSetUp()9278 void testSetUp() override
9279 {
9280 Texture2DTestES3::testSetUp();
9281
9282 glActiveTexture(GL_TEXTURE0);
9283 glGenTextures(3, mTextures);
9284 glGenFramebuffers(1, &mFBO);
9285 glGenRenderbuffers(1, &mRenderbuffer);
9286
9287 for (size_t textureIndex = 0; textureIndex < 3; textureIndex++)
9288 {
9289 glBindTexture(GL_TEXTURE_2D, mTextures[textureIndex]);
9290 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
9291 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
9292 }
9293
9294 glBindTexture(GL_TEXTURE_2D, 0);
9295
9296 ASSERT_GL_NO_ERROR();
9297 }
9298
testTearDown()9299 void testTearDown() override
9300 {
9301 glDeleteTextures(3, mTextures);
9302 glDeleteFramebuffers(1, &mFBO);
9303 glDeleteRenderbuffers(1, &mRenderbuffer);
9304
9305 Texture2DTestES3::testTearDown();
9306 }
9307
testNorm16Texture(GLint internalformat,GLenum format,GLenum type)9308 void testNorm16Texture(GLint internalformat, GLenum format, GLenum type)
9309 {
9310 // TODO(http://anglebug.com/4089) Fails on Win Intel OpenGL driver
9311 ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
9312 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_norm16"));
9313
9314 GLushort pixelValue = (type == GL_SHORT) ? 0x7FFF : 0x6A35;
9315 GLushort imageData[] = {pixelValue, pixelValue, pixelValue, pixelValue};
9316
9317 setUpProgram();
9318
9319 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9320 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0],
9321 0);
9322
9323 for (int i = 0; i < 2; ++i)
9324 {
9325 bool isSubImage = i == 1;
9326 SCOPED_TRACE("is subimage:" + std::to_string(isSubImage));
9327 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
9328 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16_EXT, 1, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT,
9329 nullptr);
9330
9331 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
9332 if (isSubImage)
9333 {
9334 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, nullptr);
9335 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, format, type, imageData);
9336 }
9337 else
9338 {
9339 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
9340 }
9341 EXPECT_GL_NO_ERROR();
9342
9343 drawQuad(mProgram, "position", 0.5f);
9344
9345 GLubyte expectedValue =
9346 (type == GL_SHORT) ? 0xFF : static_cast<GLubyte>(pixelValue >> 8);
9347
9348 EXPECT_PIXEL_COLOR_EQ(0, 0,
9349 SliceFormatColor(format, GLColor(expectedValue, expectedValue,
9350 expectedValue, expectedValue)));
9351 }
9352 glBindFramebuffer(GL_FRAMEBUFFER, 0);
9353
9354 ASSERT_GL_NO_ERROR();
9355 }
9356
testReadPixelsRGBAWithRangeAndPixelStoreMode(GLuint x,GLuint y,GLuint width,GLuint height,GLint packRowLength,GLint packAlignment,GLint packSkipPixels,GLint packSkipRows,GLenum type,GLColor16UI color)9357 void testReadPixelsRGBAWithRangeAndPixelStoreMode(GLuint x,
9358 GLuint y,
9359 GLuint width,
9360 GLuint height,
9361 GLint packRowLength,
9362 GLint packAlignment,
9363 GLint packSkipPixels,
9364 GLint packSkipRows,
9365 GLenum type,
9366 GLColor16UI color)
9367 {
9368 // PACK modes debugging
9369 GLint s = 2; // single component size in bytes, UNSIGNED_SHORT -> 2 in our case
9370 GLint n = 4; // 4 components per pixel, stands for GL_RGBA
9371
9372 GLuint l = packRowLength == 0 ? width : packRowLength;
9373 const GLint &a = packAlignment;
9374
9375 // According to
9376 // https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glPixelStorei.xhtml
9377 GLint k = (s >= a) ? n * l : a / s * (1 + (s * n * l - 1) / a);
9378 std::size_t componentCount = n * packSkipPixels + k * (packSkipRows + height);
9379 if (static_cast<GLuint>(packRowLength) < width)
9380 {
9381 componentCount += width * n * s - k;
9382 }
9383
9384 // Populate the pixels array with random dirty value
9385 constexpr GLushort kDirtyValue = 0x1234;
9386 std::vector<GLushort> pixels(componentCount, kDirtyValue);
9387 glReadPixels(x, y, width, height, GL_RGBA, type, pixels.data());
9388
9389 EXPECT_GL_NO_ERROR();
9390
9391 GLushort *pixelRowStart = pixels.data();
9392 pixelRowStart += n * packSkipPixels + k * packSkipRows;
9393
9394 std::vector<bool> modifiedPixels(componentCount, false);
9395
9396 char errorInfo[200];
9397
9398 for (GLuint row = 0; row < height; ++row)
9399 {
9400 GLushort *curPixel = pixelRowStart;
9401 for (GLuint col = 0, len = (row == height - 1) ? width : std::min(l, width); col < len;
9402 ++col)
9403 {
9404 snprintf(errorInfo, sizeof(errorInfo),
9405 "extent: {%u, %u}, coord: (%u, %u), rowLength: %d, alignment: %d, "
9406 "skipPixels: %d, skipRows: %d\n",
9407 width, height, col, row, packRowLength, packAlignment, packSkipPixels,
9408 packSkipRows);
9409 EXPECT_EQ(color.R, curPixel[0]) << errorInfo;
9410 EXPECT_EQ(color.G, curPixel[1]) << errorInfo;
9411 EXPECT_EQ(color.B, curPixel[2]) << errorInfo;
9412 EXPECT_EQ(color.A, curPixel[3]) << errorInfo;
9413
9414 std::ptrdiff_t diff = curPixel - pixels.data();
9415 modifiedPixels[diff + 0] = true;
9416 modifiedPixels[diff + 1] = true;
9417 modifiedPixels[diff + 2] = true;
9418 modifiedPixels[diff + 3] = true;
9419
9420 curPixel += n;
9421 }
9422 pixelRowStart += k;
9423 }
9424
9425 for (std::size_t i = 0; i < modifiedPixels.size(); ++i)
9426 {
9427 if (!modifiedPixels[i])
9428 {
9429 EXPECT_EQ(pixels[i], kDirtyValue);
9430 }
9431 }
9432 }
9433
testNorm16RenderAndReadPixels(GLint internalformat,GLenum format,GLenum type)9434 void testNorm16RenderAndReadPixels(GLint internalformat, GLenum format, GLenum type)
9435 {
9436 // TODO(http://anglebug.com/4089) Fails on Win Intel OpenGL driver
9437 ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
9438 // TODO(http://anglebug.com/4245) Fails on Win AMD OpenGL driver
9439 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
9440 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_norm16"));
9441
9442 GLushort pixelValue = 0x6A35;
9443 GLushort imageData[] = {pixelValue, pixelValue, pixelValue, pixelValue};
9444 GLColor16UI color = SliceFormatColor16UI(
9445 format, GLColor16UI(pixelValue, pixelValue, pixelValue, pixelValue));
9446 // Size of drawing viewport
9447 constexpr GLint width = 8, height = 8;
9448
9449 setUpProgram();
9450
9451 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
9452 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, type, nullptr);
9453
9454 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9455 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1],
9456 0);
9457
9458 glBindTexture(GL_TEXTURE_2D, mTextures[2]);
9459 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
9460 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9461 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9462
9463 EXPECT_GL_NO_ERROR();
9464
9465 drawQuad(mProgram, "position", 0.5f);
9466
9467 // ReadPixels against different width, height, pixel pack mode combinations to test
9468 // workaround of pixels rearrangement
9469
9470 // {x, y, width, height}
9471 std::vector<std::array<GLint, 4>> areas = {
9472 {0, 0, 1, 1}, {0, 0, 1, 2}, {0, 0, 2, 1}, {0, 0, 2, 2},
9473 {0, 0, 3, 2}, {0, 0, 3, 3}, {0, 0, 4, 3}, {0, 0, 4, 4},
9474
9475 {1, 3, 3, 2}, {1, 3, 3, 3}, {3, 2, 4, 3}, {3, 2, 4, 4},
9476
9477 {0, 0, 5, 6}, {2, 1, 5, 6}, {0, 0, 6, 1}, {0, 0, 7, 1},
9478 {0, 0, 7, 3}, {0, 0, 7, 8}, {1, 0, 7, 8}, {0, 0, 8, 8},
9479 };
9480
9481 // Put default settings at the last
9482 std::vector<GLint> paramsPackRowLength = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0};
9483 std::vector<GLint> paramsPackAlignment = {1, 2, 8, 4};
9484 std::vector<std::array<GLint, 2>> paramsPackSkipPixelsAndRows = {{1, 0}, {0, 1}, {1, 1},
9485 {3, 1}, {20, 20}, {0, 0}};
9486
9487 // Restore pixel pack modes later
9488 GLint restorePackAlignment;
9489 glGetIntegerv(GL_PACK_ALIGNMENT, &restorePackAlignment);
9490 GLint restorePackRowLength;
9491 glGetIntegerv(GL_PACK_ROW_LENGTH, &restorePackRowLength);
9492 GLint restorePackSkipPixels;
9493 glGetIntegerv(GL_PACK_SKIP_PIXELS, &restorePackSkipPixels);
9494 GLint restorePackSkipRows;
9495 glGetIntegerv(GL_PACK_SKIP_ROWS, &restorePackSkipRows);
9496
9497 // Variable symbols are based on:
9498 // https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glPixelStorei.xhtml
9499 for (const auto &skipped : paramsPackSkipPixelsAndRows)
9500 {
9501 glPixelStorei(GL_PACK_SKIP_PIXELS, skipped[0]);
9502 glPixelStorei(GL_PACK_SKIP_ROWS, skipped[1]);
9503 for (GLint a : paramsPackAlignment)
9504 {
9505 glPixelStorei(GL_PACK_ALIGNMENT, a);
9506 for (GLint l : paramsPackRowLength)
9507 {
9508 glPixelStorei(GL_PACK_ROW_LENGTH, l);
9509
9510 for (const auto &area : areas)
9511 {
9512 ASSERT(area[0] + area[2] <= width);
9513 ASSERT(area[1] + area[3] <= height);
9514 testReadPixelsRGBAWithRangeAndPixelStoreMode(area[0], area[1], area[2],
9515 area[3], l, a, skipped[0],
9516 skipped[1], type, color);
9517 }
9518 }
9519 }
9520 }
9521
9522 glPixelStorei(GL_PACK_ALIGNMENT, restorePackAlignment);
9523 glPixelStorei(GL_PACK_ROW_LENGTH, restorePackRowLength);
9524 glPixelStorei(GL_PACK_SKIP_PIXELS, restorePackSkipPixels);
9525 glPixelStorei(GL_PACK_SKIP_ROWS, restorePackSkipRows);
9526
9527 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
9528 glRenderbufferStorage(GL_RENDERBUFFER, internalformat, 1, 1);
9529 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
9530 mRenderbuffer);
9531 glBindRenderbuffer(GL_RENDERBUFFER, 0);
9532 EXPECT_GL_NO_ERROR();
9533
9534 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
9535 glClear(GL_COLOR_BUFFER_BIT);
9536
9537 EXPECT_PIXEL_16UI_COLOR(
9538 0, 0, SliceFormatColor16UI(format, GLColor16UI(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF)));
9539
9540 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
9541 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
9542
9543 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1],
9544 0);
9545 EXPECT_PIXEL_16UI_COLOR(
9546 0, 0, SliceFormatColor16UI(format, GLColor16UI(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF)));
9547
9548 ASSERT_GL_NO_ERROR();
9549
9550 glBindFramebuffer(GL_FRAMEBUFFER, 0);
9551 }
9552
9553 GLuint mTextures[3];
9554 GLuint mFBO;
9555 GLuint mRenderbuffer;
9556 };
9557
TEST_P(Texture2DNorm16TestES3,TextureNorm16R16TextureTest)9558 TEST_P(Texture2DNorm16TestES3, TextureNorm16R16TextureTest)
9559 {
9560 testNorm16Texture(GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
9561 }
9562
TEST_P(Texture2DNorm16TestES3,TextureNorm16R16SNORMTextureTest)9563 TEST_P(Texture2DNorm16TestES3, TextureNorm16R16SNORMTextureTest)
9564 {
9565 testNorm16Texture(GL_R16_SNORM_EXT, GL_RED, GL_SHORT);
9566 }
9567
TEST_P(Texture2DNorm16TestES3,TextureNorm16RG16TextureTest)9568 TEST_P(Texture2DNorm16TestES3, TextureNorm16RG16TextureTest)
9569 {
9570 testNorm16Texture(GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
9571 }
9572
TEST_P(Texture2DNorm16TestES3,TextureNorm16RG16SNORMTextureTest)9573 TEST_P(Texture2DNorm16TestES3, TextureNorm16RG16SNORMTextureTest)
9574 {
9575 testNorm16Texture(GL_RG16_SNORM_EXT, GL_RG, GL_SHORT);
9576 }
9577
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGB16TextureTest)9578 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGB16TextureTest)
9579 {
9580 // (http://anglebug.com/4215) Driver bug on some Qualcomm Adreno gpu
9581 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
9582
9583 testNorm16Texture(GL_RGB16_EXT, GL_RGB, GL_UNSIGNED_SHORT);
9584 }
9585
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGB16SNORMTextureTest)9586 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGB16SNORMTextureTest)
9587 {
9588 // (http://anglebug.com/4215) Driver bug on some Qualcomm Adreno gpu
9589 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
9590
9591 testNorm16Texture(GL_RGB16_SNORM_EXT, GL_RGB, GL_SHORT);
9592 }
9593
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGBA16TextureTest)9594 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGBA16TextureTest)
9595 {
9596 testNorm16Texture(GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
9597 }
9598
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGBA16SNORMTextureTest)9599 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGBA16SNORMTextureTest)
9600 {
9601 testNorm16Texture(GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT);
9602 }
9603
TEST_P(Texture2DNorm16TestES3,TextureNorm16R16RenderTest)9604 TEST_P(Texture2DNorm16TestES3, TextureNorm16R16RenderTest)
9605 {
9606 // http://anglebug.com/5153
9607 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && IsNVIDIA());
9608
9609 testNorm16RenderAndReadPixels(GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
9610 }
9611
TEST_P(Texture2DNorm16TestES3,TextureNorm16RG16RenderTest)9612 TEST_P(Texture2DNorm16TestES3, TextureNorm16RG16RenderTest)
9613 {
9614 // http://anglebug.com/5153
9615 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && IsNVIDIA());
9616
9617 testNorm16RenderAndReadPixels(GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT);
9618 }
9619
TEST_P(Texture2DNorm16TestES3,TextureNorm16RGBA16RenderTest)9620 TEST_P(Texture2DNorm16TestES3, TextureNorm16RGBA16RenderTest)
9621 {
9622 // http://anglebug.com/5153
9623 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && IsNVIDIA());
9624
9625 testNorm16RenderAndReadPixels(GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT);
9626 }
9627
9628 class Texture2DRGTest : public Texture2DTest
9629 {
9630 protected:
Texture2DRGTest()9631 Texture2DRGTest()
9632 : Texture2DTest(), mRenderableTexture(0), mTestTexture(0), mFBO(0), mRenderbuffer(0)
9633 {}
9634
testSetUp()9635 void testSetUp() override
9636 {
9637 Texture2DTest::testSetUp();
9638
9639 glActiveTexture(GL_TEXTURE0);
9640 glGenTextures(1, &mRenderableTexture);
9641 glGenTextures(1, &mTestTexture);
9642 glGenFramebuffers(1, &mFBO);
9643 glGenRenderbuffers(1, &mRenderbuffer);
9644
9645 glBindTexture(GL_TEXTURE_2D, mRenderableTexture);
9646 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9647 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9648 glBindTexture(GL_TEXTURE_2D, mTestTexture);
9649 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9650 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9651
9652 glBindTexture(GL_TEXTURE_2D, 0);
9653
9654 setUpProgram();
9655 glUseProgram(mProgram);
9656 glUniform1i(mTexture2DUniformLocation, 0);
9657
9658 ASSERT_GL_NO_ERROR();
9659 }
9660
testTearDown()9661 void testTearDown() override
9662 {
9663 glDeleteTextures(1, &mRenderableTexture);
9664 glDeleteTextures(1, &mTestTexture);
9665 glDeleteFramebuffers(1, &mFBO);
9666 glDeleteRenderbuffers(1, &mRenderbuffer);
9667
9668 Texture2DTest::testTearDown();
9669 }
9670
setupFormatTextures(GLenum internalformat,GLenum format,GLenum type,GLvoid * imageData)9671 void setupFormatTextures(GLenum internalformat, GLenum format, GLenum type, GLvoid *imageData)
9672 {
9673 glBindTexture(GL_TEXTURE_2D, mRenderableTexture);
9674 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9675
9676 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9677 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
9678 mRenderableTexture, 0);
9679
9680 glBindTexture(GL_TEXTURE_2D, mTestTexture);
9681 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
9682
9683 EXPECT_GL_NO_ERROR();
9684 }
9685
testRGTexture(GLColor expectedColor)9686 void testRGTexture(GLColor expectedColor)
9687 {
9688 drawQuad(mProgram, "position", 0.5f);
9689
9690 EXPECT_GL_NO_ERROR();
9691 EXPECT_PIXEL_COLOR_NEAR(0, 0, expectedColor, kPixelTolerance);
9692 }
9693
testRGRender(GLenum internalformat,GLenum format)9694 void testRGRender(GLenum internalformat, GLenum format)
9695 {
9696 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
9697 glRenderbufferStorage(GL_RENDERBUFFER, internalformat, 1, 1);
9698 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
9699 mRenderbuffer);
9700 glBindRenderbuffer(GL_RENDERBUFFER, 0);
9701 EXPECT_GL_NO_ERROR();
9702
9703 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
9704 glClear(GL_COLOR_BUFFER_BIT);
9705
9706 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
9707
9708 ASSERT_GL_NO_ERROR();
9709 EXPECT_PIXEL_COLOR_EQ(0, 0, SliceFormatColor(format, GLColor(255u, 255u, 255u, 255u)));
9710 }
9711
9712 GLuint mRenderableTexture;
9713 GLuint mTestTexture;
9714 GLuint mFBO;
9715 GLuint mRenderbuffer;
9716 };
9717
9718 // Test unorm texture formats enabled by the GL_EXT_texture_rg extension.
TEST_P(Texture2DRGTest,TextureRGUNormTest)9719 TEST_P(Texture2DRGTest, TextureRGUNormTest)
9720 {
9721 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
9722 // This workaround causes a GL error on Windows AMD, which is likely a driver bug.
9723 // The workaround is not intended to be enabled in this configuration so skip it.
9724 ANGLE_SKIP_TEST_IF(
9725 getEGLWindow()->isFeatureEnabled(Feature::EmulateCopyTexImage2DFromRenderbuffers) &&
9726 IsWindows() && IsAMD());
9727
9728 GLubyte pixelValue = 0xab;
9729 GLubyte imageData[] = {pixelValue, pixelValue};
9730
9731 setupFormatTextures(GL_RED_EXT, GL_RED_EXT, GL_UNSIGNED_BYTE, imageData);
9732 testRGTexture(
9733 SliceFormatColor(GL_RED_EXT, GLColor(pixelValue, pixelValue, pixelValue, pixelValue)));
9734 testRGRender(GL_R8_EXT, GL_RED_EXT);
9735
9736 setupFormatTextures(GL_RG_EXT, GL_RG_EXT, GL_UNSIGNED_BYTE, imageData);
9737 testRGTexture(
9738 SliceFormatColor(GL_RG_EXT, GLColor(pixelValue, pixelValue, pixelValue, pixelValue)));
9739 testRGRender(GL_RG8_EXT, GL_RG_EXT);
9740 }
9741
9742 // Test float texture formats enabled by the GL_EXT_texture_rg extension.
TEST_P(Texture2DRGTest,TextureRGFloatTest)9743 TEST_P(Texture2DRGTest, TextureRGFloatTest)
9744 {
9745 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
9746 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
9747
9748 GLfloat pixelValue = 0.54321;
9749 GLfloat imageData[] = {pixelValue, pixelValue};
9750
9751 GLubyte expectedValue = static_cast<GLubyte>(pixelValue * 255.0f);
9752 GLColor expectedColor = GLColor(expectedValue, expectedValue, expectedValue, expectedValue);
9753
9754 setupFormatTextures(GL_RED_EXT, GL_RED_EXT, GL_FLOAT, imageData);
9755 testRGTexture(SliceFormatColor(GL_RED_EXT, expectedColor));
9756
9757 setupFormatTextures(GL_RG_EXT, GL_RG_EXT, GL_FLOAT, imageData);
9758 testRGTexture(SliceFormatColor(GL_RG_EXT, expectedColor));
9759 }
9760
9761 // Test half-float texture formats enabled by the GL_EXT_texture_rg extension.
TEST_P(Texture2DRGTest,TextureRGHalfFloatTest)9762 TEST_P(Texture2DRGTest, TextureRGHalfFloatTest)
9763 {
9764 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_rg"));
9765 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
9766
9767 GLfloat pixelValueFloat = 0.543f;
9768 GLhalf pixelValue = 0x3858;
9769 GLhalf imageData[] = {pixelValue, pixelValue};
9770
9771 GLubyte expectedValue = static_cast<GLubyte>(pixelValueFloat * 255.0f);
9772 GLColor expectedColor = GLColor(expectedValue, expectedValue, expectedValue, expectedValue);
9773
9774 setupFormatTextures(GL_RED_EXT, GL_RED_EXT, GL_HALF_FLOAT_OES, imageData);
9775 testRGTexture(SliceFormatColor(GL_RED_EXT, expectedColor));
9776
9777 setupFormatTextures(GL_RG_EXT, GL_RG_EXT, GL_HALF_FLOAT_OES, imageData);
9778 testRGTexture(SliceFormatColor(GL_RG_EXT, expectedColor));
9779 }
9780
9781 class Texture2DFloatTest : public Texture2DTest
9782 {
9783 protected:
Texture2DFloatTest()9784 Texture2DFloatTest()
9785 : Texture2DTest(), mRenderableTexture(0), mTestTexture(0), mFBO(0), mRenderbuffer(0)
9786 {}
9787
testSetUp()9788 void testSetUp() override
9789 {
9790 Texture2DTest::testSetUp();
9791
9792 glActiveTexture(GL_TEXTURE0);
9793 glGenTextures(1, &mRenderableTexture);
9794 glGenTextures(1, &mTestTexture);
9795 glGenFramebuffers(1, &mFBO);
9796 glGenRenderbuffers(1, &mRenderbuffer);
9797
9798 setUpProgram();
9799 glUseProgram(mProgram);
9800 glUniform1i(mTexture2DUniformLocation, 0);
9801
9802 glBindTexture(GL_TEXTURE_2D, mRenderableTexture);
9803 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
9804
9805 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9806 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
9807 mRenderableTexture, 0);
9808
9809 ASSERT_GL_NO_ERROR();
9810 }
9811
testTearDown()9812 void testTearDown() override
9813 {
9814 glDeleteTextures(1, &mRenderableTexture);
9815 glDeleteTextures(1, &mTestTexture);
9816 glDeleteFramebuffers(1, &mFBO);
9817 glDeleteRenderbuffers(1, &mRenderbuffer);
9818
9819 Texture2DTest::testTearDown();
9820 }
9821
testFloatTextureSample(GLenum internalFormat,GLenum format,GLenum type)9822 void testFloatTextureSample(GLenum internalFormat, GLenum format, GLenum type)
9823 {
9824 constexpr GLfloat imageDataFloat[] = {
9825 0.2f,
9826 0.3f,
9827 0.4f,
9828 0.5f,
9829 };
9830 constexpr GLhalf imageDataHalf[] = {
9831 0x3266,
9832 0x34CD,
9833 0x3666,
9834 0x3800,
9835 };
9836 GLColor expectedValue;
9837 for (int i = 0; i < 4; i++)
9838 {
9839 expectedValue[i] = static_cast<GLubyte>(imageDataFloat[i] * 255.0f);
9840 }
9841
9842 const GLvoid *imageData;
9843 switch (type)
9844 {
9845 case GL_FLOAT:
9846 imageData = imageDataFloat;
9847 break;
9848 case GL_HALF_FLOAT:
9849 case GL_HALF_FLOAT_OES:
9850 imageData = imageDataHalf;
9851 break;
9852 default:
9853 imageData = nullptr;
9854 }
9855 ASSERT(imageData != nullptr);
9856
9857 glBindTexture(GL_TEXTURE_2D, mTestTexture);
9858 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, format, type, imageData);
9859
9860 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9861 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9862
9863 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9864 drawQuad(mProgram, "position", 0.5f);
9865
9866 EXPECT_GL_NO_ERROR();
9867 EXPECT_PIXEL_COLOR_NEAR(0, 0, SliceFormatColor(format, expectedValue), kPixelTolerance);
9868 }
9869
testFloatTextureLinear(GLenum internalFormat,GLenum format,GLenum type)9870 void testFloatTextureLinear(GLenum internalFormat, GLenum format, GLenum type)
9871 {
9872 int numComponents;
9873 switch (format)
9874 {
9875 case GL_RGBA:
9876 numComponents = 4;
9877 break;
9878 case GL_RGB:
9879 numComponents = 3;
9880 break;
9881 case GL_LUMINANCE_ALPHA:
9882 numComponents = 2;
9883 break;
9884 case GL_LUMINANCE:
9885 case GL_ALPHA:
9886 numComponents = 1;
9887 break;
9888 default:
9889 numComponents = 0;
9890 }
9891 ASSERT(numComponents > 0);
9892
9893 constexpr GLfloat pixelIntensitiesFloat[] = {0.0f, 1.0f, 0.0f, 1.0f};
9894 constexpr GLhalf pixelIntensitiesHalf[] = {0x0000, 0x3C00, 0x0000, 0x3C00};
9895
9896 GLfloat imageDataFloat[16];
9897 GLhalf imageDataHalf[16];
9898 for (int i = 0; i < 4; i++)
9899 {
9900 for (int c = 0; c < numComponents; c++)
9901 {
9902 imageDataFloat[i * numComponents + c] = pixelIntensitiesFloat[i];
9903 imageDataHalf[i * numComponents + c] = pixelIntensitiesHalf[i];
9904 }
9905 }
9906
9907 const GLvoid *imageData;
9908 switch (type)
9909 {
9910 case GL_FLOAT:
9911 imageData = imageDataFloat;
9912 break;
9913 case GL_HALF_FLOAT:
9914 case GL_HALF_FLOAT_OES:
9915 imageData = imageDataHalf;
9916 break;
9917 default:
9918 imageData = nullptr;
9919 }
9920 ASSERT(imageData != nullptr);
9921
9922 glBindTexture(GL_TEXTURE_2D, mTestTexture);
9923 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 2, 2, 0, format, type, imageData);
9924
9925 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
9926 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
9927
9928 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9929 drawQuad(mProgram, "position", 0.5f);
9930
9931 EXPECT_GL_NO_ERROR();
9932 // Source texture contains 2 black pixels and 2 white pixels, we sample in the center so we
9933 // should expect the final value to be gray (halfway in-between)
9934 EXPECT_PIXEL_COLOR_NEAR(0, 0, SliceFormatColor(format, GLColor(127u, 127u, 127u, 127u)),
9935 kPixelTolerance);
9936 }
9937
performFloatTextureRender(GLenum internalFormat,GLenum renderBufferFormat,GLenum format,GLenum type)9938 bool performFloatTextureRender(GLenum internalFormat,
9939 GLenum renderBufferFormat,
9940 GLenum format,
9941 GLenum type)
9942 {
9943 glBindTexture(GL_TEXTURE_2D, mTestTexture);
9944 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, format, type, nullptr);
9945 glBindTexture(GL_TEXTURE_2D, 0);
9946
9947 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
9948 glRenderbufferStorage(GL_RENDERBUFFER, renderBufferFormat, 1, 1);
9949 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
9950 mRenderbuffer);
9951 glBindRenderbuffer(GL_RENDERBUFFER, 0);
9952 EXPECT_GL_NO_ERROR();
9953
9954 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
9955 {
9956 return false;
9957 }
9958
9959 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
9960
9961 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
9962 glClear(GL_COLOR_BUFFER_BIT);
9963
9964 EXPECT_GL_NO_ERROR();
9965 return true;
9966 }
9967
9968 GLuint mRenderableTexture;
9969 GLuint mTestTexture;
9970 GLuint mFBO;
9971 GLuint mRenderbuffer;
9972 };
9973
9974 class Texture2DFloatTestES3 : public Texture2DFloatTest
9975 {
9976 protected:
testFloatTextureRender(GLenum internalFormat,GLenum format,GLenum type)9977 void testFloatTextureRender(GLenum internalFormat, GLenum format, GLenum type)
9978 {
9979 bool framebufferComplete =
9980 performFloatTextureRender(internalFormat, internalFormat, format, type);
9981 EXPECT_TRUE(framebufferComplete);
9982 EXPECT_PIXEL_COLOR32F_NEAR(0, 0,
9983 SliceFormatColor32F(format, GLColor32F(1.0f, 1.0f, 1.0f, 1.0f)),
9984 kPixelTolerance32F);
9985 }
9986 };
9987
9988 class Texture2DFloatTestES2 : public Texture2DFloatTest
9989 {
9990 protected:
checkFloatTextureRender(GLenum renderBufferFormat,GLenum format,GLenum type)9991 bool checkFloatTextureRender(GLenum renderBufferFormat, GLenum format, GLenum type)
9992 {
9993 bool framebufferComplete =
9994 performFloatTextureRender(format, renderBufferFormat, format, type);
9995
9996 if (!framebufferComplete)
9997 {
9998 return false;
9999 }
10000
10001 EXPECT_PIXEL_COLOR32F_NEAR(0, 0,
10002 SliceFormatColor32F(format, GLColor32F(1.0f, 1.0f, 1.0f, 1.0f)),
10003 kPixelTolerance32F);
10004 return true;
10005 }
10006 };
10007
10008 // Test texture sampling for ES3 float texture formats
TEST_P(Texture2DFloatTestES3,TextureFloatSampleBasicTest)10009 TEST_P(Texture2DFloatTestES3, TextureFloatSampleBasicTest)
10010 {
10011 testFloatTextureSample(GL_RGBA32F, GL_RGBA, GL_FLOAT);
10012 testFloatTextureSample(GL_RGB32F, GL_RGB, GL_FLOAT);
10013 }
10014
10015 // Test texture sampling for ES2 float texture formats
TEST_P(Texture2DFloatTestES2,TextureFloatSampleBasicTest)10016 TEST_P(Texture2DFloatTestES2, TextureFloatSampleBasicTest)
10017 {
10018 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10019 testFloatTextureSample(GL_RGBA, GL_RGBA, GL_FLOAT);
10020 testFloatTextureSample(GL_RGB, GL_RGB, GL_FLOAT);
10021 }
10022
10023 // Test texture sampling for ES3 half float texture formats
TEST_P(Texture2DFloatTestES3,TextureHalfFloatSampleBasicTest)10024 TEST_P(Texture2DFloatTestES3, TextureHalfFloatSampleBasicTest)
10025 {
10026 testFloatTextureSample(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
10027 testFloatTextureSample(GL_RGB16F, GL_RGB, GL_HALF_FLOAT);
10028 }
10029
10030 // Test texture sampling for ES2 half float texture formats
TEST_P(Texture2DFloatTestES2,TextureHalfFloatSampleBasicTest)10031 TEST_P(Texture2DFloatTestES2, TextureHalfFloatSampleBasicTest)
10032 {
10033 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10034 testFloatTextureSample(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES);
10035 testFloatTextureSample(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES);
10036 }
10037
10038 // Test texture sampling for legacy GLES 2.0 float texture formats in ES3
TEST_P(Texture2DFloatTestES3,TextureFloatSampleLegacyTest)10039 TEST_P(Texture2DFloatTestES3, TextureFloatSampleLegacyTest)
10040 {
10041 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10042
10043 testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
10044 testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_FLOAT);
10045 testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
10046
10047 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
10048 {
10049 testFloatTextureSample(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT);
10050 testFloatTextureSample(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT);
10051 testFloatTextureSample(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT);
10052 }
10053 }
10054
10055 // Test texture sampling for legacy GLES 2.0 float texture formats in ES2
TEST_P(Texture2DFloatTestES2,TextureFloatSampleLegacyTest)10056 TEST_P(Texture2DFloatTestES2, TextureFloatSampleLegacyTest)
10057 {
10058 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10059
10060 testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
10061 testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_FLOAT);
10062 testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
10063 }
10064
10065 // Test texture sampling for legacy GLES 2.0 half float texture formats in ES3
TEST_P(Texture2DFloatTestES3,TextureHalfFloatSampleLegacyTest)10066 TEST_P(Texture2DFloatTestES3, TextureHalfFloatSampleLegacyTest)
10067 {
10068 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10069
10070 testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
10071 testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
10072 testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
10073
10074 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
10075 {
10076 testFloatTextureSample(GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT);
10077 testFloatTextureSample(GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT);
10078 testFloatTextureSample(GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT);
10079 }
10080 }
10081 // Test texture sampling for legacy GLES 2.0 half float texture formats in ES2
TEST_P(Texture2DFloatTestES2,TextureHalfFloatSampleLegacyTest)10082 TEST_P(Texture2DFloatTestES2, TextureHalfFloatSampleLegacyTest)
10083 {
10084 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10085
10086 testFloatTextureSample(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
10087 testFloatTextureSample(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
10088 testFloatTextureSample(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
10089 }
10090
10091 // Test linear sampling for ES3 32F formats
TEST_P(Texture2DFloatTestES3,TextureFloatLinearTest)10092 TEST_P(Texture2DFloatTestES3, TextureFloatLinearTest)
10093 {
10094 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
10095 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
10096
10097 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
10098
10099 testFloatTextureLinear(GL_RGBA32F, GL_RGBA, GL_FLOAT);
10100 testFloatTextureLinear(GL_RGB32F, GL_RGB, GL_FLOAT);
10101 }
10102 // Test linear sampling for ES2 32F formats
TEST_P(Texture2DFloatTestES2,TextureFloatLinearTest)10103 TEST_P(Texture2DFloatTestES2, TextureFloatLinearTest)
10104 {
10105 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
10106 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
10107
10108 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
10109
10110 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10111
10112 testFloatTextureLinear(GL_RGBA, GL_RGBA, GL_FLOAT);
10113 }
10114
10115 // Test linear sampling for ES3 16F formats
TEST_P(Texture2DFloatTestES3,TextureHalfFloatLinearTest)10116 TEST_P(Texture2DFloatTestES3, TextureHalfFloatLinearTest)
10117 {
10118 // Half float formats must be linearly filterable in GLES 3.0 core
10119 testFloatTextureLinear(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
10120 testFloatTextureLinear(GL_RGB16F, GL_RGB, GL_HALF_FLOAT);
10121 }
10122 // Test linear sampling for ES2 16F formats
TEST_P(Texture2DFloatTestES2,TextureHalfFloatLinearTest)10123 TEST_P(Texture2DFloatTestES2, TextureHalfFloatLinearTest)
10124 {
10125 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float_linear"));
10126 testFloatTextureLinear(GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES);
10127 testFloatTextureLinear(GL_RGB, GL_RGB, GL_HALF_FLOAT_OES);
10128 }
10129
10130 // Test linear sampling for legacy GLES 2.0 32F formats in ES3
TEST_P(Texture2DFloatTestES3,TextureFloatLinearLegacyTest)10131 TEST_P(Texture2DFloatTestES3, TextureFloatLinearLegacyTest)
10132 {
10133 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
10134 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
10135
10136 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10137 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
10138
10139 testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
10140 testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_FLOAT);
10141 testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
10142
10143 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
10144 {
10145 testFloatTextureLinear(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT);
10146 testFloatTextureLinear(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT);
10147 testFloatTextureLinear(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT);
10148 }
10149 }
10150 // Test linear sampling for legacy GLES 2.0 32F formats in ES2
TEST_P(Texture2DFloatTestES2,TextureFloatLinearLegacyTest)10151 TEST_P(Texture2DFloatTestES2, TextureFloatLinearLegacyTest)
10152 {
10153 // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
10154 ANGLE_SKIP_TEST_IF(IsMac() && IsARM64() && (IsDesktopOpenGL()));
10155
10156 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
10157 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float_linear"));
10158
10159 testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT);
10160 testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_FLOAT);
10161 testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT);
10162 }
10163
10164 // Test linear sampling for legacy GLES 2.0 16F formats in ES3
TEST_P(Texture2DFloatTestES3,TextureHalfFloatLinearLegacyTest)10165 TEST_P(Texture2DFloatTestES3, TextureHalfFloatLinearLegacyTest)
10166 {
10167 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10168 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float_linear"));
10169
10170 testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
10171 testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
10172 testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
10173
10174 if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
10175 {
10176 testFloatTextureLinear(GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT);
10177 testFloatTextureLinear(GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT);
10178 testFloatTextureLinear(GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT);
10179 }
10180 }
10181 // Test linear sampling for legacy GLES 2.0 16F formats in ES2
TEST_P(Texture2DFloatTestES2,TextureHalfFloatLinearLegacyTest)10182 TEST_P(Texture2DFloatTestES2, TextureHalfFloatLinearLegacyTest)
10183 {
10184 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float"));
10185 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_half_float_linear"));
10186
10187 testFloatTextureLinear(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES);
10188 testFloatTextureLinear(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES);
10189 testFloatTextureLinear(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES);
10190 }
10191
10192 // Test color-renderability for ES3 float and half float textures
TEST_P(Texture2DFloatTestES3,TextureFloatRenderTest)10193 TEST_P(Texture2DFloatTestES3, TextureFloatRenderTest)
10194 {
10195 // http://anglebug.com/4092
10196 ANGLE_SKIP_TEST_IF(IsD3D9());
10197 // EXT_color_buffer_float covers float, half float, and 11-11-10 float formats
10198 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
10199
10200 testFloatTextureRender(GL_R32F, GL_RED, GL_FLOAT);
10201 testFloatTextureRender(GL_RG32F, GL_RG, GL_FLOAT);
10202 testFloatTextureRender(GL_RGBA32F, GL_RGBA, GL_FLOAT);
10203
10204 testFloatTextureRender(GL_R16F, GL_RED, GL_HALF_FLOAT);
10205 testFloatTextureRender(GL_RG16F, GL_RG, GL_HALF_FLOAT);
10206 testFloatTextureRender(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
10207
10208 testFloatTextureRender(GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT);
10209 }
10210
10211 // Test color-renderability for ES2 half float textures
TEST_P(Texture2DFloatTestES2,TextureFloatRenderTest)10212 TEST_P(Texture2DFloatTestES2, TextureFloatRenderTest)
10213 {
10214 // EXT_color_buffer_half_float requires at least one format to be renderable, but does not
10215 // require a specific one
10216 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"));
10217 // https://crbug.com/1003971
10218 ANGLE_SKIP_TEST_IF(IsOzone());
10219 // http://anglebug.com/4092
10220 ANGLE_SKIP_TEST_IF(IsD3D9());
10221
10222 bool atLeastOneSupported = false;
10223
10224 if (IsGLExtensionEnabled("GL_OES_texture_half_float") ||
10225 IsGLExtensionEnabled("GL_OES_texture_half_float"))
10226 {
10227 atLeastOneSupported |= checkFloatTextureRender(GL_R16F_EXT, GL_RED_EXT, GL_HALF_FLOAT_OES);
10228 atLeastOneSupported |= checkFloatTextureRender(GL_RG16F_EXT, GL_RG_EXT, GL_HALF_FLOAT_OES);
10229 }
10230 if (IsGLExtensionEnabled("GL_OES_texture_half_float"))
10231 {
10232 atLeastOneSupported |= checkFloatTextureRender(GL_RGB16F_EXT, GL_RGB, GL_HALF_FLOAT_OES);
10233
10234 // If OES_texture_half_float is supported, then RGBA half float textures must be renderable
10235 bool rgbaSupported = checkFloatTextureRender(GL_RGBA16F_EXT, GL_RGBA, GL_HALF_FLOAT_OES);
10236 EXPECT_TRUE(rgbaSupported);
10237 atLeastOneSupported |= rgbaSupported;
10238 }
10239
10240 EXPECT_TRUE(atLeastOneSupported);
10241 }
10242
10243 // Test that UNPACK_SKIP_IMAGES doesn't have an effect on 2D texture uploads.
10244 // GLES 3.0.4 section 3.8.3.
TEST_P(Texture2DTestES3,UnpackSkipImages2D)10245 TEST_P(Texture2DTestES3, UnpackSkipImages2D)
10246 {
10247 // Crashes on Nexus 5X due to a driver bug. http://anglebug.com/1429
10248 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
10249
10250 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10251 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10252 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10253 ASSERT_GL_NO_ERROR();
10254
10255 // SKIP_IMAGES should not have an effect on uploading 2D textures
10256 glPixelStorei(GL_UNPACK_SKIP_IMAGES, 1000);
10257 ASSERT_GL_NO_ERROR();
10258
10259 std::vector<GLColor> pixelsGreen(128u * 128u, GLColor::green);
10260
10261 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10262 pixelsGreen.data());
10263 ASSERT_GL_NO_ERROR();
10264
10265 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE,
10266 pixelsGreen.data());
10267 ASSERT_GL_NO_ERROR();
10268
10269 glUseProgram(mProgram);
10270 drawQuad(mProgram, "position", 0.5f);
10271 ASSERT_GL_NO_ERROR();
10272
10273 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10274 }
10275
10276 // Test that skip defined in unpack parameters is taken into account when determining whether
10277 // unpacking source extends outside unpack buffer bounds.
TEST_P(Texture2DTestES3,UnpackSkipPixelsOutOfBounds)10278 TEST_P(Texture2DTestES3, UnpackSkipPixelsOutOfBounds)
10279 {
10280 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10281 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10282 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10283 ASSERT_GL_NO_ERROR();
10284
10285 GLBuffer buf;
10286 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
10287 std::vector<GLColor> pixelsGreen(128u * 128u, GLColor::green);
10288 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
10289 GL_DYNAMIC_COPY);
10290 ASSERT_GL_NO_ERROR();
10291
10292 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10293 ASSERT_GL_NO_ERROR();
10294
10295 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 1);
10296 ASSERT_GL_NO_ERROR();
10297
10298 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10299 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
10300
10301 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
10302 glPixelStorei(GL_UNPACK_SKIP_ROWS, 1);
10303 ASSERT_GL_NO_ERROR();
10304
10305 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10306 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
10307 }
10308
10309 // Test unpacking to texture from a buffer with a compatible format but different type.
10310 // Compatible formats can be found in "Table 8.2: Valid combinations of format, type, and sized
10311 // internal format." of the OpenGL ES 3.2 spec.
TEST_P(Texture2DTestES3,UnpackCompatibleFormatButDifferentType)10312 TEST_P(Texture2DTestES3, UnpackCompatibleFormatButDifferentType)
10313 {
10314 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10315 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10316 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10317 ASSERT_GL_NO_ERROR();
10318
10319 // Create texture with GL_RGBA4 format and fill with red
10320 std::vector<GLColor> pixelsRed(128u * 128u, GLColor::red);
10321 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10322 pixelsRed.data());
10323 ASSERT_GL_NO_ERROR();
10324
10325 // Call glTexSubImage2D with incompatible format and expect an error
10326 std::array<GLubyte, 2> rgColor = {255, 255};
10327 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RG, GL_UNSIGNED_BYTE, rgColor.data());
10328 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
10329
10330 glUseProgram(mProgram);
10331 drawQuad(mProgram, "position", 0.5f);
10332 ASSERT_GL_NO_ERROR();
10333 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10334
10335 // Create unpack buffer with GL_RGBA8
10336 GLBuffer buf;
10337 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
10338 std::vector<GLColor> pixelsGreen(128u * 128u, GLColor::green);
10339 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
10340 GL_DYNAMIC_COPY);
10341 ASSERT_GL_NO_ERROR();
10342
10343 // Unpack GL_RGBA8 buffer data to GL_RGBA4 texture
10344 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10345 ASSERT_GL_NO_ERROR();
10346
10347 // Validate that the data was unpacked correctly
10348 glUseProgram(mProgram);
10349 drawQuad(mProgram, "position", 0.5f);
10350 ASSERT_GL_NO_ERROR();
10351
10352 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10353 }
10354
10355 // Test that unpacking rows that overlap in a pixel unpack buffer works as expected.
TEST_P(Texture2DTestES3,UnpackOverlappingRowsFromUnpackBuffer)10356 TEST_P(Texture2DTestES3, UnpackOverlappingRowsFromUnpackBuffer)
10357 {
10358 ANGLE_SKIP_TEST_IF(IsD3D11());
10359
10360 // Incorrect rendering results seen on OSX AMD.
10361 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsMac() && IsAMD());
10362
10363 const GLuint width = 8u;
10364 const GLuint height = 8u;
10365 const GLuint unpackRowLength = 5u;
10366 const GLuint unpackSkipPixels = 1u;
10367
10368 setWindowWidth(width);
10369 setWindowHeight(height);
10370
10371 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10372 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10373 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10374 ASSERT_GL_NO_ERROR();
10375
10376 GLBuffer buf;
10377 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
10378 std::vector<GLColor> pixelsGreen((height - 1u) * unpackRowLength + width + unpackSkipPixels,
10379 GLColor::green);
10380
10381 for (GLuint skippedPixel = 0u; skippedPixel < unpackSkipPixels; ++skippedPixel)
10382 {
10383 pixelsGreen[skippedPixel] = GLColor(255, 0, 0, 255);
10384 }
10385
10386 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixelsGreen.size() * 4u, pixelsGreen.data(),
10387 GL_DYNAMIC_COPY);
10388 ASSERT_GL_NO_ERROR();
10389
10390 glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackRowLength);
10391 glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackSkipPixels);
10392 ASSERT_GL_NO_ERROR();
10393
10394 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
10395 ASSERT_GL_NO_ERROR();
10396
10397 glUseProgram(mProgram);
10398 drawQuad(mProgram, "position", 0.5f);
10399 ASSERT_GL_NO_ERROR();
10400
10401 GLuint windowPixelCount = getWindowWidth() * getWindowHeight();
10402 std::vector<GLColor> actual(windowPixelCount, GLColor::black);
10403 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
10404 actual.data());
10405 std::vector<GLColor> expected(windowPixelCount, GLColor::green);
10406 EXPECT_EQ(expected, actual);
10407 }
10408
10409 template <typename T>
UNorm(double value)10410 T UNorm(double value)
10411 {
10412 return static_cast<T>(value * static_cast<double>(std::numeric_limits<T>::max()));
10413 }
10414
10415 // Test rendering a depth texture with mipmaps.
TEST_P(Texture2DTestES3,DepthTexturesWithMipmaps)10416 TEST_P(Texture2DTestES3, DepthTexturesWithMipmaps)
10417 {
10418 // TODO(cwallez) this is failing on Intel Win7 OpenGL.
10419 // TODO(zmo) this is faling on Win Intel HD 530 Debug.
10420 // http://anglebug.com/1706
10421 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsOpenGL());
10422
10423 // Seems to fail on AMD D3D11. Possibly driver bug. http://anglebug.com/3342
10424 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsD3D11());
10425
10426 // TODO(cnorthrop): Also failing on Vulkan/Windows/AMD. http://anglebug.com/3950
10427 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
10428
10429 const int size = getWindowWidth();
10430
10431 auto dim = [size](int level) { return size >> level; };
10432 int levels = gl::log2(size);
10433
10434 glActiveTexture(GL_TEXTURE0);
10435 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10436 glTexStorage2D(GL_TEXTURE_2D, levels, GL_DEPTH_COMPONENT24, size, size);
10437 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10438 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10439 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
10440 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
10441 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
10442 ASSERT_GL_NO_ERROR();
10443
10444 glUseProgram(mProgram);
10445 glUniform1i(mTexture2DUniformLocation, 0);
10446
10447 std::vector<unsigned char> expected;
10448
10449 for (int level = 0; level < levels; ++level)
10450 {
10451 double value = (static_cast<double>(level) / static_cast<double>(levels - 1));
10452 expected.push_back(UNorm<unsigned char>(value));
10453
10454 int levelDim = dim(level);
10455
10456 ASSERT_GT(levelDim, 0);
10457
10458 std::vector<unsigned int> initData(levelDim * levelDim, UNorm<unsigned int>(value));
10459 glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, levelDim, levelDim, GL_DEPTH_COMPONENT,
10460 GL_UNSIGNED_INT, initData.data());
10461 }
10462 ASSERT_GL_NO_ERROR();
10463
10464 for (int level = 0; level < levels; ++level)
10465 {
10466 glViewport(0, 0, dim(level), dim(level));
10467 drawQuad(mProgram, "position", 0.5f);
10468 GLColor actual = ReadColor(0, 0);
10469 EXPECT_NEAR(expected[level], actual.R, 10u);
10470 }
10471
10472 ASSERT_GL_NO_ERROR();
10473 }
10474
10475 class Texture2DDepthTest : public Texture2DTest
10476 {
10477 protected:
Texture2DDepthTest()10478 Texture2DDepthTest() : Texture2DTest() {}
10479
getVertexShaderSource()10480 const char *getVertexShaderSource() override
10481 {
10482 return "attribute vec4 vPosition;\n"
10483 "void main() {\n"
10484 " gl_Position = vPosition;\n"
10485 "}\n";
10486 }
10487
getFragmentShaderSource()10488 const char *getFragmentShaderSource() override
10489 {
10490 return "precision mediump float;\n"
10491 "uniform sampler2D ShadowMap;"
10492 "void main() {\n"
10493 " vec4 shadow_value = texture2D(ShadowMap, vec2(0.5, 0.5));"
10494 " if (shadow_value.x == shadow_value.z && shadow_value.x != 0.0) {"
10495 " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);"
10496 " } else {"
10497 " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
10498 " }"
10499 "}\n";
10500 }
10501
checkTexImageFormatSupport(GLenum format,GLenum internalformat,GLenum type)10502 bool checkTexImageFormatSupport(GLenum format, GLenum internalformat, GLenum type)
10503 {
10504 EXPECT_GL_NO_ERROR();
10505
10506 GLTexture tex;
10507 glBindTexture(GL_TEXTURE_2D, tex);
10508 glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, type, nullptr);
10509
10510 return (glGetError() == GL_NO_ERROR);
10511 }
10512
testBehavior(bool useSizedComponent)10513 void testBehavior(bool useSizedComponent)
10514 {
10515 int w = getWindowWidth();
10516 int h = getWindowHeight();
10517 GLuint format = GL_DEPTH_COMPONENT;
10518 GLuint internalFormat = GL_DEPTH_COMPONENT;
10519
10520 if (useSizedComponent)
10521 {
10522 internalFormat = GL_DEPTH_COMPONENT24;
10523 }
10524
10525 GLFramebuffer fbo;
10526 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10527 ASSERT_GL_NO_ERROR();
10528
10529 GLTexture depthTexture;
10530 glBindTexture(GL_TEXTURE_2D, depthTexture);
10531 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10532 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10533 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
10534 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
10535
10536 TexCoordDrawTest::setUpProgram();
10537 GLint shadowMapLocation = glGetUniformLocation(mProgram, "ShadowMap");
10538 ASSERT_NE(-1, shadowMapLocation);
10539
10540 GLint positionLocation = glGetAttribLocation(mProgram, "vPosition");
10541 ASSERT_NE(-1, positionLocation);
10542
10543 ANGLE_SKIP_TEST_IF(!checkTexImageFormatSupport(format, internalFormat, GL_UNSIGNED_INT));
10544 glBindTexture(GL_TEXTURE_2D, depthTexture);
10545 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, format, GL_UNSIGNED_INT, nullptr);
10546 ASSERT_GL_NO_ERROR();
10547
10548 // try adding a color buffer.
10549 GLTexture colorTex;
10550 glBindTexture(GL_TEXTURE_2D, colorTex);
10551 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
10552 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
10553 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10554 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10555 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10556 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
10557 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
10558 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
10559 ASSERT_GL_NO_ERROR();
10560
10561 glViewport(0, 0, w, h);
10562 // Fill depthTexture with 0.75
10563 glClearDepthf(0.75);
10564 glClear(GL_DEPTH_BUFFER_BIT);
10565
10566 // Revert to normal framebuffer to test depth shader
10567 glBindFramebuffer(GL_FRAMEBUFFER, 0);
10568 glViewport(0, 0, w, h);
10569 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
10570 glClearDepthf(0.0f);
10571 ASSERT_GL_NO_ERROR();
10572
10573 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
10574 ASSERT_GL_NO_ERROR();
10575
10576 glActiveTexture(GL_TEXTURE0);
10577 glBindTexture(GL_TEXTURE_2D, depthTexture);
10578
10579 glUseProgram(mProgram);
10580 ASSERT_GL_NO_ERROR();
10581
10582 glUniform1i(shadowMapLocation, 0);
10583
10584 const GLfloat gTriangleVertices[] = {-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f};
10585
10586 glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
10587 ASSERT_GL_NO_ERROR();
10588 glEnableVertexAttribArray(positionLocation);
10589 ASSERT_GL_NO_ERROR();
10590 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10591 ASSERT_GL_NO_ERROR();
10592
10593 GLuint pixels[1];
10594 glReadPixels(w / 2, h / 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
10595 ASSERT_GL_NO_ERROR();
10596
10597 // The GLES 3.x spec says that the depth texture sample can be found in the RED component.
10598 // However, the OES_depth_texture indicates that the depth value is treated as luminance and
10599 // is in all the color components. Multiple implementations implement a workaround that
10600 // follows the OES_depth_texture behavior if the internalformat given at glTexImage2D was a
10601 // unsized format (e.g. DEPTH_COMPONENT) and the GLES 3.x behavior if it was a sized
10602 // internalformat such as GL_DEPTH_COMPONENT24. The shader will write out a different color
10603 // depending on if it sees the texture sample in only the RED component.
10604 if (useSizedComponent)
10605 {
10606 ASSERT_NE(pixels[0], 0xff0000ff);
10607 }
10608 else
10609 {
10610 ASSERT_EQ(pixels[0], 0xff0000ff);
10611 }
10612
10613 glBindFramebuffer(GL_FRAMEBUFFER, 0);
10614 glDeleteProgram(mProgram);
10615 }
10616 };
10617
10618 // Test depth texture compatibility with OES_depth_texture. Uses unsized internal format.
TEST_P(Texture2DDepthTest,DepthTextureES2Compatibility)10619 TEST_P(Texture2DDepthTest, DepthTextureES2Compatibility)
10620 {
10621 ANGLE_SKIP_TEST_IF(IsD3D11());
10622 ANGLE_SKIP_TEST_IF(IsIntel() && IsD3D9());
10623 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_depth_texture") &&
10624 !IsGLExtensionEnabled("GL_OES_depth_texture"));
10625 // http://anglebug.com/4092
10626 ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
10627 ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());
10628
10629 // When the depth texture is specified with unsized internalformat implementations follow
10630 // OES_depth_texture behavior. Otherwise they follow GLES 3.0 behavior.
10631 testBehavior(false);
10632 }
10633
10634 // Test depth texture compatibility with GLES3 using sized internalformat.
TEST_P(Texture2DDepthTest,DepthTextureES3Compatibility)10635 TEST_P(Texture2DDepthTest, DepthTextureES3Compatibility)
10636 {
10637 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
10638
10639 // http://anglebug.com/5243
10640 ANGLE_SKIP_TEST_IF(IsMetal() && !IsMetalTextureSwizzleAvailable());
10641
10642 testBehavior(true);
10643 }
10644
10645 // Tests unpacking into the unsized GL_ALPHA format.
TEST_P(Texture2DTestES3,UnsizedAlphaUnpackBuffer)10646 TEST_P(Texture2DTestES3, UnsizedAlphaUnpackBuffer)
10647 {
10648 // Initialize the texure.
10649 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10650 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, getWindowWidth(), getWindowHeight(), 0, GL_ALPHA,
10651 GL_UNSIGNED_BYTE, nullptr);
10652 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10653 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10654
10655 std::vector<GLubyte> bufferData(getWindowWidth() * getWindowHeight(), 127);
10656
10657 // Pull in the color data from the unpack buffer.
10658 GLBuffer unpackBuffer;
10659 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
10660 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer);
10661 glBufferData(GL_PIXEL_UNPACK_BUFFER, getWindowWidth() * getWindowHeight(), bufferData.data(),
10662 GL_STATIC_DRAW);
10663
10664 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth(), getWindowHeight(), GL_ALPHA,
10665 GL_UNSIGNED_BYTE, nullptr);
10666
10667 // Clear to a weird color to make sure we're drawing something.
10668 glClearColor(0.5f, 0.8f, 1.0f, 0.2f);
10669 glClear(GL_COLOR_BUFFER_BIT);
10670
10671 // Draw with the alpha texture and verify.
10672 drawQuad(mProgram, "position", 0.5f);
10673
10674 ASSERT_GL_NO_ERROR();
10675 EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 127, 1);
10676 }
10677
10678 // Ensure stale unpack data doesn't propagate in D3D11.
TEST_P(Texture2DTestES3,StaleUnpackData)10679 TEST_P(Texture2DTestES3, StaleUnpackData)
10680 {
10681 // Init unpack buffer.
10682 GLsizei pixelCount = getWindowWidth() * getWindowHeight() / 2;
10683 std::vector<GLColor> pixels(pixelCount, GLColor::red);
10684
10685 GLBuffer unpackBuffer;
10686 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
10687 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer);
10688 GLsizei bufferSize = pixelCount * sizeof(GLColor);
10689 glBufferData(GL_PIXEL_UNPACK_BUFFER, bufferSize, pixels.data(), GL_STATIC_DRAW);
10690
10691 // Create from unpack buffer.
10692 glBindTexture(GL_TEXTURE_2D, mTexture2D);
10693 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth() / 2, getWindowHeight() / 2, 0,
10694 GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10695 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10696 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10697
10698 drawQuad(mProgram, "position", 0.5f);
10699
10700 ASSERT_GL_NO_ERROR();
10701 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10702
10703 // Fill unpack with green, recreating buffer.
10704 pixels.assign(getWindowWidth() * getWindowHeight(), GLColor::green);
10705 GLsizei size2 = getWindowWidth() * getWindowHeight() * sizeof(GLColor);
10706 glBufferData(GL_PIXEL_UNPACK_BUFFER, size2, pixels.data(), GL_STATIC_DRAW);
10707
10708 // Reinit texture with green.
10709 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth() / 2, getWindowHeight() / 2, GL_RGBA,
10710 GL_UNSIGNED_BYTE, nullptr);
10711
10712 drawQuad(mProgram, "position", 0.5f);
10713
10714 ASSERT_GL_NO_ERROR();
10715 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10716 }
10717
10718 // Ensure that texture parameters passed as floats that are converted to ints are rounded before
10719 // validating they are less than 0.
TEST_P(Texture2DTestES3,TextureBaseMaxLevelRoundingValidation)10720 TEST_P(Texture2DTestES3, TextureBaseMaxLevelRoundingValidation)
10721 {
10722 GLTexture texture;
10723 glBindTexture(GL_TEXTURE_2D, texture);
10724
10725 // Use a negative number that will round to zero when converted to an integer
10726 // According to the spec(2.3.1 Data Conversion For State - Setting Commands):
10727 // "Validation of values performed by state-setting commands is performed after conversion,
10728 // unless specified otherwise for a specific command."
10729 GLfloat param = -7.30157126e-07f;
10730 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, param);
10731 EXPECT_GL_NO_ERROR();
10732
10733 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, param);
10734 EXPECT_GL_NO_ERROR();
10735 }
10736
10737 // This test covers a D3D format redefinition bug for 3D textures. The base level format was not
10738 // being properly checked, and the texture storage of the previous texture format was persisting.
10739 // This would result in an ASSERT in debug and incorrect rendering in release.
10740 // See http://anglebug.com/1609 and WebGL 2 test conformance2/misc/views-with-offsets.html.
TEST_P(Texture3DTestES3,FormatRedefinitionBug)10741 TEST_P(Texture3DTestES3, FormatRedefinitionBug)
10742 {
10743 GLTexture tex;
10744 glBindTexture(GL_TEXTURE_3D, tex);
10745 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10746
10747 GLFramebuffer framebuffer;
10748 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
10749 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0);
10750
10751 glCheckFramebufferStatus(GL_FRAMEBUFFER);
10752
10753 std::vector<uint8_t> pixelData(100, 0);
10754
10755 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB565, 1, 1, 1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, nullptr);
10756 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
10757 pixelData.data());
10758
10759 ASSERT_GL_NO_ERROR();
10760 }
10761
10762 // Test glTexSubImage using PBO to 3D texture that expose the regression bug
10763 // https://issuetracker.google.com/170657065
TEST_P(Texture3DTestES3,TexSubImageWithPBO)10764 TEST_P(Texture3DTestES3, TexSubImageWithPBO)
10765 {
10766 GLTexture tex;
10767
10768 GLuint pbo;
10769 glGenBuffers(1, &pbo);
10770 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
10771 std::vector<uint8_t> pixelData(128 * 128 * 8 * 4, 0x1f);
10772 glBufferData(GL_PIXEL_UNPACK_BUFFER, 128 * 128 * 8 * 4, pixelData.data(), GL_STATIC_DRAW);
10773
10774 glBindTexture(GL_TEXTURE_3D, tex);
10775 glTexStorage3D(GL_TEXTURE_3D, 8, GL_RGBA8, 128, 128, 8);
10776 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
10777 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10778 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 128, 128, 8, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10779 glTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 64, 64, 4, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10780 glTexSubImage3D(GL_TEXTURE_3D, 2, 0, 0, 0, 32, 32, 2, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10781 glTexSubImage3D(GL_TEXTURE_3D, 3, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10782 glTexSubImage3D(GL_TEXTURE_3D, 4, 0, 0, 0, 8, 8, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10783 glTexSubImage3D(GL_TEXTURE_3D, 5, 0, 0, 0, 4, 4, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10784 glTexSubImage3D(GL_TEXTURE_3D, 6, 0, 0, 0, 2, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10785 glTexSubImage3D(GL_TEXTURE_3D, 7, 0, 0, 0, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10786
10787 drawQuad(mProgram, "position", 0.5f);
10788 ASSERT_GL_NO_ERROR();
10789
10790 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 128, 128, 8, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10791 glTexSubImage3D(GL_TEXTURE_3D, 1, 0, 0, 0, 64, 64, 4, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10792 glTexSubImage3D(GL_TEXTURE_3D, 2, 0, 0, 0, 32, 32, 2, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10793 ASSERT_GL_NO_ERROR();
10794
10795 drawQuad(mProgram, "position", 0.5f);
10796 ASSERT_GL_NO_ERROR();
10797 }
10798
10799 // Test basic pixel unpack buffer OOB checks when uploading to a 2D or 3D texture
TEST_P(Texture3DTestES3,BasicUnpackBufferOOB)10800 TEST_P(Texture3DTestES3, BasicUnpackBufferOOB)
10801 {
10802 // 2D tests
10803 {
10804 GLTexture tex;
10805 glBindTexture(GL_TEXTURE_2D, tex);
10806
10807 GLBuffer pbo;
10808 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
10809
10810 // Test OOB
10811 glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 - 1, nullptr, GL_STATIC_DRAW);
10812 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10813 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
10814
10815 // Test OOB
10816 glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2, nullptr, GL_STATIC_DRAW);
10817 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10818 ASSERT_GL_NO_ERROR();
10819 }
10820
10821 // 3D tests
10822 {
10823 GLTexture tex;
10824 glBindTexture(GL_TEXTURE_3D, tex);
10825
10826 GLBuffer pbo;
10827 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
10828
10829 // Test OOB
10830 glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 * 2 - 1, nullptr,
10831 GL_STATIC_DRAW);
10832 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10833 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
10834
10835 // Test OOB
10836 glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(GLColor) * 2 * 2 * 2, nullptr, GL_STATIC_DRAW);
10837 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
10838 ASSERT_GL_NO_ERROR();
10839 }
10840 }
10841
10842 // Tests behaviour with a single texture and multiple sampler objects.
TEST_P(Texture2DTestES3,SingleTextureMultipleSamplers)10843 TEST_P(Texture2DTestES3, SingleTextureMultipleSamplers)
10844 {
10845 GLint maxTextureUnits = 0;
10846 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
10847 ANGLE_SKIP_TEST_IF(maxTextureUnits < 4);
10848
10849 constexpr int kSize = 16;
10850
10851 // Make a single-level texture, fill it with red.
10852 std::vector<GLColor> redColors(kSize * kSize, GLColor::red);
10853 GLTexture tex;
10854 glBindTexture(GL_TEXTURE_2D, tex);
10855 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10856 redColors.data());
10857 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10858 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10859
10860 // Simple confidence check.
10861 draw2DTexturedQuad(0.5f, 1.0f, true);
10862 ASSERT_GL_NO_ERROR();
10863 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10864
10865 // Bind texture to unit 1 with a sampler object making it incomplete.
10866 GLSampler sampler;
10867 glBindSampler(0, sampler);
10868 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10869 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10870
10871 // Make a mipmap texture, fill it with blue.
10872 std::vector<GLColor> blueColors(kSize * kSize, GLColor::blue);
10873 GLTexture mipmapTex;
10874 glBindTexture(GL_TEXTURE_2D, mipmapTex);
10875 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
10876 blueColors.data());
10877 glGenerateMipmap(GL_TEXTURE_2D);
10878
10879 // Draw with the sampler, expect blue.
10880 draw2DTexturedQuad(0.5f, 1.0f, true);
10881 ASSERT_GL_NO_ERROR();
10882 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
10883
10884 // Simple multitexturing program.
10885 constexpr char kVS[] =
10886 "#version 300 es\n"
10887 "in vec2 position;\n"
10888 "out vec2 texCoord;\n"
10889 "void main()\n"
10890 "{\n"
10891 " gl_Position = vec4(position, 0, 1);\n"
10892 " texCoord = position * 0.5 + vec2(0.5);\n"
10893 "}";
10894
10895 constexpr char kFS[] =
10896 "#version 300 es\n"
10897 "precision mediump float;\n"
10898 "in vec2 texCoord;\n"
10899 "uniform sampler2D tex1;\n"
10900 "uniform sampler2D tex2;\n"
10901 "uniform sampler2D tex3;\n"
10902 "uniform sampler2D tex4;\n"
10903 "out vec4 color;\n"
10904 "void main()\n"
10905 "{\n"
10906 " color = (texture(tex1, texCoord) + texture(tex2, texCoord) \n"
10907 " + texture(tex3, texCoord) + texture(tex4, texCoord)) * 0.25;\n"
10908 "}";
10909
10910 ANGLE_GL_PROGRAM(program, kVS, kFS);
10911
10912 std::array<GLint, 4> texLocations = {
10913 {glGetUniformLocation(program, "tex1"), glGetUniformLocation(program, "tex2"),
10914 glGetUniformLocation(program, "tex3"), glGetUniformLocation(program, "tex4")}};
10915 for (GLint location : texLocations)
10916 {
10917 ASSERT_NE(-1, location);
10918 }
10919
10920 // Init the uniform data.
10921 glUseProgram(program);
10922 for (GLint location = 0; location < 4; ++location)
10923 {
10924 glUniform1i(texLocations[location], location);
10925 }
10926
10927 // Initialize four samplers
10928 GLSampler samplers[4];
10929
10930 // 0: non-mipped.
10931 glBindSampler(0, samplers[0]);
10932 glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10933 glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10934
10935 // 1: mipped.
10936 glBindSampler(1, samplers[1]);
10937 glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10938 glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10939
10940 // 2: non-mipped.
10941 glBindSampler(2, samplers[2]);
10942 glSamplerParameteri(samplers[2], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
10943 glSamplerParameteri(samplers[2], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10944
10945 // 3: mipped.
10946 glBindSampler(3, samplers[3]);
10947 glSamplerParameteri(samplers[3], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
10948 glSamplerParameteri(samplers[3], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
10949
10950 // Bind two blue mipped textures and two single layer textures, should all draw.
10951 glActiveTexture(GL_TEXTURE0);
10952 glBindTexture(GL_TEXTURE_2D, tex);
10953
10954 glActiveTexture(GL_TEXTURE1);
10955 glBindTexture(GL_TEXTURE_2D, mipmapTex);
10956
10957 glActiveTexture(GL_TEXTURE2);
10958 glBindTexture(GL_TEXTURE_2D, tex);
10959
10960 glActiveTexture(GL_TEXTURE3);
10961 glBindTexture(GL_TEXTURE_2D, mipmapTex);
10962
10963 ASSERT_GL_NO_ERROR();
10964
10965 drawQuad(program, "position", 0.5f);
10966 ASSERT_GL_NO_ERROR();
10967 EXPECT_PIXEL_NEAR(0, 0, 128, 0, 128, 255, 2);
10968
10969 // Bind four single layer textures, two should be incomplete.
10970 glActiveTexture(GL_TEXTURE1);
10971 glBindTexture(GL_TEXTURE_2D, tex);
10972
10973 glActiveTexture(GL_TEXTURE3);
10974 glBindTexture(GL_TEXTURE_2D, tex);
10975
10976 drawQuad(program, "position", 0.5f);
10977 ASSERT_GL_NO_ERROR();
10978 EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 2);
10979 }
10980
10981 // The test is added to cover http://anglebug.com/2153. Cubemap completeness checks used to start
10982 // always at level 0 instead of the base level resulting in an incomplete texture if the faces at
10983 // level 0 are not created. The test creates a cubemap texture, specifies the images only for mip
10984 // level 1 filled with white color, updates the base level to be 1 and renders a quad. The program
10985 // samples the cubemap using a direction vector (1,1,1).
TEST_P(TextureCubeTestES3,SpecifyAndSampleFromBaseLevel1)10986 TEST_P(TextureCubeTestES3, SpecifyAndSampleFromBaseLevel1)
10987 {
10988 // Check http://anglebug.com/2155.
10989 ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA());
10990
10991 constexpr char kVS[] =
10992 R"(#version 300 es
10993 precision mediump float;
10994 in vec3 pos;
10995 void main() {
10996 gl_Position = vec4(pos, 1.0);
10997 })";
10998
10999 constexpr char kFS[] =
11000 R"(#version 300 es
11001 precision mediump float;
11002 out vec4 color;
11003 uniform samplerCube uTex;
11004 void main(){
11005 color = texture(uTex, vec3(1.0));
11006 })";
11007
11008 ANGLE_GL_PROGRAM(program, kVS, kFS);
11009 glUseProgram(program);
11010
11011 glUniform1i(glGetUniformLocation(program, "uTex"), 0);
11012 glActiveTexture(GL_TEXTURE0);
11013
11014 GLTexture cubeTex;
11015 glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTex);
11016
11017 const int kFaceWidth = 1;
11018 const int kFaceHeight = 1;
11019 std::vector<uint32_t> texData(kFaceWidth * kFaceHeight, 0xFFFFFFFF);
11020 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11021 GL_UNSIGNED_BYTE, texData.data());
11022 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11023 GL_UNSIGNED_BYTE, texData.data());
11024 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11025 GL_UNSIGNED_BYTE, texData.data());
11026 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11027 GL_UNSIGNED_BYTE, texData.data());
11028 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11029 GL_UNSIGNED_BYTE, texData.data());
11030 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 1, GL_RGBA8, kFaceWidth, kFaceHeight, 0, GL_RGBA,
11031 GL_UNSIGNED_BYTE, texData.data());
11032 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11033 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11034 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
11035 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);
11036 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT);
11037 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 1);
11038
11039 drawQuad(program, "pos", 0.5f, 1.0f, true);
11040 ASSERT_GL_NO_ERROR();
11041
11042 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::white);
11043 }
11044
11045 // Test GL_PIXEL_UNPACK_BUFFER with GL_TEXTURE_CUBE_MAP.
TEST_P(TextureCubeTestES3,CubeMapPixelUnpackBuffer)11046 TEST_P(TextureCubeTestES3, CubeMapPixelUnpackBuffer)
11047 {
11048 // Check http://anglebug.com/2155.
11049 ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA());
11050
11051 constexpr char kVS[] =
11052 R"(#version 300 es
11053 precision mediump float;
11054 in vec3 pos;
11055 void main() {
11056 gl_Position = vec4(pos, 1.0);
11057 })";
11058
11059 constexpr char kFS[] =
11060 R"(#version 300 es
11061 precision mediump float;
11062 out vec4 color;
11063 uniform samplerCube uTex;
11064 void main(){
11065 color = texture(uTex, vec3(1.0));
11066 })";
11067
11068 ANGLE_GL_PROGRAM(program, kVS, kFS);
11069 glUseProgram(program);
11070
11071 glUniform1i(glGetUniformLocation(program, "uTex"), 0);
11072 glActiveTexture(GL_TEXTURE0);
11073
11074 GLTexture cubeTex;
11075 glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTex);
11076
11077 const int kFaceWidth = 4;
11078 const int kFaceHeight = 4;
11079
11080 uint16_t kHalfFloatOne = 0x3C00;
11081 uint16_t kHalfFloatZero = 0;
11082
11083 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA16F, kFaceWidth, kFaceHeight);
11084 struct RGBA16F
11085 {
11086 uint16_t R, G, B, A;
11087 };
11088 RGBA16F redColor = {kHalfFloatOne, kHalfFloatZero, kHalfFloatZero, kHalfFloatOne};
11089
11090 std::vector<RGBA16F> pixels(kFaceWidth * kFaceHeight, redColor);
11091 GLBuffer buffer;
11092 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
11093 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixels.size() * sizeof(RGBA16F), pixels.data(),
11094 GL_DYNAMIC_DRAW);
11095 EXPECT_GL_NO_ERROR();
11096 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
11097
11098 for (GLenum faceIndex = 0; faceIndex < 6; faceIndex++)
11099 {
11100 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, 0, 0, 0, kFaceWidth,
11101 kFaceHeight, GL_RGBA, GL_HALF_FLOAT, 0);
11102 EXPECT_GL_NO_ERROR();
11103 }
11104 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
11105
11106 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11107 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
11108 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
11109 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);
11110 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT);
11111
11112 drawQuad(program, "pos", 0.5f, 1.0f, true);
11113 ASSERT_GL_NO_ERROR();
11114
11115 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::red);
11116 }
11117
11118 // Test creating a mutable cubemap, committing it, and then incomaptibly redefining one layer, while
11119 // compatibly redefining another layer.
TEST_P(TextureCubeTestES3,IncompatibleLayerAThenCompatibleLayerB)11120 TEST_P(TextureCubeTestES3, IncompatibleLayerAThenCompatibleLayerB)
11121 {
11122 GLTexture tex;
11123 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11124
11125 std::vector<uint32_t> data(32 * 32 * 4, 0xC00FFC00);
11126
11127 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11128 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11129 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11130 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11131 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11132 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11133 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11134 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11135 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11136 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11137 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11138 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11139 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
11140 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 32, 32, 0, GL_RGBA,
11141 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11142 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11143 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11144 EXPECT_GL_NO_ERROR();
11145 }
11146
11147 // Test creating a mutable cubemap, committing it, and then comaptibly redefining one layer, while
11148 // incompatibly redefining another layer.
TEST_P(TextureCubeTestES3,CompatibleLayerAThenIncompatibleLayerB)11149 TEST_P(TextureCubeTestES3, CompatibleLayerAThenIncompatibleLayerB)
11150 {
11151 GLTexture tex;
11152 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11153
11154 std::vector<uint32_t> data(32 * 32 * 4, 0xC00FFC00);
11155
11156 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11157 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11158 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11159 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11160 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11161 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11162 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11163 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11164 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11165 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11166 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11167 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11168 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
11169 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11170 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11171 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 32, 32, 0, GL_RGBA,
11172 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11173 EXPECT_GL_NO_ERROR();
11174 }
11175
11176 // Test creating a mutable cubemap, committing it, and then incomaptibly redefining two layers,
11177 // while compatibly redefining another layer.
TEST_P(TextureCubeTestES3,IncompatibleLayerABThenCompatibleLayerC)11178 TEST_P(TextureCubeTestES3, IncompatibleLayerABThenCompatibleLayerC)
11179 {
11180 GLTexture tex;
11181 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11182
11183 std::vector<uint32_t> data(32 * 32 * 4, 0xC00FFC00);
11184
11185 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11186 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11187 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11188 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11189 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11190 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11191 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11192 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11193 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11194 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11195 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11196 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11197 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
11198 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, 32, 32, 0, GL_RGBA,
11199 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11200 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, 32, 32, 0, GL_RGBA,
11201 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11202 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, 16, 16, 0, GL_RGBA,
11203 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11204 EXPECT_GL_NO_ERROR();
11205 }
11206
11207 // Test creating a mutable cubemap, committing it, and then incomaptibly redefining two layers and
11208 // compatibly redefining them again.
TEST_P(TextureCubeTestES3,IncompatibleLayerABThenCompatibleLayerAB)11209 TEST_P(TextureCubeTestES3, IncompatibleLayerABThenCompatibleLayerAB)
11210 {
11211 GLTexture tex;
11212 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11213
11214 constexpr uint32_t kSize = 64;
11215
11216 std::vector<uint32_t> data(kSize * kSize * 4 * 4, 0xC00FFC00);
11217 std::vector<uint32_t> data2(kSize * kSize * 4 * 4, 0xC00003FF);
11218
11219 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11220 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11221 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11222 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11223 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11224 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11225 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11226 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11227 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11228 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11229 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11230 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11231 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
11232 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA,
11233 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11234 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA,
11235 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11236 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11237 GL_UNSIGNED_INT_2_10_10_10_REV, data2.data());
11238 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11239 GL_UNSIGNED_INT_2_10_10_10_REV, data2.data());
11240
11241 glActiveTexture(GL_TEXTURE0);
11242 glBindTexture(GL_TEXTURE_2D, 0);
11243 glActiveTexture(GL_TEXTURE1);
11244 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11245
11246 glUseProgram(mProgram);
11247 glUniform1i(mTexture2DUniformLocation, 0);
11248 glUniform1i(mTextureCubeUniformLocation, 1);
11249
11250 const int w = getWindowWidth();
11251 const int h = getWindowHeight();
11252
11253 for (uint32_t i = 0; i < 6; ++i)
11254 {
11255 glUniform1i(mTextureCubeFaceUniformLocation, i);
11256 glClear(GL_COLOR_BUFFER_BIT);
11257 drawQuad(mProgram, "position", 0.5f);
11258
11259 const bool expectRed = i == 2 || i == 5;
11260 const GLColor expect = expectRed ? GLColor::red : GLColor::green;
11261 EXPECT_PIXEL_RECT_EQ(2, 2, w - 4, h - 4, expect);
11262 EXPECT_GL_NO_ERROR();
11263 }
11264 }
11265
11266 // Similar to IncompatibleLayerABThenCompatibleLayerAB, but with a single-level texture
TEST_P(TextureCubeTestES3,IncompatibleLayerABThenCompatibleLayerABSingleLevel)11267 TEST_P(TextureCubeTestES3, IncompatibleLayerABThenCompatibleLayerABSingleLevel)
11268 {
11269 GLTexture tex;
11270 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11271
11272 constexpr uint32_t kSize = 64;
11273
11274 std::vector<uint32_t> data(kSize * kSize * 4 * 4, 0xC00FFC00);
11275 std::vector<uint32_t> data2(kSize * kSize * 4 * 4, 0xC00003FF);
11276
11277 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11278 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11279 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11280 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11281 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11282 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11283 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11284 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11285 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11286 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11287 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11288 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11289
11290 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11291 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11292
11293 glActiveTexture(GL_TEXTURE0);
11294 glBindTexture(GL_TEXTURE_2D, 0);
11295 glActiveTexture(GL_TEXTURE1);
11296 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
11297
11298 glUseProgram(mProgram);
11299 glUniform1i(mTexture2DUniformLocation, 0);
11300 glUniform1i(mTextureCubeUniformLocation, 1);
11301
11302 const int w = getWindowWidth();
11303 const int h = getWindowHeight();
11304
11305 for (uint32_t i = 0; i < 6; ++i)
11306 {
11307 glUniform1i(mTextureCubeFaceUniformLocation, i);
11308 glClear(GL_COLOR_BUFFER_BIT);
11309 drawQuad(mProgram, "position", 0.5f);
11310
11311 EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green);
11312 EXPECT_GL_NO_ERROR();
11313 }
11314
11315 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA,
11316 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11317 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize * 2, kSize * 2, 0, GL_RGBA,
11318 GL_UNSIGNED_INT_2_10_10_10_REV, data.data());
11319 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11320 GL_UNSIGNED_INT_2_10_10_10_REV, data2.data());
11321 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB10_A2, kSize, kSize, 0, GL_RGBA,
11322 GL_UNSIGNED_INT_2_10_10_10_REV, data2.data());
11323
11324 for (uint32_t i = 0; i < 6; ++i)
11325 {
11326 glUniform1i(mTextureCubeFaceUniformLocation, i);
11327 glClear(GL_COLOR_BUFFER_BIT);
11328 drawQuad(mProgram, "position", 0.5f);
11329
11330 const bool expectRed = i == 2 || i == 5;
11331 const GLColor expect = expectRed ? GLColor::red : GLColor::green;
11332 EXPECT_PIXEL_RECT_EQ(2, 2, w - 4, h - 4, expect);
11333 EXPECT_GL_NO_ERROR();
11334 }
11335 }
11336
11337 // Verify that using negative texture base level and max level generates GL_INVALID_VALUE.
TEST_P(Texture2DTestES3,NegativeTextureBaseLevelAndMaxLevel)11338 TEST_P(Texture2DTestES3, NegativeTextureBaseLevelAndMaxLevel)
11339 {
11340 GLuint texture = create2DTexture();
11341
11342 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, -1);
11343 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11344
11345 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, -1);
11346 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11347
11348 glDeleteTextures(1, &texture);
11349 EXPECT_GL_NO_ERROR();
11350 }
11351
11352 // Test setting base level after calling generateMipmap on a LUMA texture.
11353 // Covers http://anglebug.com/2498
TEST_P(Texture2DTestES3,GenerateMipmapAndBaseLevelLUMA)11354 TEST_P(Texture2DTestES3, GenerateMipmapAndBaseLevelLUMA)
11355 {
11356 glActiveTexture(GL_TEXTURE0);
11357 glBindTexture(GL_TEXTURE_2D, mTexture2D);
11358
11359 constexpr const GLsizei kWidth = 8;
11360 constexpr const GLsizei kHeight = 8;
11361 std::array<GLubyte, kWidth * kHeight * 2> whiteData;
11362 whiteData.fill(255u);
11363
11364 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, kWidth, kHeight, 0, GL_LUMINANCE_ALPHA,
11365 GL_UNSIGNED_BYTE, whiteData.data());
11366 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
11367 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11368 glGenerateMipmap(GL_TEXTURE_2D);
11369 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
11370 EXPECT_GL_NO_ERROR();
11371
11372 drawQuad(mProgram, "position", 0.5f);
11373 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::white);
11374 }
11375
11376 // Incompatible levels with non-mipmap filtering should work.
TEST_P(Texture2DTestES3,IncompatibleMipsButNoMipmapFiltering)11377 TEST_P(Texture2DTestES3, IncompatibleMipsButNoMipmapFiltering)
11378 {
11379 // http://anglebug.com/4782
11380 ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && (IsAMD() || IsIntel()));
11381
11382 // http://anglebug.com/4786
11383 ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsNVIDIAShield());
11384
11385 glActiveTexture(GL_TEXTURE0);
11386 glBindTexture(GL_TEXTURE_2D, mTexture2D);
11387
11388 constexpr const GLsizei kSize = 8;
11389 const std::vector<GLColor> kLevel0Data(kSize * kSize, GLColor::blue);
11390 const std::vector<GLColor> kLevel1Data(kSize * kSize, GLColor::red);
11391
11392 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11393 kLevel0Data.data());
11394 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11395 kLevel1Data.data());
11396 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
11397 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11398 EXPECT_GL_NO_ERROR();
11399
11400 // Draw with base level 0. The GL_LINEAR filtering ensures the texture's image is not created
11401 // with mipmap.
11402 drawQuad(mProgram, "position", 0.5f);
11403 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
11404
11405 // Verify draw with level 1.
11406 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
11407 drawQuad(mProgram, "position", 0.5f);
11408 EXPECT_GL_NO_ERROR();
11409 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel1Data[0]);
11410
11411 // Verify draw with level 0 again
11412 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
11413 drawQuad(mProgram, "position", 0.5f);
11414 EXPECT_GL_NO_ERROR();
11415 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
11416 }
11417
11418 // A collection of negative tests for QCOM foveated rendering extensions
TEST_P(Texture2DTestES3Foveation,NegativeTests)11419 TEST_P(Texture2DTestES3Foveation, NegativeTests)
11420 {
11421 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated") ||
11422 !IsGLExtensionEnabled("GL_QCOM_texture_foveated"));
11423
11424 // Switch to foveated framebuffer
11425 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11426
11427 // QCOM framebuffer foveated tests
11428 GLuint providedFeatures = 0;
11429
11430 // Test invalid numLayers
11431 glFramebufferFoveationConfigQCOM(mFramebuffer, std::numeric_limits<uint32_t>::max(), 1,
11432 GL_FOVEATION_ENABLE_BIT_QCOM, &providedFeatures);
11433 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11434
11435 // Test invalid focal points
11436 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, std::numeric_limits<uint32_t>::max(),
11437 GL_FOVEATION_ENABLE_BIT_QCOM, &providedFeatures);
11438 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11439
11440 // Test setting foveation parameters on a framebuffer that is not configured
11441 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11442 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
11443
11444 // Configure framebuffer correctly
11445 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11446 &providedFeatures);
11447 EXPECT_GL_NO_ERROR();
11448 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11449
11450 // Try to configure it again
11451 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11452 &providedFeatures);
11453 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11454
11455 // Set foveation parameters
11456 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11457 EXPECT_GL_NO_ERROR();
11458
11459 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
11460
11461 GLTexture texture;
11462 glActiveTexture(GL_TEXTURE0);
11463 glBindTexture(GL_TEXTURE_2D, texture);
11464 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
11465 GL_UNSIGNED_BYTE, nullptr);
11466 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11467 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11468 EXPECT_GL_NO_ERROR();
11469
11470 // Change attachments and try to perform a clear and draw
11471 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
11472 ASSERT_GL_NO_ERROR();
11473
11474 glUseProgram(mProgram);
11475
11476 // Clear
11477 glClearColor(0.5f, 0.8f, 1.0f, 0.2f);
11478 glClear(GL_COLOR_BUFFER_BIT);
11479 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
11480
11481 // Draw
11482 drawQuad(mProgram, "position", 0.5f);
11483 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
11484
11485 // QCOM texture foveated tests
11486 glBindTexture(GL_TEXTURE_2D, texture);
11487 // Test invalid feature bit
11488 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
11489 GL_FOVEATION_SCALED_BIN_METHOD_BIT_QCOM);
11490 EXPECT_GL_ERROR(GL_INVALID_ENUM);
11491
11492 // Test setting foveation parameters on a framebuffer that is not configured
11493 glTextureFoveationParametersQCOM(texture, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11494 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
11495
11496 // Configure texture
11497 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
11498 GL_FOVEATION_ENABLE_BIT_QCOM);
11499 EXPECT_GL_NO_ERROR();
11500
11501 // Test invalid focal points
11502 GLint supportedNumFocalPoints = 0;
11503 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_NUM_FOCAL_POINTS_QUERY_QCOM,
11504 &supportedNumFocalPoints);
11505 EXPECT_GL_NO_ERROR();
11506
11507 glTextureFoveationParametersQCOM(texture, 0, supportedNumFocalPoints + 1, 0.0f, 0.0f, 8.0f,
11508 8.0f, 0.0f);
11509 EXPECT_GL_ERROR(GL_INVALID_VALUE);
11510
11511 // Attach foveated texture while framebuffer is also fovated and check framebuffer completeness
11512 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
11513 ASSERT_GL_NO_ERROR();
11514 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_FOVEATION_QCOM,
11515 glCheckFramebufferStatus(GL_FRAMEBUFFER));
11516
11517 // Attach multiple foveated textures to an un-foveated framebuffer and check completeness
11518 GLFramebuffer fbo;
11519 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
11520 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
11521 ASSERT_GL_NO_ERROR();
11522 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
11523
11524 glBindTexture(GL_TEXTURE_2D, mFramebufferColorTexture);
11525 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
11526 GL_UNSIGNED_BYTE, nullptr);
11527 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11528 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11529 EXPECT_GL_NO_ERROR();
11530 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
11531 GL_FOVEATION_ENABLE_BIT_QCOM);
11532 EXPECT_GL_NO_ERROR();
11533
11534 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
11535 mFramebufferColorTexture, 0);
11536 ASSERT_GL_NO_ERROR();
11537 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_FOVEATION_QCOM,
11538 glCheckFramebufferStatus(GL_FRAMEBUFFER));
11539 }
11540
11541 // QCOM framebuffer foveated rendering + clear
TEST_P(Texture2DTestES3Foveation,Clear)11542 TEST_P(Texture2DTestES3Foveation, Clear)
11543 {
11544 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11545
11546 // Switch to foveated framebuffer
11547 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11548
11549 // Just need 1 focal point
11550 GLuint providedFeatures = 0;
11551 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11552 &providedFeatures);
11553 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11554 // Set foveation parameters
11555 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11556 EXPECT_GL_NO_ERROR();
11557
11558 // Clear
11559 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11560 glClear(GL_COLOR_BUFFER_BIT);
11561 EXPECT_GL_NO_ERROR();
11562
11563 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
11564 }
11565
11566 // QCOM framebuffer foveated rendering + clear then draw
TEST_P(Texture2DTestES3Foveation,ClearThenDraw)11567 TEST_P(Texture2DTestES3Foveation, ClearThenDraw)
11568 {
11569 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11570
11571 // Switch to foveated framebuffer
11572 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11573
11574 // Just need 1 focal point
11575 GLuint providedFeatures = 0;
11576 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11577 &providedFeatures);
11578 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11579 // Set foveation parameters
11580 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11581 EXPECT_GL_NO_ERROR();
11582
11583 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11584 glUseProgram(program);
11585
11586 // Clear
11587 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11588 glClear(GL_COLOR_BUFFER_BIT);
11589 EXPECT_GL_NO_ERROR();
11590
11591 // Draw
11592 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11593 EXPECT_GL_NO_ERROR();
11594
11595 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
11596 }
11597
11598 // QCOM framebuffer foveated rendering with rendebuffer attachment + clear then draw
TEST_P(Texture2DTestES3Foveation,RenderbufferAttachmentClearThenDraw)11599 TEST_P(Texture2DTestES3Foveation, RenderbufferAttachmentClearThenDraw)
11600 {
11601 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11602
11603 // Switch to foveated framebuffer and attach a renderbuffer
11604 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11605 GLRenderbuffer renderbuffer;
11606 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
11607 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, getWindowWidth(), getWindowHeight());
11608 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
11609 EXPECT_GL_NO_ERROR();
11610
11611 // Just need 1 focal point
11612 GLuint providedFeatures = 0;
11613 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11614 &providedFeatures);
11615 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11616 // Set foveation parameters
11617 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11618 EXPECT_GL_NO_ERROR();
11619
11620 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11621 glUseProgram(program);
11622
11623 // Clear
11624 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11625 glClear(GL_COLOR_BUFFER_BIT);
11626 EXPECT_GL_NO_ERROR();
11627
11628 // Draw
11629 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11630 EXPECT_GL_NO_ERROR();
11631
11632 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
11633 }
11634
11635 // QCOM framebuffer foveated rendering + draw, clear then draw
TEST_P(Texture2DTestES3Foveation,DrawClearDraw)11636 TEST_P(Texture2DTestES3Foveation, DrawClearDraw)
11637 {
11638 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11639
11640 // Switch to foveated framebuffer
11641 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11642
11643 // Just need 1 focal point
11644 GLuint providedFeatures = 0;
11645 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11646 &providedFeatures);
11647 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11648 // Set foveation parameters
11649 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11650 EXPECT_GL_NO_ERROR();
11651
11652 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11653 glUseProgram(greenProgram);
11654
11655 // Draw
11656 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
11657 EXPECT_GL_NO_ERROR();
11658
11659 // Clear
11660 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
11661 glClear(GL_COLOR_BUFFER_BIT);
11662 EXPECT_GL_NO_ERROR();
11663
11664 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
11665 glUseProgram(blueProgram);
11666
11667 // Draw
11668 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
11669 EXPECT_GL_NO_ERROR();
11670
11671 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
11672 }
11673
11674 // QCOM framebuffer foveated rendering - draw before and after enabling foveation
TEST_P(Texture2DTestES3Foveation,DrawThenEnableFoveationAndDraw)11675 TEST_P(Texture2DTestES3Foveation, DrawThenEnableFoveationAndDraw)
11676 {
11677 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11678
11679 // Switch to foveated framebuffer
11680 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11681
11682 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
11683
11684 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11685 glUseProgram(program);
11686
11687 // Clear
11688 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11689 glClear(GL_COLOR_BUFFER_BIT);
11690 EXPECT_GL_NO_ERROR();
11691
11692 // Draw
11693 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11694 EXPECT_GL_NO_ERROR();
11695
11696 // Configure foveated rendering for framebuffer
11697 // Just need 1 focal point
11698 GLuint providedFeatures = 0;
11699 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11700 &providedFeatures);
11701 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11702 // Set foveation parameters
11703 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11704 EXPECT_GL_NO_ERROR();
11705
11706 // Draw
11707 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11708 EXPECT_GL_NO_ERROR();
11709
11710 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
11711 }
11712
11713 // QCOM framebuffer foveated rendering + draw, change foveation parameters and then draw
TEST_P(Texture2DTestES3Foveation,DrawChangeFoveationParametersThenDraw)11714 TEST_P(Texture2DTestES3Foveation, DrawChangeFoveationParametersThenDraw)
11715 {
11716 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11717
11718 // Switch to foveated framebuffer
11719 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11720
11721 // Just need 1 focal point
11722 GLuint providedFeatures = 0;
11723 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11724 &providedFeatures);
11725 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11726 // Set foveation parameters
11727 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11728 EXPECT_GL_NO_ERROR();
11729
11730 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11731 glUseProgram(greenProgram);
11732
11733 // Draw
11734 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
11735 EXPECT_GL_NO_ERROR();
11736
11737 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
11738
11739 // Change foveation parameters
11740 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.5f, 0.5f, 3.0f, 3.0f, 3.0f);
11741 EXPECT_GL_NO_ERROR();
11742
11743 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
11744 glUseProgram(blueProgram);
11745
11746 // Draw
11747 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
11748 EXPECT_GL_NO_ERROR();
11749
11750 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
11751 }
11752
11753 // QCOM framebuffer foveated rendering + draw and use as blit source
TEST_P(Texture2DTestES3Foveation,DrawThenUseAsBlitSource)11754 TEST_P(Texture2DTestES3Foveation, DrawThenUseAsBlitSource)
11755 {
11756 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11757
11758 // Switch to foveated framebuffer
11759 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11760
11761 glActiveTexture(GL_TEXTURE0);
11762 glBindTexture(GL_TEXTURE_2D, mTexture2D);
11763
11764 const GLsizei kSizeW = getWindowWidth();
11765 const GLsizei kSizeH = getWindowHeight();
11766 std::vector<GLColor> data(kSizeW * kSizeH, GLColor::blue);
11767 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSizeW, kSizeH, 0, GL_RGBA, GL_UNSIGNED_BYTE,
11768 data.data());
11769 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11770 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11771 EXPECT_GL_NO_ERROR();
11772
11773 // Just need 1 focal point
11774 GLuint providedFeatures = 0;
11775 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11776 &providedFeatures);
11777 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11778 // Set foveation parameters
11779 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11780 EXPECT_GL_NO_ERROR();
11781
11782 glUseProgram(mProgram);
11783
11784 // Verify
11785 drawQuad(mProgram, "position", 0.5f);
11786 EXPECT_GL_NO_ERROR();
11787
11788 // Blit data from foveated framebuffer into default framebuffer
11789 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
11790 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
11791 glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
11792 getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
11793
11794 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
11795 }
11796
11797 // QCOM framebuffer foveated rendering + draw and use as blit target
TEST_P(Texture2DTestES3Foveation,DrawThenUseAsBlitTarget)11798 TEST_P(Texture2DTestES3Foveation, DrawThenUseAsBlitTarget)
11799 {
11800 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11801
11802 // Switch to foveated framebuffer
11803 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11804
11805 // Just need 1 focal point
11806 GLuint providedFeatures = 0;
11807 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11808 &providedFeatures);
11809 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11810 // Set foveation parameters
11811 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11812 EXPECT_GL_NO_ERROR();
11813
11814 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11815 glUseProgram(greenProgram);
11816
11817 // Draw
11818 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
11819 EXPECT_GL_NO_ERROR();
11820 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
11821
11822 // Switch to default framebuffer and clear to blue
11823 glBindFramebuffer(GL_FRAMEBUFFER, 0);
11824 EXPECT_GL_NO_ERROR();
11825 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11826 glClear(GL_COLOR_BUFFER_BIT);
11827 EXPECT_GL_NO_ERROR();
11828
11829 // Blit data from default framebuffer into foveated framebuffer
11830 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
11831 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
11832 glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
11833 getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
11834
11835 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
11836 }
11837
11838 // QCOM framebuffer foveated rendering, reuse texture between 2 foveated framebuffers
TEST_P(Texture2DTestES3Foveation,ReuseTextureForFoveatedDraw)11839 TEST_P(Texture2DTestES3Foveation, ReuseTextureForFoveatedDraw)
11840 {
11841 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11842
11843 // Switch to foveated framebuffer
11844 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
11845
11846 // Just need 1 focal point
11847 GLuint providedFeatures = 0;
11848 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11849 &providedFeatures);
11850 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11851 // Set foveation parameters
11852 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11853 EXPECT_GL_NO_ERROR();
11854
11855 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11856 glUseProgram(greenProgram);
11857
11858 // Draw
11859 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
11860 EXPECT_GL_NO_ERROR();
11861
11862 // Create another framebuffer
11863 GLFramebuffer framebuffer;
11864 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
11865
11866 // Resuse texture from mFramebuffer
11867 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
11868 mFramebufferColorTexture, 0);
11869
11870 // Configure foveation parameters of the new framebuffer
11871 // Just need 1 focal point
11872 providedFeatures = 0;
11873 glFramebufferFoveationConfigQCOM(framebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11874 &providedFeatures);
11875 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11876 // Set foveation parameters
11877 glFramebufferFoveationParametersQCOM(framebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11878 EXPECT_GL_NO_ERROR();
11879
11880 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
11881 glUseProgram(blueProgram);
11882
11883 // Draw
11884 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
11885 EXPECT_GL_NO_ERROR();
11886
11887 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
11888 }
11889
11890 // QCOM framebuffer foveated rendering with MSAA framebuffer
TEST_P(Texture2DTestES3Foveation,DrawWithMsaaFramebuffer)11891 TEST_P(Texture2DTestES3Foveation, DrawWithMsaaFramebuffer)
11892 {
11893 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_framebuffer_foveated"));
11894 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
11895
11896 // Create a new MSAA framebuffer
11897 GLFramebuffer msaaFramebuffer;
11898 glBindFramebuffer(GL_FRAMEBUFFER, msaaFramebuffer);
11899 GLTexture texture;
11900 glActiveTexture(GL_TEXTURE0);
11901 glBindTexture(GL_TEXTURE_2D, texture);
11902 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
11903 GL_UNSIGNED_BYTE, nullptr);
11904 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
11905 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
11906 EXPECT_GL_NO_ERROR();
11907
11908 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
11909 texture, 0, 4);
11910 ASSERT_GL_NO_ERROR();
11911 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
11912
11913 // Just need 1 focal point
11914 GLuint providedFeatures = 0;
11915 glFramebufferFoveationConfigQCOM(mFramebuffer, 1, 1, GL_FOVEATION_ENABLE_BIT_QCOM,
11916 &providedFeatures);
11917 ASSERT_NE(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM, 0u);
11918 // Set foveation parameters
11919 glFramebufferFoveationParametersQCOM(mFramebuffer, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11920 EXPECT_GL_NO_ERROR();
11921
11922 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11923 glUseProgram(program);
11924
11925 // Clear
11926 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11927 glClear(GL_COLOR_BUFFER_BIT);
11928 EXPECT_GL_NO_ERROR();
11929
11930 // Draw
11931 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
11932 EXPECT_GL_NO_ERROR();
11933
11934 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
11935 }
11936
11937 // QCOM texture foveated rendering, basic draw
TEST_P(Texture2DTestES3Foveation,FoveatedTextureDraw)11938 TEST_P(Texture2DTestES3Foveation, FoveatedTextureDraw)
11939 {
11940 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_texture_foveated"));
11941
11942 // Create non-foveated framebuffer
11943 GLFramebuffer framebuffer;
11944 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
11945 glActiveTexture(GL_TEXTURE0);
11946 glBindTexture(GL_TEXTURE_2D, mFramebufferColorTexture);
11947 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
11948 mFramebufferColorTexture, 0);
11949 ASSERT_GL_NO_ERROR();
11950 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
11951
11952 // Render before configuring foveation on the texture
11953 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
11954 glUseProgram(greenProgram);
11955
11956 // Clear
11957 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
11958 glClear(GL_COLOR_BUFFER_BIT);
11959 EXPECT_GL_NO_ERROR();
11960
11961 // Draw
11962 drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
11963 EXPECT_GL_NO_ERROR();
11964
11965 // Configure foveation for the texture
11966 GLint supportedFoveationFeatures = 0;
11967 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_QUERY_QCOM,
11968 &supportedFoveationFeatures);
11969 ASSERT_EQ(supportedFoveationFeatures & GL_FOVEATION_ENABLE_BIT_QCOM,
11970 GL_FOVEATION_ENABLE_BIT_QCOM);
11971 GLint supportedNumFocalPoints = 0;
11972 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_NUM_FOCAL_POINTS_QUERY_QCOM,
11973 &supportedNumFocalPoints);
11974 ASSERT_GE(supportedNumFocalPoints, 1);
11975 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
11976 GL_FOVEATION_ENABLE_BIT_QCOM);
11977 EXPECT_GL_NO_ERROR();
11978
11979 // Set foveation parameters
11980 glTextureFoveationParametersQCOM(mFramebufferColorTexture, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
11981 EXPECT_GL_NO_ERROR();
11982
11983 // Render and verify after configuring foveation on the texture
11984 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
11985 glUseProgram(blueProgram);
11986
11987 // Clear
11988 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
11989 glClear(GL_COLOR_BUFFER_BIT);
11990 EXPECT_GL_NO_ERROR();
11991
11992 // Draw
11993 drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
11994 EXPECT_GL_NO_ERROR();
11995
11996 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::blue);
11997 }
11998
11999 // QCOM texture foveated rendering to MSAA texture followed by a blit
TEST_P(Texture2DTestES31Foveation,MsaaTextureDrawThenUseAsBlitSource)12000 TEST_P(Texture2DTestES31Foveation, MsaaTextureDrawThenUseAsBlitSource)
12001 {
12002 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_texture_foveated"));
12003
12004 // Create a non-foveated framebuffer
12005 GLFramebuffer framebuffer;
12006 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
12007
12008 // Create an msaa texture and bind to framebuffer
12009 GLTexture textureMS;
12010 glActiveTexture(GL_TEXTURE0);
12011 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureMS);
12012 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, getWindowWidth(),
12013 getWindowHeight(), GL_TRUE);
12014 EXPECT_GL_NO_ERROR();
12015
12016 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
12017 textureMS, 0);
12018 ASSERT_GL_NO_ERROR();
12019 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
12020
12021 // Just need 1 focal point
12022 glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM,
12023 GL_FOVEATION_ENABLE_BIT_QCOM);
12024 EXPECT_GL_NO_ERROR();
12025
12026 // Set foveation parameters
12027 glTextureFoveationParametersQCOM(textureMS, 0, 0, 0.0f, 0.0f, 8.0f, 8.0f, 0.0f);
12028 EXPECT_GL_NO_ERROR();
12029
12030 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
12031 glUseProgram(program);
12032
12033 // Clear
12034 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
12035 glClear(GL_COLOR_BUFFER_BIT);
12036 EXPECT_GL_NO_ERROR();
12037
12038 // Draw
12039 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
12040 EXPECT_GL_NO_ERROR();
12041
12042 // Blit data from framebuffer with foveated texture into default framebuffer
12043 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
12044 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
12045 glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
12046 getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
12047
12048 glBindFramebuffer(GL_FRAMEBUFFER, 0);
12049 EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::green);
12050 }
12051
12052 // Enabling mipmap filtering after previously having used the texture without it should work.
TEST_P(Texture2DTestES3,NoMipmapDrawThenMipmapDraw)12053 TEST_P(Texture2DTestES3, NoMipmapDrawThenMipmapDraw)
12054 {
12055 glActiveTexture(GL_TEXTURE0);
12056 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12057
12058 constexpr const GLsizei kSize = 8;
12059 const std::vector<GLColor> kLevel0Data(kSize * kSize, GLColor::blue);
12060 const std::vector<GLColor> kLevelOtherData(kSize * kSize, GLColor::red);
12061
12062 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12063 kLevel0Data.data());
12064 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12065 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12066 EXPECT_GL_NO_ERROR();
12067
12068 // Draw so the texture's image is allocated.
12069 drawQuad(mProgram, "position", 0.5f);
12070 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
12071
12072 // Specify the rest of the image
12073 for (GLint mip = 1; (kSize >> mip) >= 1; ++mip)
12074 {
12075 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
12076 GL_UNSIGNED_BYTE, kLevelOtherData.data());
12077 }
12078 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
12079
12080 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
12081 glUseProgram(program);
12082 GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
12083 GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform());
12084 ASSERT_NE(-1, textureLoc);
12085 ASSERT_NE(-1, lodLoc);
12086 glUniform1i(textureLoc, 0);
12087
12088 // Verify the mips
12089 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12090 {
12091 glUniform1f(lodLoc, mip);
12092 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12093 EXPECT_GL_NO_ERROR();
12094 EXPECT_PIXEL_COLOR_EQ(0, 0, (mip == 0 ? kLevel0Data[0] : kLevelOtherData[0]));
12095 }
12096 }
12097
12098 // Disabling mipmap filtering after previously having used the texture with it should work.
TEST_P(Texture2DTestES3,MipmapDrawThenNoMipmapDraw)12099 TEST_P(Texture2DTestES3, MipmapDrawThenNoMipmapDraw)
12100 {
12101 glActiveTexture(GL_TEXTURE0);
12102 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12103
12104 constexpr const GLsizei kSize = 8;
12105 const std::vector<GLColor> kLevel0Data(kSize * kSize, GLColor::blue);
12106 const std::vector<GLColor> kLevelOtherData(kSize * kSize, GLColor::red);
12107
12108 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12109 kLevel0Data.data());
12110 for (GLint mip = 1; (kSize >> mip) >= 1; ++mip)
12111 {
12112 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
12113 GL_UNSIGNED_BYTE, kLevelOtherData.data());
12114 }
12115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
12116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12117 EXPECT_GL_NO_ERROR();
12118
12119 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
12120 glUseProgram(program);
12121 GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
12122 GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform());
12123 ASSERT_NE(-1, textureLoc);
12124 ASSERT_NE(-1, lodLoc);
12125 glUniform1i(textureLoc, 0);
12126
12127 // Verify the mips.
12128 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12129 {
12130 glUniform1f(lodLoc, mip);
12131 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12132 EXPECT_GL_NO_ERROR();
12133 EXPECT_PIXEL_COLOR_EQ(0, 0, (mip == 0 ? kLevel0Data[0] : kLevelOtherData[0]));
12134 }
12135
12136 // Disable mipmapping and verify mips again.
12137 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12138
12139 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12140 {
12141 glUniform1f(lodLoc, mip);
12142 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12143 EXPECT_GL_NO_ERROR();
12144 EXPECT_PIXEL_COLOR_EQ(0, 0, kLevel0Data[0]);
12145 }
12146 }
12147
12148 // Respecify texture with more mips.
TEST_P(Texture2DTestES3,RespecifyWithMoreMips)12149 TEST_P(Texture2DTestES3, RespecifyWithMoreMips)
12150 {
12151 glActiveTexture(GL_TEXTURE0);
12152 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12153
12154 constexpr const GLsizei kSize = 8;
12155 const std::vector<GLColor> kLevelEvenData(kSize * kSize, GLColor::blue);
12156 const std::vector<GLColor> kLevelOddData(kSize * kSize * 4, GLColor::red);
12157
12158 auto getLevelData = [&](GLint mip) {
12159 return mip % 2 == 0 ? kLevelEvenData.data() : kLevelOddData.data();
12160 };
12161
12162 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12163 {
12164 glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
12165 GL_UNSIGNED_BYTE, getLevelData(mip));
12166 }
12167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
12168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12169 EXPECT_GL_NO_ERROR();
12170
12171 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
12172 glUseProgram(program);
12173 GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
12174 GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform());
12175 ASSERT_NE(-1, textureLoc);
12176 ASSERT_NE(-1, lodLoc);
12177 glUniform1i(textureLoc, 0);
12178
12179 // Verify the mips.
12180 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12181 {
12182 glUniform1f(lodLoc, mip);
12183 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12184 EXPECT_GL_NO_ERROR();
12185 EXPECT_PIXEL_COLOR_EQ(0, 0, getLevelData(mip)[0]);
12186 }
12187
12188 // Respecify the texture with more mips, without changing any parameters.
12189 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize * 2, kSize * 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12190 kLevelOddData.data());
12191 for (GLint mip = 0; (kSize >> mip) >= 1; ++mip)
12192 {
12193 glTexImage2D(GL_TEXTURE_2D, mip + 1, GL_RGBA, kSize >> mip, kSize >> mip, 0, GL_RGBA,
12194 GL_UNSIGNED_BYTE, getLevelData(mip));
12195 }
12196
12197 // Verify the mips.
12198 for (GLint mip = 0; ((kSize * 2) >> mip) >= 1; ++mip)
12199 {
12200 glUniform1f(lodLoc, mip);
12201 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
12202 EXPECT_GL_NO_ERROR();
12203 EXPECT_PIXEL_COLOR_EQ(0, 0, getLevelData(mip - 1)[0]);
12204 }
12205 }
12206
12207 // Covers a bug in the D3D11 backend: http://anglebug.com/2772
12208 // When using a sampler the texture was created as if it has mipmaps,
12209 // regardless what you specified in GL_TEXTURE_MIN_FILTER via
12210 // glSamplerParameteri() -- mistakenly the default value
12211 // GL_NEAREST_MIPMAP_LINEAR or the value set via glTexParameteri() was
12212 // evaluated.
12213 // If you didn't provide mipmaps and didn't let the driver generate them
12214 // this led to not sampling your texture data when minification occurred.
TEST_P(Texture2DTestES3,MinificationWithSamplerNoMipmapping)12215 TEST_P(Texture2DTestES3, MinificationWithSamplerNoMipmapping)
12216 {
12217 constexpr char kVS[] =
12218 "#version 300 es\n"
12219 "out vec2 texcoord;\n"
12220 "in vec4 position;\n"
12221 "void main()\n"
12222 "{\n"
12223 " gl_Position = vec4(position.xy * 0.1, 0.0, 1.0);\n"
12224 " texcoord = (position.xy * 0.5) + 0.5;\n"
12225 "}\n";
12226
12227 constexpr char kFS[] =
12228 "#version 300 es\n"
12229 "precision highp float;\n"
12230 "uniform highp sampler2D tex;\n"
12231 "in vec2 texcoord;\n"
12232 "out vec4 fragColor;\n"
12233 "void main()\n"
12234 "{\n"
12235 " fragColor = texture(tex, texcoord);\n"
12236 "}\n";
12237
12238 ANGLE_GL_PROGRAM(program, kVS, kFS);
12239
12240 GLSampler sampler;
12241 glBindSampler(0, sampler);
12242 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
12243 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
12244
12245 glActiveTexture(GL_TEXTURE0);
12246 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12247
12248 const GLsizei texWidth = getWindowWidth();
12249 const GLsizei texHeight = getWindowHeight();
12250 const std::vector<GLColor> whiteData(texWidth * texHeight, GLColor::white);
12251
12252 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12253 whiteData.data());
12254 EXPECT_GL_NO_ERROR();
12255
12256 drawQuad(program, "position", 0.5f);
12257 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, angle::GLColor::white);
12258 }
12259
testUploadThenUseInDifferentStages(const std::vector<UploadThenUseStageParam> & uses)12260 void Texture2DTest::testUploadThenUseInDifferentStages(
12261 const std::vector<UploadThenUseStageParam> &uses)
12262 {
12263 constexpr char kVSSampleVS[] = R"(attribute vec4 a_position;
12264 uniform sampler2D u_tex2D;
12265 varying vec4 v_color;
12266
12267 void main()
12268 {
12269 gl_Position = vec4(a_position.xy, 0.0, 1.0);
12270 v_color = texture2D(u_tex2D, a_position.xy * 0.5 + vec2(0.5));
12271 })";
12272
12273 constexpr char kVSSampleFS[] = R"(precision mediump float;
12274 varying vec4 v_color;
12275
12276 void main()
12277 {
12278 gl_FragColor = v_color;
12279 })";
12280
12281 ANGLE_GL_PROGRAM(sampleInVS, kVSSampleVS, kVSSampleFS);
12282 ANGLE_GL_PROGRAM(sampleInFS, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
12283
12284 GLFramebuffer fbo[2];
12285 GLTexture color[2];
12286 for (uint32_t i = 0; i < 2; ++i)
12287 {
12288 glBindFramebuffer(GL_FRAMEBUFFER, fbo[i]);
12289 glBindTexture(GL_TEXTURE_2D, color[i]);
12290 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
12291 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color[i], 0);
12292 }
12293
12294 const GLColor kImageColor(63, 31, 0, 255);
12295
12296 GLTexture tex;
12297 glBindTexture(GL_TEXTURE_2D, tex);
12298 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kImageColor);
12299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12301 glActiveTexture(GL_TEXTURE0);
12302 ASSERT_GL_NO_ERROR();
12303
12304 glEnable(GL_BLEND);
12305 glBlendFunc(GL_ONE, GL_ONE);
12306
12307 glClearColor(0, 0, 0, 1);
12308
12309 glBindFramebuffer(GL_FRAMEBUFFER, fbo[1]);
12310 glClear(GL_COLOR_BUFFER_BIT);
12311 glBindFramebuffer(GL_FRAMEBUFFER, fbo[0]);
12312 glClear(GL_COLOR_BUFFER_BIT);
12313
12314 uint32_t curFboIndex = 0;
12315 uint32_t fboDrawCount[2] = {};
12316
12317 for (const UploadThenUseStageParam &use : uses)
12318 {
12319 const GLProgram &program = use.useStage == GL_VERTEX_SHADER ? sampleInVS : sampleInFS;
12320 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
12321 ASSERT_GL_NO_ERROR();
12322
12323 ++fboDrawCount[curFboIndex];
12324
12325 if (use.closeRenderPassAfterUse)
12326 {
12327 // Close the render pass without accidentally incurring additional barriers.
12328 curFboIndex = 1 - curFboIndex;
12329 glBindFramebuffer(GL_FRAMEBUFFER, fbo[curFboIndex]);
12330 }
12331 }
12332
12333 // Make sure the transfer operations below aren't reordered with the rendering above and thus
12334 // introduce additional synchronization.
12335 glFinish();
12336
12337 for (uint32_t i = 0; i < 2; ++i)
12338 {
12339 const GLColor kExpectedColor(63 * std::min(4u, fboDrawCount[i]),
12340 31 * std::min(8u, fboDrawCount[i]), 0, 255);
12341
12342 glBindFramebuffer(GL_FRAMEBUFFER, fbo[i]);
12343 EXPECT_PIXEL_COLOR_EQ(0, 0, kExpectedColor);
12344 }
12345 }
12346
12347 // Test synchronization when a texture is used in different shader stages after data upload.
12348 //
12349 // - Use in VS
12350 // - Use in FS
TEST_P(Texture2DTest,UploadThenVSThenFS)12351 TEST_P(Texture2DTest, UploadThenVSThenFS)
12352 {
12353 testUploadThenUseInDifferentStages({
12354 {GL_VERTEX_SHADER, false},
12355 {GL_FRAGMENT_SHADER, false},
12356 });
12357 }
12358
12359 // Test synchronization when a texture is used in different shader stages after data upload.
12360 //
12361 // - Use in VS
12362 // - Break render pass
12363 // - Use in FS
TEST_P(Texture2DTest,UploadThenVSThenNewRPThenFS)12364 TEST_P(Texture2DTest, UploadThenVSThenNewRPThenFS)
12365 {
12366 testUploadThenUseInDifferentStages({
12367 {GL_VERTEX_SHADER, true},
12368 {GL_FRAGMENT_SHADER, false},
12369 });
12370 }
12371
12372 // Test synchronization when a texture is used in different shader stages after data upload.
12373 //
12374 // - Use in FS
12375 // - Use in VS
TEST_P(Texture2DTest,UploadThenFSThenVS)12376 TEST_P(Texture2DTest, UploadThenFSThenVS)
12377 {
12378 testUploadThenUseInDifferentStages({
12379 {GL_FRAGMENT_SHADER, false},
12380 {GL_VERTEX_SHADER, false},
12381 });
12382 }
12383
12384 // Test synchronization when a texture is used in different shader stages after data upload.
12385 //
12386 // - Use in FS
12387 // - Break render pass
12388 // - Use in VS
TEST_P(Texture2DTest,UploadThenFSThenNewRPThenVS)12389 TEST_P(Texture2DTest, UploadThenFSThenNewRPThenVS)
12390 {
12391 testUploadThenUseInDifferentStages({
12392 {GL_FRAGMENT_SHADER, true},
12393 {GL_VERTEX_SHADER, false},
12394 });
12395 }
12396
12397 // Test synchronization when a texture is used in different shader stages after data upload.
12398 //
12399 // - Use in VS
12400 // - Use in FS
12401 // - Use in VS
TEST_P(Texture2DTest,UploadThenVSThenFSThenVS)12402 TEST_P(Texture2DTest, UploadThenVSThenFSThenVS)
12403 {
12404 testUploadThenUseInDifferentStages({
12405 {GL_VERTEX_SHADER, false},
12406 {GL_FRAGMENT_SHADER, false},
12407 {GL_VERTEX_SHADER, false},
12408 });
12409 }
12410
12411 // Test synchronization when a texture is used in different shader stages after data upload.
12412 //
12413 // - Use in VS
12414 // - Break render pass
12415 // - Use in FS
12416 // - Use in VS
TEST_P(Texture2DTest,UploadThenVSThenNewRPThenFSThenVS)12417 TEST_P(Texture2DTest, UploadThenVSThenNewRPThenFSThenVS)
12418 {
12419 testUploadThenUseInDifferentStages({
12420 {GL_VERTEX_SHADER, true},
12421 {GL_FRAGMENT_SHADER, false},
12422 {GL_VERTEX_SHADER, false},
12423 });
12424 }
12425
12426 // Test synchronization when a texture is used in different shader stages after data upload.
12427 //
12428 // - Use in VS
12429 // - Break render pass
12430 // - Use in FS
12431 // - Break render pass
12432 // - Use in VS
TEST_P(Texture2DTest,UploadThenVSThenNewRPThenFSThenNewRPThenVS)12433 TEST_P(Texture2DTest, UploadThenVSThenNewRPThenFSThenNewRPThenVS)
12434 {
12435 testUploadThenUseInDifferentStages({
12436 {GL_VERTEX_SHADER, true},
12437 {GL_FRAGMENT_SHADER, true},
12438 {GL_VERTEX_SHADER, false},
12439 });
12440 }
12441
12442 // Test synchronization when a texture is used in different shader stages after data upload.
12443 //
12444 // - Use in FS
12445 // - Use in VS
12446 // - Break render pass
12447 // - Use in FS
TEST_P(Texture2DTest,UploadThenFSThenVSThenNewRPThenFS)12448 TEST_P(Texture2DTest, UploadThenFSThenVSThenNewRPThenFS)
12449 {
12450 testUploadThenUseInDifferentStages({
12451 {GL_FRAGMENT_SHADER, false},
12452 {GL_VERTEX_SHADER, true},
12453 {GL_FRAGMENT_SHADER, false},
12454 });
12455 }
12456
12457 // Test synchronization when a texture is used in different shader stages after data upload.
12458 //
12459 // - Use in FS
12460 // - Break render pass
12461 // - Use in VS
12462 // - Use in FS
TEST_P(Texture2DTest,UploadThenFSThenNewRPThenVSThenFS)12463 TEST_P(Texture2DTest, UploadThenFSThenNewRPThenVSThenFS)
12464 {
12465 testUploadThenUseInDifferentStages({
12466 {GL_FRAGMENT_SHADER, true},
12467 {GL_VERTEX_SHADER, false},
12468 {GL_FRAGMENT_SHADER, false},
12469 });
12470 }
12471
12472 // Test synchronization when a texture is used in different shader stages after data upload.
12473 //
12474 // - Use in FS
12475 // - Break render pass
12476 // - Use in FS
12477 // - Use in VS
TEST_P(Texture2DTest,UploadThenFSThenNewRPThenFSThenVS)12478 TEST_P(Texture2DTest, UploadThenFSThenNewRPThenFSThenVS)
12479 {
12480 testUploadThenUseInDifferentStages({
12481 {GL_FRAGMENT_SHADER, true},
12482 {GL_FRAGMENT_SHADER, false},
12483 {GL_VERTEX_SHADER, false},
12484 });
12485 }
12486
12487 // Test that interleaved updates and draw calls many times work
TEST_P(Texture2DTest,DrawThenUpdateMultipleTimes)12488 TEST_P(Texture2DTest, DrawThenUpdateMultipleTimes)
12489 {
12490 constexpr uint32_t kTexWidth = 16;
12491 constexpr uint32_t kTexHeight = 16;
12492 constexpr uint32_t kBpp = 4;
12493
12494 // Create the texture
12495 glActiveTexture(GL_TEXTURE0);
12496 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12497 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12498 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12499 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12500 nullptr);
12501 EXPECT_GL_ERROR(GL_NO_ERROR);
12502
12503 constexpr GLubyte kInitialColor = 16;
12504 GLubyte expectedFinalColorValue = kInitialColor;
12505 glEnable(GL_BLEND);
12506 glBlendFunc(GL_ONE, GL_ONE);
12507 glClearColor(0, 0, 0, 0);
12508 glClear(GL_COLOR_BUFFER_BIT);
12509
12510 // First draw the screen with initial color
12511 {
12512 ANGLE_GL_PROGRAM(colorProgram, angle::essl1_shaders::vs::Simple(),
12513 angle::essl1_shaders::fs::UniformColor());
12514 glUseProgram(colorProgram);
12515 GLint colorUniformLocation =
12516 glGetUniformLocation(colorProgram, angle::essl1_shaders::ColorUniform());
12517 ASSERT_NE(colorUniformLocation, -1);
12518 glUniform4f(colorUniformLocation, kInitialColor / 256.f, kInitialColor / 256.f,
12519 kInitialColor / 256.f, kInitialColor / 256.f);
12520 drawQuad(colorProgram, angle::essl1_shaders::PositionAttrib(), 0.5f);
12521 }
12522
12523 // Then update the texture then draw it multiple times
12524 constexpr GLubyte kColorsToUpdate[] = {16, 64, 64};
12525 setUpProgram();
12526 glUseProgram(mProgram);
12527 glUniform1i(mTexture2DUniformLocation, 0);
12528
12529 for (auto color : kColorsToUpdate)
12530 {
12531 expectedFinalColorValue += color;
12532 std::vector<GLubyte> fullTextureData(kTexWidth * kTexHeight * kBpp, color);
12533 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, GL_UNSIGNED_BYTE,
12534 fullTextureData.data());
12535
12536 drawQuad(mProgram, "position", 0.5f);
12537 }
12538
12539 // The final color should be sum of all updated colors.
12540 const GLColor expectedFinalColor(expectedFinalColorValue, expectedFinalColorValue,
12541 expectedFinalColorValue, expectedFinalColorValue);
12542 EXPECT_GL_NO_ERROR();
12543 EXPECT_PIXEL_COLOR_EQ(1 * getWindowWidth() / 4, getWindowHeight() / 2, expectedFinalColor);
12544 }
12545
12546 // Test that clears due to emulated formats are to the correct level given non-zero base level.
TEST_P(Texture2DTestES3,NonZeroBaseEmulatedClear)12547 TEST_P(Texture2DTestES3, NonZeroBaseEmulatedClear)
12548 {
12549 // Tests behavior of the Vulkan backend with emulated formats.
12550 ANGLE_SKIP_TEST_IF(!IsVulkan());
12551
12552 // TODO(http://anglebug.com/8036): Skip when using VMA image suballocation on Linux/Intel.
12553 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() &&
12554 getEGLWindow()->isFeatureEnabled(Feature::UseVmaForImageSuballocation));
12555
12556 // This test assumes GL_RGB is always emulated, which overrides the
12557 // Feature::AllocateNonZeroMemory memory feature, clearing the memory to zero. However, if the
12558 // format is *not* emulated and the feature Feature::AllocateNonZeroMemory is enabled, the
12559 // texture memory will contain non-zero memory, which means the color is not black (causing the
12560 // test to fail).
12561 ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllocateNonZeroMemory));
12562
12563 setUpProgram();
12564
12565 glActiveTexture(GL_TEXTURE0);
12566 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12567 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
12568 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
12569 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 4, 4, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
12570 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
12571 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
12572 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4);
12573 EXPECT_GL_NO_ERROR();
12574
12575 drawQuad(mProgram, "position", 0.5f);
12576
12577 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
12578 }
12579
12580 // Test that uploading data to buffer that's in use then using it as PBO to update a texture works.
TEST_P(Texture2DTestES3,UseAsUBOThenUpdateThenAsPBO)12581 TEST_P(Texture2DTestES3, UseAsUBOThenUpdateThenAsPBO)
12582 {
12583 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
12584 GLColor::red};
12585 const std::array<GLColor, 4> kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue,
12586 GLColor::blue};
12587
12588 GLBuffer buffer;
12589 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
12590 glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_COPY);
12591 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
12592 EXPECT_GL_NO_ERROR();
12593
12594 constexpr char kVerifyUBO[] = R"(#version 300 es
12595 precision mediump float;
12596 uniform block {
12597 uvec4 data;
12598 } ubo;
12599 out vec4 colorOut;
12600 void main()
12601 {
12602 if (all(equal(ubo.data, uvec4(0xFF0000FFu))))
12603 colorOut = vec4(0, 1.0, 0, 1.0);
12604 else
12605 colorOut = vec4(1.0, 0, 0, 1.0);
12606 })";
12607
12608 ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
12609 drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
12610 EXPECT_GL_NO_ERROR();
12611
12612 // Update buffer data
12613 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
12614 EXPECT_GL_NO_ERROR();
12615
12616 // Bind as PBO
12617 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
12618 EXPECT_GL_NO_ERROR();
12619
12620 // Upload from PBO to texture
12621 GLTexture tex;
12622 glBindTexture(GL_TEXTURE_2D, tex);
12623 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
12624 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
12625 EXPECT_GL_NO_ERROR();
12626
12627 // Make sure uniform data is correct.
12628 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
12629
12630 // Make sure the texture data is correct.
12631 GLFramebuffer fbo;
12632 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
12633 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
12634 EXPECT_GL_NO_ERROR();
12635 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
12636
12637 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
12638 }
12639
12640 // Test if the RenderTargetCache is updated when the TextureStorage object is freed
TEST_P(Texture2DTestES3,UpdateRenderTargetCacheOnDestroyTexStorage)12641 TEST_P(Texture2DTestES3, UpdateRenderTargetCacheOnDestroyTexStorage)
12642 {
12643 ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
12644 const GLenum attachments[] = {GL_COLOR_ATTACHMENT0};
12645
12646 GLTexture tex;
12647 GLFramebuffer fb;
12648 glBindTexture(GL_TEXTURE_2D, tex);
12649 glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 100, 1);
12650 glBindFramebuffer(GL_FRAMEBUFFER, fb);
12651 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
12652 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments);
12653 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
12654 drawQuad(drawRed, essl3_shaders::PositionAttrib(), 1.0f);
12655 EXPECT_GL_NO_ERROR();
12656
12657 EXPECT_PIXEL_RECT_EQ(0, 0, 100, 1, GLColor::red);
12658 }
12659
12660 // Test that we can allocate at least 4096 images, which is the maximum allocation count on some
12661 // platforms. Image suballocation should enable us to allocate more than this limit.
TEST_P(Texture2DTestES3,AllocateMoreThan4096Textures)12662 TEST_P(Texture2DTestES3, AllocateMoreThan4096Textures)
12663 {
12664 ANGLE_SKIP_TEST_IF(!getEGLWindow()->isFeatureEnabled(Feature::UseVmaForImageSuballocation));
12665
12666 // The test is skipped when AllocateNonZeroMemory is enabled due to risk of timeout.
12667 ANGLE_SKIP_TEST_IF(getEGLWindow()->isFeatureEnabled(Feature::AllocateNonZeroMemory));
12668
12669 constexpr size_t kTextureCount = 8000;
12670 std::vector<GLTexture> textures(kTextureCount);
12671 for (auto &texture : textures)
12672 {
12673 glBindTexture(GL_TEXTURE_2D, texture);
12674 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
12675 }
12676 EXPECT_GL_NO_ERROR();
12677 }
12678
12679 // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
12680 // texture is output.
TEST_P(Texture2DIntegerTestES3,IntegerTextureNonZeroBaseLevel)12681 TEST_P(Texture2DIntegerTestES3, IntegerTextureNonZeroBaseLevel)
12682 {
12683 // http://anglebug.com/3478
12684 ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsDesktopOpenGL());
12685
12686 glActiveTexture(GL_TEXTURE0);
12687 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12688 int width = getWindowWidth();
12689 int height = getWindowHeight();
12690 GLColor color = GLColor::green;
12691 std::vector<GLColor> pixels(width * height, color);
12692 GLint baseLevel = 1;
12693 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, baseLevel);
12694 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12695 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12696 glTexImage2D(GL_TEXTURE_2D, baseLevel, GL_RGBA8UI, width, height, 0, GL_RGBA_INTEGER,
12697 GL_UNSIGNED_BYTE, pixels.data());
12698
12699 setUpProgram();
12700 glUseProgram(mProgram);
12701 glUniform1i(mTexture2DUniformLocation, 0);
12702 drawQuad(mProgram, "position", 0.5f);
12703
12704 EXPECT_GL_NO_ERROR();
12705 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
12706 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
12707 }
12708
12709 // Draw a quad with an integer cube texture with a non-zero base level, and test that the color of
12710 // the texture is output.
TEST_P(TextureCubeIntegerTestES3,IntegerCubeTextureNonZeroBaseLevel)12711 TEST_P(TextureCubeIntegerTestES3, IntegerCubeTextureNonZeroBaseLevel)
12712 {
12713 // All output checks returned black, rather than the texture color.
12714 ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
12715
12716 glActiveTexture(GL_TEXTURE0);
12717
12718 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
12719 GLint baseLevel = 1;
12720 int width = getWindowWidth();
12721 int height = getWindowHeight();
12722 GLColor color = GLColor::green;
12723 std::vector<GLColor> pixels(width * height, color);
12724 for (GLenum faceIndex = 0; faceIndex < 6; faceIndex++)
12725 {
12726 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, baseLevel, GL_RGBA8UI, width,
12727 height, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pixels.data());
12728 EXPECT_GL_NO_ERROR();
12729 }
12730 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, baseLevel);
12731 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12732 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12733
12734 glUseProgram(mProgram);
12735 glUniform1i(mTextureCubeUniformLocation, 0);
12736 drawQuad(mProgram, "position", 0.5f);
12737
12738 EXPECT_GL_NO_ERROR();
12739 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
12740 EXPECT_PIXEL_COLOR_EQ(width - 1, 0, color);
12741 EXPECT_PIXEL_COLOR_EQ(0, height - 1, color);
12742 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
12743 }
12744
12745 // This test sets up a cube map with four distincly colored MIP levels.
12746 // The size of the texture and the geometry is chosen such that levels 1 or 2 should be chosen at
12747 // the corners of the screen.
TEST_P(TextureCubeIntegerEdgeTestES3,IntegerCubeTextureCorner)12748 TEST_P(TextureCubeIntegerEdgeTestES3, IntegerCubeTextureCorner)
12749 {
12750 glActiveTexture(GL_TEXTURE0);
12751
12752 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
12753 int width = getWindowWidth();
12754 int height = getWindowHeight();
12755 ASSERT_EQ(width, height);
12756 GLColor color[4] = {GLColor::white, GLColor::green, GLColor::blue, GLColor::red};
12757 for (GLint level = 0; level < 4; level++)
12758 {
12759 for (GLenum faceIndex = 0; faceIndex < 6; faceIndex++)
12760 {
12761 int levelWidth = (2 * width) >> level;
12762 int levelHeight = (2 * height) >> level;
12763 std::vector<GLColor> pixels(levelWidth * levelHeight, color[level]);
12764 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, GL_RGBA8UI, levelWidth,
12765 levelHeight, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pixels.data());
12766 EXPECT_GL_NO_ERROR();
12767 }
12768 }
12769 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
12770 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12771 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 3);
12772
12773 glUseProgram(mProgram);
12774 glUniform1i(mTextureCubeUniformLocation, 0);
12775 drawQuad(mProgram, "position", 0.5f);
12776
12777 ASSERT_GL_NO_ERROR();
12778 // Check that we do not read from levels 0 or 3. Levels 1 and 2 are both acceptable.
12779 EXPECT_EQ(ReadColor(0, 0).R, 0);
12780 EXPECT_EQ(ReadColor(width - 1, 0).R, 0);
12781 EXPECT_EQ(ReadColor(0, height - 1).R, 0);
12782 EXPECT_EQ(ReadColor(width - 1, height - 1).R, 0);
12783 }
12784
12785 // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
12786 // texture is output.
TEST_P(Texture2DIntegerProjectiveOffsetTestES3,NonZeroBaseLevel)12787 TEST_P(Texture2DIntegerProjectiveOffsetTestES3, NonZeroBaseLevel)
12788 {
12789 // Fails on AMD: http://crbug.com/967796
12790 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
12791
12792 glActiveTexture(GL_TEXTURE0);
12793 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12794 int width = getWindowWidth();
12795 int height = getWindowHeight();
12796 GLColor color = GLColor::green;
12797 std::vector<GLColor> pixels(width * height, color);
12798 GLint baseLevel = 1;
12799 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, baseLevel);
12800 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12801 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12802 glTexImage2D(GL_TEXTURE_2D, baseLevel, GL_RGBA8UI, width, height, 0, GL_RGBA_INTEGER,
12803 GL_UNSIGNED_BYTE, pixels.data());
12804
12805 setUpProgram();
12806 glUseProgram(mProgram);
12807 glUniform1i(mTexture2DUniformLocation, 0);
12808 drawQuad(mProgram, "position", 0.5f);
12809
12810 EXPECT_GL_NO_ERROR();
12811 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
12812 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
12813 }
12814
12815 // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
12816 // texture is output.
TEST_P(Texture2DArrayIntegerTestES3,NonZeroBaseLevel)12817 TEST_P(Texture2DArrayIntegerTestES3, NonZeroBaseLevel)
12818 {
12819 // Test fail: http://anglebug.com/5959
12820 ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
12821
12822 glActiveTexture(GL_TEXTURE0);
12823 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
12824 int width = getWindowWidth();
12825 int height = getWindowHeight();
12826 int depth = 2;
12827 GLColor color = GLColor::green;
12828 std::vector<GLColor> pixels(width * height * depth, color);
12829 GLint baseLevel = 1;
12830 glTexImage3D(GL_TEXTURE_2D_ARRAY, baseLevel, GL_RGBA8UI, width, height, depth, 0,
12831 GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pixels.data());
12832 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, baseLevel);
12833 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12834 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12835
12836 drawQuad(mProgram, "position", 0.5f);
12837
12838 EXPECT_GL_NO_ERROR();
12839 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
12840 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
12841 }
12842
12843 // Draw a quad with an integer 3D texture with a non-zero base level, and test that the color of the
12844 // texture is output.
TEST_P(Texture3DIntegerTestES3,NonZeroBaseLevel)12845 TEST_P(Texture3DIntegerTestES3, NonZeroBaseLevel)
12846 {
12847 glActiveTexture(GL_TEXTURE0);
12848 glBindTexture(GL_TEXTURE_3D, mTexture3D);
12849 int width = getWindowWidth();
12850 int height = getWindowHeight();
12851 int depth = 2;
12852 GLColor color = GLColor::green;
12853 std::vector<GLColor> pixels(width * height * depth, color);
12854 GLint baseLevel = 1;
12855 glTexImage3D(GL_TEXTURE_3D, baseLevel, GL_RGBA8UI, width, height, depth, 0, GL_RGBA_INTEGER,
12856 GL_UNSIGNED_BYTE, pixels.data());
12857 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, baseLevel);
12858 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
12859 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
12860
12861 drawQuad(mProgram, "position", 0.5f);
12862
12863 EXPECT_GL_NO_ERROR();
12864 EXPECT_PIXEL_COLOR_EQ(0, 0, color);
12865 EXPECT_PIXEL_COLOR_EQ(width - 1, height - 1, color);
12866 }
12867
runCompressedSubImage()12868 void PBOCompressedTextureTest::runCompressedSubImage()
12869 {
12870 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
12871 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
12872 // http://anglebug.com/4115
12873 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsDesktopOpenGL());
12874 ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsDesktopOpenGL());
12875
12876 if (getClientMajorVersion() < 3)
12877 {
12878 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
12879 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
12880 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_compressed_ETC2_RGB8_texture"));
12881 }
12882
12883 const GLuint width = 4u;
12884 const GLuint height = 4u;
12885
12886 setWindowWidth(width);
12887 setWindowHeight(height);
12888
12889 // Setup primary Texture
12890 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12891 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
12892 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
12893
12894 if (getClientMajorVersion() < 3)
12895 {
12896 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_ETC2, width, height);
12897 }
12898 else
12899 {
12900 glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_ETC2, width, height);
12901 }
12902 ASSERT_GL_NO_ERROR();
12903
12904 // Setup PBO and fill it with a red
12905 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
12906 glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height / 2u, kCompressedImageETC2, GL_STATIC_DRAW);
12907 ASSERT_GL_NO_ERROR();
12908
12909 // Write PBO to mTexture
12910 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_COMPRESSED_RGB8_ETC2,
12911 width * height / 2u, nullptr);
12912 ASSERT_GL_NO_ERROR();
12913
12914 setUpProgram();
12915 // Draw using PBO updated texture
12916 glUseProgram(mProgram);
12917 glUniform1i(mTexture2DUniformLocation, 0);
12918 glBindTexture(GL_TEXTURE_2D, mTexture2D);
12919 drawQuad(mProgram, "position", 0.5f);
12920 ASSERT_GL_NO_ERROR();
12921
12922 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
12923 ASSERT_GL_NO_ERROR();
12924 }
12925
12926 // Test that uses glCompressedTexSubImage2D combined with a PBO
TEST_P(PBOCompressedTextureTest,PBOCompressedSubImage)12927 TEST_P(PBOCompressedTextureTest, PBOCompressedSubImage)
12928 {
12929 runCompressedSubImage();
12930 }
12931
12932 // Verify the row length state is ignored when using compressed tex image calls.
TEST_P(PBOCompressedTextureTest,PBOCompressedSubImageWithUnpackRowLength)12933 TEST_P(PBOCompressedTextureTest, PBOCompressedSubImageWithUnpackRowLength)
12934 {
12935 // ROW_LENGTH requires ES3 or an extension.
12936 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
12937 !IsGLExtensionEnabled("GL_EXT_unpack_subimage"));
12938
12939 glPixelStorei(GL_UNPACK_ROW_LENGTH, 1);
12940 runCompressedSubImage();
12941 }
12942
12943 class PBOCompressedTexture3DTest : public ANGLETest<>
12944 {
12945 protected:
PBOCompressedTexture3DTest()12946 PBOCompressedTexture3DTest() {}
12947 };
12948
12949 // Test that uses glCompressedTexSubImage3D combined with a PBO
12950 TEST_P(PBOCompressedTexture3DTest, 2DArray)
12951 {
12952 // We use GetTexImage to determine if the internal texture format is emulated
12953 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_get_image"));
12954
12955 const GLuint width = 4u;
12956 const GLuint height = 4u;
12957 const GLuint depth = 1u;
12958
12959 setWindowWidth(width);
12960 setWindowHeight(height);
12961
12962 // Setup primary texture as a 2DArray holding ETC2 data
12963 GLTexture texture2DArray;
12964 glBindTexture(GL_TEXTURE_2D_ARRAY, texture2DArray);
12965 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
12966 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
12967 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_COMPRESSED_RGB8_ETC2, width, height, depth);
12968
12969 // If the format emulated, we can't transfer it from a PBO
12970 ANGLE_SKIP_TEST_IF(IsFormatEmulated(GL_TEXTURE_2D_ARRAY));
12971
12972 // Set up a VS that simply passes through position and texcord
12973 const char kVS[] = R"(#version 300 es
12974 in vec4 position;
12975 out vec3 texCoord;
12976
12977 void main()
12978 {
12979 gl_Position = vec4(position.xy, 0.0, 1.0);
12980 texCoord = vec3(position.xy * 0.5 + vec2(0.5), 0.0);
12981 })";
12982
12983 // and FS that pulls from the 2DArray, writing out color
12984 const char kFS[] = R"(#version 300 es
12985 precision mediump float;
12986 uniform highp sampler2DArray tex2DArray;
12987 in vec3 texCoord;
12988 out vec4 fragColor;
12989
12990 void main()
12991 {
12992 fragColor = texture(tex2DArray, texCoord);
12993 })";
12994
12995 // Compile the shaders and create the program
12996 ANGLE_GL_PROGRAM(program, kVS, kFS);
12997 ASSERT_GL_NO_ERROR();
12998
12999 // Setup PBO and fill it with a red
13000 GLBuffer pbo;
13001 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
13002 glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height * depth / 2u, kCompressedImageETC2,
13003 GL_STATIC_DRAW);
13004 ASSERT_GL_NO_ERROR();
13005
13006 // Write PBO to texture2DArray
13007 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, depth,
13008 GL_COMPRESSED_RGB8_ETC2, width * height * depth / 2u, nullptr);
13009
13010 ASSERT_GL_NO_ERROR();
13011
13012 // Draw using PBO updated texture
13013 glUseProgram(program);
13014 glUniform1i(glGetUniformLocation(program, "tex2DArray"), 0);
13015 glBindTexture(GL_TEXTURE_2D_ARRAY, texture2DArray);
13016 drawQuad(program, "position", 0.5f);
13017 ASSERT_GL_NO_ERROR();
13018
13019 // Verify the texture now contains data from the PBO
13020 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13021 ASSERT_GL_NO_ERROR();
13022 }
13023
13024 // Test using ETC1_RGB8 with subimage updates
TEST_P(ETC1CompressedTextureTest,ETC1CompressedSubImage)13025 TEST_P(ETC1CompressedTextureTest, ETC1CompressedSubImage)
13026 {
13027 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
13028 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
13029
13030 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
13031 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
13032 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
13033
13034 const GLuint width = 4u;
13035 const GLuint height = 4u;
13036
13037 setWindowWidth(width);
13038 setWindowHeight(height);
13039
13040 // Setup primary Texture
13041 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
13042 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
13043
13044 if (getClientMajorVersion() < 3)
13045 {
13046 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, width, height);
13047 }
13048 else
13049 {
13050 glTexStorage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, width, height);
13051 }
13052 ASSERT_GL_NO_ERROR();
13053
13054 // Populate a subimage of the texture
13055 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_ETC1_RGB8_OES,
13056 width * height / 2u, kCompressedImageETC2);
13057 ASSERT_GL_NO_ERROR();
13058
13059 // Render and ensure we get red
13060 glUseProgram(mProgram);
13061 drawQuad(mProgram, "position", 0.5f);
13062 ASSERT_GL_NO_ERROR();
13063
13064 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13065 ASSERT_GL_NO_ERROR();
13066 }
13067
13068 // Fully-define a NPOT compressed texture and draw; set MAX_LEVEL and draw; then increase
13069 // MAX_LEVEL and draw. This used to cause Vulkan validation errors.
TEST_P(ETC1CompressedTextureTest,ETC1CompressedImageNPOT)13070 TEST_P(ETC1CompressedTextureTest, ETC1CompressedImageNPOT)
13071 {
13072 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
13073 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
13074
13075 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
13076 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
13077
13078 const GLuint width = 5u;
13079 const GLuint height = 5u;
13080 // round up to the nearest block size
13081 const GLsizei imageSize = 8 * 8 / 2;
13082 // smallest block size
13083 const GLsizei minImageSize = 4 * 4 / 2;
13084
13085 uint8_t data[imageSize] = {0};
13086
13087 setWindowWidth(width);
13088 setWindowHeight(height);
13089
13090 // Setup primary Texture
13091 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
13092 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
13093 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13094 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13095
13096 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, width, height, 0, imageSize, data);
13097 ASSERT_GL_NO_ERROR();
13098
13099 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, width / 2, height / 2, 0,
13100 minImageSize, data);
13101 ASSERT_GL_NO_ERROR();
13102
13103 glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_ETC1_RGB8_OES, width / 4, height / 4, 0,
13104 minImageSize, data);
13105 ASSERT_GL_NO_ERROR();
13106
13107 glUseProgram(mProgram);
13108 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
13109 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13110 drawQuad(mProgram, "position", 0.5f);
13111 ASSERT_GL_NO_ERROR();
13112
13113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
13114 drawQuad(mProgram, "position", 0.5f);
13115 ASSERT_GL_NO_ERROR();
13116 }
13117
13118 // Define two NPOT compressed textures, set MAX_LEVEL, draw, and swap buffers
13119 // with the two textures. This used to cause release of staging buffers
13120 // that have not been flushed.
TEST_P(ETC1CompressedTextureTest,ETC1CompressedImageDraws)13121 TEST_P(ETC1CompressedTextureTest, ETC1CompressedImageDraws)
13122 {
13123 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
13124 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
13125
13126 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
13127 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
13128
13129 const GLuint width = 384u;
13130 const GLuint height = 384u;
13131 // round up to the nearest block size
13132 const GLsizei imageSize = width * height / 2;
13133
13134 uint8_t data[imageSize] = {0};
13135
13136 setWindowWidth(width);
13137 setWindowHeight(height);
13138
13139 const GLuint smallerWidth = 384u;
13140 const GLuint smallerHeight = 320u;
13141 // round up to the nearest block size
13142 const GLsizei smallerImageSize = smallerWidth * smallerHeight / 2;
13143
13144 // Setup primary Texture
13145 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
13146 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
13147 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13148 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13149
13150 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, smallerWidth, smallerHeight, 0,
13151 smallerImageSize, data);
13152 ASSERT_GL_NO_ERROR();
13153
13154 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, 192, 160, 0, 15360, data);
13155 ASSERT_GL_NO_ERROR();
13156
13157 GLTexture largerTexture;
13158 glBindTexture(GL_TEXTURE_2D, largerTexture);
13159
13160 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, width, height, 0, imageSize, data);
13161 ASSERT_GL_NO_ERROR();
13162
13163 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, 192, 192, 0, 18432, data);
13164 ASSERT_GL_NO_ERROR();
13165
13166 glBindTexture(GL_TEXTURE_2D, mTexture2D);
13167
13168 glUseProgram(mProgram);
13169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
13170 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13171 drawQuad(mProgram, "position", 0.5f);
13172 ASSERT_GL_NO_ERROR();
13173 swapBuffers();
13174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
13175 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
13176 drawQuad(mProgram, "position", 0.5f);
13177 ASSERT_GL_NO_ERROR();
13178 swapBuffers();
13179
13180 glBindTexture(GL_TEXTURE_2D, largerTexture);
13181
13182 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
13183 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13184 drawQuad(mProgram, "position", 0.5f);
13185 ASSERT_GL_NO_ERROR();
13186 swapBuffers();
13187
13188 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
13189 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
13190 drawQuad(mProgram, "position", 0.5f);
13191 ASSERT_GL_NO_ERROR();
13192 swapBuffers();
13193
13194 glBindTexture(GL_TEXTURE_2D, mTexture2D);
13195
13196 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
13197 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13198 drawQuad(mProgram, "position", 0.5f);
13199 swapBuffers();
13200 ASSERT_GL_NO_ERROR();
13201 }
13202
13203 // Fully-define a compressed texture and draw; then decrease MAX_LEVEL and draw; then increase
13204 // MAX_LEVEL and draw. This used to cause Vulkan validation errors.
TEST_P(ETC1CompressedTextureTest,ETC1ShrinkThenGrowMaxLevels)13205 TEST_P(ETC1CompressedTextureTest, ETC1ShrinkThenGrowMaxLevels)
13206 {
13207 // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
13208 ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
13209
13210 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
13211 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
13212
13213 const GLuint width = 4u;
13214 const GLuint height = 4u;
13215
13216 setWindowWidth(width);
13217 setWindowHeight(height);
13218
13219 // Setup primary Texture
13220 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
13221 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
13222
13223 if (getClientMajorVersion() < 3)
13224 {
13225 glTexStorage2DEXT(GL_TEXTURE_2D, 3, GL_ETC1_RGB8_OES, width, height);
13226 }
13227 else
13228 {
13229 glTexStorage2D(GL_TEXTURE_2D, 3, GL_ETC1_RGB8_OES, width, height);
13230 }
13231 ASSERT_GL_NO_ERROR();
13232
13233 // Populate a subimage of the texture
13234 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_ETC1_RGB8_OES,
13235 width * height / 2u, kCompressedImageETC2);
13236 glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, width / 2, height / 2, GL_ETC1_RGB8_OES,
13237 width * height / 2u, kCompressedImageETC2);
13238 glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, width / 4, height / 4, GL_ETC1_RGB8_OES,
13239 width * height / 2u, kCompressedImageETC2);
13240 ASSERT_GL_NO_ERROR();
13241
13242 // Set MAX_LEVEL to 2 (the highest level)
13243 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
13244
13245 // Render and ensure we get red
13246 glUseProgram(mProgram);
13247 drawQuad(mProgram, "position", 0.5f);
13248 ASSERT_GL_NO_ERROR();
13249 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13250 ASSERT_GL_NO_ERROR();
13251
13252 // Decrease MAX_LEVEL to 0, render, and ensure we still get red
13253 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13254 drawQuad(mProgram, "position", 0.5f);
13255 ASSERT_GL_NO_ERROR();
13256 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13257 ASSERT_GL_NO_ERROR();
13258
13259 // Increase MAX_LEVEL back to 2, render, and ensure we still get red
13260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
13261 drawQuad(mProgram, "position", 0.5f);
13262 ASSERT_GL_NO_ERROR();
13263 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
13264 ASSERT_GL_NO_ERROR();
13265 }
13266
13267 class TextureBufferTestES31 : public ANGLETest<>
13268 {
13269 protected:
TextureBufferTestES31()13270 TextureBufferTestES31() {}
13271
13272 void drawWithIncompleteOrZeroTexture(bool useCompleteTexture, bool useNonZeroTexture);
13273 };
13274
drawWithIncompleteOrZeroTexture(bool useCompleteTexture,bool useNonZeroTexture)13275 void TextureBufferTestES31::drawWithIncompleteOrZeroTexture(bool useCompleteTexture,
13276 bool useNonZeroTexture)
13277 {
13278 constexpr char kSamplerBuffer[] = R"(#version 310 es
13279 #extension GL_OES_texture_buffer : require
13280 precision mediump float;
13281 uniform highp samplerBuffer s;
13282 out vec4 colorOut;
13283 void main()
13284 {
13285 colorOut = texelFetch(s, 0);
13286 })";
13287
13288 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kSamplerBuffer);
13289 glUseProgram(program);
13290 EXPECT_GL_NO_ERROR();
13291
13292 // Bind as texture buffer
13293 GLTexture texture;
13294 glActiveTexture(GL_TEXTURE0);
13295 glBindTexture(GL_TEXTURE_BUFFER, useNonZeroTexture ? texture.get() : 0u);
13296 EXPECT_GL_NO_ERROR();
13297
13298 if (useCompleteTexture)
13299 {
13300 const std::array<GLColor, 4> kData = {GLColor::blue, GLColor::blue, GLColor::blue,
13301 GLColor::blue};
13302
13303 // Create buffer and initialize with data
13304 GLBuffer buffer;
13305 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
13306 glBufferData(GL_TEXTURE_BUFFER, sizeof(kData), kData.data(), GL_DYNAMIC_DRAW);
13307 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13308 EXPECT_GL_NO_ERROR();
13309 }
13310
13311 // Draw texture buffer
13312 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5);
13313 EXPECT_GL_NO_ERROR();
13314
13315 if (useCompleteTexture)
13316 {
13317 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
13318 }
13319 }
13320
13321 // Test that mutating a buffer attached to a texture returns correct results in query.
TEST_P(TextureBufferTestES31,QueryWidthAfterBufferResize)13322 TEST_P(TextureBufferTestES31, QueryWidthAfterBufferResize)
13323 {
13324 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
13325
13326 constexpr GLint kInitialSize = 128;
13327 constexpr std::array<GLint, 4> kModifiedSizes = {96, 192, 32, 256};
13328
13329 GLTexture texture;
13330 glBindTexture(GL_TEXTURE_BUFFER, texture);
13331
13332 GLBuffer buffer;
13333 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
13334 glBufferData(GL_TEXTURE_BUFFER, kInitialSize, nullptr, GL_STATIC_DRAW);
13335
13336 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13337 ASSERT_GL_NO_ERROR();
13338
13339 GLint queryResult = 0;
13340 glGetTexLevelParameteriv(GL_TEXTURE_BUFFER, 0, GL_TEXTURE_WIDTH, &queryResult);
13341 ASSERT_GL_NO_ERROR();
13342 EXPECT_EQ(queryResult, kInitialSize / 4);
13343
13344 for (GLint modifiedSize : kModifiedSizes)
13345 {
13346 glBufferData(GL_TEXTURE_BUFFER, modifiedSize, nullptr, GL_STATIC_DRAW);
13347 glGetTexLevelParameteriv(GL_TEXTURE_BUFFER, 0, GL_TEXTURE_WIDTH, &queryResult);
13348 ASSERT_GL_NO_ERROR();
13349 EXPECT_EQ(queryResult, modifiedSize / 4);
13350 }
13351 }
13352
13353 // Test that glTexBufferEXT can be used in two draw calls.
13354 // Covers a bug where TextureVk::setBuffer releases buffer views and doesn't init them.
TEST_P(TextureBufferTestES31,TexBufferDrawTwice)13355 TEST_P(TextureBufferTestES31, TexBufferDrawTwice)
13356 {
13357 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13358
13359 // TODO(http://anglebug.com/5832): Claims to support GL_OES_texture_buffer, but fails
13360 // compilation of shader because "extension 'GL_OES_texture_buffer' is not supported".
13361 ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
13362
13363 const std::array<GLColor, 1> kTexData = {GLColor::red};
13364
13365 GLBuffer buffer;
13366 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
13367 glBufferData(GL_TEXTURE_BUFFER, sizeof(kTexData), kTexData.data(), GL_DYNAMIC_DRAW);
13368 EXPECT_GL_NO_ERROR();
13369
13370 constexpr char kSamplerBuffer[] = R"(#version 310 es
13371 #extension GL_OES_texture_buffer : require
13372 precision mediump float;
13373 uniform highp samplerBuffer s;
13374 out vec4 colorOut;
13375 void main()
13376 {
13377 colorOut = texelFetch(s, 0);
13378 })";
13379
13380 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kSamplerBuffer);
13381
13382 // Draw once
13383 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13384 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5);
13385 EXPECT_GL_NO_ERROR();
13386
13387 // Draw twice
13388 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13389 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5);
13390 EXPECT_GL_NO_ERROR();
13391
13392 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
13393 }
13394
13395 // Test that uploading data to buffer that's in use then using it as texture buffer works.
TEST_P(TextureBufferTestES31,UseAsUBOThenUpdateThenAsTextureBuffer)13396 TEST_P(TextureBufferTestES31, UseAsUBOThenUpdateThenAsTextureBuffer)
13397 {
13398 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13399
13400 // Claims to support GL_OES_texture_buffer, but fails compilation of shader because "extension
13401 // 'GL_OES_texture_buffer' is not supported". http://anglebug.com/5832
13402 ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
13403
13404 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
13405 GLColor::red};
13406 const std::array<GLColor, 4> kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue,
13407 GLColor::blue};
13408
13409 GLBuffer buffer;
13410 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
13411 glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
13412 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
13413 EXPECT_GL_NO_ERROR();
13414
13415 constexpr char kVerifyUBO[] = R"(#version 310 es
13416 precision mediump float;
13417 layout(binding = 0) uniform block {
13418 uvec4 data;
13419 } ubo;
13420 out vec4 colorOut;
13421 void main()
13422 {
13423 if (all(equal(ubo.data, uvec4(0xFF0000FFu))))
13424 colorOut = vec4(0, 1.0, 0, 1.0);
13425 else
13426 colorOut = vec4(1.0, 0, 0, 1.0);
13427 })";
13428
13429 ANGLE_GL_PROGRAM(verifyUbo, essl31_shaders::vs::Simple(), kVerifyUBO);
13430 drawQuad(verifyUbo, essl31_shaders::PositionAttrib(), 0.5);
13431 EXPECT_GL_NO_ERROR();
13432
13433 // Update buffer data
13434 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
13435 EXPECT_GL_NO_ERROR();
13436
13437 // Bind as texture buffer
13438 GLTexture texture;
13439 glBindTexture(GL_TEXTURE_BUFFER, texture);
13440 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13441 EXPECT_GL_NO_ERROR();
13442
13443 constexpr char kVerifySamplerBuffer[] = R"(#version 310 es
13444 #extension GL_OES_texture_buffer : require
13445 precision mediump float;
13446 uniform highp samplerBuffer s;
13447 out vec4 colorOut;
13448 void main()
13449 {
13450 colorOut = texelFetch(s, 0);
13451 })";
13452
13453 ANGLE_GL_PROGRAM(verifySamplerBuffer, essl31_shaders::vs::Simple(), kVerifySamplerBuffer);
13454
13455 glEnable(GL_BLEND);
13456 glBlendFunc(GL_ONE, GL_ONE);
13457 drawQuad(verifySamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
13458 EXPECT_GL_NO_ERROR();
13459
13460 // Make sure both draw calls succeed
13461 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
13462 }
13463
13464 // Test that mapping a texture buffer with GL_MAP_INVALIDATE_BUFFER_BIT and writing to it works
13465 // correctly.
TEST_P(TextureBufferTestES31,MapTextureBufferInvalidateThenWrite)13466 TEST_P(TextureBufferTestES31, MapTextureBufferInvalidateThenWrite)
13467 {
13468 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13469
13470 // TODO(http://anglebug.com/5832): Claims to support GL_OES_texture_buffer, but fails
13471 // compilation of shader because "extension 'GL_OES_texture_buffer' is not supported".
13472 ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
13473 // TODO(http://anglebug.com/6396): The OpenGL backend doesn't correctly handle texture buffers
13474 // being invalidated when mapped.
13475 ANGLE_SKIP_TEST_IF(IsOpenGL());
13476
13477 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
13478 GLColor::red};
13479 const std::array<GLColor, 4> kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue,
13480 GLColor::blue};
13481
13482 GLBuffer buffer;
13483 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
13484 glBufferData(GL_TEXTURE_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
13485 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
13486 EXPECT_GL_NO_ERROR();
13487
13488 // Bind as texture buffer
13489 GLTexture texture;
13490 glBindTexture(GL_TEXTURE_BUFFER, texture);
13491 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13492 EXPECT_GL_NO_ERROR();
13493
13494 constexpr char kSamplerBuffer[] = R"(#version 310 es
13495 #extension GL_OES_texture_buffer : require
13496 precision mediump float;
13497 uniform highp samplerBuffer s;
13498 out vec4 colorOut;
13499 void main()
13500 {
13501 colorOut = texelFetch(s, 0);
13502 })";
13503
13504 ANGLE_GL_PROGRAM(initialSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
13505 drawQuad(initialSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
13506 EXPECT_GL_NO_ERROR();
13507
13508 // Don't read back, so we don't break the render pass.
13509
13510 // Map the buffer and update it.
13511 void *mappedBuffer = glMapBufferRange(GL_TEXTURE_BUFFER, 0, sizeof(kInitialData),
13512 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
13513 memcpy(mappedBuffer, kUpdateData.data(), sizeof(kInitialData));
13514
13515 glUnmapBuffer(GL_TEXTURE_BUFFER);
13516
13517 // Draw with the updated buffer data.
13518 ANGLE_GL_PROGRAM(updateSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
13519 drawQuad(updateSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
13520 EXPECT_GL_NO_ERROR();
13521
13522 // Make sure both draw calls succeed
13523 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
13524 }
13525
13526 // Test that calling glBufferData on a buffer that is used as texture buffer still works correctly.
TEST_P(TextureBufferTestES31,TextureBufferThenBufferData)13527 TEST_P(TextureBufferTestES31, TextureBufferThenBufferData)
13528 {
13529 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13530
13531 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
13532 GLColor::red};
13533 const std::array<GLColor, 4> kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue,
13534 GLColor::blue};
13535 // Create buffer and initialize with data
13536 GLBuffer buffer;
13537 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
13538 glBufferData(GL_TEXTURE_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
13539
13540 // Bind as texture buffer
13541 GLTexture texture;
13542 glBindTexture(GL_TEXTURE_BUFFER, texture);
13543 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
13544 EXPECT_GL_NO_ERROR();
13545
13546 constexpr char kSamplerBuffer[] = R"(#version 310 es
13547 #extension GL_OES_texture_buffer : require
13548 precision mediump float;
13549 uniform highp samplerBuffer s;
13550 out vec4 colorOut;
13551 void main()
13552 {
13553 colorOut = texelFetch(s, 0);
13554 })";
13555
13556 ANGLE_GL_PROGRAM(initialSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
13557 drawQuad(initialSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
13558
13559 // Don't read back, so we keep the original buffer busy. Issue a glBufferData call with same
13560 // size and nullptr so that the old buffer storage gets orphaned.
13561 glBufferData(GL_TEXTURE_BUFFER, sizeof(kUpdateData), nullptr, GL_DYNAMIC_DRAW);
13562 glBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(kUpdateData), kUpdateData.data());
13563
13564 // Draw with the updated buffer data.
13565 ANGLE_GL_PROGRAM(updateSamplerBuffer, essl31_shaders::vs::Simple(), kSamplerBuffer);
13566 drawQuad(updateSamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
13567 EXPECT_GL_NO_ERROR();
13568 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
13569 }
13570
13571 // Test workaround in Vulkan backend for mismatched texture buffer and sampler formats
TEST_P(TextureBufferTestES31,TexBufferFormatMismatch)13572 TEST_P(TextureBufferTestES31, TexBufferFormatMismatch)
13573 {
13574 ANGLE_SKIP_TEST_IF(!IsVulkan());
13575 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
13576
13577 auto runTestCase = [&](auto texData, GLenum format, const char *samplerType) {
13578 std::stringstream fsStream;
13579 fsStream << R"(#version 310 es
13580 #extension GL_EXT_texture_buffer : require
13581 precision mediump float;
13582 uniform highp )"
13583 << samplerType << R"( s;
13584 out vec4 colorOut;
13585 void main()
13586 {
13587 colorOut = vec4(texelFetch(s, 0).r, 0, 0, 1);
13588 })";
13589 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), fsStream.str().c_str());
13590
13591 GLBuffer buffer;
13592 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
13593
13594 glBufferData(GL_TEXTURE_BUFFER, sizeof(texData), texData.data(), GL_DYNAMIC_DRAW);
13595 glTexBufferEXT(GL_TEXTURE_BUFFER, format, buffer);
13596
13597 drawQuad(program, essl31_shaders::PositionAttrib(), 0.5);
13598 EXPECT_GL_NO_ERROR();
13599 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
13600 };
13601
13602 const std::array<uint8_t, 4> kTexData8n{255}; // 8-bit normalized {1,0,0,0}
13603 const std::array<uint8_t, 4> kTexData8i{1}; // 8-bit (u)int {1,0,0,0}
13604
13605 // Test all 8-bit formats from EXT_texture_buffer.txt Table texbo.1
13606 for (auto format :
13607 {GL_R8, GL_R8I, GL_R8UI, GL_RG8, GL_RG8I, GL_RG8UI, GL_RGBA8, GL_RGBA8I, GL_RGBA8UI})
13608 {
13609 // float sampler
13610 runTestCase(kTexData8n, format, "samplerBuffer");
13611 // integer samplers
13612 runTestCase(kTexData8i, format, "isamplerBuffer");
13613 runTestCase(kTexData8i, format, "usamplerBuffer");
13614 }
13615
13616 const uint16_t kHalfFloatOne = 0x3C00;
13617 const std::array<uint16_t, 4> kTexData16f{kHalfFloatOne}; // 16-bit float {1,0,0,0}
13618 const std::array<uint16_t, 4> kTexData16i{1}; // 16-bit (u)int {1,0,0,0}
13619
13620 // Test all 16-bit formats from EXT_texture_buffer.txt Table texbo.1
13621 for (auto format : {GL_R16F, GL_R16I, GL_R16UI, GL_RG16F, GL_RG16I, GL_RG16UI, GL_RGBA16F,
13622 GL_RGBA16I, GL_RGBA16UI})
13623 {
13624 // float sampler
13625 runTestCase(kTexData16f, format, "samplerBuffer");
13626 // integer samplers
13627 runTestCase(kTexData16i, format, "isamplerBuffer");
13628 runTestCase(kTexData16i, format, "usamplerBuffer");
13629 }
13630
13631 const std::array<GLfloat, 4> kTexData32f{1.0f}; // 32-bit float {1,0,0,0}
13632 const std::array<uint32_t, 4> kTexData32i{1}; // 32-bit (u)int {1,0,0,0}
13633
13634 // Test all 32-bit formats from EXT_texture_buffer.txt Table texbo.1
13635 for (auto format : {GL_R32F, GL_R32I, GL_R32UI, GL_RG32F, GL_RG32I, GL_RG32UI, GL_RGB32F,
13636 GL_RGB32I, GL_RGB32UI, GL_RGBA32F, GL_RGBA32I, GL_RGBA32UI})
13637 {
13638 // float sampler
13639 runTestCase(kTexData32f, format, "samplerBuffer");
13640 // integer samplers
13641 runTestCase(kTexData32i, format, "isamplerBuffer");
13642 runTestCase(kTexData32i, format, "usamplerBuffer");
13643 }
13644 }
13645
13646 // Create an integer format texture but specify a FLOAT sampler. OpenGL
13647 // tolerates this but it causes a Vulkan validation error.
TEST_P(Texture2DTestES3,TexImageFormatMismatch)13648 TEST_P(Texture2DTestES3, TexImageFormatMismatch)
13649 {
13650 GLint textureUnit = 2;
13651 GLuint genericBuffer;
13652 GLubyte genericBufferMemory[1024];
13653 GLuint texture;
13654 GLuint sampler;
13655 GLuint vertexArray;
13656
13657 glGenBuffers(1, &genericBuffer);
13658 glBindBuffer(GL_ARRAY_BUFFER, genericBuffer);
13659 glBufferData(GL_ARRAY_BUFFER, 1024, &genericBufferMemory, GL_STATIC_DRAW);
13660
13661 glGenTextures(1, &texture);
13662 glBindTexture(GL_TEXTURE_2D, texture);
13663 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
13664 glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, 8, 8, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT,
13665 &genericBufferMemory);
13666
13667 const char *vertexShaderSource = getVertexShaderSource();
13668 const char *fragmentShaderSource = getFragmentShaderSource();
13669 ANGLE_GL_PROGRAM(testProgram, vertexShaderSource, fragmentShaderSource);
13670
13671 GLint texLocation = glGetUniformLocation(testProgram, "tex");
13672 glUseProgram(testProgram);
13673
13674 glUniform1iv(texLocation, 1, &textureUnit);
13675
13676 glGenSamplers(1, &sampler);
13677 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13678 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13679
13680 glBindBuffer(GL_UNIFORM_BUFFER, genericBuffer);
13681
13682 glActiveTexture(GL_TEXTURE0 + textureUnit);
13683 glBindTexture(GL_TEXTURE_2D, texture);
13684 glBindSampler(textureUnit, sampler);
13685
13686 glGenVertexArrays(1, &vertexArray);
13687 glBindVertexArray(vertexArray);
13688 glBindBuffer(GL_ARRAY_BUFFER, genericBuffer);
13689
13690 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, genericBuffer);
13691 glBindVertexArray(vertexArray);
13692 glDrawElementsInstanced(GL_TRIANGLES, 4, GL_UNSIGNED_SHORT, 0, 1);
13693 }
13694
13695 // Checks that drawing incomplete zero texture buffer does not crash.
TEST_P(TextureBufferTestES31,DrawIncompleteZeroTexture)13696 TEST_P(TextureBufferTestES31, DrawIncompleteZeroTexture)
13697 {
13698 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13699
13700 drawWithIncompleteOrZeroTexture(false, false);
13701 }
13702
13703 // Checks that drawing incomplete non-zero texture buffer does not crash.
TEST_P(TextureBufferTestES31,DrawIncompleteNonZeroTexture)13704 TEST_P(TextureBufferTestES31, DrawIncompleteNonZeroTexture)
13705 {
13706 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13707
13708 drawWithIncompleteOrZeroTexture(false, true);
13709 }
13710
13711 // Checks that drawing complete zero texture buffer produces expected results.
TEST_P(TextureBufferTestES31,DrawCompleteZeroTexture)13712 TEST_P(TextureBufferTestES31, DrawCompleteZeroTexture)
13713 {
13714 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13715
13716 drawWithIncompleteOrZeroTexture(true, false);
13717 }
13718
13719 // Checks that drawing complete non-zero texture buffer produces expected results.
TEST_P(TextureBufferTestES31,DrawCompleteNonZeroTexture)13720 TEST_P(TextureBufferTestES31, DrawCompleteNonZeroTexture)
13721 {
13722 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
13723
13724 drawWithIncompleteOrZeroTexture(true, true);
13725 }
13726
13727 // Test that the correct error is generated if texture buffer support used anyway when not enabled.
TEST_P(TextureBufferTestES31,TestErrorWhenNotEnabled)13728 TEST_P(TextureBufferTestES31, TestErrorWhenNotEnabled)
13729 {
13730 ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_texture_buffer"));
13731
13732 GLTexture texture;
13733 glBindTexture(GL_TEXTURE_BUFFER, texture);
13734 ASSERT_GL_ERROR(GL_INVALID_ENUM);
13735 }
13736
13737 class CopyImageTestES31 : public ANGLETest<>
13738 {
13739 protected:
CopyImageTestES31()13740 CopyImageTestES31() {}
13741 };
13742
13743 // Test that copies between RGB formats doesn't affect the emulated alpha channel, if any.
TEST_P(CopyImageTestES31,PreserveEmulatedAlpha)13744 TEST_P(CopyImageTestES31, PreserveEmulatedAlpha)
13745 {
13746 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
13747
13748 constexpr GLsizei kSize = 1;
13749
13750 GLTexture src, dst;
13751
13752 // Set up the textures
13753 glBindTexture(GL_TEXTURE_2D, src);
13754 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, kSize, kSize);
13755
13756 const GLColor kInitColor(50, 100, 150, 200);
13757 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGB, GL_UNSIGNED_BYTE, &kInitColor);
13758
13759 glBindTexture(GL_TEXTURE_2D, dst);
13760 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8UI, kSize, kSize);
13761 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
13762 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
13763
13764 // Copy from src to dst
13765 glCopyImageSubDataEXT(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize,
13766 kSize, 1);
13767
13768 // Bind dst as image
13769 glBindImageTexture(0, dst, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI);
13770
13771 // Create a buffer for output
13772 constexpr GLsizei kBufferSize = kSize * kSize * sizeof(uint32_t) * 4;
13773 GLBuffer buffer;
13774 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
13775 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
13776 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffer);
13777
13778 constexpr char kCS[] = R"(#version 310 es
13779 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
13780 layout(rgba8ui, binding = 0) readonly uniform highp uimage2D imageIn;
13781 layout(std140, binding = 1) buffer dataOut {
13782 uvec4 data[];
13783 };
13784 void main()
13785 {
13786 uvec4 color = imageLoad(imageIn, ivec2(0));
13787 data[0] = color;
13788 })";
13789
13790 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
13791 glUseProgram(program);
13792 glDispatchCompute(1, 1, 1);
13793 EXPECT_GL_NO_ERROR();
13794
13795 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
13796
13797 const uint32_t *ptr = reinterpret_cast<uint32_t *>(
13798 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT));
13799
13800 EXPECT_EQ(ptr[0], kInitColor.R);
13801 EXPECT_EQ(ptr[1], kInitColor.G);
13802 EXPECT_EQ(ptr[2], kInitColor.B);
13803
13804 // Expect alpha to be 1, even if the RGB format is emulated with RGBA.
13805 EXPECT_EQ(ptr[3], 1u);
13806
13807 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
13808 }
13809
13810 // Verify a common pattern used by the Unreal Engine that trips up the tracer
TEST_P(CopyImageTestES31,CubeMapCopyImageSubData)13811 TEST_P(CopyImageTestES31, CubeMapCopyImageSubData)
13812 {
13813 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
13814
13815 constexpr char kVS[] =
13816 R"(#version 300 es
13817 precision mediump float;
13818 in vec3 pos;
13819 void main() {
13820 gl_Position = vec4(pos, 1.0);
13821 })";
13822
13823 constexpr char kFS[] =
13824 R"(#version 300 es
13825 precision mediump float;
13826 out vec4 color;
13827 uniform samplerCube uTex;
13828 void main(){
13829 // sample from lod 1.0
13830 color = textureLod(uTex, vec3(1.0), 1.0);
13831 })";
13832
13833 ANGLE_GL_PROGRAM(program, kVS, kFS);
13834 glUseProgram(program);
13835
13836 // Set up two cube maps, then verify we can copy between them
13837 constexpr size_t kSize = 2;
13838 constexpr int levels = 2;
13839 std::vector<GLColor> pixelsGreen(kSize * kSize, GLColor::green);
13840 std::vector<GLColor> pixelsRed(kSize * kSize, GLColor::red);
13841
13842 // Initialize src to green
13843 GLTexture texCubeSrc;
13844 glBindTexture(GL_TEXTURE_CUBE_MAP, texCubeSrc);
13845 for (int i = 0; i < levels; i++)
13846 {
13847 for (GLenum face = 0; face < 6; face++)
13848 {
13849 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, i, GL_RGBA, kSize >> i, kSize >> i,
13850 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelsGreen.data());
13851 }
13852 }
13853 ASSERT_GL_NO_ERROR();
13854
13855 // Initialize dst to red
13856 GLTexture texCubeDst;
13857 glBindTexture(GL_TEXTURE_CUBE_MAP, texCubeDst);
13858 for (int i = 0; i < levels; i++)
13859 {
13860 for (GLenum face = 0; face < 6; face++)
13861 {
13862 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, i, GL_RGBA, kSize >> i, kSize >> i,
13863 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelsRed.data());
13864 }
13865 }
13866 ASSERT_GL_NO_ERROR();
13867
13868 // Clear to blue
13869 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
13870 glClear(GL_COLOR_BUFFER_BIT);
13871 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
13872
13873 // Sample from the dst texture to ensure it has the right color
13874 GLint textureLoc = glGetUniformLocation(program, "uTex");
13875 ASSERT_NE(-1, textureLoc);
13876 glUniform1i(textureLoc, 0);
13877
13878 // Draw once and sample from level 1, which is red
13879 drawQuad(program, "pos", 0.5f);
13880 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
13881
13882 // Swap to trigger MEC
13883 swapBuffers();
13884
13885 // Copy level 1 from src to dst
13886 glCopyImageSubDataEXT(texCubeSrc, GL_TEXTURE_CUBE_MAP, 1, 0, 0, 0, texCubeDst,
13887 GL_TEXTURE_CUBE_MAP, 1, 0, 0, 0, kSize >> 1, kSize >> 1, 6);
13888 ASSERT_GL_NO_ERROR();
13889
13890 // Draw again and verify we get green
13891 drawQuad(program, "pos", 0.5f);
13892 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
13893
13894 // Swap again to end the capture
13895 swapBuffers();
13896
13897 ASSERT_GL_NO_ERROR();
13898 }
13899
13900 // Verify that copies between texture layers works, including when there is a read after write in a
13901 // level/layer.
TEST_P(CopyImageTestES31,ArraySelfCopyImageSubDataWithReadAfterWrite)13902 TEST_P(CopyImageTestES31, ArraySelfCopyImageSubDataWithReadAfterWrite)
13903 {
13904 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
13905
13906 // Set up a texture with multiple layers, then verify we can copy between them
13907 constexpr uint32_t kWidth = 13;
13908 constexpr uint32_t kHeight = 57;
13909 constexpr uint32_t kLayers = 5;
13910 constexpr uint32_t kLevels = 2;
13911 std::vector<GLColor> pixelsRed(kWidth * kHeight, GLColor::red);
13912 std::vector<GLColor> pixelsGreen(kWidth * kHeight, GLColor::green);
13913 std::vector<GLColor> pixelsBlue(kWidth * kHeight, GLColor::blue);
13914
13915 const GLColor *colors[3] = {
13916 pixelsRed.data(),
13917 pixelsGreen.data(),
13918 pixelsBlue.data(),
13919 };
13920
13921 GLTexture tex;
13922 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
13923 glTexStorage3D(GL_TEXTURE_2D_ARRAY, kLevels, GL_RGBA8, kWidth, kHeight, kLayers);
13924 for (uint32_t level = 0; level < kLevels; ++level)
13925 {
13926 for (uint32_t layer = 0; layer < kLayers; ++layer)
13927 {
13928 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0, 0, layer, kWidth >> level,
13929 kHeight >> level, 1, GL_RGBA, GL_UNSIGNED_BYTE,
13930 colors[(level + layer) % 3]);
13931 }
13932 }
13933 ASSERT_GL_NO_ERROR();
13934
13935 // The texture has the following colors:
13936 // Layer 0 Layer 1 Layer 2 Layer 3 Layer 4
13937 // Level 0 Red Green Blue Red Green
13938 // Level 1 Green Blue Red Green Blue
13939
13940 // Copy level 0, layer 0 to level 0, layer 2
13941 glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0,
13942 2, kWidth, kHeight, 1);
13943
13944 // Copy level 1, layers 3, 4 to level 1, layers 1, 2
13945 glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 1, 0, 0, 3, tex, GL_TEXTURE_2D_ARRAY, 1, 0, 0,
13946 1, kWidth >> 1, kHeight >> 1, 2);
13947
13948 // Partially copy level 1, layer 1 to level 0, layer 3
13949 // Level 1/layer 1 will be read from after being written to
13950 glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 1, kWidth / 8, kHeight / 8, 1, tex,
13951 GL_TEXTURE_2D_ARRAY, 0, kWidth / 4, kHeight / 4, 3, kWidth / 4,
13952 kHeight / 4, 1);
13953 ASSERT_GL_NO_ERROR();
13954
13955 // Verify colors
13956 GLFramebuffer FBO;
13957 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
13958 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0);
13959 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
13960
13961 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
13962 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
13963
13964 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
13965 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
13966
13967 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 3);
13968 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight / 4, GLColor::red);
13969 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 4, kHeight, GLColor::red);
13970 EXPECT_PIXEL_RECT_EQ(0, kHeight / 4 + kHeight / 4, kWidth,
13971 kHeight - (kHeight / 4 + kHeight / 4), GLColor::red);
13972 EXPECT_PIXEL_RECT_EQ(kWidth / 4 + kWidth / 4, 0, kWidth - (kWidth / 4 + kWidth / 4), kHeight,
13973 GLColor::red);
13974 EXPECT_PIXEL_RECT_EQ(kWidth / 4, kHeight / 4, kWidth / 4, kHeight / 4, GLColor::green);
13975
13976 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 4);
13977 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
13978
13979 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 0);
13980 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
13981
13982 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 1);
13983 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
13984
13985 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 2);
13986 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
13987
13988 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 3);
13989 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
13990
13991 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 4);
13992 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
13993 ASSERT_GL_NO_ERROR();
13994 }
13995
13996 // Verify that copies between texture layers works, including when there is a write after read in a
13997 // level/layer.
TEST_P(CopyImageTestES31,ArraySelfCopyImageSubDataWithWriteAfterRead)13998 TEST_P(CopyImageTestES31, ArraySelfCopyImageSubDataWithWriteAfterRead)
13999 {
14000 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
14001
14002 // Set up a texture with multiple layers, then verify we can copy between them
14003 constexpr uint32_t kWidth = 13;
14004 constexpr uint32_t kHeight = 57;
14005 constexpr uint32_t kLayers = 5;
14006 constexpr uint32_t kLevels = 2;
14007 std::vector<GLColor> pixelsRed(kWidth * kHeight, GLColor::red);
14008 std::vector<GLColor> pixelsGreen(kWidth * kHeight, GLColor::green);
14009 std::vector<GLColor> pixelsBlue(kWidth * kHeight, GLColor::blue);
14010
14011 const GLColor *colors[3] = {
14012 pixelsRed.data(),
14013 pixelsGreen.data(),
14014 pixelsBlue.data(),
14015 };
14016
14017 GLTexture tex;
14018 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
14019 glTexStorage3D(GL_TEXTURE_2D_ARRAY, kLevels, GL_RGBA8, kWidth, kHeight, kLayers);
14020 for (uint32_t level = 0; level < kLevels; ++level)
14021 {
14022 for (uint32_t layer = 0; layer < kLayers; ++layer)
14023 {
14024 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0, 0, layer, kWidth >> level,
14025 kHeight >> level, 1, GL_RGBA, GL_UNSIGNED_BYTE,
14026 colors[(level + layer) % 3]);
14027 }
14028 }
14029 ASSERT_GL_NO_ERROR();
14030
14031 // The texture has the following colors:
14032 // Layer 0 Layer 1 Layer 2 Layer 3 Layer 4
14033 // Level 0 Red Green Blue Red Green
14034 // Level 1 Green Blue Red Green Blue
14035
14036 // Copy level 0, layer 0 to level 0, layer 2
14037 glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0,
14038 2, kWidth, kHeight, 1);
14039 ASSERT_GL_NO_ERROR();
14040
14041 // Copy level 0, layer 1 to level 0, layer 3
14042 glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0,
14043 3, kWidth, kHeight, 1);
14044 ASSERT_GL_NO_ERROR();
14045
14046 // Copy level 0, layer 0 to level 0, layer 1
14047 // Level 0/layer 1 will be written to from after being read from
14048 glCopyImageSubDataEXT(tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, tex, GL_TEXTURE_2D_ARRAY, 0, 0, 0,
14049 1, kWidth, kHeight, 1);
14050 ASSERT_GL_NO_ERROR();
14051
14052 // Verify colors
14053 GLFramebuffer FBO;
14054 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
14055 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0);
14056 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14057
14058 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
14059 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14060
14061 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
14062 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14063
14064 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 3);
14065 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
14066
14067 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 4);
14068 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
14069
14070 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 0);
14071 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
14072
14073 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 1);
14074 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
14075
14076 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 2);
14077 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::red);
14078
14079 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 3);
14080 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::green);
14081
14082 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 4);
14083 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
14084 ASSERT_GL_NO_ERROR();
14085 }
14086
14087 // Verify that copies between 3D texture slices work
TEST_P(CopyImageTestES31,Texture3DSelfCopyImageSubData)14088 TEST_P(CopyImageTestES31, Texture3DSelfCopyImageSubData)
14089 {
14090 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
14091
14092 // Set up a texture with multiple layers, then verify we can copy between them
14093 constexpr uint32_t kWidth = 23;
14094 constexpr uint32_t kHeight = 47;
14095 constexpr uint32_t kDepth = 5;
14096 constexpr uint32_t kLevels = 2;
14097 std::vector<GLColor> pixelsRed(kWidth * kHeight, GLColor::red);
14098 std::vector<GLColor> pixelsGreen(kWidth * kHeight, GLColor::green);
14099 std::vector<GLColor> pixelsBlue(kWidth * kHeight, GLColor::blue);
14100
14101 const GLColor *colors[3] = {
14102 pixelsRed.data(),
14103 pixelsGreen.data(),
14104 pixelsBlue.data(),
14105 };
14106
14107 GLTexture tex;
14108 glBindTexture(GL_TEXTURE_3D, tex);
14109 glTexStorage3D(GL_TEXTURE_3D, kLevels, GL_RGBA8, kWidth, kHeight, kDepth);
14110 for (uint32_t level = 0; level < kLevels; ++level)
14111 {
14112 for (uint32_t depth = 0; depth < kDepth >> level; ++depth)
14113 {
14114 glTexSubImage3D(GL_TEXTURE_3D, level, 0, 0, depth, kWidth >> level, kHeight >> level, 1,
14115 GL_RGBA, GL_UNSIGNED_BYTE, colors[(level + depth) % 3]);
14116 }
14117 }
14118 ASSERT_GL_NO_ERROR();
14119
14120 // The texture has the following colors:
14121 // Slice 0 Slice 1 Slice 2 Slice 3 Slice 4
14122 // Level 0 Red Green Blue Red Green
14123 // Level 1 Green Blue
14124
14125 // Copy level 1, slice 1 to level 1, slice 0
14126 glCopyImageSubDataEXT(tex, GL_TEXTURE_3D, 1, 0, 0, 1, tex, GL_TEXTURE_3D, 1, 0, 0, 0,
14127 kWidth >> 1, kHeight >> 1, 1);
14128 ASSERT_GL_NO_ERROR();
14129
14130 // Copy level 0, slice 3, 4 to level 0, slice 1, 2
14131 glCopyImageSubDataEXT(tex, GL_TEXTURE_3D, 0, 0, 0, 3, tex, GL_TEXTURE_3D, 0, 0, 0, 1, kWidth,
14132 kHeight, 2);
14133 ASSERT_GL_NO_ERROR();
14134
14135 // Partially copy level 1, slice 1 to level 0, slice 3
14136 glCopyImageSubDataEXT(tex, GL_TEXTURE_3D, 1, kWidth / 8, kHeight / 8, 1, tex, GL_TEXTURE_3D, 0,
14137 kWidth / 4, kHeight / 4, 3, kWidth / 4, kHeight / 4, 1);
14138 ASSERT_GL_NO_ERROR();
14139
14140 // Verify colors
14141 GLFramebuffer FBO;
14142 glBindFramebuffer(GL_FRAMEBUFFER, FBO);
14143 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0);
14144 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14145
14146 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
14147 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
14148
14149 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
14150 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
14151
14152 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 3);
14153 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight / 4, GLColor::red);
14154 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 4, kHeight, GLColor::red);
14155 EXPECT_PIXEL_RECT_EQ(0, kHeight / 4 + kHeight / 4, kWidth,
14156 kHeight - (kHeight / 4 + kHeight / 4), GLColor::red);
14157 EXPECT_PIXEL_RECT_EQ(kWidth / 4 + kWidth / 4, 0, kWidth - (kWidth / 4 + kWidth / 4), kHeight,
14158 GLColor::red);
14159 EXPECT_PIXEL_RECT_EQ(kWidth / 4, kHeight / 4, kWidth / 4, kHeight / 4, GLColor::blue);
14160
14161 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 4);
14162 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
14163
14164 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 0);
14165 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
14166
14167 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 1, 1);
14168 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth >> 1, kHeight >> 1, GLColor::blue);
14169 ASSERT_GL_NO_ERROR();
14170 }
14171
14172 class TextureChangeStorageUploadTest : public ANGLETest<>
14173 {
14174 protected:
TextureChangeStorageUploadTest()14175 TextureChangeStorageUploadTest()
14176 {
14177 setWindowWidth(256);
14178 setWindowHeight(256);
14179 setConfigRedBits(8);
14180 setConfigGreenBits(8);
14181 setConfigBlueBits(8);
14182 setConfigAlphaBits(8);
14183 }
14184
testSetUp()14185 void testSetUp() override
14186 {
14187 mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
14188 if (mProgram == 0)
14189 {
14190 FAIL() << "shader compilation failed.";
14191 }
14192
14193 glUseProgram(mProgram);
14194
14195 glClearColor(0, 0, 0, 0);
14196 glClearDepthf(0.0);
14197 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
14198
14199 glEnable(GL_BLEND);
14200 glDisable(GL_DEPTH_TEST);
14201
14202 glGenTextures(1, &mTexture);
14203 ASSERT_GL_NO_ERROR();
14204 }
14205
testTearDown()14206 void testTearDown() override
14207 {
14208 glDeleteTextures(1, &mTexture);
14209 glDeleteProgram(mProgram);
14210 }
14211
14212 GLuint mProgram;
14213 GLint mColorLocation;
14214 GLuint mTexture;
14215 };
14216
14217 // Verify that respecifying storage and re-uploading doesn't crash.
TEST_P(TextureChangeStorageUploadTest,Basic)14218 TEST_P(TextureChangeStorageUploadTest, Basic)
14219 {
14220 constexpr int kImageSize = 8; // 4 doesn't trip ASAN
14221 constexpr int kSmallerImageSize = kImageSize / 2;
14222 EXPECT_GT(kImageSize, kSmallerImageSize);
14223 EXPECT_GT(kSmallerImageSize / 2, 0);
14224
14225 std::array<GLColor, kImageSize * kImageSize> kColor;
14226
14227 glBindTexture(GL_TEXTURE_2D, mTexture);
14228 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
14229 kColor.data());
14230 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSmallerImageSize, kSmallerImageSize);
14231 // need partial update to sidestep optimizations that remove the full upload
14232 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSmallerImageSize / 2, kSmallerImageSize / 2, GL_RGBA,
14233 GL_UNSIGNED_BYTE, kColor.data());
14234 EXPECT_GL_NO_ERROR();
14235 }
14236
14237 class ExtraSamplerCubeShadowUseTest : public ANGLETest<>
14238 {
14239 protected:
ExtraSamplerCubeShadowUseTest()14240 ExtraSamplerCubeShadowUseTest() : ANGLETest() {}
14241
getVertexShaderSource()14242 const char *getVertexShaderSource() { return "#version 300 es\nvoid main() {}"; }
14243
getFragmentShaderSource()14244 const char *getFragmentShaderSource()
14245 {
14246 return R"(#version 300 es
14247 precision mediump float;
14248
14249 uniform mediump samplerCube var_0002; // this has to be there
14250 uniform highp samplerCubeShadow var_0004; // this has to be a cube shadow sampler
14251 out vec4 color;
14252 void main() {
14253
14254 vec4 var_0031 = texture(var_0002, vec3(1,1,1));
14255 ivec2 size = textureSize(var_0004, 0) ;
14256 var_0031.x += float(size.y);
14257
14258 color = var_0031;
14259 })";
14260 }
14261
testSetUp()14262 void testSetUp() override
14263 {
14264 mProgram = CompileProgram(getVertexShaderSource(), getFragmentShaderSource());
14265 if (mProgram == 0)
14266 {
14267 FAIL() << "shader compilation failed.";
14268 }
14269 glUseProgram(mProgram);
14270 ASSERT_GL_NO_ERROR();
14271 }
14272
testTearDown()14273 void testTearDown() override { glDeleteProgram(mProgram); }
14274
14275 GLuint mProgram;
14276 };
14277
TEST_P(ExtraSamplerCubeShadowUseTest,Basic)14278 TEST_P(ExtraSamplerCubeShadowUseTest, Basic)
14279 {
14280 glDrawArrays(GL_TRIANGLE_FAN, 0, 3);
14281 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
14282 }
14283
14284 // Tests covering RBG->RGBA emulation path
14285 class RGBTextureBufferTestES31 : public ANGLETest<>
14286 {
14287 protected:
RGBTextureBufferTestES31()14288 RGBTextureBufferTestES31()
14289 {
14290 setWindowWidth(128);
14291 setWindowHeight(128);
14292 setConfigRedBits(8);
14293 setConfigGreenBits(8);
14294 setConfigBlueBits(8);
14295 setConfigAlphaBits(8);
14296 }
14297 void TestInt(GLuint format);
14298 };
14299
SetupTextureBufferDrawProgram(GLProgram & program,GLuint format)14300 void SetupTextureBufferDrawProgram(GLProgram &program, GLuint format)
14301 {
14302 constexpr char kVS[] = R"(#version 310 es
14303 precision highp float;
14304 in vec4 inputAttribute;
14305
14306 void main()
14307 {
14308 gl_Position = inputAttribute;
14309 })";
14310
14311 if (format == GL_RGB32UI)
14312 {
14313 constexpr char kFS[] = R"(#version 310 es
14314 #extension GL_EXT_texture_buffer : require
14315 precision mediump float;
14316 uniform highp usamplerBuffer tex;
14317 layout(location = 0) out mediump vec4 color;
14318
14319 void main()
14320 {
14321 uvec4 v = texelFetch(tex, 1);
14322 color = vec4(float(v.r)/255.0, float(v.g)/255.0, float(v.b)/255.0, v.a);
14323 })";
14324 program.makeRaster(kVS, kFS);
14325 }
14326 if (format == GL_RGB32I)
14327 {
14328 constexpr char kFS[] = R"(#version 310 es
14329 #extension GL_EXT_texture_buffer : require
14330 precision mediump float;
14331 uniform highp isamplerBuffer tex;
14332 layout(location = 0) out mediump vec4 color;
14333
14334 void main()
14335 {
14336 ivec4 v = texelFetch(tex, 1);
14337 color = vec4(float(v.r)/255.0, float(v.g)/255.0, float(v.b)/255.0, v.a);
14338 })";
14339 program.makeRaster(kVS, kFS);
14340 }
14341 if (format == GL_RGB32F)
14342 {
14343 constexpr char kFS[] = R"(#version 310 es
14344 #extension GL_EXT_texture_buffer : require
14345 precision mediump float;
14346 uniform highp samplerBuffer tex;
14347 layout(location = 0) out mediump vec4 color;
14348
14349 void main()
14350 {
14351 vec4 v = texelFetch(tex, 1);
14352 color = vec4(float(v.r)/255.0, float(v.g)/255.0, float(v.b)/255.0, v.a);
14353 })";
14354 program.makeRaster(kVS, kFS);
14355 }
14356 ASSERT_TRUE(program.valid());
14357 }
14358
TestInt(GLuint format)14359 void RGBTextureBufferTestES31::TestInt(GLuint format)
14360 {
14361 const GLint pixelSize = sizeof(GLuint) * 3;
14362
14363 // Offset must be aligned to GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT (16, 64, ...)
14364 GLint offsetAlignment = 0;
14365 glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &offsetAlignment);
14366 ASSERT(offsetAlignment % sizeof(GLuint) == 0);
14367 GLint byteOffset = ((pixelSize * 2) / offsetAlignment + 1) * offsetAlignment;
14368
14369 GLint intOffset = byteOffset / sizeof(GLuint);
14370
14371 std::vector<GLuint> texData(intOffset + 3 * 2);
14372
14373 // first texel(1) col
14374 GLColor col = MakeGLColor(11, 22, 33, 255);
14375 texData[3] = col.R;
14376 texData[4] = col.G;
14377 texData[5] = col.B;
14378
14379 // second texel(1) col2
14380 GLColor col2 = MakeGLColor(44, 55, 66, 255);
14381 texData[intOffset + 3] = col2.R;
14382 texData[intOffset + 4] = col2.G;
14383 texData[intOffset + 5] = col2.B;
14384
14385 GLTexture texture;
14386 glBindTexture(GL_TEXTURE_BUFFER, texture);
14387
14388 GLBuffer buffer;
14389 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
14390 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * texData.size(), texData.data(),
14391 GL_STATIC_DRAW);
14392 ASSERT_GL_NO_ERROR();
14393
14394 GLProgram program;
14395 SetupTextureBufferDrawProgram(program, format);
14396
14397 glTexBufferEXT(GL_TEXTURE_BUFFER, format, buffer);
14398
14399 drawQuad(program, "inputAttribute", 0.5f);
14400 ASSERT_GL_NO_ERROR();
14401 EXPECT_PIXEL_COLOR_NEAR(0, 0, col, 1);
14402
14403 glTexBufferRangeEXT(GL_TEXTURE_BUFFER, format, buffer, byteOffset, pixelSize * 2);
14404 ASSERT_GL_NO_ERROR();
14405 drawQuad(program, "inputAttribute", 0.5f);
14406 EXPECT_PIXEL_COLOR_NEAR(0, 0, col2, 1);
14407
14408 // Now update the buffer to check the converted data also gets updated.
14409 GLColor colUpd = MakeGLColor(77, 88, 99, 255);
14410 GLuint texDataUpd[] = {0, 0, 0, colUpd.R, colUpd.G, colUpd.B}; // second texel(1) colUpd
14411 glBufferSubData(GL_TEXTURE_BUFFER, byteOffset, sizeof(texDataUpd), texDataUpd);
14412 ASSERT_GL_NO_ERROR();
14413 drawQuad(program, "inputAttribute", 0.5f);
14414 EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd, 1);
14415
14416 // Update with glMapBuffer (hits a different code path...)
14417 GLColor colUpd2 = MakeGLColor(111, 122, 133, 255);
14418 GLuint texDataUpd2[] = {0, 0, 0, colUpd2.R, colUpd2.G, colUpd2.B}; // second texel(1) colUpd2
14419 void *mappedBuffer =
14420 glMapBufferRange(GL_TEXTURE_BUFFER, byteOffset, sizeof(texDataUpd2), GL_MAP_WRITE_BIT);
14421 memcpy(mappedBuffer, texDataUpd2, sizeof(texDataUpd2));
14422 glUnmapBuffer(GL_TEXTURE_BUFFER);
14423 ASSERT_GL_NO_ERROR();
14424 drawQuad(program, "inputAttribute", 0.5f);
14425 EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd2, 1);
14426 }
14427
14428 // Tests GL_RGB32UI texture buffer
TEST_P(RGBTextureBufferTestES31,Uint)14429 TEST_P(RGBTextureBufferTestES31, Uint)
14430 {
14431 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
14432
14433 TestInt(GL_RGB32UI);
14434 }
14435
14436 // Tests GL_RGB32I texture buffer
TEST_P(RGBTextureBufferTestES31,Sint)14437 TEST_P(RGBTextureBufferTestES31, Sint)
14438 {
14439 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
14440
14441 TestInt(GL_RGB32I);
14442 }
14443
14444 // Tests GL_RGB32F texture buffer
TEST_P(RGBTextureBufferTestES31,Float)14445 TEST_P(RGBTextureBufferTestES31, Float)
14446 {
14447 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
14448
14449 // first texel(1) col
14450 GLColor col = MakeGLColor(11, 22, 33, 255);
14451 GLfloat texData[6]{};
14452 texData[3] = col.R;
14453 texData[4] = col.G;
14454 texData[5] = col.B;
14455
14456 GLTexture texture;
14457 glBindTexture(GL_TEXTURE_BUFFER, texture);
14458
14459 GLBuffer buffer;
14460 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
14461 glBufferData(GL_TEXTURE_BUFFER, sizeof(texData), texData, GL_STATIC_DRAW);
14462 ASSERT_GL_NO_ERROR();
14463
14464 GLProgram program;
14465 SetupTextureBufferDrawProgram(program, GL_RGB32F);
14466
14467 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGB32F, buffer);
14468
14469 drawQuad(program, "inputAttribute", 0.5f);
14470 ASSERT_GL_NO_ERROR();
14471 EXPECT_PIXEL_COLOR_NEAR(0, 0, col, 1);
14472
14473 // Now update the buffer to check the converted data also gets updated.
14474 GLColor colUpd = MakeGLColor(77, 88, 99, 255);
14475 GLfloat texDataUpd[6]{};
14476 texDataUpd[3] = colUpd.R;
14477 texDataUpd[4] = colUpd.G;
14478 texDataUpd[5] = colUpd.B;
14479 glBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(texDataUpd), texDataUpd);
14480 ASSERT_GL_NO_ERROR();
14481 drawQuad(program, "inputAttribute", 0.5f);
14482 EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd, 1);
14483
14484 // Update with glMapBuffer (hits a different code path...)
14485 GLColor colUpd2 = MakeGLColor(111, 122, 133, 255);
14486 GLfloat texDataUpd2[6]{};
14487 texDataUpd2[3] = colUpd2.R;
14488 texDataUpd2[4] = colUpd2.G;
14489 texDataUpd2[5] = colUpd2.B;
14490 void *mappedBuffer =
14491 glMapBufferRange(GL_TEXTURE_BUFFER, 0, sizeof(texDataUpd2), GL_MAP_WRITE_BIT);
14492 memcpy(mappedBuffer, texDataUpd2, sizeof(texDataUpd2));
14493 glUnmapBuffer(GL_TEXTURE_BUFFER);
14494 ASSERT_GL_NO_ERROR();
14495 drawQuad(program, "inputAttribute", 0.5f);
14496 EXPECT_PIXEL_COLOR_NEAR(0, 0, colUpd2, 1);
14497 }
14498
SetupSSBOProgram(GLProgram & program)14499 void SetupSSBOProgram(GLProgram &program)
14500 {
14501 constexpr char kVS[] = R"(#version 310 es
14502 precision highp float;
14503 in vec4 inputAttribute;
14504
14505 void main()
14506 {
14507 gl_Position = inputAttribute;
14508 })";
14509
14510 constexpr char kFS[] = R"(#version 310 es
14511 layout(location = 0) out mediump vec4 color;
14512 layout(std140, binding = 0) buffer outBlock {
14513 uvec4 data[2]; // uvec4 to avoid padding
14514 };
14515 void main (void)
14516 {
14517 data[0] = uvec4(11u, 22u, 33u, 44u);
14518 data[1] = uvec4(55u, 66u, 0u, 0u);
14519 color = vec4(0);
14520 })";
14521
14522 program.makeRaster(kVS, kFS);
14523 ASSERT_TRUE(program.valid());
14524 }
14525
14526 // Tests RGB32 texture buffer with a SSBO write
TEST_P(RGBTextureBufferTestES31,SSBOWrite)14527 TEST_P(RGBTextureBufferTestES31, SSBOWrite)
14528 {
14529 GLProgram programSSBO;
14530 SetupSSBOProgram(programSSBO);
14531
14532 GLProgram programBufferDraw;
14533 SetupTextureBufferDrawProgram(programBufferDraw, GL_RGB32UI);
14534
14535 constexpr GLint kBufferSize = 2 * 4 * sizeof(GLuint);
14536 GLBuffer buffer;
14537 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
14538 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
14539 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, 0, kBufferSize);
14540
14541 drawQuad(programSSBO, "inputAttribute", 0.5f);
14542 ASSERT_GL_NO_ERROR();
14543
14544 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
14545
14546 glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGB32UI, buffer);
14547 drawQuad(programBufferDraw, "inputAttribute", 0.5f);
14548 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(44, 55, 66, 255), 1);
14549 }
14550
14551 class TextureTestES31 : public ANGLETest<>
14552 {
14553 protected:
TextureTestES31()14554 TextureTestES31()
14555 {
14556 setWindowWidth(128);
14557 setWindowHeight(128);
14558 setConfigRedBits(8);
14559 setConfigGreenBits(8);
14560 setConfigBlueBits(8);
14561 setConfigAlphaBits(8);
14562 }
14563 };
14564
14565 // Verify that image uniforms can link in separable programs
TEST_P(TextureTestES31,LinkedImageUniforms)14566 TEST_P(TextureTestES31, LinkedImageUniforms)
14567 {
14568 ANGLE_SKIP_TEST_IF(!IsVulkan());
14569
14570 GLint maxVertexImageUniforms;
14571 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
14572 ANGLE_SKIP_TEST_IF(maxVertexImageUniforms == 0);
14573
14574 constexpr char kVS[] = R"(#version 310 es
14575 precision highp float;
14576 precision highp image2D;
14577 layout(binding = 0, r32f) uniform image2D img;
14578
14579 void main()
14580 {
14581 vec2 position = -imageLoad(img, ivec2(0, 0)).rr;
14582 if (gl_VertexID == 1)
14583 position = vec2(3, -1);
14584 else if (gl_VertexID == 2)
14585 position = vec2(-1, 3);
14586
14587 gl_Position = vec4(position, 0, 1);
14588 })";
14589
14590 constexpr char kFS[] = R"(#version 310 es
14591 precision highp float;
14592 precision highp image2D;
14593 layout(binding = 0, r32f) uniform image2D img;
14594 layout(location = 0) out vec4 color;
14595
14596 void main()
14597 {
14598 color = imageLoad(img, ivec2(0, 0));
14599 })";
14600
14601 ANGLE_GL_PROGRAM(program, kVS, kFS);
14602
14603 GLTexture texture;
14604 GLfloat value = 1.0;
14605
14606 glBindTexture(GL_TEXTURE_2D, texture);
14607 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
14608 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &value);
14609 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
14610 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
14611
14612 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F);
14613
14614 glUseProgram(program);
14615 glDrawArrays(GL_TRIANGLES, 0, 3);
14616
14617 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
14618 ASSERT_GL_NO_ERROR();
14619 }
14620
14621 // Test that layer-related parameters are ignored when binding a 2D texture
TEST_P(TextureTestES31,Texture2DLayered)14622 TEST_P(TextureTestES31, Texture2DLayered)
14623 {
14624 constexpr char kFS[] = R"(#version 310 es
14625 precision highp float;
14626 precision highp image2D;
14627 layout(binding = 0, r32f) uniform image2D img;
14628 layout(location = 0) out vec4 color;
14629
14630 void main()
14631 {
14632 color = imageLoad(img, ivec2(0, 0));
14633 })";
14634
14635 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
14636
14637 GLTexture texture;
14638 GLfloat value = 1.0;
14639
14640 glBindTexture(GL_TEXTURE_2D, texture);
14641 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
14642 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &value);
14643 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
14644 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
14645
14646 glClearColor(0.0, 1.0, 0.0, 1.0);
14647 for (const bool layered : {true, false})
14648 {
14649 for (const GLint layer : {0, 1})
14650 {
14651 glClear(GL_COLOR_BUFFER_BIT);
14652 glBindImageTexture(0, texture, 0, layered, layer, GL_READ_ONLY, GL_R32F);
14653 ASSERT_GL_NO_ERROR();
14654
14655 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14656 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red)
14657 << "Layered: " << (layered ? "true" : "false") << ", Layer: " << layer;
14658 }
14659 }
14660 }
14661
14662 // Test that rebinding the shader image level without changing the program works
TEST_P(TextureTestES31,Texture2DChangeLevel)14663 TEST_P(TextureTestES31, Texture2DChangeLevel)
14664 {
14665 constexpr char kFS[] = R"(#version 310 es
14666 precision highp float;
14667 precision highp image2D;
14668 layout(binding = 0, r32f) uniform image2D img;
14669 layout(location = 0) out vec4 color;
14670
14671 void main()
14672 {
14673 color = imageLoad(img, ivec2(0, 0));
14674 })";
14675 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
14676
14677 // Must be active before calling drawQuad to avoid program switches
14678 glUseProgram(program);
14679
14680 GLTexture texture;
14681 const GLfloat level0[4] = {0.5, 0.5, 0.5, 0.5};
14682 const GLfloat level1[1] = {1.0};
14683
14684 glBindTexture(GL_TEXTURE_2D, texture);
14685 glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32F, 2, 2);
14686 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RED, GL_FLOAT, level0);
14687 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 1, 1, GL_RED, GL_FLOAT, level1);
14688 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
14689 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
14690
14691 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
14692 ASSERT_GL_NO_ERROR();
14693 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14694 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 0, 255), 1);
14695
14696 glBindImageTexture(0, texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
14697 ASSERT_GL_NO_ERROR();
14698 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14699 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
14700 }
14701
14702 // Test that rebinding the shader image layer/level without changing the program works
TEST_P(TextureTestES31,Texture2DArrayChangeLayerLevel)14703 TEST_P(TextureTestES31, Texture2DArrayChangeLayerLevel)
14704 {
14705 constexpr char kFS[] = R"(#version 310 es
14706 precision highp float;
14707 precision highp image2D;
14708 layout(binding = 0, r32f) uniform image2D img;
14709 layout(location = 0) out vec4 color;
14710
14711 void main()
14712 {
14713 color = imageLoad(img, ivec2(0, 0));
14714 })";
14715 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
14716
14717 // Must be active before calling drawQuad to avoid program switches
14718 glUseProgram(program);
14719
14720 GLTexture texture;
14721 const GLfloat level0layer0[4] = {0.25, 0.25, 0.25, 0.25};
14722 const GLfloat level0layer1[4] = {0.50, 0.50, 0.50, 0.50};
14723 const GLfloat level1layer0[1] = {0.75};
14724 const GLfloat level1layer1[1] = {1.00};
14725
14726 glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
14727 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 2, 2, 2);
14728 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 2, 2, 1, GL_RED, GL_FLOAT, level0layer0);
14729 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 2, 2, 1, GL_RED, GL_FLOAT, level0layer1);
14730 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, 1, 1, 1, GL_RED, GL_FLOAT, level1layer0);
14731 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 1, 1, 1, 1, GL_RED, GL_FLOAT, level1layer1);
14732 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
14733 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
14734
14735 // Level 0, layer 0
14736 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
14737 ASSERT_GL_NO_ERROR();
14738 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14739 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(63, 0, 0, 255), 1);
14740
14741 // Level 0, layer 1
14742 glBindImageTexture(0, texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_R32F);
14743 ASSERT_GL_NO_ERROR();
14744 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14745 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 0, 255), 1);
14746
14747 // Level 1, layer 0
14748 glBindImageTexture(0, texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
14749 ASSERT_GL_NO_ERROR();
14750 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14751 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(191, 0, 0, 255), 1);
14752
14753 // Level 1, layer 1
14754 glBindImageTexture(0, texture, 1, GL_FALSE, 1, GL_READ_WRITE, GL_R32F);
14755 ASSERT_GL_NO_ERROR();
14756 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14757 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 0, 0, 255), 1);
14758 }
14759
14760 // Test that switching between a 2D texture and a layer of a 2D array texture works
TEST_P(TextureTestES31,Texture2DTo2DArraySwitch)14761 TEST_P(TextureTestES31, Texture2DTo2DArraySwitch)
14762 {
14763 constexpr char kFS[] = R"(#version 310 es
14764 precision highp float;
14765 precision highp image2D;
14766 layout(binding = 0, r32f) uniform image2D img;
14767 layout(location = 0) out vec4 color;
14768
14769 void main()
14770 {
14771 color = imageLoad(img, ivec2(0, 0));
14772 })";
14773 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
14774
14775 // Must be active before calling drawQuad to avoid program switches
14776 glUseProgram(program);
14777
14778 GLTexture texture2D;
14779 GLTexture texture2DArray;
14780 const GLfloat data2D[1] = {0.50};
14781 const GLfloat data2DArray0[1] = {0.25};
14782 const GLfloat data2DArray1[1] = {0.75};
14783
14784 glBindTexture(GL_TEXTURE_2D, texture2D);
14785 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
14786 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, data2D);
14787 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
14788 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
14789
14790 glBindTexture(GL_TEXTURE_2D_ARRAY, texture2DArray);
14791 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 1, 1, 2);
14792 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 1, 1, 1, GL_RED, GL_FLOAT, data2DArray0);
14793 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 1, 1, 1, GL_RED, GL_FLOAT, data2DArray1);
14794 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
14795 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
14796
14797 // Texture2D
14798 glBindImageTexture(0, texture2D, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
14799 ASSERT_GL_NO_ERROR();
14800 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14801 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 0, 255), 1);
14802
14803 // Texture2D array, layer 0
14804 glBindImageTexture(0, texture2DArray, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
14805 ASSERT_GL_NO_ERROR();
14806 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14807 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(63, 0, 0, 255), 1);
14808
14809 // Texture2D again
14810 glBindImageTexture(0, texture2D, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
14811 ASSERT_GL_NO_ERROR();
14812 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14813 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 0, 255), 1);
14814
14815 // Texture2D array, layer 1
14816 glBindImageTexture(0, texture2DArray, 0, GL_FALSE, 1, GL_READ_WRITE, GL_R32F);
14817 ASSERT_GL_NO_ERROR();
14818 drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
14819 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(191, 0, 0, 255), 1);
14820 }
14821
14822 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
14823 // tests should be run against.
14824 #define ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB() \
14825 ES2_OPENGL().enable(Feature::EmulateCopyTexImage2D), \
14826 ES2_OPENGLES().enable(Feature::EmulateCopyTexImage2D)
14827 #define ES3_EMULATE_COPY_TEX_IMAGE_VIA_SUB() \
14828 ES3_OPENGL().enable(Feature::EmulateCopyTexImage2D), \
14829 ES3_OPENGLES().enable(Feature::EmulateCopyTexImage2D)
14830 #define ES2_EMULATE_COPY_TEX_IMAGE() \
14831 ES2_OPENGL().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers), \
14832 ES2_OPENGLES().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers)
14833 #define ES3_EMULATE_COPY_TEX_IMAGE() \
14834 ES3_OPENGL().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers), \
14835 ES3_OPENGLES().enable(Feature::EmulateCopyTexImage2DFromRenderbuffers)
14836 ANGLE_INSTANTIATE_TEST(Texture2DTest,
14837 ANGLE_ALL_TEST_PLATFORMS_ES2,
14838 ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB(),
14839 ES2_EMULATE_COPY_TEX_IMAGE(),
14840 ES2_WEBGPU());
14841 ANGLE_INSTANTIATE_TEST_ES2(TextureCubeTest);
14842 ANGLE_INSTANTIATE_TEST_ES2(Texture2DTestWithDrawScale);
14843 ANGLE_INSTANTIATE_TEST_ES2(Sampler2DAsFunctionParameterTest);
14844 ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayTest);
14845 ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayAsFunctionParameterTest);
14846
14847 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3);
14848 ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DTestES3,
14849 ES3_VULKAN().enable(Feature::AllocateNonZeroMemory),
14850 ES3_VULKAN().enable(Feature::ForceFallbackFormat));
14851
14852 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DMemoryTestES3);
14853 ANGLE_INSTANTIATE_TEST_ES3(Texture2DMemoryTestES3);
14854
14855 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3YUV);
14856 ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DTestES3YUV,
14857 ES3_VULKAN().enable(Feature::PreferLinearFilterForYUV),
14858 ES3_VULKAN().enable(Feature::DisableProgramCaching));
14859
14860 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3RobustInit);
14861 ANGLE_INSTANTIATE_TEST_ES3(Texture2DTestES3RobustInit);
14862
14863 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES3Foveation);
14864 ANGLE_INSTANTIATE_TEST_ES3(Texture2DTestES3Foveation);
14865
14866 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES31Foveation);
14867 ANGLE_INSTANTIATE_TEST_ES31(Texture2DTestES31Foveation);
14868
14869 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DTestES31PPO);
14870 ANGLE_INSTANTIATE_TEST_ES31(Texture2DTestES31PPO);
14871
14872 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DBaseMaxTestES3);
14873 ANGLE_INSTANTIATE_TEST_ES3(Texture2DBaseMaxTestES3);
14874
14875 ANGLE_INSTANTIATE_TEST_ES2(Texture3DTestES2);
14876
14877 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture3DTestES3);
14878 ANGLE_INSTANTIATE_TEST_ES3(Texture3DTestES3);
14879
14880 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DIntegerAlpha1TestES3);
14881 ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerAlpha1TestES3);
14882
14883 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DUnsignedIntegerAlpha1TestES3);
14884 ANGLE_INSTANTIATE_TEST_ES3(Texture2DUnsignedIntegerAlpha1TestES3);
14885
14886 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ShadowSamplerPlusSampler3DTestES3);
14887 ANGLE_INSTANTIATE_TEST_ES3(ShadowSamplerPlusSampler3DTestES3);
14888
14889 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SamplerTypeMixTestES3);
14890 ANGLE_INSTANTIATE_TEST_ES3(SamplerTypeMixTestES3);
14891
14892 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DArrayTestES3);
14893 ANGLE_INSTANTIATE_TEST_ES3(Texture2DArrayTestES3);
14894
14895 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureSizeTextureArrayTest);
14896 ANGLE_INSTANTIATE_TEST_ES3(TextureSizeTextureArrayTest);
14897
14898 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructTest);
14899 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructAsFunctionParameterTest);
14900 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructArrayAsFunctionParameterTest);
14901 ANGLE_INSTANTIATE_TEST_ES2(SamplerInNestedStructAsFunctionParameterTest);
14902 ANGLE_INSTANTIATE_TEST_ES2(SamplerInStructAndOtherVariableTest);
14903 ANGLE_INSTANTIATE_TEST_ES2(TextureAnisotropyTest);
14904 ANGLE_INSTANTIATE_TEST_ES2(TextureBorderClampTest);
14905
14906 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBorderClampTestES3);
14907 ANGLE_INSTANTIATE_TEST_ES3(TextureBorderClampTestES3);
14908
14909 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBorderClampIntegerTestES3);
14910 ANGLE_INSTANTIATE_TEST_ES3(TextureBorderClampIntegerTestES3);
14911
14912 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(TextureMirrorClampToEdgeTest);
14913
14914 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureMirrorClampToEdgeTestES3);
14915 ANGLE_INSTANTIATE_TEST_ES3(TextureMirrorClampToEdgeTestES3);
14916
14917 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureMirrorClampToEdgeIntegerTestES3);
14918 ANGLE_INSTANTIATE_TEST_ES3(TextureMirrorClampToEdgeIntegerTestES3);
14919
14920 ANGLE_INSTANTIATE_TEST_ES2(TextureLimitsTest);
14921
14922 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DNorm16TestES3);
14923 ANGLE_INSTANTIATE_TEST_ES3(Texture2DNorm16TestES3);
14924
14925 ANGLE_INSTANTIATE_TEST(Texture2DRGTest,
14926 ANGLE_ALL_TEST_PLATFORMS_ES2,
14927 ANGLE_ALL_TEST_PLATFORMS_ES3,
14928 ES2_EMULATE_COPY_TEX_IMAGE_VIA_SUB(),
14929 ES3_EMULATE_COPY_TEX_IMAGE_VIA_SUB(),
14930 ES2_EMULATE_COPY_TEX_IMAGE(),
14931 ES3_EMULATE_COPY_TEX_IMAGE());
14932
14933 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DFloatTestES3);
14934 ANGLE_INSTANTIATE_TEST_ES3(Texture2DFloatTestES3);
14935
14936 ANGLE_INSTANTIATE_TEST_ES2(Texture2DFloatTestES2);
14937
14938 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeTestES3);
14939 ANGLE_INSTANTIATE_TEST_ES3(TextureCubeTestES3);
14940
14941 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DIntegerTestES3);
14942 ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerTestES3);
14943
14944 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeIntegerTestES3);
14945 ANGLE_INSTANTIATE_TEST_ES3(TextureCubeIntegerTestES3);
14946
14947 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureCubeIntegerEdgeTestES3);
14948 ANGLE_INSTANTIATE_TEST_ES3(TextureCubeIntegerEdgeTestES3);
14949
14950 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DIntegerProjectiveOffsetTestES3);
14951 ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerProjectiveOffsetTestES3);
14952
14953 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DArrayIntegerTestES3);
14954 ANGLE_INSTANTIATE_TEST_ES3(Texture2DArrayIntegerTestES3);
14955
14956 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture3DIntegerTestES3);
14957 ANGLE_INSTANTIATE_TEST_ES3(Texture3DIntegerTestES3);
14958
14959 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(Texture2DDepthTest);
14960 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(PBOCompressedTextureTest);
14961 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ETC1CompressedTextureTest);
14962 ANGLE_INSTANTIATE_TEST_ES3(PBOCompressedTexture3DTest);
14963
14964 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureBufferTestES31);
14965 ANGLE_INSTANTIATE_TEST_ES31(TextureBufferTestES31);
14966
14967 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureTestES31);
14968 ANGLE_INSTANTIATE_TEST_ES31(TextureTestES31);
14969
14970 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CopyImageTestES31);
14971 ANGLE_INSTANTIATE_TEST_ES31(CopyImageTestES31);
14972
14973 ANGLE_INSTANTIATE_TEST_ES3(TextureChangeStorageUploadTest);
14974
14975 ANGLE_INSTANTIATE_TEST_ES3(ExtraSamplerCubeShadowUseTest);
14976
14977 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Texture2DDepthStencilTestES3);
14978 ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DDepthStencilTestES3,
14979 ES3_VULKAN().enable(Feature::ForceFallbackFormat));
14980
14981 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RGBTextureBufferTestES31);
14982 ANGLE_INSTANTIATE_TEST_ES31(RGBTextureBufferTestES31);
14983
14984 } // anonymous namespace
14985