blob: 19f7fa8d1c37e9686328c53cb476e7c18b662dea [file] [log] [blame]
Jamie Madillfa05f602015-05-07 13:47:11 -04001//
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
Corentin Wallezd3970de2015-05-14 11:07:48 -04007#include "test_utils/ANGLETest.h"
Jamie Madillf67115c2014-04-22 13:14:05 -04008
Jamie Madillfa05f602015-05-07 13:47:11 -04009using namespace angle;
Austin Kinross18b931d2014-09-29 12:58:31 -070010
Jamie Madillfa05f602015-05-07 13:47:11 -040011namespace
12{
13
Jamie Madillf67115c2014-04-22 13:14:05 -040014class TextureTest : public ANGLETest
15{
Jamie Madillbc393df2015-01-29 13:46:07 -050016 protected:
Jamie Madillfa05f602015-05-07 13:47:11 -040017 TextureTest()
Jamie Madillf67115c2014-04-22 13:14:05 -040018 {
19 setWindowWidth(128);
20 setWindowHeight(128);
21 setConfigRedBits(8);
22 setConfigGreenBits(8);
23 setConfigBlueBits(8);
24 setConfigAlphaBits(8);
25 }
26
Jamie Madillfa05f602015-05-07 13:47:11 -040027 void SetUp() override
Jamie Madillf67115c2014-04-22 13:14:05 -040028 {
29 ANGLETest::SetUp();
Jamie Madilld4cfa572014-07-08 10:00:32 -040030 glGenTextures(1, &mTexture2D);
31 glGenTextures(1, &mTextureCube);
Jamie Madillf67115c2014-04-22 13:14:05 -040032
Jamie Madilld4cfa572014-07-08 10:00:32 -040033 glBindTexture(GL_TEXTURE_2D, mTexture2D);
Jamie Madillf67115c2014-04-22 13:14:05 -040034 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
35 EXPECT_GL_NO_ERROR();
36
Jamie Madilld4cfa572014-07-08 10:00:32 -040037 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
38 glTexStorage2DEXT(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 1, 1);
39 EXPECT_GL_NO_ERROR();
40
Jamie Madillf67115c2014-04-22 13:14:05 -040041 ASSERT_GL_NO_ERROR();
Geoff Langc41e42d2014-04-28 10:58:16 -040042
43 const std::string vertexShaderSource = SHADER_SOURCE
44 (
45 precision highp float;
46 attribute vec4 position;
47 varying vec2 texcoord;
48
Jamie Madill9aca0592014-10-06 16:26:59 -040049 uniform vec2 textureScale;
50
Geoff Langc41e42d2014-04-28 10:58:16 -040051 void main()
52 {
Jamie Madill9aca0592014-10-06 16:26:59 -040053 gl_Position = vec4(position.xy * textureScale, 0.0, 1.0);
Geoff Langc41e42d2014-04-28 10:58:16 -040054 texcoord = (position.xy * 0.5) + 0.5;
55 }
56 );
57
Jamie Madilld4cfa572014-07-08 10:00:32 -040058 const std::string fragmentShaderSource2D = SHADER_SOURCE
Geoff Langc41e42d2014-04-28 10:58:16 -040059 (
60 precision highp float;
61 uniform sampler2D tex;
62 varying vec2 texcoord;
63
64 void main()
65 {
66 gl_FragColor = texture2D(tex, texcoord);
67 }
68 );
69
Jamie Madilld4cfa572014-07-08 10:00:32 -040070 const std::string fragmentShaderSourceCube = SHADER_SOURCE
71 (
72 precision highp float;
73 uniform sampler2D tex2D;
74 uniform samplerCube texCube;
75 varying vec2 texcoord;
76
77 void main()
78 {
79 gl_FragColor = texture2D(tex2D, texcoord);
80 gl_FragColor += textureCube(texCube, vec3(texcoord, 0));
81 }
82 );
83
Jamie Madill5599c8f2014-08-26 13:16:39 -040084 m2DProgram = CompileProgram(vertexShaderSource, fragmentShaderSource2D);
85 mCubeProgram = CompileProgram(vertexShaderSource, fragmentShaderSourceCube);
Jamie Madilld4cfa572014-07-08 10:00:32 -040086 if (m2DProgram == 0 || mCubeProgram == 0)
Geoff Langc41e42d2014-04-28 10:58:16 -040087 {
88 FAIL() << "shader compilation failed.";
89 }
90
Jamie Madilld4cfa572014-07-08 10:00:32 -040091 mTexture2DUniformLocation = glGetUniformLocation(m2DProgram, "tex");
Jamie Madill9aca0592014-10-06 16:26:59 -040092 ASSERT_NE(-1, mTexture2DUniformLocation);
93
94 mTextureScaleUniformLocation = glGetUniformLocation(m2DProgram, "textureScale");
95 ASSERT_NE(-1, mTextureScaleUniformLocation);
96
97 glUseProgram(m2DProgram);
98 glUniform2f(mTextureScaleUniformLocation, 1.0f, 1.0f);
99 glUseProgram(0);
100 ASSERT_GL_NO_ERROR();
Jamie Madillf67115c2014-04-22 13:14:05 -0400101 }
102
Jamie Madillfa05f602015-05-07 13:47:11 -0400103 void TearDown() override
Jamie Madillf67115c2014-04-22 13:14:05 -0400104 {
Jamie Madilld4cfa572014-07-08 10:00:32 -0400105 glDeleteTextures(1, &mTexture2D);
106 glDeleteTextures(1, &mTextureCube);
107 glDeleteProgram(m2DProgram);
108 glDeleteProgram(mCubeProgram);
Jamie Madillf67115c2014-04-22 13:14:05 -0400109
110 ANGLETest::TearDown();
111 }
112
Jamie Madillbc393df2015-01-29 13:46:07 -0500113 // Tests CopyTexSubImage with floating point textures of various formats.
114 void testFloatCopySubImage(int sourceImageChannels, int destImageChannels)
115 {
Geoff Langbde666a2015-04-07 17:17:08 -0400116 // TODO(jmadill): Figure out why this is broken on Intel D3D11
117 if (isIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
118 {
119 std::cout << "Test skipped on Intel D3D11." << std::endl;
120 return;
121 }
122
Geoff Langfbfa47c2015-03-31 11:26:00 -0400123 if (getClientVersion() < 3)
124 {
125 if (!extensionEnabled("GL_OES_texture_float"))
126 {
127 std::cout << "Test skipped due to missing GL_OES_texture_float." << std::endl;
128 return;
129 }
130
131 if ((sourceImageChannels < 3 || destImageChannels < 3) && !extensionEnabled("GL_EXT_texture_rg"))
132 {
133 std::cout << "Test skipped due to missing GL_EXT_texture_rg." << std::endl;
134 return;
135 }
136 }
137
Jamie Madillbc393df2015-01-29 13:46:07 -0500138 GLfloat sourceImageData[4][16] =
139 {
140 { // R
141 1.0f,
142 0.0f,
143 0.0f,
144 1.0f
145 },
146 { // RG
147 1.0f, 0.0f,
148 0.0f, 1.0f,
149 0.0f, 0.0f,
150 1.0f, 1.0f
151 },
152 { // RGB
153 1.0f, 0.0f, 0.0f,
154 0.0f, 1.0f, 0.0f,
155 0.0f, 0.0f, 1.0f,
156 1.0f, 1.0f, 0.0f
157 },
158 { // RGBA
159 1.0f, 0.0f, 0.0f, 1.0f,
160 0.0f, 1.0f, 0.0f, 1.0f,
161 0.0f, 0.0f, 1.0f, 1.0f,
162 1.0f, 1.0f, 0.0f, 1.0f
163 },
164 };
165
166 GLenum imageFormats[] =
167 {
168 GL_R32F,
169 GL_RG32F,
170 GL_RGB32F,
171 GL_RGBA32F,
172 };
173
174 GLenum sourceUnsizedFormats[] =
175 {
176 GL_RED,
177 GL_RG,
178 GL_RGB,
179 GL_RGBA,
180 };
181
182 GLuint textures[2];
183
184 glGenTextures(2, textures);
185
186 GLfloat *imageData = sourceImageData[sourceImageChannels - 1];
187 GLenum sourceImageFormat = imageFormats[sourceImageChannels - 1];
188 GLenum sourceUnsizedFormat = sourceUnsizedFormats[sourceImageChannels - 1];
189 GLenum destImageFormat = imageFormats[destImageChannels - 1];
190
191 glBindTexture(GL_TEXTURE_2D, textures[0]);
192 glTexStorage2DEXT(GL_TEXTURE_2D, 1, sourceImageFormat, 2, 2);
193 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
194 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
195 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, sourceUnsizedFormat, GL_FLOAT, imageData);
196
hendrikwb27f79a2015-03-04 11:26:46 -0800197 if (sourceImageChannels < 3 && !extensionEnabled("GL_EXT_texture_rg"))
Jamie Madillbc393df2015-01-29 13:46:07 -0500198 {
199 // This is not supported
200 ASSERT_GL_ERROR(GL_INVALID_OPERATION);
201 }
202 else
203 {
204 ASSERT_GL_NO_ERROR();
205 }
206
207 GLuint fbo;
208 glGenFramebuffers(1, &fbo);
209 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
210 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
211
212 glBindTexture(GL_TEXTURE_2D, textures[1]);
213 glTexStorage2DEXT(GL_TEXTURE_2D, 1, destImageFormat, 2, 2);
214 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
215 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
216
217 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 2, 2);
218 ASSERT_GL_NO_ERROR();
219
220 glBindFramebuffer(GL_FRAMEBUFFER, 0);
221 drawQuad(m2DProgram, "position", 0.5f);
Jamie Madillbc393df2015-01-29 13:46:07 -0500222
223 int testImageChannels = std::min(sourceImageChannels, destImageChannels);
224
225 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
226 if (testImageChannels > 1)
227 {
228 EXPECT_PIXEL_EQ(getWindowHeight() - 1, 0, 0, 255, 0, 255);
229 EXPECT_PIXEL_EQ(getWindowHeight() - 1, getWindowWidth() - 1, 255, 255, 0, 255);
230 if (testImageChannels > 2)
231 {
232 EXPECT_PIXEL_EQ(0, getWindowWidth() - 1, 0, 0, 255, 255);
233 }
234 }
235
236 glDeleteFramebuffers(1, &fbo);
237 glDeleteTextures(2, textures);
238
239 ASSERT_GL_NO_ERROR();
240 }
241
Jamie Madilld4cfa572014-07-08 10:00:32 -0400242 GLuint mTexture2D;
243 GLuint mTextureCube;
Geoff Langc41e42d2014-04-28 10:58:16 -0400244
Jamie Madilld4cfa572014-07-08 10:00:32 -0400245 GLuint m2DProgram;
246 GLuint mCubeProgram;
247 GLint mTexture2DUniformLocation;
Jamie Madill9aca0592014-10-06 16:26:59 -0400248 GLint mTextureScaleUniformLocation;
Jamie Madillf67115c2014-04-22 13:14:05 -0400249};
250
Jamie Madillfa05f602015-05-07 13:47:11 -0400251TEST_P(TextureTest, NegativeAPISubImage)
Jamie Madillf67115c2014-04-22 13:14:05 -0400252{
Jamie Madilld4cfa572014-07-08 10:00:32 -0400253 glBindTexture(GL_TEXTURE_2D, mTexture2D);
Jamie Madillf67115c2014-04-22 13:14:05 -0400254 EXPECT_GL_ERROR(GL_NO_ERROR);
255
256 const GLubyte *pixels[20] = { 0 };
257 glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
258 EXPECT_GL_ERROR(GL_INVALID_VALUE);
259}
Geoff Langc41e42d2014-04-28 10:58:16 -0400260
Jamie Madillfa05f602015-05-07 13:47:11 -0400261TEST_P(TextureTest, ZeroSizedUploads)
Geoff Langc41e42d2014-04-28 10:58:16 -0400262{
Jamie Madilld4cfa572014-07-08 10:00:32 -0400263 glBindTexture(GL_TEXTURE_2D, mTexture2D);
Geoff Langc41e42d2014-04-28 10:58:16 -0400264 EXPECT_GL_ERROR(GL_NO_ERROR);
265
266 // Use the texture first to make sure it's in video memory
Jamie Madilld4cfa572014-07-08 10:00:32 -0400267 glUseProgram(m2DProgram);
268 glUniform1i(mTexture2DUniformLocation, 0);
269 drawQuad(m2DProgram, "position", 0.5f);
Geoff Langc41e42d2014-04-28 10:58:16 -0400270
271 const GLubyte *pixel[4] = { 0 };
272
273 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
274 EXPECT_GL_NO_ERROR();
275
276 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
277 EXPECT_GL_NO_ERROR();
278
279 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
280 EXPECT_GL_NO_ERROR();
281}
Jamie Madilld4cfa572014-07-08 10:00:32 -0400282
283// Test drawing with two texture types, to trigger an ANGLE bug in validation
Jamie Madillfa05f602015-05-07 13:47:11 -0400284TEST_P(TextureTest, CubeMapBug)
Jamie Madilld4cfa572014-07-08 10:00:32 -0400285{
286 glActiveTexture(GL_TEXTURE0);
287 glBindTexture(GL_TEXTURE_2D, mTexture2D);
288 glActiveTexture(GL_TEXTURE1);
289 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
290 EXPECT_GL_ERROR(GL_NO_ERROR);
291
292 glUseProgram(mCubeProgram);
293 GLint tex2DUniformLocation = glGetUniformLocation(mCubeProgram, "tex2D");
294 GLint texCubeUniformLocation = glGetUniformLocation(mCubeProgram, "texCube");
295 EXPECT_NE(-1, tex2DUniformLocation);
296 EXPECT_NE(-1, texCubeUniformLocation);
297 glUniform1i(tex2DUniformLocation, 0);
298 glUniform1i(texCubeUniformLocation, 1);
299 drawQuad(mCubeProgram, "position", 0.5f);
300 EXPECT_GL_NO_ERROR();
301}
Jamie Madill9aca0592014-10-06 16:26:59 -0400302
303// Copy of a test in conformance/textures/texture-mips, to test generate mipmaps
Jamie Madillfa05f602015-05-07 13:47:11 -0400304TEST_P(TextureTest, MipmapsTwice)
Jamie Madill9aca0592014-10-06 16:26:59 -0400305{
306 int px = getWindowWidth() / 2;
307 int py = getWindowHeight() / 2;
308
309 glActiveTexture(GL_TEXTURE0);
310 glBindTexture(GL_TEXTURE_2D, mTexture2D);
311
312 // Fill with red
313 std::vector<GLubyte> pixels(4 * 16 * 16);
314 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
315 {
316 pixels[pixelId * 4 + 0] = 255;
317 pixels[pixelId * 4 + 1] = 0;
318 pixels[pixelId * 4 + 2] = 0;
319 pixels[pixelId * 4 + 3] = 255;
320 }
321
322 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
323 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
324 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
325 glGenerateMipmap(GL_TEXTURE_2D);
326
327 glUseProgram(m2DProgram);
328 glUniform1i(mTexture2DUniformLocation, 0);
329 glUniform2f(mTextureScaleUniformLocation, 0.0625f, 0.0625f);
330 drawQuad(m2DProgram, "position", 0.5f);
331 EXPECT_GL_NO_ERROR();
332 EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
333
334 // Fill with blue
335 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
336 {
337 pixels[pixelId * 4 + 0] = 0;
338 pixels[pixelId * 4 + 1] = 0;
339 pixels[pixelId * 4 + 2] = 255;
340 pixels[pixelId * 4 + 3] = 255;
341 }
342
343 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
344 glGenerateMipmap(GL_TEXTURE_2D);
345
346 // Fill with green
347 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
348 {
349 pixels[pixelId * 4 + 0] = 0;
350 pixels[pixelId * 4 + 1] = 255;
351 pixels[pixelId * 4 + 2] = 0;
352 pixels[pixelId * 4 + 3] = 255;
353 }
354
355 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
356 glGenerateMipmap(GL_TEXTURE_2D);
357
358 drawQuad(m2DProgram, "position", 0.5f);
359
360 EXPECT_GL_NO_ERROR();
361 EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
362}
Jamie Madillf8fccb32014-11-12 15:05:26 -0500363
Jamie Madilleb32a2e2014-12-10 14:27:53 -0500364// Test creating a FBO with a cube map render target, to test an ANGLE bug
365// https://code.google.com/p/angleproject/issues/detail?id=849
Jamie Madillfa05f602015-05-07 13:47:11 -0400366TEST_P(TextureTest, CubeMapFBO)
Jamie Madilleb32a2e2014-12-10 14:27:53 -0500367{
368 GLuint fbo;
369 glGenFramebuffers(1, &fbo);
370 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
371
372 glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
373 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, mTextureCube, 0);
374
Corentin Wallez322653b2015-06-17 18:33:56 +0200375 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
Jamie Madilleb32a2e2014-12-10 14:27:53 -0500376
377 glDeleteFramebuffers(1, &fbo);
378
379 EXPECT_GL_NO_ERROR();
380}
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000381
382// Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a default color.
Jamie Madillfa05f602015-05-07 13:47:11 -0400383TEST_P(TextureTest, TexStorage)
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000384{
385 int width = getWindowWidth();
386 int height = getWindowHeight();
387
388 GLuint tex2D;
389 glGenTextures(1, &tex2D);
390 glActiveTexture(GL_TEXTURE0);
391 glBindTexture(GL_TEXTURE_2D, tex2D);
392
393 // Fill with red
394 std::vector<GLubyte> pixels(3 * 16 * 16);
395 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
396 {
397 pixels[pixelId * 3 + 0] = 255;
398 pixels[pixelId * 3 + 1] = 0;
399 pixels[pixelId * 3 + 2] = 0;
400 }
401
402 // ANGLE internally uses RGBA as the DirectX format for RGB images
403 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent alpha color.
404 // The data is kept in a CPU-side image and the image is marked as dirty.
405 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
406
407 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
408 // glTexSubImage2D should take into account that the image is dirty.
409 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
410 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
411 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
412
413 glUseProgram(m2DProgram);
414 glUniform1i(mTexture2DUniformLocation, 0);
415 glUniform2f(mTextureScaleUniformLocation, 1.f, 1.f);
416 drawQuad(m2DProgram, "position", 0.5f);
417 glDeleteTextures(1, &tex2D);
418 EXPECT_GL_NO_ERROR();
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000419 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
Geoff Langfbfa47c2015-03-31 11:26:00 -0400420
421 // Validate that the region of the texture without data has an alpha of 1.0
422 GLubyte pixel[4];
423 glReadPixels(3 * width / 4, 3 * height / 4, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
424 EXPECT_EQ(pixel[3], 255);
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000425}
426
427// Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has initialized the image with a default color.
Jamie Madillfa05f602015-05-07 13:47:11 -0400428TEST_P(TextureTest, TexStorageWithPBO)
Gregoire Payen de La Garanderie88fe1ad2015-01-19 15:09:26 +0000429{
430 if (extensionEnabled("NV_pixel_buffer_object"))
431 {
432 int width = getWindowWidth();
433 int height = getWindowHeight();
434
435 GLuint tex2D;
436 glGenTextures(1, &tex2D);
437 glActiveTexture(GL_TEXTURE0);
438 glBindTexture(GL_TEXTURE_2D, tex2D);
439
440 // Fill with red
441 std::vector<GLubyte> pixels(3 * 16 * 16);
442 for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
443 {
444 pixels[pixelId * 3 + 0] = 255;
445 pixels[pixelId * 3 + 1] = 0;
446 pixels[pixelId * 3 + 2] = 0;
447 }
448
449 // Read 16x16 region from red backbuffer to PBO
450 GLuint pbo;
451 glGenBuffers(1, &pbo);
452 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
453 glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
454
455 // ANGLE internally uses RGBA as the DirectX format for RGB images
456 // therefore glTexStorage2DEXT initializes the image to a default color to get a consistent alpha color.
457 // The data is kept in a CPU-side image and the image is marked as dirty.
458 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
459
460 // Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
461 // glTexSubImage2D should take into account that the image is dirty.
462 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, NULL);
463 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
464 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
465
466 glUseProgram(m2DProgram);
467 glUniform1i(mTexture2DUniformLocation, 0);
468 glUniform2f(mTextureScaleUniformLocation, 1.f, 1.f);
469 drawQuad(m2DProgram, "position", 0.5f);
470 glDeleteTextures(1, &tex2D);
471 glDeleteTextures(1, &pbo);
472 EXPECT_GL_NO_ERROR();
473 EXPECT_PIXEL_EQ(3 * width / 4, 3 * height / 4, 0, 0, 0, 255);
474 EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
475 }
476}
Jamie Madillbc393df2015-01-29 13:46:07 -0500477
478// See description on testFloatCopySubImage
Jamie Madillfa05f602015-05-07 13:47:11 -0400479TEST_P(TextureTest, CopySubImageFloat_R_R)
Jamie Madillbc393df2015-01-29 13:46:07 -0500480{
481 testFloatCopySubImage(1, 1);
482}
483
Jamie Madillfa05f602015-05-07 13:47:11 -0400484TEST_P(TextureTest, CopySubImageFloat_RG_R)
Jamie Madillbc393df2015-01-29 13:46:07 -0500485{
486 testFloatCopySubImage(2, 1);
487}
488
Jamie Madillfa05f602015-05-07 13:47:11 -0400489TEST_P(TextureTest, CopySubImageFloat_RG_RG)
Jamie Madillbc393df2015-01-29 13:46:07 -0500490{
491 testFloatCopySubImage(2, 2);
492}
493
Jamie Madillfa05f602015-05-07 13:47:11 -0400494TEST_P(TextureTest, CopySubImageFloat_RGB_R)
Jamie Madillbc393df2015-01-29 13:46:07 -0500495{
496 testFloatCopySubImage(3, 1);
497}
498
Jamie Madillfa05f602015-05-07 13:47:11 -0400499TEST_P(TextureTest, CopySubImageFloat_RGB_RG)
Jamie Madillbc393df2015-01-29 13:46:07 -0500500{
501 testFloatCopySubImage(3, 2);
502}
503
Jamie Madillfa05f602015-05-07 13:47:11 -0400504TEST_P(TextureTest, CopySubImageFloat_RGB_RGB)
Jamie Madillbc393df2015-01-29 13:46:07 -0500505{
506 testFloatCopySubImage(3, 3);
507}
508
Jamie Madillfa05f602015-05-07 13:47:11 -0400509TEST_P(TextureTest, CopySubImageFloat_RGBA_R)
Jamie Madillbc393df2015-01-29 13:46:07 -0500510{
511 testFloatCopySubImage(4, 1);
512}
513
Jamie Madillfa05f602015-05-07 13:47:11 -0400514TEST_P(TextureTest, CopySubImageFloat_RGBA_RG)
Jamie Madillbc393df2015-01-29 13:46:07 -0500515{
516 testFloatCopySubImage(4, 2);
517}
518
Jamie Madillfa05f602015-05-07 13:47:11 -0400519TEST_P(TextureTest, CopySubImageFloat_RGBA_RGB)
Jamie Madillbc393df2015-01-29 13:46:07 -0500520{
521 testFloatCopySubImage(4, 3);
522}
523
Jamie Madillfa05f602015-05-07 13:47:11 -0400524TEST_P(TextureTest, CopySubImageFloat_RGBA_RGBA)
Jamie Madillbc393df2015-01-29 13:46:07 -0500525{
526 testFloatCopySubImage(4, 4);
527}
Austin Kinross07285142015-03-26 11:36:16 -0700528
529// Port of https://www.khronos.org/registry/webgl/conformance-suites/1.0.3/conformance/textures/texture-npot.html
530// Run against GL_ALPHA/UNSIGNED_BYTE format, to ensure that D3D11 Feature Level 9_3 correctly handles GL_ALPHA
Jamie Madillfa05f602015-05-07 13:47:11 -0400531TEST_P(TextureTest, TextureNPOT_GL_ALPHA_UBYTE)
Austin Kinross07285142015-03-26 11:36:16 -0700532{
533 const int npotTexSize = 5;
534 const int potTexSize = 4; // Should be less than npotTexSize
535 GLuint tex2D;
536
537 if (extensionEnabled("GL_OES_texture_npot"))
538 {
539 // This test isn't applicable if texture_npot is enabled
540 return;
541 }
542
543 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
544
545 glActiveTexture(GL_TEXTURE0);
546 glGenTextures(1, &tex2D);
547 glBindTexture(GL_TEXTURE_2D, tex2D);
548
549 std::vector<GLubyte> pixels(1 * npotTexSize * npotTexSize);
550 for (size_t pixelId = 0; pixelId < npotTexSize * npotTexSize; ++pixelId)
551 {
552 pixels[pixelId] = 64;
553 }
554
555 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
556 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
557
558 // Check that an NPOT texture not on level 0 generates INVALID_VALUE
559 glTexImage2D(GL_TEXTURE_2D, 1, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
560 EXPECT_GL_ERROR(GL_INVALID_VALUE);
561
562 // Check that an NPOT texture on level 0 succeeds
563 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, npotTexSize, npotTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
564 EXPECT_GL_NO_ERROR();
565
566 // Check that generateMipmap fails on NPOT
567 glGenerateMipmap(GL_TEXTURE_2D);
568 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
569
570 // Check that nothing is drawn if filtering is not correct for NPOT
571 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
572 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
573 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
574 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
575 glClear(GL_COLOR_BUFFER_BIT);
576 drawQuad(m2DProgram, "position", 1.0f);
577 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
578
579 // NPOT texture with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255
580 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
581 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
582 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
583 glClear(GL_COLOR_BUFFER_BIT);
584 drawQuad(m2DProgram, "position", 1.0f);
585 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 255);
586
587 // NPOT texture with TEXTURE_MIN_FILTER set to LINEAR should draw
588 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
589 glClear(GL_COLOR_BUFFER_BIT);
590 drawQuad(m2DProgram, "position", 1.0f);
591 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
592
593 // Check that glTexImage2D for POT texture succeeds
594 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, potTexSize, potTexSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels.data());
595 EXPECT_GL_NO_ERROR();
596
597 // Check that generateMipmap for an POT texture succeeds
598 glGenerateMipmap(GL_TEXTURE_2D);
599 EXPECT_GL_NO_ERROR();
600
601 // POT texture with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw
602 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
603 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
604 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
605 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
606 glClear(GL_COLOR_BUFFER_BIT);
607 drawQuad(m2DProgram, "position", 1.0f);
608 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 0, 64);
609 EXPECT_GL_NO_ERROR();
610}
Jamie Madillfa05f602015-05-07 13:47:11 -0400611
612// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
Geoff Langc4222072015-05-25 13:19:48 -0400613ANGLE_INSTANTIATE_TEST(TextureTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3()); // TODO(geofflang): Figure out why this test fails on Intel OpenGL
Jamie Madillfa05f602015-05-07 13:47:11 -0400614
615} // namespace