blob: 7c842f6b6210b95e7ebd2a669b593911a039e3e5 [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.
Austin Kinrosseea095e2015-01-23 14:06:50 -08004// Note: we run these tests against 9_3 on WARP due to hardware driver issues on Win7
5ANGLE_TYPED_TEST_CASE(MipmapTest, ES2_D3D9, ES2_D3D11, ES2_D3D11_FL9_3_WARP);
Austin Kinross215b37a2014-12-22 12:56:07 -08006ANGLE_TYPED_TEST_CASE(MipmapTestES3, ES3_D3D11);
7
8template<typename T>
9class MipmapTest : public ANGLETest
10{
11 protected:
12 MipmapTest() : ANGLETest(T::GetGlesMajorVersion(), T::GetPlatform())
13 {
14 setWindowWidth(128);
15 setWindowHeight(128);
16 setConfigRedBits(8);
17 setConfigGreenBits(8);
18 setConfigBlueBits(8);
19 setConfigAlphaBits(8);
20 }
21
22 virtual void SetUp()
23 {
24 ANGLETest::SetUp();
25
26 // Vertex Shader source
27 const std::string vs = SHADER_SOURCE
28 (
29 attribute vec4 aPosition;
30 attribute vec2 aTexCoord;
31 varying vec2 vTexCoord;
32
33 void main()
34 {
35 gl_Position = aPosition;
36 vTexCoord = aTexCoord;
37 }
38 );
39
40 // Fragment Shader source
41 const std::string fs = SHADER_SOURCE
42 (
43 precision mediump float;
44
45 uniform sampler2D uTexture;
46 varying vec2 vTexCoord;
47
48 void main()
49 {
50 gl_FragColor = texture2D(uTexture, vTexCoord);
51 }
52 );
53
Austin Kinross62815bf2015-01-15 16:32:36 -080054 m2DProgram = CompileProgram(vs, fs);
55 if (m2DProgram == 0)
Austin Kinross215b37a2014-12-22 12:56:07 -080056 {
57 FAIL() << "shader compilation failed.";
58 }
59
Austin Kinross62815bf2015-01-15 16:32:36 -080060 // A simple vertex shader for the texture cube
61 const std::string cubeVS = SHADER_SOURCE
62 (
63 attribute vec4 aPosition;
64 varying vec4 vPosition;
65 void main()
66 {
67 gl_Position = aPosition;
68 vPosition = aPosition;
69 }
70 );
71
72 // A very simple fragment shader to sample from the negative-Y face of a texture cube.
73 const std::string cubeFS = SHADER_SOURCE
74 (
75 precision mediump float;
76 uniform samplerCube uTexture;
77 varying vec4 vPosition;
78
79 void main()
80 {
81 gl_FragColor = textureCube(uTexture, vec3(vPosition.x, -1, vPosition.y));
82 }
83 );
84
85 mCubeProgram = CompileProgram(cubeVS, cubeFS);
86 if (mCubeProgram == 0)
87 {
88 FAIL() << "shader compilation failed.";
89 }
90
91 m2DTextureUniformPosition = glGetUniformLocation(m2DProgram, "uTexture");
92 m2DPositionAttributePosition = glGetAttribLocation(m2DProgram, "aPosition");
93 m2DTexCoordAttributePosition = glGetAttribLocation(m2DProgram, "aTexCoord");
94
95 mLevelZeroBlueInitData = createRGBInitData(getWindowWidth(), getWindowHeight(), 0, 0, 255); // Blue
96 mLevelZeroWhiteInitData = createRGBInitData(getWindowWidth(), getWindowHeight(), 255, 255, 255); // White
97 mLevelOneInitData = createRGBInitData((getWindowWidth() / 2), (getWindowHeight() / 2), 0, 255, 0); // Green
98 mLevelTwoInitData = createRGBInitData((getWindowWidth() / 4), (getWindowHeight() / 4), 255, 0, 0); // Red
Austin Kinross215b37a2014-12-22 12:56:07 -080099
100 glGenFramebuffers(1, &mOffscreenFramebuffer);
Austin Kinross62815bf2015-01-15 16:32:36 -0800101 glGenTextures(1, &mOffscreenTexture2D);
Austin Kinross215b37a2014-12-22 12:56:07 -0800102
Austin Kinross62815bf2015-01-15 16:32:36 -0800103 // Initialize the texture2D to be empty, and don't use mips.
104 glBindTexture(GL_TEXTURE_2D, mOffscreenTexture2D);
Austin Kinross215b37a2014-12-22 12:56:07 -0800105 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
107 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
108
Austin Kinross62815bf2015-01-15 16:32:36 -0800109 // Bind the texture2D to the offscreen framebuffer's color buffer.
Austin Kinross215b37a2014-12-22 12:56:07 -0800110 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
Austin Kinross62815bf2015-01-15 16:32:36 -0800111 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mOffscreenTexture2D, 0);
Austin Kinross215b37a2014-12-22 12:56:07 -0800112 ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
113
Austin Kinross62815bf2015-01-15 16:32:36 -0800114 // Create a non-mipped texture cube. Set the negative-Y face to be blue.
115 glGenTextures(1, &mOffscreenTextureCube);
116 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
117 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
118 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
119 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
120 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
121 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
122 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
123
124 // Complete the texture cube without mipmaps to start with.
125 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
126 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
127
128 ASSERT_GL_NO_ERROR();
Austin Kinross215b37a2014-12-22 12:56:07 -0800129 }
130
131 virtual void TearDown()
132 {
Austin Kinross62815bf2015-01-15 16:32:36 -0800133 glDeleteProgram(m2DProgram);
134 glDeleteProgram(mCubeProgram);
Austin Kinross215b37a2014-12-22 12:56:07 -0800135 glDeleteFramebuffers(1, &mOffscreenFramebuffer);
Austin Kinross62815bf2015-01-15 16:32:36 -0800136 glDeleteTextures(1, &mOffscreenTexture2D);
137 glDeleteTextures(1, &mOffscreenTextureCube);
Austin Kinross215b37a2014-12-22 12:56:07 -0800138
139 delete mLevelZeroBlueInitData;
140 delete mLevelZeroWhiteInitData;
141 delete mLevelOneInitData;
142 delete mLevelTwoInitData;
143
144 ANGLETest::TearDown();
145 }
146
147 GLubyte *createRGBInitData(GLint width, GLint height, GLint r, GLint g, GLint b)
148 {
149 GLubyte *data = new GLubyte[3 * width * height];
150
151 for (int i = 0; i < width * height; i+=1)
152 {
153 data[3 * i + 0] = r;
154 data[3 * i + 1] = g;
155 data[3 * i + 2] = b;
156 }
157
158 return data;
159 }
160
161 void ClearAndDrawTexturedQuad(GLuint texture, GLsizei viewportWidth, GLsizei viewportHeight)
162 {
163 glBindFramebuffer(GL_FRAMEBUFFER, 0);
164 glClear(GL_COLOR_BUFFER_BIT);
165
166 glViewport(0, 0, viewportWidth, viewportHeight);
167
168 ASSERT_GL_NO_ERROR();
169
170 GLfloat vertexLocations[] =
171 {
172 -1.0f, 1.0f, 0.0f,
173 -1.0f, -1.0f, 0.0f,
174 1.0f, 1.0f, 0.0f,
175 1.0f, -1.0f, 0.0f,
176 };
177
178 GLfloat vertexTexCoords[] =
179 {
180 0.0f, 1.0f,
181 0.0f, 0.0f,
182 1.0f, 1.0f,
183 1.0f, 0.0f,
184 };
185
Austin Kinross62815bf2015-01-15 16:32:36 -0800186 glUseProgram(m2DProgram);
Austin Kinross215b37a2014-12-22 12:56:07 -0800187
188 glActiveTexture(GL_TEXTURE0);
189 glBindTexture(GL_TEXTURE_2D, texture);
Austin Kinross62815bf2015-01-15 16:32:36 -0800190 glUniform1i(m2DTextureUniformPosition, 0);
Austin Kinross215b37a2014-12-22 12:56:07 -0800191
Austin Kinross62815bf2015-01-15 16:32:36 -0800192 glVertexAttribPointer(m2DPositionAttributePosition, 3, GL_FLOAT, GL_FALSE, 0, vertexLocations);
193 glEnableVertexAttribArray(m2DPositionAttributePosition);
Austin Kinross215b37a2014-12-22 12:56:07 -0800194
Austin Kinross62815bf2015-01-15 16:32:36 -0800195 glVertexAttribPointer(m2DTexCoordAttributePosition, 2, GL_FLOAT, GL_FALSE, 0, vertexTexCoords);
196 glEnableVertexAttribArray(m2DTexCoordAttributePosition);
Austin Kinross215b37a2014-12-22 12:56:07 -0800197
198 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
199 }
200
Austin Kinross62815bf2015-01-15 16:32:36 -0800201 GLuint m2DProgram;
202 GLuint mCubeProgram;
Austin Kinross215b37a2014-12-22 12:56:07 -0800203 GLuint mOffscreenFramebuffer;
Austin Kinross62815bf2015-01-15 16:32:36 -0800204 GLuint mOffscreenTexture2D;
205 GLuint mOffscreenTextureCube;
Austin Kinross215b37a2014-12-22 12:56:07 -0800206
Austin Kinross62815bf2015-01-15 16:32:36 -0800207 GLint m2DTextureUniformPosition;
208 GLint m2DPositionAttributePosition;
209 GLint m2DTexCoordAttributePosition;
Austin Kinross215b37a2014-12-22 12:56:07 -0800210
211 GLubyte* mLevelZeroBlueInitData;
212 GLubyte* mLevelZeroWhiteInitData;
213 GLubyte* mLevelOneInitData;
214 GLubyte* mLevelTwoInitData;
215};
216
217template<typename T>
218class MipmapTestES3 : public ANGLETest
219{
220protected:
221 MipmapTestES3() : ANGLETest(T::GetGlesMajorVersion(), T::GetPlatform())
222 {
223 setWindowWidth(128);
224 setWindowHeight(128);
225 setConfigRedBits(8);
226 setConfigGreenBits(8);
227 setConfigBlueBits(8);
228 setConfigAlphaBits(8);
229 }
230
231 virtual void SetUp()
232 {
233 ANGLETest::SetUp();
234
235 glGenTextures(1, &mTextureArray);
236 EXPECT_GL_NO_ERROR();
237
238 ASSERT_GL_NO_ERROR();
239
Austin Kinrosse8c86272015-01-15 18:55:36 -0800240 // Don't put "#version ..." on its own line. See [cpp]p1:
241 // "If there are sequences of preprocessing tokens within the list of arguments that
242 // would otherwise act as preprocessing directives, the behavior is undefined"
Austin Kinross215b37a2014-12-22 12:56:07 -0800243 const std::string vertexShaderSource = SHADER_SOURCE
Austin Kinrosse8c86272015-01-15 18:55:36 -0800244 ( #version 300 es\n
Austin Kinross215b37a2014-12-22 12:56:07 -0800245 precision highp float;
246 in vec4 position;
247 out vec2 texcoord;
248
249 uniform vec2 textureScale;
250
251 void main()
252 {
253 gl_Position = vec4(position.xy * textureScale, 0.0, 1.0);
254 texcoord = (position.xy * 0.5) + 0.5;
255 }
256 );
257
258 const std::string fragmentShaderSourceArray = SHADER_SOURCE
Austin Kinrosse8c86272015-01-15 18:55:36 -0800259 ( #version 300 es\n
Austin Kinross215b37a2014-12-22 12:56:07 -0800260 precision highp float;
261 uniform sampler2DArray tex;
262 uniform int slice;
263 in vec2 texcoord;
264 out vec4 out_FragColor;
265
266 void main()
267 {
268 out_FragColor = texture(tex, vec3(texcoord, float(slice)));
269 }
270 );
271
272 mArrayProgram = CompileProgram(vertexShaderSource, fragmentShaderSourceArray);
273 if (mArrayProgram == 0)
274 {
275 FAIL() << "shader compilation failed.";
276 }
277
278 mTextureArrayUniformLocation = glGetUniformLocation(mArrayProgram, "tex");
279 ASSERT_NE(-1, mTextureArrayUniformLocation);
280
281 mTextureArrayScaleUniformLocation = glGetUniformLocation(mArrayProgram, "textureScale");
282 ASSERT_NE(-1, mTextureArrayScaleUniformLocation);
283
284 mTextureArraySliceUniformLocation = glGetUniformLocation(mArrayProgram, "slice");
285 ASSERT_NE(-1, mTextureArraySliceUniformLocation);
286
287 glUseProgram(mArrayProgram);
288 glUniform2f(mTextureArrayScaleUniformLocation, 1.0f, 1.0f);
289 glUseProgram(0);
290 ASSERT_GL_NO_ERROR();
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000291
292 glGenTextures(1, &mTexture3D);
293
294 ASSERT_GL_NO_ERROR();
295
296 const std::string fragmentShaderSource3D = SHADER_SOURCE
297 ( #version 300 es\n
298 precision highp float;
299 uniform sampler3D tex;
300 uniform float slice;
301 uniform float lod;
302 in vec2 texcoord;
303 out vec4 out_FragColor;
304
305 void main()
306 {
307 out_FragColor = textureLod(tex, vec3(texcoord, slice), lod);
308 }
309 );
310
311 m3DProgram = CompileProgram(vertexShaderSource, fragmentShaderSource3D);
312 if (m3DProgram == 0)
313 {
314 FAIL() << "shader compilation failed.";
315 }
316
317 mTexture3DUniformLocation = glGetUniformLocation(m3DProgram, "tex");
318 ASSERT_NE(-1, mTexture3DUniformLocation);
319
320 mTexture3DScaleUniformLocation = glGetUniformLocation(m3DProgram, "textureScale");
321 ASSERT_NE(-1, mTexture3DScaleUniformLocation);
322
323 mTexture3DSliceUniformLocation = glGetUniformLocation(m3DProgram, "slice");
324 ASSERT_NE(-1, mTexture3DSliceUniformLocation);
325
326 mTexture3DLODUniformLocation = glGetUniformLocation(m3DProgram, "lod");
327 ASSERT_NE(-1, mTexture3DLODUniformLocation);
328
329 glUseProgram(m3DProgram);
330 glUniform2f(mTexture3DScaleUniformLocation, 1.0f, 1.0f);
331 glUniform1f(mTexture3DLODUniformLocation, 0);
332 glUseProgram(0);
333 ASSERT_GL_NO_ERROR();
Austin Kinross215b37a2014-12-22 12:56:07 -0800334 }
335
336 virtual void TearDown()
337 {
338 glDeleteTextures(1, &mTextureArray);
339 glDeleteProgram(mArrayProgram);
340
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000341 glDeleteTextures(1, &mTexture3D);
342 glDeleteProgram(m3DProgram);
343
Austin Kinross215b37a2014-12-22 12:56:07 -0800344 ANGLETest::TearDown();
345 }
346
347 GLuint mTextureArray;
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000348 GLuint mTexture3D;
Austin Kinross215b37a2014-12-22 12:56:07 -0800349
350 GLuint mArrayProgram;
351 GLint mTextureArrayUniformLocation;
352 GLint mTextureArrayScaleUniformLocation;
353 GLint mTextureArraySliceUniformLocation;
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000354
355 GLuint m3DProgram;
356 GLint mTexture3DUniformLocation;
357 GLint mTexture3DScaleUniformLocation;
358 GLint mTexture3DSliceUniformLocation;
359 GLint mTexture3DLODUniformLocation;
Austin Kinross215b37a2014-12-22 12:56:07 -0800360};
361
362// 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.
363// This ensures that renderers using the zero LOD workaround (e.g. D3D11 FL9_3) correctly pass init data to the mipmapped texture,
364// even if the the zero-LOD texture is currently in use.
Austin Kinross276171b2015-01-15 13:16:18 -0800365TYPED_TEST(MipmapTest, DISABLED_ThreeLevelsInitData)
Austin Kinross215b37a2014-12-22 12:56:07 -0800366{
367 // Pass in level zero init data.
Austin Kinross62815bf2015-01-15 16:32:36 -0800368 glBindTexture(GL_TEXTURE_2D, mOffscreenTexture2D);
Austin Kinross215b37a2014-12-22 12:56:07 -0800369 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
370 ASSERT_GL_NO_ERROR();
371
372 // Disable mips.
373 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
374
375 // Draw a full-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800376 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800377 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
378
379 // Draw a half-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800380 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800381 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
382
383 // Draw a quarter-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800384 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800385 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
386
387 // Complete the texture by initializing the remaining levels.
388 int n = 1;
389 while (getWindowWidth() / pow(2, n) >= 1)
390 {
391 glTexImage2D(GL_TEXTURE_2D, n, GL_RGB, getWindowWidth() / pow(2, n), getWindowWidth() / pow(2, n), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
392 ASSERT_GL_NO_ERROR();
393 n+=1;
394 }
395
396 // Pass in level one init data.
397 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelOneInitData);
398 ASSERT_GL_NO_ERROR();
399
400 // Draw a full-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800401 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800402 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
403
404 // 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 -0800405 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800406 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
407
408 // Enable mipmaps.
409 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
410
411 // Draw a half-sized quad, and check it's green.
Austin Kinross62815bf2015-01-15 16:32:36 -0800412 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800413 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
414
415 // 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 -0800416 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800417 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 0, 255);
418
419 // Pass in level two init data.
420 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, getWindowWidth() / 4, getWindowHeight() / 4, 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelTwoInitData);
421 ASSERT_GL_NO_ERROR();
422
423 // Draw a full-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800424 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800425 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
426
427 // Draw a half-sized quad, and check it's green.
Austin Kinross62815bf2015-01-15 16:32:36 -0800428 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800429 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
430
431 // Draw a quarter-sized quad, and check it's red.
Austin Kinross62815bf2015-01-15 16:32:36 -0800432 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800433 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 0, 0, 255);
434
435 // Now disable mipmaps again, and render multiple sized quads. They should all be blue, since level 0 is blue.
436 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Austin Kinross62815bf2015-01-15 16:32:36 -0800437 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800438 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800439 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800440 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800441 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800442 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
443
444 // Now reset level 0 to white, keeping mipmaps disabled. Then, render various sized quads. They should be white.
445 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroWhiteInitData);
446 ASSERT_GL_NO_ERROR();
447
Austin Kinross62815bf2015-01-15 16:32:36 -0800448 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800449 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800450 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800451 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 255, 255, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800452 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800453 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 255, 255, 255);
454
455 // Then enable mipmaps again. The quads should be white, green, red respectively.
456 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
457
Austin Kinross62815bf2015-01-15 16:32:36 -0800458 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800459 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800460 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800461 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800462 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800463 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 0, 0, 255);
464}
465
466// This test generates (and uses) mipmaps on a texture using init data. D3D11 will use a non-renderable TextureStorage for this.
467// The test then disables mips, renders to level zero of the texture, and reenables mips before using the texture again.
468// To do this, D3D11 has to convert the TextureStorage into a renderable one.
469// This test ensures that the conversion works correctly.
470// 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.
Austin Kinrosseea095e2015-01-23 14:06:50 -0800471TYPED_TEST(MipmapTest, GenerateMipmapFromInitDataThenRender)
Austin Kinross215b37a2014-12-22 12:56:07 -0800472{
473 // Pass in initial data so the texture is blue.
474 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
475
476 // Then generate the mips.
477 glGenerateMipmap(GL_TEXTURE_2D);
478 ASSERT_GL_NO_ERROR();
479
480 // Enable mipmaps.
481 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
482
483 // Now draw the texture to various different sized areas.
Austin Kinross62815bf2015-01-15 16:32:36 -0800484 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800485 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
486
487 // Use mip level 1
Austin Kinross62815bf2015-01-15 16:32:36 -0800488 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800489 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
490
491 // Use mip level 2
Austin Kinross62815bf2015-01-15 16:32:36 -0800492 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800493 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
494
495 ASSERT_GL_NO_ERROR();
496
497 // Disable mips. Render a quad using the texture and ensure it's blue.
498 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Austin Kinross62815bf2015-01-15 16:32:36 -0800499 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800500 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
501
502 // Clear level 0 of the texture.
503 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
504 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
505 glClear(GL_COLOR_BUFFER_BIT);
506
507 // Reenable mips, and try rendering different-sized quads.
508 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
509
510 // Level 0 is now red, so this should render red.
Austin Kinross62815bf2015-01-15 16:32:36 -0800511 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800512 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
513
514 // Use mip level 1, blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800515 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800516 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
517
518 // Use mip level 2, blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800519 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800520 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
521}
522
523// This test ensures that mips are correctly generated from a rendered image.
524// In particular, on D3D11 Feature Level 9_3, the clear call will be performed on the zero-level texture, rather than the mipped one.
525// The test ensures that the zero-level texture is correctly copied into the mipped texture before the mipmaps are generated.
Austin Kinrosseea095e2015-01-23 14:06:50 -0800526TYPED_TEST(MipmapTest, GenerateMipmapFromRenderedImage)
Austin Kinross215b37a2014-12-22 12:56:07 -0800527{
528 // Bind the offscreen framebuffer/texture.
529 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
530
531 // Clear the texture to blue.
532 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
533 glClear(GL_COLOR_BUFFER_BIT);
534
535 // Then generate the mips
536 glGenerateMipmap(GL_TEXTURE_2D);
537 ASSERT_GL_NO_ERROR();
538
539 // Enable mips.
540 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
541
542 // Now draw the texture to various different sized areas.
Austin Kinross62815bf2015-01-15 16:32:36 -0800543 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800544 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
545
546 // Use mip level 1
Austin Kinross62815bf2015-01-15 16:32:36 -0800547 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800548 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
549
550 // Use mip level 2
Austin Kinross62815bf2015-01-15 16:32:36 -0800551 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800552 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
553}
554
555// Test to ensure that rendering to a mipmapped texture works, regardless of whether mipmaps are enabled or not.
556// TODO: This test hits a texture rebind bug in the D3D11 renderer. Fix this.
Austin Kinrosseea095e2015-01-23 14:06:50 -0800557TYPED_TEST(MipmapTest, RenderOntoLevelZeroAfterGenerateMipmap)
Austin Kinross215b37a2014-12-22 12:56:07 -0800558{
559 // Bind the offscreen texture/framebuffer.
560 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
561
562 // Clear the texture to blue.
563 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
564 glClear(GL_COLOR_BUFFER_BIT);
565
566 // From now on, default clear color is black.
567 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
568
569 // Now, draw the texture to a quad that's the same size as the texture. This draws to the default framebuffer.
570 // The quad should be blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800571 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800572 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
573
574 // Now go back to the texture, and generate mips on it.
575 glGenerateMipmap(GL_TEXTURE_2D);
576 ASSERT_GL_NO_ERROR();
577
578 // Now try rendering the textured quad again. Note: we've not told GL to use the generated mips.
579 // The quad should be blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800580 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800581 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
582
583 // Now tell GL to use the generated mips.
584 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
585 EXPECT_EQ(glGetError(), GL_NONE);
586
587 // Now render the textured quad again. It should be still 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 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 -0800592 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800593 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
594
595 // Now clear the texture to green. This just clears the top level. The lower mips should remain blue.
596 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
597 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
598 glClear(GL_COLOR_BUFFER_BIT);
599
600 // From now on, default clear color is black.
601 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
602
603 // 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 -0800604 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800605 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 255, 0, 255);
606
607 // Render a small textured quad. This forces minification, so should render blue (the color of levels 1+).
Austin Kinross62815bf2015-01-15 16:32:36 -0800608 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800609 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
610
611 // Disable mipmaps again
612 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
613 ASSERT_GL_NO_ERROR();
614
615 // 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 -0800616 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800617 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 255, 0, 255);
618
619 // 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 -0800620 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800621 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 255, 0, 255);
622}
623
Austin Kinross62815bf2015-01-15 16:32:36 -0800624// This test ensures that the level-zero workaround for TextureCubes (on D3D11 Feature Level 9_3)
625// works as expected. It tests enabling/disabling mipmaps, generating mipmaps, and rendering to level zero.
Austin Kinrosseea095e2015-01-23 14:06:50 -0800626TYPED_TEST(MipmapTest, TextureCubeGeneralLevelZero)
Austin Kinross62815bf2015-01-15 16:32:36 -0800627{
628 GLfloat vertexLocations[] =
629 {
630 -1.0f, 1.0f, 0.0f,
631 -1.0f, -1.0f, 0.0f,
632 1.0f, 1.0f, 0.0f,
633 1.0f, -1.0f, 0.0f,
634 };
635
636 // Set up the viewport, program, attributes, sampler and texture for the cube
637 glBindFramebuffer(GL_FRAMEBUFFER, 0);
638 glViewport(0, 0, getWindowWidth(), getWindowHeight());
639 glUseProgram(mCubeProgram);
640 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertexLocations);
641 glEnableVertexAttribArray(0);
642 glUniform1i(0, 0);
643 glActiveTexture(GL_TEXTURE0);
644 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
645
646 // Draw. Since the negative-Y face's is blue, this should be blue.
647 glClear(GL_COLOR_BUFFER_BIT);
648 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
649 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
650
651 // Generate mipmaps, and render. This should be blue.
652 glClear(GL_COLOR_BUFFER_BIT);
653 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
654 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
655 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
656 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
657 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
658
659 // Draw using a smaller viewport (to force a lower LOD of the texture). This should still be blue.
660 glClear(GL_COLOR_BUFFER_BIT);
661 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
662 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
663 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
664
665 // Now clear the negative-Y face of the cube to red.
Austin Kinross62815bf2015-01-15 16:32:36 -0800666 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
667 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mOffscreenTextureCube, 0);
668 ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
669 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
670 glClear(GL_COLOR_BUFFER_BIT);
671
672 // Switch back to the default framebuffer
673 glBindFramebuffer(GL_FRAMEBUFFER, 0);
674 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
675
676 // Draw using a full-size viewport. This should be red.
677 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
678 glClear(GL_COLOR_BUFFER_BIT);
679 glViewport(0, 0, getWindowWidth(), getWindowHeight());
680 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
681 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
682
683 // Draw using a quarter-size viewport, to force a lower LOD. This should be *BLUE*, since we only cleared level zero
684 // of the negative-Y face to red, and left its mipmaps blue.
685 glClear(GL_COLOR_BUFFER_BIT);
686 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
687 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
688 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
689
690 // Disable mipmaps again, and draw a to a quarter-size viewport.
691 // Since this should use level zero of the texture, this should be *RED*.
692 glClear(GL_COLOR_BUFFER_BIT);
693 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
694 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
695 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
696 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
697}
698
699// This test ensures that rendering to level-zero of a TextureCube works as expected.
Austin Kinrosseea095e2015-01-23 14:06:50 -0800700TYPED_TEST(MipmapTest, TextureCubeRenderToLevelZero)
Austin Kinross62815bf2015-01-15 16:32:36 -0800701{
702 GLfloat vertexLocations[] =
703 {
704 -1.0f, 1.0f, 0.0f,
705 -1.0f, -1.0f, 0.0f,
706 1.0f, 1.0f, 0.0f,
707 1.0f, -1.0f, 0.0f,
708 };
709
710 // Set up the viewport, program, attributes, sampler and texture for the cube
711 glBindFramebuffer(GL_FRAMEBUFFER, 0);
712 glViewport(0, 0, getWindowWidth(), getWindowHeight());
713 glUseProgram(mCubeProgram);
714 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertexLocations);
715 glEnableVertexAttribArray(0);
716 glUniform1i(0, 0);
717 glActiveTexture(GL_TEXTURE0);
718 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
719
720 // Draw. Since the negative-Y face's is blue, this should be blue.
721 glClear(GL_COLOR_BUFFER_BIT);
722 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
723 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
724
725 // Now clear the negative-Y face of the cube to red.
Austin Kinross62815bf2015-01-15 16:32:36 -0800726 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
727 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mOffscreenTextureCube, 0);
728 ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
729 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
730 glClear(GL_COLOR_BUFFER_BIT);
731
732 // Switch back to the default framebuffer
733 glBindFramebuffer(GL_FRAMEBUFFER, 0);
734 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
735
736 // Draw using a full-size viewport. This should be red.
737 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
738 glClear(GL_COLOR_BUFFER_BIT);
739 glViewport(0, 0, getWindowWidth(), getWindowHeight());
740 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
741 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
742
743 // Draw a to a quarter-size viewport. This should also be red.
744 glClear(GL_COLOR_BUFFER_BIT);
745 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
746 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
747 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
748}
749
Austin Kinross215b37a2014-12-22 12:56:07 -0800750// Creates a mipmapped 2D array texture with three layers, and calls ANGLE's GenerateMipmap.
751// Then tests if the mipmaps are rendered correctly for all three layers.
Austin Kinrosseea095e2015-01-23 14:06:50 -0800752TYPED_TEST(MipmapTestES3, MipmapsForTextureArray)
Austin Kinross215b37a2014-12-22 12:56:07 -0800753{
754 int px = getWindowWidth() / 2;
755 int py = getWindowHeight() / 2;
756
757 glActiveTexture(GL_TEXTURE0);
758 glBindTexture(GL_TEXTURE_2D_ARRAY, mTextureArray);
759
760 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 5, GL_RGBA8, 16, 16, 3);
761
762 // Fill the first layer with red
763 std::vector<GLubyte> pixels(4 * 16 * 16);
764 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
765 {
766 pixels[pixelId * 4 + 0] = 255;
767 pixels[pixelId * 4 + 1] = 0;
768 pixels[pixelId * 4 + 2] = 0;
769 pixels[pixelId * 4 + 3] = 255;
770 }
771
772 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
773
774 // Fill the second layer with green
775 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
776 {
777 pixels[pixelId * 4 + 0] = 0;
778 pixels[pixelId * 4 + 1] = 255;
779 pixels[pixelId * 4 + 2] = 0;
780 pixels[pixelId * 4 + 3] = 255;
781 }
782
783 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
784
785 // Fill the third layer with blue
786 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
787 {
788 pixels[pixelId * 4 + 0] = 0;
789 pixels[pixelId * 4 + 1] = 0;
790 pixels[pixelId * 4 + 2] = 255;
791 pixels[pixelId * 4 + 3] = 255;
792 }
793
794 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
795
796 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
797 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
798
799 EXPECT_GL_NO_ERROR();
800
801 glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
802
803 EXPECT_GL_NO_ERROR();
804
805 glUseProgram(mArrayProgram);
806 glUniform1i(mTextureArrayUniformLocation, 0);
807
808 EXPECT_GL_NO_ERROR();
809
810 // Draw the first slice
811 glUseProgram(mArrayProgram);
812 glUniform1i(mTextureArraySliceUniformLocation, 0);
813 drawQuad(mArrayProgram, "position", 0.5f);
814 EXPECT_GL_NO_ERROR();
815 EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
816
817 // Draw the second slice
818 glUseProgram(mArrayProgram);
819 glUniform1i(mTextureArraySliceUniformLocation, 1);
820 drawQuad(mArrayProgram, "position", 0.5f);
821 EXPECT_GL_NO_ERROR();
822 EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
823
824 // Draw the third slice
825 glUseProgram(mArrayProgram);
826 glUniform1i(mTextureArraySliceUniformLocation, 2);
827 drawQuad(mArrayProgram, "position", 0.5f);
828 EXPECT_GL_NO_ERROR();
829 EXPECT_PIXEL_EQ(px, py, 0, 0, 255, 255);
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000830}
831
832// Creates a mipmapped 3D texture with two layers, and calls ANGLE's GenerateMipmap.
833// Then tests if the mipmaps are rendered correctly for all two layers.
834TYPED_TEST(MipmapTestES3, MipmapsForTexture3D)
835{
836 int px = getWindowWidth() / 2;
837 int py = getWindowHeight() / 2;
838
839 glActiveTexture(GL_TEXTURE0);
840 glBindTexture(GL_TEXTURE_3D, mTexture3D);
841
842 glTexStorage3D(GL_TEXTURE_3D, 5, GL_RGBA8, 16, 16, 2);
843
844 // Fill the first layer with red
845 std::vector<GLubyte> pixels(4 * 16 * 16);
846 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
847 {
848 pixels[pixelId * 4 + 0] = 255;
849 pixels[pixelId * 4 + 1] = 0;
850 pixels[pixelId * 4 + 2] = 0;
851 pixels[pixelId * 4 + 3] = 255;
852 }
853
854 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
855
856 // Fill the second layer with green
857 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
858 {
859 pixels[pixelId * 4 + 0] = 0;
860 pixels[pixelId * 4 + 1] = 255;
861 pixels[pixelId * 4 + 2] = 0;
862 pixels[pixelId * 4 + 3] = 255;
863 }
864
865 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 1, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
866
867 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
868 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
869
870 EXPECT_GL_NO_ERROR();
871
872 glGenerateMipmap(GL_TEXTURE_3D);
873
874 EXPECT_GL_NO_ERROR();
875
876 glUseProgram(m3DProgram);
877 glUniform1i(mTexture3DUniformLocation, 0);
878
879 EXPECT_GL_NO_ERROR();
880
881 // Mipmap level 0
882 // Draw the first slice
883 glUseProgram(m3DProgram);
884 glUniform1f(mTexture3DLODUniformLocation, 0.);
885 glUniform1f(mTexture3DSliceUniformLocation, 0.25f);
886 drawQuad(m3DProgram, "position", 0.5f);
887 EXPECT_GL_NO_ERROR();
888 EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
889
890 // Draw the second slice
891 glUseProgram(m3DProgram);
892 glUniform1f(mTexture3DSliceUniformLocation, 0.75f);
893 drawQuad(m3DProgram, "position", 0.5f);
894 EXPECT_GL_NO_ERROR();
895 EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
896
897 // Mipmap level 1
898 // The second mipmap should only have one slice.
899
900 glUseProgram(m3DProgram);
901 glUniform1f(mTexture3DLODUniformLocation, 1.);
902 drawQuad(m3DProgram, "position", 0.5f);
903 EXPECT_GL_NO_ERROR();
904 EXPECT_PIXEL_EQ(px, py, 127, 127, 0, 255);
905
906 glUseProgram(m3DProgram);
907 glUniform1f(mTexture3DSliceUniformLocation, 0.75f);
908 drawQuad(m3DProgram, "position", 0.5f);
909 EXPECT_GL_NO_ERROR();
910 EXPECT_PIXEL_EQ(px, py, 127, 127, 0, 255);
911}