• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 MaxTextureSizeTest : public ANGLETest
12 {
13   protected:
MaxTextureSizeTest()14     MaxTextureSizeTest()
15     {
16         setWindowWidth(512);
17         setWindowHeight(512);
18         setConfigRedBits(8);
19         setConfigGreenBits(8);
20         setConfigBlueBits(8);
21         setConfigAlphaBits(8);
22     }
23 
testSetUp()24     void testSetUp() override
25     {
26         constexpr char kVS[] = R"(precision highp float;
27 attribute vec4 position;
28 varying vec2 texcoord;
29 
30 void main()
31 {
32     gl_Position = position;
33     texcoord = (position.xy * 0.5) + 0.5;
34 })";
35 
36         constexpr char kTextureFS[] = R"(precision highp float;
37 uniform sampler2D tex;
38 varying vec2 texcoord;
39 
40 void main()
41 {
42     gl_FragColor = texture2D(tex, texcoord);
43 })";
44 
45         constexpr char kBlueFS[] = R"(precision highp float;
46 void main()
47 {
48     gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
49 })";
50 
51         mTextureProgram = CompileProgram(kVS, kTextureFS);
52         mBlueProgram    = CompileProgram(kVS, kBlueFS);
53         if (mTextureProgram == 0 || mBlueProgram == 0)
54         {
55             FAIL() << "shader compilation failed.";
56         }
57 
58         mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
59 
60         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTexture2DSize);
61         glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxTextureCubeSize);
62         glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
63 
64         ASSERT_GL_NO_ERROR();
65     }
66 
testTearDown()67     void testTearDown() override
68     {
69         glDeleteProgram(mTextureProgram);
70         glDeleteProgram(mBlueProgram);
71     }
72 
73     GLuint mTextureProgram;
74     GLint mTextureUniformLocation;
75 
76     GLuint mBlueProgram;
77 
78     GLint mMaxTexture2DSize;
79     GLint mMaxTextureCubeSize;
80     GLint mMaxRenderbufferSize;
81 };
82 
TEST_P(MaxTextureSizeTest,SpecificationTexImage)83 TEST_P(MaxTextureSizeTest, SpecificationTexImage)
84 {
85     GLuint tex;
86     glGenTextures(1, &tex);
87     glBindTexture(GL_TEXTURE_2D, tex);
88 
89     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
90     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
91     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
92     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
93 
94     GLsizei textureWidth  = mMaxTexture2DSize;
95     GLsizei textureHeight = 64;
96 
97     std::vector<GLubyte> data(textureWidth * textureHeight * 4);
98     for (int y = 0; y < textureHeight; y++)
99     {
100         for (int x = 0; x < textureWidth; x++)
101         {
102             GLubyte *pixel = &data[0] + ((y * textureWidth + x) * 4);
103 
104             // Draw a gradient, red in direction, green in y direction
105             pixel[0] = static_cast<GLubyte>((float(x) / textureWidth) * 255);
106             pixel[1] = static_cast<GLubyte>((float(y) / textureHeight) * 255);
107             pixel[2] = 0;
108             pixel[3] = 255;
109         }
110     }
111 
112     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA,
113                  GL_UNSIGNED_BYTE, &data[0]);
114     EXPECT_GL_NO_ERROR();
115 
116     glUseProgram(mTextureProgram);
117     glUniform1i(mTextureUniformLocation, 0);
118 
119     drawQuad(mTextureProgram, "position", 0.5f);
120 
121     std::vector<GLubyte> pixels(getWindowWidth() * getWindowHeight() * 4);
122     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
123 
124     for (int y = 1; y < getWindowHeight(); y++)
125     {
126         for (int x = 1; x < getWindowWidth(); x++)
127         {
128             const GLubyte *prevPixel = &pixels[0] + (((y - 1) * getWindowWidth() + (x - 1)) * 4);
129             const GLubyte *curPixel  = &pixels[0] + ((y * getWindowWidth() + x) * 4);
130 
131             EXPECT_GE(curPixel[0], prevPixel[0]);
132             EXPECT_GE(curPixel[1], prevPixel[1]);
133             EXPECT_EQ(curPixel[2], prevPixel[2]);
134             EXPECT_EQ(curPixel[3], prevPixel[3]);
135         }
136     }
137 }
138 
TEST_P(MaxTextureSizeTest,SpecificationTexStorage)139 TEST_P(MaxTextureSizeTest, SpecificationTexStorage)
140 {
141     if (getClientMajorVersion() < 3 && (!IsGLExtensionEnabled("GL_EXT_texture_storage") ||
142                                         !IsGLExtensionEnabled("GL_OES_rgb8_rgba8")))
143     {
144         return;
145     }
146 
147     GLuint tex;
148     glGenTextures(1, &tex);
149     glBindTexture(GL_TEXTURE_2D, tex);
150 
151     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
152     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
153     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
154     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
155 
156     GLsizei textureWidth  = 64;
157     GLsizei textureHeight = mMaxTexture2DSize;
158 
159     std::vector<GLubyte> data(textureWidth * textureHeight * 4);
160     for (int y = 0; y < textureHeight; y++)
161     {
162         for (int x = 0; x < textureWidth; x++)
163         {
164             GLubyte *pixel = &data[0] + ((y * textureWidth + x) * 4);
165 
166             // Draw a gradient, red in direction, green in y direction
167             pixel[0] = static_cast<GLubyte>((float(x) / textureWidth) * 255);
168             pixel[1] = static_cast<GLubyte>((float(y) / textureHeight) * 255);
169             pixel[2] = 0;
170             pixel[3] = 255;
171         }
172     }
173 
174     if (getClientMajorVersion() < 3)
175     {
176         glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, textureWidth, textureHeight);
177     }
178     else
179     {
180         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8_OES, textureWidth, textureHeight);
181     }
182     EXPECT_GL_NO_ERROR();
183 
184     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, textureWidth, textureHeight, GL_RGBA, GL_UNSIGNED_BYTE,
185                     &data[0]);
186     EXPECT_GL_NO_ERROR();
187 
188     glUseProgram(mTextureProgram);
189     glUniform1i(mTextureUniformLocation, 0);
190 
191     drawQuad(mTextureProgram, "position", 0.5f);
192 
193     std::vector<GLubyte> pixels(getWindowWidth() * getWindowHeight() * 4);
194     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
195 
196     for (int y = 1; y < getWindowHeight(); y++)
197     {
198         for (int x = 1; x < getWindowWidth(); x++)
199         {
200             const GLubyte *prevPixel = &pixels[0] + (((y - 1) * getWindowWidth() + (x - 1)) * 4);
201             const GLubyte *curPixel  = &pixels[0] + ((y * getWindowWidth() + x) * 4);
202 
203             EXPECT_GE(curPixel[0], prevPixel[0]);
204             EXPECT_GE(curPixel[1], prevPixel[1]);
205             EXPECT_EQ(curPixel[2], prevPixel[2]);
206             EXPECT_EQ(curPixel[3], prevPixel[3]);
207         }
208     }
209 }
210 
TEST_P(MaxTextureSizeTest,RenderToTexture)211 TEST_P(MaxTextureSizeTest, RenderToTexture)
212 {
213     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
214                        (!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit")));
215 
216     GLuint fbo       = 0;
217     GLuint textureId = 0;
218     // create a 1-level texture at maximum size
219     glGenTextures(1, &textureId);
220     glBindTexture(GL_TEXTURE_2D, textureId);
221 
222     GLsizei textureWidth  = 64;
223     GLsizei textureHeight = mMaxTexture2DSize;
224 
225     // texture setup code
226     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
227     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
228     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
229     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
230     glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, textureWidth, textureHeight, 0, GL_BGRA_EXT,
231                  GL_UNSIGNED_BYTE, nullptr);
232     EXPECT_GL_NO_ERROR();
233 
234     // create an FBO and attach the texture
235     glGenFramebuffers(1, &fbo);
236     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
237     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
238 
239     EXPECT_GL_NO_ERROR();
240     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
241 
242     const int frameCount = 64;
243     for (int i = 0; i < frameCount; i++)
244     {
245         // clear the screen
246         glBindFramebuffer(GL_FRAMEBUFFER, 0);
247 
248         GLubyte clearRed   = static_cast<GLubyte>((float(i) / frameCount) * 255);
249         GLubyte clearGreen = 255 - clearRed;
250         GLubyte clearBlue  = 0;
251 
252         glClearColor(clearRed / 255.0f, clearGreen / 255.0f, clearBlue / 255.0f, 1.0f);
253         glClear(GL_COLOR_BUFFER_BIT);
254 
255         // render blue into the texture
256         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
257         drawQuad(mBlueProgram, "position", 0.5f);
258 
259         // copy corner of texture to LL corner of window
260         glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, 0);
261         glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, fbo);
262         glBlitFramebufferANGLE(0, 0, textureWidth - 1, getWindowHeight() - 1, 0, 0,
263                                textureWidth - 1, getWindowHeight() - 1, GL_COLOR_BUFFER_BIT,
264                                GL_NEAREST);
265         glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, 0);
266         EXPECT_GL_NO_ERROR();
267 
268         EXPECT_PIXEL_EQ(textureWidth / 2, getWindowHeight() / 2, 0, 0, 255, 255);
269         EXPECT_PIXEL_EQ(textureWidth + 10, getWindowHeight() / 2, clearRed, clearGreen, clearBlue,
270                         255);
271 
272         swapBuffers();
273     }
274 
275     glBindFramebuffer(GL_FRAMEBUFFER, 0);
276     glBindTexture(GL_TEXTURE_2D, 0);
277 
278     glDeleteFramebuffers(1, &fbo);
279     glDeleteTextures(1, &textureId);
280 }
281 
282 // TODO(geofflang): Fix the dependence on glBlitFramebufferANGLE without checks and assuming the
283 // default framebuffer is BGRA to enable the GL and GLES backends. (http://anglebug.com/1289)
284 
285 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
286 // tests should be run against.
287 ANGLE_INSTANTIATE_TEST(MaxTextureSizeTest, ES2_D3D9(), ES2_D3D11(), ES2_VULKAN());
288