1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // BPTCCompressedTextureTest.cpp: Tests of the GL_EXT_texture_compression_bptc extension
8
9 #include "test_utils/ANGLETest.h"
10 #include "test_utils/gl_raii.h"
11
12 using namespace angle;
13
14 namespace
15 {
16
17 const unsigned int kPixelTolerance = 1u;
18
19 // The pixel data represents a 4x4 pixel image with the left side colored red and the right side
20 // green. It was BC7 encoded using Microsoft's BC6HBC7Encoder.
21 const std::array<GLubyte, 16> kBC7Data4x4 = {0x50, 0x1f, 0xfc, 0xf, 0x0, 0xf0, 0xe3, 0xe1,
22 0xe1, 0xe1, 0xc1, 0xf, 0xfc, 0xc0, 0xf, 0xfc};
23
24 } // anonymous namespace
25
26 class BPTCCompressedTextureTest : public ANGLETest
27 {
28 protected:
BPTCCompressedTextureTest()29 BPTCCompressedTextureTest()
30 {
31 setWindowWidth(128);
32 setWindowHeight(128);
33 setConfigRedBits(8);
34 setConfigGreenBits(8);
35 setConfigBlueBits(8);
36 setConfigAlphaBits(8);
37 }
38
testSetUp()39 void testSetUp() override
40 {
41 constexpr char kVS[] = R"(precision highp float;
42 attribute vec4 position;
43 varying vec2 texcoord;
44
45 void main()
46 {
47 gl_Position = position;
48 texcoord = (position.xy * 0.5) + 0.5;
49 texcoord.y = 1.0 - texcoord.y;
50 })";
51
52 constexpr char kFS[] = R"(precision highp float;
53 uniform sampler2D tex;
54 varying vec2 texcoord;
55
56 void main()
57 {
58 gl_FragColor = texture2D(tex, texcoord);
59 })";
60
61 mTextureProgram = CompileProgram(kVS, kFS);
62 if (mTextureProgram == 0)
63 {
64 FAIL() << "shader compilation failed.";
65 }
66
67 mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
68
69 ASSERT_GL_NO_ERROR();
70 }
71
testTearDown()72 void testTearDown() override { glDeleteProgram(mTextureProgram); }
73
setupTextureParameters(GLuint texture)74 void setupTextureParameters(GLuint texture)
75 {
76 glBindTexture(GL_TEXTURE_2D, texture);
77 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
78 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
79 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
80 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
81 }
82
drawTexture()83 void drawTexture()
84 {
85 glUseProgram(mTextureProgram);
86 glUniform1i(mTextureUniformLocation, 0);
87 drawQuad(mTextureProgram, "position", 0.5f);
88 EXPECT_GL_NO_ERROR();
89 }
90
91 GLuint mTextureProgram;
92 GLint mTextureUniformLocation;
93 };
94
95 class BPTCCompressedTextureTestES3 : public BPTCCompressedTextureTest
96 {
97 public:
BPTCCompressedTextureTestES3()98 BPTCCompressedTextureTestES3() : BPTCCompressedTextureTest() {}
99 };
100
101 // Test sampling from a BC7 non-SRGB image.
TEST_P(BPTCCompressedTextureTest,CompressedTexImageBC7)102 TEST_P(BPTCCompressedTextureTest, CompressedTexImageBC7)
103 {
104 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc"));
105
106 GLTexture texture;
107 setupTextureParameters(texture);
108
109 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 0,
110 kBC7Data4x4.size(), kBC7Data4x4.data());
111
112 EXPECT_GL_NO_ERROR();
113
114 drawTexture();
115
116 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::red, kPixelTolerance);
117 EXPECT_PIXEL_COLOR_NEAR(0, getWindowHeight() - 1, GLColor::red, kPixelTolerance);
118 EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, 0, GLColor::green, kPixelTolerance);
119 EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green,
120 kPixelTolerance);
121 }
122
123 // Test sampling from a BC7 SRGB image.
TEST_P(BPTCCompressedTextureTest,CompressedTexImageBC7SRGB)124 TEST_P(BPTCCompressedTextureTest, CompressedTexImageBC7SRGB)
125 {
126 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc"));
127
128 GLTexture texture;
129 setupTextureParameters(texture);
130
131 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, 4, 4, 0,
132 kBC7Data4x4.size(), kBC7Data4x4.data());
133
134 EXPECT_GL_NO_ERROR();
135
136 drawTexture();
137
138 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::red, kPixelTolerance);
139 EXPECT_PIXEL_COLOR_NEAR(0, getWindowHeight() - 1, GLColor::red, kPixelTolerance);
140 EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, 0, GLColor::green, kPixelTolerance);
141 EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green,
142 kPixelTolerance);
143 }
144
145 // Test that using the BC6H floating point formats doesn't crash.
TEST_P(BPTCCompressedTextureTest,CompressedTexImageBC6HNoCrash)146 TEST_P(BPTCCompressedTextureTest, CompressedTexImageBC6HNoCrash)
147 {
148 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc"));
149
150 GLTexture texture;
151 setupTextureParameters(texture);
152
153 // This dummy pixel data represents a 4x4 pixel image.
154 // TODO(http://anglebug.com/2869): Add pixel tests for these formats. These need HDR source
155 // images.
156 std::vector<GLubyte> data;
157 data.resize(16u, 0u);
158
159 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, 4, 4, 0,
160 data.size(), data.data());
161 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, 4, 4, 0,
162 data.size(), data.data());
163
164 EXPECT_GL_NO_ERROR();
165
166 drawTexture();
167 }
168
169 // Test texStorage2D with a BPTC format.
TEST_P(BPTCCompressedTextureTestES3,CompressedTexStorage)170 TEST_P(BPTCCompressedTextureTestES3, CompressedTexStorage)
171 {
172 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc"));
173
174 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
175
176 GLTexture texture;
177 setupTextureParameters(texture);
178
179 glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4);
180 EXPECT_GL_NO_ERROR();
181 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT,
182 kBC7Data4x4.size(), kBC7Data4x4.data());
183 EXPECT_GL_NO_ERROR();
184
185 drawTexture();
186
187 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::red, kPixelTolerance);
188 EXPECT_PIXEL_COLOR_NEAR(0, getWindowHeight() - 1, GLColor::red, kPixelTolerance);
189 EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, 0, GLColor::green, kPixelTolerance);
190 EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green,
191 kPixelTolerance);
192 }
193
194 // Test validation of glCompressedTexSubImage2D with BPTC formats
TEST_P(BPTCCompressedTextureTest,CompressedTexSubImageValidation)195 TEST_P(BPTCCompressedTextureTest, CompressedTexSubImageValidation)
196 {
197 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc"));
198
199 GLTexture texture;
200 glBindTexture(GL_TEXTURE_2D, texture);
201
202 std::vector<GLubyte> data(16 * 2 * 2); // 2x2 blocks, thats 8x8 pixels.
203
204 // Size mip 0 to a large size.
205 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 8, 8, 0,
206 data.size(), data.data());
207 ASSERT_GL_NO_ERROR();
208
209 // Test a sub image with an offset that isn't a multiple of the block size.
210 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 1, 0, 4, 4, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT,
211 kBC7Data4x4.size(), kBC7Data4x4.data());
212 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
213 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 3, 4, 4, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT,
214 kBC7Data4x4.size(), kBC7Data4x4.data());
215 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
216
217 // Test a sub image with a negative offset.
218 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, -1, 0, 4, 4, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT,
219 kBC7Data4x4.size(), kBC7Data4x4.data());
220 ASSERT_GL_ERROR(GL_INVALID_VALUE);
221 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, -1, 4, 4, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT,
222 kBC7Data4x4.size(), kBC7Data4x4.data());
223 ASSERT_GL_ERROR(GL_INVALID_VALUE);
224 }
225
226 // Test that copying BPTC textures is not allowed. This restriction exists only in
227 // EXT_texture_compression_bptc, and not in the ARB variant.
TEST_P(BPTCCompressedTextureTest,CopyTexImage2DDisallowed)228 TEST_P(BPTCCompressedTextureTest, CopyTexImage2DDisallowed)
229 {
230 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc"));
231
232 GLTexture texture;
233 setupTextureParameters(texture);
234
235 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 0, 0, 4, 4, 0);
236 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
237 }
238
239 // Test that copying BPTC textures is not allowed. This restriction exists only in
240 // EXT_texture_compression_bptc, and not in the ARB variant.
TEST_P(BPTCCompressedTextureTest,CopyTexSubImage2DDisallowed)241 TEST_P(BPTCCompressedTextureTest, CopyTexSubImage2DDisallowed)
242 {
243 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc"));
244
245 GLTexture texture;
246 setupTextureParameters(texture);
247
248 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 0,
249 kBC7Data4x4.size(), kBC7Data4x4.data());
250 ASSERT_GL_NO_ERROR();
251
252 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 4, 4);
253 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
254 }
255
256 // Test that copying BPTC textures is not allowed. This restriction exists only in
257 // EXT_texture_compression_bptc, and not in the ARB variant.
TEST_P(BPTCCompressedTextureTestES3,CopyTexSubImage3DDisallowed)258 TEST_P(BPTCCompressedTextureTestES3, CopyTexSubImage3DDisallowed)
259 {
260 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc"));
261
262 GLTexture texture;
263 glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
264
265 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 1);
266 ASSERT_GL_NO_ERROR();
267
268 glCopyTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, 0, 4, 4);
269 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
270 }
271
272 // Test uploading texture data from a PBO to a texture.
TEST_P(BPTCCompressedTextureTestES3,PBOCompressedTexImage)273 TEST_P(BPTCCompressedTextureTestES3, PBOCompressedTexImage)
274 {
275 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc"));
276
277 GLTexture texture;
278 setupTextureParameters(texture);
279
280 GLBuffer buffer;
281 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
282 glBufferData(GL_PIXEL_UNPACK_BUFFER, kBC7Data4x4.size(), kBC7Data4x4.data(), GL_STREAM_DRAW);
283 ASSERT_GL_NO_ERROR();
284
285 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 0,
286 kBC7Data4x4.size(), nullptr);
287 ASSERT_GL_NO_ERROR();
288
289 drawTexture();
290
291 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::red, kPixelTolerance);
292 EXPECT_PIXEL_COLOR_NEAR(0, getWindowHeight() - 1, GLColor::red, kPixelTolerance);
293 EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, 0, GLColor::green, kPixelTolerance);
294 EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green,
295 kPixelTolerance);
296 }
297
298 // Test uploading texture data from a PBO to a texture allocated with texStorage2D.
TEST_P(BPTCCompressedTextureTestES3,PBOCompressedTexStorage)299 TEST_P(BPTCCompressedTextureTestES3, PBOCompressedTexStorage)
300 {
301 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc"));
302
303 GLTexture texture;
304 setupTextureParameters(texture);
305
306 glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4);
307 ASSERT_GL_NO_ERROR();
308
309 GLBuffer buffer;
310 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
311 glBufferData(GL_PIXEL_UNPACK_BUFFER, kBC7Data4x4.size(), kBC7Data4x4.data(), GL_STREAM_DRAW);
312 ASSERT_GL_NO_ERROR();
313
314 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT,
315 kBC7Data4x4.size(), nullptr);
316
317 ASSERT_GL_NO_ERROR();
318
319 drawTexture();
320
321 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::red, kPixelTolerance);
322 EXPECT_PIXEL_COLOR_NEAR(0, getWindowHeight() - 1, GLColor::red, kPixelTolerance);
323 EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, 0, GLColor::green, kPixelTolerance);
324 EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green,
325 kPixelTolerance);
326 }
327
328 // Test validation of glCompressedTexSubImage3D with BPTC formats
TEST_P(BPTCCompressedTextureTestES3,CompressedTexSubImage3DValidation)329 TEST_P(BPTCCompressedTextureTestES3, CompressedTexSubImage3DValidation)
330 {
331 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc"));
332
333 GLTexture texture;
334 glBindTexture(GL_TEXTURE_2D_ARRAY, texture.get());
335
336 std::vector<GLubyte> data(16 * 2 * 2); // 2x2x1 blocks, thats 8x8x1 pixels.
337
338 // Size mip 0 to a large size.
339 glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 8, 8, 1, 0,
340 data.size(), data.data());
341 ASSERT_GL_NO_ERROR();
342
343 // Test a sub image with an offset that isn't a multiple of the block size.
344 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 2, 0, 0, 4, 4, 1,
345 GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, kBC7Data4x4.size(),
346 kBC7Data4x4.data());
347 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
348 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 2, 0, 4, 4, 1,
349 GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, kBC7Data4x4.size(),
350 kBC7Data4x4.data());
351 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
352
353 // Test a sub image with a negative offset.
354 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, -1, 0, 0, 4, 4, 1,
355 GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, kBC7Data4x4.size(),
356 kBC7Data4x4.data());
357 ASSERT_GL_ERROR(GL_INVALID_VALUE);
358 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, -1, 0, 4, 4, 1,
359 GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, kBC7Data4x4.size(),
360 kBC7Data4x4.data());
361 ASSERT_GL_ERROR(GL_INVALID_VALUE);
362 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, -1, 4, 4, 1,
363 GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, kBC7Data4x4.size(),
364 kBC7Data4x4.data());
365 ASSERT_GL_ERROR(GL_INVALID_VALUE);
366 }
367
368 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
369 // tests should be run against.
370 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(BPTCCompressedTextureTest);
371
372 ANGLE_INSTANTIATE_TEST_ES3(BPTCCompressedTextureTestES3);
373