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