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