blob: b07a7de4899a53e556307f2f452fb418d348c3e8 [file] [log] [blame]
Jamie Madillfa05f602015-05-07 13:47:11 -04001//
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
Corentin Wallezd3970de2015-05-14 11:07:48 -04007#include "test_utils/ANGLETest.h"
Jamie Madillf67115c2014-04-22 13:14:05 -04008
Jamie Madillfa05f602015-05-07 13:47:11 -04009using namespace angle;
Austin Kinross18b931d2014-09-29 12:58:31 -070010
Jamie Madillfa05f602015-05-07 13:47:11 -040011namespace
12{
13
Jamie Madillf67115c2014-04-22 13:14:05 -040014class TextureTest : public ANGLETest
15{
Jamie Madillbc393df2015-01-29 13:46:07 -050016 protected:
Jamie Madillfa05f602015-05-07 13:47:11 -040017 TextureTest()
Jamie Madillf67115c2014-04-22 13:14:05 -040018 {
19 setWindowWidth(128);
20 setWindowHeight(128);
21 setConfigRedBits(8);
22 setConfigGreenBits(8);
23 setConfigBlueBits(8);
24 setConfigAlphaBits(8);
25 }
26
Jamie Madillfa05f602015-05-07 13:47:11 -040027 void SetUp() override
Jamie Madillf67115c2014-04-22 13:14:05 -040028 {
29 ANGLETest::SetUp();
Jamie Madilld4cfa572014-07-08 10:00:32 -040030 glGenTextures(1, &mTexture2D);
31 glGenTextures(1, &mTextureCube);
Jamie Madillf67115c2014-04-22 13:14:05 -040032
Jamie Madilld4cfa572014-07-08 10:00:32 -040033 glBindTexture(GL_TEXTURE_2D, mTexture2D);
Jamie Madillf67115c2014-04-22 13:14:05 -040034 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
35 EXPECT_GL_NO_ERROR();
36
Jamie Madilld4cfa572014-07-08 10:00:32 -040037 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
38 glTexStorage2DEXT(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 1, 1);
39 EXPECT_GL_NO_ERROR();
40
Jamie Madillf67115c2014-04-22 13:14:05 -040041 ASSERT_GL_NO_ERROR();
Geoff Langc41e42d2014-04-28 10:58:16 -040042
43 const std::string vertexShaderSource = SHADER_SOURCE
44 (
45 precision highp float;
46 attribute vec4 position;
47 varying vec2 texcoord;
48
Jamie Madill9aca0592014-10-06 16:26:59 -040049 uniform vec2 textureScale;
50
Geoff Langc41e42d2014-04-28 10:58:16 -040051 void main()
52 {
Jamie Madill9aca0592014-10-06 16:26:59 -040053 gl_Position = vec4(position.xy * textureScale, 0.0, 1.0);
Geoff Langc41e42d2014-04-28 10:58:16 -040054 texcoord = (position.xy * 0.5) + 0.5;
55 }
56 );
57
Jamie Madilld4cfa572014-07-08 10:00:32 -040058 const std::string fragmentShaderSource2D = SHADER_SOURCE
Geoff Langc41e42d2014-04-28 10:58:16 -040059 (
60 precision highp float;
61 uniform sampler2D tex;
62 varying vec2 texcoord;
63
64 void main()
65 {
66 gl_FragColor = texture2D(tex, texcoord);
67 }
68 );
69
Jamie Madilld4cfa572014-07-08 10:00:32 -040070 const std::string fragmentShaderSourceCube = SHADER_SOURCE
71 (
72 precision highp float;
73 uniform sampler2D tex2D;
74 uniform samplerCube texCube;
75 varying vec2 texcoord;
76
77 void main()
78 {
79 gl_FragColor = texture2D(tex2D, texcoord);
80 gl_FragColor += textureCube(texCube, vec3(texcoord, 0));
81 }
82 );
83
Jamie Madill5599c8f2014-08-26 13:16:39 -040084 m2DProgram = CompileProgram(vertexShaderSource, fragmentShaderSource2D);
85 mCubeProgram = CompileProgram(vertexShaderSource, fragmentShaderSourceCube);
Jamie Madill2453dbc2015-07-14 11:35:42 -040086 ASSERT_NE(0u, m2DProgram);
87 ASSERT_NE(0u, mCubeProgram);
Geoff Langc41e42d2014-04-28 10:58:16 -040088
Jamie Madilld4cfa572014-07-08 10:00:32 -040089 mTexture2DUniformLocation = glGetUniformLocation(m2DProgram, "tex");
Jamie Madill9aca0592014-10-06 16:26:59 -040090 ASSERT_NE(-1, mTexture2DUniformLocation);
91
92 mTextureScaleUniformLocation = glGetUniformLocation(m2DProgram, "textureScale");
93 ASSERT_NE(-1, mTextureScaleUniformLocation);
94
95 glUseProgram(m2DProgram);
96 glUniform2f(mTextureScaleUniformLocation, 1.0f, 1.0f);
97 glUseProgram(0);
98 ASSERT_GL_NO_ERROR();
Jamie Madillf67115c2014-04-22 13:14:05 -040099 }
100
Jamie Madillfa05f602015-05-07 13:47:11 -0400101 void TearDown() override
Jamie Madillf67115c2014-04-22 13:14:05 -0400102 {
Jamie Madilld4cfa572014-07-08 10:00:32 -0400103 glDeleteTextures(1, &mTexture2D);
104 glDeleteTextures(1, &mTextureCube);
105 glDeleteProgram(m2DProgram);
106 glDeleteProgram(mCubeProgram);
Jamie Madillf67115c2014-04-22 13:14:05 -0400107
108 ANGLETest::TearDown();
109 }
110
Jamie Madillbc393df2015-01-29 13:46:07 -0500111 // Tests CopyTexSubImage with floating point textures of various formats.
112 void testFloatCopySubImage(int sourceImageChannels, int destImageChannels)
113 {
Geoff Langbde666a2015-04-07 17:17:08 -0400114 // TODO(jmadill): Figure out why this is broken on Intel D3D11
115 if (isIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
116 {
117 std::cout << "Test skipped on Intel D3D11." << std::endl;
118 return;
119 }
120
Geoff Langfbfa47c2015-03-31 11:26:00 -0400121 if (getClientVersion() < 3)
122 {
123 if (!extensionEnabled("GL_OES_texture_float"))
124 {
125 std::cout << "Test skipped due to missing GL_OES_texture_float." << std::endl;
126 return;
127 }
128
129 if ((sourceImageChannels < 3 || destImageChannels < 3) && !extensionEnabled("GL_EXT_texture_rg"))
130 {
131 std::cout << "Test skipped due to missing GL_EXT_texture_rg." << std::endl;
132 return;
133 }
134 }
135
Jamie Madillbc393df2015-01-29 13:46:07 -0500136 GLfloat sourceImageData[4][16] =
137 {
138 { // R
139 1.0f,
140 0.0f,
141 0.0f,
142 1.0f
143 },
144 { // RG
145 1.0f, 0.0f,
146 0.0f, 1.0f,
147 0.0f, 0.0f,
148 1.0f, 1.0f
149 },
150 { // RGB
151 1.0f, 0.0f, 0.0f,
152 0.0f, 1.0f, 0.0f,
153 0.0f, 0.0f, 1.0f,
154 1.0f, 1.0f, 0.0f
155 },
156 { // RGBA
157 1.0f, 0.0f, 0.0f, 1.0f,
158 0.0f, 1.0f, 0.0f, 1.0f,
159 0.0f, 0.0f, 1.0f, 1.0f,
160 1.0f, 1.0f, 0.0f, 1.0f
161 },
162 };
163
164 GLenum imageFormats[] =
165 {
166 GL_R32F,
167 GL_RG32F,
168 GL_RGB32F,
169 GL_RGBA32F,
170 };
171
172 GLenum sourceUnsizedFormats[] =
173 {
174 GL_RED,
175 GL_RG,
176 GL_RGB,
177 GL_RGBA,
178 };
179
180 GLuint textures[2];
181
182 glGenTextures(2, textures);
183
184 GLfloat *imageData = sourceImageData[sourceImageChannels - 1];
185 GLenum sourceImageFormat = imageFormats[sourceImageChannels - 1];
186 GLenum sourceUnsizedFormat = sourceUnsizedFormats[sourceImageChannels - 1];
187 GLenum destImageFormat = imageFormats[destImageChannels - 1];
188
189 glBindTexture(GL_TEXTURE_2D, textures[0]);
190 glTexStorage2DEXT(GL_TEXTURE_2D, 1, sourceImageFormat, 2, 2);
191 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
192 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
193 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, sourceUnsizedFormat, GL_FLOAT, imageData);
194
hendrikwb27f79a2015-03-04 11:26:46 -0800195 if (sourceImageChannels < 3 && !extensionEnabled("GL_EXT_texture_rg"))
Jamie Madillbc393df2015-01-29 13:46:07 -0500196 {
197 // This is not supported
198 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
199 }
200 else
201 {
202 ASSERT_GL_NO_ERROR();
203 }
204
205 GLuint fbo;
206 glGenFramebuffers(1, &fbo);
207 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
208 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
209
210 glBindTexture(GL_TEXTURE_2D, textures[1]);
211 glTexStorage2DEXT(GL_TEXTURE_2D, 1, destImageFormat, 2, 2);
212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
213 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
214
215 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 2, 2);
216 ASSERT_GL_NO_ERROR();
217
218 glBindFramebuffer(GL_FRAMEBUFFER, 0);
219 drawQuad(m2DProgram, "position", 0.5f);
Jamie Madillbc393df2015-01-29 13:46:07 -0500220
221 int testImageChannels = std::min(sourceImageChannels, destImageChannels);
222
223 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
224 if (testImageChannels > 1)
225 {
226 EXPECT_PIXEL_EQ(getWindowHeight() - 1, 0, 0, 255, 0, 255);
227 EXPECT_PIXEL_EQ(getWindowHeight() - 1, getWindowWidth() - 1, 255, 255, 0, 255);
228 if (testImageChannels > 2)
229 {
230 EXPECT_PIXEL_EQ(0, getWindowWidth() - 1, 0, 0, 255, 255);
231 }
232 }
233
234 glDeleteFramebuffers(1, &fbo);
235 glDeleteTextures(2, textures);
236
237 ASSERT_GL_NO_ERROR();
238 }
239
Jamie Madilld4cfa572014-07-08 10:00:32 -0400240 GLuint mTexture2D;
241 GLuint mTextureCube;
Geoff Langc41e42d2014-04-28 10:58:16 -0400242
Jamie Madilld4cfa572014-07-08 10:00:32 -0400243 GLuint m2DProgram;
244 GLuint mCubeProgram;
245 GLint mTexture2DUniformLocation;
Jamie Madill9aca0592014-10-06 16:26:59 -0400246 GLint mTextureScaleUniformLocation;
Jamie Madillf67115c2014-04-22 13:14:05 -0400247};
248
Jamie Madill2453dbc2015-07-14 11:35:42 -0400249class TextureTestES3 : public ANGLETest
250{
251 protected:
252 TextureTestES3()
253 : m2DArrayTexture(0),
254 m2DArrayProgram(0),
255 mTextureArrayLocation(-1)
256 {
257 setWindowWidth(128);
258 setWindowHeight(128);
259 setConfigRedBits(8);
260 setConfigGreenBits(8);
261 setConfigBlueBits(8);
262 setConfigAlphaBits(8);
263 }
264
265 void SetUp() override
266 {
267 ANGLETest::SetUp();
268
269 const std::string vertexShaderSource =
270 "#version 300 es\n"
271 "out vec2 texcoord;\n"
272 "in vec4 position;\n"
273 "void main() {\n"
274 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
275 " texcoord = (position.xy * 0.5) + 0.5;\n"
276 "}";
277
278 const std::string fragmentShaderSource2DArray =
279 "#version 300 es\n"
280 "precision highp float;\n"
281 "uniform sampler2DArray tex2DArray;\n"
282 "in vec2 texcoord;\n"
283 "out vec4 fragColor;\n"
284 "void main()\n"
285 "{\n"
286 " fragColor = texture(tex2DArray, vec3(texcoord.x, texcoord.y, 0.0));\n"
287 "}\n";
288
289 m2DArrayProgram = CompileProgram(vertexShaderSource, fragmentShaderSource2DArray);
290 ASSERT_NE(0u, m2DArrayProgram);
291
292 mTextureArrayLocation = glGetUniformLocation(m2DArrayProgram, "tex2DArray");
293 ASSERT_NE(-1, mTextureArrayLocation);
294
295 glGenTextures(1, &m2DArrayTexture);
296 ASSERT_GL_NO_ERROR();
297 }
298
299 void TearDown() override
300 {
301 glDeleteTextures(1, &m2DArrayTexture);
302 glDeleteProgram(m2DArrayProgram);
303 }
304
305 GLuint m2DArrayTexture;
306 GLuint m2DArrayProgram;
307 GLint mTextureArrayLocation;
308};
309
Jamie Madillfa05f602015-05-07 13:47:11 -0400310TEST_P(TextureTest, NegativeAPISubImage)
Jamie Madillf67115c2014-04-22 13:14:05 -0400311{
Jamie Madilld4cfa572014-07-08 10:00:32 -0400312 glBindTexture(GL_TEXTURE_2D, mTexture2D);
Jamie Madillf67115c2014-04-22 13:14:05 -0400313 EXPECT_GL_ERROR(GL_NO_ERROR);
314
315 const GLubyte *pixels[20] = { 0 };
316 glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
317 EXPECT_GL_ERROR(GL_INVALID_VALUE);
318}
Geoff Langc41e42d2014-04-28 10:58:16 -0400319
Jamie Madillfa05f602015-05-07 13:47:11 -0400320TEST_P(TextureTest, ZeroSizedUploads)
Geoff Langc41e42d2014-04-28 10:58:16 -0400321{
Jamie Madilld4cfa572014-07-08 10:00:32 -0400322 glBindTexture(GL_TEXTURE_2D, mTexture2D);
Geoff Langc41e42d2014-04-28 10:58:16 -0400323 EXPECT_GL_ERROR(GL_NO_ERROR);
324
325 // Use the texture first to make sure it's in video memory
Jamie Madilld4cfa572014-07-08 10:00:32 -0400326 glUseProgram(m2DProgram);
327 glUniform1i(mTexture2DUniformLocation, 0);
328 drawQuad(m2DProgram, "position", 0.5f);
Geoff Langc41e42d2014-04-28 10:58:16 -0400329
330 const GLubyte *pixel[4] = { 0 };
331
332 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
333 EXPECT_GL_NO_ERROR();
334
335 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
336 EXPECT_GL_NO_ERROR();
337
338 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
339 EXPECT_GL_NO_ERROR();
340}
Jamie Madilld4cfa572014-07-08 10:00:32 -0400341
342// Test drawing with two texture types, to trigger an ANGLE bug in validation
Jamie Madillfa05f602015-05-07 13:47:11 -0400343TEST_P(TextureTest, CubeMapBug)
Jamie Madilld4cfa572014-07-08 10:00:32 -0400344{
345 glActiveTexture(GL_TEXTURE0);
346 glBindTexture(GL_TEXTURE_2D, mTexture2D);
347 glActiveTexture(GL_TEXTURE1);
348 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
349 EXPECT_GL_ERROR(GL_NO_ERROR);
350
351 glUseProgram(mCubeProgram);
352 GLint tex2DUniformLocation = glGetUniformLocation(mCubeProgram, "tex2D");
353 GLint texCubeUniformLocation = glGetUniformLocation(mCubeProgram, "texCube");
354 EXPECT_NE(-1, tex2DUniformLocation);
355 EXPECT_NE(-1, texCubeUniformLocation);
356 glUniform1i(tex2DUniformLocation, 0);
357 glUniform1i(texCubeUniformLocation, 1);
358 drawQuad(mCubeProgram, "position", 0.5f);
359 EXPECT_GL_NO_ERROR();
360}
Jamie Madill9aca0592014-10-06 16:26:59 -0400361
362// Copy of a test in conformance/textures/texture-mips, to test generate mipmaps
Jamie Madillfa05f602015-05-07 13:47:11 -0400363TEST_P(TextureTest, MipmapsTwice)
Jamie Madill9aca0592014-10-06 16:26:59 -0400364{
365 int px = getWindowWidth() / 2;
366 int py = getWindowHeight() / 2;
367
368 glActiveTexture(GL_TEXTURE0);
369 glBindTexture(GL_TEXTURE_2D, mTexture2D);
370
371 // Fill with red
372 std::vector<GLubyte> pixels(4 * 16 * 16);
373 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
374 {
375 pixels[pixelId * 4 + 0] = 255;
376 pixels[pixelId * 4 + 1] = 0;
377 pixels[pixelId * 4 + 2] = 0;
378 pixels[pixelId * 4 + 3] = 255;
379 }
380
381 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
382 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
383 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
384 glGenerateMipmap(GL_TEXTURE_2D);
385
386 glUseProgram(m2DProgram);
387 glUniform1i(mTexture2DUniformLocation, 0);
388 glUniform2f(mTextureScaleUniformLocation, 0.0625f, 0.0625f);
389 drawQuad(m2DProgram, "position", 0.5f);
390 EXPECT_GL_NO_ERROR();
391 EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
392
393 // Fill with blue
394 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
395 {
396 pixels[pixelId * 4 + 0] = 0;
397 pixels[pixelId * 4 + 1] = 0;
398 pixels[pixelId * 4 + 2] = 255;
399 pixels[pixelId * 4 + 3] = 255;
400 }
401
402 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
403 glGenerateMipmap(GL_TEXTURE_2D);
404
405 // Fill with green
406 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
407 {
408 pixels[pixelId * 4 + 0] = 0;
409 pixels[pixelId * 4 + 1] = 255;
410 pixels[pixelId * 4 + 2] = 0;
411 pixels[pixelId * 4 + 3] = 255;
412 }
413
414 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
415 glGenerateMipmap(GL_TEXTURE_2D);
416
417 drawQuad(m2DProgram, "position", 0.5f);
418
419 EXPECT_GL_NO_ERROR();
420 EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
421}
Jamie Madillf8fccb32014-11-12 15:05:26 -0500422
Jamie Madilleb32a2e2014-12-10 14:27:53 -0500423// Test creating a FBO with a cube map render target, to test an ANGLE bug
424// https://code.google.com/p/angleproject/issues/detail?id=849
Jamie Madillfa05f602015-05-07 13:47:11 -0400425TEST_P(TextureTest, CubeMapFBO)
Jamie Madilleb32a2e2014-12-10 14:27:53 -0500426{
427 GLuint fbo;
428 glGenFramebuffers(1, &fbo);
429 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
430
431 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
432 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, mTextureCube, 0);
433
Corentin Wallez322653b2015-06-17 18:33:56 +0200434 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
Jamie Madilleb32a2e2014-12-10 14:27:53 -0500435
436 glDeleteFramebuffers(1, &fbo);
437
438 EXPECT_GL_NO_ERROR();
439}
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000440
441// Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a default color.
Jamie Madillfa05f602015-05-07 13:47:11 -0400442TEST_P(TextureTest, TexStorage)
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000443{
444 int width = getWindowWidth();
445 int height = getWindowHeight();
446
447 GLuint tex2D;
448 glGenTextures(1, &tex2D);
449 glActiveTexture(GL_TEXTURE0);
450 glBindTexture(GL_TEXTURE_2D, tex2D);
451
452 // Fill with red
453 std::vector<GLubyte> pixels(3 * 16 * 16);
454 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
455 {
456 pixels[pixelId * 3 + 0] = 255;
457 pixels[pixelId * 3 + 1] = 0;
458 pixels[pixelId * 3 + 2] = 0;
459 }
460
461 // ANGLE internally uses RGBA as the DirectX format for RGB images
462 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent alpha color.
463 // The data is kept in a CPU-side image and the image is marked as dirty.
464 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
465
466 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
467 // glTexSubImage2D should take into account that the image is dirty.
468 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
469 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
470 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
471
472 glUseProgram(m2DProgram);
473 glUniform1i(mTexture2DUniformLocation, 0);
474 glUniform2f(mTextureScaleUniformLocation, 1.f, 1.f);
475 drawQuad(m2DProgram, "position", 0.5f);
476 glDeleteTextures(1, &tex2D);
477 EXPECT_GL_NO_ERROR();
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000478 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
Geoff Langfbfa47c2015-03-31 11:26:00 -0400479
480 // Validate that the region of the texture without data has an alpha of 1.0
481 GLubyte pixel[4];
482 glReadPixels(3 * width / 4, 3 * height / 4, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
483 EXPECT_EQ(pixel[3], 255);
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000484}
485
486// Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has initialized the image with a default color.
Jamie Madillfa05f602015-05-07 13:47:11 -0400487TEST_P(TextureTest, TexStorageWithPBO)
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000488{
489 if (extensionEnabled("NV_pixel_buffer_object"))
490 {
491 int width = getWindowWidth();
492 int height = getWindowHeight();
493
494 GLuint tex2D;
495 glGenTextures(1, &tex2D);
496 glActiveTexture(GL_TEXTURE0);
497 glBindTexture(GL_TEXTURE_2D, tex2D);
498
499 // Fill with red
500 std::vector<GLubyte> pixels(3 * 16 * 16);
501 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
502 {
503 pixels[pixelId * 3 + 0] = 255;
504 pixels[pixelId * 3 + 1] = 0;
505 pixels[pixelId * 3 + 2] = 0;
506 }
507
508 // Read 16x16 region from red backbuffer to PBO
509 GLuint pbo;
510 glGenBuffers(1, &pbo);
511 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
512 glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
513
514 // ANGLE internally uses RGBA as the DirectX format for RGB images
515 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent alpha color.
516 // The data is kept in a CPU-side image and the image is marked as dirty.
517 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
518
519 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
520 // glTexSubImage2D should take into account that the image is dirty.
521 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, NULL);
522 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
523 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
524
525 glUseProgram(m2DProgram);
526 glUniform1i(mTexture2DUniformLocation, 0);
527 glUniform2f(mTextureScaleUniformLocation, 1.f, 1.f);
528 drawQuad(m2DProgram, "position", 0.5f);
529 glDeleteTextures(1, &tex2D);
530 glDeleteTextures(1, &pbo);
531 EXPECT_GL_NO_ERROR();
532 EXPECT_PIXEL_EQ(3 * width / 4, 3 * height / 4, 0, 0, 0, 255);
533 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
534 }
535}
Jamie Madillbc393df2015-01-29 13:46:07 -0500536
537// See description on testFloatCopySubImage
Jamie Madillfa05f602015-05-07 13:47:11 -0400538TEST_P(TextureTest, CopySubImageFloat_R_R)
Jamie Madillbc393df2015-01-29 13:46:07 -0500539{
540 testFloatCopySubImage(1, 1);
541}
542
Jamie Madillfa05f602015-05-07 13:47:11 -0400543TEST_P(TextureTest, CopySubImageFloat_RG_R)
Jamie Madillbc393df2015-01-29 13:46:07 -0500544{
545 testFloatCopySubImage(2, 1);
546}
547
Jamie Madillfa05f602015-05-07 13:47:11 -0400548TEST_P(TextureTest, CopySubImageFloat_RG_RG)
Jamie Madillbc393df2015-01-29 13:46:07 -0500549{
550 testFloatCopySubImage(2, 2);
551}
552
Jamie Madillfa05f602015-05-07 13:47:11 -0400553TEST_P(TextureTest, CopySubImageFloat_RGB_R)
Jamie Madillbc393df2015-01-29 13:46:07 -0500554{
555 testFloatCopySubImage(3, 1);
556}
557
Jamie Madillfa05f602015-05-07 13:47:11 -0400558TEST_P(TextureTest, CopySubImageFloat_RGB_RG)
Jamie Madillbc393df2015-01-29 13:46:07 -0500559{
560 testFloatCopySubImage(3, 2);
561}
562
Jamie Madillfa05f602015-05-07 13:47:11 -0400563TEST_P(TextureTest, CopySubImageFloat_RGB_RGB)
Jamie Madillbc393df2015-01-29 13:46:07 -0500564{
565 testFloatCopySubImage(3, 3);
566}
567
Jamie Madillfa05f602015-05-07 13:47:11 -0400568TEST_P(TextureTest, CopySubImageFloat_RGBA_R)
Jamie Madillbc393df2015-01-29 13:46:07 -0500569{
570 testFloatCopySubImage(4, 1);
571}
572
Jamie Madillfa05f602015-05-07 13:47:11 -0400573TEST_P(TextureTest, CopySubImageFloat_RGBA_RG)
Jamie Madillbc393df2015-01-29 13:46:07 -0500574{
575 testFloatCopySubImage(4, 2);
576}
577
Jamie Madillfa05f602015-05-07 13:47:11 -0400578TEST_P(TextureTest, CopySubImageFloat_RGBA_RGB)
Jamie Madillbc393df2015-01-29 13:46:07 -0500579{
580 testFloatCopySubImage(4, 3);
581}
582
Jamie Madillfa05f602015-05-07 13:47:11 -0400583TEST_P(TextureTest, CopySubImageFloat_RGBA_RGBA)
Jamie Madillbc393df2015-01-29 13:46:07 -0500584{
585 testFloatCopySubImage(4, 4);
586}
Austin Kinross07285142015-03-26 11:36:16 -0700587
588// Port of https://www.khronos.org/registry/webgl/conformance-suites/1.0.3/conformance/textures/texture-npot.html
589// Run against GL_ALPHA/UNSIGNED_BYTE format, to ensure that D3D11 Feature Level 9_3 correctly handles GL_ALPHA
Jamie Madillfa05f602015-05-07 13:47:11 -0400590TEST_P(TextureTest, TextureNPOT_GL_ALPHA_UBYTE)
Austin Kinross07285142015-03-26 11:36:16 -0700591{
592 const int npotTexSize = 5;
593 const int potTexSize = 4; // Should be less than npotTexSize
594 GLuint tex2D;
595
596 if (extensionEnabled("GL_OES_texture_npot"))
597 {
598 // This test isn't applicable if texture_npot is enabled
599 return;
600 }
601
602 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
603
604 glActiveTexture(GL_TEXTURE0);
605 glGenTextures(1, &tex2D);
606 glBindTexture(GL_TEXTURE_2D, tex2D);
607
608 std::vector<GLubyte> pixels(1 * npotTexSize * npotTexSize);
609 for (size_t pixelId = 0; pixelId < npotTexSize * npotTexSize; ++pixelId)
610 {
611 pixels[pixelId] = 64;
612 }
613
614 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
615 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
616
617 // Check that an NPOT texture not on level 0 generates INVALID_VALUE
618 glTexImage2D(GL_TEXTURE_2D, 1, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
619 EXPECT_GL_ERROR(GL_INVALID_VALUE);
620
621 // Check that an NPOT texture on level 0 succeeds
622 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
623 EXPECT_GL_NO_ERROR();
624
625 // Check that generateMipmap fails on NPOT
626 glGenerateMipmap(GL_TEXTURE_2D);
627 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
628
629 // Check that nothing is drawn if filtering is not correct for NPOT
630 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
631 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
632 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
633 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
634 glClear(GL_COLOR_BUFFER_BIT);
635 drawQuad(m2DProgram, "position", 1.0f);
636 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
637
638 // NPOT texture with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255
639 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
640 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
641 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
642 glClear(GL_COLOR_BUFFER_BIT);
643 drawQuad(m2DProgram, "position", 1.0f);
644 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
645
646 // NPOT texture with TEXTURE_MIN_FILTER set to LINEAR should draw
647 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
648 glClear(GL_COLOR_BUFFER_BIT);
649 drawQuad(m2DProgram, "position", 1.0f);
650 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
651
652 // Check that glTexImage2D for POT texture succeeds
653 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, potTexSize, potTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
654 EXPECT_GL_NO_ERROR();
655
656 // Check that generateMipmap for an POT texture succeeds
657 glGenerateMipmap(GL_TEXTURE_2D);
658 EXPECT_GL_NO_ERROR();
659
660 // POT texture with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw
661 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
662 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
663 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
664 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
665 glClear(GL_COLOR_BUFFER_BIT);
666 drawQuad(m2DProgram, "position", 1.0f);
667 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
668 EXPECT_GL_NO_ERROR();
669}
Jamie Madillfa05f602015-05-07 13:47:11 -0400670
Jamie Madill2453dbc2015-07-14 11:35:42 -0400671// In the D3D11 renderer, we need to initialize some texture formats, to fill empty channels. EG RBA->RGBA8, with 1.0
672// in the alpha channel. This test covers a bug where redefining array textures with these formats does not work as
673// expected.
674TEST_P(TextureTestES3, RedefineInittableArray)
675{
676 std::vector<GLubyte> pixelData;
677 for (size_t count = 0; count < 5000; count++)
678 {
679 pixelData.push_back(0u);
680 pixelData.push_back(255u);
681 pixelData.push_back(0u);
682 }
683
684 glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
685 glUseProgram(m2DArrayProgram);
686 glUniform1i(mTextureArrayLocation, 0);
687
688 // The first draw worked correctly.
689 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, &pixelData[0]);
690
691 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
692 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
693 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
694 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
695 drawQuad(m2DArrayProgram, "position", 1.0f);
696 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
697
698 // The dimension of the respecification must match the original exactly to trigger the bug.
699 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 4, 4, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, &pixelData[0]);
700 drawQuad(m2DArrayProgram, "position", 1.0f);
701 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
702
703 ASSERT_GL_NO_ERROR();
704}
705
Jamie Madill3d3d2f22015-09-23 16:47:51 -0400706class TextureLimitsTest : public ANGLETest
707{
708 protected:
709 struct RGBA8
710 {
711 uint8_t R, G, B, A;
712 };
713
714 TextureLimitsTest()
715 : mProgram(0), mMaxVertexTextures(0), mMaxFragmentTextures(0), mMaxCombinedTextures(0)
716 {
717 setWindowWidth(128);
718 setWindowHeight(128);
719 setConfigRedBits(8);
720 setConfigGreenBits(8);
721 setConfigBlueBits(8);
722 setConfigAlphaBits(8);
723 }
724
725 ~TextureLimitsTest()
726 {
727 if (mProgram != 0)
728 {
729 glDeleteProgram(mProgram);
730 mProgram = 0;
731
732 if (!mTextures.empty())
733 {
734 glDeleteTextures(static_cast<GLsizei>(mTextures.size()), &mTextures[0]);
735 }
736 }
737 }
738
739 void SetUp() override
740 {
741 ANGLETest::SetUp();
742
743 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mMaxVertexTextures);
744 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mMaxFragmentTextures);
745 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mMaxCombinedTextures);
746
747 ASSERT_GL_NO_ERROR();
748 }
749
750 void compileProgramWithTextureCounts(const std::string &vertexPrefix,
751 GLint vertexTextureCount,
752 GLint vertexActiveTextureCount,
753 const std::string &fragPrefix,
754 GLint fragmentTextureCount,
755 GLint fragmentActiveTextureCount)
756 {
757 std::stringstream vertexShaderStr;
758 vertexShaderStr << "attribute vec2 position;\n"
759 << "varying vec4 color;\n"
760 << "varying vec2 texCoord;\n";
761
762 for (GLint textureIndex = 0; textureIndex < vertexTextureCount; ++textureIndex)
763 {
764 vertexShaderStr << "uniform sampler2D " << vertexPrefix << textureIndex << ";\n";
765 }
766
767 vertexShaderStr << "void main() {\n"
768 << " gl_Position = vec4(position, 0, 1);\n"
769 << " texCoord = (position * 0.5) + 0.5;\n"
770 << " color = vec4(0);\n";
771
772 for (GLint textureIndex = 0; textureIndex < vertexActiveTextureCount; ++textureIndex)
773 {
774 vertexShaderStr << " color += texture2D(" << vertexPrefix << textureIndex
775 << ", texCoord);\n";
776 }
777
778 vertexShaderStr << "}";
779
780 std::stringstream fragmentShaderStr;
781 fragmentShaderStr << "varying mediump vec4 color;\n"
782 << "varying mediump vec2 texCoord;\n";
783
784 for (GLint textureIndex = 0; textureIndex < fragmentTextureCount; ++textureIndex)
785 {
786 fragmentShaderStr << "uniform sampler2D " << fragPrefix << textureIndex << ";\n";
787 }
788
789 fragmentShaderStr << "void main() {\n"
790 << " gl_FragColor = color;\n";
791
792 for (GLint textureIndex = 0; textureIndex < fragmentActiveTextureCount; ++textureIndex)
793 {
794 fragmentShaderStr << " gl_FragColor += texture2D(" << fragPrefix << textureIndex
795 << ", texCoord);\n";
796 }
797
798 fragmentShaderStr << "}";
799
800 const std::string &vertexShaderSource = vertexShaderStr.str();
801 const std::string &fragmentShaderSource = fragmentShaderStr.str();
802
803 mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
804 }
805
806 RGBA8 getPixel(GLint texIndex)
807 {
808 RGBA8 pixel = {static_cast<uint8_t>(texIndex & 0x7u), static_cast<uint8_t>(texIndex >> 3),
809 0, 255u};
810 return pixel;
811 }
812
813 void initTextures(GLint tex2DCount, GLint texCubeCount)
814 {
815 GLint totalCount = tex2DCount + texCubeCount;
816 mTextures.assign(totalCount, 0);
817 glGenTextures(totalCount, &mTextures[0]);
818 ASSERT_GL_NO_ERROR();
819
820 std::vector<RGBA8> texData(16 * 16);
821
822 GLint texIndex = 0;
823 for (; texIndex < tex2DCount; ++texIndex)
824 {
825 texData.assign(texData.size(), getPixel(texIndex));
826 glActiveTexture(GL_TEXTURE0 + texIndex);
827 glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]);
828 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
829 &texData[0]);
830 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
831 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
832 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
833 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
834 }
835
836 ASSERT_GL_NO_ERROR();
837
838 for (; texIndex < texCubeCount; ++texIndex)
839 {
840 texData.assign(texData.size(), getPixel(texIndex));
841 glActiveTexture(GL_TEXTURE0 + texIndex);
842 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[texIndex]);
843 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
844 GL_UNSIGNED_BYTE, &texData[0]);
845 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
846 GL_UNSIGNED_BYTE, &texData[0]);
847 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
848 GL_UNSIGNED_BYTE, &texData[0]);
849 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
850 GL_UNSIGNED_BYTE, &texData[0]);
851 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
852 GL_UNSIGNED_BYTE, &texData[0]);
853 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
854 GL_UNSIGNED_BYTE, &texData[0]);
855 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
856 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
857 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
858 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
859 }
860
861 ASSERT_GL_NO_ERROR();
862 }
863
864 void testWithTextures(GLint vertexTextureCount,
865 const std::string &vertexTexturePrefix,
866 GLint fragmentTextureCount,
867 const std::string &fragmentTexturePrefix)
868 {
869 // Generate textures
870 initTextures(vertexTextureCount + fragmentTextureCount, 0);
871
872 glUseProgram(mProgram);
873 RGBA8 expectedSum = {0};
874 for (GLint texIndex = 0; texIndex < vertexTextureCount; ++texIndex)
875 {
876 std::stringstream uniformNameStr;
877 uniformNameStr << vertexTexturePrefix << texIndex;
878 const std::string &uniformName = uniformNameStr.str();
879 GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
880 ASSERT_NE(-1, location);
881
882 glUniform1i(location, texIndex);
883 RGBA8 contribution = getPixel(texIndex);
884 expectedSum.R += contribution.R;
885 expectedSum.G += contribution.G;
886 }
887
888 for (GLint texIndex = 0; texIndex < fragmentTextureCount; ++texIndex)
889 {
890 std::stringstream uniformNameStr;
891 uniformNameStr << fragmentTexturePrefix << texIndex;
892 const std::string &uniformName = uniformNameStr.str();
893 GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
894 ASSERT_NE(-1, location);
895
896 glUniform1i(location, texIndex + vertexTextureCount);
897 RGBA8 contribution = getPixel(texIndex + vertexTextureCount);
898 expectedSum.R += contribution.R;
899 expectedSum.G += contribution.G;
900 }
901
902 ASSERT_GE(256u, expectedSum.G);
903
904 drawQuad(mProgram, "position", 0.5f);
905 ASSERT_GL_NO_ERROR();
906 EXPECT_PIXEL_EQ(0, 0, expectedSum.R, expectedSum.G, 0, 255);
907 }
908
909 GLuint mProgram;
910 std::vector<GLuint> mTextures;
911 GLint mMaxVertexTextures;
912 GLint mMaxFragmentTextures;
913 GLint mMaxCombinedTextures;
914};
915
916// Test rendering with the maximum vertex texture units.
917TEST_P(TextureLimitsTest, MaxVertexTextures)
918{
919 compileProgramWithTextureCounts("tex", mMaxVertexTextures, mMaxVertexTextures, "tex", 0, 0);
920 ASSERT_NE(0u, mProgram);
921 ASSERT_GL_NO_ERROR();
922
923 testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
924}
925
926// Test rendering with the maximum fragment texture units.
927TEST_P(TextureLimitsTest, MaxFragmentTextures)
928{
929 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures, mMaxFragmentTextures);
930 ASSERT_NE(0u, mProgram);
931 ASSERT_GL_NO_ERROR();
932
933 testWithTextures(mMaxFragmentTextures, "tex", 0, "tex");
934}
935
936// Test rendering with maximum combined texture units.
937TEST_P(TextureLimitsTest, MaxCombinedTextures)
938{
Jamie Madill412f17d2015-09-25 08:43:54 -0400939 // TODO(jmadill): Investigate workaround.
940 if (isIntel() && GetParam() == ES2_OPENGL())
941 {
942 std::cout << "Test skipped on Intel." << std::endl;
943 return;
944 }
945
Jamie Madill3d3d2f22015-09-23 16:47:51 -0400946 GLint vertexTextures = mMaxVertexTextures;
947
948 if (vertexTextures + mMaxFragmentTextures > mMaxCombinedTextures)
949 {
950 vertexTextures = mMaxCombinedTextures - mMaxFragmentTextures;
951 }
952
953 compileProgramWithTextureCounts("vtex", vertexTextures, vertexTextures, "ftex",
954 mMaxFragmentTextures, mMaxFragmentTextures);
955 ASSERT_NE(0u, mProgram);
956 ASSERT_GL_NO_ERROR();
957
958 testWithTextures(vertexTextures, "vtex", mMaxFragmentTextures, "ftex");
959}
960
961// Negative test for exceeding the number of vertex textures
962TEST_P(TextureLimitsTest, ExcessiveVertexTextures)
963{
964 compileProgramWithTextureCounts("tex", mMaxVertexTextures + 1, mMaxVertexTextures + 1, "tex", 0,
965 0);
966 ASSERT_EQ(0u, mProgram);
967}
968
969// Negative test for exceeding the number of fragment textures
970TEST_P(TextureLimitsTest, ExcessiveFragmentTextures)
971{
972 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 1,
973 mMaxFragmentTextures + 1);
974 ASSERT_EQ(0u, mProgram);
975}
976
977// Test active vertex textures under the limit, but excessive textures specified.
978TEST_P(TextureLimitsTest, MaxActiveVertexTextures)
979{
980 compileProgramWithTextureCounts("tex", mMaxVertexTextures + 4, mMaxVertexTextures, "tex", 0, 0);
981 ASSERT_NE(0u, mProgram);
982 ASSERT_GL_NO_ERROR();
983
984 testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
985}
986
987// Test active fragment textures under the limit, but excessive textures specified.
988TEST_P(TextureLimitsTest, MaxActiveFragmentTextures)
989{
990 compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 4,
991 mMaxFragmentTextures);
992 ASSERT_NE(0u, mProgram);
993 ASSERT_GL_NO_ERROR();
994
995 testWithTextures(0, "tex", mMaxFragmentTextures, "tex");
996}
997
998// Negative test for pointing two sampler uniforms of different types to the same texture.
999TEST_P(TextureLimitsTest, TextureTypeConflict)
1000{
1001 const std::string &vertexShader =
1002 "attribute vec2 position;\n"
1003 "varying float color;\n"
1004 "uniform sampler2D tex2D;\n"
1005 "uniform samplerCube texCube;\n"
1006 "void main() {\n"
1007 " gl_Position = vec4(position, 0, 1);\n"
1008 " vec2 texCoord = (position * 0.5) + 0.5;\n"
1009 " color = texture2D(tex2D, texCoord).x;\n"
1010 " color += textureCube(texCube, vec3(texCoord, 0)).x;\n"
1011 "}";
1012 const std::string &fragmentShader =
1013 "varying mediump float color;\n"
1014 "void main() {\n"
1015 " gl_FragColor = vec4(color, 0, 0, 1);\n"
1016 "}";
1017
1018 mProgram = CompileProgram(vertexShader, fragmentShader);
1019 ASSERT_NE(0u, mProgram);
1020
1021 initTextures(1, 0);
1022
1023 glUseProgram(mProgram);
1024 GLint tex2DLocation = glGetUniformLocation(mProgram, "tex2D");
1025 ASSERT_NE(-1, tex2DLocation);
1026 GLint texCubeLocation = glGetUniformLocation(mProgram, "texCube");
1027 ASSERT_NE(-1, texCubeLocation);
1028
1029 glUniform1i(tex2DLocation, 0);
1030 glUniform1i(texCubeLocation, 0);
1031 ASSERT_GL_NO_ERROR();
1032
1033 drawQuad(mProgram, "position", 0.5f);
1034 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1035}
1036
1037// Negative test for rendering with texture outside the valid range.
1038// TODO(jmadill): Research if this is correct.
1039TEST_P(TextureLimitsTest, DrawWithTexturePastMaximum)
1040{
1041 const std::string &vertexShader =
1042 "attribute vec2 position;\n"
1043 "varying float color;\n"
1044 "uniform sampler2D tex2D;\n"
1045 "void main() {\n"
1046 " gl_Position = vec4(position, 0, 1);\n"
1047 " vec2 texCoord = (position * 0.5) + 0.5;\n"
1048 " color = texture2D(tex2D, texCoord).x;\n"
1049 "}";
1050 const std::string &fragmentShader =
1051 "varying mediump float color;\n"
1052 "void main() {\n"
1053 " gl_FragColor = vec4(color, 0, 0, 1);\n"
1054 "}";
1055
1056 mProgram = CompileProgram(vertexShader, fragmentShader);
1057 ASSERT_NE(0u, mProgram);
1058
1059 glUseProgram(mProgram);
1060 GLint tex2DLocation = glGetUniformLocation(mProgram, "tex2D");
1061 ASSERT_NE(-1, tex2DLocation);
1062
1063 glUniform1i(tex2DLocation, mMaxCombinedTextures);
1064 ASSERT_GL_NO_ERROR();
1065
1066 drawQuad(mProgram, "position", 0.5f);
1067 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1068}
1069
Jamie Madillfa05f602015-05-07 13:47:11 -04001070// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
Geoff Langc4222072015-05-25 13:19:48 -04001071ANGLE_INSTANTIATE_TEST(TextureTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3()); // TODO(geofflang): Figure out why this test fails on Intel OpenGL
Jamie Madill2453dbc2015-07-14 11:35:42 -04001072ANGLE_INSTANTIATE_TEST(TextureTestES3, ES3_D3D11(), ES3_OPENGL());
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001073ANGLE_INSTANTIATE_TEST(TextureLimitsTest, ES2_D3D11(), ES2_OPENGL());
Jamie Madillfa05f602015-05-07 13:47:11 -04001074
1075} // namespace