xref: /aosp_15_r20/external/angle/src/tests/gl_tests/PVRTCCompressedTextureTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2023 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 // PVRTCCompressedTextureTest.cpp: Sampling tests for PVRTC texture formats
8 // Invalid usage errors are covered by CompressedTextureFormatsTest.
9 
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 
13 using namespace angle;
14 
15 class PVRTCCompressedTextureTestES3 : public ANGLETest<>
16 {
17     static constexpr int kDim = 128;
18 
19   protected:
PVRTCCompressedTextureTestES3()20     PVRTCCompressedTextureTestES3()
21     {
22         setWindowWidth(kDim);
23         setWindowHeight(kDim);
24         setConfigRedBits(8);
25         setConfigGreenBits(8);
26         setConfigBlueBits(8);
27         setConfigAlphaBits(8);
28     }
29 
testSetUp()30     void testSetUp() override
31     {
32         // Prepare some filler data.
33         // The test only asserts that direct and PBO texture uploads produce
34         // identical results, so the decoded values do not matter here.
35         for (size_t i = 0; i < mTextureData.size(); ++i)
36         {
37             mTextureData[i] = static_cast<uint8_t>(i + i / 8 + i / 2048);
38         }
39     }
40 
test(GLenum format,GLsizei dimension)41     void test(GLenum format, GLsizei dimension)
42     {
43         // Placeholder for the decoded color values from a directly uploaded texture.
44         std::array<GLColor, kDim * kDim> controlData;
45 
46         GLsizei imageSize = 0;
47         switch (format)
48         {
49             case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
50             case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
51             case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
52             case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
53                 imageSize = (std::max(dimension, 8) * std::max(dimension, 8) * 4 + 7) / 8;
54                 break;
55             case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
56             case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
57             case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
58             case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
59                 imageSize = (std::max(dimension, 16) * std::max(dimension, 8) * 2 + 7) / 8;
60                 break;
61         }
62         ASSERT_GT(imageSize, 0);
63 
64         // Directly upload compressed data and remember the decoded values.
65         {
66             GLTexture texture;
67             glBindTexture(GL_TEXTURE_2D, texture);
68             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
69             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
70             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
71             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
72 
73             glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, dimension, dimension, 0, imageSize,
74                                    mTextureData.data());
75             ASSERT_GL_NO_ERROR();
76 
77             glClear(GL_COLOR_BUFFER_BIT);
78             drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.0f);
79             ASSERT_GL_NO_ERROR();
80 
81             glReadPixels(0, 0, kDim, kDim, GL_RGBA, GL_UNSIGNED_BYTE, controlData.data());
82             ASSERT_GL_NO_ERROR();
83         }
84 
85         // Upload the same compressed data using a PBO with different
86         // offsets and check that it is sampled correctly each time.
87         for (size_t offset = 0; offset <= 8; ++offset)
88         {
89             std::vector<GLubyte> bufferData(offset);
90             std::copy(mTextureData.begin(), mTextureData.end(), std::back_inserter(bufferData));
91             ASSERT_EQ(bufferData.size(), mTextureData.size() + offset);
92 
93             GLBuffer buffer;
94             glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
95             glBufferData(GL_PIXEL_UNPACK_BUFFER, bufferData.size(), bufferData.data(),
96                          GL_STATIC_READ);
97             ASSERT_GL_NO_ERROR();
98 
99             GLTexture texture;
100             glBindTexture(GL_TEXTURE_2D, texture);
101             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
102             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
103             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
104             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
105 
106             glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, dimension, dimension, 0, imageSize,
107                                    reinterpret_cast<void *>(offset));
108             ASSERT_GL_NO_ERROR();
109 
110             glClear(GL_COLOR_BUFFER_BIT);
111             drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.0f);
112             ASSERT_GL_NO_ERROR();
113 
114             std::array<GLColor, kDim * kDim> readData;
115             glReadPixels(0, 0, kDim, kDim, GL_RGBA, GL_UNSIGNED_BYTE, readData.data());
116             ASSERT_GL_NO_ERROR();
117 
118             // Check only one screen pixel for each texture pixel.
119             for (GLsizei x = 0; x < dimension; ++x)
120             {
121                 for (GLsizei y = 0; y < dimension; ++y)
122                 {
123                     // Tested texture sizes are multiples of the window dimensions.
124                     const size_t xScaled  = x * kDim / dimension;
125                     const size_t yScaled  = y * kDim / dimension;
126                     const size_t position = yScaled * kDim + xScaled;
127                     EXPECT_EQ(readData[position], controlData[position])
128                         << "(" << x << ", " << y << ")"
129                         << " of " << dimension << "x" << dimension << " texture with PBO offset "
130                         << offset;
131                 }
132             }
133         }
134     }
135 
run(GLenum format)136     void run(GLenum format)
137     {
138         mProgram.makeRaster(essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
139         for (auto dimension : {1, 2, 4, 8, 16, 32, 64, 128})
140         {
141             test(format, dimension);
142         }
143     }
144 
145   private:
146     std::array<GLubyte, 8192> mTextureData;
147     GLProgram mProgram;
148 };
149 
150 // Test uploading texture data from a PBO to an RGB_PVRTC_4BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3,RGB_PVRTC_4BPPV1)151 TEST_P(PVRTCCompressedTextureTestES3, RGB_PVRTC_4BPPV1)
152 {
153     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
154     run(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG);
155 }
156 
157 // Test uploading texture data from a PBO to an RGBA_PVRTC_4BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3,RGBA_PVRTC_4BPPV1)158 TEST_P(PVRTCCompressedTextureTestES3, RGBA_PVRTC_4BPPV1)
159 {
160     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
161     run(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG);
162 }
163 
164 // Test uploading texture data from a PBO to an RGB_PVRTC_2BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3,RGB_PVRTC_2BPPV1)165 TEST_P(PVRTCCompressedTextureTestES3, RGB_PVRTC_2BPPV1)
166 {
167     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
168     run(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG);
169 }
170 
171 // Test uploading texture data from a PBO to an RGBA_PVRTC_2BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3,RGBA_PVRTC_2BPPV1)172 TEST_P(PVRTCCompressedTextureTestES3, RGBA_PVRTC_2BPPV1)
173 {
174     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
175     run(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG);
176 }
177 
178 // Test uploading texture data from a PBO to an SRGB_PVRTC_4BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3,SRGB_PVRTC_4BPPV1)179 TEST_P(PVRTCCompressedTextureTestES3, SRGB_PVRTC_4BPPV1)
180 {
181     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
182     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_pvrtc_sRGB"));
183     run(GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT);
184 }
185 
186 // Test uploading texture data from a PBO to an SRGB_ALPHA_PVRTC_4BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3,SRGB_ALPHA_PVRTC_4BPPV1)187 TEST_P(PVRTCCompressedTextureTestES3, SRGB_ALPHA_PVRTC_4BPPV1)
188 {
189     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
190     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_pvrtc_sRGB"));
191     run(GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT);
192 }
193 
194 // Test uploading texture data from a PBO to an SRGB_PVRTC_2BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3,SRGB_PVRTC_2BPPV1)195 TEST_P(PVRTCCompressedTextureTestES3, SRGB_PVRTC_2BPPV1)
196 {
197     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
198     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_pvrtc_sRGB"));
199     run(GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT);
200 }
201 
202 // Test uploading texture data from a PBO to an SRGB_ALPHA_PVRTC_2BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3,SRGB_ALPHA_PVRTC_2BPPV1)203 TEST_P(PVRTCCompressedTextureTestES3, SRGB_ALPHA_PVRTC_2BPPV1)
204 {
205     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
206     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_pvrtc_sRGB"));
207     run(GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT);
208 }
209 
210 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PVRTCCompressedTextureTestES3);
211 ANGLE_INSTANTIATE_TEST_ES3(PVRTCCompressedTextureTestES3);
212