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