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 namespace angle
11 {
12
13 class SRGBTextureTest : public ANGLETest
14 {
15 protected:
SRGBTextureTest()16 SRGBTextureTest()
17 {
18 setWindowWidth(128);
19 setWindowHeight(128);
20 setConfigRedBits(8);
21 setConfigGreenBits(8);
22 setConfigBlueBits(8);
23 setConfigAlphaBits(8);
24 }
25
SetUp()26 void SetUp() override
27 {
28 ANGLETest::SetUp();
29
30 const std::string vs =
31 "precision highp float;\n"
32 "attribute vec4 position;\n"
33 "varying vec2 texcoord;\n"
34 "\n"
35 "void main()\n"
36 "{\n"
37 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
38 " texcoord = (position.xy * 0.5) + 0.5;\n"
39 "}\n";
40
41 const std::string fs =
42 "precision highp float;\n"
43 "uniform sampler2D tex;\n"
44 "varying vec2 texcoord;\n"
45 "\n"
46 "void main()\n"
47 "{\n"
48 " gl_FragColor = texture2D(tex, texcoord);\n"
49 "}\n";
50
51 mProgram = CompileProgram(vs, fs);
52 ASSERT_NE(0u, mProgram);
53
54 mTextureLocation = glGetUniformLocation(mProgram, "tex");
55 ASSERT_NE(-1, mTextureLocation);
56 }
57
TearDown()58 void TearDown() override
59 {
60 glDeleteProgram(mProgram);
61
62 ANGLETest::TearDown();
63 }
64
65 GLuint mProgram = 0;
66 GLint mTextureLocation = -1;
67 };
68
TEST_P(SRGBTextureTest,SRGBValidation)69 TEST_P(SRGBTextureTest, SRGBValidation)
70 {
71 bool supported = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() == 3;
72
73 GLuint tex = 0;
74 glGenTextures(1, &tex);
75 glBindTexture(GL_TEXTURE_2D, tex);
76
77 GLubyte pixel[3] = { 0 };
78 glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, 1, 1, 0, GL_SRGB, GL_UNSIGNED_BYTE, pixel);
79 if (supported)
80 {
81 EXPECT_GL_NO_ERROR();
82
83 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_SRGB, GL_UNSIGNED_BYTE, pixel);
84 EXPECT_GL_NO_ERROR();
85
86 glGenerateMipmap(GL_TEXTURE_2D);
87 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
88 }
89 else
90 {
91 EXPECT_GL_ERROR(GL_INVALID_ENUM);
92 }
93
94 glDeleteTextures(1, &tex);
95 }
96
TEST_P(SRGBTextureTest,SRGBAValidation)97 TEST_P(SRGBTextureTest, SRGBAValidation)
98 {
99 bool supported = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() == 3;
100
101 GLuint tex = 0;
102 glGenTextures(1, &tex);
103 glBindTexture(GL_TEXTURE_2D, tex);
104
105 GLubyte pixel[4] = { 0 };
106 glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, pixel);
107 if (supported)
108 {
109 EXPECT_GL_NO_ERROR();
110
111 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, pixel);
112 EXPECT_GL_NO_ERROR();
113
114 glGenerateMipmap(GL_TEXTURE_2D);
115 if (getClientMajorVersion() == 2)
116 {
117 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
118 }
119 else
120 {
121 EXPECT_GL_NO_ERROR();
122 }
123 }
124 else
125 {
126 EXPECT_GL_ERROR(GL_INVALID_ENUM);
127 }
128
129 glDeleteTextures(1, &tex);
130 }
131
TEST_P(SRGBTextureTest,SRGBARenderbuffer)132 TEST_P(SRGBTextureTest, SRGBARenderbuffer)
133 {
134 bool supported = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() == 3;
135
136 GLuint rbo = 0;
137 glGenRenderbuffers(1, &rbo);
138 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
139
140 glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8_EXT, 1, 1);
141 if (supported)
142 {
143 EXPECT_GL_NO_ERROR();
144 }
145 else
146 {
147 EXPECT_GL_ERROR(GL_INVALID_ENUM);
148
149 // Make sure the rbo has a size for future tests
150 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, 1, 1);
151 EXPECT_GL_NO_ERROR();
152 }
153
154 GLuint fbo = 0;
155 glGenFramebuffers(1, &fbo);
156 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
157 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
158 EXPECT_GL_NO_ERROR();
159
160 GLint colorEncoding = 0;
161 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
162 GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT, &colorEncoding);
163 if (supported)
164 {
165 EXPECT_GL_NO_ERROR();
166 EXPECT_EQ(GL_SRGB_EXT, colorEncoding);
167 }
168 else
169 {
170 EXPECT_GL_ERROR(GL_INVALID_ENUM);
171 }
172
173 glDeleteFramebuffers(1, &fbo);
174 glDeleteRenderbuffers(1, &rbo);
175 }
176
177 // Verify that if the srgb decode extension is available, srgb textures are too
TEST_P(SRGBTextureTest,SRGBDecodeExtensionAvailability)178 TEST_P(SRGBTextureTest, SRGBDecodeExtensionAvailability)
179 {
180 bool hasSRGBDecode = extensionEnabled("GL_EXT_texture_sRGB_decode");
181 if (hasSRGBDecode)
182 {
183 bool hasSRGBTextures = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() >= 3;
184 EXPECT_TRUE(hasSRGBTextures);
185 }
186 }
187
188 // Test basic functionality of SRGB decode using the texture parameter
TEST_P(SRGBTextureTest,SRGBDecodeTextureParameter)189 TEST_P(SRGBTextureTest, SRGBDecodeTextureParameter)
190 {
191 if (!extensionEnabled("GL_EXT_texture_sRGB_decode"))
192 {
193 std::cout << "Test skipped because GL_EXT_texture_sRGB_decode is not available."
194 << std::endl;
195 return;
196 }
197
198 GLColor linearColor(64, 127, 191, 255);
199 GLColor srgbColor(13, 54, 133, 255);
200
201 GLTexture tex;
202 glBindTexture(GL_TEXTURE_2D, tex.get());
203 glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
204 &linearColor);
205 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
206 ASSERT_GL_NO_ERROR();
207
208 glUseProgram(mProgram);
209 glUniform1i(mTextureLocation, 0);
210
211 glDisable(GL_DEPTH_TEST);
212 drawQuad(mProgram, "position", 0.5f);
213
214 EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0);
215
216 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
217 drawQuad(mProgram, "position", 0.5f);
218
219 EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
220 }
221
222 // Test basic functionality of SRGB decode using the sampler parameter
TEST_P(SRGBTextureTest,SRGBDecodeSamplerParameter)223 TEST_P(SRGBTextureTest, SRGBDecodeSamplerParameter)
224 {
225 if (!extensionEnabled("GL_EXT_texture_sRGB_decode") || getClientMajorVersion() < 3)
226 {
227 std::cout << "Test skipped because GL_EXT_texture_sRGB_decode or ES3 is not available."
228 << std::endl;
229 return;
230 }
231
232 GLColor linearColor(64, 127, 191, 255);
233 GLColor srgbColor(13, 54, 133, 255);
234
235 GLTexture tex;
236 glBindTexture(GL_TEXTURE_2D, tex.get());
237 glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
238 &linearColor);
239 ASSERT_GL_NO_ERROR();
240
241 GLSampler sampler;
242 glBindSampler(0, sampler.get());
243 glSamplerParameteri(sampler.get(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
244
245 glUseProgram(mProgram);
246 glUniform1i(mTextureLocation, 0);
247
248 glDisable(GL_DEPTH_TEST);
249 drawQuad(mProgram, "position", 0.5f);
250
251 EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0);
252
253 glSamplerParameteri(sampler.get(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
254 drawQuad(mProgram, "position", 0.5f);
255
256 EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
257 }
258 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
259 ANGLE_INSTANTIATE_TEST(SRGBTextureTest,
260 ES2_D3D9(),
261 ES2_D3D11(),
262 ES3_D3D11(),
263 ES2_OPENGL(),
264 ES3_OPENGL(),
265 ES2_OPENGLES(),
266 ES3_OPENGLES());
267
268 } // namespace
269