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
9 namespace angle
10 {
11
12 class CopyTexImageTest : public ANGLETest
13 {
14 protected:
CopyTexImageTest()15 CopyTexImageTest()
16 {
17 setWindowWidth(16);
18 setWindowHeight(16);
19 setConfigRedBits(8);
20 setConfigGreenBits(8);
21 setConfigBlueBits(8);
22 setConfigAlphaBits(8);
23 }
24
createFramebuffer(GLenum format,GLenum type,GLfloat color[4]) const25 GLuint createFramebuffer(GLenum format, GLenum type, GLfloat color[4]) const
26 {
27 GLuint fbo;
28 glGenFramebuffers(1, &fbo);
29 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
30
31 GLuint texture = createTexture(format, type);
32 glBindTexture(GL_TEXTURE_2D, texture);
33 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
34
35 glClearColor(color[0], color[1], color[2], color[3]);
36 glClear(GL_COLOR_BUFFER_BIT);
37
38 return fbo;
39 }
40
createTexture(GLenum format,GLenum type) const41 GLuint createTexture(GLenum format, GLenum type) const
42 {
43 GLuint tex;
44 glGenTextures(1, &tex);
45 glBindTexture(GL_TEXTURE_2D, tex);
46 glTexImage2D(GL_TEXTURE_2D, 0, format, 16, 16, 0, format, type, nullptr);
47
48 // Disable mipmapping
49 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
50 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
51
52 return tex;
53 }
54
createTextureFromCopyTexImage(GLuint fbo,GLenum format) const55 GLuint createTextureFromCopyTexImage(GLuint fbo, GLenum format) const
56 {
57 GLuint tex;
58 glGenTextures(1, &tex);
59 glBindTexture(GL_TEXTURE_2D, tex);
60
61 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
62 glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, 16, 16, 0);
63
64 // Disable mipmapping
65 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
66 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
67
68 return tex;
69 }
70
copyTextureWithCopyTexSubImage(GLuint fbo,GLuint texture,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei w,GLsizei h) const71 void copyTextureWithCopyTexSubImage(GLuint fbo,
72 GLuint texture,
73 GLint xoffset,
74 GLint yoffset,
75 GLint x,
76 GLint y,
77 GLsizei w,
78 GLsizei h) const
79 {
80 glBindTexture(GL_TEXTURE_2D, texture);
81 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
82 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, x, y, w, h);
83 }
84
SetUp()85 void SetUp() override
86 {
87 ANGLETest::SetUp();
88
89 const std::string vsSource =
90 "precision highp float;\n"
91 "attribute vec4 position;\n"
92 "varying vec2 texcoord;\n"
93 "\n"
94 "void main()\n"
95 "{\n"
96 " gl_Position = position;\n"
97 " texcoord = (position.xy * 0.5) + 0.5;\n"
98 " texcoord.y = 1.0 - texcoord.y;\n"
99 "}\n";
100
101 const std::string textureFSSource =
102 "precision highp float;\n"
103 "uniform sampler2D tex;\n"
104 "varying vec2 texcoord;\n"
105 "\n"
106 "void main()\n"
107 "{\n"
108 " gl_FragColor = texture2D(tex, texcoord);\n"
109 "}\n";
110
111 mTextureProgram = CompileProgram(vsSource, textureFSSource);
112 if (mTextureProgram == 0)
113 {
114 FAIL() << "shader compilation failed.";
115 }
116
117 mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
118
119 ASSERT_GL_NO_ERROR();
120 }
121
TearDown()122 void TearDown() override
123 {
124 glDeleteProgram(mTextureProgram);
125
126 ANGLETest::TearDown();
127 }
128
verifyResults(GLuint texture,GLubyte data[4],GLint x,GLint y)129 void verifyResults(GLuint texture, GLubyte data[4], GLint x, GLint y)
130 {
131 glViewport(0, 0, 16, 16);
132
133 glBindFramebuffer(GL_FRAMEBUFFER, 0);
134
135 // Draw a quad with the target texture
136 glUseProgram(mTextureProgram);
137 glBindTexture(GL_TEXTURE_2D, texture);
138 glUniform1i(mTextureUniformLocation, 0);
139
140 drawQuad(mTextureProgram, "position", 0.5f);
141
142 // Expect that the rendered quad has the same color as the source texture
143 EXPECT_PIXEL_NEAR(x, y, data[0], data[1], data[2], data[3], 1.0);
144 }
145
146 GLuint mTextureProgram;
147 GLint mTextureUniformLocation;
148 };
149
TEST_P(CopyTexImageTest,RGBAToL)150 TEST_P(CopyTexImageTest, RGBAToL)
151 {
152 GLfloat color[] = {
153 0.25f, 1.0f, 0.75f, 0.5f,
154 };
155
156 GLuint fbo = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color);
157 GLuint tex = createTextureFromCopyTexImage(fbo, GL_LUMINANCE);
158
159 GLubyte expected[] = {
160 64, 64, 64, 255,
161 };
162 verifyResults(tex, expected, 0, 0);
163 }
164
TEST_P(CopyTexImageTest,RGBToL)165 TEST_P(CopyTexImageTest, RGBToL)
166 {
167 // TODO (geofflang): Figure out why CopyTex[Sub]Image doesn't work with
168 // RGB->L on older Intel chips
169 if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
170 {
171 std::cout << "Test skipped on Intel OpenGL." << std::endl;
172 return;
173 }
174
175 GLfloat color[] = {
176 0.25f, 1.0f, 0.75f, 0.5f,
177 };
178
179 GLuint fbo = createFramebuffer(GL_RGB, GL_UNSIGNED_BYTE, color);
180 GLuint tex = createTextureFromCopyTexImage(fbo, GL_LUMINANCE);
181
182 GLubyte expected[] = {
183 64, 64, 64, 255,
184 };
185 verifyResults(tex, expected, 0, 0);
186 }
187
TEST_P(CopyTexImageTest,RGBAToLA)188 TEST_P(CopyTexImageTest, RGBAToLA)
189 {
190 GLfloat color[] = {
191 0.25f, 1.0f, 0.75f, 0.5f,
192 };
193
194 GLuint fbo = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color);
195 GLuint tex = createTextureFromCopyTexImage(fbo, GL_LUMINANCE_ALPHA);
196
197 GLubyte expected[] = {
198 64, 64, 64, 127,
199 };
200 verifyResults(tex, expected, 0, 0);
201 }
202
TEST_P(CopyTexImageTest,RGBAToA)203 TEST_P(CopyTexImageTest, RGBAToA)
204 {
205 GLfloat color[] = {
206 0.25f, 1.0f, 0.75f, 0.5f,
207 };
208
209 GLuint fbo = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color);
210 GLuint tex = createTextureFromCopyTexImage(fbo, GL_ALPHA);
211
212 GLubyte expected[] = {
213 0, 0, 0, 127,
214 };
215 verifyResults(tex, expected, 0, 0);
216 }
217
TEST_P(CopyTexImageTest,SubImageRGBAToL)218 TEST_P(CopyTexImageTest, SubImageRGBAToL)
219 {
220 GLfloat color0[] = {
221 0.25f, 1.0f, 0.75f, 0.5f,
222 };
223 GLuint fbo0 = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color0);
224 GLuint tex = createTextureFromCopyTexImage(fbo0, GL_LUMINANCE);
225
226 GLfloat color1[] = {
227 0.5f, 0.25f, 1.0f, 0.75f,
228 };
229 GLuint fbo1 = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color1);
230 copyTextureWithCopyTexSubImage(fbo1, tex, 2, 4, 5, 6, 8, 8);
231
232 GLubyte expected0[] = {
233 64, 64, 64, 255,
234 };
235 verifyResults(tex, expected0, 0, 0);
236
237 GLubyte expected1[] = {
238 127, 127, 127, 255,
239 };
240 verifyResults(tex, expected1, 7, 7);
241 }
242
TEST_P(CopyTexImageTest,SubImageRGBAToLA)243 TEST_P(CopyTexImageTest, SubImageRGBAToLA)
244 {
245 GLfloat color0[] = {
246 0.25f, 1.0f, 0.75f, 0.5f,
247 };
248 GLuint fbo0 = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color0);
249 GLuint tex = createTextureFromCopyTexImage(fbo0, GL_LUMINANCE_ALPHA);
250
251 GLfloat color1[] = {
252 0.5f, 0.25f, 1.0f, 0.75f,
253 };
254 GLuint fbo1 = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color1);
255 copyTextureWithCopyTexSubImage(fbo1, tex, 2, 4, 5, 6, 8, 8);
256
257 GLubyte expected0[] = {
258 64, 64, 64, 127,
259 };
260 verifyResults(tex, expected0, 0, 0);
261
262 GLubyte expected1[] = {
263 127, 127, 127, 192,
264 };
265 verifyResults(tex, expected1, 7, 7);
266 }
267
TEST_P(CopyTexImageTest,SubImageRGBToL)268 TEST_P(CopyTexImageTest, SubImageRGBToL)
269 {
270 // TODO (geofflang): Figure out why CopyTex[Sub]Image doesn't work with
271 // RGB->L on older Intel chips
272 if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
273 {
274 std::cout << "Test skipped on Intel OpenGL." << std::endl;
275 return;
276 }
277
278 GLfloat color0[] = {
279 0.25f, 1.0f, 0.75f, 0.5f,
280 };
281 GLuint fbo0 = createFramebuffer(GL_RGB, GL_UNSIGNED_BYTE, color0);
282 GLuint tex = createTextureFromCopyTexImage(fbo0, GL_LUMINANCE);
283
284 GLfloat color1[] = {
285 0.5f, 0.25f, 1.0f, 0.75f,
286 };
287 GLuint fbo1 = createFramebuffer(GL_RGB, GL_UNSIGNED_BYTE, color1);
288 copyTextureWithCopyTexSubImage(fbo1, tex, 2, 4, 5, 6, 8, 8);
289
290 GLubyte expected0[] = {
291 64, 64, 64, 255,
292 };
293 verifyResults(tex, expected0, 0, 0);
294
295 GLubyte expected1[] = {
296 127, 127, 127, 255,
297 };
298 verifyResults(tex, expected1, 7, 7);
299 }
300
301 // specialization of CopyTexImageTest is added so that some tests can be explicitly run with an ES3
302 // context
303 class CopyTexImageTestES3 : public CopyTexImageTest
304 {
305 };
306
307 // The test verifies that glCopyTexSubImage2D generates a GL_INVALID_OPERATION error
308 // when the read buffer is GL_NONE.
309 // Reference: GLES 3.0.4, Section 3.8.5 Alternate Texture Image Specification Commands
TEST_P(CopyTexImageTestES3,ReadBufferIsNone)310 TEST_P(CopyTexImageTestES3, ReadBufferIsNone)
311 {
312 GLfloat color[] = {
313 0.25f, 1.0f, 0.75f, 0.5f,
314 };
315
316 GLuint fbo = createFramebuffer(GL_RGBA, GL_UNSIGNED_BYTE, color);
317 GLuint tex = createTextureFromCopyTexImage(fbo, GL_RGBA);
318
319 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
320 glBindTexture(GL_TEXTURE_2D, tex);
321
322 glReadBuffer(GL_NONE);
323
324 EXPECT_GL_NO_ERROR();
325 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 4, 4);
326 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
327
328 glDeleteFramebuffers(1, &fbo);
329 glDeleteTextures(1, &tex);
330 }
331
332 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
333 // tests should be run against.
334 ANGLE_INSTANTIATE_TEST(CopyTexImageTest,
335 ES2_D3D9(),
336 ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE),
337 ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE),
338 ES2_OPENGL(),
339 ES2_OPENGL(3, 3),
340 ES2_OPENGLES());
341
342 ANGLE_INSTANTIATE_TEST(CopyTexImageTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
343 }
344