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