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