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 #include <vector>
10 
11 using namespace angle;
12 
13 class IncompleteTextureTest : public ANGLETest
14 {
15   protected:
IncompleteTextureTest()16     IncompleteTextureTest()
17     {
18         setWindowWidth(128);
19         setWindowHeight(128);
20         setConfigRedBits(8);
21         setConfigGreenBits(8);
22         setConfigBlueBits(8);
23         setConfigAlphaBits(8);
24     }
25 
SetUp()26     virtual void SetUp()
27     {
28         ANGLETest::SetUp();
29 
30         const std::string vertexShaderSource = SHADER_SOURCE
31         (
32             precision highp float;
33             attribute vec4 position;
34             varying vec2 texcoord;
35 
36             void main()
37             {
38                 gl_Position = position;
39                 texcoord = (position.xy * 0.5) + 0.5;
40             }
41         );
42 
43         const std::string fragmentShaderSource = SHADER_SOURCE
44         (
45             precision highp float;
46             uniform sampler2D tex;
47             varying vec2 texcoord;
48 
49             void main()
50             {
51                 gl_FragColor = texture2D(tex, texcoord);
52             }
53         );
54 
55         mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
56         if (mProgram == 0)
57         {
58             FAIL() << "shader compilation failed.";
59         }
60 
61         mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
62     }
63 
TearDown()64     virtual void TearDown()
65     {
66         glDeleteProgram(mProgram);
67 
68         ANGLETest::TearDown();
69     }
70 
fillTextureData(std::vector<GLubyte> & buffer,GLubyte r,GLubyte g,GLubyte b,GLubyte a)71     void fillTextureData(std::vector<GLubyte> &buffer, GLubyte r, GLubyte g, GLubyte b, GLubyte a)
72     {
73         size_t count = buffer.size() / 4;
74         for (size_t i = 0; i < count; i++)
75         {
76             buffer[i * 4 + 0] = r;
77             buffer[i * 4 + 1] = g;
78             buffer[i * 4 + 2] = b;
79             buffer[i * 4 + 3] = a;
80         }
81     }
82 
83     GLuint mProgram;
84     GLint mTextureUniformLocation;
85 };
86 
TEST_P(IncompleteTextureTest,IncompleteTexture2D)87 TEST_P(IncompleteTextureTest, IncompleteTexture2D)
88 {
89     GLuint tex;
90     glGenTextures(1, &tex);
91     glActiveTexture(GL_TEXTURE0);
92     glBindTexture(GL_TEXTURE_2D, tex);
93 
94     glUseProgram(mProgram);
95     glUniform1i(mTextureUniformLocation, 0);
96 
97     const GLsizei textureWidth = 2;
98     const GLsizei textureHeight = 2;
99     std::vector<GLubyte> textureData(textureWidth * textureHeight * 4);
100     fillTextureData(textureData, 255, 0, 0, 255);
101 
102     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData[0]);
103     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
104 
105     drawQuad(mProgram, "position", 0.5f);
106     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
107 
108     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
109 
110     drawQuad(mProgram, "position", 0.5f);
111     EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 255);
112 
113     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, textureWidth >> 1, textureHeight >> 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData[0]);
114 
115     drawQuad(mProgram, "position", 0.5f);
116     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
117 
118     glDeleteTextures(1, &tex);
119 }
120 
TEST_P(IncompleteTextureTest,UpdateTexture)121 TEST_P(IncompleteTextureTest, UpdateTexture)
122 {
123     GLuint tex;
124     glGenTextures(1, &tex);
125     glActiveTexture(GL_TEXTURE0);
126     glBindTexture(GL_TEXTURE_2D, tex);
127 
128     glUseProgram(mProgram);
129     glUniform1i(mTextureUniformLocation, 0);
130 
131     const GLsizei redTextureWidth = 64;
132     const GLsizei redTextureHeight = 64;
133     std::vector<GLubyte> redTextureData(redTextureWidth * redTextureHeight * 4);
134     fillTextureData(redTextureData, 255, 0, 0, 255);
135     for (size_t i = 0; i < 7; i++)
136     {
137         glTexImage2D(GL_TEXTURE_2D, static_cast<GLint>(i), GL_RGBA, redTextureWidth >> i,
138                      redTextureHeight >> i, 0, GL_RGBA, GL_UNSIGNED_BYTE, &redTextureData[0]);
139     }
140 
141     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
142     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
143 
144     drawQuad(mProgram, "position", 0.5f);
145     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
146 
147     const GLsizei greenTextureWidth = 32;
148     const GLsizei greenTextureHeight = 32;
149     std::vector<GLubyte> greenTextureData(greenTextureWidth * greenTextureHeight * 4);
150     fillTextureData(greenTextureData, 0, 255, 0, 255);
151 
152     for (size_t i = 0; i < 6; i++)
153     {
154         glTexSubImage2D(GL_TEXTURE_2D, static_cast<GLint>(i), greenTextureWidth >> i,
155                         greenTextureHeight >> i, greenTextureWidth >> i, greenTextureHeight >> i,
156                         GL_RGBA, GL_UNSIGNED_BYTE, &greenTextureData[0]);
157     }
158 
159     drawQuad(mProgram, "position", 0.5f);
160     EXPECT_PIXEL_EQ(getWindowWidth() - greenTextureWidth, getWindowHeight() - greenTextureWidth, 0, 255, 0, 255);
161 
162     glDeleteTextures(1, &tex);
163 }
164 
165 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
166 ANGLE_INSTANTIATE_TEST(IncompleteTextureTest,
167                        ES2_D3D9(),
168                        ES2_D3D11(),
169                        ES2_OPENGL(),
170                        ES2_OPENGLES());
171