blob: b287f2cf1306beedfea3b6c89f033b9dcdff9cae [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();
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000290
291 glGenTextures(1, &mTexture3D);
292
293 ASSERT_GL_NO_ERROR();
294
295 const std::string fragmentShaderSource3D = SHADER_SOURCE
296 ( #version 300 es\n
297 precision highp float;
298 uniform sampler3D tex;
299 uniform float slice;
300 uniform float lod;
301 in vec2 texcoord;
302 out vec4 out_FragColor;
303
304 void main()
305 {
306 out_FragColor = textureLod(tex, vec3(texcoord, slice), lod);
307 }
308 );
309
310 m3DProgram = CompileProgram(vertexShaderSource, fragmentShaderSource3D);
311 if (m3DProgram == 0)
312 {
313 FAIL() << "shader compilation failed.";
314 }
315
316 mTexture3DUniformLocation = glGetUniformLocation(m3DProgram, "tex");
317 ASSERT_NE(-1, mTexture3DUniformLocation);
318
319 mTexture3DScaleUniformLocation = glGetUniformLocation(m3DProgram, "textureScale");
320 ASSERT_NE(-1, mTexture3DScaleUniformLocation);
321
322 mTexture3DSliceUniformLocation = glGetUniformLocation(m3DProgram, "slice");
323 ASSERT_NE(-1, mTexture3DSliceUniformLocation);
324
325 mTexture3DLODUniformLocation = glGetUniformLocation(m3DProgram, "lod");
326 ASSERT_NE(-1, mTexture3DLODUniformLocation);
327
328 glUseProgram(m3DProgram);
329 glUniform2f(mTexture3DScaleUniformLocation, 1.0f, 1.0f);
330 glUniform1f(mTexture3DLODUniformLocation, 0);
331 glUseProgram(0);
332 ASSERT_GL_NO_ERROR();
Austin Kinross215b37a2014-12-22 12:56:07 -0800333 }
334
335 virtual void TearDown()
336 {
337 glDeleteTextures(1, &mTextureArray);
338 glDeleteProgram(mArrayProgram);
339
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000340 glDeleteTextures(1, &mTexture3D);
341 glDeleteProgram(m3DProgram);
342
Austin Kinross215b37a2014-12-22 12:56:07 -0800343 ANGLETest::TearDown();
344 }
345
346 GLuint mTextureArray;
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000347 GLuint mTexture3D;
Austin Kinross215b37a2014-12-22 12:56:07 -0800348
349 GLuint mArrayProgram;
350 GLint mTextureArrayUniformLocation;
351 GLint mTextureArrayScaleUniformLocation;
352 GLint mTextureArraySliceUniformLocation;
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000353
354 GLuint m3DProgram;
355 GLint mTexture3DUniformLocation;
356 GLint mTexture3DScaleUniformLocation;
357 GLint mTexture3DSliceUniformLocation;
358 GLint mTexture3DLODUniformLocation;
Austin Kinross215b37a2014-12-22 12:56:07 -0800359};
360
361// 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.
362// This ensures that renderers using the zero LOD workaround (e.g. D3D11 FL9_3) correctly pass init data to the mipmapped texture,
363// even if the the zero-LOD texture is currently in use.
Austin Kinross276171b2015-01-15 13:16:18 -0800364TYPED_TEST(MipmapTest, DISABLED_ThreeLevelsInitData)
Austin Kinross215b37a2014-12-22 12:56:07 -0800365{
366 // Pass in level zero init data.
Austin Kinross62815bf2015-01-15 16:32:36 -0800367 glBindTexture(GL_TEXTURE_2D, mOffscreenTexture2D);
Austin Kinross215b37a2014-12-22 12:56:07 -0800368 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
369 ASSERT_GL_NO_ERROR();
370
371 // Disable mips.
372 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
373
374 // Draw a full-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800375 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800376 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
377
378 // Draw a half-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800379 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800380 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
381
382 // Draw a quarter-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800383 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800384 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
385
386 // Complete the texture by initializing the remaining levels.
387 int n = 1;
388 while (getWindowWidth() / pow(2, n) >= 1)
389 {
390 glTexImage2D(GL_TEXTURE_2D, n, GL_RGB, getWindowWidth() / pow(2, n), getWindowWidth() / pow(2, n), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
391 ASSERT_GL_NO_ERROR();
392 n+=1;
393 }
394
395 // Pass in level one init data.
396 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelOneInitData);
397 ASSERT_GL_NO_ERROR();
398
399 // Draw a full-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800400 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800401 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
402
403 // 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 -0800404 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800405 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
406
407 // Enable mipmaps.
408 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
409
410 // Draw a half-sized quad, and check it's green.
Austin Kinross62815bf2015-01-15 16:32:36 -0800411 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800412 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
413
414 // 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 -0800415 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800416 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 0, 255);
417
418 // Pass in level two init data.
419 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, getWindowWidth() / 4, getWindowHeight() / 4, 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelTwoInitData);
420 ASSERT_GL_NO_ERROR();
421
422 // Draw a full-sized quad, and check it's blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800423 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800424 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
425
426 // Draw a half-sized quad, and check it's green.
Austin Kinross62815bf2015-01-15 16:32:36 -0800427 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800428 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
429
430 // Draw a quarter-sized quad, and check it's red.
Austin Kinross62815bf2015-01-15 16:32:36 -0800431 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800432 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 0, 0, 255);
433
434 // Now disable mipmaps again, and render multiple sized quads. They should all be blue, since level 0 is blue.
435 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Austin Kinross62815bf2015-01-15 16:32:36 -0800436 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800437 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800438 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800439 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800440 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800441 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
442
443 // Now reset level 0 to white, keeping mipmaps disabled. Then, render various sized quads. They should be white.
444 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroWhiteInitData);
445 ASSERT_GL_NO_ERROR();
446
Austin Kinross62815bf2015-01-15 16:32:36 -0800447 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800448 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800449 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800450 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 255, 255, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800451 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800452 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 255, 255, 255);
453
454 // Then enable mipmaps again. The quads should be white, green, red respectively.
455 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
456
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, 255, 255, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800459 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800460 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
Austin Kinross62815bf2015-01-15 16:32:36 -0800461 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800462 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 0, 0, 255);
463}
464
465// This test generates (and uses) mipmaps on a texture using init data. D3D11 will use a non-renderable TextureStorage for this.
466// The test then disables mips, renders to level zero of the texture, and reenables mips before using the texture again.
467// To do this, D3D11 has to convert the TextureStorage into a renderable one.
468// This test ensures that the conversion works correctly.
469// 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 -0500470TYPED_TEST(MipmapTest, DISABLED_GenerateMipmapFromInitDataThenRender)
Austin Kinross215b37a2014-12-22 12:56:07 -0800471{
472 // Pass in initial data so the texture is blue.
473 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
474
475 // Then generate the mips.
476 glGenerateMipmap(GL_TEXTURE_2D);
477 ASSERT_GL_NO_ERROR();
478
479 // Enable mipmaps.
480 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
481
482 // Now draw the texture to various different sized areas.
Austin Kinross62815bf2015-01-15 16:32:36 -0800483 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800484 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
485
486 // Use mip level 1
Austin Kinross62815bf2015-01-15 16:32:36 -0800487 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800488 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
489
490 // Use mip level 2
Austin Kinross62815bf2015-01-15 16:32:36 -0800491 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800492 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
493
494 ASSERT_GL_NO_ERROR();
495
496 // Disable mips. Render a quad using the texture and ensure it's blue.
497 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Austin Kinross62815bf2015-01-15 16:32:36 -0800498 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800499 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
500
501 // Clear level 0 of the texture.
502 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
503 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
504 glClear(GL_COLOR_BUFFER_BIT);
505
506 // Reenable mips, and try rendering different-sized quads.
507 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
508
509 // Level 0 is now red, so this should render red.
Austin Kinross62815bf2015-01-15 16:32:36 -0800510 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800511 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
512
513 // Use mip level 1, blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800514 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800515 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
516
517 // Use mip level 2, blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800518 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800519 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
520}
521
522// This test ensures that mips are correctly generated from a rendered image.
523// In particular, on D3D11 Feature Level 9_3, the clear call will be performed on the zero-level texture, rather than the mipped one.
524// 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 -0500525TYPED_TEST(MipmapTest, DISABLED_GenerateMipmapFromRenderedImage)
Austin Kinross215b37a2014-12-22 12:56:07 -0800526{
527 // Bind the offscreen framebuffer/texture.
528 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
529
530 // Clear the texture to blue.
531 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
532 glClear(GL_COLOR_BUFFER_BIT);
533
534 // Then generate the mips
535 glGenerateMipmap(GL_TEXTURE_2D);
536 ASSERT_GL_NO_ERROR();
537
538 // Enable mips.
539 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
540
541 // Now draw the texture to various different sized areas.
Austin Kinross62815bf2015-01-15 16:32:36 -0800542 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800543 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
544
545 // Use mip level 1
Austin Kinross62815bf2015-01-15 16:32:36 -0800546 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
Austin Kinross215b37a2014-12-22 12:56:07 -0800547 EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
548
549 // Use mip level 2
Austin Kinross62815bf2015-01-15 16:32:36 -0800550 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800551 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
552}
553
554// Test to ensure that rendering to a mipmapped texture works, regardless of whether mipmaps are enabled or not.
555// TODO: This test hits a texture rebind bug in the D3D11 renderer. Fix this.
Geoff Lang3b2f9f62015-01-23 16:09:06 -0500556TYPED_TEST(MipmapTest, DISABLED_RenderOntoLevelZeroAfterGenerateMipmap)
Austin Kinross215b37a2014-12-22 12:56:07 -0800557{
558 // Bind the offscreen texture/framebuffer.
559 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
560
561 // Clear the texture to blue.
562 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
563 glClear(GL_COLOR_BUFFER_BIT);
564
565 // From now on, default clear color is black.
566 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
567
568 // Now, draw the texture to a quad that's the same size as the texture. This draws to the default framebuffer.
569 // The quad should be blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800570 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800571 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
572
573 // Now go back to the texture, and generate mips on it.
574 glGenerateMipmap(GL_TEXTURE_2D);
575 ASSERT_GL_NO_ERROR();
576
577 // Now try rendering the textured quad again. Note: we've not told GL to use the generated mips.
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 tell GL to use the generated mips.
583 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
584 EXPECT_EQ(glGetError(), GL_NONE);
585
586 // Now render the textured quad again. It should be still be blue.
Austin Kinross62815bf2015-01-15 16:32:36 -0800587 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800588 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
589
590 // 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 -0800591 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800592 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
593
594 // Now clear the texture to green. This just clears the top level. The lower mips should remain blue.
595 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
596 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
597 glClear(GL_COLOR_BUFFER_BIT);
598
599 // From now on, default clear color is black.
600 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
601
602 // 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 -0800603 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800604 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 255, 0, 255);
605
606 // Render a small textured quad. This forces minification, so should render blue (the color of levels 1+).
Austin Kinross62815bf2015-01-15 16:32:36 -0800607 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800608 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
609
610 // Disable mipmaps again
611 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
612 ASSERT_GL_NO_ERROR();
613
614 // 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 -0800615 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
Austin Kinross215b37a2014-12-22 12:56:07 -0800616 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 255, 0, 255);
617
618 // 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 -0800619 ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
Austin Kinross215b37a2014-12-22 12:56:07 -0800620 EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 255, 0, 255);
621}
622
Austin Kinross62815bf2015-01-15 16:32:36 -0800623// This test ensures that the level-zero workaround for TextureCubes (on D3D11 Feature Level 9_3)
624// works as expected. It tests enabling/disabling mipmaps, generating mipmaps, and rendering to level zero.
Geoff Lang3b2f9f62015-01-23 16:09:06 -0500625TYPED_TEST(MipmapTest, DISABLED_TextureCubeGeneralLevelZero)
Austin Kinross62815bf2015-01-15 16:32:36 -0800626{
627 GLfloat vertexLocations[] =
628 {
629 -1.0f, 1.0f, 0.0f,
630 -1.0f, -1.0f, 0.0f,
631 1.0f, 1.0f, 0.0f,
632 1.0f, -1.0f, 0.0f,
633 };
634
635 // Set up the viewport, program, attributes, sampler and texture for the cube
636 glBindFramebuffer(GL_FRAMEBUFFER, 0);
637 glViewport(0, 0, getWindowWidth(), getWindowHeight());
638 glUseProgram(mCubeProgram);
639 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertexLocations);
640 glEnableVertexAttribArray(0);
641 glUniform1i(0, 0);
642 glActiveTexture(GL_TEXTURE0);
643 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
644
645 // Draw. Since the negative-Y face's is blue, this should be blue.
646 glClear(GL_COLOR_BUFFER_BIT);
647 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
648 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
649
650 // Generate mipmaps, and render. This should be blue.
651 glClear(GL_COLOR_BUFFER_BIT);
652 glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
653 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
654 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
655 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
656 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
657
658 // Draw using a smaller viewport (to force a lower LOD of the texture). This should still be blue.
659 glClear(GL_COLOR_BUFFER_BIT);
660 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
661 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
662 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
663
664 // Now clear the negative-Y face of the cube to red.
665 GLuint mOffscreenFramebuffer;
666 glGenFramebuffers(0, &mOffscreenFramebuffer);
667 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
668 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mOffscreenTextureCube, 0);
669 ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
670 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
671 glClear(GL_COLOR_BUFFER_BIT);
672
673 // Switch back to the default framebuffer
674 glBindFramebuffer(GL_FRAMEBUFFER, 0);
675 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
676
677 // Draw using a full-size viewport. This should be red.
678 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
679 glClear(GL_COLOR_BUFFER_BIT);
680 glViewport(0, 0, getWindowWidth(), getWindowHeight());
681 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
682 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
683
684 // Draw using a quarter-size viewport, to force a lower LOD. This should be *BLUE*, since we only cleared level zero
685 // of the negative-Y face to red, and left its mipmaps blue.
686 glClear(GL_COLOR_BUFFER_BIT);
687 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
688 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
689 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
690
691 // Disable mipmaps again, and draw a to a quarter-size viewport.
692 // Since this should use level zero of the texture, this should be *RED*.
693 glClear(GL_COLOR_BUFFER_BIT);
694 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
695 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
696 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
697 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
698}
699
700// This test ensures that rendering to level-zero of a TextureCube works as expected.
Geoff Lang3b2f9f62015-01-23 16:09:06 -0500701TYPED_TEST(MipmapTest, DISABLED_TextureCubeRenderToLevelZero)
Austin Kinross62815bf2015-01-15 16:32:36 -0800702{
703 GLfloat vertexLocations[] =
704 {
705 -1.0f, 1.0f, 0.0f,
706 -1.0f, -1.0f, 0.0f,
707 1.0f, 1.0f, 0.0f,
708 1.0f, -1.0f, 0.0f,
709 };
710
711 // Set up the viewport, program, attributes, sampler and texture for the cube
712 glBindFramebuffer(GL_FRAMEBUFFER, 0);
713 glViewport(0, 0, getWindowWidth(), getWindowHeight());
714 glUseProgram(mCubeProgram);
715 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertexLocations);
716 glEnableVertexAttribArray(0);
717 glUniform1i(0, 0);
718 glActiveTexture(GL_TEXTURE0);
719 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
720
721 // Draw. Since the negative-Y face's is blue, this should be blue.
722 glClear(GL_COLOR_BUFFER_BIT);
723 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
724 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
725
726 // Now clear the negative-Y face of the cube to red.
727 GLuint mOffscreenFramebuffer;
728 glGenFramebuffers(0, &mOffscreenFramebuffer);
729 glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
730 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mOffscreenTextureCube, 0);
731 ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
732 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
733 glClear(GL_COLOR_BUFFER_BIT);
734
735 // Switch back to the default framebuffer
736 glBindFramebuffer(GL_FRAMEBUFFER, 0);
737 glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
738
739 // Draw using a full-size viewport. This should be red.
740 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
741 glClear(GL_COLOR_BUFFER_BIT);
742 glViewport(0, 0, getWindowWidth(), getWindowHeight());
743 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
744 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
745
746 // Draw a to a quarter-size viewport. This should also be red.
747 glClear(GL_COLOR_BUFFER_BIT);
748 glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
749 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
750 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
751}
752
Austin Kinross215b37a2014-12-22 12:56:07 -0800753// Creates a mipmapped 2D array texture with three layers, and calls ANGLE's GenerateMipmap.
754// Then tests if the mipmaps are rendered correctly for all three layers.
Geoff Lang3b2f9f62015-01-23 16:09:06 -0500755TYPED_TEST(MipmapTestES3, DISABLED_MipmapsForTextureArray)
Austin Kinross215b37a2014-12-22 12:56:07 -0800756{
757 int px = getWindowWidth() / 2;
758 int py = getWindowHeight() / 2;
759
760 glActiveTexture(GL_TEXTURE0);
761 glBindTexture(GL_TEXTURE_2D_ARRAY, mTextureArray);
762
763 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 5, GL_RGBA8, 16, 16, 3);
764
765 // Fill the first layer with red
766 std::vector<GLubyte> pixels(4 * 16 * 16);
767 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
768 {
769 pixels[pixelId * 4 + 0] = 255;
770 pixels[pixelId * 4 + 1] = 0;
771 pixels[pixelId * 4 + 2] = 0;
772 pixels[pixelId * 4 + 3] = 255;
773 }
774
775 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
776
777 // Fill the second layer with green
778 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
779 {
780 pixels[pixelId * 4 + 0] = 0;
781 pixels[pixelId * 4 + 1] = 255;
782 pixels[pixelId * 4 + 2] = 0;
783 pixels[pixelId * 4 + 3] = 255;
784 }
785
786 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
787
788 // Fill the third layer with blue
789 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
790 {
791 pixels[pixelId * 4 + 0] = 0;
792 pixels[pixelId * 4 + 1] = 0;
793 pixels[pixelId * 4 + 2] = 255;
794 pixels[pixelId * 4 + 3] = 255;
795 }
796
797 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
798
799 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
800 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
801
802 EXPECT_GL_NO_ERROR();
803
804 glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
805
806 EXPECT_GL_NO_ERROR();
807
808 glUseProgram(mArrayProgram);
809 glUniform1i(mTextureArrayUniformLocation, 0);
810
811 EXPECT_GL_NO_ERROR();
812
813 // Draw the first slice
814 glUseProgram(mArrayProgram);
815 glUniform1i(mTextureArraySliceUniformLocation, 0);
816 drawQuad(mArrayProgram, "position", 0.5f);
817 EXPECT_GL_NO_ERROR();
818 EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
819
820 // Draw the second slice
821 glUseProgram(mArrayProgram);
822 glUniform1i(mTextureArraySliceUniformLocation, 1);
823 drawQuad(mArrayProgram, "position", 0.5f);
824 EXPECT_GL_NO_ERROR();
825 EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
826
827 // Draw the third slice
828 glUseProgram(mArrayProgram);
829 glUniform1i(mTextureArraySliceUniformLocation, 2);
830 drawQuad(mArrayProgram, "position", 0.5f);
831 EXPECT_GL_NO_ERROR();
832 EXPECT_PIXEL_EQ(px, py, 0, 0, 255, 255);
Gregoire Payen de La Garanderie32334af2015-01-30 11:38:21 +0000833}
834
835// Creates a mipmapped 3D texture with two layers, and calls ANGLE's GenerateMipmap.
836// Then tests if the mipmaps are rendered correctly for all two layers.
837TYPED_TEST(MipmapTestES3, MipmapsForTexture3D)
838{
839 int px = getWindowWidth() / 2;
840 int py = getWindowHeight() / 2;
841
842 glActiveTexture(GL_TEXTURE0);
843 glBindTexture(GL_TEXTURE_3D, mTexture3D);
844
845 glTexStorage3D(GL_TEXTURE_3D, 5, GL_RGBA8, 16, 16, 2);
846
847 // Fill the first layer with red
848 std::vector<GLubyte> pixels(4 * 16 * 16);
849 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
850 {
851 pixels[pixelId * 4 + 0] = 255;
852 pixels[pixelId * 4 + 1] = 0;
853 pixels[pixelId * 4 + 2] = 0;
854 pixels[pixelId * 4 + 3] = 255;
855 }
856
857 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
858
859 // Fill the second layer with green
860 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
861 {
862 pixels[pixelId * 4 + 0] = 0;
863 pixels[pixelId * 4 + 1] = 255;
864 pixels[pixelId * 4 + 2] = 0;
865 pixels[pixelId * 4 + 3] = 255;
866 }
867
868 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 1, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
869
870 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
871 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
872
873 EXPECT_GL_NO_ERROR();
874
875 glGenerateMipmap(GL_TEXTURE_3D);
876
877 EXPECT_GL_NO_ERROR();
878
879 glUseProgram(m3DProgram);
880 glUniform1i(mTexture3DUniformLocation, 0);
881
882 EXPECT_GL_NO_ERROR();
883
884 // Mipmap level 0
885 // Draw the first slice
886 glUseProgram(m3DProgram);
887 glUniform1f(mTexture3DLODUniformLocation, 0.);
888 glUniform1f(mTexture3DSliceUniformLocation, 0.25f);
889 drawQuad(m3DProgram, "position", 0.5f);
890 EXPECT_GL_NO_ERROR();
891 EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
892
893 // Draw the second slice
894 glUseProgram(m3DProgram);
895 glUniform1f(mTexture3DSliceUniformLocation, 0.75f);
896 drawQuad(m3DProgram, "position", 0.5f);
897 EXPECT_GL_NO_ERROR();
898 EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
899
900 // Mipmap level 1
901 // The second mipmap should only have one slice.
902
903 glUseProgram(m3DProgram);
904 glUniform1f(mTexture3DLODUniformLocation, 1.);
905 drawQuad(m3DProgram, "position", 0.5f);
906 EXPECT_GL_NO_ERROR();
907 EXPECT_PIXEL_EQ(px, py, 127, 127, 0, 255);
908
909 glUseProgram(m3DProgram);
910 glUniform1f(mTexture3DSliceUniformLocation, 0.75f);
911 drawQuad(m3DProgram, "position", 0.5f);
912 EXPECT_GL_NO_ERROR();
913 EXPECT_PIXEL_EQ(px, py, 127, 127, 0, 255);
914}