blob: 1a496d38265300955171e63fdf08bd7b7ca8abb6 [file] [log] [blame]
Jamie Madillf67115c2014-04-22 13:14:05 -04001#include "ANGLETest.h"
2
Austin Kinross18b931d2014-09-29 12:58:31 -07003// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
Geoff Lang0d3683c2014-10-23 11:08:16 -04004ANGLE_TYPED_TEST_CASE(TextureTest, ES2_D3D9, ES2_D3D11);
Austin Kinross18b931d2014-09-29 12:58:31 -07005
6template<typename T>
Jamie Madillf67115c2014-04-22 13:14:05 -04007class TextureTest : public ANGLETest
8{
9protected:
Geoff Lang0d3683c2014-10-23 11:08:16 -040010 TextureTest() : ANGLETest(T::GetGlesMajorVersion(), T::GetPlatform())
Jamie Madillf67115c2014-04-22 13:14:05 -040011 {
12 setWindowWidth(128);
13 setWindowHeight(128);
14 setConfigRedBits(8);
15 setConfigGreenBits(8);
16 setConfigBlueBits(8);
17 setConfigAlphaBits(8);
18 }
19
20 virtual void SetUp()
21 {
22 ANGLETest::SetUp();
Jamie Madilld4cfa572014-07-08 10:00:32 -040023 glGenTextures(1, &mTexture2D);
24 glGenTextures(1, &mTextureCube);
Jamie Madillf67115c2014-04-22 13:14:05 -040025
Jamie Madilld4cfa572014-07-08 10:00:32 -040026 glBindTexture(GL_TEXTURE_2D, mTexture2D);
Jamie Madillf67115c2014-04-22 13:14:05 -040027 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
28 EXPECT_GL_NO_ERROR();
29
Jamie Madilld4cfa572014-07-08 10:00:32 -040030 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
31 glTexStorage2DEXT(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 1, 1);
32 EXPECT_GL_NO_ERROR();
33
Jamie Madillf67115c2014-04-22 13:14:05 -040034 ASSERT_GL_NO_ERROR();
Geoff Langc41e42d2014-04-28 10:58:16 -040035
36 const std::string vertexShaderSource = SHADER_SOURCE
37 (
38 precision highp float;
39 attribute vec4 position;
40 varying vec2 texcoord;
41
Jamie Madill9aca0592014-10-06 16:26:59 -040042 uniform vec2 textureScale;
43
Geoff Langc41e42d2014-04-28 10:58:16 -040044 void main()
45 {
Jamie Madill9aca0592014-10-06 16:26:59 -040046 gl_Position = vec4(position.xy * textureScale, 0.0, 1.0);
Geoff Langc41e42d2014-04-28 10:58:16 -040047 texcoord = (position.xy * 0.5) + 0.5;
48 }
49 );
50
Jamie Madilld4cfa572014-07-08 10:00:32 -040051 const std::string fragmentShaderSource2D = SHADER_SOURCE
Geoff Langc41e42d2014-04-28 10:58:16 -040052 (
53 precision highp float;
54 uniform sampler2D tex;
55 varying vec2 texcoord;
56
57 void main()
58 {
59 gl_FragColor = texture2D(tex, texcoord);
60 }
61 );
62
Jamie Madilld4cfa572014-07-08 10:00:32 -040063 const std::string fragmentShaderSourceCube = SHADER_SOURCE
64 (
65 precision highp float;
66 uniform sampler2D tex2D;
67 uniform samplerCube texCube;
68 varying vec2 texcoord;
69
70 void main()
71 {
72 gl_FragColor = texture2D(tex2D, texcoord);
73 gl_FragColor += textureCube(texCube, vec3(texcoord, 0));
74 }
75 );
76
Jamie Madill5599c8f2014-08-26 13:16:39 -040077 m2DProgram = CompileProgram(vertexShaderSource, fragmentShaderSource2D);
78 mCubeProgram = CompileProgram(vertexShaderSource, fragmentShaderSourceCube);
Jamie Madilld4cfa572014-07-08 10:00:32 -040079 if (m2DProgram == 0 || mCubeProgram == 0)
Geoff Langc41e42d2014-04-28 10:58:16 -040080 {
81 FAIL() << "shader compilation failed.";
82 }
83
Jamie Madilld4cfa572014-07-08 10:00:32 -040084 mTexture2DUniformLocation = glGetUniformLocation(m2DProgram, "tex");
Jamie Madill9aca0592014-10-06 16:26:59 -040085 ASSERT_NE(-1, mTexture2DUniformLocation);
86
87 mTextureScaleUniformLocation = glGetUniformLocation(m2DProgram, "textureScale");
88 ASSERT_NE(-1, mTextureScaleUniformLocation);
89
90 glUseProgram(m2DProgram);
91 glUniform2f(mTextureScaleUniformLocation, 1.0f, 1.0f);
92 glUseProgram(0);
93 ASSERT_GL_NO_ERROR();
Jamie Madillf67115c2014-04-22 13:14:05 -040094 }
95
96 virtual void TearDown()
97 {
Jamie Madilld4cfa572014-07-08 10:00:32 -040098 glDeleteTextures(1, &mTexture2D);
99 glDeleteTextures(1, &mTextureCube);
100 glDeleteProgram(m2DProgram);
101 glDeleteProgram(mCubeProgram);
Jamie Madillf67115c2014-04-22 13:14:05 -0400102
103 ANGLETest::TearDown();
104 }
105
Jamie Madilld4cfa572014-07-08 10:00:32 -0400106 GLuint mTexture2D;
107 GLuint mTextureCube;
Geoff Langc41e42d2014-04-28 10:58:16 -0400108
Jamie Madilld4cfa572014-07-08 10:00:32 -0400109 GLuint m2DProgram;
110 GLuint mCubeProgram;
111 GLint mTexture2DUniformLocation;
Jamie Madill9aca0592014-10-06 16:26:59 -0400112 GLint mTextureScaleUniformLocation;
Jamie Madillf67115c2014-04-22 13:14:05 -0400113};
114
Austin Kinross18b931d2014-09-29 12:58:31 -0700115TYPED_TEST(TextureTest, NegativeAPISubImage)
Jamie Madillf67115c2014-04-22 13:14:05 -0400116{
Jamie Madilld4cfa572014-07-08 10:00:32 -0400117 glBindTexture(GL_TEXTURE_2D, mTexture2D);
Jamie Madillf67115c2014-04-22 13:14:05 -0400118 EXPECT_GL_ERROR(GL_NO_ERROR);
119
120 const GLubyte *pixels[20] = { 0 };
121 glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
122 EXPECT_GL_ERROR(GL_INVALID_VALUE);
123}
Geoff Langc41e42d2014-04-28 10:58:16 -0400124
Austin Kinross18b931d2014-09-29 12:58:31 -0700125TYPED_TEST(TextureTest, ZeroSizedUploads)
Geoff Langc41e42d2014-04-28 10:58:16 -0400126{
Jamie Madilld4cfa572014-07-08 10:00:32 -0400127 glBindTexture(GL_TEXTURE_2D, mTexture2D);
Geoff Langc41e42d2014-04-28 10:58:16 -0400128 EXPECT_GL_ERROR(GL_NO_ERROR);
129
130 // Use the texture first to make sure it's in video memory
Jamie Madilld4cfa572014-07-08 10:00:32 -0400131 glUseProgram(m2DProgram);
132 glUniform1i(mTexture2DUniformLocation, 0);
133 drawQuad(m2DProgram, "position", 0.5f);
Geoff Langc41e42d2014-04-28 10:58:16 -0400134
135 const GLubyte *pixel[4] = { 0 };
136
137 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
138 EXPECT_GL_NO_ERROR();
139
140 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
141 EXPECT_GL_NO_ERROR();
142
143 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
144 EXPECT_GL_NO_ERROR();
145}
Jamie Madilld4cfa572014-07-08 10:00:32 -0400146
147// Test drawing with two texture types, to trigger an ANGLE bug in validation
Austin Kinross18b931d2014-09-29 12:58:31 -0700148TYPED_TEST(TextureTest, CubeMapBug)
Jamie Madilld4cfa572014-07-08 10:00:32 -0400149{
150 glActiveTexture(GL_TEXTURE0);
151 glBindTexture(GL_TEXTURE_2D, mTexture2D);
152 glActiveTexture(GL_TEXTURE1);
153 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
154 EXPECT_GL_ERROR(GL_NO_ERROR);
155
156 glUseProgram(mCubeProgram);
157 GLint tex2DUniformLocation = glGetUniformLocation(mCubeProgram, "tex2D");
158 GLint texCubeUniformLocation = glGetUniformLocation(mCubeProgram, "texCube");
159 EXPECT_NE(-1, tex2DUniformLocation);
160 EXPECT_NE(-1, texCubeUniformLocation);
161 glUniform1i(tex2DUniformLocation, 0);
162 glUniform1i(texCubeUniformLocation, 1);
163 drawQuad(mCubeProgram, "position", 0.5f);
164 EXPECT_GL_NO_ERROR();
165}
Jamie Madill9aca0592014-10-06 16:26:59 -0400166
167// Copy of a test in conformance/textures/texture-mips, to test generate mipmaps
168TYPED_TEST(TextureTest, MipmapsTwice)
169{
170 int px = getWindowWidth() / 2;
171 int py = getWindowHeight() / 2;
172
173 glActiveTexture(GL_TEXTURE0);
174 glBindTexture(GL_TEXTURE_2D, mTexture2D);
175
176 // Fill with red
177 std::vector<GLubyte> pixels(4 * 16 * 16);
178 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
179 {
180 pixels[pixelId * 4 + 0] = 255;
181 pixels[pixelId * 4 + 1] = 0;
182 pixels[pixelId * 4 + 2] = 0;
183 pixels[pixelId * 4 + 3] = 255;
184 }
185
186 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
187 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
188 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
189 glGenerateMipmap(GL_TEXTURE_2D);
190
191 glUseProgram(m2DProgram);
192 glUniform1i(mTexture2DUniformLocation, 0);
193 glUniform2f(mTextureScaleUniformLocation, 0.0625f, 0.0625f);
194 drawQuad(m2DProgram, "position", 0.5f);
195 EXPECT_GL_NO_ERROR();
196 EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
197
198 // Fill with blue
199 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
200 {
201 pixels[pixelId * 4 + 0] = 0;
202 pixels[pixelId * 4 + 1] = 0;
203 pixels[pixelId * 4 + 2] = 255;
204 pixels[pixelId * 4 + 3] = 255;
205 }
206
207 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
208 glGenerateMipmap(GL_TEXTURE_2D);
209
210 // Fill with green
211 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
212 {
213 pixels[pixelId * 4 + 0] = 0;
214 pixels[pixelId * 4 + 1] = 255;
215 pixels[pixelId * 4 + 2] = 0;
216 pixels[pixelId * 4 + 3] = 255;
217 }
218
219 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
220 glGenerateMipmap(GL_TEXTURE_2D);
221
222 drawQuad(m2DProgram, "position", 0.5f);
223
224 EXPECT_GL_NO_ERROR();
225 EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
226}
Jamie Madillf8fccb32014-11-12 15:05:26 -0500227
Jamie Madilleb32a2e2014-12-10 14:27:53 -0500228// Test creating a FBO with a cube map render target, to test an ANGLE bug
229// https://code.google.com/p/angleproject/issues/detail?id=849
230TYPED_TEST(TextureTest, CubeMapFBO)
231{
232 GLuint fbo;
233 glGenFramebuffers(1, &fbo);
234 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
235
236 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
237 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, mTextureCube, 0);
238
239 EXPECT_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
240
241 glDeleteFramebuffers(1, &fbo);
242
243 EXPECT_GL_NO_ERROR();
244}
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000245
246// Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a default color.
247TYPED_TEST(TextureTest, TexStorage)
248{
249 int width = getWindowWidth();
250 int height = getWindowHeight();
251
252 GLuint tex2D;
253 glGenTextures(1, &tex2D);
254 glActiveTexture(GL_TEXTURE0);
255 glBindTexture(GL_TEXTURE_2D, tex2D);
256
257 // Fill with red
258 std::vector<GLubyte> pixels(3 * 16 * 16);
259 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
260 {
261 pixels[pixelId * 3 + 0] = 255;
262 pixels[pixelId * 3 + 1] = 0;
263 pixels[pixelId * 3 + 2] = 0;
264 }
265
266 // ANGLE internally uses RGBA as the DirectX format for RGB images
267 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent alpha color.
268 // The data is kept in a CPU-side image and the image is marked as dirty.
269 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
270
271 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
272 // glTexSubImage2D should take into account that the image is dirty.
273 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
274 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
275 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
276
277 glUseProgram(m2DProgram);
278 glUniform1i(mTexture2DUniformLocation, 0);
279 glUniform2f(mTextureScaleUniformLocation, 1.f, 1.f);
280 drawQuad(m2DProgram, "position", 0.5f);
281 glDeleteTextures(1, &tex2D);
282 EXPECT_GL_NO_ERROR();
283 EXPECT_PIXEL_EQ(3*width/4, 3*height/4, 0, 0, 0, 255);
284 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
285}
286
287// Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has initialized the image with a default color.
288TYPED_TEST(TextureTest, TexStorageWithPBO)
289{
290 if (extensionEnabled("NV_pixel_buffer_object"))
291 {
292 int width = getWindowWidth();
293 int height = getWindowHeight();
294
295 GLuint tex2D;
296 glGenTextures(1, &tex2D);
297 glActiveTexture(GL_TEXTURE0);
298 glBindTexture(GL_TEXTURE_2D, tex2D);
299
300 // Fill with red
301 std::vector<GLubyte> pixels(3 * 16 * 16);
302 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
303 {
304 pixels[pixelId * 3 + 0] = 255;
305 pixels[pixelId * 3 + 1] = 0;
306 pixels[pixelId * 3 + 2] = 0;
307 }
308
309 // Read 16x16 region from red backbuffer to PBO
310 GLuint pbo;
311 glGenBuffers(1, &pbo);
312 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
313 glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
314
315 // ANGLE internally uses RGBA as the DirectX format for RGB images
316 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent alpha color.
317 // The data is kept in a CPU-side image and the image is marked as dirty.
318 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
319
320 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
321 // glTexSubImage2D should take into account that the image is dirty.
322 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, NULL);
323 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
324 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
325
326 glUseProgram(m2DProgram);
327 glUniform1i(mTexture2DUniformLocation, 0);
328 glUniform2f(mTextureScaleUniformLocation, 1.f, 1.f);
329 drawQuad(m2DProgram, "position", 0.5f);
330 glDeleteTextures(1, &tex2D);
331 glDeleteTextures(1, &pbo);
332 EXPECT_GL_NO_ERROR();
333 EXPECT_PIXEL_EQ(3 * width / 4, 3 * height / 4, 0, 0, 0, 255);
334 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
335 }
336}