blob: caf2c891d1f34330f066bc32464f9929af73db12 [file] [log] [blame]
Austin Kinross215b37a2014-12-22 12:56:07 -08001#include "ANGLETest.h"
2
3// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
Geoff Lang3b2f9f62015-01-23 16:09:06 -05004ANGLE_TYPED_TEST_CASE(MipmapTest, ES2_D3D9, ES2_D3D11, ES2_D3D11_FL9_3);
Austin Kinross215b37a2014-12-22 12:56:07 -08005ANGLE_TYPED_TEST_CASE(MipmapTestES3, ES3_D3D11);
6
7template<typename T>
8class MipmapTest : public ANGLETest
9{
10 protected:
11 MipmapTest() : ANGLETest(T::GetGlesMajorVersion(), T::GetPlatform())
12 {
13 setWindowWidth(128);
14 setWindowHeight(128);
15 setConfigRedBits(8);
16 setConfigGreenBits(8);
17 setConfigBlueBits(8);
18 setConfigAlphaBits(8);
19 }
20
21 virtual void SetUp()
22 {
23 ANGLETest::SetUp();
24
25 // Vertex Shader source
26 const std::string vs = SHADER_SOURCE
27 (
28 attribute vec4 aPosition;
29 attribute vec2 aTexCoord;
30 varying vec2 vTexCoord;
31
32 void main()
33 {
34 gl_Position = aPosition;
35 vTexCoord = aTexCoord;
36 }
37 );
38
39 // Fragment Shader source
40 const std::string fs = SHADER_SOURCE
41 (
42 precision mediump float;
43
44 uniform sampler2D uTexture;
45 varying vec2 vTexCoord;
46
47 void main()
48 {
49 gl_FragColor = texture2D(uTexture, vTexCoord);
50 }
51 );
52
Austin Kinross62815bf2015-01-15 16:32:36 -080053 m2DProgram = CompileProgram(vs, fs);
54 if (m2DProgram == 0)
Austin Kinross215b37a2014-12-22 12:56:07 -080055 {
56 FAIL() << "shader compilation failed.";
57 }
58
Austin Kinross62815bf2015-01-15 16:32:36 -080059 // A simple vertex shader for the texture cube
60 const std::string cubeVS = SHADER_SOURCE
61 (
62 attribute vec4 aPosition;
63 varying vec4 vPosition;
64 void main()
65 {
66 gl_Position = aPosition;
67 vPosition = aPosition;
68 }
69 );
70
71 // A very simple fragment shader to sample from the negative-Y face of a texture cube.
72 const std::string cubeFS = SHADER_SOURCE
73 (
74 precision mediump float;
75 uniform samplerCube uTexture;
76 varying vec4 vPosition;
77
78 void main()
79 {
80 gl_FragColor = textureCube(uTexture, vec3(vPosition.x, -1, vPosition.y));
81 }
82 );
83
84 mCubeProgram = CompileProgram(cubeVS, cubeFS);
85 if (mCubeProgram == 0)
86 {
87 FAIL() << "shader compilation failed.";
88 }
89
90 m2DTextureUniformPosition = glGetUniformLocation(m2DProgram, "uTexture");
91 m2DPositionAttributePosition = glGetAttribLocation(m2DProgram, "aPosition");
92 m2DTexCoordAttributePosition = glGetAttribLocation(m2DProgram, "aTexCoord");
93
94 mLevelZeroBlueInitData = createRGBInitData(getWindowWidth(), getWindowHeight(), 0, 0, 255); // Blue
95 mLevelZeroWhiteInitData = createRGBInitData(getWindowWidth(), getWindowHeight(), 255, 255, 255); // White
96 mLevelOneInitData = createRGBInitData((getWindowWidth() / 2), (getWindowHeight() / 2), 0, 255, 0); // Green
97 mLevelTwoInitData = createRGBInitData((getWindowWidth() / 4), (getWindowHeight() / 4), 255, 0, 0); // Red
Austin Kinross215b37a2014-12-22 12:56:07 -080098
99 glGenFramebuffers(1, &mOffscreenFramebuffer);
Austin Kinross62815bf2015-01-15 16:32:36 -0800100 glGenTextures(1, &mOffscreenTexture2D);
Austin Kinross215b37a2014-12-22 12:56:07 -0800101
Austin Kinross62815bf2015-01-15 16:32:36 -0800102 // Initialize the texture2D to be empty, and don't use mips.
103 glBindTexture(GL_TEXTURE_2D, mOffscreenTexture2D);
Austin Kinross215b37a2014-12-22 12:56:07 -0800104 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
107
Austin Kinross62815bf2015-01-15 16:32:36 -0800108 // Bind the texture2D to the offscreen framebuffer's color buffer.
Austin Kinross215b37a2014-12-22 12:56:07 -0800109 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
Austin Kinross62815bf2015-01-15 16:32:36 -0800110 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mOffscreenTexture2D, 0);
Austin Kinross215b37a2014-12-22 12:56:07 -0800111 ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
112
Austin Kinross62815bf2015-01-15 16:32:36 -0800113 // Create a non-mipped texture cube. Set the negative-Y face to be blue.
114 glGenTextures(1, &mOffscreenTextureCube);
115 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
116 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
117 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
118 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
119 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
120 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
121 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
122
123 // Complete the texture cube without mipmaps to start with.
124 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
125 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
126
127 ASSERT_GL_NO_ERROR();
Austin Kinross215b37a2014-12-22 12:56:07 -0800128 }
129
130 virtual void TearDown()
131 {
Austin Kinross62815bf2015-01-15 16:32:36 -0800132 glDeleteProgram(m2DProgram);
133 glDeleteProgram(mCubeProgram);
Austin Kinross215b37a2014-12-22 12:56:07 -0800134 glDeleteFramebuffers(1, &mOffscreenFramebuffer);
Austin Kinross62815bf2015-01-15 16:32:36 -0800135 glDeleteTextures(1, &mOffscreenTexture2D);
136 glDeleteTextures(1, &mOffscreenTextureCube);
Austin Kinross215b37a2014-12-22 12:56:07 -0800137
138 delete mLevelZeroBlueInitData;
139 delete mLevelZeroWhiteInitData;
140 delete mLevelOneInitData;
141 delete mLevelTwoInitData;
142
143 ANGLETest::TearDown();
144 }
145
146 GLubyte *createRGBInitData(GLint width, GLint height, GLint r, GLint g, GLint b)
147 {
148 GLubyte *data = new GLubyte[3 * width * height];
149
150 for (int i = 0; i < width * height; i+=1)
151 {
152 data[3 * i + 0] = r;
153 data[3 * i + 1] = g;
154 data[3 * i + 2] = b;
155 }
156
157 return data;
158 }
159
160 void ClearAndDrawTexturedQuad(GLuint texture, GLsizei viewportWidth, GLsizei viewportHeight)
161 {
162 glBindFramebuffer(GL_FRAMEBUFFER, 0);
163 glClear(GL_COLOR_BUFFER_BIT);
164
165 glViewport(0, 0, viewportWidth, viewportHeight);
166
167 ASSERT_GL_NO_ERROR();
168
169 GLfloat vertexLocations[] =
170 {
171 -1.0f, 1.0f, 0.0f,
172 -1.0f, -1.0f, 0.0f,
173 1.0f, 1.0f, 0.0f,
174 1.0f, -1.0f, 0.0f,
175 };
176
177 GLfloat vertexTexCoords[] =
178 {
179 0.0f, 1.0f,
180 0.0f, 0.0f,
181 1.0f, 1.0f,
182 1.0f, 0.0f,
183 };
184
Austin Kinross62815bf2015-01-15 16:32:36 -0800185 glUseProgram(m2DProgram);
Austin Kinross215b37a2014-12-22 12:56:07 -0800186
187 glActiveTexture(GL_TEXTURE0);
188 glBindTexture(GL_TEXTURE_2D, texture);
Austin Kinross62815bf2015-01-15 16:32:36 -0800189 glUniform1i(m2DTextureUniformPosition, 0);
Austin Kinross215b37a2014-12-22 12:56:07 -0800190
Austin Kinross62815bf2015-01-15 16:32:36 -0800191 glVertexAttribPointer(m2DPositionAttributePosition, 3, GL_FLOAT, GL_FALSE, 0, vertexLocations);
192 glEnableVertexAttribArray(m2DPositionAttributePosition);
Austin Kinross215b37a2014-12-22 12:56:07 -0800193
Austin Kinross62815bf2015-01-15 16:32:36 -0800194 glVertexAttribPointer(m2DTexCoordAttributePosition, 2, GL_FLOAT, GL_FALSE, 0, vertexTexCoords);
195 glEnableVertexAttribArray(m2DTexCoordAttributePosition);
Austin Kinross215b37a2014-12-22 12:56:07 -0800196
197 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
198 }
199
Austin Kinross62815bf2015-01-15 16:32:36 -0800200 GLuint m2DProgram;
201 GLuint mCubeProgram;
Austin Kinross215b37a2014-12-22 12:56:07 -0800202 GLuint mOffscreenFramebuffer;
Austin Kinross62815bf2015-01-15 16:32:36 -0800203 GLuint mOffscreenTexture2D;
204 GLuint mOffscreenTextureCube;
Austin Kinross215b37a2014-12-22 12:56:07 -0800205
Austin Kinross62815bf2015-01-15 16:32:36 -0800206 GLint m2DTextureUniformPosition;
207 GLint m2DPositionAttributePosition;
208 GLint m2DTexCoordAttributePosition;
Austin Kinross215b37a2014-12-22 12:56:07 -0800209
210 GLubyte* mLevelZeroBlueInitData;
211 GLubyte* mLevelZeroWhiteInitData;
212 GLubyte* mLevelOneInitData;
213 GLubyte* mLevelTwoInitData;
214};
215
216template<typename T>
217class MipmapTestES3 : public ANGLETest
218{
219protected:
220 MipmapTestES3() : ANGLETest(T::GetGlesMajorVersion(), T::GetPlatform())
221 {
222 setWindowWidth(128);
223 setWindowHeight(128);
224 setConfigRedBits(8);
225 setConfigGreenBits(8);
226 setConfigBlueBits(8);
227 setConfigAlphaBits(8);
228 }
229
230 virtual void SetUp()
231 {
232 ANGLETest::SetUp();
233
234 glGenTextures(1, &mTextureArray);
235 EXPECT_GL_NO_ERROR();
236
237 ASSERT_GL_NO_ERROR();
238
Austin Kinrosse8c86272015-01-15 18:55:36 -0800239 // Don't put "#version ..." on its own line. See [cpp]p1:
240 // "If there are sequences of preprocessing tokens within the list of arguments that
241 // would otherwise act as preprocessing directives, the behavior is undefined"
Austin Kinross215b37a2014-12-22 12:56:07 -0800242 const std::string vertexShaderSource = SHADER_SOURCE
Austin Kinrosse8c86272015-01-15 18:55:36 -0800243 ( #version 300 es\n
Austin Kinross215b37a2014-12-22 12:56:07 -0800244 precision highp float;
245 in vec4 position;
246 out vec2 texcoord;
247
248 uniform vec2 textureScale;
249
250 void main()
251 {
252 gl_Position = vec4(position.xy * textureScale, 0.0, 1.0);
253 texcoord = (position.xy * 0.5) + 0.5;
254 }
255 );
256
257 const std::string fragmentShaderSourceArray = SHADER_SOURCE
Austin Kinrosse8c86272015-01-15 18:55:36 -0800258 ( #version 300 es\n
Austin Kinross215b37a2014-12-22 12:56:07 -0800259 precision highp float;
260 uniform sampler2DArray tex;
261 uniform int slice;
262 in vec2 texcoord;
263 out vec4 out_FragColor;
264
265 void main()
266 {
267 out_FragColor = texture(tex, vec3(texcoord, float(slice)));
268 }
269 );
270
271 mArrayProgram = CompileProgram(vertexShaderSource, fragmentShaderSourceArray);
272 if (mArrayProgram == 0)
273 {
274 FAIL() << "shader compilation failed.";
275 }
276
277 mTextureArrayUniformLocation = glGetUniformLocation(mArrayProgram, "tex");
278 ASSERT_NE(-1, mTextureArrayUniformLocation);
279
280 mTextureArrayScaleUniformLocation = glGetUniformLocation(mArrayProgram, "textureScale");
281 ASSERT_NE(-1, mTextureArrayScaleUniformLocation);
282
283 mTextureArraySliceUniformLocation = glGetUniformLocation(mArrayProgram, "slice");
284 ASSERT_NE(-1, mTextureArraySliceUniformLocation);
285
286 glUseProgram(mArrayProgram);
287 glUniform2f(mTextureArrayScaleUniformLocation, 1.0f, 1.0f);
288 glUseProgram(0);
289 ASSERT_GL_NO_ERROR();
290 }
291
292 virtual void TearDown()
293 {
294 glDeleteTextures(1, &mTextureArray);
295 glDeleteProgram(mArrayProgram);
296
297 ANGLETest::TearDown();
298 }
299
300 GLuint mTextureArray;
301
302 GLuint mArrayProgram;
303 GLint mTextureArrayUniformLocation;
304 GLint mTextureArrayScaleUniformLocation;
305 GLint mTextureArraySliceUniformLocation;
306};
307
308// This test uses init data for the first three levels of the texture. It passes the level 0 data in, then renders, then level 1, then renders, etc.
309// This ensures that renderers using the zero LOD workaround (e.g. D3D11 FL9_3) correctly pass init data to the mipmapped texture,
310// even if the the zero-LOD texture is currently in use.
Austin Kinross276171b2015-01-15 13:16:18 -0800311TYPED_TEST(MipmapTest, DISABLED_ThreeLevelsInitData)
Austin Kinross215b37a2014-12-22 12:56:07 -0800312{
313 // Pass in level zero init data.
Austin Kinross62815bf2015-01-15 16:32:36 -0800314 glBindTexture(GL_TEXTURE_2D, mOffscreenTexture2D);
Austin Kinross215b37a2014-12-22 12:56:07 -0800315 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
316 ASSERT_GL_NO_ERROR();
317
318 // Disable mips.
319 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
320
321 // Draw a full-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800322 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800323 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
324
325 // Draw a half-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800326 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800327 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
328
329 // Draw a quarter-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800330 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800331 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
332
333 // Complete the texture by initializing the remaining levels.
334 int n = 1;
335 while (getWindowWidth() / pow(2, n) >= 1)
336 {
337 glTexImage2D(GL_TEXTURE_2D, n, GL_RGB, getWindowWidth() / pow(2, n), getWindowWidth() / pow(2, n), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
338 ASSERT_GL_NO_ERROR();
339 n+=1;
340 }
341
342 // Pass in level one init data.
343 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelOneInitData);
344 ASSERT_GL_NO_ERROR();
345
346 // Draw a full-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800347 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800348 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
349
350 // Draw a half-sized quad, and check it's blue. We've not enabled mipmaps yet, so our init data for level one shouldn't be used.
Austin Kinross62815bf2015-01-15 16:32:36 -0800351 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800352 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
353
354 // Enable mipmaps.
355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
356
357 // Draw a half-sized quad, and check it's green.
Austin Kinross62815bf2015-01-15 16:32:36 -0800358 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800359 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
360
361 // Draw a quarter-sized quad, and check it's black, since we've not passed any init data for level two.
Austin Kinross62815bf2015-01-15 16:32:36 -0800362 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800363 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 0, 255);
364
365 // Pass in level two init data.
366 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, getWindowWidth() / 4, getWindowHeight() / 4, 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelTwoInitData);
367 ASSERT_GL_NO_ERROR();
368
369 // Draw a full-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800370 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800371 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
372
373 // Draw a half-sized quad, and check it's green.
Austin Kinross62815bf2015-01-15 16:32:36 -0800374 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800375 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
376
377 // Draw a quarter-sized quad, and check it's red.
Austin Kinross62815bf2015-01-15 16:32:36 -0800378 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800379 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 0, 0, 255);
380
381 // Now disable mipmaps again, and render multiple sized quads. They should all be blue, since level 0 is blue.
382 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Austin Kinross62815bf2015-01-15 16:32:36 -0800383 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800384 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800385 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800386 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800387 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800388 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
389
390 // Now reset level 0 to white, keeping mipmaps disabled. Then, render various sized quads. They should be white.
391 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroWhiteInitData);
392 ASSERT_GL_NO_ERROR();
393
Austin Kinross62815bf2015-01-15 16:32:36 -0800394 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800395 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800396 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800397 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 255, 255, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800398 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800399 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 255, 255, 255);
400
401 // Then enable mipmaps again. The quads should be white, green, red respectively.
402 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
403
Austin Kinross62815bf2015-01-15 16:32:36 -0800404 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800405 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800406 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800407 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800408 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800409 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 0, 0, 255);
410}
411
412// This test generates (and uses) mipmaps on a texture using init data. D3D11 will use a non-renderable TextureStorage for this.
413// The test then disables mips, renders to level zero of the texture, and reenables mips before using the texture again.
414// To do this, D3D11 has to convert the TextureStorage into a renderable one.
415// This test ensures that the conversion works correctly.
416// In particular, on D3D11 Feature Level 9_3 it ensures that both the zero LOD workaround texture AND the 'normal' texture are copied during conversion.
Geoff Lang3b2f9f62015-01-23 16:09:06 -0500417TYPED_TEST(MipmapTest, DISABLED_GenerateMipmapFromInitDataThenRender)
Austin Kinross215b37a2014-12-22 12:56:07 -0800418{
419 // Pass in initial data so the texture is blue.
420 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
421
422 // Then generate the mips.
423 glGenerateMipmap(GL_TEXTURE_2D);
424 ASSERT_GL_NO_ERROR();
425
426 // Enable mipmaps.
427 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
428
429 // Now draw the texture to various different sized areas.
Austin Kinross62815bf2015-01-15 16:32:36 -0800430 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800431 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
432
433 // Use mip level 1
Austin Kinross62815bf2015-01-15 16:32:36 -0800434 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800435 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
436
437 // Use mip level 2
Austin Kinross62815bf2015-01-15 16:32:36 -0800438 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800439 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
440
441 ASSERT_GL_NO_ERROR();
442
443 // Disable mips. Render a quad using the texture and ensure it's blue.
444 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Austin Kinross62815bf2015-01-15 16:32:36 -0800445 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800446 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
447
448 // Clear level 0 of the texture.
449 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
450 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
451 glClear(GL_COLOR_BUFFER_BIT);
452
453 // Reenable mips, and try rendering different-sized quads.
454 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
455
456 // Level 0 is now red, so this should render red.
Austin Kinross62815bf2015-01-15 16:32:36 -0800457 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800458 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
459
460 // Use mip level 1, blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800461 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800462 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
463
464 // Use mip level 2, blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800465 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800466 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
467}
468
469// This test ensures that mips are correctly generated from a rendered image.
470// In particular, on D3D11 Feature Level 9_3, the clear call will be performed on the zero-level texture, rather than the mipped one.
471// The test ensures that the zero-level texture is correctly copied into the mipped texture before the mipmaps are generated.
Geoff Lang3b2f9f62015-01-23 16:09:06 -0500472TYPED_TEST(MipmapTest, DISABLED_GenerateMipmapFromRenderedImage)
Austin Kinross215b37a2014-12-22 12:56:07 -0800473{
474 // Bind the offscreen framebuffer/texture.
475 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
476
477 // Clear the texture to blue.
478 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
479 glClear(GL_COLOR_BUFFER_BIT);
480
481 // Then generate the mips
482 glGenerateMipmap(GL_TEXTURE_2D);
483 ASSERT_GL_NO_ERROR();
484
485 // Enable mips.
486 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
487
488 // Now draw the texture to various different sized areas.
Austin Kinross62815bf2015-01-15 16:32:36 -0800489 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800490 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
491
492 // Use mip level 1
Austin Kinross62815bf2015-01-15 16:32:36 -0800493 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800494 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
495
496 // Use mip level 2
Austin Kinross62815bf2015-01-15 16:32:36 -0800497 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800498 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
499}
500
501// Test to ensure that rendering to a mipmapped texture works, regardless of whether mipmaps are enabled or not.
502// TODO: This test hits a texture rebind bug in the D3D11 renderer. Fix this.
Geoff Lang3b2f9f62015-01-23 16:09:06 -0500503TYPED_TEST(MipmapTest, DISABLED_RenderOntoLevelZeroAfterGenerateMipmap)
Austin Kinross215b37a2014-12-22 12:56:07 -0800504{
505 // Bind the offscreen texture/framebuffer.
506 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
507
508 // Clear the texture to blue.
509 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
510 glClear(GL_COLOR_BUFFER_BIT);
511
512 // From now on, default clear color is black.
513 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
514
515 // Now, draw the texture to a quad that's the same size as the texture. This draws to the default framebuffer.
516 // The quad should be blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800517 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800518 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
519
520 // Now go back to the texture, and generate mips on it.
521 glGenerateMipmap(GL_TEXTURE_2D);
522 ASSERT_GL_NO_ERROR();
523
524 // Now try rendering the textured quad again. Note: we've not told GL to use the generated mips.
525 // The quad should be blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800526 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800527 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
528
529 // Now tell GL to use the generated mips.
530 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
531 EXPECT_EQ(glGetError(), GL_NONE);
532
533 // Now render the textured quad again. It should be still be blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800534 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800535 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
536
537 // Now render the textured quad to an area smaller than the texture (i.e. to force minification). This should be blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800538 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800539 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
540
541 // Now clear the texture to green. This just clears the top level. The lower mips should remain blue.
542 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
543 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
544 glClear(GL_COLOR_BUFFER_BIT);
545
546 // From now on, default clear color is black.
547 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
548
549 // Render a textured quad equal in size to the texture. This should be green, since we just cleared level 0.
Austin Kinross62815bf2015-01-15 16:32:36 -0800550 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800551 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 255, 0, 255);
552
553 // Render a small textured quad. This forces minification, so should render blue (the color of levels 1+).
Austin Kinross62815bf2015-01-15 16:32:36 -0800554 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800555 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
556
557 // Disable mipmaps again
558 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
559 ASSERT_GL_NO_ERROR();
560
561 // Render a textured quad equal in size to the texture. This should be green, the color of level 0 in the texture.
Austin Kinross62815bf2015-01-15 16:32:36 -0800562 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800563 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 255, 0, 255);
564
565 // Render a small textured quad. This would force minification if mips were enabled, but they're not. Therefore, this should be green.
Austin Kinross62815bf2015-01-15 16:32:36 -0800566 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800567 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 255, 0, 255);
568}
569
Austin Kinross62815bf2015-01-15 16:32:36 -0800570// This test ensures that the level-zero workaround for TextureCubes (on D3D11 Feature Level 9_3)
571// works as expected. It tests enabling/disabling mipmaps, generating mipmaps, and rendering to level zero.
Geoff Lang3b2f9f62015-01-23 16:09:06 -0500572TYPED_TEST(MipmapTest, DISABLED_TextureCubeGeneralLevelZero)
Austin Kinross62815bf2015-01-15 16:32:36 -0800573{
574 GLfloat vertexLocations[] =
575 {
576 -1.0f, 1.0f, 0.0f,
577 -1.0f, -1.0f, 0.0f,
578 1.0f, 1.0f, 0.0f,
579 1.0f, -1.0f, 0.0f,
580 };
581
582 // Set up the viewport, program, attributes, sampler and texture for the cube
583 glBindFramebuffer(GL_FRAMEBUFFER, 0);
584 glViewport(0, 0, getWindowWidth(), getWindowHeight());
585 glUseProgram(mCubeProgram);
586 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertexLocations);
587 glEnableVertexAttribArray(0);
588 glUniform1i(0, 0);
589 glActiveTexture(GL_TEXTURE0);
590 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
591
592 // Draw. Since the negative-Y face's is blue, this should be blue.
593 glClear(GL_COLOR_BUFFER_BIT);
594 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
595 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
596
597 // Generate mipmaps, and render. This should be blue.
598 glClear(GL_COLOR_BUFFER_BIT);
599 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
600 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
601 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
602 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
603 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
604
605 // Draw using a smaller viewport (to force a lower LOD of the texture). This should still be blue.
606 glClear(GL_COLOR_BUFFER_BIT);
607 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
608 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
609 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
610
611 // Now clear the negative-Y face of the cube to red.
612 GLuint mOffscreenFramebuffer;
613 glGenFramebuffers(0, &mOffscreenFramebuffer);
614 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
615 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mOffscreenTextureCube, 0);
616 ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
617 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
618 glClear(GL_COLOR_BUFFER_BIT);
619
620 // Switch back to the default framebuffer
621 glBindFramebuffer(GL_FRAMEBUFFER, 0);
622 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
623
624 // Draw using a full-size viewport. This should be red.
625 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
626 glClear(GL_COLOR_BUFFER_BIT);
627 glViewport(0, 0, getWindowWidth(), getWindowHeight());
628 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
629 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
630
631 // Draw using a quarter-size viewport, to force a lower LOD. This should be *BLUE*, since we only cleared level zero
632 // of the negative-Y face to red, and left its mipmaps blue.
633 glClear(GL_COLOR_BUFFER_BIT);
634 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
635 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
636 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
637
638 // Disable mipmaps again, and draw a to a quarter-size viewport.
639 // Since this should use level zero of the texture, this should be *RED*.
640 glClear(GL_COLOR_BUFFER_BIT);
641 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
642 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
643 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
644 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
645}
646
647// This test ensures that rendering to level-zero of a TextureCube works as expected.
Geoff Lang3b2f9f62015-01-23 16:09:06 -0500648TYPED_TEST(MipmapTest, DISABLED_TextureCubeRenderToLevelZero)
Austin Kinross62815bf2015-01-15 16:32:36 -0800649{
650 GLfloat vertexLocations[] =
651 {
652 -1.0f, 1.0f, 0.0f,
653 -1.0f, -1.0f, 0.0f,
654 1.0f, 1.0f, 0.0f,
655 1.0f, -1.0f, 0.0f,
656 };
657
658 // Set up the viewport, program, attributes, sampler and texture for the cube
659 glBindFramebuffer(GL_FRAMEBUFFER, 0);
660 glViewport(0, 0, getWindowWidth(), getWindowHeight());
661 glUseProgram(mCubeProgram);
662 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertexLocations);
663 glEnableVertexAttribArray(0);
664 glUniform1i(0, 0);
665 glActiveTexture(GL_TEXTURE0);
666 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
667
668 // Draw. Since the negative-Y face's is blue, this should be blue.
669 glClear(GL_COLOR_BUFFER_BIT);
670 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
671 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
672
673 // Now clear the negative-Y face of the cube to red.
674 GLuint mOffscreenFramebuffer;
675 glGenFramebuffers(0, &mOffscreenFramebuffer);
676 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
677 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mOffscreenTextureCube, 0);
678 ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
679 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
680 glClear(GL_COLOR_BUFFER_BIT);
681
682 // Switch back to the default framebuffer
683 glBindFramebuffer(GL_FRAMEBUFFER, 0);
684 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
685
686 // Draw using a full-size viewport. This should be red.
687 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
688 glClear(GL_COLOR_BUFFER_BIT);
689 glViewport(0, 0, getWindowWidth(), getWindowHeight());
690 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
691 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
692
693 // Draw a to a quarter-size viewport. This should also be red.
694 glClear(GL_COLOR_BUFFER_BIT);
695 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
696 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
697 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
698}
699
Austin Kinross215b37a2014-12-22 12:56:07 -0800700// Creates a mipmapped 2D array texture with three layers, and calls ANGLE's GenerateMipmap.
701// Then tests if the mipmaps are rendered correctly for all three layers.
Geoff Lang3b2f9f62015-01-23 16:09:06 -0500702TYPED_TEST(MipmapTestES3, DISABLED_MipmapsForTextureArray)
Austin Kinross215b37a2014-12-22 12:56:07 -0800703{
704 int px = getWindowWidth() / 2;
705 int py = getWindowHeight() / 2;
706
707 glActiveTexture(GL_TEXTURE0);
708 glBindTexture(GL_TEXTURE_2D_ARRAY, mTextureArray);
709
710 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 5, GL_RGBA8, 16, 16, 3);
711
712 // Fill the first layer with red
713 std::vector<GLubyte> pixels(4 * 16 * 16);
714 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
715 {
716 pixels[pixelId * 4 + 0] = 255;
717 pixels[pixelId * 4 + 1] = 0;
718 pixels[pixelId * 4 + 2] = 0;
719 pixels[pixelId * 4 + 3] = 255;
720 }
721
722 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
723
724 // Fill the second layer with green
725 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
726 {
727 pixels[pixelId * 4 + 0] = 0;
728 pixels[pixelId * 4 + 1] = 255;
729 pixels[pixelId * 4 + 2] = 0;
730 pixels[pixelId * 4 + 3] = 255;
731 }
732
733 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
734
735 // Fill the third layer with blue
736 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
737 {
738 pixels[pixelId * 4 + 0] = 0;
739 pixels[pixelId * 4 + 1] = 0;
740 pixels[pixelId * 4 + 2] = 255;
741 pixels[pixelId * 4 + 3] = 255;
742 }
743
744 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
745
746 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
747 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
748
749 EXPECT_GL_NO_ERROR();
750
751 glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
752
753 EXPECT_GL_NO_ERROR();
754
755 glUseProgram(mArrayProgram);
756 glUniform1i(mTextureArrayUniformLocation, 0);
757
758 EXPECT_GL_NO_ERROR();
759
760 // Draw the first slice
761 glUseProgram(mArrayProgram);
762 glUniform1i(mTextureArraySliceUniformLocation, 0);
763 drawQuad(mArrayProgram, "position", 0.5f);
764 EXPECT_GL_NO_ERROR();
765 EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
766
767 // Draw the second slice
768 glUseProgram(mArrayProgram);
769 glUniform1i(mTextureArraySliceUniformLocation, 1);
770 drawQuad(mArrayProgram, "position", 0.5f);
771 EXPECT_GL_NO_ERROR();
772 EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
773
774 // Draw the third slice
775 glUseProgram(mArrayProgram);
776 glUniform1i(mTextureArraySliceUniformLocation, 2);
777 drawQuad(mArrayProgram, "position", 0.5f);
778 EXPECT_GL_NO_ERROR();
779 EXPECT_PIXEL_EQ(px, py, 0, 0, 255, 255);
780}