1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "test_utils/ANGLETest.h"
8 #include "test_utils/gl_raii.h"
9
10 #include "media/pixel.inc"
11
12 using namespace angle;
13
14 class DXT1CompressedTextureTest : public ANGLETest<>
15 {
16 protected:
DXT1CompressedTextureTest()17 DXT1CompressedTextureTest()
18 {
19 setWindowWidth(512);
20 setWindowHeight(512);
21 setConfigRedBits(8);
22 setConfigGreenBits(8);
23 setConfigBlueBits(8);
24 setConfigAlphaBits(8);
25 }
26
testSetUp()27 void testSetUp() override
28 {
29 constexpr char kVS[] = R"(precision highp float;
30 attribute vec4 position;
31 varying vec2 texcoord;
32
33 void main()
34 {
35 gl_Position = position;
36 texcoord = (position.xy * 0.5) + 0.5;
37 texcoord.y = 1.0 - texcoord.y;
38 })";
39
40 constexpr char kFS[] = R"(precision highp float;
41 uniform sampler2D tex;
42 varying vec2 texcoord;
43
44 void main()
45 {
46 gl_FragColor = texture2D(tex, texcoord);
47 })";
48
49 mTextureProgram = CompileProgram(kVS, kFS);
50 if (mTextureProgram == 0)
51 {
52 FAIL() << "shader compilation failed.";
53 }
54
55 mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
56
57 ASSERT_GL_NO_ERROR();
58 }
59
testTearDown()60 void testTearDown() override { glDeleteProgram(mTextureProgram); }
61
62 GLuint mTextureProgram;
63 GLint mTextureUniformLocation;
64 };
65
TEST_P(DXT1CompressedTextureTest,CompressedTexImage)66 TEST_P(DXT1CompressedTextureTest, CompressedTexImage)
67 {
68 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
69
70 GLuint texture;
71 glGenTextures(1, &texture);
72 glBindTexture(GL_TEXTURE_2D, texture);
73 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
74 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
75 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
76 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
77
78 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width,
79 pixel_0_height, 0, pixel_0_size, pixel_0_data);
80 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_1_width,
81 pixel_1_height, 0, pixel_1_size, pixel_1_data);
82 glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_2_width,
83 pixel_2_height, 0, pixel_2_size, pixel_2_data);
84 glCompressedTexImage2D(GL_TEXTURE_2D, 3, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_3_width,
85 pixel_3_height, 0, pixel_3_size, pixel_3_data);
86 glCompressedTexImage2D(GL_TEXTURE_2D, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_4_width,
87 pixel_4_height, 0, pixel_4_size, pixel_4_data);
88 glCompressedTexImage2D(GL_TEXTURE_2D, 5, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_5_width,
89 pixel_5_height, 0, pixel_5_size, pixel_5_data);
90 glCompressedTexImage2D(GL_TEXTURE_2D, 6, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_6_width,
91 pixel_6_height, 0, pixel_6_size, pixel_6_data);
92 glCompressedTexImage2D(GL_TEXTURE_2D, 7, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_7_width,
93 pixel_7_height, 0, pixel_7_size, pixel_7_data);
94 glCompressedTexImage2D(GL_TEXTURE_2D, 8, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_8_width,
95 pixel_8_height, 0, pixel_8_size, pixel_8_data);
96 glCompressedTexImage2D(GL_TEXTURE_2D, 9, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_9_width,
97 pixel_9_height, 0, pixel_9_size, pixel_9_data);
98
99 EXPECT_GL_NO_ERROR();
100
101 glUseProgram(mTextureProgram);
102 glUniform1i(mTextureUniformLocation, 0);
103
104 drawQuad(mTextureProgram, "position", 0.5f);
105
106 EXPECT_GL_NO_ERROR();
107
108 glDeleteTextures(1, &texture);
109
110 EXPECT_GL_NO_ERROR();
111 }
112
113 // Verify that DXT1 RGB textures have 1.0 alpha when sampled
TEST_P(DXT1CompressedTextureTest,DXT1Alpha)114 TEST_P(DXT1CompressedTextureTest, DXT1Alpha)
115 {
116 auto test = [&](const std::string &extName, GLenum format) {
117 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(extName));
118
119 // On platforms without native support for DXT1 RGB or texture swizzling (such as D3D or
120 // some Metal configurations), this test is allowed to succeed with transparent black
121 // instead of opaque black.
122 const bool opaque = !IsD3D() && !(IsMetal() && !IsMetalTextureSwizzleAvailable());
123
124 GLTexture texture;
125 glBindTexture(GL_TEXTURE_2D, texture);
126 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
127 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
128
129 // Image using pixels with the code for transparent black:
130 // "BLACK, if color0 <= color1 and code(x,y) == 3"
131 constexpr uint8_t CompressedImageDXT1[] = {0, 0, 0, 0, 255, 255, 255, 255};
132 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, 4, 4, 0, sizeof(CompressedImageDXT1),
133 CompressedImageDXT1);
134
135 EXPECT_GL_NO_ERROR();
136
137 glUseProgram(mTextureProgram);
138 glUniform1i(mTextureUniformLocation, 0);
139
140 constexpr GLint kDrawSize = 4;
141 // The image is one 4x4 block, make the viewport only 4x4.
142 glViewport(0, 0, kDrawSize, kDrawSize);
143
144 drawQuad(mTextureProgram, "position", 0.5f);
145
146 EXPECT_GL_NO_ERROR();
147
148 for (GLint y = 0; y < kDrawSize; y++)
149 {
150 for (GLint x = 0; x < kDrawSize; x++)
151 {
152 EXPECT_PIXEL_EQ(x, y, 0, 0, 0, opaque ? 255 : 0)
153 << "at (" << x << ", " << y << ") for " << extName;
154 }
155 }
156 };
157
158 test("GL_EXT_texture_compression_dxt1", GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
159 test("GL_EXT_texture_compression_s3tc_srgb", GL_COMPRESSED_SRGB_S3TC_DXT1_EXT);
160 }
161
TEST_P(DXT1CompressedTextureTest,CompressedTexStorage)162 TEST_P(DXT1CompressedTextureTest, CompressedTexStorage)
163 {
164 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
165
166 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
167 (!IsGLExtensionEnabled("GL_EXT_texture_storage") ||
168 !IsGLExtensionEnabled("GL_OES_rgb8_rgba8")));
169
170 GLuint texture;
171 glGenTextures(1, &texture);
172 glBindTexture(GL_TEXTURE_2D, texture);
173 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
175 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
176 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
177
178 if (getClientMajorVersion() < 3)
179 {
180 glTexStorage2DEXT(GL_TEXTURE_2D, pixel_levels, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
181 pixel_0_width, pixel_0_height);
182 }
183 else
184 {
185 glTexStorage2D(GL_TEXTURE_2D, pixel_levels, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width,
186 pixel_0_height);
187 }
188 EXPECT_GL_NO_ERROR();
189
190 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pixel_0_width, pixel_0_height,
191 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_size, pixel_0_data);
192 glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, pixel_1_width, pixel_1_height,
193 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_1_size, pixel_1_data);
194 glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, pixel_2_width, pixel_2_height,
195 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_2_size, pixel_2_data);
196 glCompressedTexSubImage2D(GL_TEXTURE_2D, 3, 0, 0, pixel_3_width, pixel_3_height,
197 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_3_size, pixel_3_data);
198 glCompressedTexSubImage2D(GL_TEXTURE_2D, 4, 0, 0, pixel_4_width, pixel_4_height,
199 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_4_size, pixel_4_data);
200 glCompressedTexSubImage2D(GL_TEXTURE_2D, 5, 0, 0, pixel_5_width, pixel_5_height,
201 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_5_size, pixel_5_data);
202 glCompressedTexSubImage2D(GL_TEXTURE_2D, 6, 0, 0, pixel_6_width, pixel_6_height,
203 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_6_size, pixel_6_data);
204 glCompressedTexSubImage2D(GL_TEXTURE_2D, 7, 0, 0, pixel_7_width, pixel_7_height,
205 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_7_size, pixel_7_data);
206 glCompressedTexSubImage2D(GL_TEXTURE_2D, 8, 0, 0, pixel_8_width, pixel_8_height,
207 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_8_size, pixel_8_data);
208 glCompressedTexSubImage2D(GL_TEXTURE_2D, 9, 0, 0, pixel_9_width, pixel_9_height,
209 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_9_size, pixel_9_data);
210
211 EXPECT_GL_NO_ERROR();
212
213 glUseProgram(mTextureProgram);
214 glUniform1i(mTextureUniformLocation, 0);
215
216 drawQuad(mTextureProgram, "position", 0.5f);
217
218 EXPECT_GL_NO_ERROR();
219
220 glDeleteTextures(1, &texture);
221
222 EXPECT_GL_NO_ERROR();
223 }
224
225 // Test validation of non block sizes, width 672 and height 114 and multiple mip levels
TEST_P(DXT1CompressedTextureTest,NonBlockSizesMipLevels)226 TEST_P(DXT1CompressedTextureTest, NonBlockSizesMipLevels)
227 {
228 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
229
230 GLTexture texture;
231 glBindTexture(GL_TEXTURE_2D, texture);
232
233 constexpr GLuint kWidth = 674;
234 constexpr GLuint kHeight = 114;
235
236 // From EXT_texture_compression_s3tc specifications:
237 // When an S3TC image with a width of <w>, height of <h>, and block size of
238 // <blocksize> (8 or 16 bytes) is decoded, the corresponding image size (in
239 // bytes) is:
240 // ceil(<w>/4) * ceil(<h>/4) * blocksize.
241 constexpr GLuint kImageSize = ((kWidth + 3) / 4) * ((kHeight + 3) / 4) * 8;
242
243 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, kWidth, kHeight, 0,
244 kImageSize, nullptr);
245 ASSERT_GL_NO_ERROR();
246
247 constexpr GLuint kImageSize1 = ((kWidth / 2 + 3) / 4) * ((kHeight / 2 + 3) / 4) * 8;
248 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, kWidth / 2,
249 kHeight / 2, 0, kImageSize1, nullptr);
250 ASSERT_GL_NO_ERROR();
251
252 constexpr GLuint kImageSize2 = ((kWidth / 4 + 3) / 4) * ((kHeight / 4 + 3) / 4) * 8;
253 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, kWidth / 4,
254 kHeight / 4, 0, kImageSize2, nullptr);
255 ASSERT_GL_NO_ERROR();
256 }
257
258 // Test validation of glCompressedTexSubImage2D with DXT formats
TEST_P(DXT1CompressedTextureTest,CompressedTexSubImageValidation)259 TEST_P(DXT1CompressedTextureTest, CompressedTexSubImageValidation)
260 {
261 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
262
263 GLTexture texture;
264 glBindTexture(GL_TEXTURE_2D, texture);
265
266 // Size mip 0 to a large size
267 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width,
268 pixel_0_height, 0, pixel_0_size, nullptr);
269 ASSERT_GL_NO_ERROR();
270
271 // Set a sub image with an offset that isn't a multiple of the block size
272 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 1, 3, pixel_1_width, pixel_1_height,
273 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_1_size, pixel_1_data);
274 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
275
276 // Set a sub image with a negative offset
277 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, -1, 0, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8,
278 pixel_1_data);
279 ASSERT_GL_ERROR(GL_INVALID_VALUE);
280
281 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, -1, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8,
282 pixel_1_data);
283 ASSERT_GL_ERROR(GL_INVALID_VALUE);
284 }
285
286 // Test that it's not possible to call CopyTexSubImage2D on a compressed texture
TEST_P(DXT1CompressedTextureTest,CopyTexSubImage2DDisallowed)287 TEST_P(DXT1CompressedTextureTest, CopyTexSubImage2DDisallowed)
288 {
289 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
290
291 GLTexture texture;
292 glBindTexture(GL_TEXTURE_2D, texture);
293
294 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width,
295 pixel_0_height, 0, pixel_0_size, nullptr);
296 ASSERT_GL_NO_ERROR();
297
298 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 4, 4);
299 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
300 }
301
TEST_P(DXT1CompressedTextureTest,PBOCompressedTexStorage)302 TEST_P(DXT1CompressedTextureTest, PBOCompressedTexStorage)
303 {
304 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
305
306 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
307 !IsGLExtensionEnabled("GL_NV_pixel_buffer_object"));
308
309 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
310 (!IsGLExtensionEnabled("GL_EXT_texture_storage") ||
311 !IsGLExtensionEnabled("GL_OES_rgb8_rgba8")));
312
313 GLuint texture;
314 glGenTextures(1, &texture);
315 glBindTexture(GL_TEXTURE_2D, texture);
316 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
317 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
319 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
320
321 if (getClientMajorVersion() < 3)
322 {
323 glTexStorage2DEXT(GL_TEXTURE_2D, pixel_levels, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
324 pixel_0_width, pixel_0_height);
325 }
326 else
327 {
328 glTexStorage2D(GL_TEXTURE_2D, pixel_levels, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width,
329 pixel_0_height);
330 }
331 EXPECT_GL_NO_ERROR();
332
333 GLuint buffer;
334 glGenBuffers(1, &buffer);
335 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
336 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixel_0_size, nullptr, GL_STREAM_DRAW);
337 EXPECT_GL_NO_ERROR();
338
339 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_0_size, pixel_0_data);
340 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pixel_0_width, pixel_0_height,
341 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_size, nullptr);
342 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_1_size, pixel_1_data);
343 glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, pixel_1_width, pixel_1_height,
344 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_1_size, nullptr);
345 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_2_size, pixel_2_data);
346 glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, pixel_2_width, pixel_2_height,
347 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_2_size, nullptr);
348 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_3_size, pixel_3_data);
349 glCompressedTexSubImage2D(GL_TEXTURE_2D, 3, 0, 0, pixel_3_width, pixel_3_height,
350 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_3_size, nullptr);
351 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_4_size, pixel_4_data);
352 glCompressedTexSubImage2D(GL_TEXTURE_2D, 4, 0, 0, pixel_4_width, pixel_4_height,
353 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_4_size, nullptr);
354 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_5_size, pixel_5_data);
355 glCompressedTexSubImage2D(GL_TEXTURE_2D, 5, 0, 0, pixel_5_width, pixel_5_height,
356 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_5_size, nullptr);
357 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_6_size, pixel_6_data);
358 glCompressedTexSubImage2D(GL_TEXTURE_2D, 6, 0, 0, pixel_6_width, pixel_6_height,
359 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_6_size, nullptr);
360 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_7_size, pixel_7_data);
361 glCompressedTexSubImage2D(GL_TEXTURE_2D, 7, 0, 0, pixel_7_width, pixel_7_height,
362 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_7_size, nullptr);
363 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_8_size, pixel_8_data);
364 glCompressedTexSubImage2D(GL_TEXTURE_2D, 8, 0, 0, pixel_8_width, pixel_8_height,
365 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_8_size, nullptr);
366 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_9_size, pixel_9_data);
367 glCompressedTexSubImage2D(GL_TEXTURE_2D, 9, 0, 0, pixel_9_width, pixel_9_height,
368 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_9_size, nullptr);
369
370 EXPECT_GL_NO_ERROR();
371
372 glUseProgram(mTextureProgram);
373 glUniform1i(mTextureUniformLocation, 0);
374
375 drawQuad(mTextureProgram, "position", 0.5f);
376
377 EXPECT_GL_NO_ERROR();
378
379 glDeleteTextures(1, &texture);
380
381 EXPECT_GL_NO_ERROR();
382 }
383
384 class DXT1CompressedTextureTestES3 : public DXT1CompressedTextureTest
385 {};
386
TEST_P(DXT1CompressedTextureTestES3,PBOCompressedTexImage)387 TEST_P(DXT1CompressedTextureTestES3, PBOCompressedTexImage)
388 {
389 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
390
391 GLuint texture;
392 glGenTextures(1, &texture);
393 glBindTexture(GL_TEXTURE_2D, texture);
394 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
395 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
396 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
397 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
398
399 GLuint buffer;
400 glGenBuffers(1, &buffer);
401 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
402 glBufferData(GL_PIXEL_UNPACK_BUFFER, pixel_0_size, nullptr, GL_STREAM_DRAW);
403 EXPECT_GL_NO_ERROR();
404
405 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_0_size, pixel_0_data);
406 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width,
407 pixel_0_height, 0, pixel_0_size, nullptr);
408 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_1_size, pixel_1_data);
409 glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_1_width,
410 pixel_1_height, 0, pixel_1_size, nullptr);
411 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_2_size, pixel_2_data);
412 glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_2_width,
413 pixel_2_height, 0, pixel_2_size, nullptr);
414 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_3_size, pixel_3_data);
415 glCompressedTexImage2D(GL_TEXTURE_2D, 3, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_3_width,
416 pixel_3_height, 0, pixel_3_size, nullptr);
417 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_4_size, pixel_4_data);
418 glCompressedTexImage2D(GL_TEXTURE_2D, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_4_width,
419 pixel_4_height, 0, pixel_4_size, nullptr);
420 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_5_size, pixel_5_data);
421 glCompressedTexImage2D(GL_TEXTURE_2D, 5, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_5_width,
422 pixel_5_height, 0, pixel_5_size, nullptr);
423 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_6_size, pixel_6_data);
424 glCompressedTexImage2D(GL_TEXTURE_2D, 6, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_6_width,
425 pixel_6_height, 0, pixel_6_size, nullptr);
426 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_7_size, pixel_7_data);
427 glCompressedTexImage2D(GL_TEXTURE_2D, 7, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_7_width,
428 pixel_7_height, 0, pixel_7_size, nullptr);
429 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_8_size, pixel_8_data);
430 glCompressedTexImage2D(GL_TEXTURE_2D, 8, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_8_width,
431 pixel_8_height, 0, pixel_8_size, nullptr);
432 glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, pixel_9_size, pixel_9_data);
433 glCompressedTexImage2D(GL_TEXTURE_2D, 9, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_9_width,
434 pixel_9_height, 0, pixel_9_size, nullptr);
435
436 EXPECT_GL_NO_ERROR();
437
438 glUseProgram(mTextureProgram);
439 glUniform1i(mTextureUniformLocation, 0);
440
441 drawQuad(mTextureProgram, "position", 0.5f);
442
443 EXPECT_GL_NO_ERROR();
444
445 glDeleteTextures(1, &buffer);
446 glDeleteTextures(1, &texture);
447
448 EXPECT_GL_NO_ERROR();
449 }
450
451 // Test validation of glCompressedTexSubImage3D with DXT formats
TEST_P(DXT1CompressedTextureTestES3,CompressedTexSubImageValidation)452 TEST_P(DXT1CompressedTextureTestES3, CompressedTexSubImageValidation)
453 {
454 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
455
456 GLTexture texture;
457 glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
458
459 // Size mip 0 to a large size
460 glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width,
461 pixel_0_height, 1, 0, pixel_0_size, nullptr);
462 ASSERT_GL_NO_ERROR();
463
464 // Set a sub image with a negative offset
465 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, -1, 0, 0, 4, 4, 1,
466 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, pixel_1_data);
467 ASSERT_GL_ERROR(GL_INVALID_VALUE);
468
469 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, -1, 0, 4, 4, 1,
470 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, pixel_1_data);
471 ASSERT_GL_ERROR(GL_INVALID_VALUE);
472
473 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, -1, 4, 4, 1,
474 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, pixel_1_data);
475 ASSERT_GL_ERROR(GL_INVALID_VALUE);
476 }
477
478 // Test validation of glCompressedTexSubImage3D with per-slice data uploads
TEST_P(DXT1CompressedTextureTestES3,CompressedTexSubImage3DValidationPerSlice)479 TEST_P(DXT1CompressedTextureTestES3, CompressedTexSubImage3DValidationPerSlice)
480 {
481 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
482
483 GLTexture texture;
484 glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
485 const GLenum format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
486
487 // 8x8x2, 4x4x2, 2x2x2, 1x1x2
488 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, format, 8, 8, 2);
489 ASSERT_GL_NO_ERROR();
490
491 uint8_t data[32] = {};
492 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 8, 8, 1, format, 32, data);
493 ASSERT_GL_NO_ERROR();
494 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 8, 8, 1, format, 32, data);
495 ASSERT_GL_NO_ERROR();
496
497 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, 4, 4, 1, format, 8, data);
498 ASSERT_GL_NO_ERROR();
499 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 1, 4, 4, 1, format, 8, data);
500 ASSERT_GL_NO_ERROR();
501
502 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 2, 0, 0, 0, 2, 2, 1, format, 8, data);
503 ASSERT_GL_NO_ERROR();
504 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 2, 0, 0, 1, 2, 2, 1, format, 8, data);
505 ASSERT_GL_NO_ERROR();
506
507 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 3, 0, 0, 0, 1, 1, 1, format, 8, data);
508 ASSERT_GL_NO_ERROR();
509 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 3, 0, 0, 1, 1, 1, 1, format, 8, data);
510 ASSERT_GL_NO_ERROR();
511 }
512
513 // Test validation of glCompressedTexSubImage3D with combined per-level data uploads
TEST_P(DXT1CompressedTextureTestES3,CompressedTexSubImage3DValidationPerLevel)514 TEST_P(DXT1CompressedTextureTestES3, CompressedTexSubImage3DValidationPerLevel)
515 {
516 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
517
518 GLTexture texture;
519 glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
520 const GLenum format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
521
522 // 8x8x2, 4x4x2, 2x2x2, 1x1x2
523 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, format, 8, 8, 2);
524 ASSERT_GL_NO_ERROR();
525
526 uint8_t data[64] = {};
527 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 8, 8, 2, format, 64, data);
528 ASSERT_GL_NO_ERROR();
529
530 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, 4, 4, 2, format, 16, data);
531 ASSERT_GL_NO_ERROR();
532
533 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 2, 0, 0, 0, 2, 2, 2, format, 16, data);
534 ASSERT_GL_NO_ERROR();
535
536 glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 3, 0, 0, 0, 1, 1, 2, format, 16, data);
537 ASSERT_GL_NO_ERROR();
538 }
539
540 // Test validation of glCompressedTexSubImage3D with DXT formats
TEST_P(DXT1CompressedTextureTestES3,CopyTexSubImage3DDisallowed)541 TEST_P(DXT1CompressedTextureTestES3, CopyTexSubImage3DDisallowed)
542 {
543 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
544
545 GLTexture texture;
546 glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
547
548 GLsizei depth = 4;
549 glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width,
550 pixel_0_height, depth, 0, pixel_0_size * depth, nullptr);
551 ASSERT_GL_NO_ERROR();
552
553 glCopyTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, 0, 4, 4);
554 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
555 }
556
557 class DXT1CompressedTextureTestWebGL2 : public DXT1CompressedTextureTest
558 {
559 protected:
DXT1CompressedTextureTestWebGL2()560 DXT1CompressedTextureTestWebGL2()
561 {
562 setWebGLCompatibilityEnabled(true);
563 setRobustResourceInit(true);
564 }
565 };
566
567 // Regression test for https://crbug.com/1289428
TEST_P(DXT1CompressedTextureTestWebGL2,InitializeTextureContents)568 TEST_P(DXT1CompressedTextureTestWebGL2, InitializeTextureContents)
569 {
570 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
571
572 glUseProgram(mTextureProgram);
573 glUniform1i(mTextureUniformLocation, 0);
574
575 glClearColor(0, 0, 1, 1);
576
577 const std::array<uint8_t, 8> kGreen = {0xE0, 0x07, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00};
578
579 GLTexture tex;
580 glBindTexture(GL_TEXTURE_2D, tex);
581 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
582 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
583 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
584 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
585
586 glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4);
587 EXPECT_GL_NO_ERROR();
588
589 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
590 drawQuad(mTextureProgram, "position", 0.5f, 1.0f, true);
591 EXPECT_GL_NO_ERROR();
592 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::black);
593
594 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 8,
595 kGreen.data());
596 EXPECT_GL_NO_ERROR();
597
598 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
599 drawQuad(mTextureProgram, "position", 0.5f, 1.0f, true);
600 EXPECT_GL_NO_ERROR();
601 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green);
602 }
603
604 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(DXT1CompressedTextureTest);
605
606 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DXT1CompressedTextureTestES3);
607 ANGLE_INSTANTIATE_TEST_ES3_AND(DXT1CompressedTextureTestES3,
608 ES3_VULKAN().enable(angle::Feature::ForceRobustResourceInit));
609
610 ANGLE_INSTANTIATE_TEST_ES3(DXT1CompressedTextureTestWebGL2);
611