1 //
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
7 #include "test_utils/ANGLETest.h"
8
9 using namespace angle;
10
11 class FramebufferRenderMipmapTest : public ANGLETest
12 {
13 protected:
FramebufferRenderMipmapTest()14 FramebufferRenderMipmapTest()
15 {
16 setWindowWidth(256);
17 setWindowHeight(256);
18 setConfigRedBits(8);
19 setConfigGreenBits(8);
20 setConfigBlueBits(8);
21 setConfigAlphaBits(8);
22 }
23
SetUp()24 virtual void SetUp()
25 {
26 ANGLETest::SetUp();
27
28 const std::string vsSource = SHADER_SOURCE
29 (
30 attribute highp vec4 position;
31 void main(void)
32 {
33 gl_Position = position;
34 }
35 );
36
37 const std::string fsSource = SHADER_SOURCE
38 (
39 uniform highp vec4 color;
40 void main(void)
41 {
42 gl_FragColor = color;
43 }
44 );
45
46 mProgram = CompileProgram(vsSource, fsSource);
47 if (mProgram == 0)
48 {
49 FAIL() << "shader compilation failed.";
50 }
51
52 mColorLocation = glGetUniformLocation(mProgram, "color");
53
54 glUseProgram(mProgram);
55
56 glClearColor(0, 0, 0, 0);
57 glClearDepthf(0.0);
58 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
59
60 glEnable(GL_BLEND);
61 glDisable(GL_DEPTH_TEST);
62
63 ASSERT_GL_NO_ERROR();
64 }
65
TearDown()66 virtual void TearDown()
67 {
68 glDeleteProgram(mProgram);
69
70 ANGLETest::TearDown();
71 }
72
73 GLuint mProgram;
74 GLint mColorLocation;
75 };
76
77 // Validate that if we are in ES3 or GL_OES_fbo_render_mipmap exists, there are no validation errors
78 // when using a non-zero level in glFramebufferTexture2D.
TEST_P(FramebufferRenderMipmapTest,Validation)79 TEST_P(FramebufferRenderMipmapTest, Validation)
80 {
81 bool renderToMipmapSupported =
82 extensionEnabled("GL_OES_fbo_render_mipmap") || getClientMajorVersion() > 2;
83
84 GLuint tex = 0;
85 glGenTextures(1, &tex);
86 glBindTexture(GL_TEXTURE_2D, tex);
87
88 const GLint levels = 5;
89 for (GLint i = 0; i < levels; i++)
90 {
91 GLsizei size = 1 << ((levels - 1) - i);
92 glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
93 }
94
95 EXPECT_GL_NO_ERROR();
96
97 GLuint fbo = 0;
98 glGenFramebuffers(1, &fbo);
99 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
100 EXPECT_GL_NO_ERROR();
101
102 for (GLint i = 0; i < levels; i++)
103 {
104 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, i);
105
106 if (i > 0 && !renderToMipmapSupported)
107 {
108 EXPECT_GL_ERROR(GL_INVALID_VALUE);
109 }
110 else
111 {
112 EXPECT_GL_NO_ERROR();
113 EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GLenum(GL_FRAMEBUFFER_COMPLETE));
114 }
115 }
116
117 glDeleteFramebuffers(1, &fbo);
118 glDeleteTextures(1, &tex);
119 }
120
121 // Render to various levels of a texture and check that they have the correct color data via ReadPixels
TEST_P(FramebufferRenderMipmapTest,RenderToMipmap)122 TEST_P(FramebufferRenderMipmapTest, RenderToMipmap)
123 {
124 // TODO(geofflang): Figure out why this is broken on Intel OpenGL
125 if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
126 {
127 std::cout << "Test skipped on Intel OpenGL." << std::endl;
128 return;
129 }
130
131 bool renderToMipmapSupported =
132 extensionEnabled("GL_OES_fbo_render_mipmap") || getClientMajorVersion() > 2;
133 if (!renderToMipmapSupported)
134 {
135 std::cout << "Test skipped because GL_OES_fbo_render_mipmap or ES3 is not available." << std::endl;
136 return;
137 }
138
139 const GLfloat levelColors[] =
140 {
141 1.0f, 0.0f, 0.0f, 1.0f,
142 0.0f, 1.0f, 0.0f, 1.0f,
143 0.0f, 0.0f, 1.0f, 1.0f,
144 1.0f, 1.0f, 0.0f, 1.0f,
145 1.0f, 0.0f, 1.0f, 1.0f,
146 0.0f, 1.0f, 1.0f, 1.0f,
147 };
148 const GLint testLevels = static_cast<GLint>(ArraySize(levelColors) / 4);
149
150 GLuint tex = 0;
151 glGenTextures(1, &tex);
152 glBindTexture(GL_TEXTURE_2D, tex);
153
154 for (GLint i = 0; i < testLevels; i++)
155 {
156 GLsizei size = 1 << ((testLevels - 1) - i);
157 glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
158 }
159
160 EXPECT_GL_NO_ERROR();
161
162 GLuint fbo = 0;
163 glGenFramebuffers(1, &fbo);
164 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
165 EXPECT_GL_NO_ERROR();
166
167 // Render to the levels of the texture with different colors
168 for (GLint i = 0; i < testLevels; i++)
169 {
170 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, i);
171 EXPECT_GL_NO_ERROR();
172
173 glUseProgram(mProgram);
174 glUniform4fv(mColorLocation, 1, levelColors + (i * 4));
175
176 drawQuad(mProgram, "position", 0.5f);
177 EXPECT_GL_NO_ERROR();
178 }
179
180 // Test that the levels of the texture are correct
181 for (GLint i = 0; i < testLevels; i++)
182 {
183 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, i);
184 EXPECT_GL_NO_ERROR();
185
186 const GLfloat *color = levelColors + (i * 4);
187 EXPECT_PIXEL_EQ(0, 0, color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255);
188 }
189
190 glDeleteFramebuffers(1, &fbo);
191 glDeleteTextures(1, &tex);
192
193 EXPECT_GL_NO_ERROR();
194 }
195
196 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
197 ANGLE_INSTANTIATE_TEST(FramebufferRenderMipmapTest,
198 ES2_D3D9(),
199 ES2_D3D11(),
200 ES3_D3D11(),
201 ES2_OPENGL(),
202 ES3_OPENGL(),
203 ES2_OPENGLES(),
204 ES3_OPENGLES());
205