blob: d21569ce1ccd74f98d4f128a178cdf410fd408d1 [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 Wallezac3ab882015-05-12 13:31:28 -04007#include "end2end_tests/ANGLETest.h"
Austin Kinross215b37a2014-12-22 12:56:07 -08008
Jamie Madillfa05f602015-05-07 13:47:11 -04009using namespace angle;
Austin Kinross215b37a2014-12-22 12:56:07 -080010
Austin Kinross215b37a2014-12-22 12:56:07 -080011class MipmapTest : public ANGLETest
12{
13 protected:
Jamie Madillfa05f602015-05-07 13:47:11 -040014 MipmapTest()
Austin Kinross215b37a2014-12-22 12:56:07 -080015 {
16 setWindowWidth(128);
17 setWindowHeight(128);
18 setConfigRedBits(8);
19 setConfigGreenBits(8);
20 setConfigBlueBits(8);
21 setConfigAlphaBits(8);
22 }
23
24 virtual void SetUp()
25 {
26 ANGLETest::SetUp();
27
28 // Vertex Shader source
29 const std::string vs = SHADER_SOURCE
30 (
31 attribute vec4 aPosition;
32 attribute vec2 aTexCoord;
33 varying vec2 vTexCoord;
34
35 void main()
36 {
37 gl_Position = aPosition;
38 vTexCoord = aTexCoord;
39 }
40 );
41
42 // Fragment Shader source
43 const std::string fs = SHADER_SOURCE
44 (
45 precision mediump float;
46
47 uniform sampler2D uTexture;
48 varying vec2 vTexCoord;
49
50 void main()
51 {
52 gl_FragColor = texture2D(uTexture, vTexCoord);
53 }
54 );
55
Austin Kinross62815bf2015-01-15 16:32:36 -080056 m2DProgram = CompileProgram(vs, fs);
57 if (m2DProgram == 0)
Austin Kinross215b37a2014-12-22 12:56:07 -080058 {
59 FAIL() << "shader compilation failed.";
60 }
61
Austin Kinross62815bf2015-01-15 16:32:36 -080062 // A simple vertex shader for the texture cube
63 const std::string cubeVS = SHADER_SOURCE
64 (
65 attribute vec4 aPosition;
66 varying vec4 vPosition;
67 void main()
68 {
69 gl_Position = aPosition;
70 vPosition = aPosition;
71 }
72 );
73
74 // A very simple fragment shader to sample from the negative-Y face of a texture cube.
75 const std::string cubeFS = SHADER_SOURCE
76 (
77 precision mediump float;
78 uniform samplerCube uTexture;
79 varying vec4 vPosition;
80
81 void main()
82 {
83 gl_FragColor = textureCube(uTexture, vec3(vPosition.x, -1, vPosition.y));
84 }
85 );
86
87 mCubeProgram = CompileProgram(cubeVS, cubeFS);
88 if (mCubeProgram == 0)
89 {
90 FAIL() << "shader compilation failed.";
91 }
92
93 m2DTextureUniformPosition = glGetUniformLocation(m2DProgram, "uTexture");
94 m2DPositionAttributePosition = glGetAttribLocation(m2DProgram, "aPosition");
95 m2DTexCoordAttributePosition = glGetAttribLocation(m2DProgram, "aTexCoord");
96
97 mLevelZeroBlueInitData = createRGBInitData(getWindowWidth(), getWindowHeight(), 0, 0, 255); // Blue
98 mLevelZeroWhiteInitData = createRGBInitData(getWindowWidth(), getWindowHeight(), 255, 255, 255); // White
99 mLevelOneInitData = createRGBInitData((getWindowWidth() / 2), (getWindowHeight() / 2), 0, 255, 0); // Green
100 mLevelTwoInitData = createRGBInitData((getWindowWidth() / 4), (getWindowHeight() / 4), 255, 0, 0); // Red
Austin Kinross215b37a2014-12-22 12:56:07 -0800101
102 glGenFramebuffers(1, &mOffscreenFramebuffer);
Austin Kinross62815bf2015-01-15 16:32:36 -0800103 glGenTextures(1, &mOffscreenTexture2D);
Austin Kinross215b37a2014-12-22 12:56:07 -0800104
Austin Kinross62815bf2015-01-15 16:32:36 -0800105 // Initialize the texture2D to be empty, and don't use mips.
106 glBindTexture(GL_TEXTURE_2D, mOffscreenTexture2D);
Austin Kinross215b37a2014-12-22 12:56:07 -0800107 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
108 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
109 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
110
Austin Kinross62815bf2015-01-15 16:32:36 -0800111 // Bind the texture2D to the offscreen framebuffer's color buffer.
Austin Kinross215b37a2014-12-22 12:56:07 -0800112 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
Austin Kinross62815bf2015-01-15 16:32:36 -0800113 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mOffscreenTexture2D, 0);
Austin Kinross215b37a2014-12-22 12:56:07 -0800114 ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
115
Austin Kinross62815bf2015-01-15 16:32:36 -0800116 // Create a non-mipped texture cube. Set the negative-Y face to be blue.
117 glGenTextures(1, &mOffscreenTextureCube);
118 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
119 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
120 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
121 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
122 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
123 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
124 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
125
126 // Complete the texture cube without mipmaps to start with.
127 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
128 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
129
130 ASSERT_GL_NO_ERROR();
Austin Kinross215b37a2014-12-22 12:56:07 -0800131 }
132
133 virtual void TearDown()
134 {
Austin Kinross62815bf2015-01-15 16:32:36 -0800135 glDeleteProgram(m2DProgram);
136 glDeleteProgram(mCubeProgram);
Austin Kinross215b37a2014-12-22 12:56:07 -0800137 glDeleteFramebuffers(1, &mOffscreenFramebuffer);
Austin Kinross62815bf2015-01-15 16:32:36 -0800138 glDeleteTextures(1, &mOffscreenTexture2D);
139 glDeleteTextures(1, &mOffscreenTextureCube);
Austin Kinross215b37a2014-12-22 12:56:07 -0800140
141 delete mLevelZeroBlueInitData;
142 delete mLevelZeroWhiteInitData;
143 delete mLevelOneInitData;
144 delete mLevelTwoInitData;
145
146 ANGLETest::TearDown();
147 }
148
149 GLubyte *createRGBInitData(GLint width, GLint height, GLint r, GLint g, GLint b)
150 {
151 GLubyte *data = new GLubyte[3 * width * height];
152
153 for (int i = 0; i < width * height; i+=1)
154 {
Minmin Gong794e0002015-04-07 18:31:54 -0700155 data[3 * i + 0] = static_cast<GLubyte>(r);
156 data[3 * i + 1] = static_cast<GLubyte>(g);
157 data[3 * i + 2] = static_cast<GLubyte>(b);
Austin Kinross215b37a2014-12-22 12:56:07 -0800158 }
159
160 return data;
161 }
162
163 void ClearAndDrawTexturedQuad(GLuint texture, GLsizei viewportWidth, GLsizei viewportHeight)
164 {
165 glBindFramebuffer(GL_FRAMEBUFFER, 0);
166 glClear(GL_COLOR_BUFFER_BIT);
167
168 glViewport(0, 0, viewportWidth, viewportHeight);
169
170 ASSERT_GL_NO_ERROR();
171
172 GLfloat vertexLocations[] =
173 {
174 -1.0f, 1.0f, 0.0f,
175 -1.0f, -1.0f, 0.0f,
176 1.0f, 1.0f, 0.0f,
177 1.0f, -1.0f, 0.0f,
178 };
179
180 GLfloat vertexTexCoords[] =
181 {
182 0.0f, 1.0f,
183 0.0f, 0.0f,
184 1.0f, 1.0f,
185 1.0f, 0.0f,
186 };
187
Austin Kinross62815bf2015-01-15 16:32:36 -0800188 glUseProgram(m2DProgram);
Austin Kinross215b37a2014-12-22 12:56:07 -0800189
190 glActiveTexture(GL_TEXTURE0);
191 glBindTexture(GL_TEXTURE_2D, texture);
Austin Kinross62815bf2015-01-15 16:32:36 -0800192 glUniform1i(m2DTextureUniformPosition, 0);
Austin Kinross215b37a2014-12-22 12:56:07 -0800193
Austin Kinross62815bf2015-01-15 16:32:36 -0800194 glVertexAttribPointer(m2DPositionAttributePosition, 3, GL_FLOAT, GL_FALSE, 0, vertexLocations);
195 glEnableVertexAttribArray(m2DPositionAttributePosition);
Austin Kinross215b37a2014-12-22 12:56:07 -0800196
Austin Kinross62815bf2015-01-15 16:32:36 -0800197 glVertexAttribPointer(m2DTexCoordAttributePosition, 2, GL_FLOAT, GL_FALSE, 0, vertexTexCoords);
198 glEnableVertexAttribArray(m2DTexCoordAttributePosition);
Austin Kinross215b37a2014-12-22 12:56:07 -0800199
200 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
201 }
202
Austin Kinross62815bf2015-01-15 16:32:36 -0800203 GLuint m2DProgram;
204 GLuint mCubeProgram;
Austin Kinross215b37a2014-12-22 12:56:07 -0800205 GLuint mOffscreenFramebuffer;
Austin Kinross62815bf2015-01-15 16:32:36 -0800206 GLuint mOffscreenTexture2D;
207 GLuint mOffscreenTextureCube;
Austin Kinross215b37a2014-12-22 12:56:07 -0800208
Austin Kinross62815bf2015-01-15 16:32:36 -0800209 GLint m2DTextureUniformPosition;
210 GLint m2DPositionAttributePosition;
211 GLint m2DTexCoordAttributePosition;
Austin Kinross215b37a2014-12-22 12:56:07 -0800212
213 GLubyte* mLevelZeroBlueInitData;
214 GLubyte* mLevelZeroWhiteInitData;
215 GLubyte* mLevelOneInitData;
216 GLubyte* mLevelTwoInitData;
217};
218
Austin Kinross215b37a2014-12-22 12:56:07 -0800219class MipmapTestES3 : public ANGLETest
220{
Jamie Madillfa05f602015-05-07 13:47:11 -0400221 protected:
222 MipmapTestES3()
Austin Kinross215b37a2014-12-22 12:56:07 -0800223 {
224 setWindowWidth(128);
225 setWindowHeight(128);
226 setConfigRedBits(8);
227 setConfigGreenBits(8);
228 setConfigBlueBits(8);
229 setConfigAlphaBits(8);
230 }
231
232 virtual void SetUp()
233 {
234 ANGLETest::SetUp();
235
236 glGenTextures(1, &mTextureArray);
237 EXPECT_GL_NO_ERROR();
238
239 ASSERT_GL_NO_ERROR();
240
Austin Kinrosse8c86272015-01-15 18:55:36 -0800241 // Don't put "#version ..." on its own line. See [cpp]p1:
242 // "If there are sequences of preprocessing tokens within the list of arguments that
243 // would otherwise act as preprocessing directives, the behavior is undefined"
Austin Kinross215b37a2014-12-22 12:56:07 -0800244 const std::string vertexShaderSource = SHADER_SOURCE
Austin Kinrosse8c86272015-01-15 18:55:36 -0800245 ( #version 300 es\n
Austin Kinross215b37a2014-12-22 12:56:07 -0800246 precision highp float;
247 in vec4 position;
248 out vec2 texcoord;
249
250 uniform vec2 textureScale;
251
252 void main()
253 {
254 gl_Position = vec4(position.xy * textureScale, 0.0, 1.0);
255 texcoord = (position.xy * 0.5) + 0.5;
256 }
257 );
258
259 const std::string fragmentShaderSourceArray = SHADER_SOURCE
Austin Kinrosse8c86272015-01-15 18:55:36 -0800260 ( #version 300 es\n
Austin Kinross215b37a2014-12-22 12:56:07 -0800261 precision highp float;
262 uniform sampler2DArray tex;
263 uniform int slice;
264 in vec2 texcoord;
265 out vec4 out_FragColor;
266
267 void main()
268 {
269 out_FragColor = texture(tex, vec3(texcoord, float(slice)));
270 }
271 );
272
273 mArrayProgram = CompileProgram(vertexShaderSource, fragmentShaderSourceArray);
274 if (mArrayProgram == 0)
275 {
276 FAIL() << "shader compilation failed.";
277 }
278
279 mTextureArrayUniformLocation = glGetUniformLocation(mArrayProgram, "tex");
280 ASSERT_NE(-1, mTextureArrayUniformLocation);
281
282 mTextureArrayScaleUniformLocation = glGetUniformLocation(mArrayProgram, "textureScale");
283 ASSERT_NE(-1, mTextureArrayScaleUniformLocation);
284
285 mTextureArraySliceUniformLocation = glGetUniformLocation(mArrayProgram, "slice");
286 ASSERT_NE(-1, mTextureArraySliceUniformLocation);
287
288 glUseProgram(mArrayProgram);
289 glUniform2f(mTextureArrayScaleUniformLocation, 1.0f, 1.0f);
290 glUseProgram(0);
291 ASSERT_GL_NO_ERROR();
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000292
293 glGenTextures(1, &mTexture3D);
294
295 ASSERT_GL_NO_ERROR();
296
297 const std::string fragmentShaderSource3D = SHADER_SOURCE
298 ( #version 300 es\n
299 precision highp float;
300 uniform sampler3D tex;
301 uniform float slice;
302 uniform float lod;
303 in vec2 texcoord;
304 out vec4 out_FragColor;
305
306 void main()
307 {
308 out_FragColor = textureLod(tex, vec3(texcoord, slice), lod);
309 }
310 );
311
312 m3DProgram = CompileProgram(vertexShaderSource, fragmentShaderSource3D);
313 if (m3DProgram == 0)
314 {
315 FAIL() << "shader compilation failed.";
316 }
317
318 mTexture3DUniformLocation = glGetUniformLocation(m3DProgram, "tex");
319 ASSERT_NE(-1, mTexture3DUniformLocation);
320
321 mTexture3DScaleUniformLocation = glGetUniformLocation(m3DProgram, "textureScale");
322 ASSERT_NE(-1, mTexture3DScaleUniformLocation);
323
324 mTexture3DSliceUniformLocation = glGetUniformLocation(m3DProgram, "slice");
325 ASSERT_NE(-1, mTexture3DSliceUniformLocation);
326
327 mTexture3DLODUniformLocation = glGetUniformLocation(m3DProgram, "lod");
328 ASSERT_NE(-1, mTexture3DLODUniformLocation);
329
330 glUseProgram(m3DProgram);
331 glUniform2f(mTexture3DScaleUniformLocation, 1.0f, 1.0f);
332 glUniform1f(mTexture3DLODUniformLocation, 0);
333 glUseProgram(0);
334 ASSERT_GL_NO_ERROR();
Austin Kinross215b37a2014-12-22 12:56:07 -0800335 }
336
337 virtual void TearDown()
338 {
339 glDeleteTextures(1, &mTextureArray);
340 glDeleteProgram(mArrayProgram);
341
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000342 glDeleteTextures(1, &mTexture3D);
343 glDeleteProgram(m3DProgram);
344
Austin Kinross215b37a2014-12-22 12:56:07 -0800345 ANGLETest::TearDown();
346 }
347
348 GLuint mTextureArray;
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000349 GLuint mTexture3D;
Austin Kinross215b37a2014-12-22 12:56:07 -0800350
351 GLuint mArrayProgram;
352 GLint mTextureArrayUniformLocation;
353 GLint mTextureArrayScaleUniformLocation;
354 GLint mTextureArraySliceUniformLocation;
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000355
356 GLuint m3DProgram;
357 GLint mTexture3DUniformLocation;
358 GLint mTexture3DScaleUniformLocation;
359 GLint mTexture3DSliceUniformLocation;
360 GLint mTexture3DLODUniformLocation;
Austin Kinross215b37a2014-12-22 12:56:07 -0800361};
362
363// 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.
364// This ensures that renderers using the zero LOD workaround (e.g. D3D11 FL9_3) correctly pass init data to the mipmapped texture,
365// even if the the zero-LOD texture is currently in use.
Jamie Madillfa05f602015-05-07 13:47:11 -0400366TEST_P(MipmapTest, DISABLED_ThreeLevelsInitData)
Austin Kinross215b37a2014-12-22 12:56:07 -0800367{
368 // Pass in level zero init data.
Austin Kinross62815bf2015-01-15 16:32:36 -0800369 glBindTexture(GL_TEXTURE_2D, mOffscreenTexture2D);
Austin Kinross215b37a2014-12-22 12:56:07 -0800370 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
371 ASSERT_GL_NO_ERROR();
372
373 // Disable mips.
374 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
375
376 // Draw a full-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800377 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800378 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
379
380 // Draw a half-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800381 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800382 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
383
384 // Draw a quarter-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800385 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800386 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
387
388 // Complete the texture by initializing the remaining levels.
389 int n = 1;
Minmin Gong794e0002015-04-07 18:31:54 -0700390 while (getWindowWidth() / (1U << n) >= 1)
Austin Kinross215b37a2014-12-22 12:56:07 -0800391 {
Minmin Gong794e0002015-04-07 18:31:54 -0700392 glTexImage2D(GL_TEXTURE_2D, n, GL_RGB, getWindowWidth() / (1U << n), getWindowWidth() / (1U << n), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
Austin Kinross215b37a2014-12-22 12:56:07 -0800393 ASSERT_GL_NO_ERROR();
394 n+=1;
395 }
396
397 // Pass in level one init data.
398 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelOneInitData);
399 ASSERT_GL_NO_ERROR();
400
401 // Draw a full-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800402 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800403 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
404
405 // 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 -0800406 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800407 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
408
409 // Enable mipmaps.
410 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
411
412 // Draw a half-sized quad, and check it's green.
Austin Kinross62815bf2015-01-15 16:32:36 -0800413 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800414 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
415
416 // 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 -0800417 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800418 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 0, 255);
419
420 // Pass in level two init data.
421 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, getWindowWidth() / 4, getWindowHeight() / 4, 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelTwoInitData);
422 ASSERT_GL_NO_ERROR();
423
424 // Draw a full-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800425 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800426 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
427
428 // Draw a half-sized quad, and check it's green.
Austin Kinross62815bf2015-01-15 16:32:36 -0800429 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800430 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
431
432 // Draw a quarter-sized quad, and check it's red.
Austin Kinross62815bf2015-01-15 16:32:36 -0800433 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800434 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 0, 0, 255);
435
436 // Now disable mipmaps again, and render multiple sized quads. They should all be blue, since level 0 is blue.
437 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Austin Kinross62815bf2015-01-15 16:32:36 -0800438 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800439 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800440 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800441 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800442 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800443 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
444
445 // Now reset level 0 to white, keeping mipmaps disabled. Then, render various sized quads. They should be white.
446 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroWhiteInitData);
447 ASSERT_GL_NO_ERROR();
448
Austin Kinross62815bf2015-01-15 16:32:36 -0800449 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800450 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800451 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800452 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 255, 255, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800453 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800454 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 255, 255, 255);
455
456 // Then enable mipmaps again. The quads should be white, green, red respectively.
457 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
458
Austin Kinross62815bf2015-01-15 16:32:36 -0800459 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800460 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
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, 255, 0, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800463 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800464 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 0, 0, 255);
465}
466
467// This test generates (and uses) mipmaps on a texture using init data. D3D11 will use a non-renderable TextureStorage for this.
468// The test then disables mips, renders to level zero of the texture, and reenables mips before using the texture again.
469// To do this, D3D11 has to convert the TextureStorage into a renderable one.
470// This test ensures that the conversion works correctly.
471// 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.
Jamie Madillfa05f602015-05-07 13:47:11 -0400472TEST_P(MipmapTest, GenerateMipmapFromInitDataThenRender)
Austin Kinross215b37a2014-12-22 12:56:07 -0800473{
474 // Pass in initial data so the texture is blue.
475 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
476
477 // Then generate the mips.
478 glGenerateMipmap(GL_TEXTURE_2D);
479 ASSERT_GL_NO_ERROR();
480
481 // Enable mipmaps.
482 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
483
484 // Now draw the texture to various different sized areas.
Austin Kinross62815bf2015-01-15 16:32:36 -0800485 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800486 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
487
488 // Use mip level 1
Austin Kinross62815bf2015-01-15 16:32:36 -0800489 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800490 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
491
492 // Use mip level 2
Austin Kinross62815bf2015-01-15 16:32:36 -0800493 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800494 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
495
496 ASSERT_GL_NO_ERROR();
497
498 // Disable mips. Render a quad using the texture and ensure it's blue.
499 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Austin Kinross62815bf2015-01-15 16:32:36 -0800500 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800501 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
502
503 // Clear level 0 of the texture.
504 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
505 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
506 glClear(GL_COLOR_BUFFER_BIT);
507
508 // Reenable mips, and try rendering different-sized quads.
509 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
510
511 // Level 0 is now red, so this should render red.
Austin Kinross62815bf2015-01-15 16:32:36 -0800512 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800513 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
514
515 // Use mip level 1, blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800516 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800517 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
518
519 // Use mip level 2, blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800520 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800521 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
522}
523
524// This test ensures that mips are correctly generated from a rendered image.
525// In particular, on D3D11 Feature Level 9_3, the clear call will be performed on the zero-level texture, rather than the mipped one.
526// The test ensures that the zero-level texture is correctly copied into the mipped texture before the mipmaps are generated.
Jamie Madillfa05f602015-05-07 13:47:11 -0400527TEST_P(MipmapTest, GenerateMipmapFromRenderedImage)
Austin Kinross215b37a2014-12-22 12:56:07 -0800528{
529 // Bind the offscreen framebuffer/texture.
530 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
531
532 // Clear the texture to blue.
533 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
534 glClear(GL_COLOR_BUFFER_BIT);
535
536 // Then generate the mips
537 glGenerateMipmap(GL_TEXTURE_2D);
538 ASSERT_GL_NO_ERROR();
539
540 // Enable mips.
541 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
542
543 // Now draw the texture to various different sized areas.
Austin Kinross62815bf2015-01-15 16:32:36 -0800544 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800545 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
546
547 // Use mip level 1
Austin Kinross62815bf2015-01-15 16:32:36 -0800548 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800549 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
550
551 // Use mip level 2
Austin Kinross62815bf2015-01-15 16:32:36 -0800552 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800553 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
554}
555
556// Test to ensure that rendering to a mipmapped texture works, regardless of whether mipmaps are enabled or not.
557// TODO: This test hits a texture rebind bug in the D3D11 renderer. Fix this.
Jamie Madillfa05f602015-05-07 13:47:11 -0400558TEST_P(MipmapTest, RenderOntoLevelZeroAfterGenerateMipmap)
Austin Kinross215b37a2014-12-22 12:56:07 -0800559{
Geoff Langf74fef52015-04-29 12:57:52 -0400560 // TODO(geofflang): Figure out why this is broken on AMD OpenGL
561 if (isAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
562 {
563 std::cout << "Test skipped on AMD OpenGL." << std::endl;
564 return;
565 }
566
Austin Kinross215b37a2014-12-22 12:56:07 -0800567 // Bind the offscreen texture/framebuffer.
568 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
569
570 // Clear the texture to blue.
571 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
572 glClear(GL_COLOR_BUFFER_BIT);
573
574 // From now on, default clear color is black.
575 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
576
577 // Now, draw the texture to a quad that's the same size as the texture. This draws to the default framebuffer.
578 // The quad should be blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800579 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800580 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
581
582 // Now go back to the texture, and generate mips on it.
583 glGenerateMipmap(GL_TEXTURE_2D);
584 ASSERT_GL_NO_ERROR();
585
586 // Now try rendering the textured quad again. Note: we've not told GL to use the generated mips.
587 // The quad should be blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800588 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800589 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
590
591 // Now tell GL to use the generated mips.
592 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
593 EXPECT_EQ(glGetError(), GL_NONE);
594
595 // Now render the textured quad again. It should be still be blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800596 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800597 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
598
599 // 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 -0800600 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800601 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
602
603 // Now clear the texture to green. This just clears the top level. The lower mips should remain blue.
604 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
605 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
606 glClear(GL_COLOR_BUFFER_BIT);
607
608 // From now on, default clear color is black.
609 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
610
611 // 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 -0800612 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800613 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 255, 0, 255);
614
615 // Render a small textured quad. This forces minification, so should render blue (the color of levels 1+).
Austin Kinross62815bf2015-01-15 16:32:36 -0800616 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800617 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
618
619 // Disable mipmaps again
620 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
621 ASSERT_GL_NO_ERROR();
622
623 // 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 -0800624 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800625 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 255, 0, 255);
626
627 // 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 -0800628 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800629 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 255, 0, 255);
630}
631
Austin Kinross62815bf2015-01-15 16:32:36 -0800632// This test ensures that the level-zero workaround for TextureCubes (on D3D11 Feature Level 9_3)
633// works as expected. It tests enabling/disabling mipmaps, generating mipmaps, and rendering to level zero.
Jamie Madillfa05f602015-05-07 13:47:11 -0400634TEST_P(MipmapTest, TextureCubeGeneralLevelZero)
Austin Kinross62815bf2015-01-15 16:32:36 -0800635{
636 GLfloat vertexLocations[] =
637 {
638 -1.0f, 1.0f, 0.0f,
639 -1.0f, -1.0f, 0.0f,
640 1.0f, 1.0f, 0.0f,
641 1.0f, -1.0f, 0.0f,
642 };
643
644 // Set up the viewport, program, attributes, sampler and texture for the cube
645 glBindFramebuffer(GL_FRAMEBUFFER, 0);
646 glViewport(0, 0, getWindowWidth(), getWindowHeight());
647 glUseProgram(mCubeProgram);
648 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertexLocations);
649 glEnableVertexAttribArray(0);
650 glUniform1i(0, 0);
651 glActiveTexture(GL_TEXTURE0);
652 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
653
654 // Draw. Since the negative-Y face's is blue, this should be blue.
655 glClear(GL_COLOR_BUFFER_BIT);
656 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
657 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
658
659 // Generate mipmaps, and render. This should be blue.
660 glClear(GL_COLOR_BUFFER_BIT);
661 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
662 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
663 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
664 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
665 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
666
667 // Draw using a smaller viewport (to force a lower LOD of the texture). This should still be blue.
668 glClear(GL_COLOR_BUFFER_BIT);
669 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
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.
Austin Kinross62815bf2015-01-15 16:32:36 -0800674 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
675 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mOffscreenTextureCube, 0);
676 ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
677 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
678 glClear(GL_COLOR_BUFFER_BIT);
679
680 // Switch back to the default framebuffer
681 glBindFramebuffer(GL_FRAMEBUFFER, 0);
682 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
683
684 // Draw using a full-size viewport. This should be red.
685 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
686 glClear(GL_COLOR_BUFFER_BIT);
687 glViewport(0, 0, getWindowWidth(), getWindowHeight());
688 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
689 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
690
691 // Draw using a quarter-size viewport, to force a lower LOD. This should be *BLUE*, since we only cleared level zero
692 // of the negative-Y face to red, and left its mipmaps blue.
693 glClear(GL_COLOR_BUFFER_BIT);
694 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
695 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
696 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
697
698 // Disable mipmaps again, and draw a to a quarter-size viewport.
699 // Since this should use level zero of the texture, this should be *RED*.
700 glClear(GL_COLOR_BUFFER_BIT);
701 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
702 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
703 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
704 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
705}
706
707// This test ensures that rendering to level-zero of a TextureCube works as expected.
Jamie Madillfa05f602015-05-07 13:47:11 -0400708TEST_P(MipmapTest, TextureCubeRenderToLevelZero)
Austin Kinross62815bf2015-01-15 16:32:36 -0800709{
710 GLfloat vertexLocations[] =
711 {
712 -1.0f, 1.0f, 0.0f,
713 -1.0f, -1.0f, 0.0f,
714 1.0f, 1.0f, 0.0f,
715 1.0f, -1.0f, 0.0f,
716 };
717
718 // Set up the viewport, program, attributes, sampler and texture for the cube
719 glBindFramebuffer(GL_FRAMEBUFFER, 0);
720 glViewport(0, 0, getWindowWidth(), getWindowHeight());
721 glUseProgram(mCubeProgram);
722 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertexLocations);
723 glEnableVertexAttribArray(0);
724 glUniform1i(0, 0);
725 glActiveTexture(GL_TEXTURE0);
726 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
727
728 // Draw. Since the negative-Y face's is blue, this should be blue.
729 glClear(GL_COLOR_BUFFER_BIT);
730 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
731 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
732
733 // Now clear the negative-Y face of the cube to red.
Austin Kinross62815bf2015-01-15 16:32:36 -0800734 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
735 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mOffscreenTextureCube, 0);
736 ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
737 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
738 glClear(GL_COLOR_BUFFER_BIT);
739
740 // Switch back to the default framebuffer
741 glBindFramebuffer(GL_FRAMEBUFFER, 0);
742 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
743
744 // Draw using a full-size viewport. This should be red.
745 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
746 glClear(GL_COLOR_BUFFER_BIT);
747 glViewport(0, 0, getWindowWidth(), getWindowHeight());
748 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
749 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
750
751 // Draw a to a quarter-size viewport. This should also be red.
752 glClear(GL_COLOR_BUFFER_BIT);
753 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
754 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
755 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
756}
757
Austin Kinross215b37a2014-12-22 12:56:07 -0800758// Creates a mipmapped 2D array texture with three layers, and calls ANGLE's GenerateMipmap.
759// Then tests if the mipmaps are rendered correctly for all three layers.
Jamie Madillfa05f602015-05-07 13:47:11 -0400760TEST_P(MipmapTestES3, MipmapsForTextureArray)
Austin Kinross215b37a2014-12-22 12:56:07 -0800761{
762 int px = getWindowWidth() / 2;
763 int py = getWindowHeight() / 2;
764
765 glActiveTexture(GL_TEXTURE0);
766 glBindTexture(GL_TEXTURE_2D_ARRAY, mTextureArray);
767
768 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 5, GL_RGBA8, 16, 16, 3);
769
770 // Fill the first layer with red
771 std::vector<GLubyte> pixels(4 * 16 * 16);
772 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
773 {
774 pixels[pixelId * 4 + 0] = 255;
775 pixels[pixelId * 4 + 1] = 0;
776 pixels[pixelId * 4 + 2] = 0;
777 pixels[pixelId * 4 + 3] = 255;
778 }
779
780 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
781
782 // Fill the second layer with green
783 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
784 {
785 pixels[pixelId * 4 + 0] = 0;
786 pixels[pixelId * 4 + 1] = 255;
787 pixels[pixelId * 4 + 2] = 0;
788 pixels[pixelId * 4 + 3] = 255;
789 }
790
791 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
792
793 // Fill the third layer with blue
794 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
795 {
796 pixels[pixelId * 4 + 0] = 0;
797 pixels[pixelId * 4 + 1] = 0;
798 pixels[pixelId * 4 + 2] = 255;
799 pixels[pixelId * 4 + 3] = 255;
800 }
801
802 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
803
804 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
805 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
806
807 EXPECT_GL_NO_ERROR();
808
809 glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
810
811 EXPECT_GL_NO_ERROR();
812
813 glUseProgram(mArrayProgram);
814 glUniform1i(mTextureArrayUniformLocation, 0);
815
816 EXPECT_GL_NO_ERROR();
817
818 // Draw the first slice
819 glUseProgram(mArrayProgram);
820 glUniform1i(mTextureArraySliceUniformLocation, 0);
821 drawQuad(mArrayProgram, "position", 0.5f);
822 EXPECT_GL_NO_ERROR();
823 EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
824
825 // Draw the second slice
826 glUseProgram(mArrayProgram);
827 glUniform1i(mTextureArraySliceUniformLocation, 1);
828 drawQuad(mArrayProgram, "position", 0.5f);
829 EXPECT_GL_NO_ERROR();
830 EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
831
832 // Draw the third slice
833 glUseProgram(mArrayProgram);
834 glUniform1i(mTextureArraySliceUniformLocation, 2);
835 drawQuad(mArrayProgram, "position", 0.5f);
836 EXPECT_GL_NO_ERROR();
837 EXPECT_PIXEL_EQ(px, py, 0, 0, 255, 255);
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000838}
839
840// Creates a mipmapped 3D texture with two layers, and calls ANGLE's GenerateMipmap.
841// Then tests if the mipmaps are rendered correctly for all two layers.
Jamie Madillfa05f602015-05-07 13:47:11 -0400842TEST_P(MipmapTestES3, MipmapsForTexture3D)
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000843{
844 int px = getWindowWidth() / 2;
845 int py = getWindowHeight() / 2;
846
847 glActiveTexture(GL_TEXTURE0);
848 glBindTexture(GL_TEXTURE_3D, mTexture3D);
849
850 glTexStorage3D(GL_TEXTURE_3D, 5, GL_RGBA8, 16, 16, 2);
851
852 // Fill the first layer with red
853 std::vector<GLubyte> pixels(4 * 16 * 16);
854 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
855 {
856 pixels[pixelId * 4 + 0] = 255;
857 pixels[pixelId * 4 + 1] = 0;
858 pixels[pixelId * 4 + 2] = 0;
859 pixels[pixelId * 4 + 3] = 255;
860 }
861
862 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
863
864 // Fill the second layer with green
865 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
866 {
867 pixels[pixelId * 4 + 0] = 0;
868 pixels[pixelId * 4 + 1] = 255;
869 pixels[pixelId * 4 + 2] = 0;
870 pixels[pixelId * 4 + 3] = 255;
871 }
872
873 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 1, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
874
875 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
876 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
877
878 EXPECT_GL_NO_ERROR();
879
880 glGenerateMipmap(GL_TEXTURE_3D);
881
882 EXPECT_GL_NO_ERROR();
883
884 glUseProgram(m3DProgram);
885 glUniform1i(mTexture3DUniformLocation, 0);
886
887 EXPECT_GL_NO_ERROR();
888
889 // Mipmap level 0
890 // Draw the first slice
891 glUseProgram(m3DProgram);
892 glUniform1f(mTexture3DLODUniformLocation, 0.);
893 glUniform1f(mTexture3DSliceUniformLocation, 0.25f);
894 drawQuad(m3DProgram, "position", 0.5f);
895 EXPECT_GL_NO_ERROR();
896 EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
897
898 // Draw the second slice
899 glUseProgram(m3DProgram);
900 glUniform1f(mTexture3DSliceUniformLocation, 0.75f);
901 drawQuad(m3DProgram, "position", 0.5f);
902 EXPECT_GL_NO_ERROR();
903 EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
904
905 // Mipmap level 1
906 // The second mipmap should only have one slice.
907
908 glUseProgram(m3DProgram);
909 glUniform1f(mTexture3DLODUniformLocation, 1.);
910 drawQuad(m3DProgram, "position", 0.5f);
911 EXPECT_GL_NO_ERROR();
912 EXPECT_PIXEL_EQ(px, py, 127, 127, 0, 255);
913
914 glUseProgram(m3DProgram);
915 glUniform1f(mTexture3DSliceUniformLocation, 0.75f);
916 drawQuad(m3DProgram, "position", 0.5f);
917 EXPECT_GL_NO_ERROR();
918 EXPECT_PIXEL_EQ(px, py, 127, 127, 0, 255);
919}
Jamie Madillfa05f602015-05-07 13:47:11 -0400920
921// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
922// Note: we run these tests against 9_3 on WARP due to hardware driver issues on Win7
923ANGLE_INSTANTIATE_TEST(MipmapTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3_WARP(), ES2_OPENGL(), ES3_OPENGL());
924ANGLE_INSTANTIATE_TEST(MipmapTestES3, ES3_D3D11());