1 //
2 // Copyright 2016 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 // CopyCompressedTextureTest.cpp: Tests of the GL_CHROMIUM_copy_compressed_texture extension
8
9 #include "test_utils/ANGLETest.h"
10
11 namespace angle
12 {
13
14 class CopyCompressedTextureTest : public ANGLETest
15 {
16 protected:
CopyCompressedTextureTest()17 CopyCompressedTextureTest()
18 {
19 setWindowWidth(256);
20 setWindowHeight(256);
21 setConfigRedBits(8);
22 setConfigGreenBits(8);
23 setConfigBlueBits(8);
24 setConfigAlphaBits(8);
25 }
26
SetUp()27 void SetUp() override
28 {
29 ANGLETest::SetUp();
30
31 glGenTextures(2, mTextures);
32
33 mProgram = CompileProgram(
34 "attribute vec2 a_position;\n"
35 "varying vec2 v_texcoord;\n"
36 "void main()\n"
37 "{\n"
38 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
39 " v_texcoord = (a_position + 1.0) * 0.5;\n"
40 "}\n",
41 "precision mediump float;\n"
42 "uniform sampler2D u_texture;\n"
43 "varying vec2 v_texcoord;\n"
44 "void main()\n"
45 "{\n"
46 " gl_FragColor = texture2D(u_texture, v_texcoord);\n"
47 "}\n");
48 ASSERT_NE(0u, mProgram);
49
50 if (extensionEnabled("GL_CHROMIUM_copy_compressed_texture"))
51 {
52 glCompressedCopyTextureCHROMIUM =
53 reinterpret_cast<PFNGLCOMPRESSEDCOPYTEXTURECHROMIUMPROC>(
54 eglGetProcAddress("glCompressedCopyTextureCHROMIUM"));
55 }
56 }
57
TearDown()58 void TearDown() override
59 {
60 glDeleteTextures(2, mTextures);
61 glDeleteProgram(mProgram);
62
63 ANGLETest::TearDown();
64 }
65
checkExtensions() const66 bool checkExtensions() const
67 {
68 if (!extensionEnabled("GL_CHROMIUM_copy_compressed_texture"))
69 {
70 std::cout
71 << "Test skipped because GL_CHROMIUM_copy_compressed_texture is not available."
72 << std::endl;
73 return false;
74 }
75
76 EXPECT_NE(nullptr, glCompressedCopyTextureCHROMIUM);
77 if (glCompressedCopyTextureCHROMIUM == nullptr)
78 {
79 return false;
80 }
81
82 return true;
83 }
84
85 GLuint mProgram = 0;
86 GLuint mTextures[2] = {0, 0};
87
88 PFNGLCOMPRESSEDCOPYTEXTURECHROMIUMPROC glCompressedCopyTextureCHROMIUM = nullptr;
89 };
90
91 namespace
92 {
93
94 const GLColor &CompressedImageColor = GLColor::red;
95
96 // Single compressed ATC block of source pixels all set to:
97 // CompressedImageColor.
98 const uint8_t CompressedImageATC[8] = {0x0, 0x7c, 0x0, 0xf8, 0x55, 0x55, 0x55, 0x55};
99
100 // Single compressed ATCIA block of source pixels all set to:
101 // CompressedImageColor.
102 const uint8_t CompressedImageATCIA[16] = {0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
103 0x0, 0x7c, 0x0, 0xf8, 0x55, 0x55, 0x55, 0x55};
104
105 // Single compressed DXT1 block of source pixels all set to:
106 // CompressedImageColor.
107 const uint8_t CompressedImageDXT1[8] = {0x00, 0xf8, 0x00, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa};
108
109 // Single compressed DXT5 block of source pixels all set to:
110 // CompressedImageColor.
111 const uint8_t CompressedImageDXT5[16] = {0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
112 0x0, 0xf8, 0x0, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa};
113
114 // Single compressed DXT1 block of source pixels all set to:
115 // CompressedImageColor.
116 const uint8_t CompressedImageETC1[8] = {0x0, 0x0, 0xf8, 0x2, 0xff, 0xff, 0x0, 0x0};
117
118 } // anonymous namespace
119
120 // Test to ensure that the basic functionality of the extension works.
TEST_P(CopyCompressedTextureTest,Basic)121 TEST_P(CopyCompressedTextureTest, Basic)
122 {
123 if (!checkExtensions())
124 {
125 return;
126 }
127
128 if (!extensionEnabled("GL_EXT_texture_compression_dxt1"))
129 {
130 std::cout << "Test skipped because GL_EXT_texture_compression_dxt1 is not available."
131 << std::endl;
132 return;
133 }
134
135 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
136 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
137 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
138 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
139 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
140 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
141 sizeof(CompressedImageDXT1), CompressedImageDXT1);
142 ASSERT_GL_NO_ERROR();
143
144 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
145 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
146 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
147 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
148 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
149 glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
150 ASSERT_GL_NO_ERROR();
151
152 // Load texture.
153 glActiveTexture(GL_TEXTURE0);
154 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
155 GLint textureLoc = glGetUniformLocation(mProgram, "u_texture");
156 glUseProgram(mProgram);
157 glUniform1i(textureLoc, 0);
158
159 // Draw.
160 drawQuad(mProgram, "a_position", 0.5f);
161
162 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, CompressedImageColor);
163 ASSERT_GL_NO_ERROR();
164 }
165
166 // Test validation of compressed formats
TEST_P(CopyCompressedTextureTest,InternalFormat)167 TEST_P(CopyCompressedTextureTest, InternalFormat)
168 {
169 if (!checkExtensions())
170 {
171 return;
172 }
173
174 struct Data
175 {
176 GLint format;
177 const uint8_t *data;
178 GLsizei dataSize;
179
180 Data() : Data(GL_NONE, nullptr, 0) {}
181 Data(GLint format, const uint8_t *data, GLsizei dataSize)
182 : format(format), data(data), dataSize(dataSize)
183 {
184 }
185 };
186 std::vector<Data> supportedFormats;
187
188 if (extensionEnabled("GL_AMD_compressed_ATC_texture"))
189 {
190 supportedFormats.push_back(
191 Data(GL_ATC_RGB_AMD, CompressedImageATC, sizeof(CompressedImageATC)));
192 supportedFormats.push_back(Data(GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD, CompressedImageATCIA,
193 sizeof(CompressedImageATCIA)));
194 }
195 if (extensionEnabled("GL_EXT_texture_compression_dxt1"))
196 {
197 supportedFormats.push_back(Data(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, CompressedImageDXT1,
198 sizeof(CompressedImageDXT1)));
199 }
200 if (extensionEnabled("GL_ANGLE_texture_compression_dxt5"))
201 {
202 supportedFormats.push_back(Data(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, CompressedImageDXT5,
203 sizeof(CompressedImageDXT5)));
204 }
205 if (extensionEnabled("GL_OES_compressed_ETC1_RGB8_texture"))
206 {
207 supportedFormats.push_back(
208 Data(GL_ETC1_RGB8_OES, CompressedImageETC1, sizeof(CompressedImageETC1)));
209 }
210
211 for (const auto &supportedFormat : supportedFormats)
212 {
213 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
214 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
215 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
216 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
217 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
218 glCompressedTexImage2D(GL_TEXTURE_2D, 0, supportedFormat.format, 4, 4, 0,
219 supportedFormat.dataSize, supportedFormat.data);
220 ASSERT_GL_NO_ERROR();
221
222 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
223 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
224 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
225 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
226 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
227 glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
228 ASSERT_GL_NO_ERROR();
229 }
230 }
231
232 // Test that uncompressed textures generate errors when copying
TEST_P(CopyCompressedTextureTest,InternalFormatNotSupported)233 TEST_P(CopyCompressedTextureTest, InternalFormatNotSupported)
234 {
235 if (!checkExtensions())
236 {
237 return;
238 }
239
240 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
243 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
244 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
245 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
246 ASSERT_GL_NO_ERROR();
247
248 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
249 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
250 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
251 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
252 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
253 ASSERT_GL_NO_ERROR();
254
255 // Check that the GL_RGBA format reports an error.
256 glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
257 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
258 }
259
260 // Test validation of texture IDs
TEST_P(CopyCompressedTextureTest,InvalidTextureIds)261 TEST_P(CopyCompressedTextureTest, InvalidTextureIds)
262 {
263 if (!checkExtensions())
264 {
265 return;
266 }
267
268 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
269 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
270 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
271 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
272 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
273 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
274 sizeof(CompressedImageDXT1), CompressedImageDXT1);
275 ASSERT_GL_NO_ERROR();
276
277 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
278 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
279 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
280 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
281 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
282 ASSERT_GL_NO_ERROR();
283
284 glCompressedCopyTextureCHROMIUM(mTextures[0], 99993);
285 EXPECT_GL_ERROR(GL_INVALID_VALUE);
286
287 glCompressedCopyTextureCHROMIUM(99994, mTextures[1]);
288 EXPECT_GL_ERROR(GL_INVALID_VALUE);
289
290 glCompressedCopyTextureCHROMIUM(99995, 99996);
291 EXPECT_GL_ERROR(GL_INVALID_VALUE);
292
293 glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
294 EXPECT_GL_NO_ERROR();
295 }
296
297 // Test that only 2D textures are valid
TEST_P(CopyCompressedTextureTest,BindingPoints)298 TEST_P(CopyCompressedTextureTest, BindingPoints)
299 {
300 if (!checkExtensions())
301 {
302 return;
303 }
304
305 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[0]);
306 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
307 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
308 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
309 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
310 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
311 face++)
312 {
313 glCompressedTexImage2D(face, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
314 sizeof(CompressedImageDXT1), CompressedImageDXT1);
315 }
316 ASSERT_GL_NO_ERROR();
317
318 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[1]);
319 glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
320 glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
321 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
322 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
323 ASSERT_GL_NO_ERROR();
324
325 glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
326 EXPECT_GL_ERROR(GL_INVALID_VALUE);
327 }
328
329 // Test the destination texture cannot be immutable
TEST_P(CopyCompressedTextureTest,Immutable)330 TEST_P(CopyCompressedTextureTest, Immutable)
331 {
332 if (!checkExtensions() || getClientMajorVersion() < 3)
333 {
334 return;
335 }
336
337 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
338 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
339 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
340 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
341 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
342 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
343 sizeof(CompressedImageDXT1), CompressedImageDXT1);
344 ASSERT_GL_NO_ERROR();
345
346 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
347 glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4);
348 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
349 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
350 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
351 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
352 ASSERT_GL_NO_ERROR();
353
354 glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
355 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
356 }
357
358 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
359 // tests should be run against.
360 ANGLE_INSTANTIATE_TEST(CopyCompressedTextureTest,
361 ES2_D3D9(),
362 ES2_D3D11(),
363 ES3_D3D11(),
364 ES2_OPENGL(),
365 ES3_OPENGL(),
366 ES2_OPENGLES(),
367 ES3_OPENGLES());
368
369 } // namespace angle
370